mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-29 13:58:21 +08:00
lmdb: ITS#8117 - reworks of comparison for MDB_INTEGERKEY and MDB_INTEGERDUP.
Change-Id: Icd24589c7a139c4395de1e7c40f16d2c7ea54cf7
This commit is contained in:
parent
d4bddde7aa
commit
f97cc739cb
1
CHANGES
1
CHANGES
@ -8,6 +8,7 @@ LMDB 0.9.15 Release Engineering
|
|||||||
Fix mdb_load with large values (ITS#8066)
|
Fix mdb_load with large values (ITS#8066)
|
||||||
Fix to retry writes on EINTR (ITS#8106)
|
Fix to retry writes on EINTR (ITS#8106)
|
||||||
Fix mdb_cursor_del on empty DB (ITS#8109)
|
Fix mdb_cursor_del on empty DB (ITS#8109)
|
||||||
|
Fix and Rework comparison for MDB_INTEGERKEY/MDB_INTEGERDUP (ITS#8117)
|
||||||
Added workaround for fdatasync bug in ext3fs
|
Added workaround for fdatasync bug in ext3fs
|
||||||
Build
|
Build
|
||||||
Don't use -fPIC for static lib
|
Don't use -fPIC for static lib
|
||||||
|
102
mdb.c
102
mdb.c
@ -1480,7 +1480,7 @@ static void mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi);
|
|||||||
static int mdb_reader_check0(MDB_env *env, int rlocked, int *dead);
|
static int mdb_reader_check0(MDB_env *env, int rlocked, int *dead);
|
||||||
|
|
||||||
/** @cond */
|
/** @cond */
|
||||||
static MDB_cmp_func mdb_cmp_memn, mdb_cmp_memnr, mdb_cmp_int, mdb_cmp_cint, mdb_cmp_long;
|
static MDB_cmp_func mdb_cmp_memn, mdb_cmp_memnr, mdb_cmp_int_a, mdb_cmp_int_na;
|
||||||
/** @endcond */
|
/** @endcond */
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -1589,7 +1589,7 @@ mdb_assert_fail(MDB_env *env, const char *expr_txt,
|
|||||||
char buf[400];
|
char buf[400];
|
||||||
sprintf(buf, "%.100s:%d: Assertion '%.200s' failed in %.40s()",
|
sprintf(buf, "%.100s:%d: Assertion '%.200s' failed in %.40s()",
|
||||||
file, line, expr_txt, func);
|
file, line, expr_txt, func);
|
||||||
if (env->me_assert_func)
|
if (env && env->me_assert_func)
|
||||||
env->me_assert_func(env, buf);
|
env->me_assert_func(env, buf);
|
||||||
fprintf(stderr, "%s\n", buf);
|
fprintf(stderr, "%s\n", buf);
|
||||||
abort();
|
abort();
|
||||||
@ -5489,29 +5489,41 @@ mdb_env_close(MDB_env *env)
|
|||||||
free(env);
|
free(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compare two items pointing at aligned size_t's */
|
/** Compare two items pointing at aligned size_t's or unsigned int's */
|
||||||
static int
|
static int
|
||||||
mdb_cmp_long(const MDB_val *a, const MDB_val *b)
|
mdb_cmp_int_a(const MDB_val *a, const MDB_val *b)
|
||||||
{
|
{
|
||||||
return (*(size_t *)a->mv_data < *(size_t *)b->mv_data) ? -1 :
|
mdb_eassert(NULL, a->mv_size == b->mv_size);
|
||||||
*(size_t *)a->mv_data > *(size_t *)b->mv_data;
|
mdb_eassert(NULL, 0 == (uintptr_t) a->mv_data % sizeof(int));
|
||||||
}
|
|
||||||
|
|
||||||
/** Compare two items pointing at aligned unsigned int's */
|
if (sizeof(int) != sizeof(size_t) && a->mv_size == sizeof(size_t))
|
||||||
static int
|
return (*(size_t *)a->mv_data < *(size_t *)b->mv_data) ? -1 :
|
||||||
mdb_cmp_int(const MDB_val *a, const MDB_val *b)
|
*(size_t *)a->mv_data > *(size_t *)b->mv_data;
|
||||||
{
|
|
||||||
return (*(unsigned int *)a->mv_data < *(unsigned int *)b->mv_data) ? -1 :
|
mdb_eassert(NULL, a->mv_size == sizeof(int) );
|
||||||
*(unsigned int *)a->mv_data > *(unsigned int *)b->mv_data;
|
return *(int *)a->mv_data - *(int *)b->mv_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compare two items pointing at unsigned ints of unknown alignment.
|
/** Compare two items pointing at unsigned ints of unknown alignment.
|
||||||
* Nodes and keys are guaranteed to be 2-byte aligned.
|
* Nodes and keys are guaranteed to be 2-byte aligned.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
mdb_cmp_cint(const MDB_val *a, const MDB_val *b)
|
mdb_cmp_int_na(const MDB_val *a, const MDB_val *b)
|
||||||
{
|
{
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
mdb_eassert(NULL, a->mv_size == b->mv_size);
|
||||||
|
mdb_eassert(NULL, 0 == a->mv_size % sizeof(short));
|
||||||
|
mdb_eassert(NULL, 0 == (uintptr_t) a->mv_data % sizeof(short)
|
||||||
|
&& 0 == (uintptr_t) b->mv_data % sizeof(short));
|
||||||
|
#ifdef MISALIGNED_OK
|
||||||
|
if (sizeof(int) != sizeof(size_t) && a->mv_size == sizeof(size_t)) {
|
||||||
|
return (*(size_t *)a->mv_data < *(size_t *)b->mv_data) ? -1 :
|
||||||
|
*(size_t *)a->mv_data > *(size_t *)b->mv_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
mdb_eassert(NULL, a->mv_size == sizeof(int) );
|
||||||
|
return *(int *)a->mv_data - *(int *)b->mv_data;
|
||||||
|
|
||||||
|
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||||
unsigned short *u, *c;
|
unsigned short *u, *c;
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
@ -5532,16 +5544,9 @@ mdb_cmp_cint(const MDB_val *a, const MDB_val *b)
|
|||||||
x = *u++ - *c++;
|
x = *u++ - *c++;
|
||||||
} while(!x && u < end);
|
} while(!x && u < end);
|
||||||
return x;
|
return x;
|
||||||
#endif
|
#endif /* BYTE_ORDER & MISALIGNED_OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compare two items pointing at size_t's of unknown alignment. */
|
|
||||||
#ifdef MISALIGNED_OK
|
|
||||||
# define mdb_cmp_clong mdb_cmp_long
|
|
||||||
#else
|
|
||||||
# define mdb_cmp_clong mdb_cmp_cint
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Compare two items lexically */
|
/** Compare two items lexically */
|
||||||
static int
|
static int
|
||||||
mdb_cmp_memn(const MDB_val *a, const MDB_val *b)
|
mdb_cmp_memn(const MDB_val *a, const MDB_val *b)
|
||||||
@ -5617,14 +5622,10 @@ mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp)
|
|||||||
cmp = mc->mc_dbx->md_cmp;
|
cmp = mc->mc_dbx->md_cmp;
|
||||||
|
|
||||||
/* Branch pages have no data, so if using integer keys,
|
/* Branch pages have no data, so if using integer keys,
|
||||||
* alignment is guaranteed. Use faster mdb_cmp_int.
|
* alignment is guaranteed. Use faster mdb_cmp_int_a.
|
||||||
*/
|
*/
|
||||||
if (cmp == mdb_cmp_cint && IS_BRANCH(mp)) {
|
if (cmp == mdb_cmp_int_na && IS_BRANCH(mp))
|
||||||
if (NODEPTR(mp, 1)->mn_ksize == sizeof(size_t))
|
cmp = mdb_cmp_int_a;
|
||||||
cmp = mdb_cmp_long;
|
|
||||||
else
|
|
||||||
cmp = mdb_cmp_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IS_LEAF2(mp)) {
|
if (IS_LEAF2(mp)) {
|
||||||
nodekey.mv_size = mc->mc_db->md_psize;
|
nodekey.mv_size = mc->mc_db->md_psize;
|
||||||
@ -6328,6 +6329,15 @@ mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data,
|
|||||||
if (key->mv_size == 0)
|
if (key->mv_size == 0)
|
||||||
return MDB_BAD_VALSIZE;
|
return MDB_BAD_VALSIZE;
|
||||||
|
|
||||||
|
if ( (mc->mc_db->md_flags & MDB_INTEGERKEY)
|
||||||
|
&& key->mv_size != sizeof(unsigned)
|
||||||
|
&& key->mv_size != sizeof(size_t) ) {
|
||||||
|
#if MDB_DEBUG
|
||||||
|
mdb_cassert(mc, ! "key-size is invalid for MDB_INTEGERKEY");
|
||||||
|
#endif
|
||||||
|
return MDB_BAD_VALSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
if (mc->mc_xcursor)
|
if (mc->mc_xcursor)
|
||||||
mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF);
|
mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF);
|
||||||
|
|
||||||
@ -6849,6 +6859,24 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
|
|||||||
return MDB_BAD_VALSIZE;
|
return MDB_BAD_VALSIZE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if ( (mc->mc_db->md_flags & MDB_INTEGERKEY)
|
||||||
|
&& key->mv_size != sizeof(unsigned)
|
||||||
|
&& key->mv_size != sizeof(size_t) ) {
|
||||||
|
#if MDB_DEBUG
|
||||||
|
mdb_cassert(mc, ! "key-size is invalid for MDB_INTEGERKEY");
|
||||||
|
#endif
|
||||||
|
return MDB_BAD_VALSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (mc->mc_db->md_flags & MDB_INTEGERDUP)
|
||||||
|
&& data->mv_size != sizeof(unsigned)
|
||||||
|
&& data->mv_size != sizeof(size_t) ) {
|
||||||
|
#if MDB_DEBUG
|
||||||
|
mdb_cassert(mc, ! "data-size is invalid MDB_INTEGERDUP");
|
||||||
|
#endif
|
||||||
|
return MDB_BAD_VALSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTF(("==> put db %d key [%s], size %"Z"u, data size %"Z"u",
|
DPRINTF(("==> put db %d key [%s], size %"Z"u, data size %"Z"u",
|
||||||
DDBI(mc), DKEY(key), key ? key->mv_size : 0, data->mv_size));
|
DDBI(mc), DKEY(key), key ? key->mv_size : 0, data->mv_size));
|
||||||
|
|
||||||
@ -6998,10 +7026,6 @@ more:
|
|||||||
if (flags == MDB_CURRENT)
|
if (flags == MDB_CURRENT)
|
||||||
goto current;
|
goto current;
|
||||||
|
|
||||||
#if UINT_MAX < SIZE_MAX
|
|
||||||
if (mc->mc_dbx->md_dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t))
|
|
||||||
mc->mc_dbx->md_dcmp = mdb_cmp_clong;
|
|
||||||
#endif
|
|
||||||
/* does data match? */
|
/* does data match? */
|
||||||
if (!mc->mc_dbx->md_dcmp(data, &olddata)) {
|
if (!mc->mc_dbx->md_dcmp(data, &olddata)) {
|
||||||
if (flags & MDB_NODUPDATA)
|
if (flags & MDB_NODUPDATA)
|
||||||
@ -7803,10 +7827,6 @@ mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node)
|
|||||||
DPRINTF(("Sub-db -%u root page %"Z"u", mx->mx_cursor.mc_dbi,
|
DPRINTF(("Sub-db -%u root page %"Z"u", mx->mx_cursor.mc_dbi,
|
||||||
mx->mx_db.md_root));
|
mx->mx_db.md_root));
|
||||||
mx->mx_dbflag = DB_VALID|DB_DIRTY; /* DB_DIRTY guides mdb_cursor_touch */
|
mx->mx_dbflag = DB_VALID|DB_DIRTY; /* DB_DIRTY guides mdb_cursor_touch */
|
||||||
#if UINT_MAX < SIZE_MAX
|
|
||||||
if (mx->mx_dbx.md_cmp == mdb_cmp_int && mx->mx_db.md_psize == sizeof(size_t))
|
|
||||||
mx->mx_dbx.md_cmp = mdb_cmp_clong;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initialize a cursor for a given transaction and database. */
|
/** Initialize a cursor for a given transaction and database. */
|
||||||
@ -8646,7 +8666,7 @@ mdb_del0(MDB_txn *txn, MDB_dbi dbi,
|
|||||||
MDB_xcursor mx;
|
MDB_xcursor mx;
|
||||||
MDB_cursor_op op;
|
MDB_cursor_op op;
|
||||||
MDB_val rdata, *xdata;
|
MDB_val rdata, *xdata;
|
||||||
int rc, exact = 0;
|
int rc, exact = 0;
|
||||||
DKBUF;
|
DKBUF;
|
||||||
|
|
||||||
DPRINTF(("====> delete db %u key [%s]", dbi, DKEY(key)));
|
DPRINTF(("====> delete db %u key [%s]", dbi, DKEY(key)));
|
||||||
@ -9808,12 +9828,12 @@ mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi)
|
|||||||
|
|
||||||
txn->mt_dbxs[dbi].md_cmp =
|
txn->mt_dbxs[dbi].md_cmp =
|
||||||
(f & MDB_REVERSEKEY) ? mdb_cmp_memnr :
|
(f & MDB_REVERSEKEY) ? mdb_cmp_memnr :
|
||||||
(f & MDB_INTEGERKEY) ? mdb_cmp_cint : mdb_cmp_memn;
|
(f & MDB_INTEGERKEY) ? mdb_cmp_int_na : mdb_cmp_memn;
|
||||||
|
|
||||||
txn->mt_dbxs[dbi].md_dcmp =
|
txn->mt_dbxs[dbi].md_dcmp =
|
||||||
!(f & MDB_DUPSORT) ? 0 :
|
!(f & MDB_DUPSORT) ? 0 :
|
||||||
((f & MDB_INTEGERDUP)
|
((f & MDB_INTEGERDUP)
|
||||||
? ((f & MDB_DUPFIXED) ? mdb_cmp_int : mdb_cmp_cint)
|
? ((f & MDB_DUPFIXED) ? mdb_cmp_int_a : mdb_cmp_int_na)
|
||||||
: ((f & MDB_REVERSEDUP) ? mdb_cmp_memnr : mdb_cmp_memn));
|
: ((f & MDB_REVERSEDUP) ? mdb_cmp_memnr : mdb_cmp_memn));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user