Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit308d00b

Browse files
author
Michael Paquier
committed
Obtain timeline ID with control file and not XLOG system function
The system function used up to now was pg_xlogfile_name_offset, whichcannot be used on a node in recovery, and it was the only way presentto fetch the timeline ID of a backup, either incremental or full. Soinstead scan the control file of server and fetch the timeline fromthat. This also removes the restriction on which a backup could notbe taken on a standby node. The next step being to have the possibilityto take backups from streams.
1 parenta31fdbd commit308d00b

File tree

4 files changed

+161
-17
lines changed

4 files changed

+161
-17
lines changed

‎Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ SRCS = \
55
data.c\
66
delete.c\
77
dir.c\
8+
fetch.c\
89
init.c\
910
parray.c\
1011
pg_rman.c\

‎backup.c

Lines changed: 79 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include<dirent.h>
1818
#include<time.h>
1919

20+
#include"catalog/pg_control.h"
2021
#include"libpq/pqsignal.h"
2122
#include"pgut/pgut-port.h"
2223

@@ -48,7 +49,7 @@ static void confirm_block_size(const char *name, int blcksz);
4849
staticvoidpg_start_backup(constchar*label,boolsmooth,pgBackup*backup);
4950
staticvoidpg_stop_backup(pgBackup*backup);
5051
staticvoidpg_switch_xlog(pgBackup*backup);
51-
staticvoidget_lsn(PGresult*res,TimeLineID*timeline,XLogRecPtr*lsn);
52+
staticvoidget_lsn(PGresult*res,XLogRecPtr*lsn);
5253
staticvoidget_xid(PGresult*res,uint32*xid);
5354
staticboolexecute_restartpoint(pgBackupOptionbkupopt);
5455

@@ -60,6 +61,7 @@ static bool dirExists(const char *path);
6061
staticvoidadd_files(parray*files,constchar*root,booladd_root,boolis_pgdata);
6162
staticintstrCompare(constvoid*str1,constvoid*str2);
6263
staticvoidcreate_file_list(parray*files,constchar*root,constchar*prefix,boolis_append);
64+
staticTimeLineIDget_current_timeline(void);
6365

6466
/*
6567
* Take a backup of database.
@@ -108,6 +110,13 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
108110
current.total_data_bytes=0;
109111
current.read_data_bytes=0;
110112

113+
/*
114+
* Obtain current timeline by scanning control file, theh LSN
115+
* obtained at output of pg_start_backup or pg_stop_backup does
116+
* not contain this information.
117+
*/
118+
current.tli=get_current_timeline();
119+
111120
/* notify start of backup to PostgreSQL server */
112121
time2iso(label,lengthof(label),current.start_time);
113122
strncat(label," with pg_rman",lengthof(label));
@@ -492,8 +501,8 @@ do_backup_arclog(parray *backup_list)
492501
pg_switch_xlog(&current);
493502

494503
/*
495-
* To take incremental backup, the file list of the last completed database
496-
* backup is needed.
504+
* To take incremental backup, the file list of the last completed
505+
*databasebackup is needed.
497506
*/
498507
prev_backup=catalog_get_last_arclog_backup(backup_list);
499508
if (verbose&&prev_backup==NULL)
@@ -985,10 +994,10 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup)
985994

986995
/* 2nd argument is 'fast'*/
987996
params[1]=smooth ?"false" :"true";
988-
res=execute("SELECT* from pg_xlogfile_name_offset(pg_start_backup($1, $2))",2,params);
997+
res=execute("SELECT pg_start_backup($1, $2)",2,params);
989998

990999
if (backup!=NULL)
991-
get_lsn(res,&backup->tli,&backup->start_lsn);
1000+
get_lsn(res,&backup->start_lsn);
9921001
PQclear(res);
9931002
disconnect();
9941003
}
@@ -998,22 +1007,42 @@ wait_for_archive(pgBackup *backup, const char *sql)
9981007
{
9991008
PGresult*res;
10001009
charready_path[MAXPGPATH];
1010+
charfile_name[MAXFNAMELEN];
10011011
inttry_count;
1012+
XLogRecPtrlsn;
1013+
TimeLineIDtli;
10021014

10031015
reconnect();
10041016
res=execute(sql,0,NULL);
1017+
1018+
/* Get LSN from execution result */
1019+
get_lsn(res,&lsn);
1020+
1021+
/*
1022+
* Enforce TLI obtention if backup is not present as this code
1023+
* path can be taken as a callback at exit.
1024+
*/
1025+
if (backup!=NULL)
1026+
tli=backup->tli;
1027+
else
1028+
tli=get_current_timeline();
1029+
1030+
/* Fill in fields if backup exists */
10051031
if (backup!=NULL)
10061032
{
1007-
get_lsn(res,&backup->tli,&backup->stop_lsn);
1033+
backup->stop_lsn=lsn;
10081034
elog(LOG,_("%s(): tli=%X lsn=%X/%08X"),
10091035
__FUNCTION__,backup->tli,
10101036
(uint32) (backup->stop_lsn >>32),
10111037
(uint32)backup->stop_lsn);
10121038
}
10131039

1014-
/* get filename from the result of pg_xlogfile_name_offset() */
1040+
/* As well as WAL file name */
1041+
XLogFileName(file_name,tli,lsn);
1042+
10151043
snprintf(ready_path,lengthof(ready_path),
1016-
"%s/pg_xlog/archive_status/%s.ready",pgdata,PQgetvalue(res,0,0));
1044+
"%s/pg_xlog/archive_status/%s.ready",pgdata,
1045+
file_name);
10171046
elog(LOG,"%s() wait for %s",__FUNCTION__,ready_path);
10181047

10191048
PQclear(res);
@@ -1049,32 +1078,41 @@ static void
10491078
pg_stop_backup(pgBackup*backup)
10501079
{
10511080
wait_for_archive(backup,
1052-
"SELECT * FROMpg_xlogfile_name_offset(pg_stop_backup())");
1081+
"SELECT * FROM pg_stop_backup()");
10531082
}
10541083

10551084
/*
1056-
* Force switch to a new transaction log file and update backup->tli.
1085+
* Force switch to a new transaction log file
10571086
*/
10581087
staticvoid
10591088
pg_switch_xlog(pgBackup*backup)
10601089
{
10611090
wait_for_archive(backup,
1062-
"SELECT * FROMpg_xlogfile_name_offset(pg_switch_xlog())");
1091+
"SELECT * FROM pg_switch_xlog())");
10631092
}
10641093

10651094
/*
1066-
* GetTimeLineID andLSN from result ofpg_xlogfile_name_offset().
1095+
* Get LSN from result ofpg_start_backup() or pg_stop_backup().
10671096
*/
10681097
staticvoid
1069-
get_lsn(PGresult*res,TimeLineID*timeline,XLogRecPtr*lsn)
1098+
get_lsn(PGresult*res,XLogRecPtr*lsn)
10701099
{
1071-
if (res==NULL||PQntuples(res)!=1||PQnfields(res)!=2)
1100+
uint32xlogid;
1101+
uint32xrecoff;
1102+
1103+
if (res==NULL||PQntuples(res)!=1||PQnfields(res)!=1)
10721104
elog(ERROR_PG_COMMAND,
1073-
_("result ofpg_xlogfile_name_offset() is invalid: %s"),
1105+
_("result ofbackup command is invalid: %s"),
10741106
PQerrorMessage(connection));
10751107

1076-
/* Extract timeline and LSN from result of pg_stop_backup() */
1077-
XLogFromFileName(PQgetvalue(res,0,0),timeline,lsn);
1108+
/*
1109+
* Extract timeline and LSN from results of pg_stop_backup()
1110+
* and friends.
1111+
*/
1112+
XLogDataFromLSN(PQgetvalue(res,0,0),&xlogid,&xrecoff);
1113+
1114+
/* Calculate LSN */
1115+
*lsn= (XLogRecPtr) ((uint64)xlogid <<32) |xrecoff;
10781116
}
10791117

10801118
/*
@@ -1598,3 +1636,27 @@ create_file_list(parray *files, const char *root, const char *prefix, bool is_ap
15981636
fclose(fp);
15991637
}
16001638
}
1639+
1640+
/*
1641+
* Scan control file of given cluster at obtain the current timeline
1642+
* since last checkpoint that occurred on it.
1643+
*/
1644+
staticTimeLineID
1645+
get_current_timeline(void)
1646+
{
1647+
char*buffer;
1648+
size_tsize;
1649+
ControlFileDatacontrol_file;
1650+
1651+
/* First fetch file... */
1652+
buffer=slurpFile(pgdata,"global/pg_control",&size);
1653+
1654+
/* .. Then interpret it */
1655+
if (size!=PG_CONTROL_SIZE)
1656+
elog(ERROR_CORRUPTED,"unexpected control file size %d, expected %d\n",
1657+
(int)size,PG_CONTROL_SIZE);
1658+
memcpy(&control_file,buffer,sizeof(ControlFileData));
1659+
1660+
/* Finally return the timeline wanted */
1661+
returncontrol_file.checkPointCopy.ThisTimeLineID;
1662+
}

‎fetch.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* fetch.c
4+
* Functions for fetching files from PostgreSQL data directory
5+
*
6+
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
7+
*
8+
*-------------------------------------------------------------------------
9+
*/
10+
11+
#include"postgres_fe.h"
12+
13+
#include"catalog/catalog.h"
14+
15+
#include<sys/types.h>
16+
#include<sys/stat.h>
17+
#include<dirent.h>
18+
#include<fcntl.h>
19+
#include<unistd.h>
20+
#include<string.h>
21+
22+
#include"pg_rman.h"
23+
24+
/*
25+
* Read a file into memory. The file to be read is <datadir>/<path>.
26+
* The file contents are returned in a malloc'd buffer, and *filesize
27+
* is set to the length of the file.
28+
*
29+
* The returned buffer is always zero-terminated; the size of the returned
30+
* buffer is actually *filesize + 1. That's handy when reading a text file.
31+
* This function can be used to read binary files as well, you can just
32+
* ignore the zero-terminator in that case.
33+
*
34+
*/
35+
char*
36+
slurpFile(constchar*datadir,constchar*path,size_t*filesize)
37+
{
38+
intfd;
39+
char*buffer;
40+
structstatstatbuf;
41+
charfullpath[MAXPGPATH];
42+
intlen;
43+
snprintf(fullpath,sizeof(fullpath),"%s/%s",datadir,path);
44+
45+
if ((fd=open(fullpath,O_RDONLY |PG_BINARY,0))==-1)
46+
elog(ERROR_CORRUPTED,_("could not open file \"%s\" for reading: %s\n"),
47+
fullpath,strerror(errno));
48+
49+
if (fstat(fd,&statbuf)<0)
50+
elog(ERROR_CORRUPTED,_("could not open file \"%s\" for reading: %s\n"),
51+
fullpath,strerror(errno));
52+
53+
len=statbuf.st_size;
54+
55+
buffer=pg_malloc(len+1);
56+
57+
if (read(fd,buffer,len)!=len)
58+
elog(ERROR_CORRUPTED,_("could not read file \"%s\": %s\n"),
59+
fullpath,strerror(errno));
60+
61+
close(fd);
62+
63+
/* Zero-terminate the buffer. */
64+
buffer[len]='\0';
65+
66+
if (filesize)
67+
*filesize=len;
68+
returnbuffer;
69+
}

‎pg_rman.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,13 @@ typedef enum CompressionMode
214214
#defineJoinPathEnd(str,prefix) \
215215
((strlen(str) <= strlen(prefix)) ? "" : str + strlen(prefix) + 1)
216216

217+
/*
218+
* Return timeline, xlog ID and record offset from an LSN of the type
219+
* 0/B000188, usual result from pg_stop_backup() and friends.
220+
*/
221+
#defineXLogDataFromLSN(data,xlogid,xrecoff)\
222+
sscanf(data, "%X/%X", xlogid, xrecoff)
223+
217224
/* path configuration */
218225
externchar*backup_path;
219226
externchar*pgdata;
@@ -253,6 +260,11 @@ extern int do_show(pgBackupRange *range, bool show_all);
253260
externintdo_delete(pgBackupRange*range,boolforce);
254261
externvoidpgBackupDelete(intkeep_generations,intkeep_days);
255262

263+
/* in fetch.c */
264+
externchar*slurpFile(constchar*datadir,
265+
constchar*path,
266+
size_t*filesize);
267+
256268
/* in validate.c */
257269
externintdo_validate(pgBackupRange*range);
258270
externvoidpgBackupValidate(pgBackup*backup,boolsize_only,boolfor_get_timeline,boolwith_database);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp