You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

318 lines
8.4 KiB

  1. #ident "$Id: test-del-inorder.c 32975 2011-07-11 23:42:51Z leifwalsh $"
  2. /* The goal of this test. Make sure that inserts stay behind deletes. */
  3. #include "test.h"
  4. #include "includes.h"
  5. #include <brt-cachetable-wrappers.h>
  6. #include "brt-flusher.h"
  7. #include "brt-flusher-internal.h"
  8. #include "checkpoint.h"
  9. static TOKUTXN const null_txn = 0;
  10. static DB * const null_db = 0;
  11. enum { NODESIZE = 1024, KSIZE=NODESIZE-100, TOKU_PSIZE=20 };
  12. CACHETABLE ct;
  13. BRT t;
  14. BOOL checkpoint_called;
  15. BOOL checkpoint_callback_called;
  16. toku_pthread_t checkpoint_tid;
  17. // callback functions for flush_some_child
  18. static bool
  19. dont_destroy_bn(void* UU(extra))
  20. {
  21. return false;
  22. }
  23. static bool recursively_flush_should_not_happen(BRTNODE UU(child), void* UU(extra)) {
  24. assert(FALSE);
  25. }
  26. static int child_to_flush(struct brt_header* UU(h), BRTNODE parent, void* UU(extra)) {
  27. assert(parent->height == 1);
  28. assert(parent->n_children == 2);
  29. return 0;
  30. }
  31. static void dummy_update_status(BRTNODE UU(child), int UU(dirtied), void* UU(extra)) {
  32. }
  33. static void checkpoint_callback(void* UU(extra)) {
  34. usleep(1*1024*1024);
  35. checkpoint_callback_called = TRUE;
  36. }
  37. static void *do_checkpoint(void *arg) {
  38. // first verify that checkpointed_data is correct;
  39. if (verbose) printf("starting a checkpoint\n");
  40. int r = toku_checkpoint(ct, NULL, checkpoint_callback, NULL, NULL, NULL, CLIENT_CHECKPOINT);
  41. assert_zero(r);
  42. if (verbose) printf("completed a checkpoint\n");
  43. return arg;
  44. }
  45. static void flusher_callback(int state, void* extra) {
  46. int desired_state = *(int *)extra;
  47. if (verbose) {
  48. printf("state %d\n", state);
  49. }
  50. if (state == desired_state) {
  51. checkpoint_called = TRUE;
  52. int r = toku_pthread_create(&checkpoint_tid, NULL, do_checkpoint, NULL);
  53. assert_zero(r);
  54. while (!checkpoint_callback_called) {
  55. usleep(1*1024*1024);
  56. }
  57. }
  58. }
  59. static void
  60. doit (int state) {
  61. BLOCKNUM node_root;
  62. BLOCKNUM node_leaves[2];
  63. int r;
  64. checkpoint_called = FALSE;
  65. checkpoint_callback_called = FALSE;
  66. toku_flusher_thread_set_callback(flusher_callback, &state);
  67. r = toku_brt_create_cachetable(&ct, 500*1024*1024, ZERO_LSN, NULL_LOGGER); assert(r==0);
  68. unlink("foo3.brt");
  69. unlink("bar3.brt");
  70. // note the basement node size is 5 times the node size
  71. // this is done to avoid rebalancing when writing a leaf
  72. // node to disk
  73. r = toku_open_brt("foo3.brt", 1, &t, NODESIZE, 5*NODESIZE, ct, null_txn, toku_builtin_compare_fun, null_db);
  74. assert(r==0);
  75. toku_testsetup_initialize(); // must precede any other toku_testsetup calls
  76. r = toku_testsetup_leaf(t, &node_leaves[0], 1, NULL, NULL);
  77. assert(r==0);
  78. r = toku_testsetup_leaf(t, &node_leaves[1], 1, NULL, NULL);
  79. assert(r==0);
  80. char* pivots[1];
  81. pivots[0] = toku_strdup("kkkkk");
  82. int pivot_len = 6;
  83. r = toku_testsetup_nonleaf(t, 1, &node_root, 2, node_leaves, pivots, &pivot_len);
  84. assert(r==0);
  85. r = toku_testsetup_root(t, node_root);
  86. assert(r==0);
  87. char dummy_val[NODESIZE/2-50];
  88. memset(dummy_val, 0, sizeof(dummy_val));
  89. r = toku_testsetup_insert_to_leaf(
  90. t,
  91. node_leaves[0],
  92. "a",
  93. 2,
  94. NULL,
  95. 0
  96. );
  97. assert_zero(r);
  98. r = toku_testsetup_insert_to_leaf(
  99. t,
  100. node_leaves[1],
  101. "x",
  102. 2,
  103. dummy_val,
  104. sizeof(dummy_val)
  105. );
  106. assert_zero(r);
  107. r = toku_testsetup_insert_to_leaf(
  108. t,
  109. node_leaves[1],
  110. "y",
  111. 2,
  112. dummy_val,
  113. sizeof(dummy_val)
  114. );
  115. assert_zero(r);
  116. r = toku_testsetup_insert_to_leaf(
  117. t,
  118. node_leaves[1],
  119. "z",
  120. 2,
  121. NULL,
  122. 0
  123. );
  124. assert_zero(r);
  125. // at this point, we have inserted two leafentries,
  126. // one in each leaf node. A flush should invoke a merge
  127. struct flusher_advice fa;
  128. flusher_advice_init(
  129. &fa,
  130. child_to_flush,
  131. dont_destroy_bn,
  132. recursively_flush_should_not_happen,
  133. default_merge_child,
  134. dummy_update_status,
  135. default_pick_child_after_split,
  136. NULL
  137. );
  138. // hack to get merge going
  139. BRTNODE node = NULL;
  140. toku_pin_node_with_min_bfe(&node, node_leaves[0], t);
  141. BLB_SEQINSERT(node, node->n_children-1) = FALSE;
  142. toku_unpin_brtnode(t, node);
  143. toku_pin_node_with_min_bfe(&node, node_leaves[1], t);
  144. BLB_SEQINSERT(node, node->n_children-1) = FALSE;
  145. toku_unpin_brtnode(t, node);
  146. struct brtnode_fetch_extra bfe;
  147. fill_bfe_for_min_read(&bfe, t->h);
  148. toku_pin_brtnode_off_client_thread(
  149. t->h,
  150. node_root,
  151. toku_cachetable_hash(t->h->cf, node_root),
  152. &bfe,
  153. TRUE,
  154. 0,
  155. NULL,
  156. &node
  157. );
  158. assert(node->height == 1);
  159. assert(node->n_children == 2);
  160. // do the flush
  161. flush_some_child(t->h, node, &fa);
  162. assert(checkpoint_callback_called);
  163. // now let's pin the root again and make sure it is has rebalanced
  164. toku_pin_brtnode_off_client_thread(
  165. t->h,
  166. node_root,
  167. toku_cachetable_hash(t->h->cf, node_root),
  168. &bfe,
  169. TRUE,
  170. 0,
  171. NULL,
  172. &node
  173. );
  174. assert(node->height == 1);
  175. assert(node->n_children == 2);
  176. toku_unpin_brtnode(t, node);
  177. void *ret;
  178. r = toku_pthread_join(checkpoint_tid, &ret);
  179. assert_zero(r);
  180. //
  181. // now the dictionary has been checkpointed
  182. // copy the file to something with a new name,
  183. // open it, and verify that the state of what is
  184. // checkpointed is what we expect
  185. //
  186. r = system("cp foo3.brt bar3.brt ");
  187. assert_zero(r);
  188. BRT c_brt;
  189. // note the basement node size is 5 times the node size
  190. // this is done to avoid rebalancing when writing a leaf
  191. // node to disk
  192. r = toku_open_brt("bar3.brt", 0, &c_brt, NODESIZE, 5*NODESIZE, ct, null_txn, toku_builtin_compare_fun, null_db);
  193. assert(r==0);
  194. //
  195. // now pin the root, verify that the state is what we expect
  196. //
  197. fill_bfe_for_full_read(&bfe, c_brt->h);
  198. toku_pin_brtnode_off_client_thread(
  199. c_brt->h,
  200. node_root,
  201. toku_cachetable_hash(c_brt->h->cf, node_root),
  202. &bfe,
  203. TRUE,
  204. 0,
  205. NULL,
  206. &node
  207. );
  208. assert(node->height == 1);
  209. assert(!node->dirty);
  210. BLOCKNUM left_child, right_child;
  211. assert(node->n_children == 2);
  212. left_child = BP_BLOCKNUM(node,0);
  213. right_child = BP_BLOCKNUM(node,1);
  214. toku_unpin_brtnode_off_client_thread(c_brt->h, node);
  215. // now let's verify the leaves are what we expect
  216. toku_pin_brtnode_off_client_thread(
  217. c_brt->h,
  218. left_child,
  219. toku_cachetable_hash(c_brt->h->cf, left_child),
  220. &bfe,
  221. TRUE,
  222. 0,
  223. NULL,
  224. &node
  225. );
  226. assert(node->height == 0);
  227. assert(!node->dirty);
  228. assert(node->n_children == 1);
  229. assert(toku_omt_size(BLB_BUFFER(node,0)) == 2);
  230. toku_unpin_brtnode_off_client_thread(c_brt->h, node);
  231. toku_pin_brtnode_off_client_thread(
  232. c_brt->h,
  233. right_child,
  234. toku_cachetable_hash(c_brt->h->cf, right_child),
  235. &bfe,
  236. TRUE,
  237. 0,
  238. NULL,
  239. &node
  240. );
  241. assert(node->height == 0);
  242. assert(!node->dirty);
  243. assert(node->n_children == 1);
  244. assert(toku_omt_size(BLB_BUFFER(node,0)) == 2);
  245. toku_unpin_brtnode_off_client_thread(c_brt->h, node);
  246. DBT k;
  247. struct check_pair pair1 = {2, "a", 0, NULL, 0};
  248. r = toku_brt_lookup(c_brt, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair1);
  249. assert(r==0);
  250. struct check_pair pair2 = {2, "x", sizeof(dummy_val), dummy_val, 0};
  251. r = toku_brt_lookup(c_brt, toku_fill_dbt(&k, "x", 2), lookup_checkf, &pair2);
  252. assert(r==0);
  253. struct check_pair pair3 = {2, "y", sizeof(dummy_val), dummy_val, 0};
  254. r = toku_brt_lookup(c_brt, toku_fill_dbt(&k, "y", 2), lookup_checkf, &pair3);
  255. assert(r==0);
  256. struct check_pair pair4 = {2, "z", 0, NULL, 0};
  257. r = toku_brt_lookup(c_brt, toku_fill_dbt(&k, "z", 2), lookup_checkf, &pair4);
  258. assert(r==0);
  259. r = toku_close_brt_nolsn(t, 0); assert(r==0);
  260. r = toku_close_brt_nolsn(c_brt, 0); assert(r==0);
  261. r = toku_cachetable_close(&ct); assert(r==0);
  262. toku_free(pivots[0]);
  263. }
  264. int
  265. test_main (int argc __attribute__((__unused__)), const char *argv[] __attribute__((__unused__))) {
  266. default_parse_args(argc, argv);
  267. doit(ft_flush_after_rebalance);
  268. return 0;
  269. }