mdbx: add 'canary' support for libfpta.

Change-Id: I62c68f149adf38d65aa9371a1fb3adac405d23ed
This commit is contained in:
Leo Yuriev 2016-11-21 20:50:39 +03:00
parent aa4fd0ec76
commit 17c6555a7f
3 changed files with 61 additions and 1 deletions

22
mdb.c
View File

@ -778,6 +778,10 @@ typedef struct MDB_meta {
volatile uint64_t mm_datasync_sign;
#define META_IS_WEAK(meta) ((meta)->mm_datasync_sign == MDB_DATASIGN_WEAK)
#define META_IS_STEADY(meta) ((meta)->mm_datasync_sign > MDB_DATASIGN_WEAK)
#if MDBX_MODE_ENABLED
volatile mdbx_canary mm_canary;
#endif
} MDB_meta;
/** Buffer for a stack-allocated meta page.
@ -809,7 +813,7 @@ typedef struct MDB_dbx {
* Every operation requires a transaction handle.
*/
struct MDB_txn {
#define MDBX_MT_SIGNATURE 0x706C553B
#define MDBX_MT_SIGNATURE 0x93D53A31
unsigned mt_signature;
MDB_txn *mt_parent; /**< parent of a nested txn */
/** Nested txn under this txn, set together with flag #MDB_TXN_HAS_CHILD */
@ -895,6 +899,10 @@ struct MDB_txn {
* dirty_list into mt_parent after freeing hidden mt_parent pages.
*/
unsigned mt_dirty_room;
#if MDBX_MODE_ENABLED
mdbx_canary mt_canary;
#endif
};
/** Enough space for 2^32 nodes with minimum of 2 keys per node. I.e., plenty.
@ -2842,6 +2850,9 @@ mdb_txn_renew0(MDB_txn *txn, unsigned flags)
txn->mt_next_pgno = meta->mm_last_pg+1;
/* Copy the DB info and flags */
memcpy(txn->mt_dbs, meta->mm_dbs, CORE_DBS * sizeof(MDB_db));
#if MDBX_MODE_ENABLED
txn->mt_canary = meta->mm_canary;
#endif
break;
}
}
@ -2858,6 +2869,9 @@ mdb_txn_renew0(MDB_txn *txn, unsigned flags)
pthread_mutex_lock(&tsan_mutex);
#endif
MDB_meta *meta = mdb_meta_head_w(env);
#if MDBX_MODE_ENABLED
txn->mt_canary = meta->mm_canary;
#endif
txn->mt_txnid = meta->mm_txnid + 1;
txn->mt_flags = flags;
#ifdef __SANITIZE_THREAD__
@ -3919,6 +3933,9 @@ mdb_txn_commit(MDB_txn *txn)
meta.mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI];
meta.mm_last_pg = txn->mt_next_pgno - 1;
meta.mm_txnid = txn->mt_txnid;
#if MDBX_MODE_ENABLED
meta.mm_canary = txn->mt_canary;
#endif
rc = mdb_env_sync0(env, env->me_flags | txn->mt_flags, &meta);
}
@ -4155,6 +4172,9 @@ mdb_env_sync0(MDB_env *env, unsigned flags, MDB_meta *pending)
target->mm_dbs[FREE_DBI] = pending->mm_dbs[FREE_DBI];
target->mm_dbs[MAIN_DBI] = pending->mm_dbs[MAIN_DBI];
target->mm_last_pg = pending->mm_last_pg;
#if MDBX_MODE_ENABLED
target->mm_canary = pending->mm_canary;
#endif
/* LY: 'commit' the meta */
target->mm_txnid = pending->mm_txnid;
target->mm_datasync_sign = pending->mm_datasync_sign;

32
mdbx.c
View File

@ -320,3 +320,35 @@ mdbx_env_pgwalk(MDB_txn *txn, MDBX_pgvisitor_func* visitor, void* user)
rc = visitor(P_INVALID, 0, user, NULL, NULL, 0, 0, 0, 0);
return rc;
}
int mdbx_canary_put(MDB_txn *txn, const mdbx_canary* canary)
{
if (unlikely(!txn))
return EINVAL;
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDB_VERSION_MISMATCH;
if (unlikely(F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)))
return EACCES;
if (likely(canary)) {
txn->mt_canary.x = canary->x;
txn->mt_canary.y = canary->y;
txn->mt_canary.z = canary->z;
}
txn->mt_canary.v = txn->mt_txnid;
return MDB_SUCCESS;
}
size_t mdbx_canary_get(MDB_txn *txn, mdbx_canary* canary)
{
if(unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE))
return 0;
if (likely(canary))
*canary = txn->mt_canary;
return txn->mt_txnid;
}

8
mdbx.h
View File

@ -211,6 +211,14 @@ typedef int MDBX_pgvisitor_func(size_t pgno, unsigned pgnumber, void* ctx,
const char* dbi, const char *type, int nentries,
int payload_bytes, int header_bytes, int unused_bytes);
int mdbx_env_pgwalk(MDB_txn *txn, MDBX_pgvisitor_func* visitor, void* ctx);
typedef struct mdbx_canary {
size_t x, y, z, v;
} mdbx_canary;
int mdbx_canary_put(MDB_txn *txn, const mdbx_canary* canary);
size_t mdbx_canary_get(MDB_txn *txn, mdbx_canary* canary);
/** @} */
#ifdef __cplusplus