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
|
||||
@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);
|
||||
/**
|
||||
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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
if(t) {
|
||||
assert(t->delta);
|
||||
assert(t->pins >= 0);
|
||||
assert(t->pins + t->delta >= 0);
|
||||
if(t->pos != r->start) {
|
||||
int newpins = t->pins + t->delta;
|
||||
t = malloc(sizeof(transition));
|
||||
t->pos = r->start;
|
||||
t->delta = delta;
|
||||
t->pins = newpins;
|
||||
assert(newpins >= 0);
|
||||
RB_ENTRY(search)(t, rt->ranges); // insert
|
||||
curpin = t->pins + t->delta;
|
||||
} else {
|
||||
t->delta += delta;
|
||||
curpin = t->pins + t->delta;
|
||||
assert(curpin >= 0);
|
||||
if(t->delta == 0) {
|
||||
RB_ENTRY(delete)(t, rt->ranges);
|
||||
key.pos = t->pos;
|
||||
|
@ -81,6 +86,7 @@ static void rangeTrackerDelta(rangeTracker * rt, const range * r, int delta) {
|
|||
t->pins = 0;
|
||||
RB_ENTRY(search)(t, rt->ranges); // insert
|
||||
curpin = t->pins + t->delta;
|
||||
assert(curpin >= 0);
|
||||
}
|
||||
|
||||
// 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->pins == curpin);
|
||||
curpin = t->pins + t->delta;
|
||||
assert(curpin >= 0);
|
||||
}
|
||||
if(!t || t->pos != r->stop) {
|
||||
// Need to allocate new transition
|
||||
|
@ -104,6 +111,7 @@ static void rangeTrackerDelta(rangeTracker * rt, const range * r, int delta) {
|
|||
t->pos = r->stop;
|
||||
t->delta = 0-delta;
|
||||
t->pins = curpin;
|
||||
assert(curpin >= 0);
|
||||
RB_ENTRY(search)(t, rt->ranges); // insert
|
||||
} else {
|
||||
// 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) {
|
||||
rangeTrackerDelta(rt, r, 1);
|
||||
static range ** rangeTrackerToArray(rangeTracker * rt) {
|
||||
// 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
|
||||
*/
|
||||
|
||||
range ** rangeTrackerRemove(rangeTracker * rt, const range * r) {
|
||||
rangeTrackerDelta(rt, r, -1);
|
||||
range ** rangeTrackerRemove(rangeTracker * rt, const range * rang) {
|
||||
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) {
|
||||
|
@ -169,3 +517,4 @@ char * transitionToString(const transition * t) {
|
|||
assert(err !=-1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include <lladd/transactional.h>
|
||||
#define LOG_NAME "check_rangeTracker.log"
|
||||
|
||||
#define QUANTIZATION 7
|
||||
|
||||
#include <lladd/io/rangeTracker.h>
|
||||
|
||||
#include "../check_includes.h"
|
||||
|
@ -18,6 +20,12 @@ long myrandom(long x) {
|
|||
return (long)((r/max));
|
||||
}
|
||||
|
||||
void rangeTrackerFreeRet(range ** ret) {
|
||||
for(int i = 0; ret[i]; i++) {
|
||||
free(ret[i]);
|
||||
}
|
||||
free(ret);
|
||||
}
|
||||
void printRT(rangeTracker * rt) {
|
||||
const transition ** ts = rangeTrackerEnumerate(rt);
|
||||
int i = 0;
|
||||
|
@ -30,7 +38,7 @@ void printRT(rangeTracker * rt) {
|
|||
}
|
||||
|
||||
START_TEST(rangeTracker_smokeTest) {
|
||||
rangeTracker * rt = rangeTrackerInit(512);
|
||||
rangeTracker * rt = rangeTrackerInit(QUANTIZATION);
|
||||
|
||||
const transition ** ts = rangeTrackerEnumerate(rt);
|
||||
|
||||
|
@ -45,7 +53,8 @@ START_TEST(rangeTracker_smokeTest) {
|
|||
r.start = 10;
|
||||
r.stop = 100;
|
||||
|
||||
rangeTrackerAdd(rt, &r);
|
||||
rangeTrackerFreeRet(rangeTrackerAdd(rt, &r));
|
||||
|
||||
|
||||
// printRT(rt);
|
||||
|
||||
|
@ -60,10 +69,12 @@ START_TEST(rangeTracker_smokeTest) {
|
|||
ts[1]->pos == 100&& ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
|
||||
|
||||
|
||||
free(ts);
|
||||
|
||||
r.start = 20;
|
||||
r.stop = 80;
|
||||
|
||||
rangeTrackerRemove(rt, &r);
|
||||
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
|
||||
|
||||
// printRT(rt);
|
||||
|
||||
|
@ -80,10 +91,11 @@ START_TEST(rangeTracker_smokeTest) {
|
|||
ts[3]->pos == 100&& ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
|
||||
|
||||
|
||||
rangeTrackerAdd(rt, &r);
|
||||
rangeTrackerFreeRet(rangeTrackerAdd(rt, &r));
|
||||
|
||||
// printRT(rt);
|
||||
|
||||
free(ts);
|
||||
ts = rangeTrackerEnumerate(rt);
|
||||
|
||||
// 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 &&
|
||||
ts[1]->pos == 100&& ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
|
||||
|
||||
rangeTrackerAdd(rt, &r);
|
||||
rangeTrackerFreeRet(rangeTrackerAdd(rt, &r));
|
||||
|
||||
// printRT(rt);
|
||||
|
||||
free(ts);
|
||||
ts = rangeTrackerEnumerate(rt);
|
||||
|
||||
// 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[3]->pos == 100&& ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
|
||||
|
||||
|
||||
rangeTrackerRemove(rt, &r);
|
||||
free(ts);
|
||||
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
|
||||
ts = rangeTrackerEnumerate(rt);
|
||||
|
||||
// 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 &&
|
||||
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);
|
||||
|
||||
|
@ -138,13 +152,13 @@ START_TEST(rangeTracker_smokeTest) {
|
|||
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[3]->pos == 100&& ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
|
||||
|
||||
free(ts);
|
||||
r.start = 80;
|
||||
r.stop = 90;
|
||||
|
||||
|
||||
|
||||
rangeTrackerAdd(rt, &r);
|
||||
rangeTrackerFreeRet(rangeTrackerAdd(rt, &r));
|
||||
|
||||
// printRT(rt);
|
||||
|
||||
|
@ -161,10 +175,11 @@ START_TEST(rangeTracker_smokeTest) {
|
|||
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[4]->pos == 100&& ts[4]->delta == -1 && ts[4]->pins == 1 && !ts[5]);
|
||||
|
||||
free(ts);
|
||||
r.start = 80;
|
||||
r.stop = 100;
|
||||
rangeTrackerRemove(rt, &r);
|
||||
|
||||
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
|
||||
|
||||
// printRT(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[3]->pos == 90 && ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
|
||||
|
||||
|
||||
free(ts);
|
||||
r.start = 10;
|
||||
r.stop = 20;
|
||||
rangeTrackerRemove(rt, &r);
|
||||
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
|
||||
|
||||
// printRT(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 &&
|
||||
ts[1]->pos == 90 && ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
|
||||
|
||||
free(ts);
|
||||
|
||||
r.start = 80;
|
||||
r.stop = 90;
|
||||
|
||||
rangeTrackerRemove(rt, &r);
|
||||
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
|
||||
|
||||
// printRT(rt);
|
||||
ts = rangeTrackerEnumerate(rt);
|
||||
|
@ -210,16 +225,16 @@ START_TEST(rangeTracker_smokeTest) {
|
|||
// | | | | |
|
||||
// | | | | |
|
||||
// | | | | |
|
||||
|
||||
|
||||
assert(!ts[0]);
|
||||
free(ts);
|
||||
|
||||
rangeTrackerDeinit(rt);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
#define RANGE_SIZE 1000
|
||||
#define ITERATIONS 1000
|
||||
#define RANGE_COUNT 100
|
||||
#define ITERATIONS 10000 //1000
|
||||
#define RANGE_COUNT 1000 // 100
|
||||
void randomRange(range * r) {
|
||||
long start = myrandom(RANGE_SIZE-1);
|
||||
long len = 1+myrandom(RANGE_SIZE - start - 1);
|
||||
|
@ -261,44 +276,66 @@ START_TEST (rangeTracker_randomTest) {
|
|||
|
||||
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);
|
||||
srandom(seed);
|
||||
|
||||
range ** r_arry;
|
||||
range * ranges = malloc(sizeof(range) * RANGE_COUNT);
|
||||
int * pins = calloc(RANGE_COUNT, sizeof(int));
|
||||
rangeTracker * rt = rangeTrackerInit(512);
|
||||
rangeTracker * rt = rangeTrackerInit(QUANTIZATION);
|
||||
for(long i = 0; i < RANGE_COUNT; i++) {
|
||||
randomRange(&(ranges[i]));
|
||||
}
|
||||
|
||||
char * bitmask = calloc(RANGE_SIZE, sizeof(char));
|
||||
char * s;
|
||||
|
||||
for(long i = 0; i < ITERATIONS; i++) {
|
||||
|
||||
int range = myrandom(RANGE_COUNT);
|
||||
|
||||
switch(myrandom(3)) {
|
||||
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]++;
|
||||
checkRangeTrackerConsistency(rt);
|
||||
break;
|
||||
}
|
||||
case 1: { // del 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]--;
|
||||
}
|
||||
checkRangeTrackerConsistency(rt);
|
||||
break;
|
||||
}
|
||||
case 2: { // change range
|
||||
if(!myrandom(100)) {
|
||||
for(long i = 0; i < RANGE_COUNT; i++) {
|
||||
if(!pins[i]) {
|
||||
randomRange(&ranges[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -308,13 +345,23 @@ START_TEST (rangeTracker_randomTest) {
|
|||
|
||||
for(long i = 0; i < RANGE_COUNT; 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]--;
|
||||
}
|
||||
}
|
||||
|
||||
free (bitmask);
|
||||
|
||||
free (ranges);
|
||||
free (pins);
|
||||
rangeTrackerDeinit(rt);
|
||||
|
||||
} END_TEST
|
||||
|
|
Loading…
Reference in a new issue