summaryrefslogtreecommitdiff
path: root/plugins/Dbx_mdbx/src
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2018-02-05 12:52:46 +0300
committerGeorge Hazan <ghazan@miranda.im>2018-02-05 12:52:46 +0300
commit7aa0aa3230ef5a94e75093fcd549cd4bff0ff7d0 (patch)
tree0afc8cd4e7f28e0474ae707454e87d811ab96421 /plugins/Dbx_mdbx/src
parent2edf9516a5442149fcadd241f8cb875c79de6841 (diff)
merge of libmdbx
Diffstat (limited to 'plugins/Dbx_mdbx/src')
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/mdbx.h18
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/bits.h21
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/defs.h6
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/lck-posix.c2
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/lck-windows.c14
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c192
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/osal.c2
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/osal.h2
-rw-r--r--plugins/Dbx_mdbx/src/libmdbx/src/version.c2
9 files changed, 183 insertions, 76 deletions
diff --git a/plugins/Dbx_mdbx/src/libmdbx/mdbx.h b/plugins/Dbx_mdbx/src/libmdbx/mdbx.h
index 8df5f4a350..4daf525f6a 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/mdbx.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/mdbx.h
@@ -1,6 +1,6 @@
/* LICENSE AND COPYRUSTING *****************************************************
*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * Copyright 2015-2018 Leonid Yuriev <leo@yuriev.ru>
* and other libmdbx authors: please see AUTHORS file.
* All rights reserved.
*
@@ -60,14 +60,11 @@
/* IMPENDING CHANGES WARNING ***************************************************
*
- * Now MDBX is under active development and until November 2017 is expected a
- * big change both of API and database format. Unfortunately those update will
- * lead to loss of compatibility with previous versions.
+ * MDBX is under active development, database format and API aren't stable
+ * at least until 2018Q2. New version won't be backwards compatible. Main focus
+ * of the rework is to provide clear and robust API and new features.
*
- * The aim of this revolution in providing a clearer robust API and adding new
- * features, including the database properties. */
-
-/*--------------------------------------------------------------------------*/
+ ******************************************************************************/
#ifdef _MSC_VER
#pragma warning(push, 1)
@@ -478,6 +475,8 @@ typedef struct MDBX_envinfo {
uint64_t mi_last_pgno; /* ID of the last used page */
uint64_t mi_recent_txnid; /* ID of the last committed transaction */
uint64_t mi_latter_reader_txnid; /* ID of the last reader transaction */
+ uint64_t mi_self_latter_reader_txnid; /* ID of the last reader transaction of
+ caller process */
uint64_t mi_meta0_txnid, mi_meta0_sign;
uint64_t mi_meta1_txnid, mi_meta1_sign;
uint64_t mi_meta2_txnid, mi_meta2_sign;
@@ -1155,7 +1154,8 @@ LIBMDBX_API int mdbx_dbi_stat(MDBX_txn *txn, MDBX_dbi dbi, MDBX_stat *stat,
* Returns A non-zero error value on failure and 0 on success. */
#define MDBX_TBL_DIRTY 0x01 /* DB was written in this txn */
#define MDBX_TBL_STALE 0x02 /* Named-DB record is older than txnID */
-#define MDBX_TBL_NEW 0x04 /* Named-DB handle opened in this txn */
+#define MDBX_TBL_FRESH 0x04 /* Named-DB handle opened in this txn */
+#define MDBX_TBL_CREAT 0x08 /* Named-DB handle created in this txn */
LIBMDBX_API int mdbx_dbi_flags_ex(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags,
unsigned *state);
LIBMDBX_API int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags);
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/bits.h b/plugins/Dbx_mdbx/src/libmdbx/src/bits.h
index 6915202ae6..a714ae733c 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/bits.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/bits.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * Copyright 2015-2018 Leonid Yuriev <leo@yuriev.ru>
* and other libmdbx authors: please see AUTHORS file.
* All rights reserved.
*
@@ -539,10 +539,11 @@ struct MDBX_txn {
/* Transaction DB Flags */
#define DB_DIRTY MDBX_TBL_DIRTY /* DB was written in this txn */
#define DB_STALE MDBX_TBL_STALE /* Named-DB record is older than txnID */
-#define DB_NEW MDBX_TBL_NEW /* Named-DB handle opened in this txn */
-#define DB_VALID 0x08 /* DB handle is valid, see also MDBX_VALID */
-#define DB_USRVALID 0x10 /* As DB_VALID, but not set for FREE_DBI */
-#define DB_DUPDATA 0x20 /* DB is MDBX_DUPSORT data */
+#define DB_FRESH MDBX_TBL_FRESH /* Named-DB handle opened in this txn */
+#define DB_CREAT MDBX_TBL_CREAT /* Named-DB handle created in this txn */
+#define DB_VALID 0x10 /* DB handle is valid, see also MDBX_VALID */
+#define DB_USRVALID 0x20 /* As DB_VALID, but not set for FREE_DBI */
+#define DB_DUPDATA 0x40 /* DB is MDBX_DUPSORT data */
/* In write txns, array of cursors for each DB */
MDBX_cursor **mt_cursors;
/* Array of flags for each DB */
@@ -743,6 +744,8 @@ struct MDBX_env {
#if defined(_WIN32) || defined(_WIN64)
MDBX_shlock me_remap_guard;
+ /* Workaround for LockFileEx and WriteFile multithread bug */
+ CRITICAL_SECTION me_windowsbug_lock;
#else
mdbx_fastmutex_t me_remap_guard;
#endif
@@ -1177,14 +1180,6 @@ static __inline void SETDSZ(MDBX_node *node, size_t size) {
#define MDBX_COMMIT_PAGES IOV_MAX
#endif
-/* Check txn and dbi arguments to a function */
-#define TXN_DBI_EXIST(txn, dbi, validity) \
- ((dbi) < (txn)->mt_numdbs && ((txn)->mt_dbflags[dbi] & (validity)))
-
-/* Check for misused dbi handles */
-#define TXN_DBI_CHANGED(txn, dbi) \
- ((txn)->mt_dbiseqs[dbi] != (txn)->mt_env->me_dbiseqs[dbi])
-
/* LY: fast enough on most systems
*
* /
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/defs.h b/plugins/Dbx_mdbx/src/libmdbx/src/defs.h
index 5190fa3a35..5e6110f8c5 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/defs.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * Copyright 2015-2018 Leonid Yuriev <leo@yuriev.ru>
* and other libmdbx authors: please see AUTHORS file.
* All rights reserved.
*
@@ -338,7 +338,7 @@
# define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s)
# define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s)
# endif
-#else
+#elif !defined(RUNNING_ON_VALGRIND)
# define VALGRIND_CREATE_MEMPOOL(h,r,z)
# define VALGRIND_DESTROY_MEMPOOL(h)
# define VALGRIND_MEMPOOL_TRIM(h,a,s)
@@ -357,7 +357,7 @@
#ifdef __SANITIZE_ADDRESS__
# include <sanitizer/asan_interface.h>
-#else
+#elif !defined(ASAN_POISON_MEMORY_REGION)
# define ASAN_POISON_MEMORY_REGION(addr, size) \
((void)(addr), (void)(size))
# define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/lck-posix.c b/plugins/Dbx_mdbx/src/libmdbx/src/lck-posix.c
index 14ce3d504d..5916c40e80 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/lck-posix.c
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/lck-posix.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * Copyright 2015-2018 Leonid Yuriev <leo@yuriev.ru>
* and other libmdbx authors: please see AUTHORS file.
* All rights reserved.
*
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/lck-windows.c b/plugins/Dbx_mdbx/src/libmdbx/src/lck-windows.c
index 0cf908aae0..c29164071d 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/lck-windows.c
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/lck-windows.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * Copyright 2015-2018 Leonid Yuriev <leo@yuriev.ru>
* and other libmdbx authors: please see AUTHORS file.
* All rights reserved.
*
@@ -88,16 +88,26 @@ static __inline BOOL funlock(mdbx_filehandle_t fd, uint64_t offset,
#define LCK_WHOLE 0, LCK_MAXLEN
int mdbx_txn_lock(MDBX_env *env, bool dontwait) {
+ if (dontwait) {
+ if (!TryEnterCriticalSection(&env->me_windowsbug_lock))
+ return MDBX_BUSY;
+ } else {
+ EnterCriticalSection(&env->me_windowsbug_lock);
+ }
+
if (flock(env->me_fd, dontwait ? (LCK_EXCLUSIVE | LCK_DONTWAIT)
: (LCK_EXCLUSIVE | LCK_WAITFOR),
LCK_BODY))
return MDBX_SUCCESS;
int rc = GetLastError();
+ LeaveCriticalSection(&env->me_windowsbug_lock);
return (!dontwait || rc != ERROR_LOCK_VIOLATION) ? rc : MDBX_BUSY;
}
void mdbx_txn_unlock(MDBX_env *env) {
- if (!funlock(env->me_fd, LCK_BODY))
+ int rc = funlock(env->me_fd, LCK_BODY);
+ LeaveCriticalSection(&env->me_windowsbug_lock);
+ if (!rc)
mdbx_panic("%s failed: errcode %u", mdbx_func_, GetLastError());
}
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c b/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c
index b3ce3388d5..aac32704a9 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * Copyright 2015-2018 Leonid Yuriev <leo@yuriev.ru>
* and other libmdbx authors: please see AUTHORS file.
* All rights reserved.
*
@@ -2671,6 +2671,7 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
/* Setup db info */
txn->mt_numdbs = env->me_numdbs;
+ mdbx_compiler_barrier();
for (unsigned i = CORE_DBS; i < txn->mt_numdbs; i++) {
unsigned x = env->me_dbflags[i];
txn->mt_dbs[i].md_flags = x & PERSISTENT_FLAGS;
@@ -2735,7 +2736,8 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
MDBX_txn **ret) {
MDBX_txn *txn;
MDBX_ntxn *ntxn;
- int rc, size, tsize;
+ int rc;
+ unsigned size, tsize;
if (unlikely(!env || !ret))
return MDBX_EINVAL;
@@ -2787,10 +2789,11 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
return MDBX_BUSY;
goto renew;
}
- if (unlikely((txn = calloc(1, size)) == NULL)) {
+ if (unlikely((txn = malloc(size)) == NULL)) {
mdbx_debug("calloc: %s", "failed");
return MDBX_ENOMEM;
}
+ memset(txn, 0, tsize);
txn->mt_dbxs = env->me_dbxs; /* static */
txn->mt_dbs = (MDBX_db *)((char *)txn + tsize);
txn->mt_dbflags = (uint8_t *)txn + size - env->me_maxdbs;
@@ -2821,7 +2824,7 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
memcpy(txn->mt_dbs, parent->mt_dbs, txn->mt_numdbs * sizeof(MDBX_db));
/* Copy parent's mt_dbflags, but clear DB_NEW */
for (i = 0; i < txn->mt_numdbs; i++)
- txn->mt_dbflags[i] = parent->mt_dbflags[i] & ~DB_NEW;
+ txn->mt_dbflags[i] = parent->mt_dbflags[i] & ~(DB_FRESH | DB_CREAT);
rc = 0;
ntxn = (MDBX_ntxn *)txn;
ntxn->mnt_pgstate =
@@ -2877,27 +2880,39 @@ uint64_t mdbx_txn_id(MDBX_txn *txn) {
static void mdbx_dbis_update(MDBX_txn *txn, int keep) {
MDBX_dbi n = txn->mt_numdbs;
if (n) {
+ bool locked = false;
MDBX_env *env = txn->mt_env;
uint8_t *tdbflags = txn->mt_dbflags;
for (unsigned i = n; --i >= CORE_DBS;) {
- if (tdbflags[i] & DB_NEW) {
- if (keep) {
- env->me_dbflags[i] = txn->mt_dbs[i].md_flags | MDBX_VALID;
- } else {
- char *ptr = env->me_dbxs[i].md_name.iov_base;
- if (ptr) {
- env->me_dbxs[i].md_name.iov_base = NULL;
- env->me_dbxs[i].md_name.iov_len = 0;
- env->me_dbflags[i] = 0;
- env->me_dbiseqs[i]++;
- free(ptr);
- }
+ if (likely((tdbflags[i] & DB_CREAT) == 0))
+ continue;
+ if (!locked) {
+ mdbx_ensure(env,
+ mdbx_fastmutex_acquire(&env->me_dbi_lock) == MDBX_SUCCESS);
+ locked = true;
+ }
+ if (keep) {
+ env->me_dbflags[i] = txn->mt_dbs[i].md_flags | MDBX_VALID;
+ mdbx_compiler_barrier();
+ if (env->me_numdbs <= i)
+ env->me_numdbs = i + 1;
+ } else {
+ char *ptr = env->me_dbxs[i].md_name.iov_base;
+ if (ptr) {
+ env->me_dbxs[i].md_name.iov_len = 0;
+ mdbx_compiler_barrier();
+ assert(env->me_dbflags[i] == 0);
+ env->me_dbiseqs[i]++;
+ env->me_dbxs[i].md_name.iov_base = NULL;
+ free(ptr);
}
}
}
- if (keep && env->me_numdbs < n)
- env->me_numdbs = n;
+
+ if (unlikely(locked))
+ mdbx_ensure(env,
+ mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS);
}
}
@@ -2914,9 +2929,6 @@ static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) {
return MDBX_PANIC;
}
- /* Export or close DBI handles opened in this txn */
- mdbx_dbis_update(txn, mode & MDBX_END_UPDATE);
-
mdbx_debug("%s txn %" PRIaTXN "%c %p on mdbenv %p, root page %" PRIaPGNO
"/%" PRIaPGNO,
names[mode & MDBX_END_OPMASK], txn->mt_txnid,
@@ -2939,6 +2951,9 @@ static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) {
txn->mt_flags = MDBX_TXN_RDONLY | MDBX_TXN_FINISHED;
txn->mt_owner = 0;
} else if (!F_ISSET(txn->mt_flags, MDBX_TXN_FINISHED)) {
+ /* Export or close DBI handles created in this txn */
+ mdbx_dbis_update(txn, mode & MDBX_END_UPDATE);
+
pgno_t *pghead = env->me_reclaimed_pglist;
if (!(mode & MDBX_END_EOTDONE)) /* !(already closed cursors) */
@@ -3562,6 +3577,44 @@ done:
return MDBX_SUCCESS;
}
+/* Check for misused dbi handles */
+#define TXN_DBI_CHANGED(txn, dbi) \
+ ((txn)->mt_dbiseqs[dbi] != (txn)->mt_env->me_dbiseqs[dbi])
+
+/* Import DBI which opened after txn started into context */
+static __cold bool mdbx_txn_import_dbi(MDBX_txn *txn, MDBX_dbi dbi) {
+ MDBX_env *env = txn->mt_env;
+ if (dbi < CORE_DBS || dbi >= env->me_numdbs)
+ return false;
+
+ mdbx_ensure(env, mdbx_fastmutex_acquire(&env->me_dbi_lock) == MDBX_SUCCESS);
+ const unsigned snap_numdbs = env->me_numdbs;
+ mdbx_compiler_barrier();
+ for (unsigned i = CORE_DBS; i < snap_numdbs; ++i) {
+ if (i >= txn->mt_numdbs)
+ txn->mt_dbflags[i] = 0;
+ if (!(txn->mt_dbflags[i] & DB_USRVALID) &&
+ (env->me_dbflags[i] & MDBX_VALID)) {
+ txn->mt_dbs[i].md_flags = env->me_dbflags[i] & PERSISTENT_FLAGS;
+ txn->mt_dbflags[i] = DB_VALID | DB_USRVALID | DB_STALE;
+ assert(txn->mt_dbxs[i].md_cmp != NULL);
+ }
+ }
+ txn->mt_numdbs = snap_numdbs;
+
+ mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS);
+ return txn->mt_dbflags[dbi] & DB_USRVALID;
+}
+
+/* Check txn and dbi arguments to a function */
+static __inline bool TXN_DBI_EXIST(MDBX_txn *txn, MDBX_dbi dbi,
+ unsigned validity) {
+ if (likely(dbi < txn->mt_numdbs && (txn->mt_dbflags[dbi] & validity)))
+ return true;
+
+ return mdbx_txn_import_dbi(txn, dbi);
+}
+
int mdbx_txn_commit(MDBX_txn *txn) {
int rc;
@@ -3644,7 +3697,7 @@ int mdbx_txn_commit(MDBX_txn *txn) {
for (i = CORE_DBS; i < txn->mt_numdbs; i++) {
/* preserve parent's DB_NEW status */
parent->mt_dbflags[i] =
- txn->mt_dbflags[i] | (parent->mt_dbflags[i] & DB_NEW);
+ txn->mt_dbflags[i] | (parent->mt_dbflags[i] & (DB_CREAT | DB_FRESH));
}
dst = parent->mt_rw_dirtylist;
@@ -4450,6 +4503,7 @@ int __cold mdbx_env_create(MDBX_env **penv) {
#if defined(_WIN32) || defined(_WIN64)
mdbx_shlock_init(&env->me_remap_guard);
+ InitializeCriticalSection(&env->me_windowsbug_lock);
#else
rc = mdbx_fastmutex_init(&env->me_remap_guard);
if (unlikely(rc != MDBX_SUCCESS)) {
@@ -5281,8 +5335,8 @@ int __cold mdbx_env_open_ex(MDBX_env *env, const char *path, unsigned flags,
env->me_path = mdbx_strdup(path);
env->me_dbxs = calloc(env->me_maxdbs, sizeof(MDBX_dbx));
- env->me_dbflags = calloc(env->me_maxdbs, sizeof(uint16_t));
- env->me_dbiseqs = calloc(env->me_maxdbs, sizeof(unsigned));
+ env->me_dbflags = calloc(env->me_maxdbs, sizeof(env->me_dbflags[0]));
+ env->me_dbiseqs = calloc(env->me_maxdbs, sizeof(env->me_dbiseqs[0]));
if (!(env->me_dbxs && env->me_path && env->me_dbflags && env->me_dbiseqs)) {
rc = MDBX_ENOMEM;
goto bailout;
@@ -5487,6 +5541,14 @@ int __cold mdbx_env_close_ex(MDBX_env *env, int dont_sync) {
mdbx_env_close0(env);
mdbx_ensure(env, mdbx_fastmutex_destroy(&env->me_dbi_lock) == MDBX_SUCCESS);
+#if defined(_WIN32) || defined(_WIN64)
+ /* me_remap_guard don't have destructor (Slim Reader/Writer Lock) */
+ DeleteCriticalSection(&env->me_windowsbug_lock);
+#else
+ mdbx_ensure(env,
+ mdbx_fastmutex_destroy(&env->me_remap_guard) == MDBX_SUCCESS);
+#endif /* Windows */
+
env->me_signature = 0;
free(env);
@@ -10099,15 +10161,19 @@ int __cold mdbx_env_info(MDBX_env *env, MDBX_envinfo *arg, size_t bytes) {
arg->mi_dxb_pagesize = env->me_psize;
arg->mi_sys_pagesize = env->me_os_psize;
- arg->mi_latter_reader_txnid = 0;
+ arg->mi_self_latter_reader_txnid = arg->mi_latter_reader_txnid = 0;
if (env->me_lck) {
MDBX_reader *r = env->me_lck->mti_readers;
- arg->mi_latter_reader_txnid = arg->mi_recent_txnid;
+ arg->mi_self_latter_reader_txnid = arg->mi_latter_reader_txnid =
+ arg->mi_recent_txnid;
for (unsigned i = 0; i < arg->mi_numreaders; ++i) {
- if (r[i].mr_pid) {
+ const mdbx_pid_t pid = r[i].mr_pid;
+ if (pid) {
const txnid_t txnid = r[i].mr_txnid;
if (arg->mi_latter_reader_txnid > txnid)
arg->mi_latter_reader_txnid = txnid;
+ if (pid == env->me_pid && arg->mi_self_latter_reader_txnid > txnid)
+ arg->mi_self_latter_reader_txnid = txnid;
}
}
}
@@ -10205,8 +10271,8 @@ int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags,
/* Is the DB already open? */
size_t len = strlen(table_name);
- MDBX_dbi scan, slot = txn->mt_numdbs;
- for (scan = txn->mt_numdbs; --scan >= CORE_DBS;) {
+ MDBX_dbi scan, slot;
+ for (slot = scan = txn->mt_numdbs; --scan >= CORE_DBS;) {
if (!txn->mt_dbxs[scan].md_name.iov_len) {
/* Remember this free slot */
slot = scan;
@@ -10261,7 +10327,38 @@ int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags,
return err;
}
- unsigned dbflag = DB_NEW | DB_VALID | DB_USRVALID;
+ if (txn->mt_numdbs < env->me_numdbs) {
+ for (unsigned i = txn->mt_numdbs; i < env->me_numdbs; ++i) {
+ txn->mt_dbflags[i] = 0;
+ if (env->me_dbflags[i] & MDBX_VALID) {
+ txn->mt_dbs[i].md_flags = env->me_dbflags[i] & PERSISTENT_FLAGS;
+ txn->mt_dbflags[i] = DB_VALID | DB_USRVALID | DB_STALE;
+ assert(txn->mt_dbxs[i].md_cmp != NULL);
+ }
+ }
+ txn->mt_numdbs = env->me_numdbs;
+ }
+
+ for (slot = scan = txn->mt_numdbs; --scan >= CORE_DBS;) {
+ if (!txn->mt_dbxs[scan].md_name.iov_len) {
+ /* Remember this free slot */
+ slot = scan;
+ continue;
+ }
+ if (len == txn->mt_dbxs[scan].md_name.iov_len &&
+ !strncmp(table_name, txn->mt_dbxs[scan].md_name.iov_base, len)) {
+ *dbi = scan;
+ rc = mdbx_dbi_bind(txn, scan, user_flags, keycmp, datacmp);
+ goto unlock_return_rc;
+ }
+ }
+
+ if (unlikely(slot >= env->me_maxdbs)) {
+ rc = MDBX_DBS_FULL;
+ goto unlock_return_rc;
+ }
+
+ unsigned dbflag = DB_FRESH | DB_VALID | DB_USRVALID;
if (unlikely(rc)) {
/* MDBX_NOTFOUND and MDBX_CREATE: Create new DB */
assert(rc == MDBX_NOTFOUND);
@@ -10278,33 +10375,37 @@ int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags,
if (unlikely(rc != MDBX_SUCCESS))
goto bailout;
- dbflag |= DB_DIRTY;
+ dbflag |= DB_DIRTY | DB_CREAT;
}
/* Got info, register DBI in this txn */
- txn->mt_dbxs[slot].md_name.iov_base = namedup;
- txn->mt_dbxs[slot].md_name.iov_len = len;
txn->mt_dbxs[slot].md_cmp = nullptr;
txn->mt_dbxs[slot].md_dcmp = nullptr;
- txn->mt_dbflags[slot] = (uint8_t)dbflag;
- txn->mt_dbiseqs[slot] = (env->me_dbiseqs[slot] += 1);
-
txn->mt_dbs[slot] = *(MDBX_db *)data.iov_base;
+ env->me_dbflags[slot] = 0;
rc = mdbx_dbi_bind(txn, slot, user_flags, keycmp, datacmp);
if (unlikely(rc != MDBX_SUCCESS)) {
- assert((dbflag & DB_DIRTY) == 0);
- /* cleanup slot */
- txn->mt_dbxs[slot].md_name.iov_base = NULL;
- txn->mt_dbxs[slot].md_name.iov_len = 0;
- txn->mt_dbflags[slot] = 0;
+ assert((dbflag & DB_CREAT) == 0);
bailout:
free(namedup);
} else {
- *dbi = slot;
+ txn->mt_dbiseqs[slot] = (env->me_dbiseqs[slot] += 1);
+ txn->mt_dbflags[slot] = (uint8_t)dbflag;
+ txn->mt_dbxs[slot].md_name.iov_base = namedup;
+ mdbx_compiler_barrier();
+ txn->mt_dbxs[slot].md_name.iov_len = len;
if (slot == txn->mt_numdbs)
txn->mt_numdbs++;
+ if ((dbflag & DB_CREAT) == 0) {
+ env->me_dbflags[slot] = txn->mt_dbs[slot].md_flags | MDBX_VALID;
+ mdbx_compiler_barrier();
+ if (env->me_numdbs <= slot)
+ env->me_numdbs = slot + 1;
+ }
+ *dbi = slot;
}
+unlock_return_rc:
mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS);
return rc;
}
@@ -10352,10 +10453,11 @@ static int mdbx_dbi_close_locked(MDBX_env *env, MDBX_dbi dbi) {
if (unlikely(!ptr))
return MDBX_BAD_DBI;
- env->me_dbxs[dbi].md_name.iov_base = NULL;
- env->me_dbxs[dbi].md_name.iov_len = 0;
env->me_dbflags[dbi] = 0;
+ env->me_dbxs[dbi].md_name.iov_len = 0;
+ mdbx_compiler_barrier();
env->me_dbiseqs[dbi]++;
+ env->me_dbxs[dbi].md_name.iov_base = NULL;
free(ptr);
return MDBX_SUCCESS;
}
@@ -10387,7 +10489,7 @@ int mdbx_dbi_flags_ex(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags,
return MDBX_EINVAL;
*flags = txn->mt_dbs[dbi].md_flags & PERSISTENT_FLAGS;
- *state = txn->mt_dbflags[dbi] & (DB_NEW | DB_DIRTY | DB_STALE);
+ *state = txn->mt_dbflags[dbi] & (DB_FRESH | DB_CREAT | DB_DIRTY | DB_STALE);
return MDBX_SUCCESS;
}
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/osal.c b/plugins/Dbx_mdbx/src/libmdbx/src/osal.c
index af0b88ce88..f95ac57a12 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/osal.c
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/osal.c
@@ -1,7 +1,7 @@
/* https://en.wikipedia.org/wiki/Operating_system_abstraction_layer */
/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * Copyright 2015-2018 Leonid Yuriev <leo@yuriev.ru>
* and other libmdbx authors: please see AUTHORS file.
* All rights reserved.
*
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/osal.h b/plugins/Dbx_mdbx/src/libmdbx/src/osal.h
index eb6cd5ee10..54559388c9 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/osal.h
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/osal.h
@@ -1,7 +1,7 @@
/* https://en.wikipedia.org/wiki/Operating_system_abstraction_layer */
/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * Copyright 2015-2018 Leonid Yuriev <leo@yuriev.ru>
* and other libmdbx authors: please see AUTHORS file.
* All rights reserved.
*
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/version.c b/plugins/Dbx_mdbx/src/libmdbx/src/version.c
index ef4f99088d..aed4fab508 100644
--- a/plugins/Dbx_mdbx/src/libmdbx/src/version.c
+++ b/plugins/Dbx_mdbx/src/libmdbx/src/version.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
+ * Copyright 2015-2018 Leonid Yuriev <leo@yuriev.ru>
* and other libmdbx authors: please see AUTHORS file.
* All rights reserved.
*