src/backend/replication/logical/reorderbuffer.c
static void
ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
						   char *data)
{
	ReorderBufferDiskChange *ondisk;
	ReorderBufferChange *change;

	ondisk = (ReorderBufferDiskChange *) data;

	change = ReorderBufferGetChange(rb);

	/* copy static part */
	memcpy(change, &ondisk->change, sizeof(ReorderBufferChange));

	data += sizeof(ReorderBufferDiskChange);

	/* restore individual stuff */
	switch (change->action)
	{
			/* fall through these, they're all similar enough */
		case REORDER_BUFFER_CHANGE_INSERT:
		case REORDER_BUFFER_CHANGE_UPDATE:
		case REORDER_BUFFER_CHANGE_DELETE:
		case REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT:
			if (change->data.tp.oldtuple)
			{
				uint32		tuplelen = ((HeapTuple) data)->t_len;

				change->data.tp.oldtuple =
					ReorderBufferGetTupleBuf(rb, tuplelen - SizeofHeapTupleHeader);

				/* restore ->tuple */
				memcpy(&change->data.tp.oldtuple->tuple, data,
					   sizeof(HeapTupleData));
				data += sizeof(HeapTupleData);

				/* reset t_data pointer into the new tuplebuf */
				change->data.tp.oldtuple->tuple.t_data =
					ReorderBufferTupleBufData(change->data.tp.oldtuple);

				/* restore tuple data itself */
				memcpy(change->data.tp.oldtuple->tuple.t_data, data, tuplelen);
				data += tuplelen;
			}

			if (change->data.tp.newtuple)
			{
				/* here, data might not be suitably aligned! */
				uint32		tuplelen;

				memcpy(&tuplelen, data + offsetof(HeapTupleData, t_len),
					   sizeof(uint32));

				change->data.tp.newtuple =
					ReorderBufferGetTupleBuf(rb, tuplelen - SizeofHeapTupleHeader);

				/* restore ->tuple */
				memcpy(&change->data.tp.newtuple->tuple, data,
					   sizeof(HeapTupleData));
				data += sizeof(HeapTupleData);

				/* reset t_data pointer into the new tuplebuf */
				change->data.tp.newtuple->tuple.t_data =
					ReorderBufferTupleBufData(change->data.tp.newtuple);

				/* restore tuple data itself */
				memcpy(change->data.tp.newtuple->tuple.t_data, data, tuplelen);
				data += tuplelen;
			}

			break;
		case REORDER_BUFFER_CHANGE_MESSAGE:
			{
				Size		prefix_size;

				/* read prefix */
				memcpy(&prefix_size, data, sizeof(Size));
				data += sizeof(Size);
				change->data.msg.prefix = MemoryContextAlloc(rb->context,
															 prefix_size);
				memcpy(change->data.msg.prefix, data, prefix_size);
				Assert(change->data.msg.prefix[prefix_size - 1] == '\0');
				data += prefix_size;

				/* read the message */
				memcpy(&change->data.msg.message_size, data, sizeof(Size));
				data += sizeof(Size);
				change->data.msg.message = MemoryContextAlloc(rb->context,
											  change->data.msg.message_size);
				memcpy(change->data.msg.message, data,
					   change->data.msg.message_size);
				data += change->data.msg.message_size;

				break;
			}
		case REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT:
			{
				Snapshot	oldsnap;
				Snapshot	newsnap;
				Size		size;

				oldsnap = (Snapshot) data;

				size = sizeof(SnapshotData) +
					sizeof(TransactionId) * oldsnap->xcnt +
					sizeof(TransactionId) * (oldsnap->subxcnt + 0);

				change->data.snapshot = MemoryContextAllocZero(rb->context, size);

				newsnap = change->data.snapshot;

				memcpy(newsnap, data, size);
				newsnap->xip = (TransactionId *)
					(((char *) newsnap) + sizeof(SnapshotData));
				newsnap->subxip = newsnap->xip + newsnap->xcnt;
				newsnap->copied = true;
				break;
			}
			/* the base struct contains all the data, easy peasy */
		case REORDER_BUFFER_CHANGE_INTERNAL_SPEC_CONFIRM:
		case REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID:
		case REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID:
			break;
	}

	dlist_push_tail(&txn->changes, &change->node);
	txn->nentries_mem++;
}
/*
 * Convert change from its on-disk format to in-memory format and queue it onto
 * the TXN's ->changes list.
 *
 * Note: although "data" is declared char*, at entry it points to a
 * maxalign'd buffer, making it safe in most of this function to assume
 * that the pointed-to data is suitably aligned for direct access.
 */
Convert change from its on-disk format to in-memory format and queue it onto
the TXN's ->changes list.

although "data" is declared char*, at entry it points to a
maxalign'd buffer, making it safe in most of this function to assume
that the pointed-to data is suitably aligned for direct access.
Convert change from its on - disk format to in - memory format and queue it onto the TXN ' s - > changes list . although " data " is declared char * at entry it points to a maxalign ' d buffer making it safe in most of this function to assume that the pointed - to data is suitably aligned for direct access .
static void
ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
						   char *data)
{
	ReorderBufferDiskChange *ondisk;
	ReorderBufferChange *change;
	ondisk = (ReorderBufferDiskChange *) data;
	change = ReorderBufferGetChange(rb);
	memcpy(change, &ondisk->change, sizeof(ReorderBufferChange));
	data += sizeof(ReorderBufferDiskChange);
	switch (change->action)
	{
		case REORDER_BUFFER_CHANGE_INSERT:
		case REORDER_BUFFER_CHANGE_UPDATE:
		case REORDER_BUFFER_CHANGE_DELETE:
		case REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT:
			if (change->data.tp.oldtuple)
			{
				uint32		tuplelen = ((HeapTuple) data)->t_len;
				change->data.tp.oldtuple =
					ReorderBufferGetTupleBuf(rb, tuplelen - SizeofHeapTupleHeader);
				memcpy(&change->data.tp.oldtuple->tuple, data,
					   sizeof(HeapTupleData));
				data += sizeof(HeapTupleData);
				change->data.tp.oldtuple->tuple.t_data =
					ReorderBufferTupleBufData(change->data.tp.oldtuple);
				memcpy(change->data.tp.oldtuple->tuple.t_data, data, tuplelen);
				data += tuplelen;
			}
			if (change->data.tp.newtuple)
			{
				uint32		tuplelen;
				memcpy(&tuplelen, data + offsetof(HeapTupleData, t_len),
					   sizeof(uint32));
				change->data.tp.newtuple =
					ReorderBufferGetTupleBuf(rb, tuplelen - SizeofHeapTupleHeader);
				memcpy(&change->data.tp.newtuple->tuple, data,
					   sizeof(HeapTupleData));
				data += sizeof(HeapTupleData);
				change->data.tp.newtuple->tuple.t_data =
					ReorderBufferTupleBufData(change->data.tp.newtuple);
				memcpy(change->data.tp.newtuple->tuple.t_data, data, tuplelen);
				data += tuplelen;
			}
			break;
		case REORDER_BUFFER_CHANGE_MESSAGE:
			{
				Size		prefix_size;
				memcpy(&prefix_size, data, sizeof(Size));
				data += sizeof(Size);
				change->data.msg.prefix = MemoryContextAlloc(rb->context,
															 prefix_size);
				memcpy(change->data.msg.prefix, data, prefix_size);
				Assert(change->data.msg.prefix[prefix_size - 1] == '\0');
				data += prefix_size;
				memcpy(&change->data.msg.message_size, data, sizeof(Size));
				data += sizeof(Size);
				change->data.msg.message = MemoryContextAlloc(rb->context,
											  change->data.msg.message_size);
				memcpy(change->data.msg.message, data,
					   change->data.msg.message_size);
				data += change->data.msg.message_size;
				break;
			}
		case REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT:
			{
				Snapshot	oldsnap;
				Snapshot	newsnap;
				Size		size;
				oldsnap = (Snapshot) data;
				size = sizeof(SnapshotData) +
					sizeof(TransactionId) * oldsnap->xcnt +
					sizeof(TransactionId) * (oldsnap->subxcnt + 0);
				change->data.snapshot = MemoryContextAllocZero(rb->context, size);
				newsnap = change->data.snapshot;
				memcpy(newsnap, data, size);
				newsnap->xip = (TransactionId *)
					(((char *) newsnap) + sizeof(SnapshotData));
				newsnap->subxip = newsnap->xip + newsnap->xcnt;
				newsnap->copied = true;
				break;
			}
		case REORDER_BUFFER_CHANGE_INTERNAL_SPEC_CONFIRM:
		case REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID:
		case REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID:
			break;
	}
	dlist_push_tail(&txn->changes, &change->node);
	txn->nentries_mem++;
}
static void ReorderBufferRestoreChange ( ReorderBuffer * rb , ReorderBufferTXN * txn , char * data ) { ReorderBufferDiskChange * ondisk ; ReorderBufferChange * change ; ondisk = ( ReorderBufferDiskChange * ) data ; change = ReorderBufferGetChange ( rb ) ; memcpy ( change , & ondisk -> change , sizeof ( ReorderBufferChange ) ) ; data += sizeof ( ReorderBufferDiskChange ) ; switch ( change -> action ) { case REORDER_BUFFER_CHANGE_INSERT : case REORDER_BUFFER_CHANGE_UPDATE : case REORDER_BUFFER_CHANGE_DELETE : case REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT : if ( change -> data . tp . oldtuple ) { uint32 tuplelen = ( ( HeapTuple ) data ) -> t_len ; change -> data . tp . oldtuple = ReorderBufferGetTupleBuf ( rb , tuplelen - SizeofHeapTupleHeader ) ; memcpy ( & change -> data . tp . oldtuple -> tuple , data , sizeof ( HeapTupleData ) ) ; data += sizeof ( HeapTupleData ) ; change -> data . tp . oldtuple -> tuple . t_data = ReorderBufferTupleBufData ( change -> data . tp . oldtuple ) ; memcpy ( change -> data . tp . oldtuple -> tuple . t_data , data , tuplelen ) ; data += tuplelen ; } if ( change -> data . tp . newtuple ) { uint32 tuplelen ; memcpy ( & tuplelen , data + offsetof ( HeapTupleData , t_len ) , sizeof ( uint32 ) ) ; change -> data . tp . newtuple = ReorderBufferGetTupleBuf ( rb , tuplelen - SizeofHeapTupleHeader ) ; memcpy ( & change -> data . tp . newtuple -> tuple , data , sizeof ( HeapTupleData ) ) ; data += sizeof ( HeapTupleData ) ; change -> data . tp . newtuple -> tuple . t_data = ReorderBufferTupleBufData ( change -> data . tp . newtuple ) ; memcpy ( change -> data . tp . newtuple -> tuple . t_data , data , tuplelen ) ; data += tuplelen ; } break ; case REORDER_BUFFER_CHANGE_MESSAGE : { Size prefix_size ; memcpy ( & prefix_size , data , sizeof ( Size ) ) ; data += sizeof ( Size ) ; change -> data . msg . prefix = MemoryContextAlloc ( rb -> context , prefix_size ) ; memcpy ( change -> data . msg . prefix , data , prefix_size ) ; Assert ( change -> data . msg . prefix [ prefix_size - 1 ] == ' \0 ' ) ; data += prefix_size ; memcpy ( & change -> data . msg . message_size , data , sizeof ( Size ) ) ; data += sizeof ( Size ) ; change -> data . msg . message = MemoryContextAlloc ( rb -> context , change -> data . msg . message_size ) ; memcpy ( change -> data . msg . message , data , change -> data . msg . message_size ) ; data += change -> data . msg . message_size ; break ; } case REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT : { Snapshot oldsnap ; Snapshot newsnap ; Size size ; oldsnap = ( Snapshot ) data ; size = sizeof ( SnapshotData ) + sizeof ( TransactionId ) * oldsnap -> xcnt + sizeof ( TransactionId ) * ( oldsnap -> subxcnt + 0 ) ; change -> data . snapshot = MemoryContextAllocZero ( rb -> context , size ) ; newsnap = change -> data . snapshot ; memcpy ( newsnap , data , size ) ; newsnap -> xip = ( TransactionId * ) ( ( ( char * ) newsnap ) + sizeof ( SnapshotData ) ) ; newsnap -> subxip = newsnap -> xip + newsnap -> xcnt ; newsnap -> copied = true ; break ; } case REORDER_BUFFER_CHANGE_INTERNAL_SPEC_CONFIRM : case REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID : case REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID : break ; } dlist_push_tail ( & txn -> changes , & change -> node ) ; txn -> nentries_mem ++ ; }
Convert change from its on-disk format to in-memory format and queue it onto
 the TXN's ->changes list.
Convert change from its on - disk format to in - memory format and queue it onto the TXN ' s - > changes list .
/* copy static part */ /* restore individual stuff */ /* fall through these, they're all similar enough */ /* restore ->tuple */ /* reset t_data pointer into the new tuplebuf */ /* restore tuple data itself */ /* here, data might not be suitably aligned! */ /* restore ->tuple */ /* reset t_data pointer into the new tuplebuf */ /* restore tuple data itself */ /* read prefix */ /* read the message */ /* the base struct contains all the data, easy peasy */