1 /*-------------------------------------------------------------------------
2  *
3  * xlogdesc.c
4  *	  rmgr descriptor routines for access/transam/xlog.c
5  *
6  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *	  src/backend/access/rmgrdesc/xlogdesc.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/transam.h"
18 #include "access/xlog.h"
19 #include "access/xlog_internal.h"
20 #include "catalog/pg_control.h"
21 #include "utils/guc.h"
22 #include "utils/timestamp.h"
23 
24 /*
25  * GUC support
26  */
27 const struct config_enum_entry wal_level_options[] = {
28 	{"minimal", WAL_LEVEL_MINIMAL, false},
29 	{"replica", WAL_LEVEL_REPLICA, false},
30 	{"archive", WAL_LEVEL_REPLICA, true},	/* deprecated */
31 	{"hot_standby", WAL_LEVEL_REPLICA, true},	/* deprecated */
32 	{"logical", WAL_LEVEL_LOGICAL, false},
33 	{NULL, 0, false}
34 };
35 
36 void
xlog_desc(StringInfo buf,XLogReaderState * record)37 xlog_desc(StringInfo buf, XLogReaderState *record)
38 {
39 	char	   *rec = XLogRecGetData(record);
40 	uint8		info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
41 
42 	if (info == XLOG_CHECKPOINT_SHUTDOWN ||
43 		info == XLOG_CHECKPOINT_ONLINE)
44 	{
45 		CheckPoint *checkpoint = (CheckPoint *) rec;
46 
47 		appendStringInfo(buf, "redo %X/%X; "
48 						 "tli %u; prev tli %u; fpw %s; xid %u:%u; oid %u; multi %u; offset %u; "
49 						 "oldest xid %u in DB %u; oldest multi %u in DB %u; "
50 						 "oldest/newest commit timestamp xid: %u/%u; "
51 						 "oldest running xid %u; %s",
52 						 (uint32) (checkpoint->redo >> 32), (uint32) checkpoint->redo,
53 						 checkpoint->ThisTimeLineID,
54 						 checkpoint->PrevTimeLineID,
55 						 checkpoint->fullPageWrites ? "true" : "false",
56 						 EpochFromFullTransactionId(checkpoint->nextFullXid),
57 						 XidFromFullTransactionId(checkpoint->nextFullXid),
58 						 checkpoint->nextOid,
59 						 checkpoint->nextMulti,
60 						 checkpoint->nextMultiOffset,
61 						 checkpoint->oldestXid,
62 						 checkpoint->oldestXidDB,
63 						 checkpoint->oldestMulti,
64 						 checkpoint->oldestMultiDB,
65 						 checkpoint->oldestCommitTsXid,
66 						 checkpoint->newestCommitTsXid,
67 						 checkpoint->oldestActiveXid,
68 						 (info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
69 	}
70 	else if (info == XLOG_NEXTOID)
71 	{
72 		Oid			nextOid;
73 
74 		memcpy(&nextOid, rec, sizeof(Oid));
75 		appendStringInfo(buf, "%u", nextOid);
76 	}
77 	else if (info == XLOG_RESTORE_POINT)
78 	{
79 		xl_restore_point *xlrec = (xl_restore_point *) rec;
80 
81 		appendStringInfoString(buf, xlrec->rp_name);
82 	}
83 	else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
84 	{
85 		/* no further information to print */
86 	}
87 	else if (info == XLOG_BACKUP_END)
88 	{
89 		XLogRecPtr	startpoint;
90 
91 		memcpy(&startpoint, rec, sizeof(XLogRecPtr));
92 		appendStringInfo(buf, "%X/%X",
93 						 (uint32) (startpoint >> 32), (uint32) startpoint);
94 	}
95 	else if (info == XLOG_PARAMETER_CHANGE)
96 	{
97 		xl_parameter_change xlrec;
98 		const char *wal_level_str;
99 		const struct config_enum_entry *entry;
100 
101 		memcpy(&xlrec, rec, sizeof(xl_parameter_change));
102 
103 		/* Find a string representation for wal_level */
104 		wal_level_str = "?";
105 		for (entry = wal_level_options; entry->name; entry++)
106 		{
107 			if (entry->val == xlrec.wal_level)
108 			{
109 				wal_level_str = entry->name;
110 				break;
111 			}
112 		}
113 
114 		appendStringInfo(buf, "max_connections=%d max_worker_processes=%d "
115 						 "max_wal_senders=%d max_prepared_xacts=%d "
116 						 "max_locks_per_xact=%d wal_level=%s "
117 						 "wal_log_hints=%s track_commit_timestamp=%s",
118 						 xlrec.MaxConnections,
119 						 xlrec.max_worker_processes,
120 						 xlrec.max_wal_senders,
121 						 xlrec.max_prepared_xacts,
122 						 xlrec.max_locks_per_xact,
123 						 wal_level_str,
124 						 xlrec.wal_log_hints ? "on" : "off",
125 						 xlrec.track_commit_timestamp ? "on" : "off");
126 	}
127 	else if (info == XLOG_FPW_CHANGE)
128 	{
129 		bool		fpw;
130 
131 		memcpy(&fpw, rec, sizeof(bool));
132 		appendStringInfoString(buf, fpw ? "true" : "false");
133 	}
134 	else if (info == XLOG_END_OF_RECOVERY)
135 	{
136 		xl_end_of_recovery xlrec;
137 
138 		memcpy(&xlrec, rec, sizeof(xl_end_of_recovery));
139 		appendStringInfo(buf, "tli %u; prev tli %u; time %s",
140 						 xlrec.ThisTimeLineID, xlrec.PrevTimeLineID,
141 						 timestamptz_to_str(xlrec.end_time));
142 	}
143 	else if (info == XLOG_OVERWRITE_CONTRECORD)
144 	{
145 		xl_overwrite_contrecord xlrec;
146 
147 		memcpy(&xlrec, rec, sizeof(xl_overwrite_contrecord));
148 		appendStringInfo(buf, "lsn %X/%X; time %s",
149 						 (uint32) (xlrec.overwritten_lsn >> 32),
150 						 (uint32) xlrec.overwritten_lsn,
151 						 timestamptz_to_str(xlrec.overwrite_time));
152 	}
153 }
154 
155 const char *
xlog_identify(uint8 info)156 xlog_identify(uint8 info)
157 {
158 	const char *id = NULL;
159 
160 	switch (info & ~XLR_INFO_MASK)
161 	{
162 		case XLOG_CHECKPOINT_SHUTDOWN:
163 			id = "CHECKPOINT_SHUTDOWN";
164 			break;
165 		case XLOG_CHECKPOINT_ONLINE:
166 			id = "CHECKPOINT_ONLINE";
167 			break;
168 		case XLOG_NOOP:
169 			id = "NOOP";
170 			break;
171 		case XLOG_NEXTOID:
172 			id = "NEXTOID";
173 			break;
174 		case XLOG_SWITCH:
175 			id = "SWITCH";
176 			break;
177 		case XLOG_BACKUP_END:
178 			id = "BACKUP_END";
179 			break;
180 		case XLOG_PARAMETER_CHANGE:
181 			id = "PARAMETER_CHANGE";
182 			break;
183 		case XLOG_RESTORE_POINT:
184 			id = "RESTORE_POINT";
185 			break;
186 		case XLOG_FPW_CHANGE:
187 			id = "FPW_CHANGE";
188 			break;
189 		case XLOG_END_OF_RECOVERY:
190 			id = "END_OF_RECOVERY";
191 			break;
192 		case XLOG_OVERWRITE_CONTRECORD:
193 			id = "OVERWRITE_CONTRECORD";
194 			break;
195 		case XLOG_FPI:
196 			id = "FPI";
197 			break;
198 		case XLOG_FPI_FOR_HINT:
199 			id = "FPI_FOR_HINT";
200 			break;
201 	}
202 
203 	return id;
204 }
205