api-13-delete.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #include "../private.h" // For NTDB_TOPLEVEL_HASH_BITS
  2. #include <ccan/hash/hash.h>
  3. #include "../ntdb.h"
  4. #include "tap-interface.h"
  5. #include "logging.h"
  6. #include "helpapi-external-agent.h"
  7. /* We rig the hash so adjacent-numbered records always clash. */
  8. static uint32_t clash(const void *key, size_t len, uint32_t seed, void *priv)
  9. {
  10. return *((const unsigned int *)key) / 2;
  11. }
  12. /* We use the same seed which we saw a failure on. */
  13. static uint32_t fixedhash(const void *key, size_t len, uint32_t seed, void *p)
  14. {
  15. return hash64_stable((const unsigned char *)key, len,
  16. *(uint64_t *)p);
  17. }
  18. static bool store_records(struct ntdb_context *ntdb)
  19. {
  20. int i;
  21. NTDB_DATA key = { (unsigned char *)&i, sizeof(i) };
  22. NTDB_DATA d, data = { (unsigned char *)&i, sizeof(i) };
  23. for (i = 0; i < 1000; i++) {
  24. if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != 0)
  25. return false;
  26. ntdb_fetch(ntdb, key, &d);
  27. if (!ntdb_deq(d, data))
  28. return false;
  29. free(d.dptr);
  30. }
  31. return true;
  32. }
  33. static void test_val(struct ntdb_context *ntdb, uint64_t val)
  34. {
  35. uint64_t v;
  36. NTDB_DATA key = { (unsigned char *)&v, sizeof(v) };
  37. NTDB_DATA d, data = { (unsigned char *)&v, sizeof(v) };
  38. /* Insert an entry, then delete it. */
  39. v = val;
  40. /* Delete should fail. */
  41. ok1(ntdb_delete(ntdb, key) == NTDB_ERR_NOEXIST);
  42. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  43. /* Insert should succeed. */
  44. ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
  45. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  46. /* Delete should succeed. */
  47. ok1(ntdb_delete(ntdb, key) == 0);
  48. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  49. /* Re-add it, then add collision. */
  50. ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
  51. v = val + 1;
  52. ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
  53. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  54. /* Can find both? */
  55. ok1(ntdb_fetch(ntdb, key, &d) == NTDB_SUCCESS);
  56. ok1(d.dsize == data.dsize);
  57. free(d.dptr);
  58. v = val;
  59. ok1(ntdb_fetch(ntdb, key, &d) == NTDB_SUCCESS);
  60. ok1(d.dsize == data.dsize);
  61. free(d.dptr);
  62. /* Delete second one. */
  63. v = val + 1;
  64. ok1(ntdb_delete(ntdb, key) == 0);
  65. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  66. /* Re-add */
  67. ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
  68. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  69. /* Now, try deleting first one. */
  70. v = val;
  71. ok1(ntdb_delete(ntdb, key) == 0);
  72. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  73. /* Can still find second? */
  74. v = val + 1;
  75. ok1(ntdb_fetch(ntdb, key, &d) == NTDB_SUCCESS);
  76. ok1(d.dsize == data.dsize);
  77. free(d.dptr);
  78. /* Now, this will be ideally placed. */
  79. v = val + 2;
  80. ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
  81. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  82. /* This will collide with both. */
  83. v = val;
  84. ok1(ntdb_store(ntdb, key, data, NTDB_INSERT) == 0);
  85. /* We can still find them all, right? */
  86. ok1(ntdb_fetch(ntdb, key, &d) == NTDB_SUCCESS);
  87. ok1(d.dsize == data.dsize);
  88. free(d.dptr);
  89. v = val + 1;
  90. ok1(ntdb_fetch(ntdb, key, &d) == NTDB_SUCCESS);
  91. ok1(d.dsize == data.dsize);
  92. free(d.dptr);
  93. v = val + 2;
  94. ok1(ntdb_fetch(ntdb, key, &d) == NTDB_SUCCESS);
  95. ok1(d.dsize == data.dsize);
  96. free(d.dptr);
  97. /* And if we delete val + 1, that val + 2 should not move! */
  98. v = val + 1;
  99. ok1(ntdb_delete(ntdb, key) == 0);
  100. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  101. v = val;
  102. ok1(ntdb_fetch(ntdb, key, &d) == NTDB_SUCCESS);
  103. ok1(d.dsize == data.dsize);
  104. free(d.dptr);
  105. v = val + 2;
  106. ok1(ntdb_fetch(ntdb, key, &d) == NTDB_SUCCESS);
  107. ok1(d.dsize == data.dsize);
  108. free(d.dptr);
  109. /* Delete those two, so we are empty. */
  110. ok1(ntdb_delete(ntdb, key) == 0);
  111. v = val;
  112. ok1(ntdb_delete(ntdb, key) == 0);
  113. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  114. }
  115. int main(int argc, char *argv[])
  116. {
  117. unsigned int i, j;
  118. struct ntdb_context *ntdb;
  119. uint64_t seed = 16014841315512641303ULL;
  120. union ntdb_attribute clash_hattr
  121. = { .hash = { .base = { NTDB_ATTRIBUTE_HASH },
  122. .fn = clash } };
  123. union ntdb_attribute fixed_hattr
  124. = { .hash = { .base = { NTDB_ATTRIBUTE_HASH },
  125. .fn = fixedhash,
  126. .data = &seed } };
  127. int flags[] = { NTDB_INTERNAL, NTDB_DEFAULT, NTDB_NOMMAP,
  128. NTDB_INTERNAL|NTDB_CONVERT, NTDB_CONVERT,
  129. NTDB_NOMMAP|NTDB_CONVERT };
  130. /* These two values gave trouble before. */
  131. int vals[] = { 755, 837 };
  132. clash_hattr.base.next = &tap_log_attr;
  133. fixed_hattr.base.next = &tap_log_attr;
  134. plan_tests(sizeof(flags) / sizeof(flags[0])
  135. * (39 * 3 + 5 + sizeof(vals)/sizeof(vals[0])*2) + 1);
  136. for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
  137. ntdb = ntdb_open("run-13-delete.ntdb", flags[i]|MAYBE_NOSYNC,
  138. O_RDWR|O_CREAT|O_TRUNC, 0600, &clash_hattr);
  139. ok1(ntdb);
  140. if (!ntdb)
  141. continue;
  142. /* Check start of hash table. */
  143. test_val(ntdb, 0);
  144. /* Check end of hash table. */
  145. test_val(ntdb, -1ULL);
  146. /* Check mixed bitpattern. */
  147. test_val(ntdb, 0x123456789ABCDEF0ULL);
  148. ok1(!ntdb->file || (ntdb->file->allrecord_lock.count == 0
  149. && ntdb->file->num_lockrecs == 0));
  150. ntdb_close(ntdb);
  151. /* Deleting these entries in the db gave problems. */
  152. ntdb = ntdb_open("run-13-delete.ntdb", flags[i]|MAYBE_NOSYNC,
  153. O_RDWR|O_CREAT|O_TRUNC, 0600, &fixed_hattr);
  154. ok1(ntdb);
  155. if (!ntdb)
  156. continue;
  157. ok1(store_records(ntdb));
  158. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  159. for (j = 0; j < sizeof(vals)/sizeof(vals[0]); j++) {
  160. NTDB_DATA key;
  161. key.dptr = (unsigned char *)&vals[j];
  162. key.dsize = sizeof(vals[j]);
  163. ok1(ntdb_delete(ntdb, key) == 0);
  164. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  165. }
  166. ntdb_close(ntdb);
  167. }
  168. ok1(tap_log_messages == 0);
  169. return exit_status();
  170. }