Blob


1 #include "stdinc.h"
2 #include "dat.h"
3 #include "fns.h"
5 int queuewrites = 0;
7 static Packet *readilump(Lump *u, IAddr *ia, u8int *score, int rac);
9 Packet*
10 readlump(u8int *score, int type, u32int size)
11 {
12 Lump *u;
13 Packet *p;
14 IAddr ia;
15 u32int n;
16 int rac;
18 qlock(&stats.lock);
19 stats.lumpreads++;
20 qunlock(&stats.lock);
21 u = lookuplump(score, type);
22 if(u->data != nil){
23 n = packetsize(u->data);
24 if(n > size){
25 seterr(EOk, "read too small: asked for %d need at least %d", size, n);
26 putlump(u);
28 return nil;
29 }
30 p = packetdup(u->data, 0, n);
31 putlump(u);
33 return p;
34 }
36 if(lookupscore(score, type, &ia, &rac) < 0){
37 //ZZZ place to check for someone trying to guess scores
38 seterr(EOk, "no block with that score exists");
40 putlump(u);
41 return nil;
42 }
43 if(ia.size > size){
44 seterr(EOk, "read too small 1: asked for %d need at least %d", size, ia.size);
46 putlump(u);
47 return nil;
48 }
50 p = readilump(u, &ia, score, rac);
51 putlump(u);
53 return p;
54 }
56 /*
57 * save away a lump, and return it's score.
58 * doesn't store duplicates, but checks that the data is really the same.
59 */
60 int
61 writelump(Packet *p, u8int *score, int type, u32int creator)
62 {
63 Lump *u;
64 int ok;
66 qlock(&stats.lock);
67 stats.lumpwrites++;
68 qunlock(&stats.lock);
70 packetsha1(p, score);
72 u = lookuplump(score, type);
73 if(u->data != nil){
74 ok = 0;
75 if(packetcmp(p, u->data) != 0){
76 seterr(EStrange, "score collision");
77 ok = -1;
78 }
79 packetfree(p);
80 putlump(u);
81 return ok;
82 }
84 if(queuewrites)
85 return queuewrite(u, p, creator);
87 ok = writeqlump(u, p, creator);
89 putlump(u);
90 return ok;
91 }
93 int
94 writeqlump(Lump *u, Packet *p, int creator)
95 {
96 ZBlock *flat;
97 Packet *old;
98 IAddr ia;
99 int ok;
100 int rac;
102 if(lookupscore(u->score, u->type, &ia, &rac) == 0){
103 /*
104 * if the read fails,
105 * assume it was corrupted data and store the block again
106 */
107 old = readilump(u, &ia, u->score, rac);
108 if(old != nil){
109 ok = 0;
110 if(packetcmp(p, old) != 0){
111 seterr(EStrange, "score collision");
112 ok = -1;
114 packetfree(p);
115 packetfree(old);
117 return ok;
119 logerr(EAdmin, "writelump: read %V failed, rewriting: %r\n", u->score);
122 flat = packet2zblock(p, packetsize(p));
123 ok = storeclump(mainindex, flat, u->score, u->type, creator, &ia);
124 freezblock(flat);
125 if(ok == 0)
126 ok = insertscore(u->score, &ia, 1);
127 if(ok == 0)
128 insertlump(u, p);
129 else
130 packetfree(p);
132 return ok;
135 static void
136 readahead(u64int a, Arena *arena, u64int aa, int n)
138 u8int buf[ClumpSize];
139 Clump cl;
140 IAddr ia;
142 while(n > 0) {
143 if (aa >= arena->used)
144 break;
145 if(readarena(arena, aa, buf, ClumpSize) < ClumpSize)
146 break;
147 if(unpackclump(&cl, buf) < 0)
148 break;
149 ia.addr = a;
150 ia.type = cl.info.type;
151 ia.size = cl.info.uncsize;
152 ia.blocks = (cl.info.size + ClumpSize + (1 << ABlockLog) - 1) >> ABlockLog;
153 insertscore(cl.info.score, &ia, 0);
154 a += ClumpSize + cl.info.size;
155 aa += ClumpSize + cl.info.size;
156 n--;
160 static Packet*
161 readilump(Lump *u, IAddr *ia, u8int *score, int rac)
163 Arena *arena;
164 ZBlock *zb;
165 Packet *p, *pp;
166 Clump cl;
167 u64int a, aa;
168 u8int sc[VtScoreSize];
170 arena = amapitoa(mainindex, ia->addr, &aa);
171 if(arena == nil)
172 return nil;
174 zb = loadclump(arena, aa, ia->blocks, &cl, sc, paranoid);
175 if(zb == nil)
176 return nil;
178 if(ia->size != cl.info.uncsize){
179 seterr(EInconsist, "index and clump size mismatch");
180 freezblock(zb);
181 return nil;
183 if(ia->type != cl.info.type){
184 seterr(EInconsist, "index and clump type mismatch");
185 freezblock(zb);
186 return nil;
188 if(scorecmp(score, sc) != 0){
189 seterr(ECrash, "score mismatch");
190 freezblock(zb);
191 return nil;
194 if(rac == 0) {
195 a = ia->addr + ClumpSize + cl.info.size;
196 aa += ClumpSize + cl.info.size;
197 readahead(a, arena, aa, 20);
200 p = zblock2packet(zb, cl.info.uncsize);
201 freezblock(zb);
202 pp = packetdup(p, 0, packetsize(p));
203 insertlump(u, pp);
204 return p;