syncarena.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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;
  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. lump = loadClump(arena, aa, 0, &cl, score, 0);
  60. if(lump == nil){
  61. fprint(2, "clump=%d failed to read correctly: %R\n", clump);
  62. err |= SyncDataErr;
  63. }else if(cl.info.type != VtTypeCorrupt){
  64. scoreMem(score, lump->data, cl.info.uncsize);
  65. if(!scoreEq(cl.info.score, score)){
  66. fprint(2, "clump=%d has mismatched score\n", clump);
  67. err = SyncDataErr;
  68. broken = 1;
  69. }else if(!vtTypeValid(cl.info.type)){
  70. fprint(2, "clump=%d has invalid type %d", clump, cl.info.type);
  71. err = SyncDataErr;
  72. broken = 1;
  73. }
  74. if(broken && fix){
  75. cl.info.type = VtTypeCorrupt;
  76. if(!writeClumpHead(arena, aa, &cl)){
  77. fprint(2, "can't write corrected clump header: %R");
  78. err |= SyncFixErr;
  79. }
  80. }
  81. }
  82. freeZBlock(lump);
  83. arena->used += ClumpSize + cl.info.size;
  84. if(!broken && !readClumpInfo(arena, clump, &ci)){
  85. fprint(2, "arena directory read failed\n");
  86. broken = 1;
  87. }else if(!broken && !clumpInfoEq(&ci, &cl.info)){
  88. if(clumpInfoEq(&ci, &zci)){
  89. err |= SyncCIZero;
  90. if(!zok)
  91. fprint(2, "unwritten clump info for clump=%d\n", clump);
  92. }else{
  93. err |= SyncCIErr;
  94. fprint(2, "bad clump info for clump=%d\n", clump);
  95. fprint(2, "\texpected score=%V type=%d size=%d uncsize=%d\n",
  96. cl.info.score, cl.info.type, cl.info.size, cl.info.uncsize);
  97. fprint(2, "\tfound score=%V type=%d size=%d uncsize=%d\n",
  98. ci.score, ci.type, ci.size, ci.uncsize);
  99. }
  100. broken = 1;
  101. }
  102. if(broken && fix){
  103. flush = 1;
  104. ci = cl.info;
  105. if(!writeClumpInfo(arena, clump, &ci)){
  106. fprint(2, "can't write correct clump directory: %R\n");
  107. err |= SyncFixErr;
  108. }
  109. }
  110. arena->uncsize += cl.info.uncsize;
  111. if(cl.info.size < cl.info.uncsize)
  112. arena->cclumps++;
  113. }
  114. if(flush){
  115. arena->wtime = now();
  116. if(arena->ctime == 0 && arena->clumps)
  117. arena->ctime = arena->wtime;
  118. if(!flushCIBlocks(arena)){
  119. fprint(2, "can't flush arena directory cache: %R");
  120. err |= SyncFixErr;
  121. }
  122. }
  123. if(used != arena->used
  124. || clumps != arena->clumps
  125. || cclumps != arena->cclumps
  126. || uncsize != arena->uncsize)
  127. err |= SyncHeader;
  128. return err;
  129. }
  130. static int
  131. writeClumpHead(Arena *arena, u64int aa, Clump *cl)
  132. {
  133. ZBlock *zb;
  134. int ok;
  135. zb = allocZBlock(ClumpSize, 0);
  136. if(zb == nil)
  137. return 0;
  138. ok = packClump(cl, zb->data)
  139. && writeArena(arena, aa, zb->data, ClumpSize) == ClumpSize;
  140. freeZBlock(zb);
  141. return ok;
  142. }
  143. static int
  144. writeClumpMagic(Arena *arena, u64int aa, u32int magic)
  145. {
  146. u8int buf[U32Size];
  147. packMagic(magic, buf);
  148. return writeArena(arena, aa, buf, U32Size) == U32Size;
  149. }