test_db_secondary.c 5.58 KB
Newer Older
1 2 3
/* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007 Tokutek Inc.  All rights reserved."

Yoni Fogel's avatar
Yoni Fogel committed
4 5 6 7 8 9
#include <string.h>
#include <db.h>
#include <assert.h>
#include <errno.h>
#include <sys/stat.h>

10
#include "test.h"
Yoni Fogel's avatar
Yoni Fogel committed
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

// DIR is defined in the Makefile

int dbtcmp(DBT *dbt1, DBT *dbt2) {
    int r;
    
    r = dbt1->size - dbt2->size;  if (r) return r;
    return memcmp(dbt1->data, dbt2->data, dbt1->size);
}

struct student_record {
	char student_id[4];
	char last_name[15];
	char first_name[15];
};
26
#define SPACES "               "
Yoni Fogel's avatar
Yoni Fogel committed
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
DB *dbp;
DB *sdbp;
DB_TXN *const null_txn = 0;
DB_ENV *dbenv;
/*
 * getname -- extracts a secondary key (the last name) from a primary
 * 	key/data pair
 */
int getname(DB *secondary, const DBT *pkey, const DBT *pdata, DBT *skey)
{
	/*
	 * Since the secondary key is a simple structure member of the
	 * record, we don't have to do anything fancy to return it.  If
	 * we have composite keys that need to be constructed from the
	 * record, rather than simply pointing into it, then the user's
	 * function might need to allocate space and copy data.  In
	 * this case, the DB_DBT_APPMALLOC flag should be set in the
	 * secondary key DBT.
	 */
	memset(skey, 0, sizeof(DBT));
	skey->data = ((struct student_record *)pdata->data)->last_name;
	skey->size = sizeof ((struct student_record *)pdata->data)->last_name;
	return (0);
}

void second_setup() {
    int r;

    /* Open/create primary */
56
    r = db_create(&dbp, dbenv, 0);                                              CKERR(r);
57
    r = dbp->open(dbp, NULL, DIR "/students.db", NULL, DB_BTREE, DB_CREATE, 0600);   CKERR(r);
Yoni Fogel's avatar
Yoni Fogel committed
58 59 60 61 62

    /*
     * Open/create secondary. Note that it supports duplicate data
     * items, since last names might not be unique.
     */
63 64
    r = db_create(&sdbp, dbenv, 0);                                             CKERR(r);
    r = sdbp->set_flags(sdbp, DB_DUP | DB_DUPSORT);                             CKERR(r);
65
    r = sdbp->open(sdbp, NULL, DIR "/lastname.db", NULL, DB_BTREE, DB_CREATE, 0600); CKERR(r);
Yoni Fogel's avatar
Yoni Fogel committed
66 67 68
    

    /* Associate the secondary with the primary. */
69
    r = dbp->associate(dbp, NULL, sdbp, getname, 0);                            CKERR(r);
Yoni Fogel's avatar
Yoni Fogel committed
70 71 72 73
}

void setup_student(struct student_record *s) {
    memset(s, 0, sizeof(struct student_record));
74 75 76 77
    memcpy(&s->student_id, "WC42"      SPACES,  sizeof(s->student_id));
    //Padded with enough spaces to fill out last/first name.
    memcpy(&s->last_name,  "Churchill" SPACES,  sizeof(s->last_name));
    memcpy(&s->first_name, "Winston"   SPACES,  sizeof(s->first_name));
Yoni Fogel's avatar
Yoni Fogel committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
}

void insert_test() {
    struct student_record s;
    DBT data;
    DBT key;
    DBT skey;
    DBT testdata;
    DBT testkey;
    int r;
    
    setup_student(&s);
    memset(&testdata,   0, sizeof(DBT));
    memset(&testkey,    0, sizeof(DBT));
    memset(&skey,       0, sizeof(DBT));
    memset(&key,        0, sizeof(DBT));
    memset(&data,       0, sizeof(DBT));
    key.data = "WC42";
    key.size = strlen("WC42");
    data.data = &s;
    data.size = sizeof(s);
    //Set up secondary key
100
    r = getname(sdbp, &key, &data, &skey);              CKERR(r);
Yoni Fogel's avatar
Yoni Fogel committed
101
        
102
    r = dbp->put(dbp, null_txn, &key, &data, 0);        CKERR(r);
Yoni Fogel's avatar
Yoni Fogel committed
103 104 105
    

    /* Try to get it from primary. */
106 107
    r = dbp->get(dbp, null_txn, &key, &testdata, 0);    CKERR(r);
    r = dbtcmp(&data, &testdata);                       CKERR(r);
Yoni Fogel's avatar
Yoni Fogel committed
108 109
    
    /* Try to get it from secondary. */
110 111
    r = sdbp->get(sdbp, null_txn, &skey, &testdata, 0); CKERR(r);
    r = dbtcmp(&data, &testdata);                       CKERR(r);
Yoni Fogel's avatar
Yoni Fogel committed
112 113

    /* Try to pget from secondary */ 
114 115 116
    r = sdbp->pget(sdbp, null_txn, &skey, &testkey, &testdata, 0);  CKERR(r);
    r = dbtcmp(&data, &testdata);                       CKERR(r);
    r = dbtcmp(&testkey, &key);                         CKERR(r);
Yoni Fogel's avatar
Yoni Fogel committed
117 118 119 120 121 122 123 124 125 126 127 128
    
    /* Make sure we fail 'pget' from primary */
    r = dbp->pget(dbp, null_txn, &key, &testkey, &data, 0);         assert(r == EINVAL);
}

void delete_from_primary() {
    int r;
    DBT key;

    memset(&key, 0, sizeof(DBT));
    key.data = "WC42";
    key.size = 4;
129
    r = dbp->del(dbp, null_txn, &key, 0);               CKERR(r);
Yoni Fogel's avatar
Yoni Fogel committed
130 131 132 133 134 135 136 137 138 139 140 141 142 143
}

void delete_from_secondary() {
    int r;
    DBT skey;
    DBT data;
    struct student_record s;

    setup_student(&s);
    memset(&skey, 0, sizeof(DBT));
    memset(&data, 0, sizeof(DBT));

    data.data = &s;
    data.size = sizeof(s);
144 145
    r = getname(sdbp, NULL, &data, &skey);              CKERR(r);
    r = sdbp->del(sdbp, null_txn, &skey, 0);            CKERR(r);
Yoni Fogel's avatar
Yoni Fogel committed
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
}

void verify_gone() {
    int r;
    DBT key;
    DBT skey;
    DBT data;
    struct student_record s;

    memset(&key, 0, sizeof(DBT));
    memset(&skey, 0, sizeof(DBT));
    memset(&data, 0, sizeof(DBT));
    key.data = "WC42";
    key.size = 4;

    /* Try (fail) to get it from primary. */
    r = dbp->get(dbp, null_txn, &key, &data, 0);        assert(r == DB_NOTFOUND);

    /* Try (fail) to get it from secondary. */
    setup_student(&s);
166
    r = getname(sdbp, NULL, &data, &skey);              CKERR(r);
Yoni Fogel's avatar
Yoni Fogel committed
167 168 169 170
    r = sdbp->get(sdbp, null_txn, &skey, &data, 0);     assert(r == DB_NOTFOUND);

    /* Try (fail) to pget from secondary */ 
    setup_student(&s);
171
    r = getname(sdbp, NULL, &data, &skey);              CKERR(r);
Yoni Fogel's avatar
Yoni Fogel committed
172 173 174 175 176 177
    r = sdbp->pget(sdbp, null_txn, &skey, &key, &data, 0);assert(r == DB_NOTFOUND);
}

int main() {
    int r;

178 179 180
    system("rm -rf " DIR);
    mkdir(DIR, 0777);

Yoni Fogel's avatar
Yoni Fogel committed
181 182 183 184 185 186 187 188
    second_setup();
    insert_test();
    delete_from_primary();
    verify_gone();
    insert_test();
    delete_from_secondary();
    verify_gone();
    
189 190
    r = dbp->close(dbp, 0);                             CKERR(r);
    r = sdbp->close(sdbp, 0);                           CKERR(r);
Yoni Fogel's avatar
Yoni Fogel committed
191 192
    return 0;
}