#define DB_STALE 0x02 /**< Named-DB record is older than txnID */
#define DB_NEW 0x04 /**< Named-DB handle opened in this txn */
#define DB_VALID 0x08 /**< DB handle is valid, see also #MDB_VALID */
+#define DB_USRVALID 0x10 /**< As #DB_VALID, but not set for #FREE_DBI */
/** @} */
/** In write txns, array of cursors for each DB */
MDB_cursor **mt_cursors;
#define MAX_WRITE (0x80000000U >> (sizeof(ssize_t) == 4))
/** Check \b txn and \b dbi arguments to a function */
-#define TXN_DBI_EXIST(txn, dbi) \
- ((txn) && (dbi) < (txn)->mt_numdbs && ((txn)->mt_dbflags[dbi] & DB_VALID))
+#define TXN_DBI_EXIST(txn, dbi, validity) \
+ ((txn) && (dbi)<(txn)->mt_numdbs && ((txn)->mt_dbflags[dbi] & (validity)))
/** Check for misused \b dbi handles */
#define TXN_DBI_CHANGED(txn, dbi) \
for (i=2; i<txn->mt_numdbs; i++) {
x = env->me_dbflags[i];
txn->mt_dbs[i].md_flags = x & PERSISTENT_FLAGS;
- txn->mt_dbflags[i] = (x & MDB_VALID) ? DB_VALID|DB_STALE : 0;
+ txn->mt_dbflags[i] = (x & MDB_VALID) ? DB_VALID|DB_USRVALID|DB_STALE : 0;
}
- txn->mt_dbflags[0] = txn->mt_dbflags[1] = DB_VALID;
+ txn->mt_dbflags[MAIN_DBI] = DB_VALID|DB_USRVALID;
+ txn->mt_dbflags[FREE_DBI] = DB_VALID;
if (env->me_maxpg < txn->mt_next_pgno) {
mdb_txn_reset0(txn, "renew0-mapfail");
DPRINTF(("===> get db %u key [%s]", dbi, DKEY(key)));
- if (!key || !data || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
+ if (!key || !data || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
return EINVAL;
if (txn->mt_flags & MDB_TXN_ERROR)
}
DPRINTF(("Sub-db -%u root page %"Z"u", mx->mx_cursor.mc_dbi,
mx->mx_db.md_root));
- mx->mx_dbflag = DB_VALID|DB_DIRTY; /* DB_DIRTY guides mdb_cursor_touch */
+ mx->mx_dbflag = DB_VALID|DB_USRVALID|DB_DIRTY; /* DB_DIRTY guides mdb_cursor_touch */
#if UINT_MAX < SIZE_MAX
if (mx->mx_dbx.md_cmp == mdb_cmp_int && mx->mx_db.md_pad == sizeof(size_t))
mx->mx_dbx.md_cmp = mdb_cmp_clong;
MDB_cursor *mc;
size_t size = sizeof(MDB_cursor);
- if (!ret || !TXN_DBI_EXIST(txn, dbi))
+ if (!ret || !TXN_DBI_EXIST(txn, dbi, DB_VALID))
return EINVAL;
if (txn->mt_flags & MDB_TXN_ERROR)
int
mdb_cursor_renew(MDB_txn *txn, MDB_cursor *mc)
{
- if (!mc || !TXN_DBI_EXIST(txn, mc->mc_dbi))
+ if (!mc || !TXN_DBI_EXIST(txn, mc->mc_dbi, DB_VALID))
return EINVAL;
if ((mc->mc_flags & C_UNTRACK) || txn->mt_cursors)
mdb_del(MDB_txn *txn, MDB_dbi dbi,
MDB_val *key, MDB_val *data)
{
- if (!key || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
+ if (!key || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
return EINVAL;
if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR))
MDB_cursor mc;
MDB_xcursor mx;
- if (!key || !data || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
+ if (!key || !data || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
return EINVAL;
if (flags & ~(MDB_NOOVERWRITE|MDB_NODUPDATA|MDB_RESERVE|MDB_APPEND|MDB_APPENDDUP))
return (flags & MDB_CREATE) ? MDB_INCOMPATIBLE : MDB_NOTFOUND;
/* Find the DB info */
- dbflag = DB_NEW|DB_VALID;
+ dbflag = DB_NEW|DB_VALID|DB_USRVALID;
exact = 0;
key.mv_size = len;
key.mv_data = (void *)name;
int mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *arg)
{
- if (!arg || !TXN_DBI_EXIST(txn, dbi))
+ if (!arg || !TXN_DBI_EXIST(txn, dbi, DB_VALID))
return EINVAL;
if (txn->mt_flags & MDB_TXN_ERROR)
int mdb_dbi_flags(MDB_txn *txn, MDB_dbi dbi, unsigned int *flags)
{
/* We could return the flags for the FREE_DBI too but what's the point? */
- if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
+ if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
return EINVAL;
*flags = txn->mt_dbs[dbi].md_flags & PERSISTENT_FLAGS;
return MDB_SUCCESS;
MDB_cursor *mc, *m2;
int rc;
- if ((unsigned)del > 1 || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
+ if ((unsigned)del > 1 || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
return EINVAL;
if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY))
int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
{
- if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
+ if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
return EINVAL;
txn->mt_dbxs[dbi].md_cmp = cmp;
int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
{
- if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
+ if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
return EINVAL;
txn->mt_dbxs[dbi].md_dcmp = cmp;
int mdb_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel)
{
- if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
+ if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
return EINVAL;
txn->mt_dbxs[dbi].md_rel = rel;
int mdb_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx)
{
- if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
+ if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
return EINVAL;
txn->mt_dbxs[dbi].md_relctx = ctx;