mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-09 17:19:20 +02:00
This is primarily useful for the upcoming pg_xlogdump --stats feature, but also allows to remove some duplicated code in the rmgr_desc routines. Due to the separation and harmonization, the output of dipsplayed records changes somewhat. But since this isn't enduser oriented content that's ok. It's potentially desirable to further change pg_xlogdump's display of records. It previously wasn't possible to show the record type separately from the description forcing it to be in the last column. But that's better done in a separate commit. Author: Abhijit Menon-Sen, slightly editorialized by me Reviewed-By: Álvaro Herrera, Andres Freund, and Heikki Linnakangas Discussion: 20140604104716.GA3989@toroid.org
181 lines
4.4 KiB
C
181 lines
4.4 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* xlogdesc.c
|
|
* rmgr descriptor routines for access/transam/xlog.c
|
|
*
|
|
* Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* src/backend/access/rmgrdesc/xlogdesc.c
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#include "postgres.h"
|
|
|
|
#include "access/xlog.h"
|
|
#include "access/xlog_internal.h"
|
|
#include "catalog/pg_control.h"
|
|
#include "utils/guc.h"
|
|
#include "utils/timestamp.h"
|
|
|
|
/*
|
|
* GUC support
|
|
*/
|
|
const struct config_enum_entry wal_level_options[] = {
|
|
{"minimal", WAL_LEVEL_MINIMAL, false},
|
|
{"archive", WAL_LEVEL_ARCHIVE, false},
|
|
{"hot_standby", WAL_LEVEL_HOT_STANDBY, false},
|
|
{"logical", WAL_LEVEL_LOGICAL, false},
|
|
{NULL, 0, false}
|
|
};
|
|
|
|
void
|
|
xlog_desc(StringInfo buf, XLogRecord *record)
|
|
{
|
|
char *rec = XLogRecGetData(record);
|
|
uint8 info = record->xl_info & ~XLR_INFO_MASK;
|
|
|
|
if (info == XLOG_CHECKPOINT_SHUTDOWN ||
|
|
info == XLOG_CHECKPOINT_ONLINE)
|
|
{
|
|
CheckPoint *checkpoint = (CheckPoint *) rec;
|
|
|
|
appendStringInfo(buf, "redo %X/%X; "
|
|
"tli %u; prev tli %u; fpw %s; xid %u/%u; oid %u; multi %u; offset %u; "
|
|
"oldest xid %u in DB %u; oldest multi %u in DB %u; "
|
|
"oldest running xid %u; %s",
|
|
(uint32) (checkpoint->redo >> 32), (uint32) checkpoint->redo,
|
|
checkpoint->ThisTimeLineID,
|
|
checkpoint->PrevTimeLineID,
|
|
checkpoint->fullPageWrites ? "true" : "false",
|
|
checkpoint->nextXidEpoch, checkpoint->nextXid,
|
|
checkpoint->nextOid,
|
|
checkpoint->nextMulti,
|
|
checkpoint->nextMultiOffset,
|
|
checkpoint->oldestXid,
|
|
checkpoint->oldestXidDB,
|
|
checkpoint->oldestMulti,
|
|
checkpoint->oldestMultiDB,
|
|
checkpoint->oldestActiveXid,
|
|
(info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
|
|
}
|
|
else if (info == XLOG_NEXTOID)
|
|
{
|
|
Oid nextOid;
|
|
|
|
memcpy(&nextOid, rec, sizeof(Oid));
|
|
appendStringInfo(buf, "%u", nextOid);
|
|
}
|
|
else if (info == XLOG_RESTORE_POINT)
|
|
{
|
|
xl_restore_point *xlrec = (xl_restore_point *) rec;
|
|
|
|
appendStringInfo(buf, "%s", xlrec->rp_name);
|
|
}
|
|
else if (info == XLOG_FPI)
|
|
{
|
|
BkpBlock *bkp = (BkpBlock *) rec;
|
|
|
|
appendStringInfo(buf, "%s block %u",
|
|
relpathperm(bkp->node, bkp->fork),
|
|
bkp->block);
|
|
}
|
|
else if (info == XLOG_BACKUP_END)
|
|
{
|
|
XLogRecPtr startpoint;
|
|
|
|
memcpy(&startpoint, rec, sizeof(XLogRecPtr));
|
|
appendStringInfo(buf, "%X/%X",
|
|
(uint32) (startpoint >> 32), (uint32) startpoint);
|
|
}
|
|
else if (info == XLOG_PARAMETER_CHANGE)
|
|
{
|
|
xl_parameter_change xlrec;
|
|
const char *wal_level_str;
|
|
const struct config_enum_entry *entry;
|
|
|
|
memcpy(&xlrec, rec, sizeof(xl_parameter_change));
|
|
|
|
/* Find a string representation for wal_level */
|
|
wal_level_str = "?";
|
|
for (entry = wal_level_options; entry->name; entry++)
|
|
{
|
|
if (entry->val == xlrec.wal_level)
|
|
{
|
|
wal_level_str = entry->name;
|
|
break;
|
|
}
|
|
}
|
|
|
|
appendStringInfo(buf, "max_connections=%d max_worker_processes=%d max_prepared_xacts=%d max_locks_per_xact=%d wal_level=%s",
|
|
xlrec.MaxConnections,
|
|
xlrec.max_worker_processes,
|
|
xlrec.max_prepared_xacts,
|
|
xlrec.max_locks_per_xact,
|
|
wal_level_str);
|
|
}
|
|
else if (info == XLOG_FPW_CHANGE)
|
|
{
|
|
bool fpw;
|
|
|
|
memcpy(&fpw, rec, sizeof(bool));
|
|
appendStringInfo(buf, "%s", fpw ? "true" : "false");
|
|
}
|
|
else if (info == XLOG_END_OF_RECOVERY)
|
|
{
|
|
xl_end_of_recovery xlrec;
|
|
|
|
memcpy(&xlrec, rec, sizeof(xl_end_of_recovery));
|
|
appendStringInfo(buf, "tli %u; prev tli %u; time %s",
|
|
xlrec.ThisTimeLineID, xlrec.PrevTimeLineID,
|
|
timestamptz_to_str(xlrec.end_time));
|
|
}
|
|
}
|
|
|
|
const char *
|
|
xlog_identify(uint8 info)
|
|
{
|
|
const char *id = NULL;
|
|
|
|
switch (info)
|
|
{
|
|
case XLOG_CHECKPOINT_SHUTDOWN:
|
|
id = "CHECKPOINT_SHUTDOWN";
|
|
break;
|
|
case XLOG_CHECKPOINT_ONLINE:
|
|
id = "CHECKPOINT_ONLINE";
|
|
break;
|
|
case XLOG_NOOP:
|
|
id = "NOOP";
|
|
break;
|
|
case XLOG_NEXTOID:
|
|
id = "NEXTOID";
|
|
break;
|
|
case XLOG_SWITCH:
|
|
id = "SWITCH";
|
|
break;
|
|
case XLOG_BACKUP_END:
|
|
id = "BACKUP_END";
|
|
break;
|
|
case XLOG_PARAMETER_CHANGE:
|
|
id = "PARAMETER_CHANGE";
|
|
break;
|
|
case XLOG_RESTORE_POINT:
|
|
id = "RESTORE_POINT";
|
|
break;
|
|
case XLOG_FPW_CHANGE:
|
|
id = "FPW_CHANGE";
|
|
break;
|
|
case XLOG_END_OF_RECOVERY:
|
|
id = "END_OF_RECOVERY";
|
|
break;
|
|
case XLOG_FPI:
|
|
id = "FPI";
|
|
break;
|
|
}
|
|
|
|
return id;
|
|
}
|