buildbuck.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #include "stdinc.h"
  2. #include "dat.h"
  3. #include "fns.h"
  4. struct IEStream
  5. {
  6. Part *part;
  7. u64int off; /* read position within part */
  8. u64int n; /* number of valid ientries left to read */
  9. u32int size; /* allocated space in buffer */
  10. u8int *buf;
  11. u8int *pos; /* current place in buffer */
  12. u8int *epos; /* end of valid buffer contents */
  13. };
  14. IEStream*
  15. initIEStream(Part *part, u64int off, u64int clumps, u32int size)
  16. {
  17. IEStream *ies;
  18. //ZZZ out of memory?
  19. ies = MKZ(IEStream);
  20. ies->buf = MKN(u8int, size);
  21. ies->epos = ies->buf;
  22. ies->pos = ies->epos;
  23. ies->off = off;
  24. ies->n = clumps;
  25. ies->size = size;
  26. ies->part = part;
  27. return ies;
  28. }
  29. void
  30. freeIEStream(IEStream *ies)
  31. {
  32. if(ies == nil)
  33. return;
  34. free(ies->buf);
  35. free(ies);
  36. }
  37. static u8int*
  38. peekIEntry(IEStream *ies)
  39. {
  40. u32int n, nn;
  41. n = ies->epos - ies->pos;
  42. if(n < IEntrySize){
  43. memmove(ies->buf, ies->pos, n);
  44. ies->epos = &ies->buf[n];
  45. ies->pos = ies->buf;
  46. nn = ies->size;
  47. if(nn > ies->n * IEntrySize)
  48. nn = ies->n * IEntrySize;
  49. nn -= n;
  50. if(nn == 0)
  51. return nil;
  52. if(!readPart(ies->part, ies->off, ies->epos, nn)){
  53. setErr(EOk, "can't read sorted index entries: %R");
  54. return nil;
  55. }
  56. ies->epos += nn;
  57. ies->off += nn;
  58. }
  59. return ies->pos;
  60. }
  61. static u32int
  62. ieBuck(Index *ix, u8int *b)
  63. {
  64. return hashBits(b, 32) / ix->div;
  65. }
  66. u32int
  67. buildBucket(Index *ix, IEStream *ies, IBucket *ib)
  68. {
  69. IEntry ie1, ie2;
  70. u8int *b;
  71. u32int buck;
  72. buck = TWID32;
  73. ib->n = 0;
  74. ib->next = 0;
  75. while(ies->n){
  76. b = peekIEntry(ies);
  77. if(b == nil)
  78. return TWID32;
  79. //fprint(2, "b=%p ies->n=%lld ib.n=%d buck=%d score=%V\n", b, ies->n, ib->n, ieBuck(ix, b), b);
  80. if(ib->n == 0)
  81. buck = ieBuck(ix, b);
  82. else{
  83. if(buck != ieBuck(ix, b))
  84. break;
  85. if(ientryCmp(&ib->data[(ib->n - 1)* IEntrySize], b) == 0){
  86. /*
  87. * guess that the larger address is the correct one to use
  88. */
  89. unpackIEntry(&ie1, &ib->data[(ib->n - 1)* IEntrySize]);
  90. unpackIEntry(&ie2, b);
  91. setErr(EOk, "duplicate index entry for score=%V type=%d\n", ie1.score, ie1.ia.type);
  92. ib->n--;
  93. if(ie1.ia.addr > ie2.ia.addr)
  94. memmove(b, &ib->data[ib->n * IEntrySize], IEntrySize);
  95. }
  96. }
  97. memmove(&ib->data[ib->n * IEntrySize], b, IEntrySize);
  98. ib->n++;
  99. ies->n--;
  100. ies->pos += IEntrySize;
  101. }
  102. return buck;
  103. }