mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-04 17:54:13 +08:00
lmdb: rework key/data comparison to avoid alignment errors.
Change-Id: I291b50ad6f7dd18f6cbdef34028d917e10166cf1
This commit is contained in:
parent
41d38a1e4d
commit
b60f510355
119
mdb.c
119
mdb.c
@ -1194,7 +1194,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_a, mdb_cmp_int_na;
|
static MDB_cmp_func mdb_cmp_memn, mdb_cmp_memnr, mdb_cmp_int_ai, mdb_cmp_int_a2, mdb_cmp_int_ua;
|
||||||
/** @endcond */
|
/** @endcond */
|
||||||
|
|
||||||
/** Return the library version info. */
|
/** Return the library version info. */
|
||||||
@ -4649,7 +4649,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned flags, mode_t mode)
|
|||||||
rc = ENOMEM;
|
rc = ENOMEM;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
env->me_dbxs[FREE_DBI].md_cmp = mdb_cmp_int_a; /* aligned MDB_INTEGERKEY */
|
env->me_dbxs[FREE_DBI].md_cmp = mdb_cmp_int_ai; /* aligned MDB_INTEGERKEY */
|
||||||
|
|
||||||
/* For RDONLY, get lockfile after we know datafile exists */
|
/* For RDONLY, get lockfile after we know datafile exists */
|
||||||
if (!(flags & MDB_RDONLY)) {
|
if (!(flags & MDB_RDONLY)) {
|
||||||
@ -4818,29 +4818,26 @@ mdb_env_close_ex(MDB_env *env, int dont_sync)
|
|||||||
free(env);
|
free(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compare two items pointing at aligned unsigned int's.
|
/** Compare two items pointing at aligned unsigned int's. */
|
||||||
*
|
|
||||||
* This is also set as #MDB_INTEGERDUP|#MDB_DUPFIXED's #MDB_dbx.%md_dcmp.
|
|
||||||
*/
|
|
||||||
static int
|
static int
|
||||||
mdb_cmp_int_a(const MDB_val *a, const MDB_val *b)
|
mdb_cmp_int_ai(const MDB_val *a, const MDB_val *b)
|
||||||
{
|
{
|
||||||
mdb_assert(NULL, a->mv_size == b->mv_size);
|
mdb_assert(NULL, a->mv_size == b->mv_size);
|
||||||
mdb_assert(NULL, 0 == (uintptr_t) a->mv_data % sizeof(int));
|
mdb_assert(NULL, 0 == (uintptr_t) a->mv_data % sizeof(int)
|
||||||
|
&& 0 == (uintptr_t) b->mv_data % sizeof(int));
|
||||||
|
|
||||||
if (sizeof(int) != sizeof(size_t) && likely(a->mv_size == sizeof(size_t)))
|
if (sizeof(int) != sizeof(size_t) && likely(a->mv_size == sizeof(size_t))) {
|
||||||
return (*(size_t *)a->mv_data < *(size_t *)b->mv_data) ? -1 :
|
return (*(size_t *)a->mv_data < *(size_t *)b->mv_data) ? -1 :
|
||||||
*(size_t *)a->mv_data > *(size_t *)b->mv_data;
|
*(size_t *)a->mv_data > *(size_t *)b->mv_data;
|
||||||
|
}
|
||||||
|
|
||||||
mdb_assert(NULL, a->mv_size == sizeof(int) );
|
mdb_assert(NULL, a->mv_size == sizeof(int) );
|
||||||
return *(int *)a->mv_data - *(int *)b->mv_data;
|
return *(int *)a->mv_data - *(int *)b->mv_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compare two items pointing at unsigneds of unknown alignment.
|
/** Compare two items pointing at 2-byte aligned unsigned int's. */
|
||||||
* Nodes and keys are guaranteed to be 2-byte aligned.
|
|
||||||
*/
|
|
||||||
static int
|
static int
|
||||||
mdb_cmp_int_na(const MDB_val *a, const MDB_val *b)
|
mdb_cmp_int_a2(const MDB_val *a, const MDB_val *b)
|
||||||
{
|
{
|
||||||
mdb_assert(NULL, a->mv_size == b->mv_size);
|
mdb_assert(NULL, a->mv_size == b->mv_size);
|
||||||
mdb_assert(NULL, 0 == a->mv_size % sizeof(short));
|
mdb_assert(NULL, 0 == a->mv_size % sizeof(short));
|
||||||
@ -4854,29 +4851,68 @@ mdb_cmp_int_na(const MDB_val *a, const MDB_val *b)
|
|||||||
|
|
||||||
mdb_assert(NULL, a->mv_size == sizeof(int) );
|
mdb_assert(NULL, a->mv_size == sizeof(int) );
|
||||||
return *(int *)a->mv_data - *(int *)b->mv_data;
|
return *(int *)a->mv_data - *(int *)b->mv_data;
|
||||||
|
|
||||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
|
||||||
unsigned short *u, *c;
|
|
||||||
int x;
|
|
||||||
|
|
||||||
u = (unsigned short *) ((char *) a->mv_data + a->mv_size);
|
|
||||||
c = (unsigned short *) ((char *) b->mv_data + a->mv_size);
|
|
||||||
do {
|
|
||||||
x = *--u - *--c;
|
|
||||||
} while(!x && u > (unsigned short *)a->mv_data);
|
|
||||||
return x;
|
|
||||||
#else
|
#else
|
||||||
unsigned short *u, *c, *end;
|
{
|
||||||
int x;
|
int x;
|
||||||
|
unsigned short *u, *c;
|
||||||
|
|
||||||
end = (unsigned short *) ((char *) a->mv_data + a->mv_size);
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
u = (unsigned short *)a->mv_data;
|
u = (unsigned short *) ((char *) a->mv_data + a->mv_size);
|
||||||
c = (unsigned short *)b->mv_data;
|
c = (unsigned short *) ((char *) b->mv_data + a->mv_size);
|
||||||
do {
|
do {
|
||||||
x = *u++ - *c++;
|
x = *--u - *--c;
|
||||||
} while(!x && u < end);
|
} while(!x && u > (unsigned short *)a->mv_data);
|
||||||
return x;
|
#else /* BYTE_ORDER */
|
||||||
#endif /* BYTE_ORDER & MISALIGNED_OK */
|
unsigned short *end;
|
||||||
|
|
||||||
|
end = (unsigned short *) ((char *) a->mv_data + a->mv_size);
|
||||||
|
u = (unsigned short *)a->mv_data;
|
||||||
|
c = (unsigned short *)b->mv_data;
|
||||||
|
do {
|
||||||
|
x = *u++ - *c++;
|
||||||
|
} while(!x && u < end);
|
||||||
|
#endif /* BYTE_ORDER */
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
#endif /* MISALIGNED_OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compare two items pointing at unsigneds of unknown alignment.
|
||||||
|
*
|
||||||
|
* This is also set as #MDB_INTEGERDUP|#MDB_DUPFIXED's #MDB_dbx.%md_dcmp.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
mdb_cmp_int_ua(const MDB_val *a, const MDB_val *b)
|
||||||
|
{
|
||||||
|
mdb_assert(NULL, a->mv_size == b->mv_size);
|
||||||
|
#if MISALIGNED_OK
|
||||||
|
if (sizeof(int) != sizeof(size_t) && likely(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_assert(NULL, a->mv_size == sizeof(int) );
|
||||||
|
return *(int *)a->mv_data - *(int *)b->mv_data;
|
||||||
|
#else
|
||||||
|
mdb_assert(NULL, a->mv_size == sizeof(int) || a->mv_size == sizeof(size_t));
|
||||||
|
{
|
||||||
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
|
const unsigned char *p1, *p2;
|
||||||
|
int diff;
|
||||||
|
|
||||||
|
p1 = (const unsigned char *)a->mv_data + a->mv_size;
|
||||||
|
p2 = (const unsigned char *)b->mv_data + a->mv_size;
|
||||||
|
|
||||||
|
do {
|
||||||
|
diff = *--p1 - *--p2;
|
||||||
|
if (diff)
|
||||||
|
return diff;
|
||||||
|
} while(p1 != a->mv_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else /* BYTE_ORDER */
|
||||||
|
return memcmp(a->mv_data, b->mv_data, a->mv_size);
|
||||||
|
#endif /* BYTE_ORDER */
|
||||||
|
#endif /* MISALIGNED_OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compare two items lexically */
|
/** Compare two items lexically */
|
||||||
@ -4954,10 +4990,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_a.
|
* alignment is guaranteed. Use faster mdb_cmp_int_ai.
|
||||||
*/
|
*/
|
||||||
if (cmp == mdb_cmp_int_na && IS_BRANCH(mp))
|
if (cmp == mdb_cmp_int_a2 && IS_BRANCH(mp))
|
||||||
cmp = mdb_cmp_int_a;
|
cmp = mdb_cmp_int_ai;
|
||||||
|
|
||||||
if (IS_LEAF2(mp)) {
|
if (IS_LEAF2(mp)) {
|
||||||
nodekey.mv_size = mc->mc_db->md_xsize;
|
nodekey.mv_size = mc->mc_db->md_xsize;
|
||||||
@ -9124,17 +9160,16 @@ mdb_env_info(MDB_env *env, MDB_envinfo *arg)
|
|||||||
static void
|
static void
|
||||||
mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi)
|
mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi)
|
||||||
{
|
{
|
||||||
uint16_t f = txn->mt_dbs[dbi].md_flags;
|
unsigned f = txn->mt_dbs[dbi].md_flags;
|
||||||
|
|
||||||
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_int_na : mdb_cmp_memn;
|
(f & MDB_INTEGERKEY) ? mdb_cmp_int_a2 : 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) ? mdb_cmp_int_ua :
|
||||||
? ((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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned flags, MDB_dbi *dbi)
|
int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned flags, MDB_dbi *dbi)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user