Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * pg_controldata.c
4 : *
5 : * Routines to expose the contents of the control data file via
6 : * a set of SQL functions.
7 : *
8 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
9 : * Portions Copyright (c) 1994, Regents of the University of California
10 : *
11 : * IDENTIFICATION
12 : * src/backend/utils/misc/pg_controldata.c
13 : *-------------------------------------------------------------------------
14 : */
15 :
16 : #include "postgres.h"
17 :
18 : #include "funcapi.h"
19 : #include "miscadmin.h"
20 : #include "access/htup_details.h"
21 : #include "access/xlog_internal.h"
22 : #include "catalog/pg_control.h"
23 : #include "catalog/pg_type.h"
24 : #include "common/controldata_utils.h"
25 : #include "utils/builtins.h"
26 : #include "utils/pg_lsn.h"
27 : #include "utils/timestamp.h"
28 :
29 : Datum
30 0 : pg_control_system(PG_FUNCTION_ARGS)
31 : {
32 : Datum values[4];
33 : bool nulls[4];
34 : TupleDesc tupdesc;
35 : HeapTuple htup;
36 : ControlFileData *ControlFile;
37 : bool crc_ok;
38 :
39 : /*
40 : * Construct a tuple descriptor for the result row. This must match this
41 : * function's pg_proc entry!
42 : */
43 0 : tupdesc = CreateTemplateTupleDesc(4, false);
44 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pg_control_version",
45 : INT4OID, -1, 0);
46 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catalog_version_no",
47 : INT4OID, -1, 0);
48 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 3, "system_identifier",
49 : INT8OID, -1, 0);
50 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pg_control_last_modified",
51 : TIMESTAMPTZOID, -1, 0);
52 0 : tupdesc = BlessTupleDesc(tupdesc);
53 :
54 : /* read the control file */
55 0 : ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
56 0 : if (!crc_ok)
57 0 : ereport(ERROR,
58 : (errmsg("calculated CRC checksum does not match value stored in file")));
59 :
60 0 : values[0] = Int32GetDatum(ControlFile->pg_control_version);
61 0 : nulls[0] = false;
62 :
63 0 : values[1] = Int32GetDatum(ControlFile->catalog_version_no);
64 0 : nulls[1] = false;
65 :
66 0 : values[2] = Int64GetDatum(ControlFile->system_identifier);
67 0 : nulls[2] = false;
68 :
69 0 : values[3] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->time));
70 0 : nulls[3] = false;
71 :
72 0 : htup = heap_form_tuple(tupdesc, values, nulls);
73 :
74 0 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
75 : }
76 :
77 : Datum
78 0 : pg_control_checkpoint(PG_FUNCTION_ARGS)
79 : {
80 : Datum values[19];
81 : bool nulls[19];
82 : TupleDesc tupdesc;
83 : HeapTuple htup;
84 : ControlFileData *ControlFile;
85 : XLogSegNo segno;
86 : char xlogfilename[MAXFNAMELEN];
87 : bool crc_ok;
88 :
89 : /*
90 : * Construct a tuple descriptor for the result row. This must match this
91 : * function's pg_proc entry!
92 : */
93 0 : tupdesc = CreateTemplateTupleDesc(19, false);
94 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 1, "checkpoint_lsn",
95 : LSNOID, -1, 0);
96 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 2, "prior_lsn",
97 : LSNOID, -1, 0);
98 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 3, "redo_lsn",
99 : LSNOID, -1, 0);
100 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 4, "redo_wal_file",
101 : TEXTOID, -1, 0);
102 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 5, "timeline_id",
103 : INT4OID, -1, 0);
104 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 6, "prev_timeline_id",
105 : INT4OID, -1, 0);
106 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 7, "full_page_writes",
107 : BOOLOID, -1, 0);
108 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 8, "next_xid",
109 : TEXTOID, -1, 0);
110 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 9, "next_oid",
111 : OIDOID, -1, 0);
112 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 10, "next_multixact_id",
113 : XIDOID, -1, 0);
114 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 11, "next_multi_offset",
115 : XIDOID, -1, 0);
116 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 12, "oldest_xid",
117 : XIDOID, -1, 0);
118 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 13, "oldest_xid_dbid",
119 : OIDOID, -1, 0);
120 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 14, "oldest_active_xid",
121 : XIDOID, -1, 0);
122 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 15, "oldest_multi_xid",
123 : XIDOID, -1, 0);
124 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 16, "oldest_multi_dbid",
125 : OIDOID, -1, 0);
126 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 17, "oldest_commit_ts_xid",
127 : XIDOID, -1, 0);
128 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 18, "newest_commit_ts_xid",
129 : XIDOID, -1, 0);
130 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 19, "checkpoint_time",
131 : TIMESTAMPTZOID, -1, 0);
132 0 : tupdesc = BlessTupleDesc(tupdesc);
133 :
134 : /* Read the control file. */
135 0 : ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
136 0 : if (!crc_ok)
137 0 : ereport(ERROR,
138 : (errmsg("calculated CRC checksum does not match value stored in file")));
139 :
140 : /*
141 : * Calculate name of the WAL file containing the latest checkpoint's REDO
142 : * start point.
143 : */
144 0 : XLByteToSeg(ControlFile->checkPointCopy.redo, segno);
145 0 : XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID, segno);
146 :
147 : /* Populate the values and null arrays */
148 0 : values[0] = LSNGetDatum(ControlFile->checkPoint);
149 0 : nulls[0] = false;
150 :
151 0 : values[1] = LSNGetDatum(ControlFile->prevCheckPoint);
152 0 : nulls[1] = false;
153 :
154 0 : values[2] = LSNGetDatum(ControlFile->checkPointCopy.redo);
155 0 : nulls[2] = false;
156 :
157 0 : values[3] = CStringGetTextDatum(xlogfilename);
158 0 : nulls[3] = false;
159 :
160 0 : values[4] = Int32GetDatum(ControlFile->checkPointCopy.ThisTimeLineID);
161 0 : nulls[4] = false;
162 :
163 0 : values[5] = Int32GetDatum(ControlFile->checkPointCopy.PrevTimeLineID);
164 0 : nulls[5] = false;
165 :
166 0 : values[6] = BoolGetDatum(ControlFile->checkPointCopy.fullPageWrites);
167 0 : nulls[6] = false;
168 :
169 0 : values[7] = CStringGetTextDatum(psprintf("%u:%u",
170 : ControlFile->checkPointCopy.nextXidEpoch,
171 : ControlFile->checkPointCopy.nextXid));
172 0 : nulls[7] = false;
173 :
174 0 : values[8] = ObjectIdGetDatum(ControlFile->checkPointCopy.nextOid);
175 0 : nulls[8] = false;
176 :
177 0 : values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
178 0 : nulls[9] = false;
179 :
180 0 : values[10] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset);
181 0 : nulls[10] = false;
182 :
183 0 : values[11] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
184 0 : nulls[11] = false;
185 :
186 0 : values[12] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestXidDB);
187 0 : nulls[12] = false;
188 :
189 0 : values[13] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestActiveXid);
190 0 : nulls[13] = false;
191 :
192 0 : values[14] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestMulti);
193 0 : nulls[14] = false;
194 :
195 0 : values[15] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestMultiDB);
196 0 : nulls[15] = false;
197 :
198 0 : values[16] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestCommitTsXid);
199 0 : nulls[16] = false;
200 :
201 0 : values[17] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid);
202 0 : nulls[17] = false;
203 :
204 0 : values[18] = TimestampTzGetDatum(
205 : time_t_to_timestamptz(ControlFile->checkPointCopy.time));
206 0 : nulls[18] = false;
207 :
208 0 : htup = heap_form_tuple(tupdesc, values, nulls);
209 :
210 0 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
211 : }
212 :
213 : Datum
214 0 : pg_control_recovery(PG_FUNCTION_ARGS)
215 : {
216 : Datum values[5];
217 : bool nulls[5];
218 : TupleDesc tupdesc;
219 : HeapTuple htup;
220 : ControlFileData *ControlFile;
221 : bool crc_ok;
222 :
223 : /*
224 : * Construct a tuple descriptor for the result row. This must match this
225 : * function's pg_proc entry!
226 : */
227 0 : tupdesc = CreateTemplateTupleDesc(5, false);
228 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 1, "min_recovery_end_lsn",
229 : LSNOID, -1, 0);
230 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 2, "min_recovery_end_timeline",
231 : INT4OID, -1, 0);
232 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 3, "backup_start_lsn",
233 : LSNOID, -1, 0);
234 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 4, "backup_end_lsn",
235 : LSNOID, -1, 0);
236 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 5, "end_of_backup_record_required",
237 : BOOLOID, -1, 0);
238 0 : tupdesc = BlessTupleDesc(tupdesc);
239 :
240 : /* read the control file */
241 0 : ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
242 0 : if (!crc_ok)
243 0 : ereport(ERROR,
244 : (errmsg("calculated CRC checksum does not match value stored in file")));
245 :
246 0 : values[0] = LSNGetDatum(ControlFile->minRecoveryPoint);
247 0 : nulls[0] = false;
248 :
249 0 : values[1] = Int32GetDatum(ControlFile->minRecoveryPointTLI);
250 0 : nulls[1] = false;
251 :
252 0 : values[2] = LSNGetDatum(ControlFile->backupStartPoint);
253 0 : nulls[2] = false;
254 :
255 0 : values[3] = LSNGetDatum(ControlFile->backupEndPoint);
256 0 : nulls[3] = false;
257 :
258 0 : values[4] = BoolGetDatum(ControlFile->backupEndRequired);
259 0 : nulls[4] = false;
260 :
261 0 : htup = heap_form_tuple(tupdesc, values, nulls);
262 :
263 0 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
264 : }
265 :
266 : Datum
267 0 : pg_control_init(PG_FUNCTION_ARGS)
268 : {
269 : Datum values[12];
270 : bool nulls[12];
271 : TupleDesc tupdesc;
272 : HeapTuple htup;
273 : ControlFileData *ControlFile;
274 : bool crc_ok;
275 :
276 : /*
277 : * Construct a tuple descriptor for the result row. This must match this
278 : * function's pg_proc entry!
279 : */
280 0 : tupdesc = CreateTemplateTupleDesc(12, false);
281 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 1, "max_data_alignment",
282 : INT4OID, -1, 0);
283 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database_block_size",
284 : INT4OID, -1, 0);
285 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 3, "blocks_per_segment",
286 : INT4OID, -1, 0);
287 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 4, "wal_block_size",
288 : INT4OID, -1, 0);
289 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 5, "bytes_per_wal_segment",
290 : INT4OID, -1, 0);
291 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 6, "max_identifier_length",
292 : INT4OID, -1, 0);
293 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 7, "max_index_columns",
294 : INT4OID, -1, 0);
295 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 8, "max_toast_chunk_size",
296 : INT4OID, -1, 0);
297 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 9, "large_object_chunk_size",
298 : INT4OID, -1, 0);
299 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 10, "float4_pass_by_value",
300 : BOOLOID, -1, 0);
301 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 11, "float8_pass_by_value",
302 : BOOLOID, -1, 0);
303 0 : TupleDescInitEntry(tupdesc, (AttrNumber) 12, "data_page_checksum_version",
304 : INT4OID, -1, 0);
305 0 : tupdesc = BlessTupleDesc(tupdesc);
306 :
307 : /* read the control file */
308 0 : ControlFile = get_controlfile(DataDir, NULL, &crc_ok);
309 0 : if (!crc_ok)
310 0 : ereport(ERROR,
311 : (errmsg("calculated CRC checksum does not match value stored in file")));
312 :
313 0 : values[0] = Int32GetDatum(ControlFile->maxAlign);
314 0 : nulls[0] = false;
315 :
316 0 : values[1] = Int32GetDatum(ControlFile->blcksz);
317 0 : nulls[1] = false;
318 :
319 0 : values[2] = Int32GetDatum(ControlFile->relseg_size);
320 0 : nulls[2] = false;
321 :
322 0 : values[3] = Int32GetDatum(ControlFile->xlog_blcksz);
323 0 : nulls[3] = false;
324 :
325 0 : values[4] = Int32GetDatum(ControlFile->xlog_seg_size);
326 0 : nulls[4] = false;
327 :
328 0 : values[5] = Int32GetDatum(ControlFile->nameDataLen);
329 0 : nulls[5] = false;
330 :
331 0 : values[6] = Int32GetDatum(ControlFile->indexMaxKeys);
332 0 : nulls[6] = false;
333 :
334 0 : values[7] = Int32GetDatum(ControlFile->toast_max_chunk_size);
335 0 : nulls[7] = false;
336 :
337 0 : values[8] = Int32GetDatum(ControlFile->loblksize);
338 0 : nulls[8] = false;
339 :
340 0 : values[9] = BoolGetDatum(ControlFile->float4ByVal);
341 0 : nulls[9] = false;
342 :
343 0 : values[10] = BoolGetDatum(ControlFile->float8ByVal);
344 0 : nulls[10] = false;
345 :
346 0 : values[11] = Int32GetDatum(ControlFile->data_checksum_version);
347 0 : nulls[11] = false;
348 :
349 0 : htup = heap_form_tuple(tupdesc, values, nulls);
350 :
351 0 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
352 : }
|