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