123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- #include "stdinc.h"
- #include "dat.h"
- #include "fns.h"
- int queueWrites = 0;
- static Packet *readILump(Lump *u, IAddr *ia, u8int *score, int rac);
- Packet*
- readLump(u8int *score, int type, u32int size)
- {
- Lump *u;
- Packet *p;
- IAddr ia;
- u32int n;
- int rac;
- vtLock(stats.lock);
- stats.lumpReads++;
- vtUnlock(stats.lock);
- u = lookupLump(score, type);
- if(u->data != nil){
- n = packetSize(u->data);
- if(n > size){
- setErr(EOk, "read too small: asked for %d need at least %d", size, n);
- putLump(u);
- return nil;
- }
- p = packetDup(u->data, 0, n);
- putLump(u);
- return p;
- }
- if(!lookupScore(score, type, &ia, &rac)){
- //ZZZ place to check for someone trying to guess scores
- setErr(EOk, "no block with that score exists");
- putLump(u);
- return nil;
- }
- if(ia.size > size){
- setErr(EOk, "read too small 1: asked for %d need at least %d", size, ia.size);
- putLump(u);
- return nil;
- }
- p = readILump(u, &ia, score, rac);
- putLump(u);
- return p;
- }
- /*
- * save away a lump, and return it's score.
- * doesn't store duplicates, but checks that the data is really the same.
- */
- int
- writeLump(Packet *p, u8int *score, int type, u32int creator)
- {
- Lump *u;
- int ok;
- vtLock(stats.lock);
- stats.lumpWrites++;
- vtUnlock(stats.lock);
- packetSha1(p, score);
- u = lookupLump(score, type);
- if(u->data != nil){
- ok = 1;
- if(packetCmp(p, u->data) != 0){
- setErr(EStrange, "score collision");
- ok = 0;
- }
- packetFree(p);
- putLump(u);
- return ok;
- }
- if(queueWrites)
- return queueWrite(u, p, creator);
- ok = writeQLump(u, p, creator);
- putLump(u);
- return ok;
- }
- int
- writeQLump(Lump *u, Packet *p, int creator)
- {
- ZBlock *flat;
- Packet *old;
- IAddr ia;
- int ok;
- int rac;
- if(lookupScore(u->score, u->type, &ia, &rac)){
- /*
- * if the read fails,
- * assume it was corrupted data and store the block again
- */
- old = readILump(u, &ia, u->score, rac);
- if(old != nil){
- ok = 1;
- if(packetCmp(p, old) != 0){
- setErr(EStrange, "score collision");
- ok = 0;
- }
- packetFree(p);
- packetFree(old);
- return ok;
- }
- logErr(EAdmin, "writelump: read %V failed, rewriting: %R\n", u->score);
- }
- flat = packet2ZBlock(p, packetSize(p));
- ok = storeClump(mainIndex, flat, u->score, u->type, creator, &ia);
- freeZBlock(flat);
- if(ok)
- ok = insertScore(u->score, &ia, 1);
- if(ok)
- insertLump(u, p);
- else
- packetFree(p);
- return ok;
- }
- static void
- readAhead(u64int a, Arena *arena, u64int aa, int n)
- {
- u8int buf[ClumpSize];
- Clump cl;
- IAddr ia;
- while(n > 0) {
- if (aa >= arena->used)
- break;
- if(readArena(arena, aa, buf, ClumpSize) < ClumpSize)
- break;
- if(!unpackClump(&cl, buf))
- break;
- ia.addr = a;
- ia.type = cl.info.type;
- ia.size = cl.info.uncsize;
- ia.blocks = (cl.info.size + ClumpSize + (1 << ABlockLog) - 1) >> ABlockLog;
- insertScore(cl.info.score, &ia, 0);
- a += ClumpSize + cl.info.size;
- aa += ClumpSize + cl.info.size;
- n--;
- }
- }
- static Packet*
- readILump(Lump *u, IAddr *ia, u8int *score, int rac)
- {
- Arena *arena;
- ZBlock *zb;
- Packet *p, *pp;
- Clump cl;
- u64int a, aa;
- u8int sc[VtScoreSize];
- arena = amapItoA(mainIndex, ia->addr, &aa);
- if(arena == nil)
- return nil;
- zb = loadClump(arena, aa, ia->blocks, &cl, sc, paranoid);
- if(zb == nil)
- return nil;
- if(ia->size != cl.info.uncsize){
- setErr(EInconsist, "index and clump size mismatch");
- freeZBlock(zb);
- return nil;
- }
- if(ia->type != cl.info.type){
- setErr(EInconsist, "index and clump type mismatch");
- freeZBlock(zb);
- return nil;
- }
- if(!scoreEq(score, sc)){
- setErr(ECrash, "score mismatch");
- freeZBlock(zb);
- return nil;
- }
- if(rac == 0) {
- a = ia->addr + ClumpSize + cl.info.size;
- aa += ClumpSize + cl.info.size;
- readAhead(a, arena, aa, 20);
- }
- p = zblock2Packet(zb, cl.info.uncsize);
- freeZBlock(zb);
- pp = packetDup(p, 0, packetSize(p));
- insertLump(u, pp);
- return p;
- }
|