api-firstkey-nextkey.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #include "config.h"
  2. #include "../ntdb.h"
  3. #include "../private.h"
  4. #include "tap-interface.h"
  5. #include "logging.h"
  6. #include "helpapi-external-agent.h"
  7. #define NUM_RECORDS 1000
  8. static bool store_records(struct ntdb_context *ntdb)
  9. {
  10. int i;
  11. NTDB_DATA key = { (unsigned char *)&i, sizeof(i) };
  12. NTDB_DATA data = { (unsigned char *)&i, sizeof(i) };
  13. for (i = 0; i < NUM_RECORDS; i++)
  14. if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != 0)
  15. return false;
  16. return true;
  17. }
  18. struct trav_data {
  19. unsigned int records[NUM_RECORDS];
  20. unsigned int calls;
  21. };
  22. static int trav(struct ntdb_context *ntdb, NTDB_DATA key, NTDB_DATA dbuf, void *p)
  23. {
  24. struct trav_data *td = p;
  25. int val;
  26. memcpy(&val, dbuf.dptr, dbuf.dsize);
  27. td->records[td->calls++] = val;
  28. return 0;
  29. }
  30. /* Since ntdb_nextkey frees dptr, we need to clone it. */
  31. static NTDB_DATA dup_key(NTDB_DATA key)
  32. {
  33. void *p = malloc(key.dsize);
  34. memcpy(p, key.dptr, key.dsize);
  35. key.dptr = p;
  36. return key;
  37. }
  38. int main(int argc, char *argv[])
  39. {
  40. unsigned int i, j;
  41. int num;
  42. struct trav_data td;
  43. NTDB_DATA k;
  44. struct ntdb_context *ntdb;
  45. union ntdb_attribute seed_attr;
  46. enum NTDB_ERROR ecode;
  47. int flags[] = { NTDB_INTERNAL, NTDB_DEFAULT, NTDB_NOMMAP,
  48. NTDB_INTERNAL|NTDB_CONVERT, NTDB_CONVERT,
  49. NTDB_NOMMAP|NTDB_CONVERT };
  50. seed_attr.base.attr = NTDB_ATTRIBUTE_SEED;
  51. seed_attr.base.next = &tap_log_attr;
  52. seed_attr.seed.seed = 6334326220117065685ULL;
  53. plan_tests(sizeof(flags) / sizeof(flags[0])
  54. * (NUM_RECORDS*6 + (NUM_RECORDS-1)*3 + 22) + 1);
  55. for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
  56. ntdb = ntdb_open("api-firstkey-nextkey.ntdb",
  57. flags[i]|MAYBE_NOSYNC,
  58. O_RDWR|O_CREAT|O_TRUNC, 0600,
  59. &seed_attr);
  60. ok1(ntdb);
  61. if (!ntdb)
  62. continue;
  63. ok1(ntdb_firstkey(ntdb, &k) == NTDB_ERR_NOEXIST);
  64. /* One entry... */
  65. k.dptr = (unsigned char *)&num;
  66. k.dsize = sizeof(num);
  67. num = 0;
  68. ok1(ntdb_store(ntdb, k, k, NTDB_INSERT) == 0);
  69. ok1(ntdb_firstkey(ntdb, &k) == NTDB_SUCCESS);
  70. ok1(k.dsize == sizeof(num));
  71. ok1(memcmp(k.dptr, &num, sizeof(num)) == 0);
  72. ok1(ntdb_nextkey(ntdb, &k) == NTDB_ERR_NOEXIST);
  73. /* Two entries. */
  74. k.dptr = (unsigned char *)&num;
  75. k.dsize = sizeof(num);
  76. num = 1;
  77. ok1(ntdb_store(ntdb, k, k, NTDB_INSERT) == 0);
  78. ok1(ntdb_firstkey(ntdb, &k) == NTDB_SUCCESS);
  79. ok1(k.dsize == sizeof(num));
  80. memcpy(&num, k.dptr, sizeof(num));
  81. ok1(num == 0 || num == 1);
  82. ok1(ntdb_nextkey(ntdb, &k) == NTDB_SUCCESS);
  83. ok1(k.dsize == sizeof(j));
  84. memcpy(&j, k.dptr, sizeof(j));
  85. ok1(j == 0 || j == 1);
  86. ok1(j != num);
  87. ok1(ntdb_nextkey(ntdb, &k) == NTDB_ERR_NOEXIST);
  88. /* Clean up. */
  89. k.dptr = (unsigned char *)&num;
  90. k.dsize = sizeof(num);
  91. num = 0;
  92. ok1(ntdb_delete(ntdb, k) == 0);
  93. num = 1;
  94. ok1(ntdb_delete(ntdb, k) == 0);
  95. /* Now lots of records. */
  96. ok1(store_records(ntdb));
  97. td.calls = 0;
  98. num = ntdb_traverse(ntdb, trav, &td);
  99. ok1(num == NUM_RECORDS);
  100. ok1(td.calls == NUM_RECORDS);
  101. /* Simple loop should match ntdb_traverse */
  102. for (j = 0, ecode = ntdb_firstkey(ntdb, &k); j < td.calls; j++) {
  103. int val;
  104. ok1(ecode == NTDB_SUCCESS);
  105. ok1(k.dsize == sizeof(val));
  106. memcpy(&val, k.dptr, k.dsize);
  107. ok1(td.records[j] == val);
  108. ecode = ntdb_nextkey(ntdb, &k);
  109. }
  110. /* But arbitrary orderings should work too. */
  111. for (j = td.calls-1; j > 0; j--) {
  112. k.dptr = (unsigned char *)&td.records[j-1];
  113. k.dsize = sizeof(td.records[j-1]);
  114. k = dup_key(k);
  115. ok1(ntdb_nextkey(ntdb, &k) == NTDB_SUCCESS);
  116. ok1(k.dsize == sizeof(td.records[j]));
  117. ok1(memcmp(k.dptr, &td.records[j], k.dsize) == 0);
  118. free(k.dptr);
  119. }
  120. /* Even delete should work. */
  121. for (j = 0, ecode = ntdb_firstkey(ntdb, &k);
  122. ecode != NTDB_ERR_NOEXIST;
  123. j++) {
  124. ok1(ecode == NTDB_SUCCESS);
  125. ok1(k.dsize == 4);
  126. ok1(ntdb_delete(ntdb, k) == 0);
  127. ecode = ntdb_nextkey(ntdb, &k);
  128. }
  129. diag("delete using first/nextkey gave %u of %u records",
  130. j, NUM_RECORDS);
  131. ok1(j == NUM_RECORDS);
  132. ntdb_close(ntdb);
  133. }
  134. ok1(tap_log_messages == 0);
  135. return exit_status();
  136. }