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 // This test crashes if a failed loader creation causes the db to be corrupted by unlinking
40 // the underlying fractal tree files.  This unlinking occurs because the txn that logs the
41 // load log entries is committed rather than aborted.
42 
43 #include "test.h"
44 #include <db.h>
45 #include <sys/resource.h>
46 
47 static int loader_flags = 0;
48 static const char *envdir = TOKU_TEST_FILENAME;
49 
run_test(int ndb)50 static void run_test(int ndb) {
51     int r;
52 
53     char rmcmd[32 + strlen(envdir)];
54     snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", envdir);
55     r = system(rmcmd);                                                                             CKERR(r);
56     r = toku_os_mkdir(envdir, S_IRWXU+S_IRWXG+S_IRWXO);                                                       CKERR(r);
57 
58     DB_ENV *env;
59     r = db_env_create(&env, 0);                                                                               CKERR(r);
60     int envflags = DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_CREATE | DB_PRIVATE;
61     r = env->open(env, envdir, envflags, S_IRWXU+S_IRWXG+S_IRWXO);                                            CKERR(r);
62     env->set_errfile(env, stderr);
63 
64     DB *dbs[ndb];
65     uint32_t db_flags[ndb];
66     uint32_t dbt_flags[ndb];
67     for (int i = 0; i < ndb; i++) {
68         db_flags[i] = DB_NOOVERWRITE;
69         dbt_flags[i] = 0;
70         r = db_create(&dbs[i], env, 0); CKERR(r);
71         char name[32];
72         sprintf(name, "db%d", i);
73         r = dbs[i]->open(dbs[i], NULL, name, NULL, DB_BTREE, DB_CREATE, 0666); CKERR(r);
74     }
75 
76     DB_TXN *txn;
77     r = env->txn_begin(env, NULL, &txn, 0); CKERR(r);
78 
79     struct rlimit current_nproc_limit;
80     r = getrlimit(RLIMIT_NPROC, &current_nproc_limit);
81     assert(r == 0);
82 
83     struct rlimit new_nproc_limit = current_nproc_limit;
84     new_nproc_limit.rlim_cur = 0;
85     r = setrlimit(RLIMIT_NPROC, &new_nproc_limit);
86     assert(r == 0);
87 
88     DB_LOADER *loader;
89     int loader_r = env->create_loader(env, txn, &loader, ndb > 0 ? dbs[0] : NULL, ndb, dbs, db_flags, dbt_flags, loader_flags);
90 
91     r = setrlimit(RLIMIT_NPROC, &current_nproc_limit);
92     assert(r == 0);
93 
94     if (loader_flags & LOADER_DISALLOW_PUTS)  {
95         CKERR(loader_r);
96         loader_r = loader->close(loader);
97         CKERR(loader_r);
98     } else {
99         CKERR2(loader_r, EAGAIN);
100     }
101 
102     r = txn->commit(txn, 0); CKERR(r);
103 
104     for (int i = 0; i < ndb; i++) {
105         r = dbs[i]->close(dbs[i], 0); CKERR(r);
106     }
107 
108     for (int i = 0; i < ndb; i++) {
109         r = db_create(&dbs[i], env, 0); CKERR(r);
110         char name[32];
111         sprintf(name, "db%d", i);
112         r = dbs[i]->open(dbs[i], NULL, name, NULL, DB_BTREE, 0, 0666); CKERR(r);
113     }
114 
115     for (int i = 0; i < ndb; i++) {
116         r = dbs[i]->close(dbs[i], 0); CKERR(r);
117     }
118 
119     r = env->close(env, 0); CKERR(r);
120 }
121 
do_args(int argc,char * const argv[])122 static void do_args(int argc, char * const argv[]) {
123     int resultcode;
124     char *cmd = argv[0];
125     argc--; argv++;
126     while (argc>0) {
127         if (strcmp(argv[0], "-h")==0) {
128 	    resultcode=0;
129 	do_usage:
130 	    fprintf(stderr, "Usage: %s -h -v -q -p\n", cmd);
131 	    exit(resultcode);
132 	} else if (strcmp(argv[0], "-v")==0) {
133 	    verbose++;
134 	} else if (strcmp(argv[0],"-q")==0) {
135 	    verbose--;
136 	    if (verbose<0) verbose=0;
137         } else if (strcmp(argv[0], "-p") == 0) {
138             loader_flags |= LOADER_DISALLOW_PUTS;
139         } else if (strcmp(argv[0], "-z") == 0) {
140             loader_flags |= LOADER_COMPRESS_INTERMEDIATES;
141         } else if (strcmp(argv[0], "-e") == 0) {
142             argc--; argv++;
143             if (argc > 0)
144                 envdir = argv[0];
145 	} else {
146 	    fprintf(stderr, "Unknown arg: %s\n", argv[0]);
147 	    resultcode=1;
148 	    goto do_usage;
149 	}
150 	argc--;
151 	argv++;
152     }
153 }
154 
test_main(int argc,char * const * argv)155 int test_main(int argc, char * const *argv) {
156     do_args(argc, argv);
157     run_test(1);
158     return 0;
159 }
160