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