commit 59a9682013a2f4c5ee679ba910fe234ea61f6808 from: rsc date: Thu Jun 17 21:13:51 2004 UTC attempt better flushing ' commit - eacc220a040de32a873340274f09b8e0498ff85f commit + 59a9682013a2f4c5ee679ba910fe234ea61f6808 blob - b2f5b15576b20873a275c858b008e9f7a4d34d34 blob + 1afa2a460c2affb7e5e7783ae16daba557724542 --- src/libventi/file.c +++ src/libventi/file.c @@ -664,7 +664,7 @@ mkindices(VtEntry *e, u32int bn, int *index) { int i, np; - memset(index, 0, VtPointerDepth*sizeof(int)); + memset(index, 0, (VtPointerDepth+1)*sizeof(int)); np = e->psize/VtScoreSize; for(i=0; bn > 0; i++){ @@ -1168,8 +1168,8 @@ vtfileflushbefore(VtFile *r, u64int offset) { VtBlock *b, *bb; VtEntry e; - int i, base, depth, ppb, epb, ok; - int index[VtPointerDepth+1], index1[VtPointerDepth+1], j, ret; + int i, base, depth, ppb, epb, doflush; + int index[VtPointerDepth+1], j, ret; VtBlock *bi[VtPointerDepth+2]; uchar *score; @@ -1181,6 +1181,9 @@ vtfileflushbefore(VtFile *r, u64int offset) if(b == nil) return -1; + /* + * compute path through tree for the last written byte and the next one. + */ ret = -1; memset(bi, 0, sizeof bi); depth = DEPTH(e.type); @@ -1190,10 +1193,12 @@ vtfileflushbefore(VtFile *r, u64int offset) goto Err; if(i > depth) goto Err; - mkindices(&e, offset/e.dsize, index1); ppb = e.psize / VtScoreSize; epb = e.dsize / VtEntrySize; + /* + * load the blocks along the last written byte + */ index[depth] = r->offset % r->epb; for(i=depth; i>=0; i--){ bb = blockwalk(b, index[i], r->c, VtORDWR, &e); @@ -1204,33 +1209,41 @@ vtfileflushbefore(VtFile *r, u64int offset) } ret = 0; + /* + * walk up the path from leaf to root, flushing anything that + * has been finished. + */ base = e.type&~VtTypeDepthMask; for(i=0; ic, nil, b->data+j*VtScoreSize, ppb, epb, base+i-1) < 0) goto Err; + /* - * if the rest of the block is already flushed, - * we can flush the whole block. + * if index[i-1] is the last entry in the block and is global + * (i.e. the kid is flushed), then we can flush this block. */ - ok = 0; - if(index[i] != index1[i]){ - ok = 1; - for(; jdata+j*VtScoreSize) != NilBlock) - ok = 0; - } + if(j==ppb-1 && vtglobaltolocal(b->data+j*VtScoreSize)==NilBlock) + doflush = 1; } - if(ok){ + if(doflush){ if(i == depth) score = e.score; else