api-13-delete.c 5.5 KB

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