~ubuntu-branches/ubuntu/trusty/mariadb-5.5/trusty-proposed

« back to all changes in this revision

Viewing changes to storage/tokudb/ft-index/src/tests/hotindexer-undo-do-test.cc

  • Committer: Package Import Robot
  • Author(s): James Page, Otto Kekäläinen
  • Date: 2014-02-17 16:51:52 UTC
  • mfrom: (2.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20140217165152-k315d3175g865kkx
Tags: 5.5.35-1
[ Otto Kekäläinen ]
* New upstream release, fixing the following security issues:
  - Buffer overflow in client/mysql.cc (Closes: #737597).
    - CVE-2014-0001
  - http://www.oracle.com/technetwork/topics/security/cpujan2014-1972949.html
    - CVE-2013-5891
    - CVE-2013-5908
    - CVE-2014-0386
    - CVE-2014-0393
    - CVE-2014-0401
    - CVE-2014-0402
    - CVE-2014-0412
    - CVE-2014-0420
    - CVE-2014-0437
* Upstream https://mariadb.atlassian.net/browse/MDEV-4902
  fixes compatibility with Bison 3.0 (Closes: #733002)
* Updated Russian debconf translation (Closes: #734426)
* Updated Japanese debconf translation (Closes: #735284)
* Updated French debconf translation (Closes: #736480)
* Renamed SONAME properly (Closes: #732967)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 
2
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
 
3
/*
 
4
COPYING CONDITIONS NOTICE:
 
5
 
 
6
  This program is free software; you can redistribute it and/or modify
 
7
  it under the terms of version 2 of the GNU General Public License as
 
8
  published by the Free Software Foundation, and provided that the
 
9
  following conditions are met:
 
10
 
 
11
      * Redistributions of source code must retain this COPYING
 
12
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
 
13
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
 
14
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
 
15
        GRANT (below).
 
16
 
 
17
      * Redistributions in binary form must reproduce this COPYING
 
18
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
 
19
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
 
20
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
 
21
        GRANT (below) in the documentation and/or other materials
 
22
        provided with the distribution.
 
23
 
 
24
  You should have received a copy of the GNU General Public License
 
25
  along with this program; if not, write to the Free Software
 
26
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
27
  02110-1301, USA.
 
28
 
 
29
COPYRIGHT NOTICE:
 
30
 
 
31
  TokuDB, Tokutek Fractal Tree Indexing Library.
 
32
  Copyright (C) 2007-2013 Tokutek, Inc.
 
33
 
 
34
DISCLAIMER:
 
35
 
 
36
  This program is distributed in the hope that it will be useful, but
 
37
  WITHOUT ANY WARRANTY; without even the implied warranty of
 
38
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
39
  General Public License for more details.
 
40
 
 
41
UNIVERSITY PATENT NOTICE:
 
42
 
 
43
  The technology is licensed by the Massachusetts Institute of
 
44
  Technology, Rutgers State University of New Jersey, and the Research
 
45
  Foundation of State University of New York at Stony Brook under
 
46
  United States of America Serial No. 11/760379 and to the patents
 
47
  and/or patent applications resulting from it.
 
48
 
 
49
PATENT MARKING NOTICE:
 
50
 
 
51
  This software is covered by US Patent No. 8,185,551.
 
52
  This software is covered by US Patent No. 8,489,638.
 
53
 
 
54
PATENT RIGHTS GRANT:
 
55
 
 
56
  "THIS IMPLEMENTATION" means the copyrightable works distributed by
 
57
  Tokutek as part of the Fractal Tree project.
 
58
 
 
59
  "PATENT CLAIMS" means the claims of patents that are owned or
 
60
  licensable by Tokutek, both currently or in the future; and that in
 
61
  the absence of this license would be infringed by THIS
 
62
  IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
 
63
 
 
64
  "PATENT CHALLENGE" shall mean a challenge to the validity,
 
65
  patentability, enforceability and/or non-infringement of any of the
 
66
  PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
 
67
 
 
68
  Tokutek hereby grants to you, for the term and geographical scope of
 
69
  the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
 
70
  irrevocable (except as stated in this section) patent license to
 
71
  make, have made, use, offer to sell, sell, import, transfer, and
 
72
  otherwise run, modify, and propagate the contents of THIS
 
73
  IMPLEMENTATION, where such license applies only to the PATENT
 
74
  CLAIMS.  This grant does not include claims that would be infringed
 
75
  only as a consequence of further modifications of THIS
 
76
  IMPLEMENTATION.  If you or your agent or licensee institute or order
 
77
  or agree to the institution of patent litigation against any entity
 
78
  (including a cross-claim or counterclaim in a lawsuit) alleging that
 
79
  THIS IMPLEMENTATION constitutes direct or contributory patent
 
80
  infringement, or inducement of patent infringement, then any rights
 
81
  granted to you under this License shall terminate as of the date
 
82
  such litigation is filed.  If you or your agent or exclusive
 
83
  licensee institute or order or agree to the institution of a PATENT
 
84
  CHALLENGE, then Tokutek may terminate any rights granted to you
 
85
  under this License.
 
86
*/
 
87
 
 
88
#ident "Copyright (c) 2010-2013 Tokutek Inc.  All rights reserved."
 
89
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
 
90
#ident "$Id$"
 
91
 
 
92
// test the hotindexer undo do function
 
93
// read a description of the live transactions and a leafentry from a test file, run the undo do function,
 
94
// and print out the actions taken by the undo do function while processing the leafentry
 
95
 
 
96
#include "test.h"
 
97
 
 
98
#include <ft/tokuconst.h>
 
99
#include <ft/fttypes.h>
 
100
#include <ft/omt.h>
 
101
#include <ft/leafentry.h>
 
102
#include <ft/ule.h>
 
103
#include <ft/ule-internal.h>
 
104
#include <ft/le-cursor.h>
 
105
#include "indexer-internal.h"
 
106
#include <ft/xids-internal.h>
 
107
 
 
108
struct txn {
 
109
    TXNID xid;
 
110
    TOKUTXN_STATE state;
 
111
};
 
112
 
 
113
struct live {
 
114
    int n;
 
115
    int o;
 
116
    struct txn *txns;
 
117
};
 
118
 
 
119
static void
 
120
live_init(struct live *live) {
 
121
    live->n = live->o = 0;
 
122
    live->txns = NULL;
 
123
}
 
124
 
 
125
static void
 
126
live_destroy(struct live *live) {
 
127
    toku_free(live->txns);
 
128
}
 
129
 
 
130
static void
 
131
live_add(struct live *live, TXNID xid, TOKUTXN_STATE state) {
 
132
    if (live->o >= live->n) {
 
133
        int newn = live->n == 0 ? 1 : live->n * 2;
 
134
        live->txns = (struct txn *) toku_realloc(live->txns, newn * sizeof (struct txn));
 
135
        resource_assert(live->txns);
 
136
        live->n = newn;
 
137
    }
 
138
    live->txns[live->o++] = (struct txn ) { xid, state };
 
139
}
 
140
 
 
141
static TOKUTXN_STATE
 
142
lookup_txn_state(struct live *live, TXNID xid) {
 
143
    TOKUTXN_STATE r = TOKUTXN_RETIRED;
 
144
    for (int i = 0; i < live->o; i++) {
 
145
        if (live->txns[i].xid == xid) {
 
146
            r = live->txns[i].state;
 
147
            break;
 
148
        }
 
149
    }
 
150
    return r;
 
151
}
 
152
 
 
153
// live transaction ID set
 
154
struct live live_xids;
 
155
 
 
156
static void
 
157
uxr_init(UXR uxr, uint8_t type, void *val, uint32_t vallen, TXNID xid) {
 
158
    uxr->type = type;
 
159
    uxr->valp = toku_malloc(vallen); resource_assert(uxr->valp);
 
160
    memcpy(uxr->valp, val, vallen);
 
161
    uxr->vallen = vallen;
 
162
    uxr->xid = xid;
 
163
}
 
164
 
 
165
static void
 
166
uxr_destroy(UXR uxr) {
 
167
    toku_free(uxr->valp);
 
168
    uxr->valp = NULL;
 
169
}
 
170
 
 
171
static ULE
 
172
ule_init(ULE ule) {
 
173
    ule->num_puxrs = 0;
 
174
    ule->num_cuxrs = 0;
 
175
    ule->uxrs = ule->uxrs_static;
 
176
    return ule;
 
177
}
 
178
 
 
179
static void
 
180
ule_destroy(ULE ule) {
 
181
    for (unsigned int i = 0; i < ule->num_cuxrs + ule->num_puxrs; i++) {
 
182
        uxr_destroy(&ule->uxrs[i]);
 
183
    }
 
184
}
 
185
 
 
186
static void
 
187
ule_add_provisional(ULE ule, UXR uxr) {
 
188
    invariant(ule->num_cuxrs + ule->num_puxrs + 1 <= MAX_TRANSACTION_RECORDS*2);
 
189
    ule->uxrs[ule->num_cuxrs + ule->num_puxrs] = *uxr;
 
190
    ule->num_puxrs++;
 
191
}
 
192
 
 
193
static void
 
194
ule_add_committed(ULE ule, UXR uxr) {
 
195
    lazy_assert(ule->num_puxrs == 0);
 
196
    invariant(ule->num_cuxrs + 1 <= MAX_TRANSACTION_RECORDS*2);
 
197
    ule->uxrs[ule->num_cuxrs] = *uxr;
 
198
    ule->num_cuxrs++;
 
199
}
 
200
 
 
201
static ULE
 
202
ule_create(void) {
 
203
    ULE ule = (ULE) toku_calloc(1, sizeof (ULE_S)); resource_assert(ule);
 
204
    if (ule)
 
205
        ule_init(ule);
 
206
    return ule;
 
207
}
 
208
 
 
209
static void
 
210
ule_free(ULE ule) {
 
211
    ule_destroy(ule);
 
212
    toku_free(ule);
 
213
}
 
214
 
 
215
static void
 
216
print_xids(XIDS xids) {
 
217
    printf("[");
 
218
    if (xids->num_xids == 0)
 
219
        printf("0");
 
220
    else {
 
221
        for (int i = 0; i < xids->num_xids; i++) {
 
222
            printf("%" PRIu64, xids->ids[i]);
 
223
            if (i+1 < xids->num_xids)
 
224
                printf(",");
 
225
        }
 
226
    }
 
227
    printf("] ");
 
228
}
 
229
 
 
230
static void
 
231
print_dbt(DBT *dbt) {
 
232
    printf("%.*s ", dbt->size, (char *) dbt->data);
 
233
}
 
234
 
 
235
static int
 
236
put_callback(DB *dest_db, DB *src_db, DBT_ARRAY *dest_keys, DBT_ARRAY *dest_vals, const DBT *src_key, const DBT *src_val) {
 
237
    toku_dbt_array_resize(dest_keys, 1);
 
238
    toku_dbt_array_resize(dest_vals, 1);
 
239
    DBT *dest_key = &dest_keys->dbts[0];
 
240
    DBT *dest_val = &dest_vals->dbts[0];
 
241
    (void) dest_db; (void) src_db; (void) dest_key; (void) dest_val; (void) src_key; (void) src_val;
 
242
 
 
243
    lazy_assert(src_db != NULL && dest_db != NULL);
 
244
 
 
245
    switch (dest_key->flags) {
 
246
    case 0:
 
247
        dest_key->data = src_val->data;
 
248
        dest_key->size = src_val->size;
 
249
        break;
 
250
    case DB_DBT_REALLOC:
 
251
        dest_key->data = toku_realloc(dest_key->data, src_val->size);
 
252
        memcpy(dest_key->data, src_val->data, src_val->size);
 
253
        dest_key->size = src_val->size;
 
254
        break;
 
255
    default:
 
256
        lazy_assert(0);
 
257
    }
 
258
 
 
259
    if (dest_val)
 
260
        switch (dest_val->flags) {
 
261
        case 0:
 
262
            lazy_assert(0);
 
263
            break;
 
264
        case DB_DBT_REALLOC:
 
265
            dest_val->data = toku_realloc(dest_val->data, src_key->size);
 
266
            memcpy(dest_val->data, src_key->data, src_key->size);
 
267
            dest_val->size = src_key->size;
 
268
            break;
 
269
        default:
 
270
            lazy_assert(0);
 
271
        }
 
272
 
 
273
    return 0;
 
274
}
 
275
 
 
276
static int
 
277
del_callback(DB *dest_db, DB *src_db, DBT_ARRAY *dest_keys, const DBT *src_key, const DBT *src_data) {
 
278
    toku_dbt_array_resize(dest_keys, 1);
 
279
    DBT *dest_key = &dest_keys->dbts[0];
 
280
    (void) dest_db; (void) src_db; (void) dest_key; (void) src_key; (void) src_data;
 
281
 
 
282
    lazy_assert(src_db != NULL && dest_db != NULL);
 
283
 
 
284
    switch (dest_key->flags) {
 
285
    case 0:
 
286
        dest_key->data = src_data->data;
 
287
        dest_key->size = src_data->size;
 
288
        break;
 
289
    case DB_DBT_REALLOC:
 
290
        dest_key->data = toku_realloc(dest_key->data, src_data->size);
 
291
        memcpy(dest_key->data, src_data->data, src_data->size);
 
292
        dest_key->size = src_data->size;
 
293
        break;
 
294
    default:
 
295
        lazy_assert(0);
 
296
    }
 
297
    return 0;
 
298
}
 
299
 
 
300
 
 
301
static DB_INDEXER *test_indexer = NULL;
 
302
static DB *test_hotdb = NULL;
 
303
 
 
304
static TOKUTXN_STATE
 
305
test_xid_state(DB_INDEXER *indexer, TXNID xid) {
 
306
    invariant(indexer == test_indexer);
 
307
    TOKUTXN_STATE r = lookup_txn_state(&live_xids, xid);
 
308
    return r;
 
309
}
 
310
 
 
311
static void 
 
312
test_lock_key(DB_INDEXER *indexer, TXNID xid, DB *hotdb, DBT *key) {
 
313
    invariant(indexer == test_indexer);
 
314
    invariant(hotdb == test_hotdb);
 
315
    TOKUTXN_STATE txn_state = test_xid_state(indexer, xid);
 
316
    invariant(txn_state == TOKUTXN_LIVE || txn_state == TOKUTXN_PREPARING);
 
317
    printf("lock [%" PRIu64 "] ", xid);
 
318
    print_dbt(key);
 
319
    printf("\n");
 
320
}
 
321
 
 
322
static int 
 
323
test_delete_provisional(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, XIDS xids) {
 
324
    invariant(indexer == test_indexer);
 
325
    invariant(hotdb == test_hotdb);
 
326
    printf("delete_provisional ");
 
327
    print_xids(xids);
 
328
    print_dbt(hotkey);
 
329
    printf("\n");
 
330
    return 0;
 
331
}
 
332
 
 
333
static int
 
334
test_delete_committed(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, XIDS xids) {
 
335
    invariant(indexer == test_indexer);
 
336
    invariant(hotdb == test_hotdb);
 
337
    printf("delete_committed ");
 
338
    print_xids(xids);
 
339
    print_dbt(hotkey);
 
340
    printf("\n");
 
341
    return 0;
 
342
}
 
343
 
 
344
static int 
 
345
test_insert_provisional(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, DBT *hotval, XIDS xids) {
 
346
    invariant(indexer == test_indexer);
 
347
    invariant(hotdb == test_hotdb);
 
348
    printf("insert_provisional ");
 
349
    print_xids(xids);
 
350
    print_dbt(hotkey);
 
351
    print_dbt(hotval);
 
352
    printf("\n");
 
353
    return 0;
 
354
}
 
355
 
 
356
static int 
 
357
test_insert_committed(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, DBT *hotval, XIDS xids) {
 
358
    invariant(indexer == test_indexer);
 
359
    invariant(hotdb == test_hotdb);
 
360
    printf("insert_committed ");
 
361
    print_xids(xids);
 
362
    print_dbt(hotkey);
 
363
    print_dbt(hotval);
 
364
    printf("\n");
 
365
    return 0;
 
366
}
 
367
 
 
368
static int
 
369
test_commit_any(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, XIDS xids) {
 
370
    invariant(indexer == test_indexer);
 
371
    invariant(hotdb == test_hotdb);
 
372
    printf("commit_any ");
 
373
    print_xids(xids);
 
374
    print_dbt(hotkey);
 
375
    printf("\n");
 
376
    return 0;
 
377
}
 
378
 
 
379
static int
 
380
split_fields(char *line, char *fields[], int maxfields) {
 
381
    int i;
 
382
    for (i = 0; i < maxfields; i++, line = NULL) {
 
383
        fields[i] = strtok(line, " ");
 
384
        if (fields[i] == NULL) 
 
385
            break;
 
386
    }
 
387
    return i;
 
388
}
 
389
 
 
390
static int
 
391
read_line(char **line_ptr, size_t *len_ptr, FILE *f) {
 
392
    char *line = *line_ptr;
 
393
    size_t len = 0;
 
394
    bool in_comment = false;
 
395
    while (1) {
 
396
        int c = fgetc(f);
 
397
        if (c == EOF)
 
398
            break;
 
399
        else if (c == '\n') {
 
400
            in_comment = false;
 
401
            if (len > 0)
 
402
                break;
 
403
        } else {
 
404
            if (c == '#')
 
405
                in_comment = true;
 
406
            if (!in_comment) {
 
407
                XREALLOC_N(len+1, line);
 
408
                line[len++] = c;
 
409
            }
 
410
        }
 
411
    }
 
412
    if (len > 0) {
 
413
        XREALLOC_N(len+1, line);
 
414
        line[len] = '\0';
 
415
    }
 
416
    *line_ptr = line;
 
417
    *len_ptr = len;
 
418
    return len == 0 ? -1 : 0;
 
419
}
 
420
 
 
421
struct saved_lines_t {
 
422
    char** savedlines;
 
423
    uint32_t capacity;
 
424
    uint32_t used;
 
425
};
 
426
 
 
427
static void
 
428
save_line(char** line, saved_lines_t* saved) {
 
429
    if (saved->capacity == saved->used) {
 
430
        if (saved->capacity == 0) {
 
431
            saved->capacity = 1;
 
432
        }
 
433
        saved->capacity *= 2;
 
434
        XREALLOC_N(saved->capacity, saved->savedlines);
 
435
    }
 
436
    saved->savedlines[saved->used++] = *line;
 
437
    *line = nullptr;
 
438
}
 
439
 
 
440
static int
 
441
read_test(char *testname, ULE ule, DBT* key, saved_lines_t* saved) {
 
442
    int r = 0;
 
443
    FILE *f = fopen(testname, "r");
 
444
    if (f) {
 
445
        char *line = NULL;
 
446
        size_t len = 0;
 
447
        while (read_line(&line, &len, f) != -1) {
 
448
            // printf("%s", line);
 
449
 
 
450
            const int maxfields = 8;
 
451
            char *fields[maxfields];
 
452
            int nfields = split_fields(line, fields, maxfields);
 
453
            // for (int i = 0; i < nfields; i++); printf("%s ", fields[i]); printf("\n");
 
454
 
 
455
            if (nfields < 1)
 
456
                continue;
 
457
            // live xid...
 
458
            if (strcmp(fields[0], "live") == 0) {
 
459
                for (int i = 1; i < nfields; i++)
 
460
                    live_add(&live_xids, atoll(fields[i]), TOKUTXN_LIVE);
 
461
                continue;
 
462
            }
 
463
            // xid <XID> [live|committing|aborting]
 
464
            if (strcmp(fields[0], "xid") == 0 && nfields == 3) {
 
465
                TXNID xid = atoll(fields[1]);
 
466
                TOKUTXN_STATE state = TOKUTXN_RETIRED;
 
467
                if (strcmp(fields[2], "live") == 0)
 
468
                    state = TOKUTXN_LIVE;
 
469
                else if (strcmp(fields[2], "preparing") == 0)
 
470
                    state = TOKUTXN_PREPARING;
 
471
                else if (strcmp(fields[2], "committing") == 0)
 
472
                    state = TOKUTXN_COMMITTING;
 
473
                else if (strcmp(fields[2], "aborting") == 0)
 
474
                    state = TOKUTXN_ABORTING;
 
475
                else
 
476
                    assert(0);
 
477
                live_add(&live_xids, xid, state);
 
478
                continue;
 
479
            }
 
480
            // key KEY
 
481
            if (strcmp(fields[0], "key") == 0 && nfields == 2) {
 
482
                save_line(&line, saved);
 
483
                dbt_init(key, fields[1], strlen(fields[1]));
 
484
                continue;
 
485
            }
 
486
            // insert committed|provisional XID DATA
 
487
            if (strcmp(fields[0], "insert") == 0 && nfields == 4) {
 
488
                save_line(&line, saved);
 
489
                UXR_S uxr_s; 
 
490
                uxr_init(&uxr_s, XR_INSERT, fields[3], strlen(fields[3]), atoll(fields[2]));
 
491
                if (fields[1][0] == 'p')
 
492
                    ule_add_provisional(ule, &uxr_s);
 
493
                if (fields[1][0] == 'c')
 
494
                    ule_add_committed(ule, &uxr_s);
 
495
                continue;
 
496
            }
 
497
            // delete committed|provisional XID
 
498
            if (strcmp(fields[0], "delete") == 0 && nfields == 3) {
 
499
                UXR_S uxr_s; 
 
500
                uxr_init(&uxr_s, XR_DELETE, NULL, 0, atoll(fields[2]));
 
501
                if (fields[1][0] == 'p')
 
502
                    ule_add_provisional(ule, &uxr_s);
 
503
                if (fields[1][0] == 'c')
 
504
                    ule_add_committed(ule, &uxr_s);
 
505
                continue;
 
506
            }
 
507
            // placeholder XID
 
508
            if (strcmp(fields[0], "placeholder") == 0 && nfields == 2) {
 
509
                UXR_S uxr_s; 
 
510
                uxr_init(&uxr_s, XR_PLACEHOLDER, NULL, 0, atoll(fields[1]));
 
511
                ule_add_provisional(ule, &uxr_s);
 
512
                continue;
 
513
            }
 
514
            // placeholder provisional XID
 
515
            if (strcmp(fields[0], "placeholder") == 0 && nfields == 3 && fields[1][0] == 'p') {
 
516
                UXR_S uxr_s; 
 
517
                uxr_init(&uxr_s, XR_PLACEHOLDER, NULL, 0, atoll(fields[2]));
 
518
                ule_add_provisional(ule, &uxr_s);
 
519
                continue;
 
520
            }
 
521
            fprintf(stderr, "%s???\n", line);
 
522
            r = EINVAL;
 
523
        }
 
524
        toku_free(line);
 
525
        fclose(f);
 
526
    } else {
 
527
        r = errno;
 
528
        fprintf(stderr, "fopen %s errno=%d\n", testname, errno);
 
529
    }
 
530
    return r;
 
531
 }
 
532
 
 
533
static int
 
534
run_test(char *envdir, char *testname) {
 
535
    if (verbose)
 
536
        printf("%s\n", testname);
 
537
 
 
538
    live_init(&live_xids);
 
539
 
 
540
    int r;
 
541
    DB_ENV *env = NULL;
 
542
    r = db_env_create(&env, 0); assert_zero(r);
 
543
    r = env->set_redzone(env, 0); assert_zero(r);
 
544
 
 
545
    r = env->set_generate_row_callback_for_put(env, put_callback); assert_zero(r);
 
546
    r = env->set_generate_row_callback_for_del(env, del_callback); assert_zero(r);
 
547
 
 
548
    r = env->open(env, envdir, DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE, S_IRWXU+S_IRWXG+S_IRWXO); assert_zero(r);
 
549
 
 
550
    DB *src_db = NULL;
 
551
    r = db_create(&src_db, env, 0); assert_zero(r);
 
552
    r = src_db->open(src_db, NULL, "0.tdb", NULL, DB_BTREE, DB_AUTO_COMMIT+DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert_zero(r);
 
553
 
 
554
    DB *dest_db = NULL;
 
555
    r = db_create(&dest_db, env, 0); assert_zero(r);
 
556
    r = dest_db->open(dest_db, NULL, "1.tdb", NULL, DB_BTREE, DB_AUTO_COMMIT+DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert_zero(r);
 
557
 
 
558
    DB_TXN *txn = NULL;
 
559
    r = env->txn_begin(env, NULL, &txn, 0); assert_zero(r);
 
560
 
 
561
    DB_INDEXER *indexer = NULL;
 
562
    r = env->create_indexer(env, txn, &indexer, src_db, 1, &dest_db, NULL, 0); assert_zero(r);
 
563
 
 
564
    // set test callbacks
 
565
    indexer->i->test_xid_state = test_xid_state;
 
566
    indexer->i->test_lock_key = test_lock_key;
 
567
    indexer->i->test_delete_provisional = test_delete_provisional;
 
568
    indexer->i->test_delete_committed = test_delete_committed;
 
569
    indexer->i->test_insert_provisional = test_insert_provisional;
 
570
    indexer->i->test_insert_committed = test_insert_committed;
 
571
    indexer->i->test_commit_any = test_commit_any;
 
572
 
 
573
    // verify indexer and hotdb in the callbacks
 
574
    test_indexer = indexer;
 
575
    test_hotdb = dest_db;
 
576
 
 
577
    // create a ule
 
578
    ULE ule = ule_create(); 
 
579
    ule_init(ule);
 
580
 
 
581
    saved_lines_t saved;
 
582
    ZERO_STRUCT(saved);
 
583
    // read the test
 
584
    DBT key;
 
585
    ZERO_STRUCT(key);
 
586
    r = read_test(testname, ule, &key, &saved);
 
587
    if (r != 0)
 
588
        return r;
 
589
 
 
590
    r = indexer->i->undo_do(indexer, dest_db, &key, ule); assert_zero(r);
 
591
 
 
592
    ule_free(ule);
 
593
    key.data = NULL;
 
594
 
 
595
    for (uint32_t i = 0; i < saved.used; i++) {
 
596
        toku_free(saved.savedlines[i]);
 
597
    }
 
598
    toku_free(saved.savedlines);
 
599
 
 
600
    r = indexer->close(indexer); assert_zero(r);
 
601
 
 
602
    r = txn->abort(txn); assert_zero(r);
 
603
 
 
604
    r = src_db->close(src_db, 0); assert_zero(r);
 
605
    r = dest_db->close(dest_db, 0); assert_zero(r);
 
606
 
 
607
    r = env->close(env, 0); assert_zero(r);
 
608
 
 
609
    live_destroy(&live_xids);
 
610
    
 
611
    return r;
 
612
}
 
613
 
 
614
int
 
615
test_main(int argc, char * const argv[]) {
 
616
    int r;
 
617
 
 
618
    // parse_args(argc, argv);
 
619
    int i;
 
620
    for (i = 1; i < argc; i++) {
 
621
        char * const arg = argv[i];
 
622
        if (strcmp(arg, "-v") == 0) {
 
623
            verbose++;
 
624
            continue;
 
625
        }
 
626
        if (strcmp(arg, "-q") == 0) {
 
627
            verbose = 0;
 
628
            continue;
 
629
        }
 
630
        
 
631
        break;
 
632
    }
 
633
 
 
634
    toku_os_recursive_delete(TOKU_TEST_FILENAME);
 
635
    r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
 
636
    assert_zero(r);
 
637
    for (r = 0 ; r == 0 && i < argc; i++) {
 
638
        char *testname = argv[i];
 
639
        char pid[10];
 
640
        sprintf(pid, "%d", toku_os_getpid());
 
641
        char envdir[TOKU_PATH_MAX+1];
 
642
        toku_path_join(envdir, 2, TOKU_TEST_FILENAME, pid);
 
643
 
 
644
        toku_os_recursive_delete(envdir);
 
645
        r = toku_os_mkdir(envdir, S_IRWXU+S_IRWXG+S_IRWXO); assert_zero(r);
 
646
 
 
647
        r = run_test(envdir, testname);
 
648
    }
 
649
 
 
650
    return r;
 
651
}
 
652