7 * Write a lump to disk. Updates ia with an index address
8 * for the newly-written lump. Upon return, the lump will
9 * have been placed in the disk cache but will likely not be on disk yet.
12 storeclump(Index *ix, ZBlock *zb, u8int *sc, int type, u32int creator, IAddr *ia)
17 u8int bh[VtScoreSize];
20 trace(TraceLump, "storeclump enter", sc, type);
22 if(size > VtMaxLumpSize){
23 seterr(EStrange, "lump too large");
26 if(vttypevalid(type) < 0){
27 seterr(EStrange, "invalid lump type");
32 scoremem(bh, zb->data, size);
33 if(scorecmp(sc, bh) != 0){
34 seterr(ECorrupt, "storing clump: corrupted; expected=%V got=%V, size=%d", sc, bh, size);
39 cb = alloczblock(size + ClumpSize + U32Size, 0, 0);
44 cl.info.uncsize = size;
47 scorecp(cl.info.score, sc);
49 trace(TraceLump, "storeclump whackblock");
50 dsize = whackblock(&cb->data[ClumpSize], zb->data, size);
51 if(dsize > 0 && dsize < size){
52 cl.encoding = ClumpECompress;
55 fprint(2, "whack error: dsize=%d size=%d\n", dsize, size);
58 cl.encoding = ClumpENone;
60 memmove(&cb->data[ClumpSize], zb->data, size);
62 memset(cb->data+ClumpSize+dsize, 0, 4);
68 ia->blocks = (dsize + ClumpSize + (1 << ABlockLog) - 1) >> ABlockLog;
70 a = writeiclump(ix, &cl, cb->data, &ia->addr);
72 trace(TraceLump, "storeclump exit %lld", a);
81 stats.clumpbwrites += size;
82 stats.clumpbcomp += dsize;
90 clumpmagic(Arena *arena, u64int aa)
94 if(readarena(arena, aa, buf, U32Size) < 0)
96 return unpackmagic(buf);
100 * fetch a block based at addr.
101 * score is filled in with the block's score.
102 * blocks is roughly the length of the clump on disk;
103 * if zero, the length is unknown.
106 loadclump(Arena *arena, u64int aa, int blocks, Clump *cl, u8int *score, int verify)
110 u8int bh[VtScoreSize], *buf;
117 qunlock(&stats.lock);
123 trace(TraceLump, "loadclump enter");
125 cb = alloczblock(blocks << ABlockLog, 0, 0);
128 n = readarena(arena, aa, cb->data, blocks << ABlockLog);
131 seterr(ECorrupt, "loadclump read less than a header");
135 trace(TraceLump, "loadclump unpack");
136 if(unpackclump(cl, cb->data, arena->clumpmagic) < 0){
137 seterr(ECorrupt, "loadclump %s %llud: %r", arena->name, aa);
142 if(n < cl->info.size){
145 cb = alloczblock(n, 0, 0);
148 if(readarena(arena, aa + ClumpSize, cb->data, n) != n){
149 seterr(ECorrupt, "loadclump read too little data");
155 buf = cb->data + ClumpSize;
157 scorecp(score, cl->info.score);
159 zb = alloczblock(cl->info.uncsize, 0, 0);
164 switch(cl->encoding){
166 trace(TraceLump, "loadclump decompress");
168 nunc = unwhack(&uw, zb->data, cl->info.uncsize, buf, cl->info.size);
169 if(nunc != cl->info.uncsize){
171 seterr(ECorrupt, "decompression of %llud failed: %s", aa, uw.err);
173 seterr(ECorrupt, "decompression of %llud gave partial block: %d/%d\n", aa, nunc, cl->info.uncsize);
180 if(cl->info.size != cl->info.uncsize){
181 seterr(ECorrupt, "loading clump: bad uncompressed size for uncompressed block %llud", aa);
186 scoremem(bh, buf, cl->info.uncsize);
187 if(scorecmp(cl->info.score, bh) != 0)
188 seterr(ECorrupt, "pre-copy sha1 wrong at %s %llud: expected=%V got=%V", arena->name, aa, cl->info.score, bh);
189 memmove(zb->data, buf, cl->info.uncsize);
192 seterr(ECorrupt, "unknown encoding in loadlump %llud", aa);
200 trace(TraceLump, "loadclump verify");
201 scoremem(bh, zb->data, cl->info.uncsize);
202 if(scorecmp(cl->info.score, bh) != 0){
203 seterr(ECorrupt, "loading clump: corrupted at %s %llud; expected=%V got=%V", arena->name, aa, cl->info.score, bh);
207 if(vttypevalid(cl->info.type) < 0){
208 seterr(ECorrupt, "loading lump at %s %llud: invalid lump type %d", arena->name, aa, cl->info.type);
214 trace(TraceLump, "loadclump exit");
217 stats.clumpbreads += cl->info.size;
218 stats.clumpbuncomp += cl->info.uncsize;
219 qunlock(&stats.lock);