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 TokuDB
6 
7 
8 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9 
10     TokuDBis 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     TokuDB 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 TokuDB.  If not, see <http://www.gnu.org/licenses/>.
21 
22 ======= */
23 
24 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
25 
26 // test tokudb cardinality in status dictionary
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdint.h>
30 #include <assert.h>
31 #include <memory.h>
32 #include <errno.h>
33 #include <sys/stat.h>
34 #include <db.h>
35 typedef unsigned long long ulonglong;
36 #include <tokudb_status.h>
37 #include <tokudb_buffer.h>
38 
39 #include "fake_mysql.h"
40 
41 #if __APPLE__
42 typedef unsigned long ulong;
43 #endif
44 #include <tokudb_card.h>
45 
test_no_keys(DB_ENV * env)46 static void test_no_keys(DB_ENV *env) {
47     int error;
48 
49     DB_TXN *txn = NULL;
50     error = env->txn_begin(env, NULL, &txn, 0);
51     assert(error == 0);
52 
53     DB *status_db = NULL;
54     error = tokudb::create_status(env, &status_db, "status_no_keys", txn);
55     assert(error == 0);
56 
57     const uint keys = 0;
58     const uint key_parts = 0;
59     TABLE_SHARE s = { MAX_KEY, keys, key_parts, NULL };
60 
61     error = tokudb::alter_card(status_db, txn, &s, &s);
62     assert(error == 0);
63 
64     error = txn->commit(txn, 0);
65     assert(error == 0);
66 
67     error = tokudb::close_status(&status_db);
68     assert(error == 0);
69 }
70 
test_keys(DB_ENV * env)71 static void test_keys(DB_ENV *env) {
72     int error;
73 
74     DB_TXN *txn = NULL;
75     error = env->txn_begin(env, NULL, &txn, 0);
76     assert(error == 0);
77 
78     DB *status_db = NULL;
79     error = tokudb::create_status(env, &status_db, "status_keys", txn);
80     assert(error == 0);
81 
82     // define tables
83     const uint ta_keys = 3;
84     const uint ta_key_parts = 1;
85     const int ta_rec_per_keys = ta_keys * ta_key_parts;
86     uint64_t ta_rec_per_key[ta_rec_per_keys] = {
87         1000, 2000, 3000,
88     };
89     KEY_INFO ta_key_info[ta_rec_per_keys] = {
90         { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_a" },
91         { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_b" },
92         { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_c" },
93     };
94     TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info };
95 
96     // set initial cardinality
97     error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key);
98     assert(error == 0);
99 
100     error = tokudb::alter_card(status_db, txn, &ta, &ta);
101     assert(error == 0);
102 
103     // verify
104     uint64_t current_rec_per_key[ta_rec_per_keys];
105     error = tokudb::get_card_from_status(status_db, txn, ta_rec_per_keys, current_rec_per_key);
106     assert(error == 0);
107     for (uint i = 0; i < ta_rec_per_keys; i++) {
108         assert(current_rec_per_key[i] == ta_rec_per_key[i]);
109     }
110 
111     error = txn->commit(txn, 0);
112     assert(error == 0);
113 
114     error = tokudb::close_status(&status_db);
115     assert(error == 0);
116 }
117 
test_drop_0(DB_ENV * env)118 static void test_drop_0(DB_ENV *env) {
119     int error;
120 
121     DB_TXN *txn = NULL;
122     error = env->txn_begin(env, NULL, &txn, 0);
123     assert(error == 0);
124 
125     DB *status_db = NULL;
126     error = tokudb::create_status(env, &status_db, "status_drop_0", txn);
127     assert(error == 0);
128 
129     // define tables
130     const uint ta_keys = 3;
131     const uint ta_key_parts = 1;
132     const uint ta_rec_per_keys = ta_keys * ta_key_parts;
133     uint64_t ta_rec_per_key[ta_rec_per_keys] = {
134         1000, 2000, 3000,
135     };
136     KEY_INFO ta_key_info[ta_rec_per_keys] = {
137         { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_a" },
138         { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_b" },
139         { 0, ta_key_parts, &ta_rec_per_key[2], (char *) "key_c" },
140     };
141     TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info };
142 
143     const uint tb_keys = 2;
144     const uint tb_key_parts = 1;
145     const int tb_rec_per_keys = tb_keys * tb_key_parts;
146     uint64_t tb_rec_per_key[tb_rec_per_keys] = {
147         2000, 3000,
148     };
149     KEY_INFO tb_key_info[tb_rec_per_keys] = {
150         { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_b" },
151         { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_c" },
152     };
153     TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info };
154 
155     // set initial cardinality
156     error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key);
157     assert(error == 0);
158 
159     error = tokudb::alter_card(status_db, txn, &ta, &tb);
160     assert(error == 0);
161 
162     // verify
163     uint64_t current_rec_per_key[tb_rec_per_keys];
164     error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key);
165     assert(error == 0);
166     for (uint i = 0; i < tb_rec_per_keys; i++) {
167         assert(current_rec_per_key[i] == tb_rec_per_key[i]);
168     }
169 
170     error = txn->commit(txn, 0);
171     assert(error == 0);
172 
173     error = tokudb::close_status(&status_db);
174     assert(error == 0);
175 }
176 
test_drop_1(DB_ENV * env)177 static void test_drop_1(DB_ENV *env) {
178     int error;
179 
180     DB_TXN *txn = NULL;
181     error = env->txn_begin(env, NULL, &txn, 0);
182     assert(error == 0);
183 
184     DB *status_db = NULL;
185     error = tokudb::create_status(env, &status_db, "status_drop_1", txn);
186     assert(error == 0);
187 
188     // define tables
189     const uint ta_keys = 3;
190     const uint ta_key_parts = 1;
191     const uint ta_rec_per_keys = ta_keys * ta_key_parts;
192     uint64_t ta_rec_per_key[ta_rec_per_keys] = {
193         1000, 2000, 3000,
194     };
195     KEY_INFO ta_key_info[ta_rec_per_keys] = {
196         { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_a" },
197         { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_b" },
198         { 0, ta_key_parts, &ta_rec_per_key[2], (char *) "key_c" },
199     };
200     TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info };
201 
202     const uint tb_keys = 2;
203     const uint tb_key_parts = 1;
204     const int tb_rec_per_keys = tb_keys * tb_key_parts;
205     uint64_t tb_rec_per_key[tb_rec_per_keys] = {
206         1000, 3000,
207     };
208     KEY_INFO tb_key_info[tb_rec_per_keys] = {
209         { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_a" },
210         { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_c" },
211     };
212     TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info };
213 
214     // set initial cardinality
215     error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key);
216     assert(error == 0);
217 
218     error = tokudb::alter_card(status_db, txn, &ta, &tb);
219     assert(error == 0);
220 
221     // verify
222     uint64_t current_rec_per_key[tb_rec_per_keys];
223     error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key);
224     assert(error == 0);
225     for (uint i = 0; i < tb_rec_per_keys; i++) {
226         assert(current_rec_per_key[i] == tb_rec_per_key[i]);
227     }
228 
229     error = txn->commit(txn, 0);
230     assert(error == 0);
231 
232     error = tokudb::close_status(&status_db);
233     assert(error == 0);
234 }
235 
test_drop_2(DB_ENV * env)236 static void test_drop_2(DB_ENV *env) {
237     int error;
238 
239     DB_TXN *txn = NULL;
240     error = env->txn_begin(env, NULL, &txn, 0);
241     assert(error == 0);
242 
243     DB *status_db = NULL;
244     error = tokudb::create_status(env, &status_db, "status_drop_2", txn);
245     assert(error == 0);
246 
247     // define tables
248     const uint ta_keys = 3;
249     const uint ta_key_parts = 1;
250     const uint ta_rec_per_keys = ta_keys * ta_key_parts;
251     uint64_t ta_rec_per_key[ta_rec_per_keys] = {
252         1000, 2000, 3000,
253     };
254     KEY_INFO ta_key_info[ta_rec_per_keys] = {
255         { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_a" },
256         { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_b" },
257         { 0, ta_key_parts, &ta_rec_per_key[2], (char *) "key_c" },
258     };
259     TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info };
260 
261     const uint tb_keys = 2;
262     const uint tb_key_parts = 1;
263     const int tb_rec_per_keys = tb_keys * tb_key_parts;
264     uint64_t tb_rec_per_key[tb_rec_per_keys] = {
265         1000, 2000,
266     };
267     KEY_INFO tb_key_info[tb_rec_per_keys] = {
268         { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_a" },
269         { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_b" },
270     };
271     TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info };
272 
273     // set initial cardinality
274     error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key);
275     assert(error == 0);
276 
277     error = tokudb::alter_card(status_db, txn, &ta, &tb);
278     assert(error == 0);
279 
280     // verify
281     uint64_t current_rec_per_key[tb_rec_per_keys];
282     error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key);
283     assert(error == 0);
284     for (uint i = 0; i < tb_rec_per_keys; i++) {
285         assert(current_rec_per_key[i] == tb_rec_per_key[i]);
286     }
287 
288     error = txn->commit(txn, 0);
289     assert(error == 0);
290 
291     error = tokudb::close_status(&status_db);
292     assert(error == 0);
293 }
294 
test_drop_1_multiple_parts(DB_ENV * env)295 static void test_drop_1_multiple_parts(DB_ENV *env) {
296     int error;
297 
298     DB_TXN *txn = NULL;
299     error = env->txn_begin(env, NULL, &txn, 0);
300     assert(error == 0);
301 
302     DB *status_db = NULL;
303     error = tokudb::create_status(env, &status_db, "status_drop_1_multiple_parts", txn);
304     assert(error == 0);
305 
306     // define tables
307     const uint ta_keys = 3;
308     const uint ta_key_parts = 1+2+3;
309     const uint ta_rec_per_keys = ta_key_parts;
310     uint64_t ta_rec_per_key[ta_rec_per_keys] = {
311         1000, 2000, 2001, 3000, 3001, 3002,
312     };
313     KEY_INFO ta_key_info[ta_rec_per_keys] = {
314         { 0, 1, &ta_rec_per_key[0], (char *) "key_a" },
315         { 0, 2, &ta_rec_per_key[0+1], (char *) "key_b" },
316         { 0, 3, &ta_rec_per_key[0+1+2], (char *) "key_c" },
317     };
318     TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info };
319 
320     const uint tb_keys = 2;
321     const uint tb_key_parts = 1+3;
322     const int tb_rec_per_keys = tb_key_parts;
323     uint64_t tb_rec_per_key[tb_rec_per_keys] = {
324         1000, 3000, 3001, 3002,
325     };
326     KEY_INFO tb_key_info[tb_rec_per_keys] = {
327         { 0, 1, &tb_rec_per_key[0], (char *) "key_a" },
328         { 0, 3, &tb_rec_per_key[0+1], (char *) "key_c" },
329     };
330     TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info };
331 
332     // set initial cardinality
333     error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key);
334     assert(error == 0);
335 
336     error = tokudb::alter_card(status_db, txn, &ta, &tb);
337     assert(error == 0);
338 
339     // verify
340     uint64_t current_rec_per_key[tb_rec_per_keys];
341     error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key);
342     assert(error == 0);
343     for (uint i = 0; i < tb_rec_per_keys; i++) {
344         assert(current_rec_per_key[i] == tb_rec_per_key[i]);
345     }
346 
347     error = txn->commit(txn, 0);
348     assert(error == 0);
349 
350     error = tokudb::close_status(&status_db);
351     assert(error == 0);
352 }
353 
test_add_0(DB_ENV * env)354 static void test_add_0(DB_ENV *env) {
355     int error;
356 
357     DB_TXN *txn = NULL;
358     error = env->txn_begin(env, NULL, &txn, 0);
359     assert(error == 0);
360 
361     DB *status_db = NULL;
362     error = tokudb::create_status(env, &status_db, "status_add_0", txn);
363     assert(error == 0);
364 
365     // define tables
366     const uint ta_keys = 2;
367     const uint ta_key_parts = 1;
368     const uint ta_rec_per_keys = ta_keys * ta_key_parts;
369     uint64_t ta_rec_per_key[ta_rec_per_keys] = {
370         2000, 3000,
371     };
372     KEY_INFO ta_key_info[ta_rec_per_keys] = {
373         { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_b" },
374         { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_c" },
375     };
376     TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info };
377 
378     const uint tb_keys = 3;
379     const uint tb_key_parts = 1;
380     const int tb_rec_per_keys = tb_keys * tb_key_parts;
381     uint64_t tb_rec_per_key[tb_rec_per_keys] = {
382         0 /*not computed*/, 2000, 3000,
383     };
384     KEY_INFO tb_key_info[tb_rec_per_keys] = {
385         { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_a" },
386         { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_b" },
387         { 0, tb_key_parts, &tb_rec_per_key[2], (char *) "key_c" },
388     };
389     TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info };
390 
391     // set initial cardinality
392     error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key);
393     assert(error == 0);
394 
395     error = tokudb::alter_card(status_db, txn, &ta, &tb);
396     assert(error == 0);
397 
398     // verify
399     uint64_t current_rec_per_key[tb_rec_per_keys];
400     error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key);
401     assert(error == 0);
402     for (uint i = 0; i < tb_rec_per_keys; i++) {
403         assert(current_rec_per_key[i] == tb_rec_per_key[i]);
404     }
405 
406     error = txn->commit(txn, 0);
407     assert(error == 0);
408 
409     error = tokudb::close_status(&status_db);
410     assert(error == 0);
411 }
412 
test_add_1(DB_ENV * env)413 static void test_add_1(DB_ENV *env) {
414     int error;
415 
416     DB_TXN *txn = NULL;
417     error = env->txn_begin(env, NULL, &txn, 0);
418     assert(error == 0);
419 
420     DB *status_db = NULL;
421     error = tokudb::create_status(env, &status_db, "status_add_1", txn);
422     assert(error == 0);
423 
424     // define tables
425     const uint ta_keys = 2;
426     const uint ta_key_parts = 1;
427     const uint ta_rec_per_keys = ta_keys * ta_key_parts;
428     uint64_t ta_rec_per_key[ta_rec_per_keys] = {
429         2000, 3000,
430     };
431     KEY_INFO ta_key_info[ta_rec_per_keys] = {
432         { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_b" },
433         { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_c" },
434     };
435     TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info };
436 
437     const uint tb_keys = 3;
438     const uint tb_key_parts = 1;
439     const int tb_rec_per_keys = tb_keys * tb_key_parts;
440     uint64_t tb_rec_per_key[tb_rec_per_keys] = {
441         2000, 0 /*not computed*/, 3000,
442     };
443     KEY_INFO tb_key_info[tb_rec_per_keys] = {
444         { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_b" },
445         { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_a" },
446         { 0, tb_key_parts, &tb_rec_per_key[2], (char *) "key_c" },
447     };
448     TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info };
449 
450     // set initial cardinality
451     error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key);
452     assert(error == 0);
453 
454     error = tokudb::alter_card(status_db, txn, &ta, &tb);
455     assert(error == 0);
456 
457     // verify
458     uint64_t current_rec_per_key[tb_rec_per_keys];
459     error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key);
460     assert(error == 0);
461     for (uint i = 0; i < tb_rec_per_keys; i++) {
462         assert(current_rec_per_key[i] == tb_rec_per_key[i]);
463     }
464 
465     error = txn->commit(txn, 0);
466     assert(error == 0);
467 
468     error = tokudb::close_status(&status_db);
469     assert(error == 0);
470 }
471 
test_add_2(DB_ENV * env)472 static void test_add_2(DB_ENV *env) {
473     int error;
474 
475     DB_TXN *txn = NULL;
476     error = env->txn_begin(env, NULL, &txn, 0);
477     assert(error == 0);
478 
479     DB *status_db = NULL;
480     error = tokudb::create_status(env, &status_db, "status_add_2", txn);
481     assert(error == 0);
482 
483     // define tables
484     const uint ta_keys = 2;
485     const uint ta_key_parts = 1;
486     const uint ta_rec_per_keys = ta_keys * ta_key_parts;
487     uint64_t ta_rec_per_key[ta_rec_per_keys] = {
488         2000, 3000,
489     };
490     KEY_INFO ta_key_info[ta_rec_per_keys] = {
491         { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_b" },
492         { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_c" },
493     };
494     TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info };
495 
496     const uint tb_keys = 3;
497     const uint tb_key_parts = 1;
498     const int tb_rec_per_keys = tb_keys * tb_key_parts;
499     uint64_t tb_rec_per_key[tb_rec_per_keys] = {
500         2000, 3000, 0 /*not computed*/,
501     };
502     KEY_INFO tb_key_info[tb_rec_per_keys] = {
503         { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_b" },
504         { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_c" },
505         { 0, tb_key_parts, &tb_rec_per_key[2], (char *) "key_a" },
506     };
507     TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info };
508 
509     // set initial cardinality
510     error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key);
511     assert(error == 0);
512 
513     error = tokudb::alter_card(status_db, txn, &ta, &tb);
514     assert(error == 0);
515 
516     // verify
517     uint64_t current_rec_per_key[tb_rec_per_keys];
518     error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key);
519     assert(error == 0);
520     for (uint i = 0; i < tb_rec_per_keys; i++) {
521         assert(current_rec_per_key[i] == tb_rec_per_key[i]);
522     }
523 
524     error = txn->commit(txn, 0);
525     assert(error == 0);
526 
527     error = tokudb::close_status(&status_db);
528     assert(error == 0);
529 }
530 
test_add_0_multiple_parts(DB_ENV * env)531 static void test_add_0_multiple_parts(DB_ENV *env) {
532     int error;
533 
534     DB_TXN *txn = NULL;
535     error = env->txn_begin(env, NULL, &txn, 0);
536     assert(error == 0);
537 
538     DB *status_db = NULL;
539     error = tokudb::create_status(env, &status_db, "status_add_0_multiple_parts", txn);
540     assert(error == 0);
541 
542     // define tables
543     const uint ta_keys = 2;
544     const uint ta_key_parts = 3+4;
545     const uint ta_rec_per_keys = ta_key_parts;
546     uint64_t ta_rec_per_key[ta_rec_per_keys] = {
547         2000, 2001, 2002, 3000, 3001, 3002, 3003,
548     };
549     KEY_INFO ta_key_info[ta_rec_per_keys] = {
550         { 0, 3, &ta_rec_per_key[0], (char *) "key_b" },
551         { 0, 4, &ta_rec_per_key[3], (char *) "key_c" },
552     };
553     TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info };
554 
555     const uint tb_keys = 3;
556     const uint tb_key_parts = 2+3+4;
557     const int tb_rec_per_keys = tb_key_parts;
558     uint64_t tb_rec_per_key[tb_rec_per_keys] = {
559         0, 0 /*not computed*/, 2000, 2001, 2002, 3000, 3001, 3002, 3003,
560     };
561     KEY_INFO tb_key_info[tb_rec_per_keys] = {
562         { 0, 2, &tb_rec_per_key[0], (char *) "key_a" },
563         { 0, 3, &tb_rec_per_key[0+2], (char *) "key_b" },
564         { 0, 4, &tb_rec_per_key[0+2+3], (char *) "key_c" },
565     };
566     TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info };
567 
568     // set initial cardinality
569     error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key);
570     assert(error == 0);
571 
572     error = tokudb::alter_card(status_db, txn, &ta, &tb);
573     assert(error == 0);
574 
575     // verify
576     uint64_t current_rec_per_key[tb_rec_per_keys];
577     error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key);
578     assert(error == 0);
579     for (uint i = 0; i < tb_rec_per_keys; i++) {
580         assert(current_rec_per_key[i] == tb_rec_per_key[i]);
581     }
582 
583     error = txn->commit(txn, 0);
584     assert(error == 0);
585 
586     error = tokudb::close_status(&status_db);
587     assert(error == 0);
588 }
589 
main()590 int main() {
591     int error;
592 
593     error = system("rm -rf " __FILE__ ".testdir");
594     assert(error == 0);
595 
596     error = mkdir(__FILE__ ".testdir", S_IRWXU+S_IRWXG+S_IRWXO);
597     assert(error == 0);
598 
599     DB_ENV *env = NULL;
600     error = db_env_create(&env, 0);
601     assert(error == 0);
602 
603     error = env->open(env, __FILE__ ".testdir", DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
604     assert(error == 0);
605 
606     test_no_keys(env);
607     test_keys(env);
608     test_drop_0(env);
609     test_drop_1(env);
610     test_drop_2(env);
611     test_drop_1_multiple_parts(env);
612     test_add_0(env);
613     test_add_1(env);
614     test_add_2(env);
615     test_add_0_multiple_parts(env);
616 
617     error = env->close(env, 0);
618     assert(error == 0);
619 
620     return 0;
621 }
622