meta = env->me_metas[txn->mt_txnid & 1];
}
} else {
+ /* Not yet touching txn == env->me_txn0, it may be active */
if (ti) {
if (LOCK_MUTEX(rc, env, MDB_MUTEX(env, w)))
return rc;
{
MDB_txn *txn;
MDB_ntxn *ntxn;
- int rc, size, tsize = sizeof(MDB_txn);
+ int rc, size, tsize;
flags &= MDB_TXN_BEGIN_FLAGS;
flags |= env->me_flags & MDB_WRITEMAP;
}
if (env->me_flags & MDB_RDONLY & ~flags) /* write txn in RDONLY env */
return EACCES;
+
+ size = tsize = sizeof(MDB_txn);
if (parent) {
/* Nested transactions: Max 1 child, write txns only, no writemap */
flags |= parent->mt_flags;
{
return (parent->mt_flags & MDB_TXN_RDONLY) ? EINVAL : MDB_BAD_TXN;
}
- tsize = sizeof(MDB_ntxn);
- }
- size = tsize;
- if (!(flags & MDB_RDONLY)) {
- if (!parent) {
- txn = env->me_txn0; /* just reuse preallocated write txn */
- goto ok;
- }
- /* child txns use own copy of cursors */
+ /* Child txns save MDB_pgstate and use own copy of cursors */
+ size = tsize = sizeof(MDB_ntxn);
size += env->me_maxdbs * sizeof(MDB_cursor *);
+ } else if (!(flags & MDB_RDONLY)) {
+ /* Reuse preallocated write txn. However, do not touch it until
+ * mdb_txn_renew0() succeeds, since it currently may be active.
+ */
+ txn = env->me_txn0;
+ goto renew;
}
size += env->me_maxdbs * (sizeof(MDB_db)+1);
txn->mt_flags = flags;
txn->mt_env = env;
-ok:
if (parent) {
unsigned int i;
txn->mt_u.dirty_list = malloc(sizeof(MDB_ID2)*MDB_IDL_UM_SIZE);
if (rc)
mdb_txn_reset0(txn, "beginchild-fail");
} else {
+renew:
rc = mdb_txn_renew0(txn);
}
if (rc) {
if (rc)
goto leave;
}
- if (!((flags & MDB_RDONLY) ||
- (env->me_pbuf = calloc(1, env->me_psize))))
- rc = ENOMEM;
if (!(flags & MDB_RDONLY)) {
MDB_txn *txn;
int tsize = sizeof(MDB_txn), size = tsize + env->me_maxdbs *
(sizeof(MDB_db)+sizeof(MDB_cursor *)+sizeof(unsigned int)+1);
- txn = calloc(1, size);
- if (txn) {
+ if ((env->me_pbuf = calloc(1, env->me_psize)) &&
+ (txn = calloc(1, size)))
+ {
txn->mt_dbs = (MDB_db *)((char *)txn + tsize);
txn->mt_cursors = (MDB_cursor **)(txn->mt_dbs + env->me_maxdbs);
txn->mt_dbiseqs = (unsigned int *)(txn->mt_cursors + env->me_maxdbs);