On Tue, Jan 11, 2011 at 02:24, Robert Haas <[email protected]> wrote:
> On Mon, Jan 10, 2011 at 10:41 AM, Simon Riggs <[email protected]> wrote:
>>> >>> I think we need a status enum. ('BACKUP', 'CATCHUP', 'STREAM') for the 3
>>> >>> phases of replication.
>>> >>
>>> >> That seems reasonable. But if we keep BACKUP in there, should we
>>> >> really have it called pg_stat_replication? (yeah, I know, I'm not
>>> >> giving up :P)
>>> >>
>>> >> (You'd need a 4th mode for WAITING or so, to indicate it's waiting for
>>> >> a command)
>>> >
>>> > That's something different.
>>> >
>>> > The 3 phases are more concrete.
>>> >
>>> > BACKUP --> CATCHUP<---> STREAM
>>> >
>>> > When you connect you either do BACKUP or CATCHUP. Once in CATCHUP mode
>>> > you never issue a BACKUP. Once we have caught up we move to STREAM. That
>>> > has nothing to do with idle/active.
>>>
>>> So how does a walsender that's waiting for a command from the client
>>> show up? Surely it's not in "catchup" mode yet?
>>
>> There is a trivial state between connect and first command. If you think
>> that is worth publishing, feel free. STARTING?
>
> I think it's worth publishing. STARTING would be OK, or maybe STARTUP
> to parallel the other two -UP states.
Here's a patch for this. I chose IDLE, because that's what we call
other backends that are waiting for commands...
Does this seem correct?
--
Magnus Hagander
Me: http://www.hagander.net/
Work: http://www.redpill-linpro.com/
*** a/doc/src/sgml/monitoring.sgml
--- b/doc/src/sgml/monitoring.sgml
***************
*** 298,305 **** postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
<entry><structname>pg_stat_replication</><indexterm><primary>pg_stat_replication</primary></indexterm></entry>
<entry>One row per WAL sender process, showing process <acronym>ID</>,
user OID, user name, application name, client's address and port number,
! time at which the server process began execution, and transaction log
! location.
</entry>
</row>
--- 298,305 ----
<entry><structname>pg_stat_replication</><indexterm><primary>pg_stat_replication</primary></indexterm></entry>
<entry>One row per WAL sender process, showing process <acronym>ID</>,
user OID, user name, application name, client's address and port number,
! time at which the server process began execution, current WAL sender
! state and transaction log location.
</entry>
</row>
*** a/src/backend/catalog/system_views.sql
--- b/src/backend/catalog/system_views.sql
***************
*** 501,506 **** CREATE VIEW pg_stat_replication AS
--- 501,507 ----
S.client_addr,
S.client_port,
S.backend_start,
+ W.state,
W.sent_location
FROM pg_stat_get_activity(NULL) AS S, pg_authid U,
pg_stat_get_wal_senders() AS W
*** a/src/backend/replication/basebackup.c
--- b/src/backend/replication/basebackup.c
***************
*** 24,29 ****
--- 24,30 ----
#include "libpq/pqformat.h"
#include "nodes/pg_list.h"
#include "replication/basebackup.h"
+ #include "replication/walsender.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "utils/builtins.h"
***************
*** 83,88 **** SendBaseBackup(const char *options)
--- 84,91 ----
ALLOCSET_DEFAULT_MAXSIZE);
old_context = MemoryContextSwitchTo(backup_context);
+ WalSndSetState(WalSndState_BACKUP);
+
if (backup_label == NULL)
ereport(FATAL,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
*** a/src/backend/replication/walsender.c
--- b/src/backend/replication/walsender.c
***************
*** 179,184 **** WalSndHandshake(void)
--- 179,185 ----
{
int firstchar;
+ WalSndSetState(WalSndState_IDLE);
set_ps_display("idle", false);
/* Wait for a command to arrive */
***************
*** 482,487 **** WalSndLoop(void)
--- 483,491 ----
if (!XLogSend(output_message, &caughtup))
break;
}
+
+ /* Update our state to indicate if we're behind or not */
+ WalSndSetState(caughtup ? WalSndState_STREAMING : WalSndState_CATCHUP);
}
/*
***************
*** 533,538 **** InitWalSnd(void)
--- 537,543 ----
*/
walsnd->pid = MyProcPid;
MemSet(&walsnd->sentPtr, 0, sizeof(XLogRecPtr));
+ walsnd->state = WalSndState_IDLE;
SpinLockRelease(&walsnd->mutex);
/* don't need the lock anymore */
OwnLatch((Latch *) &walsnd->latch);
***************
*** 960,965 **** WalSndWakeup(void)
--- 965,999 ----
SetLatch(&WalSndCtl->walsnds[i].latch);
}
+ /* Set state for current walsender (only called in walsender) */
+ void WalSndSetState(WalSndState state)
+ {
+ /* use volatile pointer to prevent code rearrangement */
+ volatile WalSnd *walsnd = MyWalSnd;
+
+ SpinLockAcquire(&walsnd->mutex);
+ walsnd->state = state;
+ SpinLockRelease(&walsnd->mutex);
+ }
+
+ /*
+ * Return a string constant representing the state. This is used
+ * in system views, and should *not* be translated.
+ */
+ static const char *
+ WalSndGetStateString(WalSndState state)
+ {
+ switch (state)
+ {
+ case WalSndState_IDLE: return "IDLE";
+ case WalSndState_BACKUP: return "BACKUP";
+ case WalSndState_CATCHUP: return "CATCHUP";
+ case WalSndState_STREAMING: return "STREAMING";
+ }
+ return "UNKNOWN";
+ }
+
+
/*
* Returns activity of walsenders, including pids and xlog locations sent to
* standby servers.
***************
*** 967,973 **** WalSndWakeup(void)
Datum
pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
{
! #define PG_STAT_GET_WAL_SENDERS_COLS 2
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
TupleDesc tupdesc;
Tuplestorestate *tupstore;
--- 1001,1007 ----
Datum
pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
{
! #define PG_STAT_GET_WAL_SENDERS_COLS 3
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
TupleDesc tupdesc;
Tuplestorestate *tupstore;
***************
*** 1021,1027 **** pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
memset(nulls, 0, sizeof(nulls));
values[0] = Int32GetDatum(walsnd->pid);
! values[1] = CStringGetTextDatum(sent_location);
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
}
--- 1055,1062 ----
memset(nulls, 0, sizeof(nulls));
values[0] = Int32GetDatum(walsnd->pid);
! values[1] = CStringGetTextDatum(WalSndGetStateString(walsnd->state));
! values[2] = CStringGetTextDatum(sent_location);
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
}
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 3075,3081 **** DATA(insert OID = 1936 ( pg_stat_get_backend_idset PGNSP PGUID 12 1 100 0 f f
DESCR("statistics: currently active backend IDs");
DATA(insert OID = 2022 ( pg_stat_get_activity PGNSP PGUID 12 1 100 0 f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,16,1184,1184,1184,869,23}" "{i,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,procpid,usesysid,application_name,current_query,waiting,xact_start,query_start,backend_start,client_addr,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ ));
DESCR("statistics: information about currently active backends");
! DATA(insert OID = 3099 ( pg_stat_get_wal_senders PGNSP PGUID 12 1 10 0 f f f f t s 0 0 2249 "" "{23,25}" "{o,o}" "{procpid,sent_location}" _null_ pg_stat_get_wal_senders _null_ _null_ _null_ ));
DESCR("statistics: information about currently active replication");
DATA(insert OID = 2026 ( pg_backend_pid PGNSP PGUID 12 1 0 0 f f f t f s 0 0 23 "" _null_ _null_ _null_ _null_ pg_backend_pid _null_ _null_ _null_ ));
DESCR("statistics: current backend PID");
--- 3075,3081 ----
DESCR("statistics: currently active backend IDs");
DATA(insert OID = 2022 ( pg_stat_get_activity PGNSP PGUID 12 1 100 0 f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,16,1184,1184,1184,869,23}" "{i,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,procpid,usesysid,application_name,current_query,waiting,xact_start,query_start,backend_start,client_addr,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ ));
DESCR("statistics: information about currently active backends");
! DATA(insert OID = 3099 ( pg_stat_get_wal_senders PGNSP PGUID 12 1 10 0 f f f f t s 0 0 2249 "" "{23,25,25}" "{o,o,o}" "{procpid,state,sent_location}" _null_ pg_stat_get_wal_senders _null_ _null_ _null_ ));
DESCR("statistics: information about currently active replication");
DATA(insert OID = 2026 ( pg_backend_pid PGNSP PGUID 12 1 0 0 f f f t f s 0 0 23 "" _null_ _null_ _null_ _null_ pg_backend_pid _null_ _null_ _null_ ));
DESCR("statistics: current backend PID");
*** a/src/include/replication/walsender.h
--- b/src/include/replication/walsender.h
***************
*** 16,27 ****
--- 16,36 ----
#include "storage/latch.h"
#include "storage/spin.h"
+
+ typedef enum WalSndState {
+ WalSndState_IDLE = 0,
+ WalSndState_BACKUP,
+ WalSndState_CATCHUP,
+ WalSndState_STREAMING
+ } WalSndState;
+
/*
* Each walsender has a WalSnd struct in shared memory.
*/
typedef struct WalSnd
{
pid_t pid; /* this walsender's process id, or 0 */
+ WalSndState state; /* this walsender's state */
XLogRecPtr sentPtr; /* WAL has been sent up to this point */
slock_t mutex; /* locks shared variables shown above */
***************
*** 53,58 **** extern void WalSndSignals(void);
--- 62,68 ----
extern Size WalSndShmemSize(void);
extern void WalSndShmemInit(void);
extern void WalSndWakeup(void);
+ extern void WalSndSetState(WalSndState state);
extern Datum pg_stat_get_wal_senders(PG_FUNCTION_ARGS);
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers