test_reverse_compare_fun.c 3.75 KB
Newer Older
1 2 3
/* try a reverse compare function to verify that the database always uses the application's
   compare function */

4 5 6
#include <arpa/inet.h>
#include <assert.h>
#include <db.h>
7 8 9
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
10 11 12 13 14
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#define CKERR(r) if (r!=0) fprintf(stderr, "%s:%d error %d %s\n", __FILE__, __LINE__, r, db_strerror(r)); assert(r==0);
15 16 17 18 19 20 21 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

DBT *dbt_init(DBT *dbt, void *data, u_int32_t size) {
    memset(dbt, 0, sizeof *dbt);
    dbt->data = data;
    dbt->size = size;
    return dbt;
}

DBT *dbt_init_malloc(DBT *dbt) {
    memset(dbt, 0, sizeof *dbt);
    dbt->flags = DB_DBT_MALLOC;
    return dbt;
}

int keycompare (const void *key1, unsigned int key1len, const void *key2, unsigned int key2len) {
    if (key1len==key2len) {
	return memcmp(key1,key2,key1len);
    } else if (key1len<key2len) {
	int r = memcmp(key1,key2,key1len);
	if (r<=0) return -1; /* If the keys are the same up to 1's length, then return -1, since key1 is shorter than key2. */
	else return 1;
    } else {
	return -keycompare(key2,key2len,key1,key1len);
    }
}

int reverse_compare(DB *db __attribute__((__unused__)), const DBT *a, const DBT*b) {
    return -keycompare(a->data, a->size, b->data, b->size);
}

void expect(DBC *cursor, int k, int v) {
    DBT key, val;
    int r = cursor->c_get(cursor, dbt_init_malloc(&key), dbt_init_malloc(&val), DB_NEXT);
48
    CKERR(r);
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
    assert(key.size == sizeof k);
    int kk;
    memcpy(&kk, key.data, key.size);
    assert(val.size == sizeof v);
    int vv;
    memcpy(&vv, val.data, val.size);
    if (kk != k || vv != v) printf("expect key %d got %d - %d %d\n", htonl(k), htonl(kk), htonl(v), htonl(vv));
    assert(kk == k);
    assert(vv == v);

    free(key.data);
    free(val.data);
}

void test_reverse_compare(int n) {
    printf("test_reverse_compare:%d\n", n);

    DB_ENV * const null_env = 0;
    DB *db;
    DB_TXN * const null_txn = 0;
69 70
    const char * const fname = DIR "/reverse.compare.db";

71 72 73
    int r;
    int i;

74 75
    system("rm -rf " DIR);
    mkdir(DIR, 0777);
76 77 78

    /* create the dup database file */
    r = db_create(&db, null_env, 0);
79
    CKERR(r);
80
    r = db->set_flags(db, 0);
81
    CKERR(r);
82
    r = db->set_pagesize(db, 4096);
83
    CKERR(r);
84
    r = db->set_bt_compare(db, reverse_compare);
85
    CKERR(r);
86
    r = db->open(db, null_txn, fname, "main", DB_BTREE, DB_CREATE, 0666);
87
    CKERR(r);
88 89 90 91 92 93 94 95 96 97

    /* insert n unique keys {0, 1,  n-1} */
    for (i=0; i<n; i++) {
        DBT key, val;
        int k, v;
        k = htonl(i);
        dbt_init(&key, &k, sizeof k);
        v = i;
        dbt_init(&val, &v, sizeof v);
        r = db->put(db, null_txn, &key, &val, 0);
98
        CKERR(r);
99 100 101 102
    }

    /* reopen the database to force nonleaf buffering */
    r = db->close(db, 0);
103
    CKERR(r);
104
    r = db_create(&db, null_env, 0);
105
    CKERR(r);
106
    r = db->set_flags(db, 0);
107
    CKERR(r);
108
    r = db->set_pagesize(db, 4096);
109
    CKERR(r);
110
    r = db->set_bt_compare(db, reverse_compare);
111
    CKERR(r);
112
    r = db->open(db, null_txn, fname, "main", DB_BTREE, 0, 0666);
113
    CKERR(r);
114 115 116 117 118 119 120 121 122 123

    /* insert n unique keys {n, n+1,  2*n-1} */
    for (i=n; i<2*n; i++) {
        DBT key, val;
        int k, v;
        k = htonl(i);
        dbt_init(&key, &k, sizeof k);
        v = i;
        dbt_init(&val, &v, sizeof v);
        r = db->put(db, null_txn, &key, &val, 0);
124
        CKERR(r);
125 126 127 128 129
    }

    /* verify the sort order with a cursor */
    DBC *cursor;
    r = db->cursor(db, null_txn, &cursor, 0);
130
    CKERR(r);
131 132 133 134 135 136

    //for (i=0; i<2*n; i++) 
    for (i=2*n-1; i>=0; i--)
        expect(cursor, htonl(i), i);

    r = cursor->c_close(cursor);
137
    CKERR(r);
138 139

    r = db->close(db, 0);
140
    CKERR(r);
141 142 143 144 145 146 147 148 149 150
}

int main() {
    int i;

    for (i = 1; i <= (1<<16); i *= 2) {
        test_reverse_compare(i);
    }
    return 0;
}