diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 5880054245..b1bcb477c6 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -49,6 +49,7 @@ #include "storage/proc.h" #include "storage/smgr.h" #include "storage/standby.h" +#include "utils/ps_status.h" #include "utils/rel.h" #include "utils/resowner_private.h" #include "utils/timestamp.h" @@ -3669,6 +3670,8 @@ void LockBufferForCleanup(Buffer buffer) { BufferDesc *bufHdr; + TimestampTz waitStart = 0; + char *new_status = NULL; Assert(BufferIsValid(buffer)); Assert(PinCountWaitBuf == NULL); @@ -3690,6 +3693,9 @@ LockBufferForCleanup(Buffer buffer) bufHdr = GetBufferDescriptor(buffer - 1); + if (update_process_title) + waitStart = GetCurrentTimestamp(); + for (;;) { uint32 buf_state; @@ -3703,6 +3709,13 @@ LockBufferForCleanup(Buffer buffer) { /* Successfully acquired exclusive lock with pincount 1 */ UnlockBufHdr(bufHdr, buf_state); + + /* Reset ps display if we changed it */ + if (new_status) + { + set_ps_display(new_status); + pfree(new_status); + } return; } /* Failed, so mark myself as waiting for pincount 1 */ @@ -3718,6 +3731,22 @@ LockBufferForCleanup(Buffer buffer) UnlockBufHdr(bufHdr, buf_state); LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + /* Report via ps if we have been waiting for more than 500 msec */ + if (update_process_title && new_status == NULL && + TimestampDifferenceExceeds(waitStart, GetCurrentTimestamp(), + 500)) + { + const char *old_status; + int len; + + old_status = get_ps_display(&len); + new_status = (char *) palloc(len + 8 + 1); + memcpy(new_status, old_status, len); + strcpy(new_status + len, " waiting"); + set_ps_display(new_status); + new_status[len] = '\0'; /* truncate off " waiting" */ + } + /* Wait to be signaled by UnpinBuffer() */ if (InHotStandby) { diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c index 08f695a980..24fc6de521 100644 --- a/src/backend/storage/ipc/standby.c +++ b/src/backend/storage/ipc/standby.c @@ -47,6 +47,7 @@ static void ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlis static void SendRecoveryConflictWithBufferPin(ProcSignalReason reason); static XLogRecPtr LogCurrentRunningXacts(RunningTransactions CurrRunningXacts); static void LogAccessExclusiveLocks(int nlocks, xl_standby_lock *locks); +static char *update_process_title_waiting(TimestampTz waitStart); /* * Keep track of all the locks owned by a given transaction. @@ -244,24 +245,9 @@ ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist, /* wait until the virtual xid is gone */ while (!VirtualXactLock(*waitlist, false)) { - /* - * Report via ps if we have been waiting for more than 500 msec - * (should that be configurable?) - */ - if (update_process_title && new_status == NULL && report_waiting && - TimestampDifferenceExceeds(waitStart, GetCurrentTimestamp(), - 500)) - { - const char *old_status; - int len; - - old_status = get_ps_display(&len); - new_status = (char *) palloc(len + 8 + 1); - memcpy(new_status, old_status, len); - strcpy(new_status + len, " waiting"); - set_ps_display(new_status); - new_status[len] = '\0'; /* truncate off " waiting" */ - } + /* Report via ps we are waiting */ + if (update_process_title && new_status == NULL && report_waiting) + new_status = update_process_title_waiting(waitStart); /* Is it time to kill it? */ if (WaitExceedsMaxStandbyDelay()) @@ -352,6 +338,12 @@ ResolveRecoveryConflictWithTablespace(Oid tsid) void ResolveRecoveryConflictWithDatabase(Oid dbid) { + char *new_status = NULL; + TimestampTz waitStart = 0; + + if (update_process_title) + waitStart = GetCurrentTimestamp(); + /* * We don't do ResolveRecoveryConflictWithVirtualXIDs() here since that * only waits for transactions and completely idle sessions would block @@ -365,6 +357,10 @@ ResolveRecoveryConflictWithDatabase(Oid dbid) */ while (CountDBBackends(dbid) > 0) { + /* Report via ps we are waiting */ + if (update_process_title && new_status == NULL) + new_status = update_process_title_waiting(waitStart); + CancelDBBackends(dbid, PROCSIG_RECOVERY_CONFLICT_DATABASE, true); /* @@ -373,6 +369,13 @@ ResolveRecoveryConflictWithDatabase(Oid dbid) */ pg_usleep(10000); } + + /* Reset ps display if we changed it */ + if (new_status) + { + set_ps_display(new_status); + pfree(new_status); + } } /* @@ -1108,3 +1111,33 @@ LogStandbyInvalidations(int nmsgs, SharedInvalidationMessage *msgs, nmsgs * sizeof(SharedInvalidationMessage)); XLogInsert(RM_STANDBY_ID, XLOG_INVALIDATIONS); } + +/* + * Append " waiting" to the process title if we have been waiting for + * more than 500 msec since waitStart, and return palloc'd original + * process title. (should that be configurable?) + */ +static char * +update_process_title_waiting(TimestampTz waitStart) +{ + char *new_status = NULL; + + if (!update_process_title) + return NULL; + + if (TimestampDifferenceExceeds(waitStart, GetCurrentTimestamp(), + 500)) + { + const char *old_status; + int len; + + old_status = get_ps_display(&len); + new_status = (char *) palloc(len + 8 + 1); + memcpy(new_status, old_status, len); + strcpy(new_status + len, " waiting"); + set_ps_display(new_status); + new_status[len] = '\0'; /* truncate off " waiting" */ + } + + return new_status; +}