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, ¤t_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, ¤t_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