syncarena.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include "stdinc.h"
  2. #include "dat.h"
  3. #include "fns.h"
  4. static int writeClumpHead(Arena *arena, u64int aa, Clump *cl);
  5. static int writeClumpMagic(Arena *arena, u64int aa, u32int magic);
  6. int
  7. clumpInfoEq(ClumpInfo *c, ClumpInfo *d)
  8. {
  9. return c->type == d->type
  10. && c->size == d->size
  11. && c->uncsize == d->uncsize
  12. && scoreEq(c->score, d->score);
  13. }
  14. /*
  15. * synchronize the clump info directory with
  16. * with the clumps actually stored in the arena.
  17. * the directory should be at least as up to date
  18. * as the arena's trailer.
  19. *
  20. * checks/updates at most n clumps.
  21. *
  22. * returns 1 if ok, -1 if an error occured, 0 if blocks were updated
  23. */
  24. int
  25. syncArena(Arena *arena, u32int n, int zok, int fix)
  26. {
  27. ZBlock *lump;
  28. Clump cl;
  29. ClumpInfo ci;
  30. static ClumpInfo zci;
  31. u8int score[VtScoreSize];
  32. u64int uncsize, used, aa;
  33. u32int clump, clumps, cclumps, magic;
  34. int err, flush, broken, cierr;
  35. used = arena->used;
  36. clumps = arena->clumps;
  37. cclumps = arena->cclumps;
  38. uncsize = arena->uncsize;
  39. flush = 0;
  40. err = 0;
  41. for(; n; n--){
  42. aa = arena->used;
  43. clump = arena->clumps;
  44. magic = clumpMagic(arena, aa);
  45. if(magic == ClumpFreeMagic)
  46. break;
  47. if(magic != ClumpMagic){
  48. fprint(2, "illegal clump magic number=%#8.8ux at clump=%d\n", magic, clump);
  49. err |= SyncDataErr;
  50. //ZZZ write a zero here?
  51. if(0 && fix && !writeClumpMagic(arena, aa, ClumpFreeMagic)){
  52. fprint(2, "can't write corrected clump free magic: %R");
  53. err |= SyncFixErr;
  54. }
  55. break;
  56. }
  57. arena->clumps++;
  58. broken = 0;
  59. cierr = 0;
  60. lump = loadClump(arena, aa, 0, &cl, score, 0);
  61. if(lump == nil){
  62. fprint(2, "clump=%d failed to read correctly: %R\n", clump);
  63. err |= SyncDataErr;
  64. }else if(cl.info.type != VtTypeCorrupt){
  65. scoreMem(score, lump->data, cl.info.uncsize);
  66. if(!scoreEq(cl.info.score, score)){
  67. fprint(2, "clump=%d has mismatched score\n", clump);
  68. err = SyncDataErr;
  69. broken = 1;
  70. }else if(!vtTypeValid(cl.info.type)){
  71. fprint(2, "clump=%d has invalid type %d", clump, cl.info.type);
  72. err = SyncDataErr;
  73. broken = 1;
  74. }
  75. if(broken && fix){
  76. cl.info.type = VtTypeCorrupt;
  77. if(!writeClumpHead(arena, aa, &cl)){
  78. fprint(2, "can't write corrected clump header: %R");
  79. err |= SyncFixErr;
  80. }
  81. }
  82. }
  83. freeZBlock(lump);
  84. arena->used += ClumpSize + cl.info.size;
  85. if(!broken && !readClumpInfo(arena, clump, &ci)){
  86. fprint(2, "arena directory read failed\n");
  87. broken = 1;
  88. }else if(!broken && !clumpInfoEq(&ci, &cl.info)){
  89. if(clumpInfoEq(&ci, &zci)){
  90. cierr |= SyncCIZero;
  91. if(!zok){
  92. fprint(2, "unwritten clump info for clump=%d ", clump);
  93. fprint(2, "score=%V type=%d\n",
  94. cl.info.score, cl.info.type);
  95. }
  96. }else{
  97. cierr |= SyncCIErr;
  98. fprint(2, "bad clump info for clump=%d\n", clump);
  99. fprint(2, "\texpected score=%V type=%d size=%d uncsize=%d\n",
  100. cl.info.score, cl.info.type, cl.info.size, cl.info.uncsize);
  101. fprint(2, "\tfound score=%V type=%d size=%d uncsize=%d\n",
  102. ci.score, ci.type, ci.size, ci.uncsize);
  103. }
  104. broken = 1;
  105. }
  106. if(broken && fix){
  107. flush = 1;
  108. ci = cl.info;
  109. if(!writeClumpInfo(arena, clump, &ci)){
  110. fprint(2, "can't write correct clump directory: %R\n");
  111. err |= SyncFixErr;
  112. }else
  113. cierr &= ~(SyncCIZero|SyncCIErr);
  114. }
  115. err |= cierr;
  116. arena->uncsize += cl.info.uncsize;
  117. if(cl.info.size < cl.info.uncsize)
  118. arena->cclumps++;
  119. }
  120. if(flush){
  121. arena->wtime = now();
  122. if(arena->ctime == 0 && arena->clumps)
  123. arena->ctime = arena->wtime;
  124. if(!flushCIBlocks(arena)){
  125. fprint(2, "can't flush arena directory cache: %R");
  126. err |= SyncFixErr;
  127. }
  128. }
  129. if(used != arena->used
  130. || clumps != arena->clumps
  131. || cclumps != arena->cclumps
  132. || uncsize != arena->uncsize)
  133. err |= SyncHeader;
  134. return err;
  135. }
  136. static int
  137. writeClumpHead(Arena *arena, u64int aa, Clump *cl)
  138. {
  139. ZBlock *zb;
  140. int ok;
  141. zb = allocZBlock(ClumpSize, 0);
  142. if(zb == nil)
  143. return 0;
  144. ok = packClump(cl, zb->data)
  145. && writeArena(arena, aa, zb->data, ClumpSize) == ClumpSize;
  146. freeZBlock(zb);
  147. return ok;
  148. }
  149. static int
  150. writeClumpMagic(Arena *arena, u64int aa, u32int magic)
  151. {
  152. u8int buf[U32Size];
  153. packMagic(magic, buf);
  154. return writeArena(arena, aa, buf, U32Size) == U32Size;
  155. }