test_cursor_count.cpp 11.3 KB
Newer Older
1
#include <stdlib.h>
2
#include <unistd.h>
3
#include <errno.h>
4 5 6
#include <arpa/inet.h>
#include <assert.h>
#include <db_cxx.h>
7
#include <memory.h>
8

9 10
int verbose;

Bradley C. Kuszmaul's avatar
Bradley C. Kuszmaul committed
11 12
#define FNAME __FILE__ ".tdb"

13 14 15 16 17 18 19 20 21 22 23 24
#ifndef DB_YESOVERWRITE
#define BDB 1
#define DB_YESOVERWRITE 0
#else
#define TDB 1
#endif

int keyeq(Dbt *a, Dbt *b) {
    if (a->get_size() != b->get_size()) return 0;
    return memcmp(a->get_data(), b->get_data(), a->get_size()) == 0;
}

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
int my_cursor_count(Dbc *cursor, db_recno_t *count, Db *db) {
    int r;
    Dbt key; key.set_flags(DB_DBT_REALLOC);
    Dbt val; val.set_flags(DB_DBT_REALLOC);
    r = cursor->get(&key, &val, DB_CURRENT); assert(r == 0);
    
    Dbc *count_cursor;
    r = db->cursor(0, &count_cursor, 0); assert(r == 0);
    r = count_cursor->get(&key, &val, DB_SET); assert(r == 0);
    *count = 0;

    Dbt nkey, nval;
    for (;; ) {
        *count += 1;
        nkey.set_flags(DB_DBT_REALLOC);
        nval.set_flags(DB_DBT_REALLOC);
        r = count_cursor->get(&nkey, &nval, DB_NEXT);
        if (r != 0) break;
        if (!keyeq(&key, &nkey)) break;
    }
    r = 0;
46 47 48 49
    if (nkey.get_data()) toku_free(nkey.get_data());
    if (nval.get_data()) toku_free(nval.get_data());
    if (key.get_data()) toku_free(key.get_data());
    if (val.get_data()) toku_free(val.get_data());
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
    int rr = count_cursor->close(); assert(rr == 0);
    return r;
}

int my_next_nodup(Dbc *cursor, Dbt *key, Dbt *val) {
    int r;
    Dbt currentkey; currentkey.set_flags(DB_DBT_REALLOC);
    Dbt currentval; currentval.set_flags(DB_DBT_REALLOC);
    r = cursor->get(&currentkey, &currentval, DB_CURRENT); assert(r == 0);
    Dbt nkey; nkey.set_flags(DB_DBT_REALLOC);
    Dbt nval; nval.set_flags(DB_DBT_REALLOC);
    for (;;) {
        r = cursor->get(&nkey, &nval, DB_NEXT);
        if (r != 0) break;
        if (!keyeq(&currentkey, &nkey)) break;
    }
66 67 68 69
    if (nkey.get_data()) toku_free(nkey.get_data());
    if (nval.get_data()) toku_free(nval.get_data());
    if (currentkey.get_data()) toku_free(currentkey.get_data());
    if (currentval.get_data()) toku_free(currentval.get_data());
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
    if (r == 0) r = cursor->get(key, val, DB_CURRENT);
    return r;
}

int my_prev_nodup(Dbc *cursor, Dbt *key, Dbt *val) {
    int r;
    Dbt currentkey; currentkey.set_flags(DB_DBT_REALLOC);
    Dbt currentval; currentval.set_flags(DB_DBT_REALLOC);
    r = cursor->get(&currentkey, &currentval, DB_CURRENT); assert(r == 0);
    Dbt nkey; nkey.set_flags(DB_DBT_REALLOC);
    Dbt nval; nval.set_flags(DB_DBT_REALLOC);
    for (;;) {
        r = cursor->get(&nkey, &nval, DB_PREV);
        if (r != 0) break;
        if (!keyeq(&currentkey, &nkey)) break;
    }
86 87 88 89
    if (nkey.get_data()) toku_free(nkey.get_data());
    if (nval.get_data()) toku_free(nval.get_data());
    if (currentkey.get_data()) toku_free(currentkey.get_data());
    if (currentval.get_data()) toku_free(currentval.get_data());
90 91 92 93 94 95 96 97 98 99 100 101 102
    if (r == 0) r = cursor->get(key, val, DB_CURRENT);
    return r;
}

int my_next_dup(Dbc *cursor, Dbt *key, Dbt *val) {
    int r;
    Dbt currentkey; currentkey.set_flags(DB_DBT_REALLOC);
    Dbt currentval; currentval.set_flags(DB_DBT_REALLOC);
    r = cursor->get(&currentkey, &currentval, DB_CURRENT); assert(r == 0);
    Dbt nkey; nkey.set_flags(DB_DBT_REALLOC);
    Dbt nval; nval.set_flags(DB_DBT_REALLOC);
    r = cursor->get(&nkey, &nval, DB_NEXT);
    if (r == 0 && !keyeq(&currentkey, &nkey)) r = DB_NOTFOUND;
103 104 105 106
    if (nkey.get_data()) toku_free(nkey.get_data());
    if (nval.get_data()) toku_free(nval.get_data());
    if (currentkey.get_data()) toku_free(currentkey.get_data());
    if (currentval.get_data()) toku_free(currentval.get_data());
107 108 109 110 111 112 113 114 115 116 117 118 119
    if (r == 0) r = cursor->get(key, val, DB_CURRENT);
    return r;
}

int my_prev_dup(Dbc *cursor, Dbt *key, Dbt *val) {
    int r;
    Dbt currentkey; currentkey.set_flags(DB_DBT_REALLOC);
    Dbt currentval; currentval.set_flags(DB_DBT_REALLOC);
    r = cursor->get(&currentkey, &currentval, DB_CURRENT); assert(r == 0);
    Dbt nkey; nkey.set_flags(DB_DBT_REALLOC);
    Dbt nval; nval.set_flags(DB_DBT_REALLOC);
    r = cursor->get(&nkey, &nval, DB_PREV);
    if (r == 0 && !keyeq(&currentkey, &nkey)) r = DB_NOTFOUND;
120 121 122 123
    if (nkey.get_data()) toku_free(nkey.get_data());
    if (nval.get_data()) toku_free(nval.get_data());
    if (currentkey.get_data()) toku_free(currentkey.get_data());
    if (currentval.get_data()) toku_free(currentval.get_data());
124 125 126 127
    if (r == 0) r = cursor->get(key, val, DB_CURRENT);
    return r;
}

128
void load(Db *db, int n) {
129
    if (verbose) printf("load\n");
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
    int i;
    for (i=0; i<n; i++) {
        if (i == n/2) continue;
        int k = htonl(i);
        Dbt key(&k, sizeof k);
        int v = i;
        Dbt val(&v, sizeof v);
        int r = db->put(0, &key, &val, DB_YESOVERWRITE); assert(r == 0);
    }

    for (i=0; i<n; i++) {
        int k = htonl(n/2);
        int v = i;
        Dbt key(&k, sizeof k);
        Dbt val(&v, sizeof v);
        int r = db->put(0, &key, &val, DB_YESOVERWRITE); assert(r == 0);
    }
}

149
void test_cursor_count_flags(Db *db) {
150 151 152 153 154 155 156
    int r;
    Dbc *cursor;
    
    r = db->cursor(0, &cursor, 0); assert(r == 0);
    Dbt key; key.set_flags(DB_DBT_MALLOC);
    Dbt val; val.set_flags(DB_DBT_MALLOC);
    r = cursor->get(&key, &val, DB_FIRST); assert(r == 0);
157 158
    if (key.get_data()) toku_free(key.get_data());
    if (val.get_data()) toku_free(val.get_data());
159 160 161
    db_recno_t n;
    r = cursor->count(&n, 1); assert(r == EINVAL);
    r = cursor->count(&n, 0); assert(r == 0);
162
    if (verbose) printf("n=%d\n", n);
163 164 165
    r = cursor->close(); assert(r == 0);
}    

166
void walk(Db *db, int n) {
167
    if (verbose) printf("walk\n");
168 169 170
    Dbc *cursor;
    int r = db->cursor(0, &cursor, 0); assert(r == 0);
    Dbt key, val;
171 172
    int i;
    for (i=0;;i++) {
173 174 175 176 177 178 179 180 181 182 183
        key.set_flags(DB_DBT_REALLOC);
        val.set_flags(DB_DBT_REALLOC);
        r = cursor->get(&key, &val, DB_NEXT);
        if (r != 0) break;
        int k;
        assert(key.get_size() == sizeof k);
        memcpy(&k, key.get_data(), key.get_size());
        k = htonl(k);
        int v;
        assert(val.get_size() == sizeof v);
        memcpy(&v, val.get_data(), val.get_size());
184 185 186
        db_recno_t count;
        r = cursor->count(&count, 0); assert(r == 0);
        if (verbose) printf("%d %d %d\n", k, v, count);
187
#if 0
188 189 190
        db_recno_t mycount;
        r = my_cursor_count(cursor, &mycount, db); assert(r == 0);
        assert(mycount == count);
191
#endif
192
        if (k == n/2) assert((int)count == n); else assert(count == 1);
193
    }
194
    assert(i == 2*n-1);
195 196
    toku_free(key.get_data());
    toku_free(val.get_data());
197 198 199
    r = cursor->close(); assert(r == 0);
}

200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
int cursor_set(Dbc *cursor, int k) {
    Dbt key(&k, sizeof k);
    Dbt val;
    int r = cursor->get(&key, &val, DB_SET);
    return r;
}

void test_zero_count(Db *db, int n) {
    if (verbose) printf("test_zero_count\n");
    Dbc *cursor;
    int r = db->cursor(0, &cursor, 0); assert(r == 0);

    r = cursor_set(cursor, htonl(n/2)); assert(r == 0);
    db_recno_t count;
    r = cursor->count(&count, 0); assert(r == 0);
    assert((int)count == n);

    Dbt key; key.set_flags(DB_DBT_REALLOC);
    Dbt val; val.set_flags(DB_DBT_REALLOC);
    int i;
    for (i=1; count > 0; i++) {
        r = cursor->del(0); assert(r == 0);
        db_recno_t newcount;
        r = cursor->count(&newcount, 0);
        if (r != 0) 
            break;
        assert(newcount == count - 1);
        count = newcount;
        r = cursor->get(&key, &val, DB_NEXT_DUP); 
        if (r != 0) break;
    }
    assert(i == n);
232 233
    if (key.get_data()) toku_free(key.get_data());
    if (val.get_data()) toku_free(val.get_data());
234 235 236
    r = cursor->close(); assert(r == 0);
}

237
void test_next_nodup(Db *db, int n) {
238
    if (verbose) printf("test_next_nodup\n");
239 240 241 242 243 244
    int r;
    Dbc *cursor;
    r = db->cursor(0, &cursor, 0); assert(r == 0);
    Dbt key; key.set_flags(DB_DBT_REALLOC);
    Dbt val; val.set_flags(DB_DBT_REALLOC);
    r = cursor->get(&key, &val, DB_FIRST); assert(r == 0);
245
    int i = 0;
246
    while (r == 0) {
247 248 249 250
        int k = htonl(*(int*)key.get_data());
        int v = *(int*)val.get_data();
        if (verbose) printf("%d %d\n", k, v);
        assert(k == i);
251
        if (k == n/2) assert(v == 0); else assert(v == i);
252
        i += 1;
253 254
        // r = my_next_nodup(cursor, &key, &val);
        r = cursor->get(&key, &val, DB_NEXT_NODUP);
255
    }
256
    assert(i == n);
257 258
    if (key.get_data()) toku_free(key.get_data());
    if (val.get_data()) toku_free(val.get_data());
259 260 261
    r = cursor->close(); assert(r == 0);
}

262 263
void test_prev_nodup(Db *db, int n) {
    if (verbose) printf("test_prev_nodup\n");
264
    int r;
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
    Dbc *cursor;
    r = db->cursor(0, &cursor, 0); assert(r == 0);
    Dbt key; key.set_flags(DB_DBT_REALLOC);
    Dbt val; val.set_flags(DB_DBT_REALLOC);
    r = cursor->get(&key, &val, DB_LAST); assert(r == 0);
    int i = n-1;
    while (r == 0) {
        int k = htonl(*(int*)key.get_data());
        int v = *(int*)val.get_data();
        if (verbose) printf("%d %d\n", k, v);
        assert(k == i);
        if (k == n/2) assert(v == n-1); else assert(v == i);
        i -= 1;
        // r = my_next_nodup(cursor, &key, &val);
        r = cursor->get(&key, &val, DB_PREV_NODUP);
    }
    assert(i == -1);
282 283
    if (key.get_data()) toku_free(key.get_data());
    if (val.get_data()) toku_free(val.get_data());
284
    r = cursor->close(); assert(r == 0);
285 286 287
}

void test_next_dup(Db *db, int n) {
288
    if (verbose) printf("test_next_dup\n");
289 290 291 292 293 294 295 296 297
    int r;
    Dbc *cursor;
    r = db->cursor(0, &cursor, 0); assert(r == 0);
    int k = htonl(n/2);
    Dbt setkey(&k, sizeof k);
    Dbt key; key.set_flags(DB_DBT_REALLOC);
    Dbt val; val.set_flags(DB_DBT_REALLOC);
    r = cursor->get(&setkey, &val, DB_SET); assert(r == 0);
    r = cursor->get(&key, &val, DB_CURRENT); assert(r == 0);
298
    int i = 0;
299
    while (r == 0) {
300 301 302 303 304
        int k = htonl(*(int*)key.get_data());
        int v = *(int*)val.get_data();
        if (verbose) printf("%d %d\n", k, v);
        assert(k == n/2); assert(v == i);
        i += 1;
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
        // r = my_next_dup(cursor, &key, &val);
        r = cursor->get(&key, &val, DB_NEXT_DUP);
    }
    assert(i == n);
#ifdef DB_PREV_DUP
    i = n - 1;
    for (;;) {
        r = cursor->get(&key, &val, DB_CURRENT);
        assert(r == 0);
        int k = htonl(*(int*)key.get_data());
        int v = *(int*)val.get_data();
        assert(k == n/2); assert(v == i);
        r = cursor->get(&key, &val, DB_PREV_DUP);
        if (r != 0) break;
        i -= 1;
320
    }
321 322
    assert(i == 0);
#endif
323 324
    if (key.get_data()) toku_free(key.get_data());
    if (val.get_data()) toku_free(val.get_data());
325 326 327
    r = cursor->close(); assert(r == 0);
}

328 329 330 331 332 333 334
int main(int argc, char *argv[]) {
    for (int i=1; i<argc; i++) {
        char *arg = argv[i];
        if (strcmp(arg, "-v") == 0 || strcmp(arg, "--verbose") == 0)
            verbose = 1;
    }

335 336
    int r;

337 338 339 340 341
#if defined(USE_ENV) && USE_ENV
    DbEnv env(DB_CXX_NO_EXCEPTIONS);
    r = env.open(".", DB_INIT_MPOOL + DB_CREATE + DB_PRIVATE, 0777); assert(r == 0);
    Db db(&env, DB_CXX_NO_EXCEPTIONS);
#else
342
    Db db(0, DB_CXX_NO_EXCEPTIONS);
343 344
#endif

345
    r = db.set_flags(DB_DUP + DB_DUPSORT); assert(r == 0);
Bradley C. Kuszmaul's avatar
Bradley C. Kuszmaul committed
346 347
    unlink(FNAME);
    r = db.open(0, FNAME, 0, DB_BTREE, DB_CREATE, 0777); assert(r == 0);
348 349
    
    load(&db, 10);
350
    test_cursor_count_flags(&db);
351 352
    walk(&db, 10);
    test_next_nodup(&db, 10);
353
    test_prev_nodup(&db, 10);
354
    test_next_dup(&db, 10);
355
    test_zero_count(&db, 10);
356 357 358

    return 0;
}