Age Owner Branch data TLA 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-2026, 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 "access/htup_details.h"
19 : : #include "access/transam.h"
20 : : #include "access/xlog.h"
21 : : #include "access/xlog_internal.h"
22 : : #include "catalog/pg_control.h"
23 : : #include "common/controldata_utils.h"
24 : : #include "funcapi.h"
25 : : #include "miscadmin.h"
26 : : #include "storage/lwlock.h"
27 : : #include "utils/builtins.h"
28 : : #include "utils/pg_lsn.h"
29 : : #include "utils/timestamp.h"
30 : :
31 : : Datum
3794 mail@joeconway.com 32 :GIC 16 : pg_control_system(PG_FUNCTION_ARGS)
33 : : {
34 : : Datum values[4];
35 : : bool nulls[4];
36 : : TupleDesc tupdesc;
37 : : HeapTuple htup;
38 : : ControlFileData *ControlFile;
39 : : bool crc_ok;
40 : :
1312 michael@paquier.xyz 41 [ - + ]: 16 : if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1312 michael@paquier.xyz 42 [ # # ]:UIC 0 : elog(ERROR, "return type must be a row type");
43 : :
44 : : /* read the control file */
1013 tmunro@postgresql.or 45 :GIC 16 : LWLockAcquire(ControlFileLock, LW_SHARED);
2672 peter@eisentraut.org 46 : 16 : ControlFile = get_controlfile(DataDir, &crc_ok);
1013 tmunro@postgresql.or 47 : 16 : LWLockRelease(ControlFileLock);
3587 peter_e@gmx.net 48 [ - + ]: 16 : if (!crc_ok)
3651 peter_e@gmx.net 49 [ # # ]:UIC 0 : ereport(ERROR,
50 : : (errmsg("calculated CRC checksum does not match value stored in file")));
51 : :
3794 mail@joeconway.com 52 :GIC 16 : values[0] = Int32GetDatum(ControlFile->pg_control_version);
53 : 16 : nulls[0] = false;
54 : :
55 : 16 : values[1] = Int32GetDatum(ControlFile->catalog_version_no);
56 : 16 : nulls[1] = false;
57 : :
58 : 16 : values[2] = Int64GetDatum(ControlFile->system_identifier);
59 : 16 : nulls[2] = false;
60 : :
61 : 16 : values[3] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->time));
62 : 16 : nulls[3] = false;
63 : :
64 : 16 : htup = heap_form_tuple(tupdesc, values, nulls);
65 : :
66 : 16 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
67 : : }
68 : :
69 : : Datum
70 : 11 : pg_control_checkpoint(PG_FUNCTION_ARGS)
71 : : {
72 : : Datum values[19];
73 : : bool nulls[19];
74 : : TupleDesc tupdesc;
75 : : HeapTuple htup;
76 : : ControlFileData *ControlFile;
77 : : XLogSegNo segno;
78 : : char xlogfilename[MAXFNAMELEN];
79 : : bool crc_ok;
80 : :
1312 michael@paquier.xyz 81 [ - + ]: 11 : if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1312 michael@paquier.xyz 82 [ # # ]:UIC 0 : elog(ERROR, "return type must be a row type");
83 : :
84 : : /* Read the control file. */
1013 tmunro@postgresql.or 85 :GIC 11 : LWLockAcquire(ControlFileLock, LW_SHARED);
2672 peter@eisentraut.org 86 : 11 : ControlFile = get_controlfile(DataDir, &crc_ok);
1013 tmunro@postgresql.or 87 : 11 : LWLockRelease(ControlFileLock);
3587 peter_e@gmx.net 88 [ - + ]: 11 : if (!crc_ok)
3651 peter_e@gmx.net 89 [ # # ]:UIC 0 : ereport(ERROR,
90 : : (errmsg("calculated CRC checksum does not match value stored in file")));
91 : :
92 : : /*
93 : : * Calculate name of the WAL file containing the latest checkpoint's REDO
94 : : * start point.
95 : : */
3231 andres@anarazel.de 96 :GIC 11 : XLByteToSeg(ControlFile->checkPointCopy.redo, segno, wal_segment_size);
97 : 11 : XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID,
98 : : segno, wal_segment_size);
99 : :
100 : : /* Populate the values and null arrays */
3794 mail@joeconway.com 101 : 11 : values[0] = LSNGetDatum(ControlFile->checkPoint);
102 : 11 : nulls[0] = false;
103 : :
3182 simon@2ndQuadrant.co 104 : 11 : values[1] = LSNGetDatum(ControlFile->checkPointCopy.redo);
3794 mail@joeconway.com 105 : 11 : nulls[1] = false;
106 : :
3182 simon@2ndQuadrant.co 107 : 11 : values[2] = CStringGetTextDatum(xlogfilename);
3794 mail@joeconway.com 108 : 11 : nulls[2] = false;
109 : :
3182 simon@2ndQuadrant.co 110 : 11 : values[3] = Int32GetDatum(ControlFile->checkPointCopy.ThisTimeLineID);
3794 mail@joeconway.com 111 : 11 : nulls[3] = false;
112 : :
3182 simon@2ndQuadrant.co 113 : 11 : values[4] = Int32GetDatum(ControlFile->checkPointCopy.PrevTimeLineID);
3794 mail@joeconway.com 114 : 11 : nulls[4] = false;
115 : :
3182 simon@2ndQuadrant.co 116 : 11 : values[5] = BoolGetDatum(ControlFile->checkPointCopy.fullPageWrites);
3794 mail@joeconway.com 117 : 11 : nulls[5] = false;
118 : :
5 msawada@postgresql.o 119 : 11 : values[6] = BoolGetDatum(ControlFile->checkPointCopy.logicalDecodingEnabled);
3182 simon@2ndQuadrant.co 120 : 11 : nulls[6] = false;
121 : :
5 msawada@postgresql.o 122 : 11 : values[7] = CStringGetTextDatum(psprintf("%u:%u",
123 : : EpochFromFullTransactionId(ControlFile->checkPointCopy.nextXid),
124 : : XidFromFullTransactionId(ControlFile->checkPointCopy.nextXid)));
3794 mail@joeconway.com 125 : 11 : nulls[7] = false;
126 : :
5 msawada@postgresql.o 127 : 11 : values[8] = ObjectIdGetDatum(ControlFile->checkPointCopy.nextOid);
3794 mail@joeconway.com 128 : 11 : nulls[8] = false;
129 : :
5 msawada@postgresql.o 130 : 11 : values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
3794 mail@joeconway.com 131 : 11 : nulls[9] = false;
132 : :
5 msawada@postgresql.o 133 : 11 : values[10] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset);
3794 mail@joeconway.com 134 : 11 : nulls[10] = false;
135 : :
5 msawada@postgresql.o 136 : 11 : values[11] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
3794 mail@joeconway.com 137 : 11 : nulls[11] = false;
138 : :
5 msawada@postgresql.o 139 : 11 : values[12] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestXidDB);
3794 mail@joeconway.com 140 : 11 : nulls[12] = false;
141 : :
5 msawada@postgresql.o 142 : 11 : values[13] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestActiveXid);
3794 mail@joeconway.com 143 : 11 : nulls[13] = false;
144 : :
5 msawada@postgresql.o 145 : 11 : values[14] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestMulti);
3794 mail@joeconway.com 146 : 11 : nulls[14] = false;
147 : :
5 msawada@postgresql.o 148 : 11 : values[15] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestMultiDB);
3794 mail@joeconway.com 149 : 11 : nulls[15] = false;
150 : :
5 msawada@postgresql.o 151 : 11 : values[16] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestCommitTsXid);
3794 mail@joeconway.com 152 : 11 : nulls[16] = false;
153 : :
5 msawada@postgresql.o 154 : 11 : values[17] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid);
3182 simon@2ndQuadrant.co 155 : 11 : nulls[17] = false;
156 : :
5 msawada@postgresql.o 157 : 11 : values[18] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->checkPointCopy.time));
158 : 11 : nulls[18] = false;
159 : :
3794 mail@joeconway.com 160 : 11 : htup = heap_form_tuple(tupdesc, values, nulls);
161 : :
162 : 11 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
163 : : }
164 : :
165 : : Datum
166 : 4 : pg_control_recovery(PG_FUNCTION_ARGS)
167 : : {
168 : : Datum values[5];
169 : : bool nulls[5];
170 : : TupleDesc tupdesc;
171 : : HeapTuple htup;
172 : : ControlFileData *ControlFile;
173 : : bool crc_ok;
174 : :
1312 michael@paquier.xyz 175 [ - + ]: 4 : if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1312 michael@paquier.xyz 176 [ # # ]:UIC 0 : elog(ERROR, "return type must be a row type");
177 : :
178 : : /* read the control file */
1013 tmunro@postgresql.or 179 :GIC 4 : LWLockAcquire(ControlFileLock, LW_SHARED);
2672 peter@eisentraut.org 180 : 4 : ControlFile = get_controlfile(DataDir, &crc_ok);
1013 tmunro@postgresql.or 181 : 4 : LWLockRelease(ControlFileLock);
3587 peter_e@gmx.net 182 [ - + ]: 4 : if (!crc_ok)
3651 peter_e@gmx.net 183 [ # # ]:UIC 0 : ereport(ERROR,
184 : : (errmsg("calculated CRC checksum does not match value stored in file")));
185 : :
3794 mail@joeconway.com 186 :GIC 4 : values[0] = LSNGetDatum(ControlFile->minRecoveryPoint);
187 : 4 : nulls[0] = false;
188 : :
189 : 4 : values[1] = Int32GetDatum(ControlFile->minRecoveryPointTLI);
190 : 4 : nulls[1] = false;
191 : :
192 : 4 : values[2] = LSNGetDatum(ControlFile->backupStartPoint);
193 : 4 : nulls[2] = false;
194 : :
195 : 4 : values[3] = LSNGetDatum(ControlFile->backupEndPoint);
196 : 4 : nulls[3] = false;
197 : :
198 : 4 : values[4] = BoolGetDatum(ControlFile->backupEndRequired);
199 : 4 : nulls[4] = false;
200 : :
201 : 4 : htup = heap_form_tuple(tupdesc, values, nulls);
202 : :
203 : 4 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
204 : : }
205 : :
206 : : Datum
207 : 5 : pg_control_init(PG_FUNCTION_ARGS)
208 : : {
209 : : Datum values[12];
210 : : bool nulls[12];
211 : : TupleDesc tupdesc;
212 : : HeapTuple htup;
213 : : ControlFileData *ControlFile;
214 : : bool crc_ok;
215 : :
1312 michael@paquier.xyz 216 [ - + ]: 5 : if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1312 michael@paquier.xyz 217 [ # # ]:UIC 0 : elog(ERROR, "return type must be a row type");
218 : :
219 : : /* read the control file */
1013 tmunro@postgresql.or 220 :GIC 5 : LWLockAcquire(ControlFileLock, LW_SHARED);
2672 peter@eisentraut.org 221 : 5 : ControlFile = get_controlfile(DataDir, &crc_ok);
1013 tmunro@postgresql.or 222 : 5 : LWLockRelease(ControlFileLock);
3587 peter_e@gmx.net 223 [ - + ]: 5 : if (!crc_ok)
3651 peter_e@gmx.net 224 [ # # ]:UIC 0 : ereport(ERROR,
225 : : (errmsg("calculated CRC checksum does not match value stored in file")));
226 : :
3794 mail@joeconway.com 227 :GIC 5 : values[0] = Int32GetDatum(ControlFile->maxAlign);
228 : 5 : nulls[0] = false;
229 : :
230 : 5 : values[1] = Int32GetDatum(ControlFile->blcksz);
231 : 5 : nulls[1] = false;
232 : :
233 : 5 : values[2] = Int32GetDatum(ControlFile->relseg_size);
234 : 5 : nulls[2] = false;
235 : :
236 : 5 : values[3] = Int32GetDatum(ControlFile->xlog_blcksz);
237 : 5 : nulls[3] = false;
238 : :
239 : 5 : values[4] = Int32GetDatum(ControlFile->xlog_seg_size);
240 : 5 : nulls[4] = false;
241 : :
242 : 5 : values[5] = Int32GetDatum(ControlFile->nameDataLen);
243 : 5 : nulls[5] = false;
244 : :
245 : 5 : values[6] = Int32GetDatum(ControlFile->indexMaxKeys);
246 : 5 : nulls[6] = false;
247 : :
248 : 5 : values[7] = Int32GetDatum(ControlFile->toast_max_chunk_size);
249 : 5 : nulls[7] = false;
250 : :
251 : 5 : values[8] = Int32GetDatum(ControlFile->loblksize);
252 : 5 : nulls[8] = false;
253 : :
2438 peter@eisentraut.org 254 : 5 : values[9] = BoolGetDatum(ControlFile->float8ByVal);
3794 mail@joeconway.com 255 : 5 : nulls[9] = false;
256 : :
2438 peter@eisentraut.org 257 : 5 : values[10] = Int32GetDatum(ControlFile->data_checksum_version);
3794 mail@joeconway.com 258 : 5 : nulls[10] = false;
259 : :
519 msawada@postgresql.o 260 : 5 : values[11] = BoolGetDatum(ControlFile->default_char_signedness);
261 : 5 : nulls[11] = false;
262 : :
3794 mail@joeconway.com 263 : 5 : htup = heap_form_tuple(tupdesc, values, nulls);
264 : :
265 : 5 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
266 : : }
|