#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
* 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.
- * <li>#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.
+ * <li>#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.
* </ul>
* @param[in] mode The UNIX permissions to set on created files. This parameter
* is ignored on Windows.
*
* 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
{
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;
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)
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);
}
}
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;
* 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;
}
* 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)
}
/* 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;
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;