1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3 #ident "$Id$"
4 /*======
5 This file is part of PerconaFT.
6
7
8 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9
10 PerconaFT is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License, version 2,
12 as published by the Free Software Foundation.
13
14 PerconaFT is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
21
22 ----------------------------------------
23
24 PerconaFT is free software: you can redistribute it and/or modify
25 it under the terms of the GNU Affero General Public License, version 3,
26 as published by the Free Software Foundation.
27
28 PerconaFT is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU Affero General Public License for more details.
32
33 You should have received a copy of the GNU Affero General Public License
34 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
35 ======= */
36
37 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38
39 #include "test.h"
40
41 #include <util/dbt.h>
42 #include <ft/ft-cachetable-wrappers.h>
43
44 // Each FT maintains a sequential insert heuristic to determine if its
45 // worth trying to insert directly into a well-known rightmost leaf node.
46 //
47 // The heuristic is only maintained when a rightmost leaf node is known.
48 //
49 // This test verifies that sequential inserts increase the seqinsert score
50 // and that a single non-sequential insert resets the score.
51
test_seqinsert_heuristic(void)52 static void test_seqinsert_heuristic(void) {
53 int r = 0;
54 char name[TOKU_PATH_MAX + 1];
55 toku_path_join(name, 2, TOKU_TEST_FILENAME, "ftdata");
56 toku_os_recursive_delete(TOKU_TEST_FILENAME);
57 r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU); CKERR(r);
58
59 FT_HANDLE ft_handle;
60 CACHETABLE ct;
61 toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
62 r = toku_open_ft_handle(name, 1, &ft_handle,
63 4*1024*1024, 64*1024,
64 TOKU_DEFAULT_COMPRESSION_METHOD, ct, NULL,
65 toku_builtin_compare_fun); CKERR(r);
66 FT ft = ft_handle->ft;
67
68 int k;
69 DBT key, val;
70 const int val_size = 1024 * 1024;
71 char *XMALLOC_N(val_size, val_buf);
72 memset(val_buf, 'x', val_size);
73 toku_fill_dbt(&val, val_buf, val_size);
74
75 // Insert many rows sequentially. This is enough data to:
76 // - force the root to split (the righmost leaf will then be known)
77 // - raise the seqinsert score high enough to enable direct rightmost injections
78 const int rows_to_insert = 200;
79 for (int i = 0; i < rows_to_insert; i++) {
80 k = toku_htonl(i);
81 toku_fill_dbt(&key, &k, sizeof(k));
82 toku_ft_insert(ft_handle, &key, &val, NULL);
83 }
84 invariant(ft->rightmost_blocknum.b != RESERVED_BLOCKNUM_NULL);
85 invariant(ft->seqinsert_score == FT_SEQINSERT_SCORE_THRESHOLD);
86
87 // Insert on the left extreme. The seq insert score is high enough
88 // that we will attempt to insert into the rightmost leaf. We won't
89 // be successful because key 0 won't be in the bounds of the rightmost leaf.
90 // This failure should reset the seqinsert score back to 0.
91 k = toku_htonl(0);
92 toku_fill_dbt(&key, &k, sizeof(k));
93 toku_ft_insert(ft_handle, &key, &val, NULL);
94 invariant(ft->seqinsert_score == 0);
95
96 // Insert in the middle. The score should not go up.
97 k = toku_htonl(rows_to_insert / 2);
98 toku_fill_dbt(&key, &k, sizeof(k));
99 toku_ft_insert(ft_handle, &key, &val, NULL);
100 invariant(ft->seqinsert_score == 0);
101
102 // Insert on the right extreme. The score should go up.
103 k = toku_htonl(rows_to_insert);
104 toku_fill_dbt(&key, &k, sizeof(k));
105 toku_ft_insert(ft_handle, &key, &val, NULL);
106 invariant(ft->seqinsert_score == 1);
107
108 // Insert again on the right extreme again, the score should go up.
109 k = toku_htonl(rows_to_insert + 1);
110 toku_fill_dbt(&key, &k, sizeof(k));
111 toku_ft_insert(ft_handle, &key, &val, NULL);
112 invariant(ft->seqinsert_score == 2);
113
114 // Insert close to, but not at, the right extreme. The score should reset.
115 // -- the magic number 4 derives from the fact that vals are 1mb and nodes are 4mb
116 k = toku_htonl(rows_to_insert - 4);
117 toku_fill_dbt(&key, &k, sizeof(k));
118 toku_ft_insert(ft_handle, &key, &val, NULL);
119 invariant(ft->seqinsert_score == 0);
120
121 toku_free(val_buf);
122 toku_ft_handle_close(ft_handle);
123 toku_cachetable_close(&ct);
124 toku_os_recursive_delete(TOKU_TEST_FILENAME);
125 }
126
test_main(int argc,const char * argv[])127 int test_main(int argc, const char *argv[]) {
128 default_parse_args(argc, argv);
129 test_seqinsert_heuristic();
130 return 0;
131 }
132