1 a0d146ed 2005-07-12 devnull #include "stdinc.h"
2 a0d146ed 2005-07-12 devnull #include "dat.h"
3 a0d146ed 2005-07-12 devnull #include "fns.h"
5 a0d146ed 2005-07-12 devnull int queuewrites = 0;
6 a0d146ed 2005-07-12 devnull int writestodevnull = 0;
8 a0d146ed 2005-07-12 devnull static Packet *readilump(Lump *u, IAddr *ia, u8int *score, int rac);
11 a0d146ed 2005-07-12 devnull readlump(u8int *score, int type, u32int size, int *cached)
14 a0d146ed 2005-07-12 devnull Packet *p;
15 a0d146ed 2005-07-12 devnull IAddr ia;
16 a0d146ed 2005-07-12 devnull u32int n;
19 a0d146ed 2005-07-12 devnull trace(TraceLump, "readlump enter");
21 a0d146ed 2005-07-12 devnull qlock(&stats.lock);
22 a0d146ed 2005-07-12 devnull stats.lumpreads++;
23 a0d146ed 2005-07-12 devnull qunlock(&stats.lock);
25 a0d146ed 2005-07-12 devnull if(scorecmp(score, zeroscore) == 0)
26 a0d146ed 2005-07-12 devnull return packetalloc();
27 a0d146ed 2005-07-12 devnull u = lookuplump(score, type);
28 a0d146ed 2005-07-12 devnull if(u->data != nil){
29 a0d146ed 2005-07-12 devnull trace(TraceLump, "readlump lookuplump hit");
30 a0d146ed 2005-07-12 devnull if(cached)
31 a0d146ed 2005-07-12 devnull *cached = 1;
32 a0d146ed 2005-07-12 devnull n = packetsize(u->data);
33 a0d146ed 2005-07-12 devnull if(n > size){
34 a0d146ed 2005-07-12 devnull seterr(EOk, "read too small: asked for %d need at least %d", size, n);
35 a0d146ed 2005-07-12 devnull putlump(u);
37 a0d146ed 2005-07-12 devnull return nil;
39 a0d146ed 2005-07-12 devnull p = packetdup(u->data, 0, n);
40 a0d146ed 2005-07-12 devnull putlump(u);
41 a0d146ed 2005-07-12 devnull return p;
44 a0d146ed 2005-07-12 devnull if(cached)
45 a0d146ed 2005-07-12 devnull *cached = 0;
47 a0d146ed 2005-07-12 devnull if(lookupscore(score, type, &ia, &rac) < 0){
48 a0d146ed 2005-07-12 devnull //ZZZ place to check for someone trying to guess scores
49 a0d146ed 2005-07-12 devnull seterr(EOk, "no block with score %V/%d exists", score, type);
51 a0d146ed 2005-07-12 devnull putlump(u);
52 a0d146ed 2005-07-12 devnull return nil;
54 a0d146ed 2005-07-12 devnull if(ia.size > size){
55 a0d146ed 2005-07-12 devnull seterr(EOk, "read too small 1: asked for %d need at least %d", size, ia.size);
57 a0d146ed 2005-07-12 devnull putlump(u);
58 a0d146ed 2005-07-12 devnull return nil;
61 a0d146ed 2005-07-12 devnull trace(TraceLump, "readlump readilump");
62 a0d146ed 2005-07-12 devnull p = readilump(u, &ia, score, rac);
63 a0d146ed 2005-07-12 devnull putlump(u);
65 a0d146ed 2005-07-12 devnull trace(TraceLump, "readlump exit");
66 a0d146ed 2005-07-12 devnull return p;
70 a0d146ed 2005-07-12 devnull * save away a lump, and return it's score.
71 a0d146ed 2005-07-12 devnull * doesn't store duplicates, but checks that the data is really the same.
74 a0d146ed 2005-07-12 devnull writelump(Packet *p, u8int *score, int type, u32int creator, uint ms)
80 a0d146ed 2005-07-12 devnull qlock(&stats.lock);
81 a0d146ed 2005-07-12 devnull stats.lumpwrites++;
82 a0d146ed 2005-07-12 devnull qunlock(&stats.lock);
85 a0d146ed 2005-07-12 devnull packetsha1(p, score);
86 a0d146ed 2005-07-12 devnull if(packetsize(p) == 0 || writestodevnull==1){
87 a0d146ed 2005-07-12 devnull packetfree(p);
88 a0d146ed 2005-07-12 devnull return 0;
91 a0d146ed 2005-07-12 devnull u = lookuplump(score, type);
92 a0d146ed 2005-07-12 devnull if(u->data != nil){
94 a0d146ed 2005-07-12 devnull if(packetcmp(p, u->data) != 0){
95 a0d146ed 2005-07-12 devnull seterr(EStrange, "score collision");
98 a0d146ed 2005-07-12 devnull packetfree(p);
99 a0d146ed 2005-07-12 devnull putlump(u);
100 a0d146ed 2005-07-12 devnull return ok;
103 a0d146ed 2005-07-12 devnull if(writestodevnull==2){
104 a0d146ed 2005-07-12 devnull packetfree(p);
105 a0d146ed 2005-07-12 devnull return 0;
108 a0d146ed 2005-07-12 devnull if(queuewrites)
109 a0d146ed 2005-07-12 devnull return queuewrite(u, p, creator, ms);
111 a0d146ed 2005-07-12 devnull ok = writeqlump(u, p, creator, ms);
113 a0d146ed 2005-07-12 devnull putlump(u);
114 a0d146ed 2005-07-12 devnull return ok;
118 a0d146ed 2005-07-12 devnull writeqlump(Lump *u, Packet *p, int creator, uint ms)
120 a0d146ed 2005-07-12 devnull ZBlock *flat;
121 a0d146ed 2005-07-12 devnull Packet *old;
122 a0d146ed 2005-07-12 devnull IAddr ia;
124 a0d146ed 2005-07-12 devnull int rac;
126 a0d146ed 2005-07-12 devnull if(lookupscore(u->score, u->type, &ia, &rac) == 0){
127 a0d146ed 2005-07-12 devnull /* assume the data is here! XXX */
128 a0d146ed 2005-07-12 devnull packetfree(p);
129 a0d146ed 2005-07-12 devnull ms = msec() - ms;
130 a0d146ed 2005-07-12 devnull addstat2(StatRpcWriteOld, 1, StatRpcWriteOldTime, ms);
131 a0d146ed 2005-07-12 devnull return 0;
134 a0d146ed 2005-07-12 devnull * if the read fails,
135 a0d146ed 2005-07-12 devnull * assume it was corrupted data and store the block again
137 a0d146ed 2005-07-12 devnull old = readilump(u, &ia, u->score, rac);
138 a0d146ed 2005-07-12 devnull if(old != nil){
140 a0d146ed 2005-07-12 devnull if(packetcmp(p, old) != 0){
141 a0d146ed 2005-07-12 devnull seterr(EStrange, "score collision");
142 a0d146ed 2005-07-12 devnull ok = -1;
144 a0d146ed 2005-07-12 devnull packetfree(p);
145 a0d146ed 2005-07-12 devnull packetfree(old);
147 a0d146ed 2005-07-12 devnull ms = msec() - ms;
148 a0d146ed 2005-07-12 devnull addstat2(StatRpcWriteOld, 1, StatRpcWriteOldTime, ms);
149 a0d146ed 2005-07-12 devnull return ok;
151 a0d146ed 2005-07-12 devnull logerr(EAdmin, "writelump: read %V failed, rewriting: %r\n", u->score);
154 a0d146ed 2005-07-12 devnull flat = packet2zblock(p, packetsize(p));
155 a0d146ed 2005-07-12 devnull ok = storeclump(mainindex, flat, u->score, u->type, creator, &ia);
156 a0d146ed 2005-07-12 devnull freezblock(flat);
157 a0d146ed 2005-07-12 devnull if(ok == 0)
158 a0d146ed 2005-07-12 devnull ok = insertscore(u->score, &ia, 1);
159 a0d146ed 2005-07-12 devnull if(ok == 0)
160 a0d146ed 2005-07-12 devnull insertlump(u, p);
162 a0d146ed 2005-07-12 devnull packetfree(p);
164 a0d146ed 2005-07-12 devnull ms = msec() - ms;
165 a0d146ed 2005-07-12 devnull addstat2(StatRpcWriteNew, 1, StatRpcWriteNewTime, ms);
166 a0d146ed 2005-07-12 devnull return ok;
169 a0d146ed 2005-07-12 devnull static void
170 a0d146ed 2005-07-12 devnull lreadahead(u64int a, Arena *arena, u64int aa, int n)
172 a0d146ed 2005-07-12 devnull u8int buf[ClumpSize];
173 a0d146ed 2005-07-12 devnull Clump cl;
174 a0d146ed 2005-07-12 devnull IAddr ia;
176 a0d146ed 2005-07-12 devnull while(n > 0) {
177 a0d146ed 2005-07-12 devnull if (aa >= arena->memstats.used)
179 a0d146ed 2005-07-12 devnull if(readarena(arena, aa, buf, ClumpSize) < ClumpSize)
181 a0d146ed 2005-07-12 devnull if(unpackclump(&cl, buf, arena->clumpmagic) < 0)
183 a0d146ed 2005-07-12 devnull ia.addr = a;
184 a0d146ed 2005-07-12 devnull ia.type = cl.info.type;
185 a0d146ed 2005-07-12 devnull ia.size = cl.info.uncsize;
186 a0d146ed 2005-07-12 devnull ia.blocks = (cl.info.size + ClumpSize + (1 << ABlockLog) - 1) >> ABlockLog;
187 a0d146ed 2005-07-12 devnull insertscore(cl.info.score, &ia, 0);
188 a0d146ed 2005-07-12 devnull a += ClumpSize + cl.info.size;
189 a0d146ed 2005-07-12 devnull aa += ClumpSize + cl.info.size;
194 a0d146ed 2005-07-12 devnull static Packet*
195 a0d146ed 2005-07-12 devnull readilump(Lump *u, IAddr *ia, u8int *score, int rac)
197 a0d146ed 2005-07-12 devnull Arena *arena;
198 a0d146ed 2005-07-12 devnull ZBlock *zb;
199 a0d146ed 2005-07-12 devnull Packet *p, *pp;
200 a0d146ed 2005-07-12 devnull Clump cl;
201 a0d146ed 2005-07-12 devnull u64int a, aa;
202 a0d146ed 2005-07-12 devnull u8int sc[VtScoreSize];
204 a0d146ed 2005-07-12 devnull trace(TraceLump, "readilump enter");
205 a0d146ed 2005-07-12 devnull arena = amapitoa(mainindex, ia->addr, &aa);
206 a0d146ed 2005-07-12 devnull if(arena == nil){
207 a0d146ed 2005-07-12 devnull trace(TraceLump, "readilump amapitoa failed");
208 a0d146ed 2005-07-12 devnull return nil;
211 a0d146ed 2005-07-12 devnull trace(TraceLump, "readilump loadclump");
212 a0d146ed 2005-07-12 devnull zb = loadclump(arena, aa, ia->blocks, &cl, sc, paranoid);
213 a0d146ed 2005-07-12 devnull if(zb == nil){
214 a0d146ed 2005-07-12 devnull trace(TraceLump, "readilump loadclump failed");
215 a0d146ed 2005-07-12 devnull return nil;
218 a0d146ed 2005-07-12 devnull if(ia->size != cl.info.uncsize){
219 a0d146ed 2005-07-12 devnull seterr(EInconsist, "index and clump size mismatch");
220 a0d146ed 2005-07-12 devnull freezblock(zb);
221 a0d146ed 2005-07-12 devnull return nil;
223 a0d146ed 2005-07-12 devnull if(ia->type != cl.info.type){
224 a0d146ed 2005-07-12 devnull seterr(EInconsist, "index and clump type mismatch");
225 a0d146ed 2005-07-12 devnull freezblock(zb);
226 a0d146ed 2005-07-12 devnull return nil;
228 a0d146ed 2005-07-12 devnull if(scorecmp(score, sc) != 0){
229 a0d146ed 2005-07-12 devnull seterr(ECrash, "score mismatch");
230 a0d146ed 2005-07-12 devnull freezblock(zb);
231 a0d146ed 2005-07-12 devnull return nil;
234 a0d146ed 2005-07-12 devnull if(rac == 0) {
235 a0d146ed 2005-07-12 devnull trace(TraceLump, "readilump readahead");
236 a0d146ed 2005-07-12 devnull a = ia->addr + ClumpSize + cl.info.size;
237 a0d146ed 2005-07-12 devnull aa += ClumpSize + cl.info.size;
238 a0d146ed 2005-07-12 devnull lreadahead(a, arena, aa, 20);
241 a0d146ed 2005-07-12 devnull trace(TraceLump, "readilump success");
242 a0d146ed 2005-07-12 devnull p = zblock2packet(zb, cl.info.uncsize);
243 a0d146ed 2005-07-12 devnull freezblock(zb);
244 a0d146ed 2005-07-12 devnull pp = packetdup(p, 0, packetsize(p));
245 a0d146ed 2005-07-12 devnull trace(TraceLump, "readilump insertlump");
246 a0d146ed 2005-07-12 devnull insertlump(u, pp);
247 a0d146ed 2005-07-12 devnull trace(TraceLump, "readilump exit");
248 a0d146ed 2005-07-12 devnull return p;