verify-misrouted-msgs.c 5.83 KB
Newer Older
1
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
// vim: expandtab:ts=8:sw=4:softtabstop=4:
3
#ident "$Id$"
4 5 6 7 8 9
#ident "Copyright (c) 2011 Tokutek Inc.  All rights reserved."

// generate a tree with misrouted messages in the child buffers.
// check that brt verify finds them.

#include "includes.h"
10
#include <ft-cachetable-wrappers.h>
11 12
#include "test.h"

13 14 15
static FTNODE
make_node(FT_HANDLE brt, int height) {
    FTNODE node = NULL;
16
    int n_children = (height == 0) ? 1 : 0;
17
    toku_create_new_ftnode(brt, &node, height, n_children);
18
    if (n_children) BP_STATE(node,0) = PT_AVAIL;
19 20 21 22
    return node;
}

static void
23
append_leaf(FTNODE leafnode, void *key, size_t keylen, void *val, size_t vallen) {
24 25 26 27 28 29
    assert(leafnode->height == 0);

    DBT thekey; toku_fill_dbt(&thekey, key, keylen);
    DBT theval; toku_fill_dbt(&theval, val, vallen);

    // get an index that we can use to create a new leaf entry
30
    uint32_t idx = toku_omt_size(BLB_BUFFER(leafnode, 0));
31 32

    // apply an insert to the leaf node
33
    MSN msn = next_dummymsn();
34 35
    FT_MSG_S cmd = { FT_INSERT, msn, xids_get_root_xids(), .u.id = { &thekey, &theval } };
    toku_ft_bn_apply_cmd_once(BLB(leafnode,0), &cmd, idx, NULL, NULL, NULL);
36 37 38 39 40 41

    // dont forget to dirty the node
    leafnode->dirty = 1;
}

static void
42
populate_leaf(FTNODE leafnode, int seq, int n, int *minkey, int *maxkey) {
43 44 45 46 47 48 49 50 51 52
    for (int i = 0; i < n; i++) {
        int k = htonl(seq + i);
        int v = seq + i;
        append_leaf(leafnode, &k, sizeof k, &v, sizeof v);
    }
    *minkey = htonl(seq);
    *maxkey = htonl(seq + n - 1);
}

static void
53
insert_into_child_buffer(FT_HANDLE brt, FTNODE node, int childnum, int minkey, int maxkey) {
54 55 56 57 58 59
    int k = htonl(maxkey);
    maxkey = htonl(k+1);
    for (unsigned int val = htonl(minkey); val <= htonl(maxkey); val++) {
        unsigned int key = htonl(val);
        DBT thekey; toku_fill_dbt(&thekey, &key, sizeof key);
        DBT theval; toku_fill_dbt(&theval, &val, sizeof val);
60
	MSN msn = next_dummymsn();
61
        toku_ft_append_to_child_buffer(brt->h->compare_fun, NULL, node, childnum, FT_INSERT, msn, xids_get_root_xids(), true, &thekey, &theval);
62 63 64
    }
}

65 66 67
static FTNODE
make_tree(FT_HANDLE brt, int height, int fanout, int nperleaf, int *seq, int *minkey, int *maxkey) {
    FTNODE node;
68 69 70 71 72 73 74 75
    if (height == 0) {
        node = make_node(brt, 0);
        populate_leaf(node, *seq, nperleaf, minkey, maxkey);
        *seq += nperleaf;
    } else {
        node = make_node(brt, height);
        int minkeys[fanout], maxkeys[fanout];
        for (int childnum = 0; childnum < fanout; childnum++) {
76
            FTNODE child = make_tree(brt, height-1, fanout, nperleaf, seq, &minkeys[childnum], &maxkeys[childnum]);
77
            if (childnum == 0) {
78
                toku_ft_nonleaf_append_child(node, child, NULL);
79
            } else {
80
                int k = maxkeys[childnum-1]; // use the max of the left tree
81
                DBT pivotkey;
82
                toku_ft_nonleaf_append_child(node, child, toku_fill_dbt(&pivotkey, toku_xmemdup(&k, sizeof k), sizeof k));
83
            }
84
            toku_unpin_ftnode(brt->h, child);
85
            insert_into_child_buffer(brt, node, childnum, minkeys[childnum], maxkeys[childnum]);
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
        }
        *minkey = minkeys[0];
        *maxkey = maxkeys[0];
        for (int i = 1; i < fanout; i++) {
            if (memcmp(minkey, &minkeys[i], sizeof minkeys[i]) > 0)
                *minkey = minkeys[i];
            if (memcmp(maxkey, &maxkeys[i], sizeof maxkeys[i]) < 0)
                *maxkey = maxkeys[i];
        }
    }
    return node;
}

static UU() void
deleted_row(UU() DB *db, UU() DBT *key, UU() DBT *val) {
}

static void 
test_make_tree(int height, int fanout, int nperleaf, int do_verify) {
    int r;

    // cleanup
108
    char fname[]= __SRCFILE__ ".ft_handle";
109 110 111 112 113
    r = unlink(fname);
    assert(r == 0 || (r == -1 && errno == ENOENT));

    // create a cachetable
    CACHETABLE ct = NULL;
114
    r = toku_create_cachetable(&ct, 0, ZERO_LSN, NULL_LOGGER);
115 116 117 118
    assert(r == 0);

    // create the brt
    TOKUTXN null_txn = NULL;
119 120
    FT_HANDLE brt = NULL;
    r = toku_open_ft_handle(fname, 1, &brt, 1024, 256, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
121 122 123 124
    assert(r == 0);

    // make a tree
    int seq = 0, minkey, maxkey;
125
    FTNODE newroot = make_tree(brt, height, fanout, nperleaf, &seq, &minkey, &maxkey);
126 127 128

    // discard the old root block
    // set the new root to point to the new tree
129
    toku_ft_set_new_root_blocknum(brt->h, newroot->thisnodename);
130 131

    // unpin the new root
132
    toku_unpin_ftnode(brt->h, newroot);
133 134

    if (do_verify) {
135
        r = toku_verify_ft(brt);
136 137 138 139
        assert(r != 0);
    }

    // flush to the file system
140
    r = toku_close_ft_handle_nolsn(brt, 0);     
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
    assert(r == 0);

    // shutdown the cachetable
    r = toku_cachetable_close(&ct);
    assert(r == 0);
}

static int
usage(void) {
    return 1;
}

int
test_main (int argc , const char *argv[]) {
    int height = 1;
    int fanout = 2;
    int nperleaf = 8;
    int do_verify = 1;
159
    initialize_dummymsn();
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
    for (int i = 1; i < argc; i++) {
        const char *arg = argv[i];
        if (strcmp(arg, "-v") == 0) {
            verbose++;
            continue;
        }
        if (strcmp(arg, "-q") == 0) {
            verbose = 0;
            continue;
        }
        if (strcmp(arg, "--height") == 0 && i+1 < argc) {
            height = atoi(argv[++i]);
            continue;
        }
        if (strcmp(arg, "--fanout") == 0 && i+1 < argc) {
            fanout = atoi(argv[++i]);
            continue;
        }
        if (strcmp(arg, "--nperleaf") == 0 && i+1 < argc) {
            nperleaf = atoi(argv[++i]);
            continue;
        }
        if (strcmp(arg, "--verify") == 0 && i+1 < argc) {
            do_verify = atoi(argv[++i]);
            continue;
        }
        return usage();
    }
    test_make_tree(height, fanout, nperleaf, do_verify);
    return 0;
}