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 // Test for #3681: iibench hangs.  The scenario is
40 //  * Thread 1 calls root_put_msg, get_and_pin_root, 1 holds read lock on the root.
41 //  * Thread 2 calls checkpoint, marks the root for checkpoint.
42 //  * Thread 2 calls end_checkpoint, tries to write lock the root, sets want_write, and blocks on the rwlock because there is a reader.
43 //  * Thread 1 calls apply_msg_to_in_memory_leaves, calls get_and_pin_if_in_memory, tries to get a read lock on the root node and blocks on the rwlock because there is a write request on the lock.
44 
45 
46 #include "cachetable/checkpoint.h"
47 #include "test.h"
48 
49 CACHETABLE ct;
50 FT_HANDLE t;
51 
52 static TOKUTXN const null_txn = 0;
53 
54 volatile bool done = false;
55 
setup(void)56 static void setup (void) {
57     toku_cachetable_create(&ct, 0, ZERO_LSN, nullptr);
58     const char *fname = TOKU_TEST_FILENAME;
59     unlink(fname);
60     { int r = toku_open_ft_handle(fname, 1, &t, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);         assert(r==0); }
61 }
62 
63 
finish(void)64 static void finish (void) {
65     { int r = toku_close_ft_handle_nolsn(t, 0);                                                                       assert(r==0); };
66     toku_cachetable_close(&ct);
67 }
68 
starta(void * n)69 static void *starta (void *n) {
70     assert(n==NULL);
71     for (int i=0; i<10000; i++) {
72 	DBT k,v;
73 	char ks[20], vs[20];
74 	snprintf(ks, sizeof(ks), "hello%03d", i);
75 	snprintf(vs, sizeof(vs), "there%03d", i);
76 	toku_ft_insert(t, toku_fill_dbt(&k, ks, strlen(ks)), toku_fill_dbt(&v, vs, strlen(vs)), null_txn);
77 	usleep(1);
78     }
79     done = true;
80     return NULL;
81 }
startb(void * n)82 static void *startb (void *n) {
83     assert(n==NULL);
84     int count=0;
85     while (!done) {
86         CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct);
87         int r = toku_checkpoint(cp, NULL, NULL, NULL, NULL, NULL, CLIENT_CHECKPOINT); assert(r==0);
88         count++;
89     }
90     printf("count=%d\n", count);
91     return NULL;
92 }
93 
test3681(void)94 static void test3681(void) {
95     setup();
96     toku_pthread_t a, b;
97     {
98         int r;
99         r = toku_pthread_create(
100             toku_uninstrumented, &a, nullptr, starta, nullptr);
101         assert(r == 0);
102     }
103     {
104         int r;
105         r = toku_pthread_create(
106             toku_uninstrumented, &b, nullptr, startb, nullptr);
107         assert(r == 0);
108     }
109     {
110         int r;
111         void *v;
112         r = toku_pthread_join(a, &v);
113         assert(r == 0);
114         assert(v == NULL);
115     }
116     {
117         int r;
118         void *v;
119         r = toku_pthread_join(b, &v);
120         assert(r == 0);
121         assert(v == NULL);
122     }
123     finish();
124 }
125 
test_main(int argc,const char * argv[])126 int test_main (int argc, const char *argv[]) {
127     default_parse_args(argc, argv);
128     test3681();
129     return 0;
130 }
131 
132