+int
+mdb_txn_begin(MDB_env *env, int rdonly, MDB_txn **ret)
+{
+ MDB_txn *txn;
+ int rc;
+
+ if (env->me_flags & MDB_FATAL_ERROR) {
+ DPUTS("mdb_txn_begin: environment had fatal error, must shutdown!");
+ return MDB_PANIC;
+ }
+ if ((txn = calloc(1, sizeof(MDB_txn) + env->me_maxdbs * sizeof(MDB_db))) == NULL) {
+ DPRINTF("calloc: %s", strerror(errno));
+ return ENOMEM;
+ }
+ txn->mt_dbs = (MDB_db *)(txn+1);
+ if (rdonly) {
+ txn->mt_flags |= MDB_TXN_RDONLY;
+ }
+ txn->mt_env = env;
+
+ rc = mdb_txn_renew0(txn);
+ if (rc)
+ free(txn);
+ else {
+ *ret = txn;
+ DPRINTF("begin txn %p %lu%c on mdbenv %p, root page %lu", txn,
+ txn->mt_txnid, (txn->mt_flags & MDB_TXN_RDONLY) ? 'r' : 'w',
+ (void *) env, txn->mt_dbs[MAIN_DBI].md_root);
+ }
+
+ return rc;
+}
+
+static inline void
+mdb_txn_reset0(MDB_txn *txn)
+{
+ MDB_env *env = txn->mt_env;