7 static int sizeToDepth(uvlong s, int psize, int dsize);
10 sizeToDepth(uvlong s, int psize, int dsize)
15 /* determine pointer depth */
16 np = psize/VtScoreSize;
17 s = (s + dsize - 1)/dsize;
18 for(d = 0; s > 1; d++)
23 /* assumes u is lock? */
25 sourceAlloc(Cache *c, Lump *u, ulong block, int entry, int readOnly)
30 if(u->asize < (entry+1)*VtEntrySize) {
35 if(!vtEntryUnpack(&d, u->data, entry))
38 if(!(d.flags & VtEntryActive)) {
39 fprint(2, "bad flags %#ux %V\n", d.flags, d.score);
44 /* HACK for backwards compatiblity - should go away at some point */
46 if(d.size > d.dsize) fprint(2, "depth == 0! size = %ulld\n", d.size);
47 d.depth = sizeToDepth(d.size, d.psize, d.dsize);
50 if(d.depth < sizeToDepth(d.size, d.psize, d.dsize)) {
55 r = vtMemAllocZ(sizeof(Source));
56 r->lk = vtLockAlloc();
58 r->readOnly = readOnly;
59 r->lump = lumpIncRef(u);
63 r->dir = (d.flags & VtEntryDir) != 0;
69 r->epb = r->dsize/VtEntrySize;
75 sourceOpen(Source *r, ulong entry, int readOnly)
80 if(0)fprint(2, "sourceOpen: %V:%d: %lud\n", r->lump->score, r->entry, entry);
81 if(r->readOnly && !readOnly) {
82 vtSetError(EReadOnly);
88 u = sourceGetLump(r, bn, readOnly, 1);
92 r = sourceAlloc(r->cache, u, bn, entry%r->epb, readOnly);
98 sourceCreate(Source *r, int psize, int dsize, int isdir, ulong entry)
107 vtSetError(EReadOnly);
113 * look at a random block to see if we can find an empty entry
115 entry = sourceGetDirSize(r);
116 entry = r->epb*lnrand(entry/r->epb+1);
120 * need to loop since multiple threads could be trying to allocate
124 sourceSetDepth(r, (uvlong)(bn+1)*r->dsize);
125 u = sourceGetLump(r, bn, 0, 1);
128 for(i=entry%r->epb; i<r->epb; i++) {
129 vtEntryUnpack(&dir, u->data, i);
130 if((dir.flags&VtEntryActive) == 0 && dir.gen != ~0)
134 entry = sourceGetDirSize(r);
140 dir.flags = VtEntryActive;
142 dir.flags |= VtEntryDir;
145 memmove(dir.score, vtZeroScore, VtScoreSize);
146 vtEntryPack(&dir, u->data, i);
148 sourceSetDirSize(r, bn*r->epb + i + 1);
149 rr = sourceAlloc(r->cache, u, bn, i, 0);
156 sourceRemove(Source *r)
158 lumpFreeEntry(r->lump, r->entry);
163 sourceSetDepth(Source *r, uvlong size)
170 vtSetError(EReadOnly);
174 depth = sizeToDepth(size, r->psize, r->dsize);
178 if(depth > VtPointerDepth) {
185 if(r->depth >= depth) {
192 if(!vtEntryUnpack(&dir, u->data, r->entry)) {
197 while(dir.depth < depth) {
198 v = cacheAllocLump(r->cache, VtPointerType0+r->depth, r->psize, r->dir);
201 memmove(v->data, dir.score, VtScoreSize);
202 memmove(dir.score, v->score, VtScoreSize);
206 vtEntryPack(&dir, u->data, r->entry);
209 r->depth = dir.depth;
212 return dir.depth == depth;
216 sourceGetVtEntry(Source *r, VtEntry *dir)
222 if(!vtEntryUnpack(dir, u->data, r->entry)) {
231 sourceGetSize(Source *r)
244 sourceSetSize(Source *r, uvlong size)
251 vtSetError(EReadOnly);
255 if(size > VtMaxFileSize || size > ((uvlong)MaxBlock)*r->dsize) {
261 depth = sizeToDepth(size, r->psize, r->dsize);
266 if(depth > r->depth) {
274 vtEntryUnpack(&dir, u->data, r->entry);
276 vtEntryPack(&dir, u->data, r->entry);
284 sourceSetDirSize(Source *r, ulong ds)
288 size = (uvlong)r->dsize*(ds/r->epb);
289 size += VtEntrySize*(ds%r->epb);
290 return sourceSetSize(r, size);
294 sourceGetDirSize(Source *r)
299 size = sourceGetSize(r);
300 ds = r->epb*(size/r->dsize);
301 ds += (size%r->dsize)/VtEntrySize;
306 sourceGetNumBlocks(Source *r)
308 return (sourceGetSize(r)+r->dsize-1)/r->dsize;
312 sourceWalk(Source *r, ulong block, int readOnly, int *off)
317 int elem[VtPointerDepth+1];
320 if(r->readOnly && !readOnly) {
321 vtSetError(EReadOnly);
326 np = r->psize/VtScoreSize;
328 for(i=0; i<r->depth; i++) {
334 vtSetError(EBadOffset);
338 u = lumpIncRef(r->lump);
343 for(i=depth; i>0; i--) {
344 v = lumpWalk(u, elem[i], VtPointerType0+i-1, r->psize, readOnly, 0);
355 sourceGetLump(Source *r, ulong block, int readOnly, int lock)
360 if(r->readOnly && !readOnly) {
361 vtSetError(EReadOnly);
364 if(block == NilBlock) {
365 vtSetError(ENilBlock);
368 if(0)fprint(2, "sourceGetLump: %V:%d %lud\n", r->lump->score, r->entry, block);
369 u = sourceWalk(r, block, readOnly, &off);
376 v = lumpWalk(u, off, type, r->dsize, readOnly, lock);
382 sourceFree(Source *k)
386 lumpDecRef(k->lump, 0);
388 memset(k, ~0, sizeof(*k));