fast_shutdown_syncrep_v1.patch

application/octet-stream

Filename: fast_shutdown_syncrep_v1.patch
Type: application/octet-stream
Part: 0
Message: Sync Rep and shutdown Re: Sync Rep v19

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: context
Series: patch v1
File+
src/backend/replication/syncrep.c 44 0
src/backend/tcop/dest.c 22 0
src/backend/tcop/postgres.c 3 0
*** a/src/backend/replication/syncrep.c
--- b/src/backend/replication/syncrep.c
***************
*** 164,183 **** SyncRepWaitForLSN(XLogRecPtr XactCommitLSN)
  
  			case SYNC_REP_WAITING:
  				/*
- 				 * Check for conditions that would cause us to leave the
- 				 * wait state before the LSN has been reached.
- 				 */
- 				if (!PostmasterIsAlive(true))
- 				{
- 					LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
- 					SHMQueueDelete(&(MyProc->syncRepLinks));
- 					LWLockRelease(SyncRepLock);
- 
- 					MyProc->syncRepState = SYNC_REP_MUST_DISCONNECT;
- 					return;
- 				}
- 
- 				/*
  				 * We don't receive SIGHUPs at this point, so resetting
  				 * synchronous_standby_names has no effect on waiters.
  				 */
--- 164,169 ----
***************
*** 191,216 **** SyncRepWaitForLSN(XLogRecPtr XactCommitLSN)
  				 * WalSender has checked our LSN and has removed us from
  				 * queue. Cleanup local state and leave.
  				 */
- 				Assert(SHMQueueIsDetached(&(MyProc->syncRepLinks)));
- 
  				MyProc->syncRepState = SYNC_REP_NOT_WAITING;
! 				MyProc->waitLSN.xlogid = 0;
! 				MyProc->waitLSN.xrecoff = 0;
! 
! 				if (new_status)
! 				{
! 					/* Reset ps display */
! 					set_ps_display(new_status, false);
! 					pfree(new_status);
! 				}
! 
! 				return;
  
  			case SYNC_REP_MUST_DISCONNECT:
  				return;
  
  			default:
! 				elog(FATAL, "invalid syncRepState");
  		}
  
  		/*
--- 177,212 ----
  				 * WalSender has checked our LSN and has removed us from
  				 * queue. Cleanup local state and leave.
  				 */
  				MyProc->syncRepState = SYNC_REP_NOT_WAITING;
! 				goto cleanup;
  
  			case SYNC_REP_MUST_DISCONNECT:
  				return;
  
  			default:
! 				/*
! 				 * Just close the connection without returning anything
! 				 * to the client instead of throwing ERROR/FATAL error
! 				 * since it's not allowed while in COMMIT state.
! 				 */
! 				elog(WARNING, "invalid syncRepState");
! 				goto disconnect;
! 		}
! 
! 		/*
! 		 * Check for conditions that would cause us to leave the
! 		 * wait state before the LSN has been reached.
! 		 */
! 		if (!PostmasterIsAlive(true) || ProcDiePending)
! 		{
! 			if (ProcDiePending)
! 				ereport(LOG,
! 						(errcode(ERRCODE_ADMIN_SHUTDOWN),
! 						 errmsg("canceling the wait for replication and terminating "
! 								"connection due to administrator command"),
! 						 errdetail("The transaction has already been committed locally "
! 								   "but might have not been replicated to the standby.")));
! 			goto disconnect;
  		}
  
  		/*
***************
*** 220,225 **** SyncRepWaitForLSN(XLogRecPtr XactCommitLSN)
--- 216,241 ----
  		 */
  		WaitLatch(&MyProc->waitLatch, 60000000L);
  	}
+ 
+ disconnect:
+ 	LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
+ 	SHMQueueDelete(&(MyProc->syncRepLinks));
+ 	LWLockRelease(SyncRepLock);
+ 
+ 	MyProc->syncRepState = SYNC_REP_MUST_DISCONNECT;
+ 
+ cleanup:
+ 	Assert(SHMQueueIsDetached(&(MyProc->syncRepLinks)));
+ 
+ 	MyProc->waitLSN.xlogid = 0;
+ 	MyProc->waitLSN.xrecoff = 0;
+ 
+ 	if (new_status)
+ 	{
+ 		/* Reset ps display */
+ 		set_ps_display(new_status, false);
+ 		pfree(new_status);
+ 	}
  }
  
  /*
*** a/src/backend/tcop/dest.c
--- b/src/backend/tcop/dest.c
***************
*** 36,41 ****
--- 36,45 ----
  #include "executor/tstoreReceiver.h"
  #include "libpq/libpq.h"
  #include "libpq/pqformat.h"
+ #include "miscadmin.h"
+ #include "replication/syncrep.h"
+ #include "storage/ipc.h"
+ #include "tcop/tcopprot.h"
  #include "utils/portal.h"
  
  
***************
*** 144,149 **** EndCommand(const char *commandTag, CommandDest dest)
--- 148,171 ----
  		case DestRemoteExecute:
  
  			/*
+ 			 * If we receive SIGTERM while we are waiting for synchronous
+ 			 * replication, we close the connection before returning the
+ 			 * "success" indication to the client. This prevents the client
+ 			 * from thinking that the transaction which might have not been
+ 			 * replicated yet has been committed and visible in the standby.
+ 			 */
+ 			if (MyProc->syncRepState == SYNC_REP_MUST_DISCONNECT)
+ 			{
+ 				/*
+ 				 * Reset whereToSendOutput to prevent ereport from
+ 				 * attempting to send any more messages to client.
+ 				 */
+ 				whereToSendOutput = DestNone;
+ 
+ 				proc_exit(0);
+ 			}
+ 
+ 			/*
  			 * We assume the commandTag is plain ASCII and therefore requires
  			 * no encoding conversion.
  			 */
*** a/src/backend/tcop/postgres.c
--- b/src/backend/tcop/postgres.c
***************
*** 2643,2648 **** die(SIGNAL_ARGS)
--- 2643,2651 ----
  			InterruptHoldoffCount--;
  			ProcessInterrupts();
  		}
+ 
+ 		/* Wake up myself waiting on the latch */
+ 		SetLatch(&(MyProc->waitLatch));
  	}
  
  	errno = save_errno;