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