run-13-delete.c 5.4 KB

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