run-03-coalesce.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include "ntdb-source.h"
  2. #include "tap-interface.h"
  3. #include "logging.h"
  4. #include "layout.h"
  5. #include "helprun-external-agent.h"
  6. static ntdb_len_t free_record_length(struct ntdb_context *ntdb, ntdb_off_t off)
  7. {
  8. struct ntdb_free_record f;
  9. enum NTDB_ERROR ecode;
  10. ecode = ntdb_read_convert(ntdb, off, &f, sizeof(f));
  11. if (ecode != NTDB_SUCCESS)
  12. return ecode;
  13. if (frec_magic(&f) != NTDB_FREE_MAGIC)
  14. return NTDB_ERR_CORRUPT;
  15. return frec_len(&f);
  16. }
  17. int main(int argc, char *argv[])
  18. {
  19. ntdb_off_t b_off, test;
  20. struct ntdb_context *ntdb;
  21. struct ntdb_layout *layout;
  22. NTDB_DATA data, key;
  23. ntdb_len_t len;
  24. /* FIXME: Test NTDB_CONVERT */
  25. /* FIXME: Test lock order fail. */
  26. plan_tests(42);
  27. data = ntdb_mkdata("world", 5);
  28. key = ntdb_mkdata("hello", 5);
  29. /* No coalescing can be done due to EOF */
  30. layout = new_ntdb_layout();
  31. ntdb_layout_add_freetable(layout);
  32. len = 15560;
  33. ntdb_layout_add_free(layout, len, 0);
  34. ntdb_layout_write(layout, free, &tap_log_attr, "run-03-coalesce.ntdb");
  35. /* NOMMAP is for lockcheck. */
  36. ntdb = ntdb_open("run-03-coalesce.ntdb", NTDB_NOMMAP|MAYBE_NOSYNC,
  37. O_RDWR, 0, &tap_log_attr);
  38. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  39. ok1(free_record_length(ntdb, layout->elem[1].base.off) == len);
  40. /* Figure out which bucket free entry is. */
  41. b_off = bucket_off(ntdb->ftable_off, size_to_bucket(len));
  42. /* Lock and fail to coalesce. */
  43. ok1(ntdb_lock_free_bucket(ntdb, b_off, NTDB_LOCK_WAIT) == 0);
  44. test = layout->elem[1].base.off;
  45. ok1(coalesce(ntdb, layout->elem[1].base.off, b_off, len, &test)
  46. == 0);
  47. ntdb_unlock_free_bucket(ntdb, b_off);
  48. ok1(free_record_length(ntdb, layout->elem[1].base.off) == len);
  49. ok1(test == layout->elem[1].base.off);
  50. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  51. ntdb_close(ntdb);
  52. ntdb_layout_free(layout);
  53. /* No coalescing can be done due to used record */
  54. layout = new_ntdb_layout();
  55. ntdb_layout_add_freetable(layout);
  56. ntdb_layout_add_free(layout, 15528, 0);
  57. ntdb_layout_add_used(layout, key, data, 6);
  58. ntdb_layout_write(layout, free, &tap_log_attr, "run-03-coalesce.ntdb");
  59. /* NOMMAP is for lockcheck. */
  60. ntdb = ntdb_open("run-03-coalesce.ntdb", NTDB_NOMMAP|MAYBE_NOSYNC,
  61. O_RDWR, 0, &tap_log_attr);
  62. ok1(free_record_length(ntdb, layout->elem[1].base.off) == 15528);
  63. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  64. /* Figure out which bucket free entry is. */
  65. b_off = bucket_off(ntdb->ftable_off, size_to_bucket(15528));
  66. /* Lock and fail to coalesce. */
  67. ok1(ntdb_lock_free_bucket(ntdb, b_off, NTDB_LOCK_WAIT) == 0);
  68. test = layout->elem[1].base.off;
  69. ok1(coalesce(ntdb, layout->elem[1].base.off, b_off, 15528, &test)
  70. == 0);
  71. ntdb_unlock_free_bucket(ntdb, b_off);
  72. ok1(free_record_length(ntdb, layout->elem[1].base.off) == 15528);
  73. ok1(test == layout->elem[1].base.off);
  74. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  75. ntdb_close(ntdb);
  76. ntdb_layout_free(layout);
  77. /* Coalescing can be done due to two free records, then EOF */
  78. layout = new_ntdb_layout();
  79. ntdb_layout_add_freetable(layout);
  80. ntdb_layout_add_free(layout, 1024, 0);
  81. ntdb_layout_add_free(layout, 14520, 0);
  82. ntdb_layout_write(layout, free, &tap_log_attr, "run-03-coalesce.ntdb");
  83. /* NOMMAP is for lockcheck. */
  84. ntdb = ntdb_open("run-03-coalesce.ntdb", NTDB_NOMMAP|MAYBE_NOSYNC,
  85. O_RDWR, 0, &tap_log_attr);
  86. ok1(free_record_length(ntdb, layout->elem[1].base.off) == 1024);
  87. ok1(free_record_length(ntdb, layout->elem[2].base.off) == 14520);
  88. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  89. /* Figure out which bucket (first) free entry is. */
  90. b_off = bucket_off(ntdb->ftable_off, size_to_bucket(1024));
  91. /* Lock and coalesce. */
  92. ok1(ntdb_lock_free_bucket(ntdb, b_off, NTDB_LOCK_WAIT) == 0);
  93. test = layout->elem[2].base.off;
  94. ok1(coalesce(ntdb, layout->elem[1].base.off, b_off, 1024, &test)
  95. == 1024 + sizeof(struct ntdb_used_record) + 14520);
  96. /* Should tell us it's erased this one... */
  97. ok1(test == NTDB_ERR_NOEXIST);
  98. ok1(ntdb->file->allrecord_lock.count == 0 && ntdb->file->num_lockrecs == 0);
  99. ok1(free_record_length(ntdb, layout->elem[1].base.off)
  100. == 1024 + sizeof(struct ntdb_used_record) + 14520);
  101. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  102. ntdb_close(ntdb);
  103. ntdb_layout_free(layout);
  104. /* Coalescing can be done due to two free records, then data */
  105. layout = new_ntdb_layout();
  106. ntdb_layout_add_freetable(layout);
  107. ntdb_layout_add_free(layout, 1024, 0);
  108. ntdb_layout_add_free(layout, 14488, 0);
  109. ntdb_layout_add_used(layout, key, data, 6);
  110. ntdb_layout_write(layout, free, &tap_log_attr, "run-03-coalesce.ntdb");
  111. /* NOMMAP is for lockcheck. */
  112. ntdb = ntdb_open("run-03-coalesce.ntdb", NTDB_NOMMAP|MAYBE_NOSYNC,
  113. O_RDWR, 0, &tap_log_attr);
  114. ok1(free_record_length(ntdb, layout->elem[1].base.off) == 1024);
  115. ok1(free_record_length(ntdb, layout->elem[2].base.off) == 14488);
  116. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  117. /* Figure out which bucket free entry is. */
  118. b_off = bucket_off(ntdb->ftable_off, size_to_bucket(1024));
  119. /* Lock and coalesce. */
  120. ok1(ntdb_lock_free_bucket(ntdb, b_off, NTDB_LOCK_WAIT) == 0);
  121. test = layout->elem[2].base.off;
  122. ok1(coalesce(ntdb, layout->elem[1].base.off, b_off, 1024, &test)
  123. == 1024 + sizeof(struct ntdb_used_record) + 14488);
  124. ok1(ntdb->file->allrecord_lock.count == 0 && ntdb->file->num_lockrecs == 0);
  125. ok1(free_record_length(ntdb, layout->elem[1].base.off)
  126. == 1024 + sizeof(struct ntdb_used_record) + 14488);
  127. ok1(test == NTDB_ERR_NOEXIST);
  128. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  129. ntdb_close(ntdb);
  130. ntdb_layout_free(layout);
  131. /* Coalescing can be done due to three free records, then EOF */
  132. layout = new_ntdb_layout();
  133. ntdb_layout_add_freetable(layout);
  134. ntdb_layout_add_free(layout, 1024, 0);
  135. ntdb_layout_add_free(layout, 512, 0);
  136. ntdb_layout_add_free(layout, 13992, 0);
  137. ntdb_layout_write(layout, free, &tap_log_attr, "run-03-coalesce.ntdb");
  138. /* NOMMAP is for lockcheck. */
  139. ntdb = ntdb_open("run-03-coalesce.ntdb", NTDB_NOMMAP|MAYBE_NOSYNC,
  140. O_RDWR, 0, &tap_log_attr);
  141. ok1(free_record_length(ntdb, layout->elem[1].base.off) == 1024);
  142. ok1(free_record_length(ntdb, layout->elem[2].base.off) == 512);
  143. ok1(free_record_length(ntdb, layout->elem[3].base.off) == 13992);
  144. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  145. /* Figure out which bucket free entry is. */
  146. b_off = bucket_off(ntdb->ftable_off, size_to_bucket(1024));
  147. /* Lock and coalesce. */
  148. ok1(ntdb_lock_free_bucket(ntdb, b_off, NTDB_LOCK_WAIT) == 0);
  149. test = layout->elem[2].base.off;
  150. ok1(coalesce(ntdb, layout->elem[1].base.off, b_off, 1024, &test)
  151. == 1024 + sizeof(struct ntdb_used_record) + 512
  152. + sizeof(struct ntdb_used_record) + 13992);
  153. ok1(ntdb->file->allrecord_lock.count == 0
  154. && ntdb->file->num_lockrecs == 0);
  155. ok1(free_record_length(ntdb, layout->elem[1].base.off)
  156. == 1024 + sizeof(struct ntdb_used_record) + 512
  157. + sizeof(struct ntdb_used_record) + 13992);
  158. ok1(ntdb_check(ntdb, NULL, NULL) == 0);
  159. ntdb_close(ntdb);
  160. ntdb_layout_free(layout);
  161. ok1(tap_log_messages == 0);
  162. return exit_status();
  163. }