On Fri, 26 Jul 2019 18:22:25 +0200 Jehan-Guillaume de Rorthais <j...@dalibo.com> wrote:
> On Fri, 26 Jul 2019 10:02:58 +0200 > Jehan-Guillaume de Rorthais <j...@dalibo.com> wrote: > > > On Fri, 26 Jul 2019 16:49:53 +0900 (Tokyo Standard Time) > > Kyotaro Horiguchi <horikyota....@gmail.com> wrote: > [...] > > > We have an LSN reporting function each for several objectives. > > > > > > pg_current_wal_lsn > > > pg_current_wal_insert_lsn > > > pg_current_wal_flush_lsn > > > pg_last_wal_receive_lsn > > > pg_last_wal_replay_lsn > > > > Yes. In fact, my current implementation might be split as: > > > > pg_current_wal_tl: returns TL on a production cluster > > pg_last_wal_received_tl: returns last received TL on a standby > > > > If useful, I could add pg_last_wal_replayed_tl. I don't think *insert_tl and > > *flush_tl would be useful as a cluster in production is not supposed to > > change its timeline during its lifetime. > > > > > But, I'm not sure just adding further pg_last_*_timeline() to > > > this list is a good thing.. > > > > I think this is a much better idea than mixing different case (production > > and standby) in the same function as I did. Moreover, it's much more > > coherent with other existing functions. > > Please, find in attachment a new version of the patch. It now creates two new > fonctions: > > pg_current_wal_tl() > pg_last_wal_received_tl() I just found I forgot to use PG_RETURN_INT32 in pg_last_wal_received_tl(). Please find the corrected patch in attachment: 0001-v3-Add-functions-to-get-timeline.patch Also, TimeLineID is declared as a uint32. So why do we use PG_RETURN_INT32/Int32GetDatum to return a timeline and not PG_RETURN_UINT32? See eg. in pg_stat_get_wal_receiver(). Regards,
>From 031d60de3e4239c83554c89c0c382c6390545434 Mon Sep 17 00:00:00 2001 From: Jehan-Guillaume de Rorthais <j...@dalibo.com> Date: Thu, 25 Jul 2019 19:36:40 +0200 Subject: [PATCH] Add functions to get timeline pg_current_wal_tl() returns the current timeline of a cluster in production. pg_last_wal_received_tl() returns the timeline of the last xlog record flushed to disk. --- src/backend/access/transam/xlog.c | 17 +++++++++++++++++ src/backend/access/transam/xlogfuncs.c | 20 ++++++++++++++++++++ src/backend/replication/walreceiver.c | 19 +++++++++++++++++++ src/include/access/xlog.h | 1 + src/include/catalog/pg_proc.dat | 12 ++++++++++++ 5 files changed, 69 insertions(+) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index da3d250986..fd30c88534 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -12243,3 +12243,20 @@ XLogRequestWalReceiverReply(void) { doRequestWalReceiverReply = true; } + +/* + * Returns current active timeline. + */ +TimeLineID +GetCurrentTimeLine(void) +{ + TimeLineID localTimeLineID; + + SpinLockAcquire(&XLogCtl->info_lck); + + localTimeLineID = XLogCtl->ThisTimeLineID; + + SpinLockRelease(&XLogCtl->info_lck); + + return localTimeLineID; +} diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c index b35043bf71..ae877be351 100644 --- a/src/backend/access/transam/xlogfuncs.c +++ b/src/backend/access/transam/xlogfuncs.c @@ -776,3 +776,23 @@ pg_promote(PG_FUNCTION_ARGS) (errmsg("server did not promote within %d seconds", wait_seconds))); PG_RETURN_BOOL(false); } + +/* + * Returns the current timeline on a production cluster + */ +Datum +pg_current_wal_tl(PG_FUNCTION_ARGS) +{ + TimeLineID currentTL; + + if (RecoveryInProgress()) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("recovery is in progress"), + errhint("%s cannot be executed during recovery.", + "pg_current_wal_tl()"))); + + currentTL = GetCurrentTimeLine(); + + PG_RETURN_INT32(currentTL); +} diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index 6abc780778..9bffd822ff 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -1454,3 +1454,22 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS) /* Returns the record as Datum */ PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); } + +/* + * Returns the timeline of the last xlog record flushed to WAL + */ +Datum +pg_last_wal_received_tl(PG_FUNCTION_ARGS) +{ + TimeLineID lastReceivedTL; + WalRcvData *walrcv = WalRcv; + + SpinLockAcquire(&walrcv->mutex); + lastReceivedTL = walrcv->receivedTLI; + SpinLockRelease(&walrcv->mutex); + + if (!lastReceivedTL) + PG_RETURN_NULL(); + + PG_RETURN_INT32(lastReceivedTL); +} diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index d519252aad..f0502c0b41 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -313,6 +313,7 @@ extern XLogRecPtr GetInsertRecPtr(void); extern XLogRecPtr GetFlushRecPtr(void); extern XLogRecPtr GetLastImportantRecPtr(void); extern void RemovePromoteSignalFiles(void); +extern TimeLineID GetCurrentTimeLine(void); extern bool CheckPromoteSignal(void); extern void WakeupRecovery(void); diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 0902dce5f1..d7ec6ea100 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -6006,6 +6006,18 @@ { oid => '2851', descr => 'wal filename, given a wal location', proname => 'pg_walfile_name', prorettype => 'text', proargtypes => 'pg_lsn', prosrc => 'pg_walfile_name' }, +{ oid => '3434', + descr => 'current timeline', + proname => 'pg_current_wal_tl', prorettype => 'int4', + proargtypes => '', proallargtypes => '{int4}', + proargmodes => '{o}', proargnames => '{timeline}', + prosrc => 'pg_current_wal_tl' }, +{ oid => '3435', + descr => 'current wal flush timeline', + proname => 'pg_last_wal_received_tl', prorettype => 'int4', + proargtypes => '', proallargtypes => '{int4}', + proargmodes => '{o}', proargnames => '{timeline}', + prosrc => 'pg_last_wal_received_tl' }, { oid => '3165', descr => 'difference in bytes, given two wal locations', proname => 'pg_wal_lsn_diff', prorettype => 'numeric', -- 2.20.1