123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- #include "stdinc.h"
- #include "dat.h"
- #include "fns.h"
- int syncwrites = 0;
- int queuewrites = 0;
- int writestodevnull = 0;
- int verifywrites = 0;
- static Packet *readilump(Lump *u, IAddr *ia, u8int *score);
- /*
- * Some of this logic is duplicated in hdisk.c
- */
- Packet*
- readlump(u8int *score, int type, u32int size, int *cached)
- {
- Lump *u;
- Packet *p;
- IAddr ia;
- u32int n;
- trace(TraceLump, "readlump enter");
- /*
- qlock(&stats.lock);
- stats.lumpreads++;
- qunlock(&stats.lock);
- */
- if(scorecmp(score, zeroscore) == 0)
- return packetalloc();
- u = lookuplump(score, type);
- if(u->data != nil){
- trace(TraceLump, "readlump lookuplump hit");
- if(cached)
- *cached = 1;
- 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(cached)
- *cached = 0;
- if(lookupscore(score, type, &ia) < 0){
- /* ZZZ place to check for someone trying to guess scores */
- seterr(EOk, "no block with score %V/%d exists", score, type);
- 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;
- }
- trace(TraceLump, "readlump readilump");
- p = readilump(u, &ia, score);
- putlump(u);
- trace(TraceLump, "readlump exit");
- 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, uint ms)
- {
- Lump *u;
- int ok;
- /*
- qlock(&stats.lock);
- stats.lumpwrites++;
- qunlock(&stats.lock);
- */
- packetsha1(p, score);
- if(packetsize(p) == 0 || writestodevnull==1){
- packetfree(p);
- return 0;
- }
- u = lookuplump(score, type);
- if(u->data != nil){
- ok = 0;
- if(packetcmp(p, u->data) != 0){
- uchar nscore[VtScoreSize];
- packetsha1(u->data, nscore);
- if(scorecmp(u->score, score) != 0)
- seterr(EStrange, "lookuplump returned bad score %V not %V", u->score, score);
- else if(scorecmp(u->score, nscore) != 0)
- seterr(EStrange, "lookuplump returned bad data %V not %V", nscore, u->score);
- else
- seterr(EStrange, "score collision %V", score);
- ok = -1;
- }
- packetfree(p);
- putlump(u);
- return ok;
- }
- if(writestodevnull==2){
- packetfree(p);
- return 0;
- }
- if(queuewrites)
- return queuewrite(u, p, creator, ms);
- ok = writeqlump(u, p, creator, ms);
- putlump(u);
- return ok;
- }
- int
- writeqlump(Lump *u, Packet *p, int creator, uint ms)
- {
- ZBlock *flat;
- Packet *old;
- IAddr ia;
- int ok;
- if(lookupscore(u->score, u->type, &ia) == 0){
- if(verifywrites == 0){
- /* assume the data is here! */
- packetfree(p);
- ms = msec() - ms;
- addstat2(StatRpcWriteOld, 1, StatRpcWriteOldTime, ms);
- return 0;
- }
- /*
- * if the read fails,
- * assume it was corrupted data and store the block again
- */
- old = readilump(u, &ia, u->score);
- if(old != nil){
- ok = 0;
- if(packetcmp(p, old) != 0){
- uchar nscore[VtScoreSize];
- packetsha1(old, nscore);
- if(scorecmp(u->score, nscore) != 0)
- seterr(EStrange, "readilump returned bad data %V not %V", nscore, u->score);
- else
- seterr(EStrange, "score collision %V", u->score);
- ok = -1;
- }
- packetfree(p);
- packetfree(old);
- ms = msec() - ms;
- addstat2(StatRpcWriteOld, 1, StatRpcWriteOldTime, ms);
- 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 == 0)
- insertlump(u, p);
- else
- packetfree(p);
-
- if(syncwrites){
- flushdcache();
- flushicache();
- flushdcache();
- }
- ms = msec() - ms;
- addstat2(StatRpcWriteNew, 1, StatRpcWriteNewTime, ms);
- return ok;
- }
- static Packet*
- readilump(Lump *u, IAddr *ia, u8int *score)
- {
- Arena *arena;
- ZBlock *zb;
- Packet *p, *pp;
- Clump cl;
- u64int aa;
- u8int sc[VtScoreSize];
- trace(TraceLump, "readilump enter");
- arena = amapitoa(mainindex, ia->addr, &aa);
- if(arena == nil){
- trace(TraceLump, "readilump amapitoa failed");
- return nil;
- }
- trace(TraceLump, "readilump loadclump");
- zb = loadclump(arena, aa, ia->blocks, &cl, sc, paranoid);
- if(zb == nil){
- trace(TraceLump, "readilump loadclump failed");
- 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(scorecmp(score, sc) != 0){
- seterr(ECrash, "score mismatch");
- freezblock(zb);
- return nil;
- }
- trace(TraceLump, "readilump success");
- p = zblock2packet(zb, cl.info.uncsize);
- freezblock(zb);
- pp = packetdup(p, 0, packetsize(p));
- trace(TraceLump, "readilump insertlump");
- insertlump(u, pp);
- trace(TraceLump, "readilump exit");
- return p;
- }
|