mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-27 03:20:22 +08:00
Merge remote-tracking branch 'origin/mdb.master'
This commit is contained in:
commit
55d91653fd
@ -137,6 +137,12 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef int mdb_mode_t;
|
||||
#else
|
||||
typedef mode_t mdb_mode_t;
|
||||
#endif
|
||||
|
||||
/** @defgroup mdb MDB API
|
||||
* @{
|
||||
* @brief OpenLDAP Lightning Memory-Mapped Database Manager
|
||||
@ -498,7 +504,7 @@ int mdb_env_create(MDB_env **env);
|
||||
* <li>EAGAIN - the environment was locked by another process.
|
||||
* </ul>
|
||||
*/
|
||||
int mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mode_t mode);
|
||||
int mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode);
|
||||
|
||||
/** @brief Copy an MDB environment to the specified path.
|
||||
*
|
||||
@ -761,14 +767,18 @@ int mdb_txn_renew(MDB_txn *txn);
|
||||
/** @brief Open a database in the environment.
|
||||
*
|
||||
* The database handle may be discarded by calling #mdb_dbi_close().
|
||||
* It denotes the name and parameters of a database, independently of
|
||||
* whether such a database exists. It will not exist if the transaction
|
||||
* which created it aborted, nor if another process deleted it. The
|
||||
* database handle resides in the shared environment, it is not owned
|
||||
* by the given transaction. Only one thread should call this function;
|
||||
* it is not mutex-protected in a read-only transaction.
|
||||
* Preexisting transactions, other than the current transaction and
|
||||
* any parents, must not use the new handle. Nor must their children.
|
||||
* The old database handle is returned if the database was already open.
|
||||
* The handle must only be closed once.
|
||||
* The database handle will be private to the current transaction until
|
||||
* the transaction is successfully committed. If the transaction is
|
||||
* aborted the handle will be closed automatically.
|
||||
* After a successful commit the
|
||||
* handle will reside in the shared environment, and may be used
|
||||
* by other transactions. This function must not be called from
|
||||
* multiple concurrent transactions. A transaction that uses this function
|
||||
* must finish (either commit or abort) before any other transaction may
|
||||
* use this function.
|
||||
*
|
||||
* To use named databases (with name != NULL), #mdb_env_set_maxdbs()
|
||||
* must be called before opening the environment.
|
||||
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
||||
|
@ -286,6 +286,8 @@ typedef MDB_ID txnid_t;
|
||||
#endif
|
||||
|
||||
#if !(__STDC_VERSION__ >= 199901L || defined(__GNUC__))
|
||||
# undef MDB_DEBUG
|
||||
# define MDB_DEBUG 0
|
||||
# define DPRINTF (void) /* Vararg macros may be unsupported */
|
||||
#elif MDB_DEBUG
|
||||
static int mdb_debug;
|
||||
@ -743,6 +745,11 @@ typedef struct MDB_db {
|
||||
pgno_t md_root; /**< the root page of this tree */
|
||||
} MDB_db;
|
||||
|
||||
/** mdb_dbi_open flags */
|
||||
#define PERSISTENT_FLAGS 0x7fff
|
||||
#define VALID_FLAGS (MDB_REVERSEKEY|MDB_DUPSORT|MDB_INTEGERKEY|MDB_DUPFIXED|\
|
||||
MDB_INTEGERDUP|MDB_REVERSEDUP|MDB_CREATE)
|
||||
|
||||
/** Handle for the DB used to track free pages. */
|
||||
#define FREE_DBI 0
|
||||
/** Handle for the default DB. */
|
||||
@ -822,6 +829,9 @@ struct MDB_txn {
|
||||
*/
|
||||
#define DB_DIRTY 0x01 /**< DB was written in this txn */
|
||||
#define DB_STALE 0x02 /**< DB record is older than txnID */
|
||||
#define DB_NEW 0x04 /**< DB handle opened in this txn */
|
||||
#define DB_VALID 0x08 /**< DB handle is valid */
|
||||
#define MDB_VALID 0x8000 /**< DB handle is valid, for me_dbflags */
|
||||
/** @} */
|
||||
/** In write txns, array of cursors for each DB */
|
||||
MDB_cursor **mt_cursors;
|
||||
@ -1768,6 +1778,7 @@ mdb_txn_renew0(MDB_txn *txn)
|
||||
{
|
||||
MDB_env *env = txn->mt_env;
|
||||
unsigned int i;
|
||||
uint16_t x;
|
||||
int rc;
|
||||
|
||||
/* Setup db info */
|
||||
@ -1832,11 +1843,11 @@ mdb_txn_renew0(MDB_txn *txn)
|
||||
|
||||
/* Copy the DB info and flags */
|
||||
memcpy(txn->mt_dbs, env->me_metas[txn->mt_toggle]->mm_dbs, 2 * sizeof(MDB_db));
|
||||
for (i=2; i<txn->mt_numdbs; i++)
|
||||
txn->mt_dbs[i].md_flags = env->me_dbflags[i];
|
||||
txn->mt_dbflags[0] = txn->mt_dbflags[1] = 0;
|
||||
if (txn->mt_numdbs > 2)
|
||||
memset(txn->mt_dbflags+2, DB_STALE, txn->mt_numdbs-2);
|
||||
for (i=2; i<txn->mt_numdbs; i++) {
|
||||
txn->mt_dbs[i].md_flags = x = env->me_dbflags[i];
|
||||
txn->mt_dbflags[i] = (x & MDB_VALID) ? DB_VALID|DB_STALE : 0;
|
||||
}
|
||||
txn->mt_dbflags[0] = txn->mt_dbflags[1] = DB_VALID;
|
||||
|
||||
if (env->me_maxpg < txn->mt_next_pgno) {
|
||||
mdb_txn_reset0(txn);
|
||||
@ -1910,6 +1921,7 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
|
||||
txn->mt_env = env;
|
||||
|
||||
if (parent) {
|
||||
unsigned int i;
|
||||
txn->mt_free_pgs = mdb_midl_alloc();
|
||||
if (!txn->mt_free_pgs) {
|
||||
free(txn);
|
||||
@ -1932,7 +1944,9 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
|
||||
txn->mt_numdbs = parent->mt_numdbs;
|
||||
txn->mt_dbxs = parent->mt_dbxs;
|
||||
memcpy(txn->mt_dbs, parent->mt_dbs, txn->mt_numdbs * sizeof(MDB_db));
|
||||
memcpy(txn->mt_dbflags, parent->mt_dbflags, txn->mt_numdbs);
|
||||
/* 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;
|
||||
rc = 0;
|
||||
ntxn = (MDB_ntxn *)txn;
|
||||
ntxn->mnt_pgstate = env->me_pgstate; /* save parent me_pghead & co */
|
||||
@ -1971,13 +1985,23 @@ static void
|
||||
mdb_txn_reset0(MDB_txn *txn)
|
||||
{
|
||||
MDB_env *env = txn->mt_env;
|
||||
unsigned int i;
|
||||
|
||||
/* Close any DBI handles opened in this txn */
|
||||
for (i=2; i<txn->mt_numdbs; i++) {
|
||||
if (txn->mt_dbflags[i] & DB_NEW) {
|
||||
char *ptr = env->me_dbxs[i].md_name.mv_data;
|
||||
env->me_dbxs[i].md_name.mv_data = NULL;
|
||||
env->me_dbxs[i].md_name.mv_size = 0;
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) {
|
||||
if (!(env->me_flags & MDB_ROFS))
|
||||
txn->mt_u.reader->mr_txnid = (txnid_t)-1;
|
||||
} else {
|
||||
MDB_page *dp;
|
||||
unsigned int i;
|
||||
|
||||
/* close(free) all cursors */
|
||||
for (i=0; i<txn->mt_numdbs; i++) {
|
||||
@ -2081,13 +2105,14 @@ mdb_txn_commit(MDB_txn *txn)
|
||||
env = txn->mt_env;
|
||||
|
||||
if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) {
|
||||
if (txn->mt_numdbs > env->me_numdbs) {
|
||||
/* update the DB flags */
|
||||
MDB_dbi i;
|
||||
for (i = env->me_numdbs; i<txn->mt_numdbs; i++)
|
||||
env->me_dbflags[i] = txn->mt_dbs[i].md_flags;
|
||||
env->me_numdbs = i;
|
||||
/* update the DB flags */
|
||||
for (i = 2; i<txn->mt_numdbs; i++) {
|
||||
if (txn->mt_dbflags[i] & DB_NEW)
|
||||
env->me_dbflags[i] = txn->mt_dbs[i].md_flags | MDB_VALID;
|
||||
}
|
||||
if (txn->mt_numdbs > env->me_numdbs)
|
||||
env->me_numdbs = txn->mt_numdbs;
|
||||
txn->mt_numdbs = 2; /* so txn_abort() doesn't close any new handles */
|
||||
mdb_txn_abort(txn);
|
||||
return MDB_SUCCESS;
|
||||
}
|
||||
@ -2120,8 +2145,14 @@ mdb_txn_commit(MDB_txn *txn)
|
||||
|
||||
/* Update parent's DB table. */
|
||||
memcpy(parent->mt_dbs, txn->mt_dbs, txn->mt_numdbs * sizeof(MDB_db));
|
||||
memcpy(parent->mt_dbflags, txn->mt_dbflags, txn->mt_numdbs);
|
||||
txn->mt_parent->mt_numdbs = txn->mt_numdbs;
|
||||
txn->mt_parent->mt_dbflags[0] = txn->mt_dbflags[0];
|
||||
txn->mt_parent->mt_dbflags[1] = txn->mt_dbflags[1];
|
||||
for (i=2; i<txn->mt_numdbs; i++) {
|
||||
/* preserve parent's DB_NEW status */
|
||||
x = txn->mt_parent->mt_dbflags[i] & DB_NEW;
|
||||
txn->mt_parent->mt_dbflags[i] = txn->mt_dbflags[i] | x;
|
||||
}
|
||||
|
||||
dst = txn->mt_parent->mt_u.dirty_list;
|
||||
src = txn->mt_u.dirty_list;
|
||||
@ -2464,13 +2495,13 @@ sync:
|
||||
done:
|
||||
env->me_pglast = 0;
|
||||
env->me_txn = NULL;
|
||||
if (txn->mt_numdbs > env->me_numdbs) {
|
||||
/* update the DB flags */
|
||||
MDB_dbi i;
|
||||
for (i = env->me_numdbs; i<txn->mt_numdbs; i++)
|
||||
env->me_dbflags[i] = txn->mt_dbs[i].md_flags;
|
||||
env->me_numdbs = i;
|
||||
/* update the DB flags */
|
||||
for (i = 2; i<txn->mt_numdbs; i++) {
|
||||
if (txn->mt_dbflags[i] & DB_NEW)
|
||||
env->me_dbflags[i] = txn->mt_dbs[i].md_flags | MDB_VALID;
|
||||
}
|
||||
if (txn->mt_numdbs > env->me_numdbs)
|
||||
env->me_numdbs = txn->mt_numdbs;
|
||||
|
||||
UNLOCK_MUTEX_W(env);
|
||||
free(txn);
|
||||
@ -3378,7 +3409,7 @@ fail:
|
||||
#define CHANGELESS (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY|MDB_WRITEMAP)
|
||||
|
||||
int
|
||||
mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mode_t mode)
|
||||
mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode)
|
||||
{
|
||||
int oflags, rc, len, excl;
|
||||
char *lpath, *dpath;
|
||||
@ -3705,10 +3736,14 @@ void
|
||||
mdb_env_close(MDB_env *env)
|
||||
{
|
||||
MDB_page *dp;
|
||||
int i;
|
||||
|
||||
if (env == NULL)
|
||||
return;
|
||||
|
||||
for (i = env->me_numdbs; --i > MAIN_DBI; )
|
||||
free(env->me_dbxs[i].md_name.mv_data);
|
||||
|
||||
VGMEMP_DESTROY(env);
|
||||
while ((dp = env->me_dpages) != NULL) {
|
||||
VGMEMP_DEFINED(&dp->mp_next, sizeof(dp->mp_next));
|
||||
@ -4124,13 +4159,14 @@ mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags)
|
||||
/* The txn may not know this DBI, or another process may
|
||||
* have dropped and recreated the DB with other flags.
|
||||
*/
|
||||
if (mc->mc_db->md_flags != flags)
|
||||
if ((mc->mc_db->md_flags & PERSISTENT_FLAGS) != flags)
|
||||
return MDB_INCOMPATIBLE;
|
||||
memcpy(mc->mc_db, data.mv_data, sizeof(MDB_db));
|
||||
}
|
||||
if (flags & MDB_PS_MODIFY)
|
||||
dbflag = DB_DIRTY;
|
||||
*mc->mc_dbflag = dbflag;
|
||||
*mc->mc_dbflag &= ~DB_STALE;
|
||||
*mc->mc_dbflag |= dbflag;
|
||||
}
|
||||
}
|
||||
root = mc->mc_db->md_root;
|
||||
@ -4208,7 +4244,7 @@ mdb_get(MDB_txn *txn, MDB_dbi dbi,
|
||||
assert(data);
|
||||
DPRINTF("===> get db %u key [%s]", dbi, DKEY(key));
|
||||
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs)
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
|
||||
return EINVAL;
|
||||
|
||||
if (key->mv_size == 0 || key->mv_size > MDB_MAXKEYSIZE) {
|
||||
@ -4267,6 +4303,8 @@ mdb_cursor_sibling(MDB_cursor *mc, int move_right)
|
||||
return rc;
|
||||
|
||||
mdb_cursor_push(mc, mp);
|
||||
if (!move_right)
|
||||
mc->mc_ki[mc->mc_top] = NUMKEYS(mp)-1;
|
||||
|
||||
return MDB_SUCCESS;
|
||||
}
|
||||
@ -4661,9 +4699,9 @@ mdb_cursor_last(MDB_cursor *mc, MDB_val *key, MDB_val *data)
|
||||
}
|
||||
assert(IS_LEAF(mc->mc_pg[mc->mc_top]));
|
||||
|
||||
mc->mc_flags |= C_INITIALIZED|C_EOF;
|
||||
mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]) - 1;
|
||||
}
|
||||
mc->mc_flags |= C_INITIALIZED|C_EOF;
|
||||
leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
|
||||
|
||||
if (IS_LEAF2(mc->mc_pg[mc->mc_top])) {
|
||||
@ -4791,7 +4829,7 @@ fetchm:
|
||||
case MDB_PREV:
|
||||
case MDB_PREV_DUP:
|
||||
case MDB_PREV_NODUP:
|
||||
if (!(mc->mc_flags & C_INITIALIZED) || (mc->mc_flags & C_EOF)) {
|
||||
if (!(mc->mc_flags & C_INITIALIZED)) {
|
||||
rc = mdb_cursor_last(mc, key, data);
|
||||
mc->mc_flags |= C_INITIALIZED;
|
||||
mc->mc_ki[mc->mc_top]++;
|
||||
@ -4850,7 +4888,7 @@ mdb_cursor_touch(MDB_cursor *mc)
|
||||
rc = mdb_page_search(&mc2, &mc->mc_dbx->md_name, MDB_PS_MODIFY);
|
||||
if (rc)
|
||||
return rc;
|
||||
*mc->mc_dbflag = DB_DIRTY;
|
||||
*mc->mc_dbflag |= DB_DIRTY;
|
||||
}
|
||||
for (mc->mc_top = 0; mc->mc_top < mc->mc_snum; mc->mc_top++) {
|
||||
rc = mdb_page_touch(mc);
|
||||
@ -4912,7 +4950,7 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
|
||||
mdb_cursor_push(mc, np);
|
||||
mc->mc_db->md_root = np->mp_pgno;
|
||||
mc->mc_db->md_depth++;
|
||||
*mc->mc_dbflag = DB_DIRTY;
|
||||
*mc->mc_dbflag |= DB_DIRTY;
|
||||
if ((mc->mc_db->md_flags & (MDB_DUPSORT|MDB_DUPFIXED))
|
||||
== MDB_DUPFIXED)
|
||||
np->mp_flags |= P_LEAF2;
|
||||
@ -4930,8 +4968,9 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
|
||||
if (rc > 0) {
|
||||
rc = MDB_NOTFOUND;
|
||||
mc->mc_ki[mc->mc_top]++;
|
||||
} else {
|
||||
rc = 0;
|
||||
} else if (rc < 0) {
|
||||
/* new key is < last key */
|
||||
rc = MDB_KEYEXIST;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -5705,8 +5744,8 @@ mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node)
|
||||
}
|
||||
DPRINTF("Sub-db %u for db %u root page %zu", mx->mx_cursor.mc_dbi, mc->mc_dbi,
|
||||
mx->mx_db.md_root);
|
||||
mx->mx_dbflag = (F_ISSET(mc->mc_pg[mc->mc_top]->mp_flags, P_DIRTY)) ?
|
||||
DB_DIRTY : 0;
|
||||
mx->mx_dbflag = DB_VALID | (F_ISSET(mc->mc_pg[mc->mc_top]->mp_flags, P_DIRTY) ?
|
||||
DB_DIRTY : 0);
|
||||
mx->mx_dbx.md_name.mv_data = NODEKEY(node);
|
||||
mx->mx_dbx.md_name.mv_size = node->mn_ksize;
|
||||
#if UINT_MAX < SIZE_MAX
|
||||
@ -5752,7 +5791,7 @@ mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **ret)
|
||||
MDB_xcursor *mx = NULL;
|
||||
size_t size = sizeof(MDB_cursor);
|
||||
|
||||
if (txn == NULL || ret == NULL || dbi >= txn->mt_numdbs)
|
||||
if (txn == NULL || ret == NULL || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
|
||||
return EINVAL;
|
||||
|
||||
/* Allow read access to the freelist */
|
||||
@ -6252,8 +6291,8 @@ static int
|
||||
mdb_rebalance(MDB_cursor *mc)
|
||||
{
|
||||
MDB_node *node;
|
||||
int rc, minkeys;
|
||||
unsigned int ptop;
|
||||
int rc;
|
||||
unsigned int ptop, minkeys;
|
||||
MDB_cursor mn;
|
||||
|
||||
#if MDB_DEBUG
|
||||
@ -6333,6 +6372,8 @@ mdb_rebalance(MDB_cursor *mc)
|
||||
if (m3->mc_snum < mc->mc_snum) continue;
|
||||
if (m3->mc_pg[0] == mp) {
|
||||
m3->mc_pg[0] = mc->mc_pg[0];
|
||||
m3->mc_snum = 1;
|
||||
m3->mc_top = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6446,7 +6487,7 @@ mdb_del(MDB_txn *txn, MDB_dbi dbi,
|
||||
|
||||
DPRINTF("====> delete db %u key [%s]", dbi, DKEY(key));
|
||||
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs)
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
|
||||
return EINVAL;
|
||||
|
||||
if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) {
|
||||
@ -6897,7 +6938,7 @@ mdb_put(MDB_txn *txn, MDB_dbi dbi,
|
||||
assert(key != NULL);
|
||||
assert(data != NULL);
|
||||
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs)
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
|
||||
return EINVAL;
|
||||
|
||||
if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) {
|
||||
@ -6908,7 +6949,7 @@ mdb_put(MDB_txn *txn, MDB_dbi dbi,
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if ((flags & (MDB_NOOVERWRITE|MDB_NODUPDATA|MDB_RESERVE|MDB_APPEND)) != flags)
|
||||
if ((flags & (MDB_NOOVERWRITE|MDB_NODUPDATA|MDB_RESERVE|MDB_APPEND|MDB_APPENDDUP)) != flags)
|
||||
return EINVAL;
|
||||
|
||||
mdb_cursor_init(&mc, txn, dbi, &mx);
|
||||
@ -7019,15 +7060,11 @@ mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi)
|
||||
: ((f & MDB_REVERSEDUP) ? mdb_cmp_memnr : mdb_cmp_memn));
|
||||
}
|
||||
|
||||
#define PERSISTENT_FLAGS 0xffff
|
||||
#define VALID_FLAGS (MDB_REVERSEKEY|MDB_DUPSORT|MDB_INTEGERKEY|MDB_DUPFIXED|\
|
||||
MDB_INTEGERDUP|MDB_REVERSEDUP|MDB_CREATE)
|
||||
int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi)
|
||||
{
|
||||
MDB_val key, data;
|
||||
MDB_dbi i;
|
||||
MDB_cursor mc;
|
||||
uint16_t mdflags;
|
||||
int rc, dbflag, exact;
|
||||
unsigned int unused = 0;
|
||||
size_t len;
|
||||
@ -7078,7 +7115,7 @@ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *db
|
||||
return MDB_DBS_FULL;
|
||||
|
||||
/* Find the DB info */
|
||||
dbflag = 0;
|
||||
dbflag = DB_NEW|DB_VALID;
|
||||
exact = 0;
|
||||
key.mv_size = len;
|
||||
key.mv_data = (void *)name;
|
||||
@ -7098,7 +7135,7 @@ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *db
|
||||
dummy.md_root = P_INVALID;
|
||||
dummy.md_flags = flags & PERSISTENT_FLAGS;
|
||||
rc = mdb_cursor_put(&mc, &key, &data, F_SUBDATA);
|
||||
dbflag = DB_DIRTY;
|
||||
dbflag |= DB_DIRTY;
|
||||
}
|
||||
|
||||
/* OK, got info, add to table */
|
||||
@ -7110,18 +7147,10 @@ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *db
|
||||
txn->mt_dbflags[slot] = dbflag;
|
||||
memcpy(&txn->mt_dbs[slot], data.mv_data, sizeof(MDB_db));
|
||||
*dbi = slot;
|
||||
txn->mt_env->me_dbflags[slot] = mdflags = txn->mt_dbs[slot].md_flags;
|
||||
txn->mt_env->me_dbflags[slot] = txn->mt_dbs[slot].md_flags;
|
||||
mdb_default_cmp(txn, slot);
|
||||
if (!unused) {
|
||||
txn->mt_numdbs++;
|
||||
txn->mt_env->me_numdbs++;
|
||||
}
|
||||
/* Open the DB in parent txns as well */
|
||||
while ((txn = txn->mt_parent) != NULL) {
|
||||
txn->mt_dbflags[slot] = DB_STALE;
|
||||
txn->mt_dbs[slot].md_flags = mdflags;
|
||||
if (!unused)
|
||||
txn->mt_numdbs++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7164,7 +7193,7 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
||||
unsigned int i;
|
||||
|
||||
/* LEAF2 pages have no nodes, cannot have sub-DBs */
|
||||
if (!subs || IS_LEAF2(mc->mc_pg[mc->mc_top]))
|
||||
if (IS_LEAF2(mc->mc_pg[mc->mc_top]))
|
||||
mdb_cursor_pop(mc);
|
||||
|
||||
mdb_cursor_copy(mc, &mx);
|
||||
@ -7172,7 +7201,15 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
||||
if (IS_LEAF(mc->mc_pg[mc->mc_top])) {
|
||||
for (i=0; i<NUMKEYS(mc->mc_pg[mc->mc_top]); i++) {
|
||||
ni = NODEPTR(mc->mc_pg[mc->mc_top], i);
|
||||
if (ni->mn_flags & F_SUBDATA) {
|
||||
if (ni->mn_flags & F_BIGDATA) {
|
||||
int j, ovpages = OVPAGES(NODEDSZ(ni), mc->mc_txn->mt_env->me_psize);
|
||||
pgno_t pg;
|
||||
memcpy(&pg, NODEDATA(ni), sizeof(pg));
|
||||
for (j=0; j<ovpages; j++) {
|
||||
mdb_midl_append(&mc->mc_txn->mt_free_pgs, pg);
|
||||
pg++;
|
||||
}
|
||||
} else if (subs && (ni->mn_flags & F_SUBDATA)) {
|
||||
mdb_xcursor_init1(mc, ni);
|
||||
rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0);
|
||||
if (rc)
|
||||
@ -7190,14 +7227,18 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
||||
}
|
||||
if (!mc->mc_top)
|
||||
break;
|
||||
mc->mc_ki[mc->mc_top] = i;
|
||||
rc = mdb_cursor_sibling(mc, 1);
|
||||
if (rc) {
|
||||
/* no more siblings, go back to beginning
|
||||
* of previous level.
|
||||
*/
|
||||
mdb_cursor_pop(mc);
|
||||
for (i=1; i<mc->mc_top; i++)
|
||||
mc->mc_ki[0] = 0;
|
||||
for (i=1; i<mc->mc_snum; i++) {
|
||||
mc->mc_ki[i] = 0;
|
||||
mc->mc_pg[i] = mx.mc_pg[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* free it */
|
||||
@ -7212,7 +7253,7 @@ int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
|
||||
MDB_cursor *mc;
|
||||
int rc;
|
||||
|
||||
if (!txn || !dbi || dbi >= txn->mt_numdbs || (unsigned)del > 1)
|
||||
if (!txn || !dbi || dbi >= txn->mt_numdbs || (unsigned)del > 1 || !(txn->mt_dbflags[dbi] & DB_VALID))
|
||||
return EINVAL;
|
||||
|
||||
if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY))
|
||||
@ -7243,19 +7284,7 @@ int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
|
||||
txn->mt_dbs[dbi].md_entries = 0;
|
||||
txn->mt_dbs[dbi].md_root = P_INVALID;
|
||||
|
||||
if (!txn->mt_u.dirty_list[0].mid) {
|
||||
MDB_cursor m2;
|
||||
MDB_val key, data;
|
||||
/* make sure we have at least one dirty page in this txn
|
||||
* otherwise these changes will be ignored.
|
||||
*/
|
||||
key.mv_size = sizeof(txnid_t);
|
||||
key.mv_data = &txn->mt_txnid;
|
||||
data.mv_size = sizeof(MDB_ID);
|
||||
data.mv_data = txn->mt_free_pgs;
|
||||
mdb_cursor_init(&m2, txn, FREE_DBI, NULL);
|
||||
rc = mdb_cursor_put(&m2, &key, &data, 0);
|
||||
}
|
||||
txn->mt_flags |= MDB_TXN_DIRTY;
|
||||
}
|
||||
leave:
|
||||
mdb_cursor_close(mc);
|
||||
@ -7264,7 +7293,7 @@ leave:
|
||||
|
||||
int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
|
||||
{
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs)
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
|
||||
return EINVAL;
|
||||
|
||||
txn->mt_dbxs[dbi].md_cmp = cmp;
|
||||
@ -7273,7 +7302,7 @@ int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
|
||||
|
||||
int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
|
||||
{
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs)
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
|
||||
return EINVAL;
|
||||
|
||||
txn->mt_dbxs[dbi].md_dcmp = cmp;
|
||||
@ -7282,7 +7311,7 @@ int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
|
||||
|
||||
int mdb_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel)
|
||||
{
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs)
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
|
||||
return EINVAL;
|
||||
|
||||
txn->mt_dbxs[dbi].md_rel = rel;
|
||||
@ -7291,7 +7320,7 @@ int mdb_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel)
|
||||
|
||||
int mdb_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx)
|
||||
{
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs)
|
||||
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
|
||||
return EINVAL;
|
||||
|
||||
txn->mt_dbxs[dbi].md_relctx = ctx;
|
||||
|
@ -25,7 +25,7 @@ int main(int argc,char * argv[])
|
||||
MDB_val key, data;
|
||||
MDB_txn *txn;
|
||||
MDB_stat mst;
|
||||
MDB_cursor *cursor;
|
||||
MDB_cursor *cursor, *cur2;
|
||||
int count;
|
||||
int *values;
|
||||
char sval[32];
|
||||
@ -54,7 +54,11 @@ int main(int argc,char * argv[])
|
||||
for (i=0;i<count;i++) {
|
||||
sprintf(sval, "%03x %d foo bar", values[i], values[i]);
|
||||
rc = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE);
|
||||
if (rc) j++;
|
||||
if (rc) {
|
||||
j++;
|
||||
data.mv_size = sizeof(sval);
|
||||
data.mv_data = sval;
|
||||
}
|
||||
}
|
||||
if (j) printf("%d duplicates skipped\n", j);
|
||||
rc = mdb_txn_commit(txn);
|
||||
@ -97,25 +101,38 @@ int main(int argc,char * argv[])
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
printf("Cursor last\n");
|
||||
rc = mdb_cursor_get(cursor, &key, &data, MDB_LAST);
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
printf("Cursor prev\n");
|
||||
while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
#if 0
|
||||
/* write ops aren't coordinated with cursors,
|
||||
* this stuff all breaks
|
||||
*/
|
||||
printf("Cursor last/prev\n");
|
||||
rc = mdb_cursor_get(cursor, &key, &data, MDB_LAST);
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV);
|
||||
printf("key: %.*s, data: %.*s\n",
|
||||
(int) key.mv_size, (char *) key.mv_data,
|
||||
(int) data.mv_size, (char *) data.mv_data);
|
||||
|
||||
mdb_txn_abort(txn);
|
||||
|
||||
printf("Deleting with cursor\n");
|
||||
rc = mdb_txn_begin(env, NULL, 0, &txn);
|
||||
rc = mdb_cursor_open(db, txn, &cur2);
|
||||
rc = mdb_cursor_open(txn, dbi, &cur2);
|
||||
for (i=0; i<50; i++) {
|
||||
rc = mdb_cursor_get(cur2, &key, &data, MDB_NEXT);
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
rc = mdb_del(db, txn, &key, NULL);
|
||||
rc = mdb_del(txn, dbi, &key, NULL);
|
||||
}
|
||||
|
||||
printf("Restarting cursor in txn\n");
|
||||
@ -131,9 +148,10 @@ int main(int argc,char * argv[])
|
||||
}
|
||||
mdb_cursor_close(cur2);
|
||||
rc = mdb_txn_commit(txn);
|
||||
mdb_cursor_close(cursor);
|
||||
|
||||
printf("Restarting cursor outside txn\n");
|
||||
rc = mdb_cursor_open(db, NULL, &cursor);
|
||||
rc = mdb_txn_begin(env, NULL, 0, &txn);
|
||||
rc = mdb_cursor_open(txn, dbi, &cursor);
|
||||
rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST);
|
||||
printf("key: %p %.*s, data: %p %.*s\n",
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
@ -144,7 +162,6 @@ int main(int argc,char * argv[])
|
||||
key.mv_data, (int) key.mv_size, (char *) key.mv_data,
|
||||
data.mv_data, (int) data.mv_size, (char *) data.mv_data);
|
||||
}
|
||||
#endif
|
||||
mdb_cursor_close(cursor);
|
||||
mdb_close(env, dbi);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user