src/backend/replication/logical/reorderbuffer.c
static void
ReorderBufferCleanupTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
{
	bool		found;
	dlist_mutable_iter iter;

	/* cleanup subtransactions & their changes */
	dlist_foreach_modify(iter, &txn->subtxns)
	{
		ReorderBufferTXN *subtxn;

		subtxn = dlist_container(ReorderBufferTXN, node, iter.cur);

		/*
		 * Subtransactions are always associated to the toplevel TXN, even if
		 * they originally were happening inside another subtxn, so we won't
		 * ever recurse more than one level deep here.
		 */
		Assert(subtxn->is_known_as_subxact);
		Assert(subtxn->nsubtxns == 0);

		ReorderBufferCleanupTXN(rb, subtxn);
	}

	/* cleanup changes in the toplevel txn */
	dlist_foreach_modify(iter, &txn->changes)
	{
		ReorderBufferChange *change;

		change = dlist_container(ReorderBufferChange, node, iter.cur);

		ReorderBufferReturnChange(rb, change);
	}

	/*
	 * Cleanup the tuplecids we stored for decoding catalog snapshot access.
	 * They are always stored in the toplevel transaction.
	 */
	dlist_foreach_modify(iter, &txn->tuplecids)
	{
		ReorderBufferChange *change;

		change = dlist_container(ReorderBufferChange, node, iter.cur);
		Assert(change->action == REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID);
		ReorderBufferReturnChange(rb, change);
	}

	if (txn->base_snapshot != NULL)
	{
		SnapBuildSnapDecRefcount(txn->base_snapshot);
		txn->base_snapshot = NULL;
		txn->base_snapshot_lsn = InvalidXLogRecPtr;
	}

	/*
	 * Remove TXN from its containing list.
	 *
	 * Note: if txn->is_known_as_subxact, we are deleting the TXN from its
	 * parent's list of known subxacts; this leaves the parent's nsubxacts
	 * count too high, but we don't care.  Otherwise, we are deleting the TXN
	 * from the LSN-ordered list of toplevel TXNs.
	 */
	dlist_delete(&txn->node);

	/* now remove reference from buffer */
	hash_search(rb->by_txn,
				(void *) &txn->xid,
				HASH_REMOVE,
				&found);
	Assert(found);

	/* remove entries spilled to disk */
	if (txn->nentries != txn->nentries_mem)
		ReorderBufferRestoreCleanup(rb, txn);

	/* deallocate */
	ReorderBufferReturnTXN(rb, txn);
}
/*
 * Cleanup the contents of a transaction, usually after the transaction
 * committed or aborted.
 */
Cleanup the contents of a transaction, usually after the transaction
committed or aborted.
Cleanup the contents of a transaction usually after the transaction committed or aborted .
static void
ReorderBufferCleanupTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
{
	bool		found;
	dlist_mutable_iter iter;
	dlist_foreach_modify(iter, &txn->subtxns)
	{
		ReorderBufferTXN *subtxn;
		subtxn = dlist_container(ReorderBufferTXN, node, iter.cur);
		Assert(subtxn->is_known_as_subxact);
		Assert(subtxn->nsubtxns == 0);
		ReorderBufferCleanupTXN(rb, subtxn);
	}
	dlist_foreach_modify(iter, &txn->changes)
	{
		ReorderBufferChange *change;
		change = dlist_container(ReorderBufferChange, node, iter.cur);
		ReorderBufferReturnChange(rb, change);
	}
	dlist_foreach_modify(iter, &txn->tuplecids)
	{
		ReorderBufferChange *change;
		change = dlist_container(ReorderBufferChange, node, iter.cur);
		Assert(change->action == REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID);
		ReorderBufferReturnChange(rb, change);
	}
	if (txn->base_snapshot != NULL)
	{
		SnapBuildSnapDecRefcount(txn->base_snapshot);
		txn->base_snapshot = NULL;
		txn->base_snapshot_lsn = InvalidXLogRecPtr;
	}
	dlist_delete(&txn->node);
	hash_search(rb->by_txn,
				(void *) &txn->xid,
				HASH_REMOVE,
				&found);
	Assert(found);
	if (txn->nentries != txn->nentries_mem)
		ReorderBufferRestoreCleanup(rb, txn);
	ReorderBufferReturnTXN(rb, txn);
}
static void ReorderBufferCleanupTXN ( ReorderBuffer * rb , ReorderBufferTXN * txn ) { bool found ; dlist_mutable_iter iter ; dlist_foreach_modify ( iter , & txn -> subtxns ) { ReorderBufferTXN * subtxn ; subtxn = dlist_container ( ReorderBufferTXN , node , iter . cur ) ; Assert ( subtxn -> is_known_as_subxact ) ; Assert ( subtxn -> nsubtxns == 0 ) ; ReorderBufferCleanupTXN ( rb , subtxn ) ; } dlist_foreach_modify ( iter , & txn -> changes ) { ReorderBufferChange * change ; change = dlist_container ( ReorderBufferChange , node , iter . cur ) ; ReorderBufferReturnChange ( rb , change ) ; } dlist_foreach_modify ( iter , & txn -> tuplecids ) { ReorderBufferChange * change ; change = dlist_container ( ReorderBufferChange , node , iter . cur ) ; Assert ( change -> action == REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID ) ; ReorderBufferReturnChange ( rb , change ) ; } if ( txn -> base_snapshot != NULL ) { SnapBuildSnapDecRefcount ( txn -> base_snapshot ) ; txn -> base_snapshot = NULL ; txn -> base_snapshot_lsn = InvalidXLogRecPtr ; } dlist_delete ( & txn -> node ) ; hash_search ( rb -> by_txn , ( void * ) & txn -> xid , HASH_REMOVE , & found ) ; Assert ( found ) ; if ( txn -> nentries != txn -> nentries_mem ) ReorderBufferRestoreCleanup ( rb , txn ) ; ReorderBufferReturnTXN ( rb , txn ) ; }
Cleanup the contents of a transaction, usually after the transaction
 committed or aborted.
Cleanup the contents of a transaction usually after the transaction committed or aborted .
/* cleanup subtransactions & their changes */ /*
		 * Subtransactions are always associated to the toplevel TXN, even if
		 * they originally were happening inside another subtxn, so we won't
		 * ever recurse more than one level deep here.
		 */ /* cleanup changes in the toplevel txn */ /*
	 * Cleanup the tuplecids we stored for decoding catalog snapshot access.
	 * They are always stored in the toplevel transaction.
	 */ /*
	 * Remove TXN from its containing list.
	 *
	 * Note: if txn->is_known_as_subxact, we are deleting the TXN from its
	 * parent's list of known subxacts; this leaves the parent's nsubxacts
	 * count too high, but we don't care.  Otherwise, we are deleting the TXN
	 * from the LSN-ordered list of toplevel TXNs.
	 */ /* now remove reference from buffer */ /* remove entries spilled to disk */ /* deallocate */