void
SyncRepWaitForLSN(XLogRecPtr lsn, bool commit)
{
- char *new_status = NULL;
- const char *old_status;
int mode;
/*
/* Alter ps display to show waiting for sync rep. */
if (update_process_title)
{
- int len;
-
- old_status = get_ps_display(&len);
- new_status = (char *) palloc(len + 32 + 1);
- memcpy(new_status, old_status, len);
- sprintf(new_status + len, " waiting for %X/%X",
- LSN_FORMAT_ARGS(lsn));
- set_ps_display(new_status);
- new_status[len] = '\0'; /* truncate off " waiting ..." */
+ char buffer[32];
+
+ sprintf(buffer, "waiting for %X/%X", LSN_FORMAT_ARGS(lsn));
+ set_ps_display_suffix(buffer);
}
/*
MyProc->syncRepState = SYNC_REP_NOT_WAITING;
MyProc->waitLSN = 0;
- if (new_status)
- {
- /* Reset ps display */
- set_ps_display(new_status);
- pfree(new_status);
- }
+ /* reset ps display to remove the suffix */
+ if (update_process_title)
+ set_ps_display_remove_suffix();
}
/*
LockBufferForCleanup(Buffer buffer)
{
BufferDesc *bufHdr;
- char *new_status = NULL;
TimestampTz waitStart = 0;
+ bool waiting = false;
bool logged_recovery_conflict = false;
Assert(BufferIsPinned(buffer));
waitStart, GetCurrentTimestamp(),
NULL, false);
- /* Report change to non-waiting status */
- if (new_status)
+ if (waiting)
{
- set_ps_display(new_status);
- pfree(new_status);
+ /* reset ps display to remove the suffix if we added one */
+ set_ps_display_remove_suffix();
+ waiting = false;
}
return;
}
/* Wait to be signaled by UnpinBuffer() */
if (InHotStandby)
{
- /* Report change to waiting status */
- if (update_process_title && new_status == NULL)
+ if (!waiting)
{
- 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" */
+ /* adjust the process title to indicate that it's waiting */
+ set_ps_display_suffix("waiting");
+ waiting = true;
}
/*
bool report_waiting)
{
TimestampTz waitStart = 0;
- char *new_status = NULL;
+ bool waiting = false;
bool logged_recovery_conflict = false;
/* Fast exit, to avoid a kernel call if there's no work to be done. */
pg_usleep(5000L);
}
- if (waitStart != 0 && (!logged_recovery_conflict || new_status == NULL))
+ if (waitStart != 0 && (!logged_recovery_conflict || !waiting))
{
TimestampTz now = 0;
bool maybe_log_conflict;
bool maybe_update_title;
maybe_log_conflict = (log_recovery_conflict_waits && !logged_recovery_conflict);
- maybe_update_title = (update_process_title && new_status == NULL);
+ maybe_update_title = (update_process_title && !waiting);
/* Get the current timestamp if not report yet */
if (maybe_log_conflict || maybe_update_title)
if (maybe_update_title &&
TimestampDifferenceExceeds(waitStart, now, 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" */
+ set_ps_display_suffix("waiting");
+ waiting = true;
}
/*
LogRecoveryConflict(reason, waitStart, GetCurrentTimestamp(),
NULL, false);
- /* Reset ps display if we changed it */
- if (new_status)
- {
- set_ps_display(new_status);
- pfree(new_status);
- }
+ /* reset ps display to remove the suffix if we added one */
+ if (waiting)
+ set_ps_display_remove_suffix();
+
}
/*
{
LOCKMETHODID lockmethodid = LOCALLOCK_LOCKMETHOD(*locallock);
LockMethod lockMethodTable = LockMethods[lockmethodid];
- char *volatile new_status = NULL;
LOCK_PRINT("WaitOnLock: sleeping on lock",
locallock->lock, locallock->tag.mode);
- /* Report change to waiting status */
- if (update_process_title)
- {
- 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" */
- }
+ /* adjust the process title to indicate that it's waiting */
+ set_ps_display_suffix("waiting");
awaitedLock = locallock;
awaitedOwner = owner;
{
/* In this path, awaitedLock remains set until LockErrorCleanup */
- /* Report change to non-waiting status */
- if (update_process_title)
- {
- set_ps_display(new_status);
- pfree(new_status);
- }
+ /* reset ps display to remove the suffix */
+ set_ps_display_remove_suffix();
/* and propagate the error */
PG_RE_THROW();
awaitedLock = NULL;
- /* Report change to non-waiting status */
- if (update_process_title)
- {
- set_ps_display(new_status);
- pfree(new_status);
- }
+ /* reset ps display to remove the suffix */
+ set_ps_display_remove_suffix();
LOCK_PRINT("WaitOnLock: wakeup on lock",
locallock->lock, locallock->tag.mode);
Portal portal;
DestReceiver *receiver;
int16 format;
+ const char *cmdtagname;
+ size_t cmdtaglen;
pgstat_report_query_id(0, true);
* destination.
*/
commandTag = CreateCommandTag(parsetree->stmt);
+ cmdtagname = GetCommandTagNameAndLen(commandTag, &cmdtaglen);
- set_ps_display(GetCommandTagName(commandTag));
+ set_ps_display_with_len(cmdtagname, cmdtaglen);
BeginCommand(commandTag, dest);
char msec_str[32];
ParamsErrorCbData params_data;
ErrorContextCallback params_errcxt;
+ const char *cmdtagname;
+ size_t cmdtaglen;
/* Adjust destination to tell printtup.c what to do */
dest = whereToSendOutput;
pgstat_report_activity(STATE_RUNNING, sourceText);
- set_ps_display(GetCommandTagName(portal->commandTag));
+ cmdtagname = GetCommandTagNameAndLen(portal->commandTag, &cmdtaglen);
+
+ set_ps_display_with_len(cmdtagname, cmdtaglen);
if (save_log_statement_stats)
ResetUsage();
static size_t ps_buffer_fixed_size; /* size of the constant prefix */
+/*
+ * Length of ps_buffer before the suffix was appeneded to the end, or 0 if we
+ * didn't set a suffix.
+ */
+static size_t ps_buffer_nosuffix_len;
+
+static void flush_ps_display(void);
+
#endif /* not PS_USE_NONE */
/* save the original argv[] location here */
#endif /* not PS_USE_NONE */
}
-
-
+#ifndef PS_USE_NONE
/*
- * Call this to update the ps status display to a fixed prefix plus an
- * indication of what you're currently doing passed in the argument.
+ * update_ps_display_precheck
+ * Helper function to determine if updating the process title is
+ * something that we need to do.
*/
-void
-set_ps_display(const char *activity)
+static bool
+update_ps_display_precheck(void)
{
-#ifndef PS_USE_NONE
/* update_process_title=off disables updates */
if (!update_process_title)
- return;
+ return false;
/* no ps display for stand-alone backend */
if (!IsUnderPostmaster)
- return;
+ return false;
#ifdef PS_USE_CLOBBER_ARGV
/* If ps_buffer is a pointer, it might still be null */
if (!ps_buffer)
- return;
+ return false;
#endif
+ return true;
+}
+#endif /* not PS_USE_NONE */
+
+/*
+ * set_ps_display_suffix
+ * Adjust the process title to append 'suffix' onto the end with a space
+ * between it and the current process title.
+ */
+void
+set_ps_display_suffix(const char *suffix)
+{
+#ifndef PS_USE_NONE
+ size_t len;
+
+ /* first, check if we need to update the process title */
+ if (!update_ps_display_precheck())
+ return;
+
+ /* if there's already a suffix, overwrite it */
+ if (ps_buffer_nosuffix_len > 0)
+ ps_buffer_cur_len = ps_buffer_nosuffix_len;
+ else
+ ps_buffer_nosuffix_len = ps_buffer_cur_len;
+
+ len = strlen(suffix);
+
+ /* check if we have enough space to append the suffix */
+ if (ps_buffer_cur_len + len + 1 >= ps_buffer_size)
+ {
+ /* not enough space. Check the buffer isn't full already */
+ if (ps_buffer_cur_len < ps_buffer_size - 1)
+ {
+ /* append a space before the suffix */
+ ps_buffer[ps_buffer_cur_len++] = ' ';
+
+ /* just add what we can and fill the ps_buffer */
+ memcpy(ps_buffer + ps_buffer_cur_len, suffix,
+ ps_buffer_size - ps_buffer_cur_len - 1);
+ ps_buffer[ps_buffer_size - 1] = '\0';
+ ps_buffer_cur_len = ps_buffer_size - 1;
+ }
+ }
+ else
+ {
+ ps_buffer[ps_buffer_cur_len++] = ' ';
+ memcpy(ps_buffer + ps_buffer_cur_len, suffix, len + 1);
+ ps_buffer_cur_len = ps_buffer_cur_len + len;
+ }
+
+ Assert(strlen(ps_buffer) == ps_buffer_cur_len);
+
+ /* and set the new title */
+ flush_ps_display();
+#endif /* not PS_USE_NONE */
+}
+
+/*
+ * set_ps_display_remove_suffix
+ * Remove the process display suffix added by set_ps_display_suffix
+ */
+void
+set_ps_display_remove_suffix(void)
+{
+#ifndef PS_USE_NONE
+ /* first, check if we need to update the process title */
+ if (!update_ps_display_precheck())
+ return;
+
+ /* check we added a suffix */
+ if (ps_buffer_nosuffix_len == 0)
+ return; /* no suffix */
+
+ /* remove the suffix from ps_buffer */
+ ps_buffer[ps_buffer_nosuffix_len] = '\0';
+ ps_buffer_cur_len = ps_buffer_nosuffix_len;
+ ps_buffer_nosuffix_len = 0;
+
+ Assert(ps_buffer_cur_len == strlen(ps_buffer));
+
+ /* and set the new title */
+ flush_ps_display();
+#endif /* not PS_USE_NONE */
+}
+
+/*
+ * Call this to update the ps status display to a fixed prefix plus an
+ * indication of what you're currently doing passed in the argument.
+ *
+ * 'len' must be the same as strlen(activity)
+ */
+void
+set_ps_display_with_len(const char *activity, size_t len)
+{
+ Assert(strlen(activity) == len);
+
+#ifndef PS_USE_NONE
+ /* first, check if we need to update the process title */
+ if (!update_ps_display_precheck())
+ return;
+
+ /* wipe out any suffix when the title is completely changed */
+ ps_buffer_nosuffix_len = 0;
+
/* Update ps_buffer to contain both fixed part and activity */
- strlcpy(ps_buffer + ps_buffer_fixed_size, activity,
- ps_buffer_size - ps_buffer_fixed_size);
- ps_buffer_cur_len = strlen(ps_buffer);
+ if (ps_buffer_fixed_size + len >= ps_buffer_size)
+ {
+ /* handle the case where ps_buffer doesn't have enough space */
+ memcpy(ps_buffer + ps_buffer_fixed_size, activity,
+ ps_buffer_size - ps_buffer_fixed_size - 1);
+ ps_buffer[ps_buffer_size - 1] = '\0';
+ ps_buffer_cur_len = ps_buffer_size - 1;
+ }
+ else
+ {
+ memcpy(ps_buffer + ps_buffer_fixed_size, activity, len + 1);
+ ps_buffer_cur_len = ps_buffer_fixed_size + len;
+ }
+ Assert(strlen(ps_buffer) == ps_buffer_cur_len);
/* Transmit new setting to kernel, if necessary */
+ flush_ps_display();
+#endif /* not PS_USE_NONE */
+}
+#ifndef PS_USE_NONE
+static void
+flush_ps_display(void)
+{
#ifdef PS_USE_SETPROCTITLE
setproctitle("%s", ps_buffer);
#elif defined(PS_USE_SETPROCTITLE_FAST)
ident_handle = CreateEvent(NULL, TRUE, FALSE, name);
}
#endif /* PS_USE_WIN32 */
-#endif /* not PS_USE_NONE */
}
-
+#endif /* not PS_USE_NONE */
/*
* Returns what's currently in the ps display, in case someone needs
extern void init_ps_display(const char *fixed_part);
-extern void set_ps_display(const char *activity);
+extern void set_ps_display_suffix(const char *suffix);
+
+extern void set_ps_display_remove_suffix(void);
+
+extern void set_ps_display_with_len(const char *activity, size_t len);
+
+/*
+ * set_ps_display
+ * inlined to allow strlen to be evaluated during compilation when
+ * passing string constants.
+ */
+static inline void
+set_ps_display(const char *activity)
+{
+ set_ps_display_with_len(activity, strlen(activity));
+}
extern const char *get_ps_display(int *displen);