Blob


1 #include "stdinc.h"
2 #include "dat.h"
3 #include "fns.h"
5 int bootstrap = 0;
6 int syncwrites = 0;
7 int queuewrites = 0;
8 int writestodevnull = 0;
9 int verifywrites = 0;
11 static Packet *readilump(Lump *u, IAddr *ia, u8int *score);
13 /*
14 * Some of this logic is duplicated in hdisk.c
15 */
16 Packet*
17 readlump(u8int *score, int type, u32int size, int *cached)
18 {
19 Lump *u;
20 Packet *p;
21 IAddr ia;
22 u32int n;
24 trace(TraceLump, "readlump enter");
25 /*
26 qlock(&stats.lock);
27 stats.lumpreads++;
28 qunlock(&stats.lock);
29 */
30 if(scorecmp(score, zeroscore) == 0)
31 return packetalloc();
32 u = lookuplump(score, type);
33 if(u->data != nil){
34 trace(TraceLump, "readlump lookuplump hit");
35 if(cached)
36 *cached = 1;
37 n = packetsize(u->data);
38 if(n > size){
39 seterr(EOk, "read too small: asked for %d need at least %d", size, n);
40 putlump(u);
42 return nil;
43 }
44 p = packetdup(u->data, 0, n);
45 putlump(u);
46 return p;
47 }
49 if(cached)
50 *cached = 0;
52 if(lookupscore(score, type, &ia) < 0){
53 /* ZZZ place to check for someone trying to guess scores */
54 seterr(EOk, "no block with score %V/%d exists", score, type);
56 putlump(u);
57 return nil;
58 }
59 if(ia.size > size){
60 seterr(EOk, "read too small 1: asked for %d need at least %d", size, ia.size);
62 putlump(u);
63 return nil;
64 }
66 trace(TraceLump, "readlump readilump");
67 p = readilump(u, &ia, score);
68 putlump(u);
70 trace(TraceLump, "readlump exit");
71 return p;
72 }
74 /*
75 * save away a lump, and return it's score.
76 * doesn't store duplicates, but checks that the data is really the same.
77 */
78 int
79 writelump(Packet *p, u8int *score, int type, u32int creator, uint ms)
80 {
81 Lump *u;
82 int ok;
84 /*
85 qlock(&stats.lock);
86 stats.lumpwrites++;
87 qunlock(&stats.lock);
88 */
90 packetsha1(p, score);
91 if(packetsize(p) == 0 || writestodevnull==1){
92 packetfree(p);
93 return 0;
94 }
96 u = lookuplump(score, type);
97 if(u->data != nil){
98 ok = 0;
99 if(packetcmp(p, u->data) != 0){
100 uchar nscore[VtScoreSize];
102 packetsha1(u->data, nscore);
103 if(scorecmp(u->score, score) != 0)
104 seterr(EStrange, "lookuplump returned bad score %V not %V", u->score, score);
105 else if(scorecmp(u->score, nscore) != 0)
106 seterr(EStrange, "lookuplump returned bad data %V not %V", nscore, u->score);
107 else
108 seterr(EStrange, "score collision %V", score);
109 ok = -1;
111 packetfree(p);
112 putlump(u);
113 return ok;
116 if(writestodevnull==2){
117 packetfree(p);
118 return 0;
121 if(queuewrites)
122 return queuewrite(u, p, creator, ms);
124 ok = writeqlump(u, p, creator, ms);
126 putlump(u);
127 return ok;
130 int
131 writeqlump(Lump *u, Packet *p, int creator, uint ms)
133 ZBlock *flat;
134 Packet *old;
135 IAddr ia;
136 int ok;
138 if(lookupscore(u->score, u->type, &ia) == 0){
139 if(verifywrites == 0){
140 /* assume the data is here! */
141 packetfree(p);
142 ms = msec() - ms;
143 addstat2(StatRpcWriteOld, 1, StatRpcWriteOldTime, ms);
144 return 0;
147 /*
148 * if the read fails,
149 * assume it was corrupted data and store the block again
150 */
151 old = readilump(u, &ia, u->score);
152 if(old != nil){
153 ok = 0;
154 if(packetcmp(p, old) != 0){
155 uchar nscore[VtScoreSize];
157 packetsha1(old, nscore);
158 if(scorecmp(u->score, nscore) != 0)
159 seterr(EStrange, "readilump returned bad data %V not %V", nscore, u->score);
160 else
161 seterr(EStrange, "score collision %V", u->score);
162 ok = -1;
164 packetfree(p);
165 packetfree(old);
167 ms = msec() - ms;
168 addstat2(StatRpcWriteOld, 1, StatRpcWriteOldTime, ms);
169 return ok;
171 logerr(EAdmin, "writelump: read %V failed, rewriting: %r\n", u->score);
174 flat = packet2zblock(p, packetsize(p));
175 ok = storeclump(mainindex, flat, u->score, u->type, creator, &ia);
176 freezblock(flat);
177 if(ok == 0)
178 insertlump(u, p);
179 else
180 packetfree(p);
182 if(syncwrites){
183 flushdcache();
184 flushicache();
185 flushdcache();
188 ms = msec() - ms;
189 addstat2(StatRpcWriteNew, 1, StatRpcWriteNewTime, ms);
190 return ok;
193 static Packet*
194 readilump(Lump *u, IAddr *ia, u8int *score)
196 Arena *arena;
197 ZBlock *zb;
198 Packet *p, *pp;
199 Clump cl;
200 u64int aa;
201 u8int sc[VtScoreSize];
203 trace(TraceLump, "readilump enter");
204 arena = amapitoa(mainindex, ia->addr, &aa);
205 if(arena == nil){
206 trace(TraceLump, "readilump amapitoa failed");
207 return nil;
210 trace(TraceLump, "readilump loadclump");
211 zb = loadclump(arena, aa, ia->blocks, &cl, sc, paranoid);
212 if(zb == nil){
213 trace(TraceLump, "readilump loadclump failed");
214 return nil;
217 if(ia->size != cl.info.uncsize){
218 seterr(EInconsist, "index and clump size mismatch");
219 freezblock(zb);
220 return nil;
222 if(ia->type != cl.info.type){
223 seterr(EInconsist, "index and clump type mismatch");
224 freezblock(zb);
225 return nil;
227 if(scorecmp(score, sc) != 0){
228 seterr(ECrash, "score mismatch");
229 freezblock(zb);
230 return nil;
233 trace(TraceLump, "readilump success");
234 p = zblock2packet(zb, cl.info.uncsize);
235 freezblock(zb);
236 pp = packetdup(p, 0, packetsize(p));
237 trace(TraceLump, "readilump insertlump");
238 insertlump(u, pp);
239 trace(TraceLump, "readilump exit");
240 return p;