From 79eac42c0f1fdd6c807f0b601c03ab35bf7d7d8e Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 3 Oct 2013 10:26:44 -0700 Subject: [PATCH] s/MDB_NORDLOCK/MDB_NOLOCK/ Leave all lock management to the caller. --- libraries/liblmdb/lmdb.h | 16 ++++++++------- libraries/liblmdb/mdb.c | 43 +++++++++++++++++++++++++--------------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/libraries/liblmdb/lmdb.h b/libraries/liblmdb/lmdb.h index 968862f..8cdac26 100644 --- a/libraries/liblmdb/lmdb.h +++ b/libraries/liblmdb/lmdb.h @@ -269,8 +269,8 @@ typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *rel #define MDB_MAPASYNC 0x100000 /** tie reader locktable slots to #MDB_txn objects instead of to threads */ #define MDB_NOTLS 0x200000 - /** for #MDB_RDONLY env, don't use reader locktable, caller must manage read/write concurrency */ -#define MDB_NORDLOCK 0x400000 + /** don't do any locking, caller must manage their own locks */ +#define MDB_NOLOCK 0x400000 /** @} */ /** @defgroup mdb_dbi_open Database Flags @@ -527,11 +527,13 @@ int mdb_env_create(MDB_env **env); * user threads over individual OS threads need this option. Such an * application must also serialize the write transactions in an OS * thread, since MDB's write locking is unaware of the user threads. - *
  • #MDB_NORDLOCK - * Don't use the reader locktable at all. This flag is only valid - * with #MDB_RDONLY. MDB will use no read locks. If other processes - * may be opening the environment with write access, the callers - * must manage read/write locks themselves. + *
  • #MDB_NOLOCK + * Don't do any locking. If concurrent access is anticipated, the + * caller must manage all concurrency itself. For proper operation + * the caller must enforce single-writer semantics, and must ensure + * that no readers are using old transactions while a writer is + * active. The simplest approach is to use an exclusive lock so that + * no readers may be active at all when a writer begins. * * @param[in] mode The UNIX permissions to set on created files. This parameter * is ignored on Windows. diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 637cd08..30b562c 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -425,7 +425,8 @@ typedef uint16_t indx_t; * * If #MDB_NOTLS is set, the slot address is not saved in thread-specific data. * - * No reader table is used if the database is on a read-only filesystem. + * No reader table is used if the database is on a read-only filesystem, or + * if #MDB_NOLOCK is set. * * Since the database uses multi-version concurrency control, readers don't * actually need any locking. This table is used to keep track of which @@ -1572,12 +1573,14 @@ mdb_find_oldest(MDB_txn *txn) { int i; txnid_t mr, oldest = txn->mt_txnid - 1; - MDB_reader *r = txn->mt_env->me_txns->mti_readers; - for (i = txn->mt_env->me_txns->mti_numreaders; --i >= 0; ) { - if (r[i].mr_pid) { - mr = r[i].mr_txnid; - if (oldest > mr) - oldest = mr; + if (txn->mt_env->me_txns) { + MDB_reader *r = txn->mt_env->me_txns->mti_readers; + for (i = txn->mt_env->me_txns->mti_numreaders; --i >= 0; ) { + if (r[i].mr_pid) { + mr = r[i].mr_txnid; + if (oldest > mr) + oldest = mr; + } } } return oldest; @@ -2174,10 +2177,15 @@ mdb_txn_renew0(MDB_txn *txn) meta = env->me_metas[txn->mt_txnid & 1]; } } else { - LOCK_MUTEX_W(env); + if (env->me_txns) { + LOCK_MUTEX_W(env); - txn->mt_txnid = env->me_txns->mti_txnid; - meta = env->me_metas[txn->mt_txnid & 1]; + txn->mt_txnid = env->me_txns->mti_txnid; + meta = env->me_metas[txn->mt_txnid & 1]; + } else { + meta = env->me_metas[ mdb_env_pick_meta(env) ]; + txn->mt_txnid = meta->mm_txnid; + } txn->mt_txnid++; #if MDB_DEBUG if (txn->mt_txnid == mdb_debug_start) @@ -2417,7 +2425,8 @@ mdb_txn_reset0(MDB_txn *txn, const char *act) env->me_txn = NULL; /* The writer mutex was locked in mdb_txn_begin. */ - UNLOCK_MUTEX_W(env); + if (env->me_txns) + UNLOCK_MUTEX_W(env); } } @@ -2934,7 +2943,8 @@ done: env->me_txn = NULL; mdb_dbis_update(txn, 1); - UNLOCK_MUTEX_W(env); + if (env->me_txns) + UNLOCK_MUTEX_W(env); free(txn); return MDB_SUCCESS; @@ -3180,7 +3190,8 @@ done: * readers will get consistent data regardless of how fresh or * how stale their view of these values is. */ - env->me_txns->mti_txnid = txn->mt_txnid; + if (env->me_txns) + env->me_txns->mti_txnid = txn->mt_txnid; return MDB_SUCCESS; } @@ -3900,7 +3911,7 @@ fail: * environment and re-opening it with the new flags. */ #define CHANGEABLE (MDB_NOSYNC|MDB_NOMETASYNC|MDB_MAPASYNC) -#define CHANGELESS (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY|MDB_WRITEMAP|MDB_NOTLS|MDB_NORDLOCK) +#define CHANGELESS (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY|MDB_WRITEMAP|MDB_NOTLS|MDB_NOLOCK) int mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode) @@ -3953,7 +3964,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode } /* For RDONLY, get lockfile after we know datafile exists */ - if (!F_ISSET(flags, MDB_RDONLY)) { + if (!(flags & (MDB_RDONLY|MDB_NOLOCK))) { rc = mdb_env_setup_locks(env, lpath, mode, &excl); if (rc) goto leave; @@ -3983,7 +3994,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode goto leave; } - if ((flags & (MDB_RDONLY|MDB_NORDLOCK)) == MDB_RDONLY) { + if ((flags & (MDB_RDONLY|MDB_NOLOCK)) == MDB_RDONLY) { rc = mdb_env_setup_locks(env, lpath, mode, &excl); if (rc) goto leave;