test-dirty-flushes-on-cleaner.c 7.17 KB
Newer Older
1 2
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: expandtab:ts=8:sw=4:softtabstop=4:
Leif Walsh's avatar
Leif Walsh committed
3 4 5 6 7 8 9
#ident "Copyright (c) 2007-2011 Tokutek Inc.  All rights reserved."
#ident "$Id$"
/* The goal of this test.  Make sure that inserts stay behind deletes. */


#include "test.h"
#include "includes.h"
10 11
#include <ft-cachetable-wrappers.h>
#include "ft-flusher.h"
Leif Walsh's avatar
Leif Walsh committed
12 13 14 15 16 17 18 19 20
#include "checkpoint.h"


static TOKUTXN const null_txn = 0;
static DB * const null_db = 0;

enum { NODESIZE = 1024, KSIZE=NODESIZE-100, TOKU_PSIZE=20 };

CACHETABLE ct;
21
FT_HANDLE brt;
Leif Walsh's avatar
Leif Walsh committed
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
int fnamelen;
char *fname;

static int update_func(
    DB* UU(db),
    const DBT* key,
    const DBT* old_val, 
    const DBT* UU(extra),
    void (*set_val)(const DBT *new_val, void *set_extra),
    void *set_extra)
{
    DBT new_val;
    assert(old_val->size > 0);
    if (verbose) {
        printf("applying update to %s\n", (char *)key->data);
    }
    toku_init_dbt(&new_val);
    set_val(&new_val, set_extra);
    return 0;
}


static void
doit (void) {
    BLOCKNUM node_leaf;
    BLOCKNUM node_internal, node_root;

    int r;
    
51
    fnamelen = strlen(__SRCFILE__) + 20;
Leif Walsh's avatar
Leif Walsh committed
52 53 54
    fname = toku_malloc(fnamelen);
    assert(fname!=0);

55 56
    snprintf(fname, fnamelen, "%s.ft_handle", __SRCFILE__);
    r = toku_create_cachetable(&ct, 500*1024*1024, ZERO_LSN, NULL_LOGGER); assert(r==0);
Leif Walsh's avatar
Leif Walsh committed
57
    unlink(fname);
58
    r = toku_open_ft_handle(fname, 1, &brt, NODESIZE, NODESIZE/2, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun);
Leif Walsh's avatar
Leif Walsh committed
59 60 61
    assert(r==0);
    toku_free(fname);

62 63
    brt->ft->update_fun = update_func;
    brt->ft->update_fun = update_func;
Leif Walsh's avatar
Leif Walsh committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
    
    toku_testsetup_initialize();  // must precede any other toku_testsetup calls

    char* pivots[1];
    pivots[0] = toku_strdup("kkkkk");
    int pivot_len = 6;

    r = toku_testsetup_leaf(brt, &node_leaf, 2, pivots, &pivot_len);
    assert(r==0);

    r = toku_testsetup_nonleaf(brt, 1, &node_internal, 1, &node_leaf, 0, 0);
    assert(r==0);

    r = toku_testsetup_nonleaf(brt, 2, &node_root, 1, &node_internal, 0, 0);
    assert(r==0);

    r = toku_testsetup_root(brt, node_root);
    assert(r==0);

    //
    // at this point we have created a tree with a root, an internal node,
    // and two leaf nodes, the pivot being "kkkkk"
    //

    // now we insert a row into each leaf node
    r = toku_testsetup_insert_to_leaf (
        brt, 
        node_leaf, 
        "a", // key
        2, // keylen
        "aa", 
        3
        );
    assert(r==0);
    r = toku_testsetup_insert_to_leaf (
        brt, 
        node_leaf, 
        "z", // key
        2, // keylen
        "zz", 
        3
        );
    assert(r==0);
    char filler[400];
    memset(filler, 0, sizeof(filler));
    // now we insert filler data so that the rebalance
    // keeps it at two nodes
    r = toku_testsetup_insert_to_leaf (
        brt, 
        node_leaf, 
        "b", // key
        2, // keylen
        filler, 
        sizeof(filler)
        );
    assert(r==0);
    r = toku_testsetup_insert_to_leaf (
        brt, 
        node_leaf, 
        "y", // key
        2, // keylen
        filler, 
        sizeof(filler)
        );
    assert(r==0);

    //
    // now insert a bunch of dummy delete messages
    // into the internal node, to get its cachepressure size up    
    //
    for (int i = 0; i < 100000; i++) {
        r = toku_testsetup_insert_to_nonleaf (
            brt, 
            node_internal, 
138
            FT_DELETE_ANY, 
Leif Walsh's avatar
Leif Walsh committed
139 140 141 142 143 144 145 146 147 148 149 150 151 152
            "jj", // this key does not exist, so its message application should be a no-op
            3, 
            NULL, 
            0
            );
        assert(r==0);
    }

    //
    // now insert a broadcast message into the root
    //
    r = toku_testsetup_insert_to_nonleaf (
        brt, 
        node_root, 
153
        FT_UPDATE_BROADCAST_ALL, 
Leif Walsh's avatar
Leif Walsh committed
154 155 156 157 158 159 160 161
        NULL, 
        0, 
        NULL, 
        0
        );
    assert(r==0);

    // now lock and release the leaf node to make sure it is what we expect it to be.
162 163
    FTNODE node = NULL;
    struct ftnode_fetch_extra bfe;
164
    fill_bfe_for_min_read(&bfe, brt->ft);
165
    toku_pin_ftnode_off_client_thread(
166
        brt->ft, 
Leif Walsh's avatar
Leif Walsh committed
167
        node_leaf,
168
        toku_cachetable_hash(brt->ft->cf, node_leaf),
Leif Walsh's avatar
Leif Walsh committed
169
        &bfe,
Zardosht Kasheff's avatar
Zardosht Kasheff committed
170
        TRUE, 
Leif Walsh's avatar
Leif Walsh committed
171 172 173 174 175 176 177 178
        0,
        NULL,
        &node
        );
    assert(node->dirty);
    assert(node->n_children == 2);
    assert(BP_STATE(node,0) == PT_AVAIL);
    assert(BP_STATE(node,1) == PT_AVAIL);
179
    toku_unpin_ftnode_off_client_thread(brt->ft, node);
Leif Walsh's avatar
Leif Walsh committed
180 181 182 183

    // now do a lookup on one of the keys, this should bring a leaf node up to date 
    DBT k;
    struct check_pair pair = {2, "a", 0, NULL, 0};
184
    r = toku_ft_lookup(brt, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair);
Leif Walsh's avatar
Leif Walsh committed
185 186 187 188 189 190 191 192
    assert(r==0);

    //
    // pin the leaf one more time
    // and make sure that one basement
    // node is in memory and another is
    // on disk
    //
193
    fill_bfe_for_min_read(&bfe, brt->ft);
194
    toku_pin_ftnode_off_client_thread(
195
        brt->ft, 
Leif Walsh's avatar
Leif Walsh committed
196
        node_leaf,
197
        toku_cachetable_hash(brt->ft->cf, node_leaf),
Leif Walsh's avatar
Leif Walsh committed
198
        &bfe,
Zardosht Kasheff's avatar
Zardosht Kasheff committed
199
        TRUE, 
Leif Walsh's avatar
Leif Walsh committed
200 201 202 203 204 205 206 207
        0,
        NULL,
        &node
        );
    assert(node->dirty);
    assert(node->n_children == 2);
    assert(BP_STATE(node,0) == PT_AVAIL);
    assert(BP_STATE(node,1) == PT_AVAIL);
208
    toku_unpin_ftnode_off_client_thread(brt->ft, node);
Leif Walsh's avatar
Leif Walsh committed
209 210 211 212
    
    //
    // now let us induce a clean on the internal node
    //    
213
    fill_bfe_for_min_read(&bfe, brt->ft);
214
    toku_pin_ftnode_off_client_thread(
215
        brt->ft, 
Leif Walsh's avatar
Leif Walsh committed
216
        node_internal,
217
        toku_cachetable_hash(brt->ft->cf, node_internal),
Leif Walsh's avatar
Leif Walsh committed
218
        &bfe,
Zardosht Kasheff's avatar
Zardosht Kasheff committed
219
        TRUE, 
Leif Walsh's avatar
Leif Walsh committed
220 221 222 223 224 225 226 227 228
        0,
        NULL,
        &node
        );
    assert(node->dirty);

    // we expect that this flushes its buffer, that
    // a merge is not done, and that the lookup
    // of values "a" and "z" still works
229
    r = toku_ftnode_cleaner_callback(
Leif Walsh's avatar
Leif Walsh committed
230 231
        node,
        node_internal,
232 233
        toku_cachetable_hash(brt->ft->cf, node_internal),
        brt->ft
Leif Walsh's avatar
Leif Walsh committed
234 235 236
        );

    // verify that node_internal's buffer is empty
237
    fill_bfe_for_min_read(&bfe, brt->ft);
238
    toku_pin_ftnode_off_client_thread(
239
        brt->ft, 
Leif Walsh's avatar
Leif Walsh committed
240
        node_internal,
241
        toku_cachetable_hash(brt->ft->cf, node_internal),
Leif Walsh's avatar
Leif Walsh committed
242
        &bfe,
Zardosht Kasheff's avatar
Zardosht Kasheff committed
243
        TRUE, 
Leif Walsh's avatar
Leif Walsh committed
244 245 246 247 248 249
        0,
        NULL,
        &node
        );
    // check that buffers are empty
    assert(toku_bnc_nbytesinbuf(BNC(node, 0)) == 0);
250
    toku_unpin_ftnode_off_client_thread(brt->ft, node);
Leif Walsh's avatar
Leif Walsh committed
251 252 253 254 255 256 257 258 259 260
    
    //
    // now run a checkpoint to get everything clean,
    // and to get the rebalancing to happen
    //
    r = toku_checkpoint(ct, NULL, NULL, NULL, NULL, NULL, CLIENT_CHECKPOINT);
    assert_zero(r);

    // check that lookups on the two keys is still good
    struct check_pair pair1 = {2, "a", 0, NULL, 0};
261
    r = toku_ft_lookup(brt, toku_fill_dbt(&k, "a", 2), lookup_checkf, &pair1);
Leif Walsh's avatar
Leif Walsh committed
262 263
    assert(r==0);
    struct check_pair pair2 = {2, "z", 0, NULL, 0};
264
    r = toku_ft_lookup(brt, toku_fill_dbt(&k, "z", 2), lookup_checkf, &pair2);
Leif Walsh's avatar
Leif Walsh committed
265 266 267
    assert(r==0);


268
    r = toku_close_ft_handle_nolsn(brt, 0);    assert(r==0);
Leif Walsh's avatar
Leif Walsh committed
269 270 271 272 273 274 275 276 277 278 279
    r = toku_cachetable_close(&ct); assert(r==0);

    toku_free(pivots[0]);
}

int
test_main (int argc __attribute__((__unused__)), const char *argv[] __attribute__((__unused__))) {
    default_parse_args(argc, argv);
    doit();
    return 0;
}