00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "postgres.h"
00018
00019 #include "access/htup_details.h"
00020 #include "access/xlog.h"
00021 #include "access/xlog_fn.h"
00022 #include "access/xlog_internal.h"
00023 #include "access/xlogutils.h"
00024 #include "catalog/catalog.h"
00025 #include "catalog/pg_type.h"
00026 #include "funcapi.h"
00027 #include "miscadmin.h"
00028 #include "replication/walreceiver.h"
00029 #include "storage/smgr.h"
00030 #include "utils/builtins.h"
00031 #include "utils/numeric.h"
00032 #include "utils/guc.h"
00033 #include "utils/timestamp.h"
00034 #include "storage/fd.h"
00035
00036 static void validate_xlog_location(char *str);
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 Datum
00049 pg_start_backup(PG_FUNCTION_ARGS)
00050 {
00051 text *backupid = PG_GETARG_TEXT_P(0);
00052 bool fast = PG_GETARG_BOOL(1);
00053 char *backupidstr;
00054 XLogRecPtr startpoint;
00055 char startxlogstr[MAXFNAMELEN];
00056
00057 backupidstr = text_to_cstring(backupid);
00058
00059 startpoint = do_pg_start_backup(backupidstr, fast, NULL, NULL);
00060
00061 snprintf(startxlogstr, sizeof(startxlogstr), "%X/%X",
00062 (uint32) (startpoint >> 32), (uint32) startpoint);
00063 PG_RETURN_TEXT_P(cstring_to_text(startxlogstr));
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 Datum
00080 pg_stop_backup(PG_FUNCTION_ARGS)
00081 {
00082 XLogRecPtr stoppoint;
00083 char stopxlogstr[MAXFNAMELEN];
00084
00085 stoppoint = do_pg_stop_backup(NULL, true, NULL);
00086
00087 snprintf(stopxlogstr, sizeof(stopxlogstr), "%X/%X",
00088 (uint32) (stoppoint >> 32), (uint32) stoppoint);
00089 PG_RETURN_TEXT_P(cstring_to_text(stopxlogstr));
00090 }
00091
00092
00093
00094
00095 Datum
00096 pg_switch_xlog(PG_FUNCTION_ARGS)
00097 {
00098 XLogRecPtr switchpoint;
00099 char location[MAXFNAMELEN];
00100
00101 if (!superuser())
00102 ereport(ERROR,
00103 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00104 (errmsg("must be superuser to switch transaction log files"))));
00105
00106 if (RecoveryInProgress())
00107 ereport(ERROR,
00108 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00109 errmsg("recovery is in progress"),
00110 errhint("WAL control functions cannot be executed during recovery.")));
00111
00112 switchpoint = RequestXLogSwitch();
00113
00114
00115
00116
00117 snprintf(location, sizeof(location), "%X/%X",
00118 (uint32) (switchpoint >> 32), (uint32) switchpoint);
00119 PG_RETURN_TEXT_P(cstring_to_text(location));
00120 }
00121
00122
00123
00124
00125 Datum
00126 pg_create_restore_point(PG_FUNCTION_ARGS)
00127 {
00128 text *restore_name = PG_GETARG_TEXT_P(0);
00129 char *restore_name_str;
00130 XLogRecPtr restorepoint;
00131 char location[MAXFNAMELEN];
00132
00133 if (!superuser())
00134 ereport(ERROR,
00135 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00136 (errmsg("must be superuser to create a restore point"))));
00137
00138 if (RecoveryInProgress())
00139 ereport(ERROR,
00140 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00141 (errmsg("recovery is in progress"),
00142 errhint("WAL control functions cannot be executed during recovery."))));
00143
00144 if (!XLogIsNeeded())
00145 ereport(ERROR,
00146 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00147 errmsg("WAL level not sufficient for creating a restore point"),
00148 errhint("wal_level must be set to \"archive\" or \"hot_standby\" at server start.")));
00149
00150 restore_name_str = text_to_cstring(restore_name);
00151
00152 if (strlen(restore_name_str) >= MAXFNAMELEN)
00153 ereport(ERROR,
00154 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00155 errmsg("value too long for restore point (maximum %d characters)", MAXFNAMELEN - 1)));
00156
00157 restorepoint = XLogRestorePoint(restore_name_str);
00158
00159
00160
00161
00162 snprintf(location, sizeof(location), "%X/%X",
00163 (uint32) (restorepoint >> 32), (uint32) restorepoint);
00164 PG_RETURN_TEXT_P(cstring_to_text(location));
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174 Datum
00175 pg_current_xlog_location(PG_FUNCTION_ARGS)
00176 {
00177 XLogRecPtr current_recptr;
00178 char location[MAXFNAMELEN];
00179
00180 if (RecoveryInProgress())
00181 ereport(ERROR,
00182 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00183 errmsg("recovery is in progress"),
00184 errhint("WAL control functions cannot be executed during recovery.")));
00185
00186 current_recptr = GetXLogWriteRecPtr();
00187
00188 snprintf(location, sizeof(location), "%X/%X",
00189 (uint32) (current_recptr >> 32), (uint32) current_recptr);
00190 PG_RETURN_TEXT_P(cstring_to_text(location));
00191 }
00192
00193
00194
00195
00196
00197
00198 Datum
00199 pg_current_xlog_insert_location(PG_FUNCTION_ARGS)
00200 {
00201 XLogRecPtr current_recptr;
00202 char location[MAXFNAMELEN];
00203
00204 if (RecoveryInProgress())
00205 ereport(ERROR,
00206 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00207 errmsg("recovery is in progress"),
00208 errhint("WAL control functions cannot be executed during recovery.")));
00209
00210 current_recptr = GetXLogInsertRecPtr();
00211
00212 snprintf(location, sizeof(location), "%X/%X",
00213 (uint32) (current_recptr >> 32), (uint32) current_recptr);
00214 PG_RETURN_TEXT_P(cstring_to_text(location));
00215 }
00216
00217
00218
00219
00220
00221
00222
00223 Datum
00224 pg_last_xlog_receive_location(PG_FUNCTION_ARGS)
00225 {
00226 XLogRecPtr recptr;
00227 char location[MAXFNAMELEN];
00228
00229 recptr = GetWalRcvWriteRecPtr(NULL, NULL);
00230
00231 if (recptr == 0)
00232 PG_RETURN_NULL();
00233
00234 snprintf(location, sizeof(location), "%X/%X",
00235 (uint32) (recptr >> 32), (uint32) recptr);
00236 PG_RETURN_TEXT_P(cstring_to_text(location));
00237 }
00238
00239
00240
00241
00242
00243
00244
00245 Datum
00246 pg_last_xlog_replay_location(PG_FUNCTION_ARGS)
00247 {
00248 XLogRecPtr recptr;
00249 char location[MAXFNAMELEN];
00250
00251 recptr = GetXLogReplayRecPtr(NULL);
00252
00253 if (recptr == 0)
00254 PG_RETURN_NULL();
00255
00256 snprintf(location, sizeof(location), "%X/%X",
00257 (uint32) (recptr >> 32), (uint32) recptr);
00258 PG_RETURN_TEXT_P(cstring_to_text(location));
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 Datum
00270 pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
00271 {
00272 text *location = PG_GETARG_TEXT_P(0);
00273 char *locationstr;
00274 uint32 hi,
00275 lo;
00276 XLogSegNo xlogsegno;
00277 uint32 xrecoff;
00278 XLogRecPtr locationpoint;
00279 char xlogfilename[MAXFNAMELEN];
00280 Datum values[2];
00281 bool isnull[2];
00282 TupleDesc resultTupleDesc;
00283 HeapTuple resultHeapTuple;
00284 Datum result;
00285
00286 if (RecoveryInProgress())
00287 ereport(ERROR,
00288 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00289 errmsg("recovery is in progress"),
00290 errhint("pg_xlogfile_name_offset() cannot be executed during recovery.")));
00291
00292
00293
00294
00295 locationstr = text_to_cstring(location);
00296
00297 validate_xlog_location(locationstr);
00298
00299 if (sscanf(locationstr, "%X/%X", &hi, &lo) != 2)
00300 ereport(ERROR,
00301 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00302 errmsg("could not parse transaction log location \"%s\"",
00303 locationstr)));
00304 locationpoint = ((uint64) hi) << 32 | lo;
00305
00306
00307
00308
00309
00310 resultTupleDesc = CreateTemplateTupleDesc(2, false);
00311 TupleDescInitEntry(resultTupleDesc, (AttrNumber) 1, "file_name",
00312 TEXTOID, -1, 0);
00313 TupleDescInitEntry(resultTupleDesc, (AttrNumber) 2, "file_offset",
00314 INT4OID, -1, 0);
00315
00316 resultTupleDesc = BlessTupleDesc(resultTupleDesc);
00317
00318
00319
00320
00321 XLByteToPrevSeg(locationpoint, xlogsegno);
00322 XLogFileName(xlogfilename, ThisTimeLineID, xlogsegno);
00323
00324 values[0] = CStringGetTextDatum(xlogfilename);
00325 isnull[0] = false;
00326
00327
00328
00329
00330 xrecoff = locationpoint % XLogSegSize;
00331
00332 values[1] = UInt32GetDatum(xrecoff);
00333 isnull[1] = false;
00334
00335
00336
00337
00338 resultHeapTuple = heap_form_tuple(resultTupleDesc, values, isnull);
00339
00340 result = HeapTupleGetDatum(resultHeapTuple);
00341
00342 PG_RETURN_DATUM(result);
00343 }
00344
00345
00346
00347
00348
00349 Datum
00350 pg_xlogfile_name(PG_FUNCTION_ARGS)
00351 {
00352 text *location = PG_GETARG_TEXT_P(0);
00353 char *locationstr;
00354 uint32 hi,
00355 lo;
00356 XLogSegNo xlogsegno;
00357 XLogRecPtr locationpoint;
00358 char xlogfilename[MAXFNAMELEN];
00359
00360 if (RecoveryInProgress())
00361 ereport(ERROR,
00362 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00363 errmsg("recovery is in progress"),
00364 errhint("pg_xlogfile_name() cannot be executed during recovery.")));
00365
00366 locationstr = text_to_cstring(location);
00367
00368 validate_xlog_location(locationstr);
00369
00370 if (sscanf(locationstr, "%X/%X", &hi, &lo) != 2)
00371 ereport(ERROR,
00372 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00373 errmsg("could not parse transaction log location \"%s\"",
00374 locationstr)));
00375 locationpoint = ((uint64) hi) << 32 | lo;
00376
00377 XLByteToPrevSeg(locationpoint, xlogsegno);
00378 XLogFileName(xlogfilename, ThisTimeLineID, xlogsegno);
00379
00380 PG_RETURN_TEXT_P(cstring_to_text(xlogfilename));
00381 }
00382
00383
00384
00385
00386 Datum
00387 pg_xlog_replay_pause(PG_FUNCTION_ARGS)
00388 {
00389 if (!superuser())
00390 ereport(ERROR,
00391 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00392 (errmsg("must be superuser to control recovery"))));
00393
00394 if (!RecoveryInProgress())
00395 ereport(ERROR,
00396 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00397 errmsg("recovery is not in progress"),
00398 errhint("Recovery control functions can only be executed during recovery.")));
00399
00400 SetRecoveryPause(true);
00401
00402 PG_RETURN_VOID();
00403 }
00404
00405
00406
00407
00408 Datum
00409 pg_xlog_replay_resume(PG_FUNCTION_ARGS)
00410 {
00411 if (!superuser())
00412 ereport(ERROR,
00413 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00414 (errmsg("must be superuser to control recovery"))));
00415
00416 if (!RecoveryInProgress())
00417 ereport(ERROR,
00418 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00419 errmsg("recovery is not in progress"),
00420 errhint("Recovery control functions can only be executed during recovery.")));
00421
00422 SetRecoveryPause(false);
00423
00424 PG_RETURN_VOID();
00425 }
00426
00427
00428
00429
00430 Datum
00431 pg_is_xlog_replay_paused(PG_FUNCTION_ARGS)
00432 {
00433 if (!superuser())
00434 ereport(ERROR,
00435 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00436 (errmsg("must be superuser to control recovery"))));
00437
00438 if (!RecoveryInProgress())
00439 ereport(ERROR,
00440 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00441 errmsg("recovery is not in progress"),
00442 errhint("Recovery control functions can only be executed during recovery.")));
00443
00444 PG_RETURN_BOOL(RecoveryIsPaused());
00445 }
00446
00447
00448
00449
00450
00451
00452
00453 Datum
00454 pg_last_xact_replay_timestamp(PG_FUNCTION_ARGS)
00455 {
00456 TimestampTz xtime;
00457
00458 xtime = GetLatestXTime();
00459 if (xtime == 0)
00460 PG_RETURN_NULL();
00461
00462 PG_RETURN_TIMESTAMPTZ(xtime);
00463 }
00464
00465
00466
00467
00468 Datum
00469 pg_is_in_recovery(PG_FUNCTION_ARGS)
00470 {
00471 PG_RETURN_BOOL(RecoveryInProgress());
00472 }
00473
00474
00475
00476
00477
00478
00479 static void
00480 validate_xlog_location(char *str)
00481 {
00482 #define MAXLSNCOMPONENT 8
00483
00484 int len1,
00485 len2;
00486
00487 len1 = strspn(str, "0123456789abcdefABCDEF");
00488 if (len1 < 1 || len1 > MAXLSNCOMPONENT || str[len1] != '/')
00489 ereport(ERROR,
00490 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00491 errmsg("invalid input syntax for transaction log location: \"%s\"", str)));
00492
00493 len2 = strspn(str + len1 + 1, "0123456789abcdefABCDEF");
00494 if (len2 < 1 || len2 > MAXLSNCOMPONENT || str[len1 + 1 + len2] != '\0')
00495 ereport(ERROR,
00496 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00497 errmsg("invalid input syntax for transaction log location: \"%s\"", str)));
00498 }
00499
00500
00501
00502
00503 Datum
00504 pg_xlog_location_diff(PG_FUNCTION_ARGS)
00505 {
00506 text *location1 = PG_GETARG_TEXT_P(0);
00507 text *location2 = PG_GETARG_TEXT_P(1);
00508 char *str1,
00509 *str2;
00510 XLogRecPtr loc1,
00511 loc2;
00512 Numeric result;
00513 uint64 bytes1,
00514 bytes2;
00515 uint32 hi,
00516 lo;
00517
00518
00519
00520
00521 str1 = text_to_cstring(location1);
00522 str2 = text_to_cstring(location2);
00523
00524 validate_xlog_location(str1);
00525 validate_xlog_location(str2);
00526
00527 if (sscanf(str1, "%X/%X", &hi, &lo) != 2)
00528 ereport(ERROR,
00529 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00530 errmsg("could not parse transaction log location \"%s\"", str1)));
00531 loc1 = ((uint64) hi) << 32 | lo;
00532
00533 if (sscanf(str2, "%X/%X", &hi, &lo) != 2)
00534 ereport(ERROR,
00535 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00536 errmsg("could not parse transaction log location \"%s\"", str2)));
00537 loc2 = ((uint64) hi) << 32 | lo;
00538
00539 bytes1 = (uint64) loc1;
00540 bytes2 = (uint64) loc2;
00541
00542
00543
00544
00545
00546
00547 result = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
00548 DirectFunctionCall1(int8_numeric, Int64GetDatum((int64) bytes1)),
00549 DirectFunctionCall1(int8_numeric, Int64GetDatum((int64) bytes2))));
00550
00551 PG_RETURN_NUMERIC(result);
00552 }
00553
00554
00555
00556
00557 Datum
00558 pg_is_in_backup(PG_FUNCTION_ARGS)
00559 {
00560 PG_RETURN_BOOL(BackupInProgress());
00561 }
00562
00563
00564
00565
00566
00567
00568
00569 Datum
00570 pg_backup_start_time(PG_FUNCTION_ARGS)
00571 {
00572 Datum xtime;
00573 FILE *lfp;
00574 char fline[MAXPGPATH];
00575 char backup_start_time[30];
00576
00577
00578
00579
00580 lfp = AllocateFile(BACKUP_LABEL_FILE, "r");
00581 if (lfp == NULL)
00582 {
00583 if (errno != ENOENT)
00584 ereport(ERROR,
00585 (errcode_for_file_access(),
00586 errmsg("could not read file \"%s\": %m",
00587 BACKUP_LABEL_FILE)));
00588 PG_RETURN_NULL();
00589 }
00590
00591
00592
00593
00594 backup_start_time[0] = '\0';
00595 while (fgets(fline, sizeof(fline), lfp) != NULL)
00596 {
00597 if (sscanf(fline, "START TIME: %25[^\n]\n", backup_start_time) == 1)
00598 break;
00599 }
00600
00601
00602 if (ferror(lfp))
00603 ereport(ERROR,
00604 (errcode_for_file_access(),
00605 errmsg("could not read file \"%s\": %m", BACKUP_LABEL_FILE)));
00606
00607
00608 if (FreeFile(lfp))
00609 ereport(ERROR,
00610 (errcode_for_file_access(),
00611 errmsg("could not close file \"%s\": %m", BACKUP_LABEL_FILE)));
00612
00613 if (strlen(backup_start_time) == 0)
00614 ereport(ERROR,
00615 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00616 errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
00617
00618
00619
00620
00621 xtime = DirectFunctionCall3(timestamptz_in,
00622 CStringGetDatum(backup_start_time),
00623 ObjectIdGetDatum(InvalidOid),
00624 Int32GetDatum(-1));
00625
00626 PG_RETURN_DATUM(xtime);
00627 }