// File: jvanns[P]verbatim/sub/lmdb/libraries/liblmdb/mdb.c
// Function: mdb_txn_end
static void
mdb_txn_end(MDB_txn *txn, unsigned mode)
{
	MDB_env	*env = txn->mt_env;
#if MDB_DEBUG
	static const char *const names[] = MDB_END_NAMES;
#endif

	/* Export or close DBI handles opened in this txn */
	mdb_dbis_update(txn, mode & MDB_END_UPDATE);

	DPRINTF(("%s txn %"Z"u%c %p on mdbenv %p, root page %"Z"u",
		names[mode & MDB_END_OPMASK],
		txn->mt_txnid, (txn->mt_flags & MDB_TXN_RDONLY) ? 'r' : 'w',
		(void *) txn, (void *)env, txn->mt_dbs[MAIN_DBI].md_root));

	if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) {
		if (txn->mt_u.reader) {
			txn->mt_u.reader->mr_txnid = (txnid_t)-1;
			if (!(env->me_flags & MDB_NOTLS)) {
				txn->mt_u.reader = NULL; /* txn does not own reader */
			} else if (mode & MDB_END_SLOT) {
				txn->mt_u.reader->mr_pid = 0;
				txn->mt_u.reader = NULL;
			} /* else txn owns the slot until it does MDB_END_SLOT */
		}
		txn->mt_numdbs = 0;		/* prevent further DBI activity */
		txn->mt_flags |= MDB_TXN_FINISHED;

	} else if (!F_ISSET(txn->mt_flags, MDB_TXN_FINISHED)) {
		pgno_t *pghead = env->me_pghead;

		if (!(mode & MDB_END_UPDATE)) /* !(already closed cursors) */
			mdb_cursors_close(txn, 0);
		if (!(env->me_flags & MDB_WRITEMAP)) {
			mdb_dlist_free(txn);
		}

		txn->mt_numdbs = 0;
		txn->mt_flags = MDB_TXN_FINISHED;

		if (!txn->mt_parent) {
			mdb_midl_shrink(&txn->mt_free_pgs);
			env->me_free_pgs = txn->mt_free_pgs;
			/* me_pgstate: */
			env->me_pghead = NULL;
			env->me_pglast = 0;

			env->me_txn = NULL;
			mode = 0;	/* txn == env->me_txn0, do not free() it */

			/* The writer mutex was locked in mdb_txn_begin. */
			if (env->me_txns)
				UNLOCK_MUTEX(env->me_wmutex);
		} else {
			txn->mt_parent->mt_child = NULL;
			txn->mt_parent->mt_flags &= ~MDB_TXN_HAS_CHILD;
			env->me_pgstate = ((MDB_ntxn *)txn)->mnt_pgstate;
			mdb_midl_free(txn->mt_free_pgs);
			mdb_midl_free(txn->mt_spill_pgs);
			free(txn->mt_u.dirty_list);
		}

		mdb_midl_free(pghead);
	}

	if (mode & MDB_END_FREE)
		free(txn);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %esi
andl $0x10, %esi
callq 0xec60
movq -0x8(%rbp), %rax
movl 0x7c(%rax), %eax
andl $0x20000, %eax          # imm = 0x20000
cmpl $0x20000, %eax          # imm = 0x20000
jne 0x40f3
movq -0x8(%rbp), %rax
cmpq $0x0, 0x48(%rax)
je 0x40d6
movq -0x8(%rbp), %rax
movq 0x48(%rax), %rax
movq $-0x1, (%rax)
movq -0x18(%rbp), %rax
movl 0xc(%rax), %eax
andl $0x200000, %eax         # imm = 0x200000
cmpl $0x0, %eax
jne 0x40aa
movq -0x8(%rbp), %rax
movq $0x0, 0x48(%rax)
jmp 0x40d4
movl -0xc(%rbp), %eax
andl $0x200000, %eax         # imm = 0x200000
cmpl $0x0, %eax
je 0x40d2
movq -0x8(%rbp), %rax
movq 0x48(%rax), %rax
movl $0x0, 0x8(%rax)
movq -0x8(%rbp), %rax
movq $0x0, 0x48(%rax)
jmp 0x40d4
jmp 0x40d6
movq -0x8(%rbp), %rax
movl $0x0, 0x78(%rax)
movq -0x8(%rbp), %rax
movl 0x7c(%rax), %ecx
orl $0x1, %ecx
movl %ecx, 0x7c(%rax)
jmp 0x4249
movq -0x8(%rbp), %rax
movl 0x7c(%rax), %eax
andl $0x1, %eax
cmpl $0x1, %eax
je 0x4247
movq -0x18(%rbp), %rax
movq 0xb0(%rax), %rax
movq %rax, -0x20(%rbp)
movl -0xc(%rbp), %eax
andl $0x10, %eax
cmpl $0x0, %eax
jne 0x412b
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0x4bd0
movq -0x18(%rbp), %rax
movl 0xc(%rax), %eax
andl $0x80000, %eax          # imm = 0x80000
cmpl $0x0, %eax
jne 0x4145
movq -0x8(%rbp), %rdi
callq 0xedc0
movq -0x8(%rbp), %rax
movl $0x0, 0x78(%rax)
movq -0x8(%rbp), %rax
movl $0x1, 0x7c(%rax)
movq -0x8(%rbp), %rax
cmpq $0x0, (%rax)
jne 0x41d4
movq -0x8(%rbp), %rdi
addq $0x28, %rdi
callq 0x12740
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0xc8(%rax)
movq -0x18(%rbp), %rax
movq $0x0, 0xb0(%rax)
movq -0x18(%rbp), %rax
movq $0x0, 0xb8(%rax)
movq -0x18(%rbp), %rax
movq $0x0, 0x60(%rax)
movl $0x0, -0xc(%rbp)
movq -0x18(%rbp), %rax
cmpq $0x0, 0x40(%rax)
je 0x41d2
movq -0x18(%rbp), %rax
movq 0x40(%rax), %rdi
addq $0x40, %rdi
callq 0x2250
jmp 0x423e
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq $0x0, 0x8(%rax)
movq -0x8(%rbp), %rax
movq (%rax), %rax
movl 0x7c(%rax), %ecx
andl $-0x11, %ecx
movl %ecx, 0x7c(%rax)
movq -0x18(%rbp), %rax
movq -0x8(%rbp), %rcx
movq 0x88(%rcx), %rdx
movq %rdx, 0xb0(%rax)
movq 0x90(%rcx), %rcx
movq %rcx, 0xb8(%rax)
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x12710
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rdi
callq 0x12710
movq -0x8(%rbp), %rax
movq 0x48(%rax), %rdi
callq 0x2030
movq -0x20(%rbp), %rdi
callq 0x12710
jmp 0x4249
movl -0xc(%rbp), %eax
andl $0x20, %eax
cmpl $0x0, %eax
je 0x425d
movq -0x8(%rbp), %rdi
callq 0x2030
addq $0x20, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)