lump.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #include "stdinc.h"
  2. #include "dat.h"
  3. #include "fns.h"
  4. int queueWrites = 0;
  5. static Packet *readILump(Lump *u, IAddr *ia, u8int *score, int rac);
  6. Packet*
  7. readLump(u8int *score, int type, u32int size)
  8. {
  9. Lump *u;
  10. Packet *p;
  11. IAddr ia;
  12. u32int n;
  13. int rac;
  14. vtLock(stats.lock);
  15. stats.lumpReads++;
  16. vtUnlock(stats.lock);
  17. u = lookupLump(score, type);
  18. if(u->data != nil){
  19. n = packetSize(u->data);
  20. if(n > size){
  21. setErr(EOk, "read too small: asked for %d need at least %d", size, n);
  22. putLump(u);
  23. return nil;
  24. }
  25. p = packetDup(u->data, 0, n);
  26. putLump(u);
  27. return p;
  28. }
  29. if(!lookupScore(score, type, &ia, &rac)){
  30. //ZZZ place to check for someone trying to guess scores
  31. setErr(EOk, "no block with that score exists");
  32. putLump(u);
  33. return nil;
  34. }
  35. if(ia.size > size){
  36. setErr(EOk, "read too small 1: asked for %d need at least %d", size, ia.size);
  37. putLump(u);
  38. return nil;
  39. }
  40. p = readILump(u, &ia, score, rac);
  41. putLump(u);
  42. return p;
  43. }
  44. /*
  45. * save away a lump, and return it's score.
  46. * doesn't store duplicates, but checks that the data is really the same.
  47. */
  48. int
  49. writeLump(Packet *p, u8int *score, int type, u32int creator)
  50. {
  51. Lump *u;
  52. int ok;
  53. vtLock(stats.lock);
  54. stats.lumpWrites++;
  55. vtUnlock(stats.lock);
  56. packetSha1(p, score);
  57. u = lookupLump(score, type);
  58. if(u->data != nil){
  59. ok = 1;
  60. if(packetCmp(p, u->data) != 0){
  61. setErr(EStrange, "score collision");
  62. ok = 0;
  63. }
  64. packetFree(p);
  65. putLump(u);
  66. return ok;
  67. }
  68. if(queueWrites)
  69. return queueWrite(u, p, creator);
  70. ok = writeQLump(u, p, creator);
  71. putLump(u);
  72. return ok;
  73. }
  74. int
  75. writeQLump(Lump *u, Packet *p, int creator)
  76. {
  77. ZBlock *flat;
  78. Packet *old;
  79. IAddr ia;
  80. int ok;
  81. int rac;
  82. if(lookupScore(u->score, u->type, &ia, &rac)){
  83. /*
  84. * if the read fails,
  85. * assume it was corrupted data and store the block again
  86. */
  87. old = readILump(u, &ia, u->score, rac);
  88. if(old != nil){
  89. ok = 1;
  90. if(packetCmp(p, old) != 0){
  91. setErr(EStrange, "score collision");
  92. ok = 0;
  93. }
  94. packetFree(p);
  95. packetFree(old);
  96. return ok;
  97. }
  98. logErr(EAdmin, "writelump: read %V failed, rewriting: %R\n", u->score);
  99. }
  100. flat = packet2ZBlock(p, packetSize(p));
  101. ok = storeClump(mainIndex, flat, u->score, u->type, creator, &ia);
  102. freeZBlock(flat);
  103. if(ok)
  104. ok = insertScore(u->score, &ia, 1);
  105. if(ok)
  106. insertLump(u, p);
  107. else
  108. packetFree(p);
  109. return ok;
  110. }
  111. static void
  112. readAhead(u64int a, Arena *arena, u64int aa, int n)
  113. {
  114. u8int buf[ClumpSize];
  115. Clump cl;
  116. IAddr ia;
  117. while(n > 0) {
  118. if (aa >= arena->used)
  119. break;
  120. if(readArena(arena, aa, buf, ClumpSize) < ClumpSize)
  121. break;
  122. if(!unpackClump(&cl, buf))
  123. break;
  124. ia.addr = a;
  125. ia.type = cl.info.type;
  126. ia.size = cl.info.uncsize;
  127. ia.blocks = (cl.info.size + ClumpSize + (1 << ABlockLog) - 1) >> ABlockLog;
  128. insertScore(cl.info.score, &ia, 0);
  129. a += ClumpSize + cl.info.size;
  130. aa += ClumpSize + cl.info.size;
  131. n--;
  132. }
  133. }
  134. static Packet*
  135. readILump(Lump *u, IAddr *ia, u8int *score, int rac)
  136. {
  137. Arena *arena;
  138. ZBlock *zb;
  139. Packet *p, *pp;
  140. Clump cl;
  141. u64int a, aa;
  142. u8int sc[VtScoreSize];
  143. arena = amapItoA(mainIndex, ia->addr, &aa);
  144. if(arena == nil)
  145. return nil;
  146. zb = loadClump(arena, aa, ia->blocks, &cl, sc, paranoid);
  147. if(zb == nil)
  148. return nil;
  149. if(ia->size != cl.info.uncsize){
  150. setErr(EInconsist, "index and clump size mismatch");
  151. freeZBlock(zb);
  152. return nil;
  153. }
  154. if(ia->type != cl.info.type){
  155. setErr(EInconsist, "index and clump type mismatch");
  156. freeZBlock(zb);
  157. return nil;
  158. }
  159. if(!scoreEq(score, sc)){
  160. setErr(ECrash, "score mismatch");
  161. freeZBlock(zb);
  162. return nil;
  163. }
  164. if(rac == 0) {
  165. a = ia->addr + ClumpSize + cl.info.size;
  166. aa += ClumpSize + cl.info.size;
  167. readAhead(a, arena, aa, 20);
  168. }
  169. p = zblock2Packet(zb, cl.info.uncsize);
  170. freeZBlock(zb);
  171. pp = packetDup(p, 0, packetSize(p));
  172. insertLump(u, pp);
  173. return p;
  174. }