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
3827 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 : :
1345 michael@paquier.xyz 41 [ - + ]: 16 : if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1345 michael@paquier.xyz 42 [ # # ]:UIC 0 : elog(ERROR, "return type must be a row type");
43 : :
44 : : /* read the control file */
1046 tmunro@postgresql.or 45 :GIC 16 : LWLockAcquire(ControlFileLock, LW_SHARED);
2705 peter@eisentraut.org 46 : 16 : ControlFile = get_controlfile(DataDir, &crc_ok);
1046 tmunro@postgresql.or 47 : 16 : LWLockRelease(ControlFileLock);
3620 peter_e@gmx.net 48 [ - + ]: 16 : if (!crc_ok)
3684 peter_e@gmx.net 49 [ # # ]:UIC 0 : ereport(ERROR,
50 : : (errmsg("calculated CRC checksum does not match value stored in file")));
51 : :
3827 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 : 14 : pg_control_checkpoint(PG_FUNCTION_ARGS)
71 : : {
72 : : Datum values[20];
73 : : bool nulls[20];
74 : : TupleDesc tupdesc;
75 : : HeapTuple htup;
76 : : ControlFileData *ControlFile;
77 : : XLogSegNo segno;
78 : : char xlogfilename[MAXFNAMELEN];
79 : : bool crc_ok;
80 : :
1345 michael@paquier.xyz 81 [ - + ]: 14 : if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1345 michael@paquier.xyz 82 [ # # ]:UIC 0 : elog(ERROR, "return type must be a row type");
83 : :
84 : : /* Read the control file. */
1046 tmunro@postgresql.or 85 :GIC 14 : LWLockAcquire(ControlFileLock, LW_SHARED);
2705 peter@eisentraut.org 86 : 14 : ControlFile = get_controlfile(DataDir, &crc_ok);
1046 tmunro@postgresql.or 87 : 14 : LWLockRelease(ControlFileLock);
3620 peter_e@gmx.net 88 [ - + ]: 14 : if (!crc_ok)
3684 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 : : */
3264 andres@anarazel.de 96 :GIC 14 : XLByteToSeg(ControlFile->checkPointCopy.redo, segno, wal_segment_size);
97 : 14 : XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID,
98 : : segno, wal_segment_size);
99 : :
100 : : /* Populate the values and null arrays */
3827 mail@joeconway.com 101 : 14 : values[0] = LSNGetDatum(ControlFile->checkPoint);
102 : 14 : nulls[0] = false;
103 : :
3215 simon@2ndQuadrant.co 104 : 14 : values[1] = LSNGetDatum(ControlFile->checkPointCopy.redo);
3827 mail@joeconway.com 105 : 14 : nulls[1] = false;
106 : :
3215 simon@2ndQuadrant.co 107 : 14 : values[2] = CStringGetTextDatum(xlogfilename);
3827 mail@joeconway.com 108 : 14 : nulls[2] = false;
109 : :
3215 simon@2ndQuadrant.co 110 : 14 : values[3] = Int32GetDatum(ControlFile->checkPointCopy.ThisTimeLineID);
3827 mail@joeconway.com 111 : 14 : nulls[3] = false;
112 : :
3215 simon@2ndQuadrant.co 113 : 14 : values[4] = Int32GetDatum(ControlFile->checkPointCopy.PrevTimeLineID);
3827 mail@joeconway.com 114 : 14 : nulls[4] = false;
115 : :
3215 simon@2ndQuadrant.co 116 : 14 : values[5] = BoolGetDatum(ControlFile->checkPointCopy.fullPageWrites);
3827 mail@joeconway.com 117 : 14 : nulls[5] = false;
118 : :
38 msawada@postgresql.o 119 : 14 : values[6] = BoolGetDatum(ControlFile->checkPointCopy.logicalDecodingEnabled);
3215 simon@2ndQuadrant.co 120 : 14 : nulls[6] = false;
121 : :
38 msawada@postgresql.o 122 : 14 : values[7] = CStringGetTextDatum(psprintf("%u:%u",
123 : : EpochFromFullTransactionId(ControlFile->checkPointCopy.nextXid),
124 : : XidFromFullTransactionId(ControlFile->checkPointCopy.nextXid)));
3827 mail@joeconway.com 125 : 14 : nulls[7] = false;
126 : :
38 msawada@postgresql.o 127 : 14 : values[8] = ObjectIdGetDatum(ControlFile->checkPointCopy.nextOid);
3827 mail@joeconway.com 128 : 14 : nulls[8] = false;
129 : :
38 msawada@postgresql.o 130 : 14 : values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
3827 mail@joeconway.com 131 : 14 : nulls[9] = false;
132 : :
38 msawada@postgresql.o 133 : 14 : values[10] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset);
3827 mail@joeconway.com 134 : 14 : nulls[10] = false;
135 : :
38 msawada@postgresql.o 136 : 14 : values[11] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
3827 mail@joeconway.com 137 : 14 : nulls[11] = false;
138 : :
38 msawada@postgresql.o 139 : 14 : values[12] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestXidDB);
3827 mail@joeconway.com 140 : 14 : nulls[12] = false;
141 : :
38 msawada@postgresql.o 142 : 14 : values[13] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestActiveXid);
3827 mail@joeconway.com 143 : 14 : nulls[13] = false;
144 : :
38 msawada@postgresql.o 145 : 14 : values[14] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestMulti);
3827 mail@joeconway.com 146 : 14 : nulls[14] = false;
147 : :
38 msawada@postgresql.o 148 : 14 : values[15] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestMultiDB);
3827 mail@joeconway.com 149 : 14 : nulls[15] = false;
150 : :
38 msawada@postgresql.o 151 : 14 : values[16] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestCommitTsXid);
3827 mail@joeconway.com 152 : 14 : nulls[16] = false;
153 : :
38 msawada@postgresql.o 154 : 14 : values[17] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid);
3215 simon@2ndQuadrant.co 155 : 14 : nulls[17] = false;
156 : :
9 dgustafsson@postgres 157 : 14 : values[18] = Int32GetDatum(ControlFile->checkPointCopy.dataChecksumState);
38 msawada@postgresql.o 158 : 14 : nulls[18] = false;
159 : :
9 dgustafsson@postgres 160 : 14 : values[19] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->checkPointCopy.time));
161 : 14 : nulls[19] = false;
162 : :
3827 mail@joeconway.com 163 : 14 : htup = heap_form_tuple(tupdesc, values, nulls);
164 : :
165 : 14 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
166 : : }
167 : :
168 : : Datum
169 : 4 : pg_control_recovery(PG_FUNCTION_ARGS)
170 : : {
171 : : Datum values[5];
172 : : bool nulls[5];
173 : : TupleDesc tupdesc;
174 : : HeapTuple htup;
175 : : ControlFileData *ControlFile;
176 : : bool crc_ok;
177 : :
1345 michael@paquier.xyz 178 [ - + ]: 4 : if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1345 michael@paquier.xyz 179 [ # # ]:UIC 0 : elog(ERROR, "return type must be a row type");
180 : :
181 : : /* read the control file */
1046 tmunro@postgresql.or 182 :GIC 4 : LWLockAcquire(ControlFileLock, LW_SHARED);
2705 peter@eisentraut.org 183 : 4 : ControlFile = get_controlfile(DataDir, &crc_ok);
1046 tmunro@postgresql.or 184 : 4 : LWLockRelease(ControlFileLock);
3620 peter_e@gmx.net 185 [ - + ]: 4 : if (!crc_ok)
3684 peter_e@gmx.net 186 [ # # ]:UIC 0 : ereport(ERROR,
187 : : (errmsg("calculated CRC checksum does not match value stored in file")));
188 : :
3827 mail@joeconway.com 189 :GIC 4 : values[0] = LSNGetDatum(ControlFile->minRecoveryPoint);
190 : 4 : nulls[0] = false;
191 : :
192 : 4 : values[1] = Int32GetDatum(ControlFile->minRecoveryPointTLI);
193 : 4 : nulls[1] = false;
194 : :
195 : 4 : values[2] = LSNGetDatum(ControlFile->backupStartPoint);
196 : 4 : nulls[2] = false;
197 : :
198 : 4 : values[3] = LSNGetDatum(ControlFile->backupEndPoint);
199 : 4 : nulls[3] = false;
200 : :
201 : 4 : values[4] = BoolGetDatum(ControlFile->backupEndRequired);
202 : 4 : nulls[4] = false;
203 : :
204 : 4 : htup = heap_form_tuple(tupdesc, values, nulls);
205 : :
206 : 4 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
207 : : }
208 : :
209 : : Datum
210 : 11 : pg_control_init(PG_FUNCTION_ARGS)
211 : : {
212 : : Datum values[12];
213 : : bool nulls[12];
214 : : TupleDesc tupdesc;
215 : : HeapTuple htup;
216 : : ControlFileData *ControlFile;
217 : : bool crc_ok;
218 : :
1345 michael@paquier.xyz 219 [ - + ]: 11 : if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1345 michael@paquier.xyz 220 [ # # ]:UIC 0 : elog(ERROR, "return type must be a row type");
221 : :
222 : : /* read the control file */
1046 tmunro@postgresql.or 223 :GIC 11 : LWLockAcquire(ControlFileLock, LW_SHARED);
2705 peter@eisentraut.org 224 : 11 : ControlFile = get_controlfile(DataDir, &crc_ok);
1046 tmunro@postgresql.or 225 : 11 : LWLockRelease(ControlFileLock);
3620 peter_e@gmx.net 226 [ - + ]: 11 : if (!crc_ok)
3684 peter_e@gmx.net 227 [ # # ]:UIC 0 : ereport(ERROR,
228 : : (errmsg("calculated CRC checksum does not match value stored in file")));
229 : :
3827 mail@joeconway.com 230 :GIC 11 : values[0] = Int32GetDatum(ControlFile->maxAlign);
231 : 11 : nulls[0] = false;
232 : :
233 : 11 : values[1] = Int32GetDatum(ControlFile->blcksz);
234 : 11 : nulls[1] = false;
235 : :
236 : 11 : values[2] = Int32GetDatum(ControlFile->relseg_size);
237 : 11 : nulls[2] = false;
238 : :
239 : 11 : values[3] = Int32GetDatum(ControlFile->xlog_blcksz);
240 : 11 : nulls[3] = false;
241 : :
242 : 11 : values[4] = Int32GetDatum(ControlFile->xlog_seg_size);
243 : 11 : nulls[4] = false;
244 : :
245 : 11 : values[5] = Int32GetDatum(ControlFile->nameDataLen);
246 : 11 : nulls[5] = false;
247 : :
248 : 11 : values[6] = Int32GetDatum(ControlFile->indexMaxKeys);
249 : 11 : nulls[6] = false;
250 : :
251 : 11 : values[7] = Int32GetDatum(ControlFile->toast_max_chunk_size);
252 : 11 : nulls[7] = false;
253 : :
254 : 11 : values[8] = Int32GetDatum(ControlFile->loblksize);
255 : 11 : nulls[8] = false;
256 : :
2471 peter@eisentraut.org 257 : 11 : values[9] = BoolGetDatum(ControlFile->float8ByVal);
3827 mail@joeconway.com 258 : 11 : nulls[9] = false;
259 : :
9 dgustafsson@postgres 260 : 11 : values[10] = Int32GetDatum(ControlFile->data_checksum_version_init);
3827 mail@joeconway.com 261 : 11 : nulls[10] = false;
262 : :
552 msawada@postgresql.o 263 : 11 : values[11] = BoolGetDatum(ControlFile->default_char_signedness);
264 : 11 : nulls[11] = false;
265 : :
3827 mail@joeconway.com 266 : 11 : htup = heap_form_tuple(tupdesc, values, nulls);
267 : :
268 : 11 : PG_RETURN_DATUM(HeapTupleGetDatum(htup));
269 : : }
|