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