diff options
author | Hallvard Furuseth <hallvard@openldap.org> | 2017-03-12 20:08:53 +0100 |
---|---|---|
committer | Hallvard Furuseth <hallvard@openldap.org> | 2017-03-19 13:24:08 +0100 |
commit | b5e5fcc31dd6719a618cd825a0a9c4ecef5d045b (patch) | |
tree | 7c6c1c22a7b3f7cb5d0c8868a84c65a53d7b0a5f | |
parent | 52c0df1d5052296200d1db607ba4f6bd6eb35f4d (diff) | |
download | lmdb-b5e5fcc31dd6719a618cd825a0a9c4ecef5d045b.tar.gz lmdb-b5e5fcc31dd6719a618cd825a0a9c4ecef5d045b.tar.bz2 lmdb-b5e5fcc31dd6719a618cd825a0a9c4ecef5d045b.zip |
ITS#8582 Fill in MDB_LOCK_FORMAT
Attempt to stop liblmdb variants compiled with conflicting options
from using the lockfile at the same time and thus breaking it.
-rw-r--r-- | libraries/liblmdb/mdb.c | 77 |
1 files changed, 65 insertions, 12 deletions
diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 59e3d93..4a364f7 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -480,12 +480,6 @@ typedef pthread_mutex_t *mdb_mutexref_t; #define MUTEXNAME_PREFIX "/MDB" #endif -#ifdef MDB_USE_SYSV_SEM -#define SYSV_SEM_FLAG 1 /**< SysV sems in lockfile format */ -#else -#define SYSV_SEM_FLAG 0 -#endif - /** @} */ #ifdef MDB_ROBUST_SUPPORTED @@ -628,6 +622,10 @@ static txnid_t mdb_debug_start; #define MDB_DATA_VERSION ((MDB_DEVEL) ? 999 : 1) /** The version number for a database's lockfile format. */ #define MDB_LOCK_VERSION ((MDB_DEVEL) ? 999 : 2) + /** Number of bits representing #MDB_LOCK_VERSION in #MDB_LOCK_FORMAT. + * The remaining bits must leave room for #MDB_lock_desc. + */ +#define MDB_LOCK_VERSION_BITS 12 /** @brief The max size of a key we can write, or 0 for computed max. * @@ -693,6 +691,19 @@ static txnid_t mdb_debug_start; /** Round \b n up to an even number. */ #define EVEN(n) (((n) + 1U) & -2) /* sign-extending -2 to match n+1U */ + /** Least significant 1-bit of \b n. n must be of an unsigned type. */ +#define LOW_BIT(n) ((n) & (-(n))) + + /** (log2(\b p2) % \b n), for p2 = power of 2 and 0 < n < 8. */ +#define LOG2_MOD(p2, n) (7 - 86 / ((p2) % ((1U<<(n))-1) + 11)) + /* Explanation: Let p2 = 2**(n*y + x), x<n and M = (1U<<n)-1. Now p2 = + * (M+1)**y * 2**x = 2**x (mod M). Finally "/" "happens" to return 7-x. + */ + + /** Should be alignment of \b type. Ensure it is a power of 2. */ +#define ALIGNOF2(type) \ + LOW_BIT(offsetof(struct { char ch_; type align_; }, align_)) + /** Used for offsets within a single page. * Since memory pages are typically 4 or 8KB in size, 12-13 bits, * this is plenty. @@ -849,7 +860,6 @@ typedef struct MDB_txninfo { #define mti_magic mt1.mtb.mtb_magic #define mti_format mt1.mtb.mtb_format #define mti_rmutex mt1.mtb.mtb_rmutex -#define mti_rmname mt1.mtb.mtb_rmname #define mti_txnid mt1.mtb.mtb_txnid #define mti_numreaders mt1.mtb.mtb_numreaders #define mti_mutexid mt1.mtb.mtb_mutexid @@ -876,11 +886,54 @@ typedef struct MDB_txninfo { /** Lockfile format signature: version, features and field layout */ #define MDB_LOCK_FORMAT \ - ((uint32_t) \ - ((MDB_LOCK_VERSION) \ - /* Flags which describe functionality */ \ - + (SYSV_SEM_FLAG << 18) \ - + (((MDB_PIDLOCK) != 0) << 16))) + ((uint32_t) \ + (((MDB_LOCK_VERSION) % (1U << MDB_LOCK_VERSION_BITS)) \ + + MDB_lock_desc * (1U << MDB_LOCK_VERSION_BITS))) + + /** Lock type and layout. Values 0-119. _WIN32 implies #MDB_PIDLOCK. + * Some low values are reserved for future tweaks. + */ +#ifdef _WIN32 +# define MDB_LOCK_TYPE (0 + ALIGNOF2(mdb_hash_t)/8 % 2) +#elif defined MDB_USE_POSIX_SEM +# define MDB_LOCK_TYPE (4 + ALIGNOF2(mdb_hash_t)/8 % 2) +#elif defined MDB_USE_SYSV_SEM +# define MDB_LOCK_TYPE (8) +#elif defined MDB_USE_POSIX_MUTEX +/* We do not know the inside of a POSIX mutex and how to check if mutexes + * used by two executables are compatible. Just check alignment and size. + */ +# define MDB_LOCK_TYPE (10 + \ + LOG2_MOD(ALIGNOF2(pthread_mutex_t), 5) + \ + sizeof(pthread_mutex_t) / 4U % 22 * 5) +#endif + +enum { + /** Magic number for lockfile layout and features. + * + * This *attempts* to stop liblmdb variants compiled with conflicting + * options from using the lockfile at the same time and thus breaking + * it. It describes locking types, and sizes and sometimes alignment + * of the various lockfile items. + * + * The detected ranges are mostly guesswork, or based simply on how + * big they could be without using more bits. So we can tweak them + * in good conscience when updating #MDB_LOCK_VERSION. + */ + MDB_lock_desc = + /* Default CACHELINE=64 vs. other values (have seen mention of 32-256) */ + (CACHELINE==64 ? 0 : 1 + LOG2_MOD(CACHELINE >> (CACHELINE>64), 5)) + + 6 * (sizeof(MDB_PID_T)/4 % 3) /* legacy(2) to word(4/8)? */ + + 18 * (sizeof(pthread_t)/4 % 5) /* can be struct{id, active data} */ + + 90 * (sizeof(MDB_txbody) / CACHELINE % 3) + + 270 * (MDB_LOCK_TYPE % 120) + /* The above is < 270*120 < 2**15 */ + + ((sizeof(txnid_t) == 8) << 15) /* 32bit/64bit */ + + ((sizeof(MDB_reader) > CACHELINE) << 16) + /* Not really needed - implied by MDB_LOCK_TYPE != (_WIN32 locking) */ + + (((MDB_PIDLOCK) != 0) << 17) + /* 18 bits total: Must be <= (32 - MDB_LOCK_VERSION_BITS). */ +}; /** @} */ /** Common header for all page types. The page type depends on #mp_flags. |