00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "access/xlog.h"
00018 #include "access/xlog_internal.h"
00019 #include "catalog/pg_control.h"
00020 #include "common/relpath.h"
00021 #include "utils/guc.h"
00022 #include "utils/timestamp.h"
00023
00024
00025
00026
00027 const struct config_enum_entry wal_level_options[] = {
00028 {"minimal", WAL_LEVEL_MINIMAL, false},
00029 {"archive", WAL_LEVEL_ARCHIVE, false},
00030 {"hot_standby", WAL_LEVEL_HOT_STANDBY, false},
00031 {NULL, 0, false}
00032 };
00033
00034 void
00035 xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
00036 {
00037 uint8 info = xl_info & ~XLR_INFO_MASK;
00038
00039 if (info == XLOG_CHECKPOINT_SHUTDOWN ||
00040 info == XLOG_CHECKPOINT_ONLINE)
00041 {
00042 CheckPoint *checkpoint = (CheckPoint *) rec;
00043
00044 appendStringInfo(buf, "checkpoint: redo %X/%X; "
00045 "tli %u; prev tli %u; fpw %s; xid %u/%u; oid %u; multi %u; offset %u; "
00046 "oldest xid %u in DB %u; oldest multi %u in DB %u; "
00047 "oldest running xid %u; %s",
00048 (uint32) (checkpoint->redo >> 32), (uint32) checkpoint->redo,
00049 checkpoint->ThisTimeLineID,
00050 checkpoint->PrevTimeLineID,
00051 checkpoint->fullPageWrites ? "true" : "false",
00052 checkpoint->nextXidEpoch, checkpoint->nextXid,
00053 checkpoint->nextOid,
00054 checkpoint->nextMulti,
00055 checkpoint->nextMultiOffset,
00056 checkpoint->oldestXid,
00057 checkpoint->oldestXidDB,
00058 checkpoint->oldestMulti,
00059 checkpoint->oldestMultiDB,
00060 checkpoint->oldestActiveXid,
00061 (info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
00062 }
00063 else if (info == XLOG_NOOP)
00064 {
00065 appendStringInfo(buf, "xlog no-op");
00066 }
00067 else if (info == XLOG_NEXTOID)
00068 {
00069 Oid nextOid;
00070
00071 memcpy(&nextOid, rec, sizeof(Oid));
00072 appendStringInfo(buf, "nextOid: %u", nextOid);
00073 }
00074 else if (info == XLOG_SWITCH)
00075 {
00076 appendStringInfo(buf, "xlog switch");
00077 }
00078 else if (info == XLOG_RESTORE_POINT)
00079 {
00080 xl_restore_point *xlrec = (xl_restore_point *) rec;
00081
00082 appendStringInfo(buf, "restore point: %s", xlrec->rp_name);
00083
00084 }
00085 else if (info == XLOG_HINT)
00086 {
00087 BkpBlock *bkp = (BkpBlock *) rec;
00088 appendStringInfo(buf, "page hint: %s block %u",
00089 relpathperm(bkp->node, bkp->fork),
00090 bkp->block);
00091 }
00092 else if (info == XLOG_BACKUP_END)
00093 {
00094 XLogRecPtr startpoint;
00095
00096 memcpy(&startpoint, rec, sizeof(XLogRecPtr));
00097 appendStringInfo(buf, "backup end: %X/%X",
00098 (uint32) (startpoint >> 32), (uint32) startpoint);
00099 }
00100 else if (info == XLOG_PARAMETER_CHANGE)
00101 {
00102 xl_parameter_change xlrec;
00103 const char *wal_level_str;
00104 const struct config_enum_entry *entry;
00105
00106 memcpy(&xlrec, rec, sizeof(xl_parameter_change));
00107
00108
00109 wal_level_str = "?";
00110 for (entry = wal_level_options; entry->name; entry++)
00111 {
00112 if (entry->val == xlrec.wal_level)
00113 {
00114 wal_level_str = entry->name;
00115 break;
00116 }
00117 }
00118
00119 appendStringInfo(buf, "parameter change: max_connections=%d max_prepared_xacts=%d max_locks_per_xact=%d wal_level=%s",
00120 xlrec.MaxConnections,
00121 xlrec.max_prepared_xacts,
00122 xlrec.max_locks_per_xact,
00123 wal_level_str);
00124 }
00125 else if (info == XLOG_FPW_CHANGE)
00126 {
00127 bool fpw;
00128
00129 memcpy(&fpw, rec, sizeof(bool));
00130 appendStringInfo(buf, "full_page_writes: %s", fpw ? "true" : "false");
00131 }
00132 else if (info == XLOG_END_OF_RECOVERY)
00133 {
00134 xl_end_of_recovery xlrec;
00135
00136 memcpy(&xlrec, rec, sizeof(xl_end_of_recovery));
00137 appendStringInfo(buf, "end_of_recovery: tli %u; prev tli %u; time %s",
00138 xlrec.ThisTimeLineID, xlrec.PrevTimeLineID,
00139 timestamptz_to_str(xlrec.end_time));
00140 }
00141 else
00142 appendStringInfo(buf, "UNKNOWN");
00143 }