RangeTracker seems to be working; still need to write unit tests for its return value.
This commit is contained in:
parent
3b1135ea2f
commit
fe30fbbd74
3 changed files with 444 additions and 40 deletions
|
@ -19,12 +19,20 @@ void rangeTrackerDeinit(rangeTracker * rt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Add a new range
|
Add a new range
|
||||||
@return a null terminated array of newly-pinned, quantized ranges
|
|
||||||
|
@return a null terminated array of newly-pinned, quantized ranges.
|
||||||
|
This array might contain ranges that were already pinned, and/or
|
||||||
|
ones that overlap (this aspect of the behavior is intentionally
|
||||||
|
left unspecified).
|
||||||
*/
|
*/
|
||||||
range ** rangeTrackerAdd(rangeTracker * rt, const range * r);
|
range ** rangeTrackerAdd(rangeTracker * rt, const range * r);
|
||||||
/**
|
/**
|
||||||
Remove a range
|
Remove a range
|
||||||
@return a null terminated array of newly-unpinned, quantized ranges
|
|
||||||
|
@return a null terminated array of unpinned, quantized ranges.
|
||||||
|
|
||||||
|
@see rangeTrackerAdd for a discussion of approximations that may
|
||||||
|
be applied to rangeTrackerRemove's return value.
|
||||||
*/
|
*/
|
||||||
range ** rangeTrackerRemove(rangeTracker * rt, const range * r);
|
range ** rangeTrackerRemove(rangeTracker * rt, const range * r);
|
||||||
|
|
||||||
|
|
|
@ -55,17 +55,22 @@ static void rangeTrackerDelta(rangeTracker * rt, const range * r, int delta) {
|
||||||
transition * t = (transition *)RB_ENTRY(lookup)(RB_LULTEQ, &key, rt->ranges);
|
transition * t = (transition *)RB_ENTRY(lookup)(RB_LULTEQ, &key, rt->ranges);
|
||||||
|
|
||||||
if(t) {
|
if(t) {
|
||||||
|
assert(t->delta);
|
||||||
|
assert(t->pins >= 0);
|
||||||
|
assert(t->pins + t->delta >= 0);
|
||||||
if(t->pos != r->start) {
|
if(t->pos != r->start) {
|
||||||
int newpins = t->pins + t->delta;
|
int newpins = t->pins + t->delta;
|
||||||
t = malloc(sizeof(transition));
|
t = malloc(sizeof(transition));
|
||||||
t->pos = r->start;
|
t->pos = r->start;
|
||||||
t->delta = delta;
|
t->delta = delta;
|
||||||
t->pins = newpins;
|
t->pins = newpins;
|
||||||
|
assert(newpins >= 0);
|
||||||
RB_ENTRY(search)(t, rt->ranges); // insert
|
RB_ENTRY(search)(t, rt->ranges); // insert
|
||||||
curpin = t->pins + t->delta;
|
curpin = t->pins + t->delta;
|
||||||
} else {
|
} else {
|
||||||
t->delta += delta;
|
t->delta += delta;
|
||||||
curpin = t->pins + t->delta;
|
curpin = t->pins + t->delta;
|
||||||
|
assert(curpin >= 0);
|
||||||
if(t->delta == 0) {
|
if(t->delta == 0) {
|
||||||
RB_ENTRY(delete)(t, rt->ranges);
|
RB_ENTRY(delete)(t, rt->ranges);
|
||||||
key.pos = t->pos;
|
key.pos = t->pos;
|
||||||
|
@ -81,6 +86,7 @@ static void rangeTrackerDelta(rangeTracker * rt, const range * r, int delta) {
|
||||||
t->pins = 0;
|
t->pins = 0;
|
||||||
RB_ENTRY(search)(t, rt->ranges); // insert
|
RB_ENTRY(search)(t, rt->ranges); // insert
|
||||||
curpin = t->pins + t->delta;
|
curpin = t->pins + t->delta;
|
||||||
|
assert(curpin >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// t is now set; iterate over the tree until we reach a transition
|
// t is now set; iterate over the tree until we reach a transition
|
||||||
|
@ -97,6 +103,7 @@ static void rangeTrackerDelta(rangeTracker * rt, const range * r, int delta) {
|
||||||
assert(t->delta);
|
assert(t->delta);
|
||||||
assert(t->pins == curpin);
|
assert(t->pins == curpin);
|
||||||
curpin = t->pins + t->delta;
|
curpin = t->pins + t->delta;
|
||||||
|
assert(curpin >= 0);
|
||||||
}
|
}
|
||||||
if(!t || t->pos != r->stop) {
|
if(!t || t->pos != r->stop) {
|
||||||
// Need to allocate new transition
|
// Need to allocate new transition
|
||||||
|
@ -104,6 +111,7 @@ static void rangeTrackerDelta(rangeTracker * rt, const range * r, int delta) {
|
||||||
t->pos = r->stop;
|
t->pos = r->stop;
|
||||||
t->delta = 0-delta;
|
t->delta = 0-delta;
|
||||||
t->pins = curpin;
|
t->pins = curpin;
|
||||||
|
assert(curpin >= 0);
|
||||||
RB_ENTRY(search)(t, rt->ranges); // insert
|
RB_ENTRY(search)(t, rt->ranges); // insert
|
||||||
} else {
|
} else {
|
||||||
// Found existing transition at end of range.
|
// Found existing transition at end of range.
|
||||||
|
@ -120,8 +128,260 @@ static void rangeTrackerDelta(rangeTracker * rt, const range * r, int delta) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
range ** rangeTrackerAdd(rangeTracker * rt, const range * r) {
|
static range ** rangeTrackerToArray(rangeTracker * rt) {
|
||||||
rangeTrackerDelta(rt, r, 1);
|
// count ranges.
|
||||||
|
int range_count = 0;
|
||||||
|
const transition * t;
|
||||||
|
int in_range = 0;
|
||||||
|
|
||||||
|
RBLIST * list = RB_ENTRY(openlist) (rt->ranges);
|
||||||
|
while((t = RB_ENTRY(readlist)(list))) {
|
||||||
|
if(!(t->pins + t->delta)) {
|
||||||
|
// end of a range.
|
||||||
|
in_range = 0;
|
||||||
|
range_count++;
|
||||||
|
} else {
|
||||||
|
in_range = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RB_ENTRY(closelist)(list);
|
||||||
|
if(in_range) {
|
||||||
|
range_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
range ** ret = calloc(range_count + 1, sizeof(range *));
|
||||||
|
|
||||||
|
int next_range = 0;
|
||||||
|
in_range = 0;
|
||||||
|
list = RB_ENTRY(openlist) (rt->ranges);
|
||||||
|
t = RB_ENTRY(readlist)(list);
|
||||||
|
if(!t) {
|
||||||
|
assert(range_count == 0);
|
||||||
|
RB_ENTRY(closelist)(list);
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
assert(!t->pins);
|
||||||
|
assert(t->delta);
|
||||||
|
assert(! ret[next_range] );
|
||||||
|
ret[next_range] = malloc(sizeof(range));
|
||||||
|
ret[next_range]->start = t->pos;
|
||||||
|
in_range = 1;
|
||||||
|
}
|
||||||
|
while((t = RB_ENTRY(readlist)(list))) {
|
||||||
|
if(t->pins + t->delta) {
|
||||||
|
if(!in_range) {
|
||||||
|
assert(! ret[next_range]);
|
||||||
|
ret[next_range] = malloc(sizeof(range));
|
||||||
|
ret[next_range]->start = t->pos;
|
||||||
|
in_range = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// end of range.
|
||||||
|
assert(in_range);
|
||||||
|
ret[next_range]->stop = t->pos;
|
||||||
|
in_range = 0;
|
||||||
|
next_range ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_ENTRY(closelist)(list);
|
||||||
|
assert(next_range == range_count);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline long roundDown(long x, long quant) {
|
||||||
|
return (x / quant) * quant;
|
||||||
|
}
|
||||||
|
static inline long roundUp(long x, long quant) {
|
||||||
|
return (((x-1) / quant) + 1) * quant;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@return a set of ranges that are pinned, and that overlap the request range.
|
||||||
|
*/
|
||||||
|
static rangeTracker * pinnedRanges(const rangeTracker * rt, const range * request, rangeTracker * ret, int delta) {
|
||||||
|
transition key;
|
||||||
|
const transition * t;
|
||||||
|
|
||||||
|
key.pos = roundDown(request->start, rt->quantization);
|
||||||
|
|
||||||
|
t = rblookup(RB_LUGTEQ, &key, rt->ranges);
|
||||||
|
|
||||||
|
if(!t) {
|
||||||
|
// No ranges after request->start, so no ranges can overlap.
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
long range_start;
|
||||||
|
|
||||||
|
// zero if we just encountered the end of a range. The range runs from
|
||||||
|
// range_start to putative_range_stop. It is possible that a new range
|
||||||
|
// begins on the page that putative_range_stop falls on, so we do not
|
||||||
|
// output the range without looking at the next transition.
|
||||||
|
int in_range;
|
||||||
|
// This is only meaningful if in_range = 0.
|
||||||
|
long putative_range_stop;
|
||||||
|
|
||||||
|
if(t) {
|
||||||
|
if(roundDown(t->pos, rt->quantization) >= roundUp(request->stop, rt->quantization)) {
|
||||||
|
if(t->pins) {
|
||||||
|
// entire range is pinned.
|
||||||
|
range tmp_r;
|
||||||
|
tmp_r.start = roundDown(request->start, rt->quantization);
|
||||||
|
tmp_r.stop = roundUp(request->stop, rt->quantization);
|
||||||
|
|
||||||
|
assert(tmp_r.start >= roundDown(request->start, rt->quantization) && tmp_r.stop <= roundUp(request->stop, rt->quantization));
|
||||||
|
rangeTrackerDelta(ret, &tmp_r, delta);
|
||||||
|
|
||||||
|
// printf("0 %s\n", rangeToString(&tmp_r));
|
||||||
|
} else {
|
||||||
|
// none of the range is pinned.
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if(t->pins) {
|
||||||
|
// The beginning of request is a range.
|
||||||
|
range_start = roundDown(request->start, rt->quantization);
|
||||||
|
if(0 == t->pins + t->delta) {
|
||||||
|
in_range = 0;
|
||||||
|
// even though we're not in range, we need to see if the next
|
||||||
|
// transition starts a range on the same page before returning a
|
||||||
|
// new range.
|
||||||
|
putative_range_stop = roundUp(t->pos, rt->quantization);
|
||||||
|
} else {
|
||||||
|
in_range = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The beginning of the request is not a range.
|
||||||
|
range_start = roundDown(t->pos, rt->quantization);
|
||||||
|
in_range = 1;
|
||||||
|
assert(t->delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while((t = rblookup(RB_LUGREAT, t, rt->ranges))) {
|
||||||
|
assert(t->delta);
|
||||||
|
|
||||||
|
if(roundUp(t->pos, rt->quantization) >= roundUp(request->stop, rt->quantization)) {
|
||||||
|
if(in_range) {
|
||||||
|
// if we're in range, part of the last page must be pinned.
|
||||||
|
in_range = 0;
|
||||||
|
putative_range_stop = roundUp(request->stop, rt->quantization);
|
||||||
|
} else {
|
||||||
|
// is this transition in the last page? If so, part of the last page must be pinned.
|
||||||
|
if(t->pos < roundUp(request->stop, rt->quantization)) {
|
||||||
|
// in_range == 0
|
||||||
|
assert(t->pins == 0);
|
||||||
|
range_start = roundDown(t->pos, rt->quantization);
|
||||||
|
putative_range_stop = roundUp(request->stop, rt->quantization);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(t->pins) {
|
||||||
|
assert(in_range);
|
||||||
|
|
||||||
|
if(!(t->pins + t->delta)) {
|
||||||
|
putative_range_stop = roundUp(t->pos, rt->quantization);
|
||||||
|
in_range = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // ! t->pins
|
||||||
|
assert(!in_range);
|
||||||
|
|
||||||
|
if(putative_range_stop < roundDown(t->pos, rt->quantization)) {
|
||||||
|
// output a new range
|
||||||
|
range tmp_r;
|
||||||
|
tmp_r.start = range_start;
|
||||||
|
tmp_r.stop = putative_range_stop;
|
||||||
|
if(tmp_r.start != tmp_r.stop) {
|
||||||
|
assert(tmp_r.start >= roundDown(request->start, rt->quantization) && tmp_r.stop <= roundUp(request->stop, rt->quantization));
|
||||||
|
rangeTrackerDelta(ret, &tmp_r, delta);
|
||||||
|
// printf("1 %s\n", rangeToString(&tmp_r));
|
||||||
|
}
|
||||||
|
range_start = roundDown(t->pos, rt->quantization);
|
||||||
|
} else {
|
||||||
|
// extend old range.
|
||||||
|
}
|
||||||
|
in_range = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(!in_range);
|
||||||
|
range tmp_r;
|
||||||
|
tmp_r.start = range_start;
|
||||||
|
tmp_r.stop = putative_range_stop;
|
||||||
|
if(tmp_r.start != tmp_r.stop) {
|
||||||
|
assert(tmp_r.start >= roundDown(request->start, rt->quantization) && tmp_r.stop <= roundUp(request->stop, rt->quantization));
|
||||||
|
rangeTrackerDelta(ret, &tmp_r, delta);
|
||||||
|
// printf("2 %s\n", rangeToString(&tmp_r));
|
||||||
|
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
range ** rangeTrackerAdd(rangeTracker * rt, const range * rng) {
|
||||||
|
// printf("pinnedRanges before add %s\n", rangeToString(rng));
|
||||||
|
rangeTracker * ret = rangeTrackerInit(rt->quantization);
|
||||||
|
pinnedRanges(rt, rng, ret, 1);
|
||||||
|
rangeTrackerDelta(rt, rng, 1);
|
||||||
|
// printf("pinnedRanges after add\n");
|
||||||
|
rangeTracker * ret2 = rangeTrackerInit(rt->quantization);
|
||||||
|
pinnedRanges(rt, rng, ret2, 1);
|
||||||
|
|
||||||
|
range ** ret_arry = rangeTrackerToArray(ret);
|
||||||
|
|
||||||
|
// remove the first array from the second...
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while(ret_arry[i]) {
|
||||||
|
rangeTrackerDelta(ret2, ret_arry[i], -1);
|
||||||
|
// while we're at it, deinit the first range tracker
|
||||||
|
rangeTrackerDelta(ret, ret_arry[i], -1);
|
||||||
|
free(ret_arry[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
free(ret_arry);
|
||||||
|
rangeTrackerDeinit(ret);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
ret_arry = rangeTrackerToArray(ret2);
|
||||||
|
|
||||||
|
while(ret_arry[i]) {
|
||||||
|
rangeTrackerDelta(ret2, ret_arry[i], -1);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
rangeTrackerDeinit(ret2);
|
||||||
|
|
||||||
|
return ret_arry;
|
||||||
|
|
||||||
|
/* // Need to return pinned ranges that overlap r.
|
||||||
|
|
||||||
|
transition key;
|
||||||
|
const transition * t;
|
||||||
|
|
||||||
|
key.pos = rng->start;
|
||||||
|
|
||||||
|
t = rblookup(RB_LULTEQ, &key, rt->ranges); // could be less than if the new range touches an existing range.
|
||||||
|
|
||||||
|
assert(t);
|
||||||
|
|
||||||
|
range r;
|
||||||
|
int in_range = 1;
|
||||||
|
r.start = roundDown(t->pos, rt->quantization);
|
||||||
|
|
||||||
|
while((t = rblookup(RB_LUGREAT, t, rt->ranges))) {
|
||||||
|
if(!(t->pins + t->delta)) {
|
||||||
|
assert(in_range);
|
||||||
|
in_range = 0;
|
||||||
|
r.stop = roundUp(t->pos, rt->quantization);
|
||||||
|
// printf("add range: [%lld-%lld]\n", (long long)r.start, (long long)r.stop);
|
||||||
|
} else if(!in_range) {
|
||||||
|
assert(t->pins == 0);
|
||||||
|
in_range = 1;
|
||||||
|
r.start = roundDown(t->pos, rt->quantization);
|
||||||
|
}
|
||||||
|
if(t->pos >= rng->stop) { break; }
|
||||||
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -129,8 +389,96 @@ range ** rangeTrackerAdd(rangeTracker * rt, const range * r) {
|
||||||
@return a null terminated array of newly-unpinned, quantized ranges
|
@return a null terminated array of newly-unpinned, quantized ranges
|
||||||
*/
|
*/
|
||||||
|
|
||||||
range ** rangeTrackerRemove(rangeTracker * rt, const range * r) {
|
range ** rangeTrackerRemove(rangeTracker * rt, const range * rang) {
|
||||||
rangeTrackerDelta(rt, r, -1);
|
rangeTracker * ret = rangeTrackerInit(rt->quantization);
|
||||||
|
// printf("pinnedRanges, before del %s\n", rangeToString(rang));
|
||||||
|
pinnedRanges(rt, rang, ret, 1);
|
||||||
|
rangeTrackerDelta(rt, rang, -1);
|
||||||
|
// printf("pinnedRanges, after del\n");
|
||||||
|
pinnedRanges(rt, rang, ret, -1);
|
||||||
|
|
||||||
|
range ** ret_arry = rangeTrackerToArray(ret);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while(ret_arry[i]) {
|
||||||
|
rangeTrackerDelta(ret, ret_arry[i], -1);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
rangeTrackerDeinit(ret);
|
||||||
|
|
||||||
|
return ret_arry;
|
||||||
|
|
||||||
|
/* // Need to return completely unpinned ranges that overlap r.
|
||||||
|
|
||||||
|
range bigger;
|
||||||
|
bigger.start = roundDown(rang->start, rt->quantization);
|
||||||
|
bigger.stop = roundUp(rang->stop, rt->quantization);
|
||||||
|
|
||||||
|
transition key;
|
||||||
|
|
||||||
|
key.pos = bigger.start;
|
||||||
|
|
||||||
|
int unpinned_range = 0;
|
||||||
|
range r;
|
||||||
|
|
||||||
|
const transition * t = RB_ENTRY(lookup)(RB_LUGTEQ, &key, rt->ranges);
|
||||||
|
|
||||||
|
long last_end = bigger.start;
|
||||||
|
|
||||||
|
// special case beginning of range
|
||||||
|
if(! t) {
|
||||||
|
t = RB_ENTRY(lookup)(RB_LULESS, &key, rt->ranges);
|
||||||
|
if(!t || 0 == t->pins + t->delta) {
|
||||||
|
// printf("A %s\n", rangeToString(&bigger));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if(t->pins == 0) {
|
||||||
|
r.start = bigger.start;
|
||||||
|
r.stop = roundDown(t->pos, rt->quantization);
|
||||||
|
if(r.start < r.stop) {
|
||||||
|
// printf("0 %s\n", rangeToString(&r));
|
||||||
|
}
|
||||||
|
unpinned_range = 1;
|
||||||
|
assert(0 != t->pins + t->delta);
|
||||||
|
t = RB_ENTRY(lookup)(RB_LUGREAT, t, rt->ranges);
|
||||||
|
}
|
||||||
|
if(t) {
|
||||||
|
unpinned_range = (0 == t->pins + t->delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(t) {
|
||||||
|
|
||||||
|
if(t->pins == 0) {
|
||||||
|
// XXX don't care if range bleeds outside of initially pinned range (for now; the difference could be huge in sparse applications)
|
||||||
|
r.start = roundUp(last_end, rt->quantization);
|
||||||
|
r.stop = roundDown(t->pos, rt->quantization);
|
||||||
|
assert(unpinned_range);
|
||||||
|
if(r.start < r.stop) {
|
||||||
|
// printf("B %s\n", rangeToString(&r));
|
||||||
|
} else {
|
||||||
|
// printf(".. %s bigger = %s\n", rangeToString(&r), rangeToString(&bigger));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// break after processing transition that runs over the edge...
|
||||||
|
if(t->pos >= bigger.stop) { break; }
|
||||||
|
|
||||||
|
last_end = t->pos;
|
||||||
|
unpinned_range = (0 == t->pins + t->delta);
|
||||||
|
t = RB_ENTRY(lookup)(RB_LUGREAT, t, rt->ranges);
|
||||||
|
}
|
||||||
|
if(! t && unpinned_range) {
|
||||||
|
r.start = roundUp(last_end, rt->quantization);
|
||||||
|
r.stop = bigger.stop;
|
||||||
|
if(r.start < r.stop) {
|
||||||
|
// printf("C %s\n", rangeToString(&r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// plan: (1) Write roundDown, roundUp macros
|
||||||
|
// enumerate pinned pages before and after operation. (Note that we need to round down and up to get stuff outside the range, but on common pages)
|
||||||
|
// return before - after, or after - before, depending on whether this is an add or a remove.
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const transition ** rangeTrackerEnumerate(rangeTracker * rt) {
|
const transition ** rangeTrackerEnumerate(rangeTracker * rt) {
|
||||||
|
@ -169,3 +517,4 @@ char * transitionToString(const transition * t) {
|
||||||
assert(err !=-1);
|
assert(err !=-1);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <lladd/transactional.h>
|
#include <lladd/transactional.h>
|
||||||
#define LOG_NAME "check_rangeTracker.log"
|
#define LOG_NAME "check_rangeTracker.log"
|
||||||
|
|
||||||
|
#define QUANTIZATION 7
|
||||||
|
|
||||||
#include <lladd/io/rangeTracker.h>
|
#include <lladd/io/rangeTracker.h>
|
||||||
|
|
||||||
#include "../check_includes.h"
|
#include "../check_includes.h"
|
||||||
|
@ -18,6 +20,12 @@ long myrandom(long x) {
|
||||||
return (long)((r/max));
|
return (long)((r/max));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rangeTrackerFreeRet(range ** ret) {
|
||||||
|
for(int i = 0; ret[i]; i++) {
|
||||||
|
free(ret[i]);
|
||||||
|
}
|
||||||
|
free(ret);
|
||||||
|
}
|
||||||
void printRT(rangeTracker * rt) {
|
void printRT(rangeTracker * rt) {
|
||||||
const transition ** ts = rangeTrackerEnumerate(rt);
|
const transition ** ts = rangeTrackerEnumerate(rt);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -30,7 +38,7 @@ void printRT(rangeTracker * rt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(rangeTracker_smokeTest) {
|
START_TEST(rangeTracker_smokeTest) {
|
||||||
rangeTracker * rt = rangeTrackerInit(512);
|
rangeTracker * rt = rangeTrackerInit(QUANTIZATION);
|
||||||
|
|
||||||
const transition ** ts = rangeTrackerEnumerate(rt);
|
const transition ** ts = rangeTrackerEnumerate(rt);
|
||||||
|
|
||||||
|
@ -45,7 +53,8 @@ START_TEST(rangeTracker_smokeTest) {
|
||||||
r.start = 10;
|
r.start = 10;
|
||||||
r.stop = 100;
|
r.stop = 100;
|
||||||
|
|
||||||
rangeTrackerAdd(rt, &r);
|
rangeTrackerFreeRet(rangeTrackerAdd(rt, &r));
|
||||||
|
|
||||||
|
|
||||||
// printRT(rt);
|
// printRT(rt);
|
||||||
|
|
||||||
|
@ -60,10 +69,12 @@ START_TEST(rangeTracker_smokeTest) {
|
||||||
ts[1]->pos == 100&& ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
|
ts[1]->pos == 100&& ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
|
||||||
|
|
||||||
|
|
||||||
|
free(ts);
|
||||||
|
|
||||||
r.start = 20;
|
r.start = 20;
|
||||||
r.stop = 80;
|
r.stop = 80;
|
||||||
|
|
||||||
rangeTrackerRemove(rt, &r);
|
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
|
||||||
|
|
||||||
// printRT(rt);
|
// printRT(rt);
|
||||||
|
|
||||||
|
@ -80,10 +91,11 @@ START_TEST(rangeTracker_smokeTest) {
|
||||||
ts[3]->pos == 100&& ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
|
ts[3]->pos == 100&& ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
|
||||||
|
|
||||||
|
|
||||||
rangeTrackerAdd(rt, &r);
|
rangeTrackerFreeRet(rangeTrackerAdd(rt, &r));
|
||||||
|
|
||||||
// printRT(rt);
|
// printRT(rt);
|
||||||
|
|
||||||
|
free(ts);
|
||||||
ts = rangeTrackerEnumerate(rt);
|
ts = rangeTrackerEnumerate(rt);
|
||||||
|
|
||||||
// 10 20 80 90 100
|
// 10 20 80 90 100
|
||||||
|
@ -95,10 +107,10 @@ START_TEST(rangeTracker_smokeTest) {
|
||||||
assert(ts[0]->pos == 10 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
|
assert(ts[0]->pos == 10 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
|
||||||
ts[1]->pos == 100&& ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
|
ts[1]->pos == 100&& ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
|
||||||
|
|
||||||
rangeTrackerAdd(rt, &r);
|
rangeTrackerFreeRet(rangeTrackerAdd(rt, &r));
|
||||||
|
|
||||||
// printRT(rt);
|
// printRT(rt);
|
||||||
|
free(ts);
|
||||||
ts = rangeTrackerEnumerate(rt);
|
ts = rangeTrackerEnumerate(rt);
|
||||||
|
|
||||||
// 10 20 80 90 100
|
// 10 20 80 90 100
|
||||||
|
@ -111,8 +123,8 @@ START_TEST(rangeTracker_smokeTest) {
|
||||||
ts[2]->pos == 80 && ts[2]->delta == -1 && ts[2]->pins == 2 &&
|
ts[2]->pos == 80 && ts[2]->delta == -1 && ts[2]->pins == 2 &&
|
||||||
ts[3]->pos == 100&& ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
|
ts[3]->pos == 100&& ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
|
||||||
|
|
||||||
|
free(ts);
|
||||||
rangeTrackerRemove(rt, &r);
|
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
|
||||||
ts = rangeTrackerEnumerate(rt);
|
ts = rangeTrackerEnumerate(rt);
|
||||||
|
|
||||||
// 10 20 80 90 100
|
// 10 20 80 90 100
|
||||||
|
@ -123,7 +135,9 @@ START_TEST(rangeTracker_smokeTest) {
|
||||||
|
|
||||||
assert(ts[0]->pos == 10 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
|
assert(ts[0]->pos == 10 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
|
||||||
ts[1]->pos == 100&& ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
|
ts[1]->pos == 100&& ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
|
||||||
rangeTrackerRemove(rt, &r);
|
free(ts);
|
||||||
|
|
||||||
|
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
|
||||||
|
|
||||||
// printRT(rt);
|
// printRT(rt);
|
||||||
|
|
||||||
|
@ -138,13 +152,13 @@ START_TEST(rangeTracker_smokeTest) {
|
||||||
ts[1]->pos == 20 && ts[1]->delta == -1 && ts[1]->pins == 1 &&
|
ts[1]->pos == 20 && ts[1]->delta == -1 && ts[1]->pins == 1 &&
|
||||||
ts[2]->pos == 80 && ts[2]->delta == 1 && ts[2]->pins == 0 &&
|
ts[2]->pos == 80 && ts[2]->delta == 1 && ts[2]->pins == 0 &&
|
||||||
ts[3]->pos == 100&& ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
|
ts[3]->pos == 100&& ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
|
||||||
|
free(ts);
|
||||||
r.start = 80;
|
r.start = 80;
|
||||||
r.stop = 90;
|
r.stop = 90;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
rangeTrackerAdd(rt, &r);
|
rangeTrackerFreeRet(rangeTrackerAdd(rt, &r));
|
||||||
|
|
||||||
// printRT(rt);
|
// printRT(rt);
|
||||||
|
|
||||||
|
@ -161,10 +175,11 @@ START_TEST(rangeTracker_smokeTest) {
|
||||||
ts[2]->pos == 80 && ts[2]->delta == 2 && ts[2]->pins == 0 &&
|
ts[2]->pos == 80 && ts[2]->delta == 2 && ts[2]->pins == 0 &&
|
||||||
ts[3]->pos == 90 && ts[3]->delta == -1 && ts[3]->pins == 2 &&
|
ts[3]->pos == 90 && ts[3]->delta == -1 && ts[3]->pins == 2 &&
|
||||||
ts[4]->pos == 100&& ts[4]->delta == -1 && ts[4]->pins == 1 && !ts[5]);
|
ts[4]->pos == 100&& ts[4]->delta == -1 && ts[4]->pins == 1 && !ts[5]);
|
||||||
|
free(ts);
|
||||||
r.start = 80;
|
r.start = 80;
|
||||||
r.stop = 100;
|
r.stop = 100;
|
||||||
rangeTrackerRemove(rt, &r);
|
|
||||||
|
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
|
||||||
|
|
||||||
// printRT(rt);
|
// printRT(rt);
|
||||||
ts = rangeTrackerEnumerate(rt);
|
ts = rangeTrackerEnumerate(rt);
|
||||||
|
@ -180,10 +195,10 @@ START_TEST(rangeTracker_smokeTest) {
|
||||||
ts[2]->pos == 80 && ts[2]->delta == 1 && ts[2]->pins == 0 &&
|
ts[2]->pos == 80 && ts[2]->delta == 1 && ts[2]->pins == 0 &&
|
||||||
ts[3]->pos == 90 && ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
|
ts[3]->pos == 90 && ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
|
||||||
|
|
||||||
|
free(ts);
|
||||||
r.start = 10;
|
r.start = 10;
|
||||||
r.stop = 20;
|
r.stop = 20;
|
||||||
rangeTrackerRemove(rt, &r);
|
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
|
||||||
|
|
||||||
// printRT(rt);
|
// printRT(rt);
|
||||||
ts = rangeTrackerEnumerate(rt);
|
ts = rangeTrackerEnumerate(rt);
|
||||||
|
@ -196,12 +211,12 @@ START_TEST(rangeTracker_smokeTest) {
|
||||||
|
|
||||||
assert(ts[0]->pos == 80 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
|
assert(ts[0]->pos == 80 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
|
||||||
ts[1]->pos == 90 && ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
|
ts[1]->pos == 90 && ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
|
||||||
|
free(ts);
|
||||||
|
|
||||||
r.start = 80;
|
r.start = 80;
|
||||||
r.stop = 90;
|
r.stop = 90;
|
||||||
|
|
||||||
rangeTrackerRemove(rt, &r);
|
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
|
||||||
|
|
||||||
// printRT(rt);
|
// printRT(rt);
|
||||||
ts = rangeTrackerEnumerate(rt);
|
ts = rangeTrackerEnumerate(rt);
|
||||||
|
@ -210,16 +225,16 @@ START_TEST(rangeTracker_smokeTest) {
|
||||||
// | | | | |
|
// | | | | |
|
||||||
// | | | | |
|
// | | | | |
|
||||||
// | | | | |
|
// | | | | |
|
||||||
|
|
||||||
|
|
||||||
assert(!ts[0]);
|
assert(!ts[0]);
|
||||||
|
free(ts);
|
||||||
|
|
||||||
rangeTrackerDeinit(rt);
|
rangeTrackerDeinit(rt);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
#define RANGE_SIZE 1000
|
#define RANGE_SIZE 1000
|
||||||
#define ITERATIONS 1000
|
#define ITERATIONS 10000 //1000
|
||||||
#define RANGE_COUNT 100
|
#define RANGE_COUNT 1000 // 100
|
||||||
void randomRange(range * r) {
|
void randomRange(range * r) {
|
||||||
long start = myrandom(RANGE_SIZE-1);
|
long start = myrandom(RANGE_SIZE-1);
|
||||||
long len = 1+myrandom(RANGE_SIZE - start - 1);
|
long len = 1+myrandom(RANGE_SIZE - start - 1);
|
||||||
|
@ -261,44 +276,66 @@ START_TEST (rangeTracker_randomTest) {
|
||||||
|
|
||||||
gettimeofday(&time,0);
|
gettimeofday(&time,0);
|
||||||
|
|
||||||
long seed = time.tv_usec + time.tv_sec * 1000000;
|
long seed = time.tv_usec + time.tv_sec * 1000000;// 1170727703805787; //
|
||||||
printf("\nSeed = %ld\n", seed);
|
printf("\nSeed = %ld\n", seed);
|
||||||
srandom(seed);
|
srandom(seed);
|
||||||
|
|
||||||
|
range ** r_arry;
|
||||||
range * ranges = malloc(sizeof(range) * RANGE_COUNT);
|
range * ranges = malloc(sizeof(range) * RANGE_COUNT);
|
||||||
int * pins = calloc(RANGE_COUNT, sizeof(int));
|
int * pins = calloc(RANGE_COUNT, sizeof(int));
|
||||||
rangeTracker * rt = rangeTrackerInit(512);
|
rangeTracker * rt = rangeTrackerInit(QUANTIZATION);
|
||||||
for(long i = 0; i < RANGE_COUNT; i++) {
|
for(long i = 0; i < RANGE_COUNT; i++) {
|
||||||
randomRange(&(ranges[i]));
|
randomRange(&(ranges[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
char * bitmask = calloc(RANGE_SIZE, sizeof(char));
|
char * s;
|
||||||
|
|
||||||
for(long i = 0; i < ITERATIONS; i++) {
|
for(long i = 0; i < ITERATIONS; i++) {
|
||||||
|
|
||||||
int range = myrandom(RANGE_COUNT);
|
int range = myrandom(RANGE_COUNT);
|
||||||
|
|
||||||
switch(myrandom(3)) {
|
switch(myrandom(3)) {
|
||||||
case 0: { // add range
|
case 0: { // add range
|
||||||
rangeTrackerAdd(rt, &ranges[range]);
|
s = rangeToString(&ranges[range]);
|
||||||
|
printf("pin %s\n", s);
|
||||||
|
free(s);
|
||||||
|
r_arry = rangeTrackerAdd(rt, &ranges[range]);
|
||||||
|
for(int i = 0; r_arry[i]; i++) {
|
||||||
|
s = rangeToString(r_arry[i]);
|
||||||
|
printf(" add returned %s\n", s);
|
||||||
|
free(s);
|
||||||
|
free(r_arry[i]);
|
||||||
|
}
|
||||||
|
free(r_arry);
|
||||||
pins[range]++;
|
pins[range]++;
|
||||||
checkRangeTrackerConsistency(rt);
|
checkRangeTrackerConsistency(rt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: { // del range
|
case 1: { // del range
|
||||||
if(pins[range]) {
|
if(pins[range]) {
|
||||||
rangeTrackerRemove(rt, &ranges[range]);
|
s = rangeToString(&ranges[range]);
|
||||||
|
printf("unpin %s\n", s);
|
||||||
|
free(s);
|
||||||
|
r_arry = rangeTrackerRemove(rt, &ranges[range]);
|
||||||
|
for(int i = 0; r_arry[i]; i++) {
|
||||||
|
s = rangeToString(r_arry[i]);
|
||||||
|
printf(" del returned %s\n", s);
|
||||||
|
free(s);
|
||||||
|
free(r_arry[i]);
|
||||||
|
}
|
||||||
|
free(r_arry);
|
||||||
pins[range]--;
|
pins[range]--;
|
||||||
}
|
}
|
||||||
checkRangeTrackerConsistency(rt);
|
checkRangeTrackerConsistency(rt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: { // change range
|
case 2: { // change range
|
||||||
|
if(!myrandom(100)) {
|
||||||
for(long i = 0; i < RANGE_COUNT; i++) {
|
for(long i = 0; i < RANGE_COUNT; i++) {
|
||||||
if(!pins[i]) {
|
if(!pins[i]) {
|
||||||
randomRange(&ranges[i]);
|
randomRange(&ranges[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -308,13 +345,23 @@ START_TEST (rangeTracker_randomTest) {
|
||||||
|
|
||||||
for(long i = 0; i < RANGE_COUNT; i++) {
|
for(long i = 0; i < RANGE_COUNT; i++) {
|
||||||
while(pins[i]) {
|
while(pins[i]) {
|
||||||
rangeTrackerRemove(rt, &ranges[i]);
|
s = rangeToString(&ranges[i]);
|
||||||
|
printf("unpin %s\n", s);
|
||||||
|
free(s);
|
||||||
|
range ** r_arry = rangeTrackerRemove(rt, &ranges[i]);
|
||||||
|
for(int i = 0; r_arry[i]; i++) {
|
||||||
|
s = rangeToString(r_arry[i]);
|
||||||
|
printf(" del returned %s\n", s);
|
||||||
|
free(s);
|
||||||
|
free(r_arry[i]);
|
||||||
|
}
|
||||||
|
free(r_arry);
|
||||||
pins[i]--;
|
pins[i]--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free (bitmask);
|
free (ranges);
|
||||||
|
free (pins);
|
||||||
rangeTrackerDeinit(rt);
|
rangeTrackerDeinit(rt);
|
||||||
|
|
||||||
} END_TEST
|
} END_TEST
|
||||||
|
|
Loading…
Reference in a new issue