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 #include "cachetable-test.h" 41 42 static void 43 clone_callback(void* UU(value_data), void** cloned_value_data, long* clone_size, PAIR_ATTR* new_attr, bool UU(for_checkpoint), void* UU(write_extraargs)) 44 { flush(CACHEFILE f,int UU (fd),CACHEKEY k,void * UU (v),void ** UU (dd),void * e,PAIR_ATTR s,PAIR_ATTR * new_size,bool w,bool keep,bool c,bool UU (is_clone))45 *cloned_value_data = (void *)1; 46 *clone_size = 8; 47 new_attr->is_valid = false; 48 } 49 50 bool clone_flush_started; 51 bool clone_flush_completed; 52 CACHETABLE ct; 53 54 static void 55 flush ( 56 CACHEFILE f __attribute__((__unused__)), 57 int UU(fd), 58 CACHEKEY k __attribute__((__unused__)), 59 void *v __attribute__((__unused__)), 60 void** UU(dd), 61 void *e __attribute__((__unused__)), 62 PAIR_ATTR s __attribute__((__unused__)), 63 PAIR_ATTR* new_size __attribute__((__unused__)), 64 bool w __attribute__((__unused__)), 65 bool keep __attribute__((__unused__)), 66 bool c __attribute__((__unused__)), fetch(CACHEFILE f,PAIR UU (p),int UU (fd),CACHEKEY k,uint32_t fullhash,void ** value,void ** UU (dd),PAIR_ATTR * sizep,int * dirtyp,void * extraargs)67 bool is_clone 68 ) 69 { 70 if (is_clone) { 71 clone_flush_started = true; 72 usleep(4*1024*1024); 73 clone_flush_completed = true; 74 } 75 } 76 77 static void *run_end_checkpoint(void *arg) { 78 CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct); 79 toku_cachetable_end_checkpoint( 80 cp, 81 NULL, 82 NULL, 83 NULL 84 ); 85 return arg; 86 } other_flush(CACHEFILE f,int UU (fd),CACHEKEY k,void * v,void ** UU (dd),void * e,PAIR_ATTR s,PAIR_ATTR * new_size,bool w,bool keep,bool c,bool UU (is_clone))87 88 // 89 // this test verifies that a PAIR that undergoes a checkpoint on the checkpoint thread is still pinnable while being written out 90 // 91 static void 92 cachetable_test (void) { 93 const int test_limit = 200; 94 int r; 95 ct = NULL; 96 toku_cachetable_create(&ct, test_limit, ZERO_LSN, nullptr); 97 const char *fname1 = TOKU_TEST_FILENAME; 98 unlink(fname1); 99 CACHEFILE f1; 100 r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r == 0); 101 create_dummy_functions(f1); 102 103 void* v1; 104 CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL); 105 wc.flush_callback = flush; 106 wc.clone_callback = clone_callback; 107 r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, true, NULL); 108 assert_zero(r); 109 r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_DIRTY, make_pair_attr(8)); 110 assert_zero(r); 111 CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct); 112 toku_cachetable_begin_checkpoint(cp, NULL); 113 114 clone_flush_started = false; 115 clone_flush_completed = false; 116 toku_pthread_t checkpoint_tid; 117 r = toku_pthread_create(toku_uninstrumented, 118 &checkpoint_tid, 119 nullptr, 120 run_end_checkpoint, 121 nullptr); 122 assert_zero(r); 123 124 usleep(1 * 1024 * 1024); 125 126 r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, wc, def_fetch, def_pf_req_callback, def_pf_callback, true, NULL); 127 assert_zero(r); 128 assert(clone_flush_started && !clone_flush_completed); 129 r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8)); 130 assert_zero(r); 131 132 void *ret; 133 r = toku_pthread_join(checkpoint_tid, &ret); 134 assert_zero(r); 135 assert(clone_flush_started && clone_flush_completed); 136 137 toku_cachetable_verify(ct); 138 toku_cachefile_close(&f1, false, ZERO_LSN); 139 toku_cachetable_close(&ct); 140 } 141 142 int 143 test_main(int argc, const char *argv[]) { 144 default_parse_args(argc, argv); 145 cachetable_test(); 146 return 0; 147 } cachetable_test(void)148