v52-0005-Fix-apply-worker-empty-prepare-dev-logs.patch

application/octet-stream

Filename: v52-0005-Fix-apply-worker-empty-prepare-dev-logs.patch
Type: application/octet-stream
Part: 3
Message: Re: [HACKERS] logical decoding of two-phase transactions

Patch

Format: format-patch
Series: patch v52-0005
Subject: Fix apply worker empty prepare (dev logs).
File+
src/backend/replication/logical/tablesync.c 23 6
src/backend/replication/logical/worker.c 58 15
From 62964901ebc60b40167b8f11db499bb60e5bcd99 Mon Sep 17 00:00:00 2001
From: Peter Smith <peter.b.smith@fujitsu.com>
Date: Mon, 8 Mar 2021 12:39:08 +1100
Subject: [PATCH v52] Fix apply worker empty prepare (dev logs).

NOT TO BE COMMITTED.

This patch is only for adding some developer logging which may help for
debugging/testing the "Fix apply worker empty prepare" patch.
---
 src/backend/replication/logical/tablesync.c | 29 +++++++++---
 src/backend/replication/logical/worker.c    | 73 +++++++++++++++++++++++------
 2 files changed, 81 insertions(+), 21 deletions(-)

diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index 97fc399..f3984d4 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -282,6 +282,12 @@ process_syncing_tables_for_sync(XLogRecPtr current_lsn)
 {
 	SpinLockAcquire(&MyLogicalRepWorker->relmutex);
 
+	elog(LOG,
+		 "!!> process_syncing_tables_for_sync: state = '%c', current_lsn = %X/%X, relstate_lsn = %X/%X",
+		 MyLogicalRepWorker->relstate,
+		 LSN_FORMAT_ARGS(current_lsn),
+		 LSN_FORMAT_ARGS(MyLogicalRepWorker->relstate_lsn));
+
 	if (MyLogicalRepWorker->relstate == SUBREL_STATE_CATCHUP &&
 		current_lsn >= MyLogicalRepWorker->relstate_lsn)
 	{
@@ -1127,6 +1133,8 @@ FetchTableStates(bool *started_tx)
 		ListCell   *lc;
 		SubscriptionRelState *rstate;
 
+		elog(LOG, "!!> FetchTableStates: Re-fetching the state list caches");
+
 		/* Clean the old lists. */
 		list_free_deep(table_states_all);
 		table_states_all = NIL;
@@ -1149,6 +1157,7 @@ FetchTableStates(bool *started_tx)
 			rstate = palloc(sizeof(SubscriptionRelState));
 			memcpy(rstate, cur_rstate, sizeof(SubscriptionRelState));
 			table_states_all = lappend(table_states_all, rstate);
+			elog(LOG, "!!> FetchTableStates: table_states_all - added Table relid %u with state '%c'", rstate->relid, rstate->state);
 
 			/* List of only not-ready states */
 			if (cur_rstate->state != SUBREL_STATE_READY)
@@ -1156,12 +1165,17 @@ FetchTableStates(bool *started_tx)
 				rstate = palloc(sizeof(SubscriptionRelState));
 				memcpy(rstate, cur_rstate, sizeof(SubscriptionRelState));
 				table_states_not_ready = lappend(table_states_not_ready, rstate);
+				elog(LOG, "!!> FetchTableStates: table_states_not_ready - added Table relid %u with state '%c'", rstate->relid, rstate->state);
 			}
 		}
 		MemoryContextSwitchTo(oldctx);
 
 		table_states_valid = true;
 	}
+	else
+	{
+		elog(LOG, "!!> FetchTableStates: Already up-to-date");
+	}
 }
 
 /*
@@ -1175,6 +1189,8 @@ AnyTablesyncInProgress()
 	int			count = 0;
 	ListCell   *lc;
 
+	elog(LOG, "!!> AnyTablesyncInProgress?");
+
 	/* We need up-to-date sync state info for subscription tables here. */
 	FetchTableStates(&started_tx);
 
@@ -1186,8 +1202,8 @@ AnyTablesyncInProgress()
 		SubscriptionRelState *rstate = (SubscriptionRelState *) lfirst(lc);
 
 		count++;
-		elog(DEBUG1,
-			 "AnyTablesyncInProgress?: #%d. Table relid %u has state '%c'",
+		elog(LOG,
+			 "!!> AnyTablesyncInProgress?: #%d. Table relid %u has state '%c'",
 			 count,
 			 rstate->relid,
 			 rstate->state);
@@ -1204,6 +1220,7 @@ AnyTablesyncInProgress()
 		if (rstate->state != SUBREL_STATE_SYNCDONE &&
 			rstate->state != SUBREL_STATE_READY)
 		{
+			elog(LOG, "!!> AnyTablesyncInProgress?: Table relid %u is busy!", rstate->relid);
 			found_busy = true;
 			break;
 		}
@@ -1215,8 +1232,8 @@ AnyTablesyncInProgress()
 		pgstat_report_stat(false);
 	}
 
-	elog(DEBUG1,
-		 "AnyTablesyncInProgress?: Scanned %d tables, and found busy = %s",
+	elog(LOG,
+		 "!!> AnyTablesyncInProgress?: Scanned %d tables, and found busy = %s",
 		 count,
 		 found_busy ? "true" : "false");
 
@@ -1242,8 +1259,8 @@ BiggestTablesyncLSN()
 			biggest_lsn = rstate->lsn;
 	}
 
-	elog(DEBUG1,
-		 "BiggestTablesyncLSN: Scanned %d tables. Biggest lsn found = %X/%X",
+	elog(LOG,
+		 "!!> BiggestTablesyncLSN: Scanned %d tables. Biggest lsn found = %X/%X",
 		 count,
 		 LSN_FORMAT_ARGS(biggest_lsn));
 
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 89988b8..430cf57 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -830,14 +830,16 @@ apply_handle_begin_prepare(StringInfo s)
 		 * Make sure every tablesync has reached at least SYNCDONE state
 		 * before letting the apply worker proceed.
 		 */
-		elog(DEBUG1,
-			 "apply_handle_begin_prepare, end_lsn = %X/%X, final_lsn = %X/%X, lstate_lsn = %X/%X",
+		elog(LOG,
+			 "!!> apply_handle_begin_prepare, end_lsn = %X/%X, final_lsn = %X/%X, lstate_lsn = %X/%X",
 			 LSN_FORMAT_ARGS(begin_data.end_lsn),
 			 LSN_FORMAT_ARGS(begin_data.final_lsn),
 			 LSN_FORMAT_ARGS(MyLogicalRepWorker->relstate_lsn));
 
 		while (AnyTablesyncInProgress())
 		{
+			elog(LOG, "!!> apply_handle_begin_prepare - waiting for all sync workers to be DONE/READY");
+
 			process_syncing_tables(begin_data.final_lsn);
 
 			/* This latch is to prevent 100% CPU looping. */
@@ -855,7 +857,12 @@ apply_handle_begin_prepare(StringInfo s)
 		 * prepared) will be saved to a spoolfile for replay later at
 		 * commit_prepared time.
 		 */
-		if (begin_data.final_lsn < BiggestTablesyncLSN())
+		if (begin_data.final_lsn < BiggestTablesyncLSN()
+#if 0
+			|| true				/* XXX - Add this line to force psf (for
+								 * easier debugging) */
+#endif
+			)
 		{
 			char		psfpath[MAXPGPATH];
 
@@ -897,6 +904,8 @@ apply_handle_prepare(StringInfo s)
 	{
 		PsfHashEntry *hentry;
 
+		elog(LOG, "!!> apply_handle_prepare: SPOOLING");
+
 		/* Write the PREPARE info to the psf file. */
 		prepare_spoolfile_handler(LOGICAL_REP_MSG_PREPARE, s);
 
@@ -915,6 +924,8 @@ apply_handle_prepare(StringInfo s)
 		 * removal on proc-exit just in case there is an unexpected restart
 		 * between now and when commit_prepared happens.
 		 */
+		elog(LOG,
+			"!!> apply_handle_prepare: Make sure the spoolfile is not removed on proc-exit");
 		hentry = (PsfHashEntry *) hash_search(psf_hash,
 											  psf_cur.name,
 											  HASH_FIND,
@@ -1001,6 +1012,8 @@ apply_handle_commit_prepared(StringInfo s)
 	{
 		int			nchanges;
 
+		elog(LOG, "!!> apply_handle_commit_prepared: replaying the spooled messages");
+
 		/*
 		 * Replay/dispatch the spooled messages (including lastly, the PREPARE
 		 * message).
@@ -1009,8 +1022,8 @@ apply_handle_commit_prepared(StringInfo s)
 		ensure_transaction();
 
 		nchanges = prepare_spoolfile_replay_messages(psfpath, prepare_data.prepare_lsn);
-		elog(DEBUG1,
-			 "apply_handle_commit_prepared: replayed %d (all) changes.",
+		elog(LOG,
+			 "!!> apply_handle_commit_prepared: replayed %d (all) changes.",
 			 nchanges);
 
 		/*
@@ -1078,6 +1091,7 @@ apply_handle_rollback_prepared(StringInfo s)
 	 * Prepare Spoolfile (using_psf) because in that case there is no matching
 	 * PrepareTransactionBlock done yet.
 	 */
+	elog(LOG, "!!> apply_handle_rollback_prepared: using_psf = %d", using_psf);
 	if (!using_psf &&
 		LookupGXact(rollback_data.gid, rollback_data.prepare_end_lsn,
 					rollback_data.preparetime))
@@ -2356,18 +2370,22 @@ apply_dispatch(StringInfo s)
 			return;
 
 		case LOGICAL_REP_MSG_BEGIN_PREPARE:
+			elog(LOG, "!!> ------ apply_handle_begin_prepare ------");
 			apply_handle_begin_prepare(s);
 			return;
 
 		case LOGICAL_REP_MSG_PREPARE:
+			elog(LOG, "!!> ------ apply_handle_prepare ------");
 			apply_handle_prepare(s);
 			return;
 
 		case LOGICAL_REP_MSG_COMMIT_PREPARED:
+			elog(LOG, "!!> ------ apply_handle_commit_prepared ------");
 			apply_handle_commit_prepared(s);
 			return;
 
 		case LOGICAL_REP_MSG_ROLLBACK_PREPARED:
+			elog(LOG, "!!> ------ apply_handle_rollback_prepared ------");
 			apply_handle_rollback_prepared(s);
 			return;
 
@@ -3561,8 +3579,8 @@ IsLogicalWorker(void)
 static bool
 prepare_spoolfile_handler(LogicalRepMsgType action, StringInfo s)
 {
-	elog(DEBUG1,
-		 "prepare_spoolfile_handler for action '%c'. %s write to spool file",
+	elog(LOG,
+		 "!!> prepare_spoolfile_handler for action '%c'. %s write to spool file",
 		 action,
 		 psf_cur.is_spooling ? "Do" : "Don't");
 
@@ -3586,7 +3604,7 @@ prepare_spoolfile_create(char *path)
 	bool		found;
 	PsfHashEntry *hentry;
 
-	elog(DEBUG1, "creating file \"%s\" for prepare changes", path);
+	elog(LOG, "!!> creating file \"%s\" for prepare changes", path);
 
 	Assert(!psf_cur.is_spooling);
 
@@ -3598,7 +3616,7 @@ prepare_spoolfile_create(char *path)
 
 	if (!found)
 	{
-		elog(DEBUG1, "Not found file \"%s\". Create it.", path);
+		elog(LOG, "!!> Not found file \"%s\". Create it.", path);
 		psf_cur.vfd = PathNameOpenFile(path, O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
 		if (psf_cur.vfd < 0)
 		{
@@ -3616,7 +3634,7 @@ prepare_spoolfile_create(char *path)
 		 * Open the file and seek to the beginning because we always want to
 		 * create/overwrite this file.
 		 */
-		elog(DEBUG1, "Found file \"%s\". Overwrite it.", path);
+		elog(LOG, "!!> Found file \"%s\". Overwrite it.", path);
 		psf_cur.vfd = PathNameOpenFile(path, O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
 		if (psf_cur.vfd < 0)
 		{
@@ -3641,6 +3659,7 @@ prepare_spoolfile_create(char *path)
 static void
 prepare_spoolfile_close()
 {
+	elog(LOG, "!!> prepare_spoolfile_close");
 	if (psf_cur.vfd >= 0)
 		FileClose(psf_cur.vfd);
 
@@ -3656,6 +3675,8 @@ prepare_spoolfile_close()
 static void
 prepare_spoolfile_delete(char *path)
 {
+	elog(LOG, "!!> prepare_spoolfile_delete: \"%s\"", path);
+
 	/* The current psf should be closed already, but make sure anyway. */
 	prepare_spoolfile_close();
 
@@ -3681,18 +3702,20 @@ prepare_spoolfile_write(char action, StringInfo s)
 
 	Assert(psf_cur.is_spooling);
 
-	elog(DEBUG1, "prepare_spoolfile_write: writing action '%c'", action);
+	elog(LOG, "!!> prepare_spoolfile_write: writing action '%c'", action);
 
 	/* total on-disk size, including the action type character */
 	len = (s->len - s->cursor) + sizeof(char);
 
 	/* first write the size */
+	elog(LOG, "!!> prepare_spoolfile_write: A writing len bytes = %d", len);
 	bytes_written = FileWrite(psf_cur.vfd, (char *)&len, sizeof(len),
 							  psf_cur.cur_offset, WAIT_EVENT_DATA_FILE_WRITE);
 	Assert(bytes_written == sizeof(len));
 	psf_cur.cur_offset += bytes_written;
 
 	/* then the action */
+	elog(LOG, "!!> prepare_spoolfile_write: B writing action = %c, %d bytes", action, (int)sizeof(action));
 	bytes_written = FileWrite(psf_cur.vfd, &action, sizeof(action),
 							  psf_cur.cur_offset, WAIT_EVENT_DATA_FILE_WRITE);
 	Assert(bytes_written == sizeof(action));
@@ -3701,6 +3724,7 @@ prepare_spoolfile_write(char action, StringInfo s)
 	/* and finally the remaining part of the buffer (after the XID) */
 	len = (s->len - s->cursor);
 
+	elog(LOG, "!!> prepare_spoolfile_write: C writing len bytes = %d", len);
 	bytes_written = FileWrite(psf_cur.vfd, &s->data[s->cursor], len,
 							  psf_cur.cur_offset, WAIT_EVENT_DATA_FILE_WRITE);
 	Assert(bytes_written == len);
@@ -3734,6 +3758,12 @@ prepare_spoolfile_exists(char *path)
 		if (fd >= 0)
 			FileClose(fd);
 
+		elog(LOG,
+			 "!!> prepare_spoolfile_exists: Prepared spoolfile \"%s\" was "
+			 "not found in the HTAB, but was %s on the disk.",
+			 path,
+			 found ? "found" : "not found");
+
 		/*
 		 * And if it was found on disk then create the HTAB entry for it.
 		 */
@@ -3743,10 +3773,16 @@ prepare_spoolfile_exists(char *path)
 										  path,
 										  HASH_ENTER,
 										  NULL);
+			elog(LOG, "!!> prepare_spoolfile_exists: Created new HTAB entry '%s'", hentry->name);
 			hentry->allow_delete = false;
 		}
 	}
 
+	elog(LOG,
+		 "!!> prepare_spoolfile_exists: Prepared spoolfile \"%s\" was %s",
+		 path,
+		 found ? "found" : "not found");
+
 	return found;
 }
 
@@ -3763,8 +3799,8 @@ prepare_spoolfile_replay_messages(char *path, XLogRecPtr final_lsn)
 				oldctx2;
 	PsfFile		psf = { .is_spooling = false, .vfd = -1, .cur_offset = 0 };
 
-	elog(DEBUG1,
-		 "prepare_spoolfile_replay_messages: replaying changes from file \"%s\"",
+	elog(LOG,
+		 "!!> prepare_spoolfile_replay_messages: replaying changes from file \"%s\"",
 		 path);
 
 	/*
@@ -3809,6 +3845,7 @@ prepare_spoolfile_replay_messages(char *path, XLogRecPtr final_lsn)
 		nbytes = FileRead(psf.vfd, (char *) &len, sizeof(len),
 						  psf.cur_offset, WAIT_EVENT_DATA_FILE_READ);
 		psf.cur_offset += nbytes;
+		elog(LOG, "!!> prepare_spoolfile_replay_messages: nbytes = %d, len = %d", nbytes, len);
 
 		/* have we reached end of the file? */
 		if (nbytes == 0)
@@ -3827,6 +3864,7 @@ prepare_spoolfile_replay_messages(char *path, XLogRecPtr final_lsn)
 		buffer = repalloc(buffer, len);
 
 		/* and finally read the data into the buffer */
+		elog(LOG, "!!> prepare_spoolfile_replay_messages: read %d bytes into buffer", len);
 		nbytes = FileRead(psf.vfd, buffer, len,
 						  psf.cur_offset, WAIT_EVENT_DATA_FILE_READ);
 		psf.cur_offset += nbytes;
@@ -3843,7 +3881,9 @@ prepare_spoolfile_replay_messages(char *path, XLogRecPtr final_lsn)
 		/* Ensure we are reading the data into our memory context. */
 		oldctx2 = MemoryContextSwitchTo(ApplyMessageContext);
 
+		elog(LOG, "!!> prepare_spoolfile_replay_messages: Before dispatch");
 		apply_dispatch(&s2);
+		elog(LOG, "!!> prepare_spoolfile_replay_messages: After dispatch");
 
 		MemoryContextReset(ApplyMessageContext);
 
@@ -3852,13 +3892,13 @@ prepare_spoolfile_replay_messages(char *path, XLogRecPtr final_lsn)
 		nchanges++;
 
 		if (nchanges % 1000 == 0)
-			elog(DEBUG1, "replayed %d changes from file '%s'",
+			elog(LOG, "!!> replayed %d changes from file '%s'",
 				 nchanges, path);
 	}
 
 	FileClose(psf.vfd);
 
-	elog(DEBUG1, "replayed %d (all) changes from file \"%s\"",
+	elog(LOG, "!!> replayed %d (all) changes from file \"%s\"",
 		 nchanges, path);
 
 	return nchanges;
@@ -3894,6 +3934,8 @@ prepare_spoolfile_on_proc_exit(int status, Datum arg)
 	HASH_SEQ_STATUS seq_status;
 	PsfHashEntry *hentry;
 
+	elog(LOG, "!!> prepare_spoolfile_on_proc_exit");
+
 	/* Iterate the HTAB looking for what file can be deleted. */
 	if (psf_hash)
 	{
@@ -3902,6 +3944,7 @@ prepare_spoolfile_on_proc_exit(int status, Datum arg)
 		{
 			char *path = hentry->name;
 
+			elog(LOG, "!!> prepare_spoolfile_proc_exit: found '%s'", path);
 			if (hentry->allow_delete)
 				prepare_spoolfile_delete(path);
 		}
-- 
1.8.3.1