// File: jvanns[P]verbatim/sub/lmdb/libraries/liblmdb/mdb.c
// Function: mdb_txn_begin
int
mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
{
	MDB_txn *txn;
	MDB_ntxn *ntxn;
	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;

	if (parent) {
		/* Nested transactions: Max 1 child, write txns only, no writemap */
		flags |= parent->mt_flags;
		if (flags & (MDB_RDONLY|MDB_WRITEMAP|MDB_TXN_BLOCKED)) {
			return (parent->mt_flags & MDB_TXN_RDONLY) ? EINVAL : MDB_BAD_TXN;
		}
		/* Child txns save MDB_pgstate and use own copy of cursors */
		size = env->me_maxdbs * (sizeof(MDB_db)+sizeof(MDB_cursor *)+1);
		size += tsize = sizeof(MDB_ntxn);
	} else if (flags & MDB_RDONLY) {
		size = env->me_maxdbs * (sizeof(MDB_db)+1);
		size += tsize = sizeof(MDB_txn);
	} else {
		/* 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;
	}
	if ((txn = calloc(1, size)) == NULL) {
		DPRINTF(("calloc: %s", strerror(errno)));
		return ENOMEM;
	}
	txn->mt_dbxs = env->me_dbxs;	/* static */
	txn->mt_dbs = (MDB_db *) ((char *)txn + tsize);
	txn->mt_dbflags = (unsigned char *)txn + size - env->me_maxdbs;
	txn->mt_flags = flags;
	txn->mt_env = env;

	if (parent) {
		unsigned int i;
		txn->mt_cursors = (MDB_cursor **)(txn->mt_dbs + env->me_maxdbs);
		txn->mt_dbiseqs = parent->mt_dbiseqs;
		txn->mt_u.dirty_list = malloc(sizeof(MDB_ID2)*MDB_IDL_UM_SIZE);
		if (!txn->mt_u.dirty_list ||
			!(txn->mt_free_pgs = mdb_midl_alloc(MDB_IDL_UM_MAX)))
		{
			free(txn->mt_u.dirty_list);
			free(txn);
			return ENOMEM;
		}
		txn->mt_txnid = parent->mt_txnid;
		txn->mt_dirty_room = parent->mt_dirty_room;
		txn->mt_u.dirty_list[0].mid = 0;
		txn->mt_spill_pgs = NULL;
		txn->mt_next_pgno = parent->mt_next_pgno;
		parent->mt_flags |= MDB_TXN_HAS_CHILD;
		parent->mt_child = txn;
		txn->mt_parent = parent;
		txn->mt_numdbs = parent->mt_numdbs;
		memcpy(txn->mt_dbs, parent->mt_dbs, txn->mt_numdbs * sizeof(MDB_db));
		/* 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 */
		if (env->me_pghead) {
			size = MDB_IDL_SIZEOF(env->me_pghead);
			env->me_pghead = mdb_midl_alloc(env->me_pghead[0]);
			if (env->me_pghead)
				memcpy(env->me_pghead, ntxn->mnt_pgstate.mf_pghead, size);
			else
				rc = ENOMEM;
		}
		if (!rc)
			rc = mdb_cursor_shadow(parent, txn);
		if (rc)
			mdb_txn_end(txn, MDB_END_FAIL_BEGINCHILD);
	} else { /* MDB_RDONLY */
		txn->mt_dbiseqs = env->me_dbiseqs;
renew:
		rc = mdb_txn_renew0(txn);
	}
	if (rc) {
		if (txn != env->me_txn0)
			free(txn);
	} else {
		txn->mt_flags |= flags;	/* could not change txn=me_txn0 earlier */
		*ret = txn;
		DPRINTF(("begin txn %"Z"u%c %p on mdbenv %p, root page %"Z"u",
			txn->mt_txnid, (flags & MDB_RDONLY) ? 'r' : 'w',
			(void *) txn, (void *) env, txn->mt_dbs[MAIN_DBI].md_root));
	}

	return rc;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movq %rcx, -0x28(%rbp)
movl -0x1c(%rbp), %eax
andl $0x70000, %eax          # imm = 0x70000
movl %eax, -0x1c(%rbp)
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
andl $0x80000, %eax          # imm = 0x80000
orl -0x1c(%rbp), %eax
movl %eax, -0x1c(%rbp)
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
andl $0x20000, %eax          # imm = 0x20000
movl -0x1c(%rbp), %ecx
xorl $-0x1, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x3ab9
movl $0xd, -0x4(%rbp)
jmp 0x3e98
cmpq $0x0, -0x18(%rbp)
je 0x3b21
movq -0x18(%rbp), %rax
movl 0x7c(%rax), %eax
orl -0x1c(%rbp), %eax
movl %eax, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
andl $0xa0013, %eax          # imm = 0xA0013
cmpl $0x0, %eax
je 0x3aff
movq -0x18(%rbp), %rax
movl 0x7c(%rax), %edx
andl $0x20000, %edx          # imm = 0x20000
movl $0xffff87c2, %eax       # imm = 0xFFFF87C2
movl $0x16, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x3e98
movq -0x10(%rbp), %rax
movl 0x24(%rax), %eax
imulq $0x39, %rax, %rax
movl %eax, -0x40(%rbp)
movl $0x98, -0x44(%rbp)
movl -0x40(%rbp), %eax
addl $0x98, %eax
movl %eax, -0x40(%rbp)
jmp 0x3b63
movl -0x1c(%rbp), %eax
andl $0x20000, %eax          # imm = 0x20000
cmpl $0x0, %eax
je 0x3b50
movq -0x10(%rbp), %rax
movl 0x24(%rax), %eax
imulq $0x31, %rax, %rax
movl %eax, -0x40(%rbp)
movl $0x88, -0x44(%rbp)
movl -0x40(%rbp), %eax
addl $0x88, %eax
movl %eax, -0x40(%rbp)
jmp 0x3b61
movq -0x10(%rbp), %rax
movq 0x68(%rax), %rax
movq %rax, -0x30(%rbp)
jmp 0x3e4f
jmp 0x3b63
movslq -0x40(%rbp), %rsi
movl $0x1, %edi
callq 0x21f0
movq %rax, -0x30(%rbp)
cmpq $0x0, %rax
jne 0x3b87
movl $0xc, -0x4(%rbp)
jmp 0x3e98
movq -0x10(%rbp), %rax
movq 0x88(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x50(%rax)
movq -0x30(%rbp), %rcx
movslq -0x44(%rbp), %rax
addq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x30(%rbp), %rcx
movslq -0x40(%rbp), %rax
addq %rax, %rcx
movq -0x10(%rbp), %rax
movl 0x24(%rax), %eax
movl %eax, %edx
xorl %eax, %eax
subq %rdx, %rax
addq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x70(%rax)
movl -0x1c(%rbp), %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x7c(%rax)
movq -0x10(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x20(%rax)
cmpq $0x0, -0x18(%rbp)
je 0x3e3c
movq -0x30(%rbp), %rax
movq 0x58(%rax), %rcx
movq -0x10(%rbp), %rax
movl 0x24(%rax), %eax
imulq $0x30, %rax, %rax
addq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x68(%rax)
movq -0x18(%rbp), %rax
movq 0x60(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x60(%rax)
movl $0x200000, %edi         # imm = 0x200000
callq 0x2260
movq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x48(%rax)
movq -0x30(%rbp), %rax
cmpq $0x0, 0x48(%rax)
je 0x3c58
movl $0x1ffff, %edi          # imm = 0x1FFFF
callq 0x126b0
movq -0x30(%rbp), %rcx
movq %rax, 0x28(%rcx)
cmpq $0x0, %rax
jne 0x3c7a
movq -0x30(%rbp), %rax
movq 0x48(%rax), %rdi
callq 0x2030
movq -0x30(%rbp), %rdi
callq 0x2030
movl $0xc, -0x4(%rbp)
jmp 0x3e98
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x18(%rbp), %rax
movl 0x80(%rax), %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x80(%rax)
movq -0x30(%rbp), %rax
movq 0x48(%rax), %rax
movq $0x0, (%rax)
movq -0x30(%rbp), %rax
movq $0x0, 0x40(%rax)
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x18(%rbp), %rax
movl 0x7c(%rax), %ecx
orl $0x10, %ecx
movl %ecx, 0x7c(%rax)
movq -0x30(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x18(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, (%rax)
movq -0x18(%rbp), %rax
movl 0x78(%rax), %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x78(%rax)
movq -0x30(%rbp), %rax
movq 0x58(%rax), %rdi
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rsi
movq -0x30(%rbp), %rax
movl 0x78(%rax), %eax
imulq $0x30, %rax, %rdx
callq 0x2230
movl $0x0, -0x48(%rbp)
movl -0x48(%rbp), %eax
movq -0x30(%rbp), %rcx
cmpl 0x78(%rcx), %eax
jae 0x3d5b
movq -0x18(%rbp), %rax
movq 0x70(%rax), %rax
movl -0x48(%rbp), %ecx
movzbl (%rax,%rcx), %eax
andl $-0x5, %eax
movb %al, %dl
movq -0x30(%rbp), %rax
movq 0x70(%rax), %rax
movl -0x48(%rbp), %ecx
movb %dl, (%rax,%rcx)
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x3d22
movl $0x0, -0x3c(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq -0x10(%rbp), %rcx
movq 0xb0(%rcx), %rdx
movq %rdx, 0x88(%rax)
movq 0xb8(%rcx), %rcx
movq %rcx, 0x90(%rax)
movq -0x10(%rbp), %rax
cmpq $0x0, 0xb0(%rax)
je 0x3e10
movq -0x10(%rbp), %rax
movq 0xb0(%rax), %rax
movq (%rax), %rax
addq $0x1, %rax
shlq $0x3, %rax
movl %eax, -0x40(%rbp)
movq -0x10(%rbp), %rax
movq 0xb0(%rax), %rax
movq (%rax), %rax
movl %eax, %edi
callq 0x126b0
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0xb0(%rax)
movq -0x10(%rbp), %rax
cmpq $0x0, 0xb0(%rax)
je 0x3e07
movq -0x10(%rbp), %rax
movq 0xb0(%rax), %rdi
movq -0x38(%rbp), %rax
movq 0x88(%rax), %rsi
movslq -0x40(%rbp), %rdx
callq 0x2230
jmp 0x3e0e
movl $0xc, -0x3c(%rbp)
jmp 0x3e10
cmpl $0x0, -0x3c(%rbp)
jne 0x3e26
movq -0x18(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x3eb0
movl %eax, -0x3c(%rbp)
cmpl $0x0, -0x3c(%rbp)
je 0x3e3a
movq -0x30(%rbp), %rdi
movl $0x6, %esi
callq 0x4030
jmp 0x3e5b
movq -0x10(%rbp), %rax
movq 0x98(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x60(%rax)
movq -0x30(%rbp), %rdi
callq 0x34c0
movl %eax, -0x3c(%rbp)
cmpl $0x0, -0x3c(%rbp)
je 0x3e7a
movq -0x30(%rbp), %rax
movq -0x10(%rbp), %rcx
cmpq 0x68(%rcx), %rax
je 0x3e78
movq -0x30(%rbp), %rdi
callq 0x2030
jmp 0x3e92
movl -0x1c(%rbp), %ecx
movq -0x30(%rbp), %rax
orl 0x7c(%rax), %ecx
movl %ecx, 0x7c(%rax)
movq -0x30(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
movl -0x3c(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)