Rewrote pinnedRanges.

This commit is contained in:
Sears Russell 2007-02-07 03:04:19 +00:00
parent fe30fbbd74
commit d2d631ff30
2 changed files with 149 additions and 21 deletions

View file

@ -198,18 +198,111 @@ static inline long roundUp(long x, long quant) {
return (((x-1) / quant) + 1) * quant;
}
static void pinnedRanges(const rangeTracker * rt, const range * request, rangeTracker * ret, int delta) {
transition key;
// we will start looking at the tree at the first transition after key.pos.
// DEL OLD COMMENT: the -1 gives us >= instead of > when we pass RB_LUGREAT into rblookup.
key.pos = roundDown(request->start, rt->quantization);
const transition * t = &key;
int in_range = 0; // 0 if the last transition marked the end of a range.
int have_range = 0; // 1 once we have encountered the first range.
range cur;
range expanded_range;
expanded_range.start = roundDown(request->start, rt->quantization);
expanded_range.stop = roundUp(request->stop, rt->quantization);
while((t = rblookup(RB_LUGREAT, t, rt->ranges))) {
assert(t->delta);
// printf("%s\n", transitionToString(t));
if(t->pos >= expanded_range.stop) {
if(in_range) {
assert(t->pins);
assert(have_range);
cur.stop = expanded_range.stop;
assert(cur.stop != cur.start);
in_range = 0;
} else {
if(!have_range) {
// we are at first transition
if(t->pins) {
cur = expanded_range;
have_range = 1;
} else {
// no ranges are pinned.
}
}
}
// Pretend we hit the end of the tree.
break;
} else {
if(in_range) {
assert(have_range);
assert(t->pins);
if(!(t->pins + t->delta)) {
cur.stop = roundUp(t->pos, rt->quantization);
assert(cur.stop != cur.start);
in_range = 0;
} else {
assert(in_range);
}
} else {
// not in range.
if(!have_range) {
// we are at first transition
if(t->pins) {
cur.start = expanded_range.start;
in_range = t->pins + t->delta;
if(! in_range) {
cur.stop = roundUp(t->pos, rt->quantization);
assert(cur.stop != cur.start);
}
} else {
cur.start = roundDown(t->pos, rt->quantization);
in_range = 1;
assert(t->pins + t->delta);
}
have_range = 1;
} else {
assert(! t->pins);
assert(t->pins + t->delta);
// do we need to merge this transition with the range, or output the old range?
if(cur.stop >= roundDown(t->pos, rt->quantization)) {
// do nothing; start position doesn't change.
} else {
// output old range, reset start position
rangeTrackerDelta(ret, &cur, delta);
cur.start = roundDown(t->pos, rt->quantization);
}
in_range = 1;
}
}
}
}
assert(!in_range);
if(have_range) {
rangeTrackerDelta(ret, &cur, delta);
}
}
//#define DBGPINS(...) printf(__VA_ARGS__)
#define DBGPINS(...)
/**
@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) {
static rangeTracker * pinnedRangesOLD(const rangeTracker * rt, const range * request, rangeTracker * ret, int delta) {
transition key;
const transition * t;
DBGPINS("Call ");
key.pos = roundDown(request->start, rt->quantization);
t = rblookup(RB_LUGTEQ, &key, rt->ranges);
if(!t) {
DBGPINS("at End\n");
// No ranges after request->start, so no ranges can overlap.
return ret;
}
@ -224,6 +317,7 @@ static rangeTracker * pinnedRanges(const rangeTracker * rt, const range * reques
long putative_range_stop;
if(t) {
DBGPINS("T %ld", t->pos);
if(roundDown(t->pos, rt->quantization) >= roundUp(request->stop, rt->quantization)) {
if(t->pins) {
// entire range is pinned.
@ -234,51 +328,80 @@ static rangeTracker * pinnedRanges(const rangeTracker * rt, const range * reques
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));
// DBGPINS("0 %s\n", rangeToString(&tmp_r));
} else {
// none of the range is pinned.
}
return ret;
}
if(t->pins) {
} else if(t->pins) {
DBGPINS("startPin ");
// The beginning of request is a range.
range_start = roundDown(request->start, rt->quantization);
if(0 == t->pins + t->delta) {
DBGPINS("!in ");
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 {
DBGPINS("in ");
in_range = 1;
}
} else {
DBGPINS("start!Pin ");
// The beginning of the request is not a range.
range_start = roundDown(t->pos, rt->quantization);
DBGPINS("A ");
in_range = 1;
assert(t->delta);
}
} else {
DBGPINS("!T ");
}
while((t = rblookup(RB_LUGREAT, t, rt->ranges))) {
DBGPINS("W %ld", t->pos);
assert(t->delta);
if(roundUp(t->pos, rt->quantization) >= roundUp(request->stop, rt->quantization)) {
DBGPINS("Break ");
if(in_range) {
assert(t->pins);
// 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);
// deal with range that ended before this transition.
range tmp_r;
assert(t->pins == 0);
if(roundUp(putative_range_stop, rt->quantization) < roundDown(t->pos, rt->quantization)) {
// There is a gap between the last range and this range.
tmp_r.start = range_start;
tmp_r.stop = putative_range_stop;
if(tmp_r.start != tmp_r.stop) {
rangeTrackerDelta(ret, &tmp_r, delta);
}
// 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
range_start = roundDown(t->pos, rt->quantization);
putative_range_stop = roundUp(request->stop, rt->quantization);
} else {
in_range = 2;
}
} else {
// There is no gap between the last range and this range.
putative_range_stop = roundUp(request->stop, rt->quantization);
}
}
break;
}
if(t->pins) {
DBGPINS("P ");
assert(in_range);
if(!(t->pins + t->delta)) {
@ -287,6 +410,7 @@ static rangeTracker * pinnedRanges(const rangeTracker * rt, const range * reques
}
} else { // ! t->pins
DBGPINS("!P ");
assert(!in_range);
if(putative_range_stop < roundDown(t->pos, rt->quantization)) {
@ -297,7 +421,7 @@ static rangeTracker * pinnedRanges(const rangeTracker * rt, const range * reques
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));
// DBGPINS("1 %s\n", rangeToString(&tmp_r));
}
range_start = roundDown(t->pos, rt->quantization);
} else {
@ -306,16 +430,20 @@ static rangeTracker * pinnedRanges(const rangeTracker * rt, const range * reques
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));
assert(in_range==0 || in_range ==2);
if(!in_range) {
range tmp_r;
tmp_r.start = range_start;
tmp_r.stop = putative_range_stop;
if(tmp_r.start != tmp_r.stop) {
DBGPINS("2 ");
assert(tmp_r.start >= roundDown(request->start, rt->quantization) && tmp_r.stop <= roundUp(request->stop, rt->quantization));
rangeTrackerDelta(ret, &tmp_r, delta);
// DBGPINS("2 %s\n", rangeToString(&tmp_r));
}
}
DBGPINS("\n");
return ret;
}

View file

@ -276,7 +276,7 @@ START_TEST (rangeTracker_randomTest) {
gettimeofday(&time,0);
long seed = time.tv_usec + time.tv_sec * 1000000;// 1170727703805787; //
long seed = time.tv_usec + time.tv_sec * 1000000; //1170807889195512; //time.tv_usec + time.tv_sec * 1000000; //1170729550013502; //time.tv_usec + time.tv_sec * 1000000;// 1170727703805787; // 1170810757441165; 1170811024737237; //
printf("\nSeed = %ld\n", seed);
srandom(seed);