Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
a030bfa6
Commit
a030bfa6
authored
Nov 04, 2011
by
Simon Riggs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move user functions related to WAL into xlogfuncs.c
parent
e145891c
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
499 additions
and
446 deletions
+499
-446
src/backend/access/transam/Makefile
src/backend/access/transam/Makefile
+2
-1
src/backend/access/transam/xlog.c
src/backend/access/transam/xlog.c
+25
-445
src/backend/access/transam/xlogfuncs.c
src/backend/access/transam/xlogfuncs.c
+467
-0
src/include/access/xlog.h
src/include/access/xlog.h
+5
-0
No files found.
src/backend/access/transam/Makefile
View file @
a030bfa6
...
...
@@ -12,7 +12,8 @@ subdir = src/backend/access/transam
top_builddir
=
../../../..
include
$(top_builddir)/src/Makefile.global
OBJS
=
clog.o transam.o varsup.o xact.o xlog.o xlogutils.o rmgr.o slru.o subtrans.o multixact.o twophase.o twophase_rmgr.o
OBJS
=
clog.o transam.o varsup.o xact.o rmgr.o slru.o subtrans.o multixact.o
\
twophase.o twophase_rmgr.o xlog.o xlogfuncs.o xlogutils.o
include
$(top_srcdir)/src/backend/common.mk
...
...
src/backend/access/transam/xlog.c
View file @
a030bfa6
...
...
@@ -35,8 +35,6 @@
#include "catalog/catversion.h"
#include "catalog/pg_control.h"
#include "catalog/pg_database.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "pgstat.h"
...
...
@@ -596,10 +594,7 @@ static void exitArchiveRecovery(TimeLineID endTLI,
uint32
endLogId
,
uint32
endLogSeg
);
static
bool
recoveryStopsHere
(
XLogRecord
*
record
,
bool
*
includeThis
);
static
void
recoveryPausesHere
(
void
);
static
bool
RecoveryIsPaused
(
void
);
static
void
SetRecoveryPause
(
bool
recoveryPause
);
static
void
SetLatestXTime
(
TimestampTz
xtime
);
static
TimestampTz
GetLatestXTime
(
void
);
static
void
CheckRequiredParameterValues
(
void
);
static
void
XLogReportParameters
(
void
);
static
void
LocalSetXLogInsertAllowed
(
void
);
...
...
@@ -5762,7 +5757,7 @@ recoveryPausesHere(void)
}
}
static
bool
bool
RecoveryIsPaused
(
void
)
{
/* use volatile pointer to prevent code rearrangement */
...
...
@@ -5776,7 +5771,7 @@ RecoveryIsPaused(void)
return
recoveryPause
;
}
static
void
void
SetRecoveryPause
(
bool
recoveryPause
)
{
/* use volatile pointer to prevent code rearrangement */
...
...
@@ -5787,70 +5782,6 @@ SetRecoveryPause(bool recoveryPause)
SpinLockRelease
(
&
xlogctl
->
info_lck
);
}
/*
* pg_xlog_replay_pause - pause recovery now
*/
Datum
pg_xlog_replay_pause
(
PG_FUNCTION_ARGS
)
{
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"must be superuser to control recovery"
))));
if
(
!
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is not in progress"
),
errhint
(
"Recovery control functions can only be executed during recovery."
)));
SetRecoveryPause
(
true
);
PG_RETURN_VOID
();
}
/*
* pg_xlog_replay_resume - resume recovery now
*/
Datum
pg_xlog_replay_resume
(
PG_FUNCTION_ARGS
)
{
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"must be superuser to control recovery"
))));
if
(
!
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is not in progress"
),
errhint
(
"Recovery control functions can only be executed during recovery."
)));
SetRecoveryPause
(
false
);
PG_RETURN_VOID
();
}
/*
* pg_is_xlog_replay_paused
*/
Datum
pg_is_xlog_replay_paused
(
PG_FUNCTION_ARGS
)
{
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"must be superuser to control recovery"
))));
if
(
!
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is not in progress"
),
errhint
(
"Recovery control functions can only be executed during recovery."
)));
PG_RETURN_BOOL
(
RecoveryIsPaused
());
}
/*
* Save timestamp of latest processed commit/abort record.
*
...
...
@@ -5872,7 +5803,7 @@ SetLatestXTime(TimestampTz xtime)
/*
* Fetch timestamp of latest processed commit/abort record.
*/
static
TimestampTz
TimestampTz
GetLatestXTime
(
void
)
{
/* use volatile pointer to prevent code rearrangement */
...
...
@@ -5886,33 +5817,6 @@ GetLatestXTime(void)
return
xtime
;
}
/*
* Returns timestamp of latest processed commit/abort record.
*
* When the server has been started normally without recovery the function
* returns NULL.
*/
Datum
pg_last_xact_replay_timestamp
(
PG_FUNCTION_ARGS
)
{
TimestampTz
xtime
;
xtime
=
GetLatestXTime
();
if
(
xtime
==
0
)
PG_RETURN_NULL
();
PG_RETURN_TIMESTAMPTZ
(
xtime
);
}
/*
* Returns bool with current recovery mode, a global state.
*/
Datum
pg_is_in_recovery
(
PG_FUNCTION_ARGS
)
{
PG_RETURN_BOOL
(
RecoveryInProgress
());
}
/*
* Returns time of receipt of current chunk of XLOG data, as well as
* whether it was received from streaming replication or from archives.
...
...
@@ -8835,34 +8739,6 @@ issue_xlog_fsync(int fd, uint32 log, uint32 seg)
}
}
/*
* pg_start_backup: set up for taking an on-line backup dump
*
* Essentially what this does is to create a backup label file in $PGDATA,
* where it will be archived as part of the backup dump. The label file
* contains the user-supplied label string (typically this would be used
* to tell where the backup dump will be stored) and the starting time and
* starting WAL location for the dump.
*/
Datum
pg_start_backup
(
PG_FUNCTION_ARGS
)
{
text
*
backupid
=
PG_GETARG_TEXT_P
(
0
);
bool
fast
=
PG_GETARG_BOOL
(
1
);
char
*
backupidstr
;
XLogRecPtr
startpoint
;
char
startxlogstr
[
MAXFNAMELEN
];
backupidstr
=
text_to_cstring
(
backupid
);
startpoint
=
do_pg_start_backup
(
backupidstr
,
fast
,
NULL
);
snprintf
(
startxlogstr
,
sizeof
(
startxlogstr
),
"%X/%X"
,
startpoint
.
xlogid
,
startpoint
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
startxlogstr
));
}
/*
* do_pg_start_backup is the workhorse of the user-visible pg_start_backup()
* function. It creates the necessary starting checkpoint and constructs the
...
...
@@ -9122,32 +8998,6 @@ pg_start_backup_callback(int code, Datum arg)
LWLockRelease
(
WALInsertLock
);
}
/*
* pg_stop_backup: finish taking an on-line backup dump
*
* We write an end-of-backup WAL record, and remove the backup label file
* created by pg_start_backup, creating a backup history file in pg_xlog
* instead (whence it will immediately be archived). The backup history file
* contains the same info found in the label file, plus the backup-end time
* and WAL location. Before 9.0, the backup-end time was read from the backup
* history file at the beginning of archive recovery, but we now use the WAL
* record for that and the file is for informational and debug purposes only.
*
* Note: different from CancelBackup which just cancels online backup mode.
*/
Datum
pg_stop_backup
(
PG_FUNCTION_ARGS
)
{
XLogRecPtr
stoppoint
;
char
stopxlogstr
[
MAXFNAMELEN
];
stoppoint
=
do_pg_stop_backup
(
NULL
,
true
);
snprintf
(
stopxlogstr
,
sizeof
(
stopxlogstr
),
"%X/%X"
,
stoppoint
.
xlogid
,
stoppoint
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
stopxlogstr
));
}
/*
* do_pg_stop_backup is the workhorse of the user-visible pg_stop_backup()
* function.
...
...
@@ -9433,166 +9283,6 @@ do_pg_abort_backup(void)
LWLockRelease
(
WALInsertLock
);
}
/*
* pg_switch_xlog: switch to next xlog file
*/
Datum
pg_switch_xlog
(
PG_FUNCTION_ARGS
)
{
XLogRecPtr
switchpoint
;
char
location
[
MAXFNAMELEN
];
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"must be superuser to switch transaction log files"
))));
if
(
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is in progress"
),
errhint
(
"WAL control functions cannot be executed during recovery."
)));
switchpoint
=
RequestXLogSwitch
();
/*
* As a convenience, return the WAL location of the switch record
*/
snprintf
(
location
,
sizeof
(
location
),
"%X/%X"
,
switchpoint
.
xlogid
,
switchpoint
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
location
));
}
/*
* pg_create_restore_point: a named point for restore
*/
Datum
pg_create_restore_point
(
PG_FUNCTION_ARGS
)
{
text
*
restore_name
=
PG_GETARG_TEXT_P
(
0
);
char
*
restore_name_str
;
XLogRecPtr
restorepoint
;
char
location
[
MAXFNAMELEN
];
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"must be superuser to create a restore point"
))));
if
(
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
(
errmsg
(
"recovery is in progress"
),
errhint
(
"WAL control functions cannot be executed during recovery."
))));
if
(
!
XLogIsNeeded
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"WAL level not sufficient for creating a restore point"
),
errhint
(
"wal_level must be set to
\"
archive
\"
or
\"
hot_standby
\"
at server start."
)));
restore_name_str
=
text_to_cstring
(
restore_name
);
if
(
strlen
(
restore_name_str
)
>=
MAXFNAMELEN
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"value too long for restore point (maximum %d characters)"
,
MAXFNAMELEN
-
1
)));
restorepoint
=
XLogRestorePoint
(
restore_name_str
);
/*
* As a convenience, return the WAL location of the restore point record
*/
snprintf
(
location
,
sizeof
(
location
),
"%X/%X"
,
restorepoint
.
xlogid
,
restorepoint
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
location
));
}
/*
* Report the current WAL write location (same format as pg_start_backup etc)
*
* This is useful for determining how much of WAL is visible to an external
* archiving process. Note that the data before this point is written out
* to the kernel, but is not necessarily synced to disk.
*/
Datum
pg_current_xlog_location
(
PG_FUNCTION_ARGS
)
{
char
location
[
MAXFNAMELEN
];
if
(
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is in progress"
),
errhint
(
"WAL control functions cannot be executed during recovery."
)));
/* Make sure we have an up-to-date local LogwrtResult */
{
/* use volatile pointer to prevent code rearrangement */
volatile
XLogCtlData
*
xlogctl
=
XLogCtl
;
SpinLockAcquire
(
&
xlogctl
->
info_lck
);
LogwrtResult
=
xlogctl
->
LogwrtResult
;
SpinLockRelease
(
&
xlogctl
->
info_lck
);
}
snprintf
(
location
,
sizeof
(
location
),
"%X/%X"
,
LogwrtResult
.
Write
.
xlogid
,
LogwrtResult
.
Write
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
location
));
}
/*
* Report the current WAL insert location (same format as pg_start_backup etc)
*
* This function is mostly for debugging purposes.
*/
Datum
pg_current_xlog_insert_location
(
PG_FUNCTION_ARGS
)
{
XLogCtlInsert
*
Insert
=
&
XLogCtl
->
Insert
;
XLogRecPtr
current_recptr
;
char
location
[
MAXFNAMELEN
];
if
(
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is in progress"
),
errhint
(
"WAL control functions cannot be executed during recovery."
)));
/*
* Get the current end-of-WAL position ... shared lock is sufficient
*/
LWLockAcquire
(
WALInsertLock
,
LW_SHARED
);
INSERT_RECPTR
(
current_recptr
,
Insert
,
Insert
->
curridx
);
LWLockRelease
(
WALInsertLock
);
snprintf
(
location
,
sizeof
(
location
),
"%X/%X"
,
current_recptr
.
xlogid
,
current_recptr
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
location
));
}
/*
* Report the last WAL receive location (same format as pg_start_backup etc)
*
* This is useful for determining how much of WAL is guaranteed to be received
* and synced to disk by walreceiver.
*/
Datum
pg_last_xlog_receive_location
(
PG_FUNCTION_ARGS
)
{
XLogRecPtr
recptr
;
char
location
[
MAXFNAMELEN
];
recptr
=
GetWalRcvWriteRecPtr
(
NULL
);
if
(
recptr
.
xlogid
==
0
&&
recptr
.
xrecoff
==
0
)
PG_RETURN_NULL
();
snprintf
(
location
,
sizeof
(
location
),
"%X/%X"
,
recptr
.
xlogid
,
recptr
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
location
));
}
/*
* Get latest redo apply position.
*
...
...
@@ -9639,149 +9329,39 @@ GetStandbyFlushRecPtr(void)
}
/*
* Report the last WAL replay location (same format as pg_start_backup etc)
*
* This is useful for determining how much of WAL is visible to read-only
* connections during recovery.
*/
Datum
pg_last_xlog_replay_location
(
PG_FUNCTION_ARGS
)
{
XLogRecPtr
recptr
;
char
location
[
MAXFNAMELEN
];
recptr
=
GetXLogReplayRecPtr
(
NULL
);
if
(
recptr
.
xlogid
==
0
&&
recptr
.
xrecoff
==
0
)
PG_RETURN_NULL
();
snprintf
(
location
,
sizeof
(
location
),
"%X/%X"
,
recptr
.
xlogid
,
recptr
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
location
));
}
/*
* Compute an xlog file name and decimal byte offset given a WAL location,
* such as is returned by pg_stop_backup() or pg_xlog_switch().
*
* Note that a location exactly at a segment boundary is taken to be in
* the previous segment. This is usually the right thing, since the
* expected usage is to determine which xlog file(s) are ready to archive.
* Get latest WAL insert pointer
*/
Datum
pg_xlogfile_name_offset
(
PG_FUNCTION_ARGS
)
XLogRecPtr
GetXLogInsertRecPtr
(
bool
needlock
)
{
text
*
location
=
PG_GETARG_TEXT_P
(
0
);
char
*
locationstr
;
unsigned
int
uxlogid
;
unsigned
int
uxrecoff
;
uint32
xlogid
;
uint32
xlogseg
;
uint32
xrecoff
;
XLogRecPtr
locationpoint
;
char
xlogfilename
[
MAXFNAMELEN
];
Datum
values
[
2
];
bool
isnull
[
2
];
TupleDesc
resultTupleDesc
;
HeapTuple
resultHeapTuple
;
Datum
result
;
if
(
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is in progress"
),
errhint
(
"pg_xlogfile_name_offset() cannot be executed during recovery."
)));
/*
* Read input and parse
*/
locationstr
=
text_to_cstring
(
location
);
if
(
sscanf
(
locationstr
,
"%X/%X"
,
&
uxlogid
,
&
uxrecoff
)
!=
2
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"could not parse transaction log location
\"
%s
\"
"
,
locationstr
)));
locationpoint
.
xlogid
=
uxlogid
;
locationpoint
.
xrecoff
=
uxrecoff
;
/*
* Construct a tuple descriptor for the result row. This must match this
* function's pg_proc entry!
*/
resultTupleDesc
=
CreateTemplateTupleDesc
(
2
,
false
);
TupleDescInitEntry
(
resultTupleDesc
,
(
AttrNumber
)
1
,
"file_name"
,
TEXTOID
,
-
1
,
0
);
TupleDescInitEntry
(
resultTupleDesc
,
(
AttrNumber
)
2
,
"file_offset"
,
INT4OID
,
-
1
,
0
);
resultTupleDesc
=
BlessTupleDesc
(
resultTupleDesc
);
/*
* xlogfilename
*/
XLByteToPrevSeg
(
locationpoint
,
xlogid
,
xlogseg
);
XLogFileName
(
xlogfilename
,
ThisTimeLineID
,
xlogid
,
xlogseg
);
values
[
0
]
=
CStringGetTextDatum
(
xlogfilename
);
isnull
[
0
]
=
false
;
/*
* offset
*/
xrecoff
=
locationpoint
.
xrecoff
-
xlogseg
*
XLogSegSize
;
values
[
1
]
=
UInt32GetDatum
(
xrecoff
);
isnull
[
1
]
=
false
;
/*
* Tuple jam: Having first prepared your Datums, then squash together
*/
resultHeapTuple
=
heap_form_tuple
(
resultTupleDesc
,
values
,
isnull
);
XLogCtlInsert
*
Insert
=
&
XLogCtl
->
Insert
;
XLogRecPtr
current_recptr
;
result
=
HeapTupleGetDatum
(
resultHeapTuple
);
if
(
needlock
)
LWLockAcquire
(
WALInsertLock
,
LW_SHARED
);
INSERT_RECPTR
(
current_recptr
,
Insert
,
Insert
->
curridx
);
if
(
needlock
)
LWLockRelease
(
WALInsertLock
);
PG_RETURN_DATUM
(
result
)
;
return
current_recptr
;
}
/*
* Compute an xlog file name given a WAL location,
* such as is returned by pg_stop_backup() or pg_xlog_switch().
* Get latest WAL write pointer
*/
Datum
pg_xlogfile_name
(
PG_FUNCTION_ARGS
)
XLogRecPtr
GetXLogWriteRecPtr
(
void
)
{
text
*
location
=
PG_GETARG_TEXT_P
(
0
);
char
*
locationstr
;
unsigned
int
uxlogid
;
unsigned
int
uxrecoff
;
uint32
xlogid
;
uint32
xlogseg
;
XLogRecPtr
locationpoint
;
char
xlogfilename
[
MAXFNAMELEN
];
if
(
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is in progress"
),
errhint
(
"pg_xlogfile_name() cannot be executed during recovery."
)));
locationstr
=
text_to_cstring
(
location
);
if
(
sscanf
(
locationstr
,
"%X/%X"
,
&
uxlogid
,
&
uxrecoff
)
!=
2
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"could not parse transaction log location
\"
%s
\"
"
,
locationstr
)));
locationpoint
.
xlogid
=
uxlogid
;
locationpoint
.
xrecoff
=
uxrecoff
;
{
/* use volatile pointer to prevent code rearrangement */
volatile
XLogCtlData
*
xlogctl
=
XLogCtl
;
XLByteToPrevSeg
(
locationpoint
,
xlogid
,
xlogseg
);
XLogFileName
(
xlogfilename
,
ThisTimeLineID
,
xlogid
,
xlogseg
);
SpinLockAcquire
(
&
xlogctl
->
info_lck
);
LogwrtResult
=
xlogctl
->
LogwrtResult
;
SpinLockRelease
(
&
xlogctl
->
info_lck
);
}
PG_RETURN_TEXT_P
(
cstring_to_text
(
xlogfilename
))
;
return
LogwrtResult
.
Write
;
}
/*
...
...
src/backend/access/transam/xlogfuncs.c
0 → 100644
View file @
a030bfa6
/*-------------------------------------------------------------------------
*
* xlogfuncs.c
*
* PostgreSQL transaction log manager user interface functions
*
* This file contains WAL control and information functions.
*
*
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/access/transam/xlogfuncs.c
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "access/xlogutils.h"
#include "catalog/catalog.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "replication/walreceiver.h"
#include "storage/smgr.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/timestamp.h"
/*
* pg_start_backup: set up for taking an on-line backup dump
*
* Essentially what this does is to create a backup label file in $PGDATA,
* where it will be archived as part of the backup dump. The label file
* contains the user-supplied label string (typically this would be used
* to tell where the backup dump will be stored) and the starting time and
* starting WAL location for the dump.
*/
Datum
pg_start_backup
(
PG_FUNCTION_ARGS
)
{
text
*
backupid
=
PG_GETARG_TEXT_P
(
0
);
bool
fast
=
PG_GETARG_BOOL
(
1
);
char
*
backupidstr
;
XLogRecPtr
startpoint
;
char
startxlogstr
[
MAXFNAMELEN
];
backupidstr
=
text_to_cstring
(
backupid
);
startpoint
=
do_pg_start_backup
(
backupidstr
,
fast
,
NULL
);
snprintf
(
startxlogstr
,
sizeof
(
startxlogstr
),
"%X/%X"
,
startpoint
.
xlogid
,
startpoint
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
startxlogstr
));
}
/*
* pg_stop_backup: finish taking an on-line backup dump
*
* We write an end-of-backup WAL record, and remove the backup label file
* created by pg_start_backup, creating a backup history file in pg_xlog
* instead (whence it will immediately be archived). The backup history file
* contains the same info found in the label file, plus the backup-end time
* and WAL location. Before 9.0, the backup-end time was read from the backup
* history file at the beginning of archive recovery, but we now use the WAL
* record for that and the file is for informational and debug purposes only.
*
* Note: different from CancelBackup which just cancels online backup mode.
*/
Datum
pg_stop_backup
(
PG_FUNCTION_ARGS
)
{
XLogRecPtr
stoppoint
;
char
stopxlogstr
[
MAXFNAMELEN
];
stoppoint
=
do_pg_stop_backup
(
NULL
,
true
);
snprintf
(
stopxlogstr
,
sizeof
(
stopxlogstr
),
"%X/%X"
,
stoppoint
.
xlogid
,
stoppoint
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
stopxlogstr
));
}
/*
* pg_switch_xlog: switch to next xlog file
*/
Datum
pg_switch_xlog
(
PG_FUNCTION_ARGS
)
{
XLogRecPtr
switchpoint
;
char
location
[
MAXFNAMELEN
];
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"must be superuser to switch transaction log files"
))));
if
(
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is in progress"
),
errhint
(
"WAL control functions cannot be executed during recovery."
)));
switchpoint
=
RequestXLogSwitch
();
/*
* As a convenience, return the WAL location of the switch record
*/
snprintf
(
location
,
sizeof
(
location
),
"%X/%X"
,
switchpoint
.
xlogid
,
switchpoint
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
location
));
}
/*
* pg_create_restore_point: a named point for restore
*/
Datum
pg_create_restore_point
(
PG_FUNCTION_ARGS
)
{
text
*
restore_name
=
PG_GETARG_TEXT_P
(
0
);
char
*
restore_name_str
;
XLogRecPtr
restorepoint
;
char
location
[
MAXFNAMELEN
];
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"must be superuser to create a restore point"
))));
if
(
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
(
errmsg
(
"recovery is in progress"
),
errhint
(
"WAL control functions cannot be executed during recovery."
))));
if
(
!
XLogIsNeeded
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"WAL level not sufficient for creating a restore point"
),
errhint
(
"wal_level must be set to
\"
archive
\"
or
\"
hot_standby
\"
at server start."
)));
restore_name_str
=
text_to_cstring
(
restore_name
);
if
(
strlen
(
restore_name_str
)
>=
MAXFNAMELEN
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"value too long for restore point (maximum %d characters)"
,
MAXFNAMELEN
-
1
)));
restorepoint
=
XLogRestorePoint
(
restore_name_str
);
/*
* As a convenience, return the WAL location of the restore point record
*/
snprintf
(
location
,
sizeof
(
location
),
"%X/%X"
,
restorepoint
.
xlogid
,
restorepoint
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
location
));
}
/*
* Report the current WAL write location (same format as pg_start_backup etc)
*
* This is useful for determining how much of WAL is visible to an external
* archiving process. Note that the data before this point is written out
* to the kernel, but is not necessarily synced to disk.
*/
Datum
pg_current_xlog_location
(
PG_FUNCTION_ARGS
)
{
XLogRecPtr
current_recptr
;
char
location
[
MAXFNAMELEN
];
if
(
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is in progress"
),
errhint
(
"WAL control functions cannot be executed during recovery."
)));
current_recptr
=
GetXLogWriteRecPtr
();
snprintf
(
location
,
sizeof
(
location
),
"%X/%X"
,
current_recptr
.
xlogid
,
current_recptr
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
location
));
}
/*
* Report the current WAL insert location (same format as pg_start_backup etc)
*
* This function is mostly for debugging purposes.
*/
Datum
pg_current_xlog_insert_location
(
PG_FUNCTION_ARGS
)
{
XLogRecPtr
current_recptr
;
char
location
[
MAXFNAMELEN
];
if
(
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is in progress"
),
errhint
(
"WAL control functions cannot be executed during recovery."
)));
current_recptr
=
GetXLogInsertRecPtr
(
true
);
snprintf
(
location
,
sizeof
(
location
),
"%X/%X"
,
current_recptr
.
xlogid
,
current_recptr
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
location
));
}
/*
* Report the last WAL receive location (same format as pg_start_backup etc)
*
* This is useful for determining how much of WAL is guaranteed to be received
* and synced to disk by walreceiver.
*/
Datum
pg_last_xlog_receive_location
(
PG_FUNCTION_ARGS
)
{
XLogRecPtr
recptr
;
char
location
[
MAXFNAMELEN
];
recptr
=
GetWalRcvWriteRecPtr
(
NULL
);
if
(
recptr
.
xlogid
==
0
&&
recptr
.
xrecoff
==
0
)
PG_RETURN_NULL
();
snprintf
(
location
,
sizeof
(
location
),
"%X/%X"
,
recptr
.
xlogid
,
recptr
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
location
));
}
/*
* Report the last WAL replay location (same format as pg_start_backup etc)
*
* This is useful for determining how much of WAL is visible to read-only
* connections during recovery.
*/
Datum
pg_last_xlog_replay_location
(
PG_FUNCTION_ARGS
)
{
XLogRecPtr
recptr
;
char
location
[
MAXFNAMELEN
];
recptr
=
GetXLogReplayRecPtr
(
NULL
);
if
(
recptr
.
xlogid
==
0
&&
recptr
.
xrecoff
==
0
)
PG_RETURN_NULL
();
snprintf
(
location
,
sizeof
(
location
),
"%X/%X"
,
recptr
.
xlogid
,
recptr
.
xrecoff
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
location
));
}
/*
* Compute an xlog file name and decimal byte offset given a WAL location,
* such as is returned by pg_stop_backup() or pg_xlog_switch().
*
* Note that a location exactly at a segment boundary is taken to be in
* the previous segment. This is usually the right thing, since the
* expected usage is to determine which xlog file(s) are ready to archive.
*/
Datum
pg_xlogfile_name_offset
(
PG_FUNCTION_ARGS
)
{
text
*
location
=
PG_GETARG_TEXT_P
(
0
);
char
*
locationstr
;
unsigned
int
uxlogid
;
unsigned
int
uxrecoff
;
uint32
xlogid
;
uint32
xlogseg
;
uint32
xrecoff
;
XLogRecPtr
locationpoint
;
char
xlogfilename
[
MAXFNAMELEN
];
Datum
values
[
2
];
bool
isnull
[
2
];
TupleDesc
resultTupleDesc
;
HeapTuple
resultHeapTuple
;
Datum
result
;
if
(
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is in progress"
),
errhint
(
"pg_xlogfile_name_offset() cannot be executed during recovery."
)));
/*
* Read input and parse
*/
locationstr
=
text_to_cstring
(
location
);
if
(
sscanf
(
locationstr
,
"%X/%X"
,
&
uxlogid
,
&
uxrecoff
)
!=
2
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"could not parse transaction log location
\"
%s
\"
"
,
locationstr
)));
locationpoint
.
xlogid
=
uxlogid
;
locationpoint
.
xrecoff
=
uxrecoff
;
/*
* Construct a tuple descriptor for the result row. This must match this
* function's pg_proc entry!
*/
resultTupleDesc
=
CreateTemplateTupleDesc
(
2
,
false
);
TupleDescInitEntry
(
resultTupleDesc
,
(
AttrNumber
)
1
,
"file_name"
,
TEXTOID
,
-
1
,
0
);
TupleDescInitEntry
(
resultTupleDesc
,
(
AttrNumber
)
2
,
"file_offset"
,
INT4OID
,
-
1
,
0
);
resultTupleDesc
=
BlessTupleDesc
(
resultTupleDesc
);
/*
* xlogfilename
*/
XLByteToPrevSeg
(
locationpoint
,
xlogid
,
xlogseg
);
XLogFileName
(
xlogfilename
,
ThisTimeLineID
,
xlogid
,
xlogseg
);
values
[
0
]
=
CStringGetTextDatum
(
xlogfilename
);
isnull
[
0
]
=
false
;
/*
* offset
*/
xrecoff
=
locationpoint
.
xrecoff
-
xlogseg
*
XLogSegSize
;
values
[
1
]
=
UInt32GetDatum
(
xrecoff
);
isnull
[
1
]
=
false
;
/*
* Tuple jam: Having first prepared your Datums, then squash together
*/
resultHeapTuple
=
heap_form_tuple
(
resultTupleDesc
,
values
,
isnull
);
result
=
HeapTupleGetDatum
(
resultHeapTuple
);
PG_RETURN_DATUM
(
result
);
}
/*
* Compute an xlog file name given a WAL location,
* such as is returned by pg_stop_backup() or pg_xlog_switch().
*/
Datum
pg_xlogfile_name
(
PG_FUNCTION_ARGS
)
{
text
*
location
=
PG_GETARG_TEXT_P
(
0
);
char
*
locationstr
;
unsigned
int
uxlogid
;
unsigned
int
uxrecoff
;
uint32
xlogid
;
uint32
xlogseg
;
XLogRecPtr
locationpoint
;
char
xlogfilename
[
MAXFNAMELEN
];
if
(
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is in progress"
),
errhint
(
"pg_xlogfile_name() cannot be executed during recovery."
)));
locationstr
=
text_to_cstring
(
location
);
if
(
sscanf
(
locationstr
,
"%X/%X"
,
&
uxlogid
,
&
uxrecoff
)
!=
2
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"could not parse transaction log location
\"
%s
\"
"
,
locationstr
)));
locationpoint
.
xlogid
=
uxlogid
;
locationpoint
.
xrecoff
=
uxrecoff
;
XLByteToPrevSeg
(
locationpoint
,
xlogid
,
xlogseg
);
XLogFileName
(
xlogfilename
,
ThisTimeLineID
,
xlogid
,
xlogseg
);
PG_RETURN_TEXT_P
(
cstring_to_text
(
xlogfilename
));
}
/*
* pg_xlog_replay_pause - pause recovery now
*/
Datum
pg_xlog_replay_pause
(
PG_FUNCTION_ARGS
)
{
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"must be superuser to control recovery"
))));
if
(
!
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is not in progress"
),
errhint
(
"Recovery control functions can only be executed during recovery."
)));
SetRecoveryPause
(
true
);
PG_RETURN_VOID
();
}
/*
* pg_xlog_replay_resume - resume recovery now
*/
Datum
pg_xlog_replay_resume
(
PG_FUNCTION_ARGS
)
{
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"must be superuser to control recovery"
))));
if
(
!
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is not in progress"
),
errhint
(
"Recovery control functions can only be executed during recovery."
)));
SetRecoveryPause
(
false
);
PG_RETURN_VOID
();
}
/*
* pg_is_xlog_replay_paused
*/
Datum
pg_is_xlog_replay_paused
(
PG_FUNCTION_ARGS
)
{
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"must be superuser to control recovery"
))));
if
(
!
RecoveryInProgress
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE
),
errmsg
(
"recovery is not in progress"
),
errhint
(
"Recovery control functions can only be executed during recovery."
)));
PG_RETURN_BOOL
(
RecoveryIsPaused
());
}
/*
* Returns timestamp of latest processed commit/abort record.
*
* When the server has been started normally without recovery the function
* returns NULL.
*/
Datum
pg_last_xact_replay_timestamp
(
PG_FUNCTION_ARGS
)
{
TimestampTz
xtime
;
xtime
=
GetLatestXTime
();
if
(
xtime
==
0
)
PG_RETURN_NULL
();
PG_RETURN_TIMESTAMPTZ
(
xtime
);
}
/*
* Returns bool with current recovery mode, a global state.
*/
Datum
pg_is_in_recovery
(
PG_FUNCTION_ARGS
)
{
PG_RETURN_BOOL
(
RecoveryInProgress
());
}
src/include/access/xlog.h
View file @
a030bfa6
...
...
@@ -293,6 +293,11 @@ extern bool XLogInsertAllowed(void);
extern
void
GetXLogReceiptTime
(
TimestampTz
*
rtime
,
bool
*
fromStream
);
extern
XLogRecPtr
GetXLogReplayRecPtr
(
XLogRecPtr
*
restoreLastRecPtr
);
extern
XLogRecPtr
GetStandbyFlushRecPtr
(
void
);
extern
XLogRecPtr
GetXLogInsertRecPtr
(
bool
needlock
);
extern
XLogRecPtr
GetXLogWriteRecPtr
(
void
);
extern
bool
RecoveryIsPaused
(
void
);
extern
void
SetRecoveryPause
(
bool
recoveryPause
);
extern
TimestampTz
GetLatestXTime
(
void
);
extern
void
UpdateControlFile
(
void
);
extern
uint64
GetSystemIdentifier
(
void
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment