diff options
author | rsc <devnull@localhost> | 2004-06-17 21:13:51 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-06-17 21:13:51 +0000 |
commit | 59a9682013a2f4c5ee679ba910fe234ea61f6808 (patch) | |
tree | 4b44626be22fd3229c84463abcff61576473f332 /src/libventi | |
parent | eacc220a040de32a873340274f09b8e0498ff85f (diff) | |
download | plan9port-59a9682013a2f4c5ee679ba910fe234ea61f6808.tar.gz plan9port-59a9682013a2f4c5ee679ba910fe234ea61f6808.tar.bz2 plan9port-59a9682013a2f4c5ee679ba910fe234ea61f6808.zip |
attempt better flushing
'
Diffstat (limited to 'src/libventi')
-rw-r--r-- | src/libventi/file.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/src/libventi/file.c b/src/libventi/file.c index b2f5b155..1afa2a46 100644 --- a/src/libventi/file.c +++ b/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; i<depth; i++){ + doflush = 0; if(i == 0){ - /* bottom: data or dir block */ - ok = offset%e.dsize == 0; + /* leaf: data or dir block */ + if(offset%e.dsize == 0) + doflush = 1; }else{ - /* middle: pointer blocks */ + /* + * interior node: pointer blocks. + * specifically, b = bi[i] is a block whose index[i-1]'th entry + * points at bi[i-1]. + */ b = bi[i]; + /* - * flush everything up to the break + * the index entries up to but not including index[i-1] point at + * finished blocks, so flush them for sure. */ for(j=0; j<index[i-1]; j++) if(flushblock(r->c, 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(; j<ppb; j++) - if(vtglobaltolocal(b->data+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 |