mdb_cmp refactoring

vmware
Howard Chu 13 years ago
parent 7bb14a2e79
commit 70a4f6f29d
  1. 211
      libraries/libmdb/mdb.c
  2. 2
      libraries/libmdb/mdb.h

@ -529,10 +529,9 @@ static size_t mdb_leaf_size(MDB_env *env, MDB_val *key,
MDB_val *data); MDB_val *data);
static size_t mdb_branch_size(MDB_env *env, MDB_val *key); static size_t mdb_branch_size(MDB_env *env, MDB_val *key);
static int memncmp(const void *s1, size_t n1, static void mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi);
const void *s2, size_t n2);
static int memnrcmp(const void *s1, size_t n1, static MDB_cmp_func memncmp, memnrcmp, intcmp;
const void *s2, size_t n2);
#ifdef _WIN32 #ifdef _WIN32
static SECURITY_DESCRIPTOR mdb_null_sd; static SECURITY_DESCRIPTOR mdb_null_sd;
@ -540,39 +539,6 @@ static SECURITY_ATTRIBUTES mdb_all_sa;
static int mdb_sec_inited; static int mdb_sec_inited;
#endif #endif
static int
memncmp(const void *s1, size_t n1, const void *s2, size_t n2)
{
int diff, len_diff = -1;
if (n1 >= n2) {
len_diff = (n1 > n2);
n1 = n2;
}
diff = memcmp(s1, s2, n1);
return diff ? diff : len_diff;
}
static int
memnrcmp(const void *s1, size_t n1, const void *s2, size_t n2)
{
const unsigned char *p1, *p2, *p1_lim;
if (n2 == 0)
return n1 != 0;
if (n1 == 0)
return -1;
p1 = (const unsigned char *)s1 + n1 - 1;
p2 = (const unsigned char *)s2 + n2 - 1;
for (p1_lim = (n1 <= n2 ? s1 : s2); *p1 == *p2; p1--, p2--) {
if (p1 == p1_lim)
return (p1 != s1) ? (p1 != p2) : (p2 != s2) ? -1 : 0;
}
return *p1 - *p2;
}
char * char *
mdb_version(int *maj, int *min, int *pat) mdb_version(int *maj, int *min, int *pat)
{ {
@ -625,17 +591,7 @@ mdb_dkey(MDB_val *key, char *buf)
int int
mdb_cmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b) mdb_cmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b)
{ {
if (txn->mt_dbxs[dbi].md_cmp) return txn->mt_dbxs[dbi].md_cmp(a, b);
return txn->mt_dbxs[dbi].md_cmp(a, b);
if (txn->mt_dbs[dbi].md_flags & (MDB_REVERSEKEY
#if __BYTE_ORDER == __LITTLE_ENDIAN
|MDB_INTEGERKEY
#endif
))
return memnrcmp(a->mv_data, a->mv_size, b->mv_data, b->mv_size);
else
return memncmp((char *)a->mv_data, a->mv_size, b->mv_data, b->mv_size);
} }
int int
@ -643,15 +599,8 @@ mdb_dcmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b)
{ {
if (txn->mt_dbxs[dbi].md_dcmp) if (txn->mt_dbxs[dbi].md_dcmp)
return txn->mt_dbxs[dbi].md_dcmp(a, b); return txn->mt_dbxs[dbi].md_dcmp(a, b);
if (txn->mt_dbs[dbi].md_flags & (0
#if __BYTE_ORDER == __LITTLE_ENDIAN
|MDB_INTEGERDUP
#endif
))
return memnrcmp(a->mv_data, a->mv_size, b->mv_data, b->mv_size);
else else
return memncmp((char *)a->mv_data, a->mv_size, b->mv_data, b->mv_size); return EINVAL; /* too bad you can't distinguish this from a valid result */
} }
/* Allocate new page(s) for writing */ /* Allocate new page(s) for writing */
@ -1979,6 +1928,67 @@ mdb_env_close(MDB_env *env)
free(env); free(env);
} }
static int
intcmp(const MDB_val *a, const MDB_val *b)
{
if (a->mv_size == sizeof(long))
{
unsigned long *la, *lb;
la = a->mv_data;
lb = b->mv_data;
return *la - *lb;
} else {
unsigned int *ia, *ib;
ia = a->mv_data;
ib = b->mv_data;
return *ia - *ib;
}
}
static int
memncmp(const MDB_val *a, const MDB_val *b)
{
int diff, len_diff;
unsigned int len;
len = a->mv_size;
len_diff = a->mv_size - b->mv_size;
if (len_diff > 0)
len = b->mv_size;
diff = memcmp(a->mv_data, b->mv_data, len);
return diff ? diff : len_diff;
}
static int
memnrcmp(const MDB_val *a, const MDB_val *b)
{
const unsigned char *p1, *p2, *p1_lim;
int diff, len_diff;
if (b->mv_size == 0)
return a->mv_size != 0;
if (a->mv_size == 0)
return -1;
p1 = (const unsigned char *)a->mv_data + a->mv_size - 1;
p2 = (const unsigned char *)b->mv_data + b->mv_size - 1;
len_diff = a->mv_size - b->mv_size;
if (len_diff < 0)
p1_lim = p1 - a->mv_size;
else
p1_lim = p1 - b->mv_size;
while (p1 >= p1_lim) {
diff = *p1 - *p2;
if (diff)
return diff;
p1--;
p2--;
}
return len_diff;
}
/* Search for key within a leaf page, using binary search. /* Search for key within a leaf page, using binary search.
* Returns the smallest entry larger or equal to the key. * Returns the smallest entry larger or equal to the key.
* If exactp is non-null, stores whether the found entry was an exact match * If exactp is non-null, stores whether the found entry was an exact match
@ -1990,29 +2000,33 @@ static MDB_node *
mdb_search_node(MDB_txn *txn, MDB_dbi dbi, MDB_page *mp, MDB_val *key, mdb_search_node(MDB_txn *txn, MDB_dbi dbi, MDB_page *mp, MDB_val *key,
int *exactp, unsigned int *kip) int *exactp, unsigned int *kip)
{ {
unsigned int i = 0; unsigned int i = 0, nkeys;
int low, high; int low, high;
int rc = 0; int rc = 0;
MDB_node *node = NULL; MDB_node *node = NULL;
MDB_val nodekey; MDB_val nodekey;
MDB_cmp_func *cmp;
DKBUF; DKBUF;
nkeys = NUMKEYS(mp);
DPRINTF("searching %u keys in %s page %lu", DPRINTF("searching %u keys in %s page %lu",
NUMKEYS(mp), nkeys, IS_LEAF(mp) ? "leaf" : "branch",
IS_LEAF(mp) ? "leaf" : "branch",
mp->mp_pgno); mp->mp_pgno);
assert(NUMKEYS(mp) > 0); assert(nkeys > 0);
memset(&nodekey, 0, sizeof(nodekey));
low = IS_LEAF(mp) ? 0 : 1; low = IS_LEAF(mp) ? 0 : 1;
high = NUMKEYS(mp) - 1; high = nkeys - 1;
cmp = txn->mt_dbxs[dbi].md_cmp;
if (IS_LEAF2(mp)) {
nodekey.mv_size = txn->mt_dbs[dbi].md_pad;
node = NODEPTR(mp, 0); /* fake */
}
while (low <= high) { while (low <= high) {
i = (low + high) >> 1; i = (low + high) >> 1;
if (IS_LEAF2(mp)) { if (IS_LEAF2(mp)) {
nodekey.mv_size = txn->mt_dbs[dbi].md_pad;
nodekey.mv_data = LEAF2KEY(mp, i, nodekey.mv_size); nodekey.mv_data = LEAF2KEY(mp, i, nodekey.mv_size);
} else { } else {
node = NODEPTR(mp, i); node = NODEPTR(mp, i);
@ -2021,14 +2035,16 @@ mdb_search_node(MDB_txn *txn, MDB_dbi dbi, MDB_page *mp, MDB_val *key,
nodekey.mv_data = NODEKEY(node); nodekey.mv_data = NODEKEY(node);
} }
rc = mdb_cmp(txn, dbi, key, &nodekey); rc = cmp(key, &nodekey);
#if DEBUG
if (IS_LEAF(mp)) if (IS_LEAF(mp))
DPRINTF("found leaf index %u [%s], rc = %i", DPRINTF("found leaf index %u [%s], rc = %i",
i, DKEY(&nodekey), rc); i, DKEY(&nodekey), rc);
else else
DPRINTF("found branch index %u [%s -> %lu], rc = %i", DPRINTF("found branch index %u [%s -> %lu], rc = %i",
i, DKEY(&nodekey), NODEPGNO(node), rc); i, DKEY(&nodekey), NODEPGNO(node), rc);
#endif
if (rc == 0) if (rc == 0)
break; break;
@ -2045,12 +2061,12 @@ mdb_search_node(MDB_txn *txn, MDB_dbi dbi, MDB_page *mp, MDB_val *key,
*exactp = (rc == 0); *exactp = (rc == 0);
if (kip) /* Store the key index if requested. */ if (kip) /* Store the key index if requested. */
*kip = i; *kip = i;
if (i >= NUMKEYS(mp)) if (i >= nkeys)
/* There is no entry larger or equal to the key. */ /* There is no entry larger or equal to the key. */
return NULL; return NULL;
/* nodeptr is fake for LEAF2 */ /* nodeptr is fake for LEAF2 */
return IS_LEAF2(mp) ? NODEPTR(mp, 0) : NODEPTR(mp, i); return node;
} }
static void static void
@ -2163,7 +2179,7 @@ mdb_search_page_root(MDB_txn *txn, MDB_dbi dbi, MDB_val *key,
return ENOMEM; return ENOMEM;
if (modify) { if (modify) {
MDB_dhead *dh = ((MDB_dhead *)mp)-1; MDB_dhead *dh;
if ((rc = mdb_touch(txn, dbi, mpp)) != 0) if ((rc = mdb_touch(txn, dbi, mpp)) != 0)
return rc; return rc;
dh = ((MDB_dhead *)mpp->mp_page)-1; dh = ((MDB_dhead *)mpp->mp_page)-1;
@ -2524,7 +2540,7 @@ mdb_cursor_set(MDB_cursor *cursor, MDB_val *key, MDB_val *data,
leaf = NODEPTR(top->mp_page, 0); leaf = NODEPTR(top->mp_page, 0);
MDB_SET_KEY(leaf, &nodekey); MDB_SET_KEY(leaf, &nodekey);
} }
rc = mdb_cmp(cursor->mc_txn, cursor->mc_dbi, key, &nodekey); rc = cursor->mc_txn->mt_dbxs[cursor->mc_dbi].md_cmp(key, &nodekey);
if (rc == 0) { if (rc == 0) {
set1: set1:
/* we're already on the right page */ /* we're already on the right page */
@ -2542,7 +2558,7 @@ set1:
leaf = NODEPTR(top->mp_page, NUMKEYS(top->mp_page)-1); leaf = NODEPTR(top->mp_page, NUMKEYS(top->mp_page)-1);
MDB_SET_KEY(leaf, &nodekey); MDB_SET_KEY(leaf, &nodekey);
} }
rc = mdb_cmp(cursor->mc_txn, cursor->mc_dbi, key, &nodekey); rc = cursor->mc_txn->mt_dbxs[cursor->mc_dbi].md_cmp(key, &nodekey);
if (rc <= 0) goto set1; if (rc <= 0) goto set1;
} }
/* If any parents have right-sibs, search. /* If any parents have right-sibs, search.
@ -2618,7 +2634,7 @@ set2:
MDB_val d2; MDB_val d2;
if ((rc = mdb_read_data(cursor->mc_txn, leaf, &d2)) != MDB_SUCCESS) if ((rc = mdb_read_data(cursor->mc_txn, leaf, &d2)) != MDB_SUCCESS)
return rc; return rc;
rc = mdb_dcmp(cursor->mc_txn, cursor->mc_dbi, data, &d2); rc = cursor->mc_txn->mt_dbxs[cursor->mc_dbi].md_cmp(data, &d2);
if (rc) { if (rc) {
if (op == MDB_GET_BOTH || rc > 0) if (op == MDB_GET_BOTH || rc > 0)
return MDB_NOTFOUND; return MDB_NOTFOUND;
@ -2941,7 +2957,7 @@ top:
if (rc == MDB_SUCCESS) { if (rc == MDB_SUCCESS) {
/* there's only a key anyway, so this is a no-op */ /* there's only a key anyway, so this is a no-op */
if (IS_LEAF2(top->mp_page)) { if (IS_LEAF2(top->mp_page)) {
int ksize = mc->mc_txn->mt_dbs[mc->mc_dbi].md_pad; unsigned int ksize = mc->mc_txn->mt_dbs[mc->mc_dbi].md_pad;
if (key->mv_size != ksize) if (key->mv_size != ksize)
return EINVAL; return EINVAL;
if (flags == MDB_CURRENT) { if (flags == MDB_CURRENT) {
@ -3103,11 +3119,13 @@ mdb_cursor_del(MDB_cursor *mc, unsigned int flags)
NULL, &mc->mc_xcursor->mx_cursor, 0, &mp2); NULL, &mc->mc_xcursor->mx_cursor, 0, &mp2);
if (rc == MDB_SUCCESS) { if (rc == MDB_SUCCESS) {
MDB_ppage *top, *parent; MDB_ppage *top, *parent;
MDB_dpage *dp;
ID2 mid;
MDB_node *ni; MDB_node *ni;
unsigned int i; unsigned int i;
#if 0
MDB_dpage *dp;
ID2 mid;
int dirty_root = 0; int dirty_root = 0;
#endif
mc->mc_txn->mt_dbs[mc->mc_dbi].md_entries -= mc->mc_txn->mt_dbs[mc->mc_dbi].md_entries -=
mc->mc_xcursor->mx_txn.mt_dbs[mc->mc_xcursor->mx_cursor.mc_dbi].md_entries; mc->mc_xcursor->mx_txn.mt_dbs[mc->mc_xcursor->mx_cursor.mc_dbi].md_entries;
@ -4353,7 +4371,6 @@ mdb_put(MDB_txn *txn, MDB_dbi dbi,
{ {
MDB_cursor mc; MDB_cursor mc;
MDB_xcursor mx; MDB_xcursor mx;
int rc;
assert(key != NULL); assert(key != NULL);
assert(data != NULL); assert(data != NULL);
@ -4443,6 +4460,38 @@ mdb_env_stat(MDB_env *env, MDB_stat *arg)
return mdb_stat0(env, &env->me_metas[toggle]->mm_dbs[MAIN_DBI], arg); return mdb_stat0(env, &env->me_metas[toggle]->mm_dbs[MAIN_DBI], arg);
} }
static void
mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi)
{
if (txn->mt_dbs[dbi].md_flags & (MDB_REVERSEKEY
#if __BYTE_ORDER == __LITTLE_ENDIAN
|MDB_INTEGERKEY
#endif
))
txn->mt_dbxs[dbi].md_cmp = memnrcmp;
else
txn->mt_dbxs[dbi].md_cmp = memncmp;
if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
if (txn->mt_dbs[dbi].md_flags & MDB_INTEGERDUP) {
if (txn->mt_dbs[dbi].md_flags & MDB_DUPFIXED)
txn->mt_dbxs[dbi].md_dcmp = intcmp;
else
#if __BYTE_ORDER == __LITTLE_ENDIAN
txn->mt_dbxs[dbi].md_dcmp = memnrcmp;
#else
txn->mt_dbxs[dbi].md_dcmp = memncmp;
#endif
} else if (txn->mt_dbs[dbi].md_flags & MDB_REVERSEDUP) {
txn->mt_dbxs[dbi].md_dcmp = memnrcmp;
} else {
txn->mt_dbxs[dbi].md_dcmp = memncmp;
}
} else {
txn->mt_dbxs[dbi].md_dcmp = NULL;
}
}
int mdb_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi) int mdb_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi)
{ {
MDB_val key, data; MDB_val key, data;
@ -4450,14 +4499,23 @@ int mdb_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi)
int rc, dirty = 0; int rc, dirty = 0;
size_t len; size_t len;
if (txn->mt_dbxs[FREE_DBI].md_cmp == NULL) {
mdb_default_cmp(txn, FREE_DBI);
}
/* main DB? */ /* main DB? */
if (!name) { if (!name) {
*dbi = MAIN_DBI; *dbi = MAIN_DBI;
if (flags & (MDB_DUPSORT|MDB_REVERSEKEY|MDB_INTEGERKEY)) if (flags & (MDB_DUPSORT|MDB_REVERSEKEY|MDB_INTEGERKEY))
txn->mt_dbs[MAIN_DBI].md_flags |= (flags & (MDB_DUPSORT|MDB_REVERSEKEY|MDB_INTEGERKEY)); txn->mt_dbs[MAIN_DBI].md_flags |= (flags & (MDB_DUPSORT|MDB_REVERSEKEY|MDB_INTEGERKEY));
mdb_default_cmp(txn, MAIN_DBI);
return MDB_SUCCESS; return MDB_SUCCESS;
} }
if (txn->mt_dbxs[MAIN_DBI].md_cmp == NULL) {
mdb_default_cmp(txn, MAIN_DBI);
}
/* Is the DB already open? */ /* Is the DB already open? */
len = strlen(name); len = strlen(name);
for (i=2; i<txn->mt_numdbs; i++) { for (i=2; i<txn->mt_numdbs; i++) {
@ -4496,8 +4554,6 @@ int mdb_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi)
if (rc == MDB_SUCCESS) { if (rc == MDB_SUCCESS) {
txn->mt_dbxs[txn->mt_numdbs].md_name.mv_data = strdup(name); txn->mt_dbxs[txn->mt_numdbs].md_name.mv_data = strdup(name);
txn->mt_dbxs[txn->mt_numdbs].md_name.mv_size = len; txn->mt_dbxs[txn->mt_numdbs].md_name.mv_size = len;
txn->mt_dbxs[txn->mt_numdbs].md_cmp = NULL;
txn->mt_dbxs[txn->mt_numdbs].md_dcmp = NULL;
txn->mt_dbxs[txn->mt_numdbs].md_rel = NULL; txn->mt_dbxs[txn->mt_numdbs].md_rel = NULL;
txn->mt_dbxs[txn->mt_numdbs].md_parent = MAIN_DBI; txn->mt_dbxs[txn->mt_numdbs].md_parent = MAIN_DBI;
txn->mt_dbxs[txn->mt_numdbs].md_dirty = dirty; txn->mt_dbxs[txn->mt_numdbs].md_dirty = dirty;
@ -4505,6 +4561,7 @@ int mdb_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi)
*dbi = txn->mt_numdbs; *dbi = txn->mt_numdbs;
txn->mt_env->me_dbs[0][txn->mt_numdbs] = txn->mt_dbs[txn->mt_numdbs]; txn->mt_env->me_dbs[0][txn->mt_numdbs] = txn->mt_dbs[txn->mt_numdbs];
txn->mt_env->me_dbs[1][txn->mt_numdbs] = txn->mt_dbs[txn->mt_numdbs]; txn->mt_env->me_dbs[1][txn->mt_numdbs] = txn->mt_dbs[txn->mt_numdbs];
mdb_default_cmp(txn, txn->mt_numdbs);
txn->mt_numdbs++; txn->mt_numdbs++;
} }

@ -157,6 +157,8 @@ typedef void (MDB_rel_func)(void *newptr, void *oldptr, size_t size);
#define MDB_DUPFIXED 0x10 #define MDB_DUPFIXED 0x10
/** with #MDB_DUPSORT, dups are numeric in native byte order */ /** with #MDB_DUPSORT, dups are numeric in native byte order */
#define MDB_INTEGERDUP 0x20 #define MDB_INTEGERDUP 0x20
/** with #MDB_DUPSORT, use reverse string dups */
#define MDB_REVERSEDUP 0x40
/** create DB if not already existing */ /** create DB if not already existing */
#define MDB_CREATE 0x40000 #define MDB_CREATE 0x40000
/** @} */ /** @} */

Loading…
Cancel
Save