Blob


1 #include "stdinc.h"
2 #include "dat.h"
3 #include "fns.h"
5 enum
6 {
7 ClumpChunks = 32*1024
8 };
10 static int missing, wrong;
12 /*
13 * shell sort is plenty good enough
14 * because we're going to do a bunch of disk i/o's
15 */
16 static void
17 sortclumpinfo(ClumpInfo *ci, int *s, int n)
18 {
19 int i, j, m, t;
21 for(m = (n + 3) / 5; m > 0; m = (m + 1) / 3){
22 for(i = n - m; i-- > 0;){
23 for(j = i + m; j < n; j += m){
24 if(memcmp(ci[s[j - m]].score, ci[s[j]].score, VtScoreSize) <= 0)
25 break;
26 t = s[j];
27 s[j] = s[j - m];
28 s[j - m] = t;
29 }
30 }
31 }
32 }
34 int
35 syncarenaindex(Index *ix, Arena *arena, u32int clump, u64int a, int fix, int *pflush, int check)
36 {
37 Packet *pack;
38 IEntry ie;
39 IAddr ia;
40 ClumpInfo *ci, *cis;
41 u64int *addrs;
42 int i, n, ok, *s, flush;
44 trace(TraceProc, "syncarenaindex enter");
46 flush = 0;
47 cis = MKN(ClumpInfo, ClumpChunks);
48 addrs = MKN(u64int, ClumpChunks);
49 s = MKN(int, ClumpChunks);
50 ok = 0;
51 for(; clump < arena->memstats.clumps; clump += n){
52 n = ClumpChunks;
53 if(n > arena->memstats.clumps - clump)
54 n = arena->memstats.clumps - clump;
55 n = readclumpinfos(arena, clump, cis, n);
56 if(n <= 0){
57 fprint(2, "arena directory read failed\n");
58 ok = -1;
59 break;
60 }
62 for(i = 0; i < n; i++){
63 addrs[i] = a;
64 a += cis[i].size + ClumpSize;
65 s[i] = i;
66 }
68 sortclumpinfo(cis, s, n);
70 for(i = 0; i < n; i++){
71 ci = &cis[s[i]];
72 ia.type = ci->type;
73 ia.size = ci->uncsize;
74 ia.addr = addrs[s[i]];
75 ia.blocks = (ci->size + ClumpSize + (1 << ABlockLog) - 1) >> ABlockLog;
77 if(!check)
78 goto Add;
79 if(loadientry(ix, ci->score, ci->type, &ie) < 0){
80 trace(TraceProc, "syncarenaindex missing block %V.%d", ci->score, ci->type);
81 missing++;
82 if(0) fprint(2, "missing block type=%d score=%V\n", ci->type, ci->score);
83 }else if(iaddrcmp(&ia, &ie.ia) != 0){
84 trace(TraceProc, "syncarenaindex mismatched entry");
85 fprint(2, "\nmismatched index entry and clump at %d\n", clump + i);
86 fprint(2, "\tclump: type=%d size=%d blocks=%d addr=%lld\n", ia.type, ia.size, ia.blocks, ia.addr);
87 fprint(2, "\tindex: type=%d size=%d block=%d addr=%lld\n", ie.ia.type, ie.ia.size, ie.ia.blocks, ie.ia.addr);
88 pack = readlump(ie.score, ie.ia.type, ie.ia.size, nil);
89 packetfree(pack);
90 if(pack != nil){
91 fprint(2, "duplicated lump\n");
92 continue;
93 }
94 wrong++;
95 }else
96 continue;
97 Add:
98 if(!fix){
99 ok = -1;
100 continue;
102 flush = 1;
103 trace(TraceProc, "syncarenaindex insert %V", ci->score);
104 insertscore(ci->score, &ia, 1);
107 if(0 && clump / 1000 != (clump + n) / 1000)
108 fprint(2, ".");
110 free(cis);
111 free(addrs);
112 free(s);
113 if(flush){
114 flushdcache();
115 *pflush = 1;
117 return ok;
120 int
121 syncindex(Index *ix, int fix, int mustflush, int check)
123 Arena *arena;
124 u64int a;
125 u32int clump;
126 int i, e, e1, ok, ok1, flush;
128 ok = 0;
129 flush = 0;
130 for(i = 0; i < ix->narenas; i++){
131 trace(TraceProc, "syncindex start %d", i);
132 arena = ix->arenas[i];
133 clump = arena->memstats.clumps;
134 a = arena->memstats.used;
135 e = syncarena(arena, ix->amap[i].start, TWID32, fix, fix);
136 e1 = e;
137 if(fix)
138 e1 &= ~(SyncHeader|SyncCIZero|SyncCIErr);
139 if(e1 == SyncHeader)
140 fprint(2, "arena %s: header is out-of-date\n", arena->name);
141 if(e1)
142 ok = -1;
143 else{
144 ok1 = syncarenaindex(ix, arena, clump, a + ix->amap[i].start, fix, &flush, check);
145 if(ok1 < 0)
146 fprint(2, "syncarenaindex: %r\n");
147 if(fix && ok1==0 && (e & SyncHeader) && wbarena(arena) < 0)
148 fprint(2, "arena=%s header write failed: %r\n", arena->name);
149 ok |= ok1;
152 if(missing || wrong)
153 fprint(2, "syncindex: %d missing entries, %d wrong entries (flush=%d)\n", missing, wrong, flush);
154 if(fix && wbindex(ix) < 0){
155 fprint(2, "can't write back index header for %s: %r\n", ix->name);
156 return -1;
158 if(fix && flush){
159 flushdcache();
160 if(mustflush){
161 flushicache();
162 flushdcache();
163 }else
164 kickicache();
166 return ok;