cachetable-checkpointer-class.cc 7.92 KB
Newer Older
Zardosht Kasheff's avatar
Zardosht Kasheff committed
1 2 3 4 5 6 7 8
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id: cachetable-checkpointer_test.cc 45903 2012-07-19 13:06:39Z leifwalsh $"
#ident "Copyright (c) 2007-2012 Tokutek Inc.  All rights reserved."

#include "includes.h"
#include "test.h"
#include "cachetable-internal.h"
9
#include "cachetable-test.h"
Zardosht Kasheff's avatar
Zardosht Kasheff committed
10 11 12 13 14 15 16 17

//
// Wrapper for the checkpointer and necessary
// data to run the tests.
//
struct checkpointer_test {
  checkpointer m_cp;
  pair_list m_pl;
18

19
  // Tests
Zardosht Kasheff's avatar
Zardosht Kasheff committed
20 21 22
  void test_begin_checkpoint();
  void test_pending_bits();
  void test_end_checkpoint();
23

24
  // Test Helper
25 26
  void add_pairs(struct cachefile *cf,
    ctpair pairs[],
27 28
    uint32_t count,
    uint32_t k);
Zardosht Kasheff's avatar
Zardosht Kasheff committed
29 30 31 32 33 34 35 36 37
};

//------------------------------------------------------------------------------
// test_begin_checkpoint() -
//
// Description:
//
void checkpointer_test::test_begin_checkpoint() {
    cachefile_list cfl;
38
    ZERO_STRUCT(cfl);
Zardosht Kasheff's avatar
Zardosht Kasheff committed
39
    cfl.init();
40

Zardosht Kasheff's avatar
Zardosht Kasheff committed
41
    cachetable ctbl;
42
    ZERO_STRUCT(ctbl);
Zardosht Kasheff's avatar
Zardosht Kasheff committed
43
    ctbl.list.init();
44

45
    ZERO_STRUCT(m_cp);
46
    m_cp.init(&ctbl.list, NULL, &ctbl.ev, &cfl);
Zardosht Kasheff's avatar
Zardosht Kasheff committed
47 48

    // 1. Call checkpoint with NO cachefiles.
49
    m_cp.begin_checkpoint();
50

Zardosht Kasheff's avatar
Zardosht Kasheff committed
51 52 53 54 55 56 57
    // 2. Call checkpoint with ONE cachefile.
    //cachefile cf;
    struct cachefile cf;
    cf.next = NULL;
    cf.for_checkpoint = false;
    m_cp.m_cf_list->m_head = &cf;
    create_dummy_functions(&cf);
58

59
    m_cp.begin_checkpoint();
Zardosht Kasheff's avatar
Zardosht Kasheff committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
    assert(m_cp.m_checkpoint_num_files == 1);
    assert(cf.for_checkpoint == true);

    // 3. Call checkpoint with MANY cachefiles.
    const uint32_t count = 3;
    struct cachefile cfs[count];
    m_cp.m_cf_list->m_head = &cfs[0];
    for (uint32_t i = 0; i < count; ++i) {
        cfs[i].for_checkpoint = false;
        create_dummy_functions(&cfs[i]);
        if (i == count - 1) {
            cfs[i].next = NULL;
        } else {
            cfs[i].next = &cfs[i + 1];
        }
    }
76

77
    m_cp.begin_checkpoint();
Zardosht Kasheff's avatar
Zardosht Kasheff committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
    assert(m_cp.m_checkpoint_num_files == count);
    for (uint32_t i = 0; i < count; ++i) {
        assert(cfs[i].for_checkpoint == true);
    }
    ctbl.list.destroy();
    m_cp.destroy();
}

//------------------------------------------------------------------------------
// test_pending_bits() -
//
// Description:
//
void checkpointer_test::test_pending_bits() {
    cachefile_list cfl;
93
    ZERO_STRUCT(cfl);
Zardosht Kasheff's avatar
Zardosht Kasheff committed
94
    cfl.init();
95

Zardosht Kasheff's avatar
Zardosht Kasheff committed
96
    cachetable ctbl;
97
    ZERO_STRUCT(ctbl);
Zardosht Kasheff's avatar
Zardosht Kasheff committed
98
    ctbl.list.init();
99

100
    ZERO_STRUCT(m_cp);
101 102
    m_cp.init(&ctbl.list, NULL, &ctbl.ev, &cfl);

Zardosht Kasheff's avatar
Zardosht Kasheff committed
103 104 105 106
    //
    // 1. Empty hash chain.
    //
    m_cp.turn_on_pending_bits();
107

Zardosht Kasheff's avatar
Zardosht Kasheff committed
108 109 110 111
    //
    // 2. One entry in pair chain
    //
    struct cachefile cf;
112
    cf.cachetable = &ctbl;
Zardosht Kasheff's avatar
Zardosht Kasheff committed
113 114 115 116 117
    memset(&cf, 0, sizeof(cf));
    cf.next = NULL;
    cf.for_checkpoint = true;
    m_cp.m_cf_list->m_head = &cf;
    create_dummy_functions(&cf);
118

Zardosht Kasheff's avatar
Zardosht Kasheff committed
119 120 121
    CACHEKEY k;
    k.b = 0;
    uint32_t hash = toku_cachetable_hash(&cf, k);
122

Zardosht Kasheff's avatar
Zardosht Kasheff committed
123 124
    ctpair p;
    CACHETABLE_WRITE_CALLBACK cb;
125

Zardosht Kasheff's avatar
Zardosht Kasheff committed
126 127 128 129 130 131 132
    pair_attr_s attr;
    attr.size = 0;
    attr.nonleaf_size = 0;
    attr.leaf_size = 0;
    attr.rollback_size = 0;
    attr.cache_pressure_size = 0;
    attr.is_valid = true;
133

Leif Walsh's avatar
Leif Walsh committed
134
    ZERO_STRUCT(p);
135 136 137 138 139
    pair_init(&p,
        &cf,
        k,
        NULL,
        attr,
Zardosht Kasheff's avatar
Zardosht Kasheff committed
140 141
        CACHETABLE_CLEAN,
        hash,
142 143
        cb,
        NULL,
Zardosht Kasheff's avatar
Zardosht Kasheff committed
144 145
        &ctbl.list);

146
    m_cp.m_list->put(&p);
147

Zardosht Kasheff's avatar
Zardosht Kasheff committed
148 149
    m_cp.turn_on_pending_bits();
    assert(p.checkpoint_pending);
150
    m_cp.m_list->evict(&p);
151

Zardosht Kasheff's avatar
Zardosht Kasheff committed
152 153 154 155
    //
    // 3. Many hash chain entries.
    //
    const uint32_t count = 3;
156
    ctpair pairs[count];
Leif Walsh's avatar
Leif Walsh committed
157
    ZERO_ARRAY(pairs);
158
    add_pairs(&cf, pairs, count, 0);
159

Zardosht Kasheff's avatar
Zardosht Kasheff committed
160
    m_cp.turn_on_pending_bits();
161

Zardosht Kasheff's avatar
Zardosht Kasheff committed
162 163 164 165 166 167 168
    for (uint32_t i = 0; i < count; ++i) {
        assert(pairs[i].checkpoint_pending);
    }
    for (uint32_t i = 0; i < count; ++i) {
        CACHEKEY key;
        key.b = i;
        uint32_t full_hash = toku_cachetable_hash(&cf, key);
169
        PAIR pp = m_cp.m_list->find_pair(&cf, key, full_hash);
Zardosht Kasheff's avatar
Zardosht Kasheff committed
170
        assert(pp);
171
        m_cp.m_list->evict(pp);
Zardosht Kasheff's avatar
Zardosht Kasheff committed
172
    }
173

174
    ctbl.list.destroy();
175
    m_cp.destroy();
Zardosht Kasheff's avatar
Zardosht Kasheff committed
176 177 178
}

//------------------------------------------------------------------------------
179
// add_pairs() -
Zardosht Kasheff's avatar
Zardosht Kasheff committed
180
//
181
// Description: Adds data (pairs) to the list referenced in the checkpoitner.
Zardosht Kasheff's avatar
Zardosht Kasheff committed
182
//
183 184 185 186 187 188 189 190 191 192 193 194 195
void checkpointer_test::add_pairs(struct cachefile *cf,
    ctpair pairs[],
    uint32_t count,
    uint32_t k)
{
    pair_attr_s attr;
    attr.size = 0;
    attr.nonleaf_size = 0;
    attr.leaf_size = 0;
    attr.rollback_size = 0;
    attr.cache_pressure_size = 0;
    attr.is_valid = true;
    CACHETABLE_WRITE_CALLBACK cb;
196
    ZERO_STRUCT(cb);  // All nullptr
197

198 199 200 201 202 203 204
    for (uint32_t i = k; i < count + k; ++i) {
        CACHEKEY key;
        key.b = i;
        uint32_t full_hash = toku_cachetable_hash(cf, key);
        pair_init(&(pairs[i]),
            cf,
            key,
205
            nullptr,
206 207 208 209
            attr,
            CACHETABLE_CLEAN,
            full_hash,
            cb,
210
            nullptr,
211
            m_cp.m_list);
Zardosht Kasheff's avatar
Zardosht Kasheff committed
212

213
        m_cp.m_list->put(&pairs[i]);
214 215 216 217
    }
}

//------------------------------------------------------------------------------
218
// get_number_pending_pairs() -
219 220 221
//
// Description: Helper function that iterates over pending list, and returns
//   the number of pairs discovered.
222
//
223 224 225 226 227 228 229 230 231 232
static uint32_t get_number_pending_pairs(pair_list *list)
{
    PAIR p;
    uint32_t count = 0;
    PAIR head = list->m_pending_head;
    while((p = list->m_pending_head) != 0)
    {
        list->m_pending_head = list->m_pending_head->pending_next;
        count++;
    }
233

234 235
    list->m_pending_head = head;
    return count;
Zardosht Kasheff's avatar
Zardosht Kasheff committed
236 237 238 239 240
}

//------------------------------------------------------------------------------
// test_end_checkpoint() -
//
241
// Description:  Adds pairs to the list, before and after a checkpoint.
Zardosht Kasheff's avatar
Zardosht Kasheff committed
242 243
//
void checkpointer_test::test_end_checkpoint() {
244 245
    // 1. Init test.
    cachetable ctbl;
246
    ZERO_STRUCT(ctbl);
247 248 249
    ctbl.list.init();

    cachefile_list cfl;
250
    ZERO_STRUCT(cfl);
251
    cfl.init();
252

253 254 255 256 257
    struct cachefile cf;
    memset(&cf, 0, sizeof(cf));
    cf.next = NULL;
    cf.for_checkpoint = true;
    create_dummy_functions(&cf);
258

259
    ZERO_STRUCT(m_cp);
260
    m_cp.init(&ctbl.list, NULL, &ctbl.ev, &cfl);
261 262 263 264 265
    m_cp.m_cf_list->m_head = &cf;

    // 2. Add data before running checkpoint.
    const uint32_t count = 6;
    ctpair pairs[count];
266
    ZERO_ARRAY(pairs);
267
    add_pairs(&cf, pairs, count / 2, 0);
268
    assert(m_cp.m_list->m_n_in_table == count / 2);
269

270 271 272 273 274 275 276
    // 3. Call begin checkpoint.
    m_cp.begin_checkpoint();
    assert(m_cp.m_checkpoint_num_files == 1);
    for (uint32_t i = 0; i < count / 2; ++i)
    {
        assert(pairs[i].checkpoint_pending);
    }
277

278 279
    // 4. Add new data between starting and stopping checkpoint.
    add_pairs(&cf, pairs, count / 2, count / 2);
280
    assert(m_cp.m_list->m_n_in_table == count);
281 282 283 284
    for (uint32_t i = count / 2; i < count / 2; ++i)
    {
        assert(!pairs[i].checkpoint_pending);
    }
285

286
    uint32_t pending_pairs = 0;
287
    pending_pairs = get_number_pending_pairs(m_cp.m_list);
288
    assert(pending_pairs == count / 2);
289

290
    // 5. Call end checkpoint
Zardosht Kasheff's avatar
Zardosht Kasheff committed
291
    m_cp.end_checkpoint(NULL, NULL);
292

293
    pending_pairs = get_number_pending_pairs(m_cp.m_list);
294 295 296 297 298 299 300
    assert(pending_pairs == 0);

    // Verify that none of the pairs are pending a checkpoint.
    for (uint32_t i = 0; i < count; ++i)
    {
        assert(!pairs[i].checkpoint_pending);
    }
301

302 303 304 305 306
    // 6. Cleanup
    for (uint32_t i = 0; i < count; ++i) {
        CACHEKEY key;
        key.b = i;
        uint32_t full_hash = toku_cachetable_hash(&cf, key);
307
        PAIR pp = m_cp.m_list->find_pair(&cf, key, full_hash);
308
        assert(pp);
309
        m_cp.m_list->evict(pp);
310
    }
311
    m_cp.destroy();
312
    ctbl.list.destroy();
Zardosht Kasheff's avatar
Zardosht Kasheff committed
313 314 315 316 317 318 319 320 321 322 323 324 325
}


//------------------------------------------------------------------------------
// test_main() -
//
// Description:
//
int
test_main(int argc, const char *argv[]) {
    int r = 0;
    default_parse_args(argc, argv);
    checkpointer_test cp_test;
326

Zardosht Kasheff's avatar
Zardosht Kasheff committed
327 328 329
    // Run the tests.
    cp_test.test_begin_checkpoint();
    cp_test.test_pending_bits();
330
    cp_test.test_end_checkpoint();
331

Zardosht Kasheff's avatar
Zardosht Kasheff committed
332 333
    return r;
}