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

Commitcaba97a

Browse files
committed
Split out recovery confing-writing code from pg_basebackup
... into a new file, fe_utils/recovery_gen.c.This can later be used by pg_rewind.Authors: Paul Guo, Jimmy Yih, Ashwin Agrawal. A few tweaks by Álvaro HerreraReviewed-by: Michaël PaquierDiscussion:https://postgr.es/m/CAEET0ZEffUkXc48pg2iqARQgGRYDiiVxDu+yYek_bTwJF+q=Uw@mail.gmail.com
1 parentf5daf7f commitcaba97a

File tree

5 files changed

+211
-161
lines changed

5 files changed

+211
-161
lines changed

‎src/bin/pg_basebackup/pg_basebackup.c

Lines changed: 3 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include"common/file_utils.h"
3232
#include"common/logging.h"
3333
#include"common/string.h"
34+
#include"fe_utils/recovery_gen.h"
3435
#include"fe_utils/string_utils.h"
3536
#include"getopt_long.h"
3637
#include"libpq-fe.h"
@@ -67,11 +68,6 @@ typedef struct TablespaceList
6768
*/
6869
#defineMINIMUM_VERSION_FOR_TEMP_SLOTS 100000
6970

70-
/*
71-
* recovery.conf is integrated into postgresql.conf from version 12.
72-
*/
73-
#defineMINIMUM_VERSION_FOR_RECOVERY_GUC 120000
74-
7571
/*
7672
* Different ways to include WAL
7773
*/
@@ -147,8 +143,6 @@ static void progress_report(int tablespacenum, const char *filename, bool force)
147143

148144
staticvoidReceiveTarFile(PGconn*conn,PGresult*res,intrownum);
149145
staticvoidReceiveAndUnpackTarFile(PGconn*conn,PGresult*res,intrownum);
150-
staticvoidGenerateRecoveryConf(PGconn*conn);
151-
staticvoidWriteRecoveryConf(void);
152146
staticvoidBaseBackup(void);
153147

154148
staticboolreached_end_position(XLogRecPtrsegendpos,uint32timeline,
@@ -1629,164 +1623,14 @@ ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum)
16291623
PQfreemem(copybuf);
16301624

16311625
if (basetablespace&&writerecoveryconf)
1632-
WriteRecoveryConf();
1626+
WriteRecoveryConfig(conn,basedir,recoveryconfcontents);
16331627

16341628
/*
16351629
* No data is synced here, everything is done for all tablespaces at the
16361630
* end.
16371631
*/
16381632
}
16391633

1640-
/*
1641-
* Escape a string so that it can be used as a value in a key-value pair
1642-
* a configuration file.
1643-
*/
1644-
staticchar*
1645-
escape_quotes(constchar*src)
1646-
{
1647-
char*result=escape_single_quotes_ascii(src);
1648-
1649-
if (!result)
1650-
{
1651-
pg_log_error("out of memory");
1652-
exit(1);
1653-
}
1654-
returnresult;
1655-
}
1656-
1657-
/*
1658-
* Create a configuration file in memory using a PQExpBuffer
1659-
*/
1660-
staticvoid
1661-
GenerateRecoveryConf(PGconn*conn)
1662-
{
1663-
PQconninfoOption*connOptions;
1664-
PQconninfoOption*option;
1665-
PQExpBufferDataconninfo_buf;
1666-
char*escaped;
1667-
1668-
recoveryconfcontents=createPQExpBuffer();
1669-
if (!recoveryconfcontents)
1670-
{
1671-
pg_log_error("out of memory");
1672-
exit(1);
1673-
}
1674-
1675-
/*
1676-
* In PostgreSQL 12 and newer versions, standby_mode is gone, replaced by
1677-
* standby.signal to trigger a standby state at recovery.
1678-
*/
1679-
if (PQserverVersion(conn)<MINIMUM_VERSION_FOR_RECOVERY_GUC)
1680-
appendPQExpBufferStr(recoveryconfcontents,"standby_mode = 'on'\n");
1681-
1682-
connOptions=PQconninfo(conn);
1683-
if (connOptions==NULL)
1684-
{
1685-
pg_log_error("out of memory");
1686-
exit(1);
1687-
}
1688-
1689-
initPQExpBuffer(&conninfo_buf);
1690-
for (option=connOptions;option&&option->keyword;option++)
1691-
{
1692-
/* Omit empty settings and those libpqwalreceiver overrides. */
1693-
if (strcmp(option->keyword,"replication")==0||
1694-
strcmp(option->keyword,"dbname")==0||
1695-
strcmp(option->keyword,"fallback_application_name")==0||
1696-
(option->val==NULL)||
1697-
(option->val!=NULL&&option->val[0]=='\0'))
1698-
continue;
1699-
1700-
/* Separate key-value pairs with spaces */
1701-
if (conninfo_buf.len!=0)
1702-
appendPQExpBufferChar(&conninfo_buf,' ');
1703-
1704-
/*
1705-
* Write "keyword=value" pieces, the value string is escaped and/or
1706-
* quoted if necessary.
1707-
*/
1708-
appendPQExpBuffer(&conninfo_buf,"%s=",option->keyword);
1709-
appendConnStrVal(&conninfo_buf,option->val);
1710-
}
1711-
1712-
/*
1713-
* Escape the connection string, so that it can be put in the config file.
1714-
* Note that this is different from the escaping of individual connection
1715-
* options above!
1716-
*/
1717-
escaped=escape_quotes(conninfo_buf.data);
1718-
appendPQExpBuffer(recoveryconfcontents,"primary_conninfo = '%s'\n",escaped);
1719-
free(escaped);
1720-
1721-
if (replication_slot)
1722-
{
1723-
/* unescaped: ReplicationSlotValidateName allows [a-z0-9_] only */
1724-
appendPQExpBuffer(recoveryconfcontents,"primary_slot_name = '%s'\n",
1725-
replication_slot);
1726-
}
1727-
1728-
if (PQExpBufferBroken(recoveryconfcontents)||
1729-
PQExpBufferDataBroken(conninfo_buf))
1730-
{
1731-
pg_log_error("out of memory");
1732-
exit(1);
1733-
}
1734-
1735-
termPQExpBuffer(&conninfo_buf);
1736-
1737-
PQconninfoFree(connOptions);
1738-
}
1739-
1740-
1741-
/*
1742-
* Write the configuration file into the directory specified in basedir,
1743-
* with the contents already collected in memory appended. Then write
1744-
* the signal file into the basedir. If the server does not support
1745-
* recovery parameters as GUCs, the signal file is not necessary, and
1746-
* configuration is written to recovery.conf.
1747-
*/
1748-
staticvoid
1749-
WriteRecoveryConf(void)
1750-
{
1751-
charfilename[MAXPGPATH];
1752-
FILE*cf;
1753-
boolis_recovery_guc_supported= true;
1754-
1755-
if (PQserverVersion(conn)<MINIMUM_VERSION_FOR_RECOVERY_GUC)
1756-
is_recovery_guc_supported= false;
1757-
1758-
snprintf(filename,MAXPGPATH,"%s/%s",basedir,
1759-
is_recovery_guc_supported ?"postgresql.auto.conf" :"recovery.conf");
1760-
1761-
cf=fopen(filename,is_recovery_guc_supported ?"a" :"w");
1762-
if (cf==NULL)
1763-
{
1764-
pg_log_error("could not open file \"%s\": %m",filename);
1765-
exit(1);
1766-
}
1767-
1768-
if (fwrite(recoveryconfcontents->data,recoveryconfcontents->len,1,cf)!=1)
1769-
{
1770-
pg_log_error("could not write to file \"%s\": %m",filename);
1771-
exit(1);
1772-
}
1773-
1774-
fclose(cf);
1775-
1776-
if (is_recovery_guc_supported)
1777-
{
1778-
snprintf(filename,MAXPGPATH,"%s/%s",basedir,"standby.signal");
1779-
cf=fopen(filename,"w");
1780-
if (cf==NULL)
1781-
{
1782-
pg_log_error("could not create file \"%s\": %m",filename);
1783-
exit(1);
1784-
}
1785-
1786-
fclose(cf);
1787-
}
1788-
}
1789-
17901634

17911635
staticvoid
17921636
BaseBackup(void)
@@ -1843,7 +1687,7 @@ BaseBackup(void)
18431687
* Build contents of configuration file if requested
18441688
*/
18451689
if (writerecoveryconf)
1846-
GenerateRecoveryConf(conn);
1690+
recoveryconfcontents=GenerateRecoveryConfig(conn,replication_slot);
18471691

18481692
/*
18491693
* Run IDENTIFY_SYSTEM so we can get the timeline

‎src/fe_utils/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ include $(top_builddir)/src/Makefile.global
1919

2020
overrideCPPFLAGS := -DFRONTEND -I$(libpq_srcdir)$(CPPFLAGS)
2121

22-
OBJS = mbprint.o print.o psqlscan.o simple_list.o string_utils.o conditional.o
22+
OBJS = conditional.o mbprint.o print.o psqlscan.o recovery_gen.o\
23+
simple_list.o string_utils.o
2324

2425
all: libpgfeutils.a
2526

‎src/fe_utils/recovery_gen.c

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* recovery_gen.c
4+
*Generator for recovery configuration
5+
*
6+
* Portions Copyright (c) 2011-2019, PostgreSQL Global Development Group
7+
*
8+
*-------------------------------------------------------------------------
9+
*/
10+
#include"postgres_fe.h"
11+
12+
#include"common/logging.h"
13+
#include"fe_utils/string_utils.h"
14+
#include"fe_utils/recovery_gen.h"
15+
16+
17+
staticchar*escape_quotes(constchar*src);
18+
19+
/*
20+
* Write recovery configuration contents into a fresh PQExpBuffer, and
21+
* return it.
22+
*/
23+
PQExpBuffer
24+
GenerateRecoveryConfig(PGconn*pgconn,char*replication_slot)
25+
{
26+
PQconninfoOption*connOptions;
27+
PQExpBufferDataconninfo_buf;
28+
char*escaped;
29+
PQExpBuffercontents;
30+
31+
Assert(pgconn!=NULL);
32+
33+
contents=createPQExpBuffer();
34+
if (!contents)
35+
{
36+
pg_log_error("out of memory");
37+
exit(1);
38+
}
39+
40+
/*
41+
* In PostgreSQL 12 and newer versions, standby_mode is gone, replaced by
42+
* standby.signal to trigger a standby state at recovery.
43+
*/
44+
if (PQserverVersion(pgconn)<MINIMUM_VERSION_FOR_RECOVERY_GUC)
45+
appendPQExpBufferStr(contents,"standby_mode = 'on'\n");
46+
47+
connOptions=PQconninfo(pgconn);
48+
if (connOptions==NULL)
49+
{
50+
pg_log_error("out of memory");
51+
exit(1);
52+
}
53+
54+
initPQExpBuffer(&conninfo_buf);
55+
for (PQconninfoOption*opt=connOptions;opt&&opt->keyword;opt++)
56+
{
57+
/* Omit empty settings and those libpqwalreceiver overrides. */
58+
if (strcmp(opt->keyword,"replication")==0||
59+
strcmp(opt->keyword,"dbname")==0||
60+
strcmp(opt->keyword,"fallback_application_name")==0||
61+
(opt->val==NULL)||
62+
(opt->val!=NULL&&opt->val[0]=='\0'))
63+
continue;
64+
65+
/* Separate key-value pairs with spaces */
66+
if (conninfo_buf.len!=0)
67+
appendPQExpBufferChar(&conninfo_buf,' ');
68+
69+
/*
70+
* Write "keyword=value" pieces, the value string is escaped and/or
71+
* quoted if necessary.
72+
*/
73+
appendPQExpBuffer(&conninfo_buf,"%s=",opt->keyword);
74+
appendConnStrVal(&conninfo_buf,opt->val);
75+
}
76+
if (PQExpBufferDataBroken(conninfo_buf))
77+
{
78+
pg_log_error("out of memory");
79+
exit(1);
80+
}
81+
82+
/*
83+
* Escape the connection string, so that it can be put in the config file.
84+
* Note that this is different from the escaping of individual connection
85+
* options above!
86+
*/
87+
escaped=escape_quotes(conninfo_buf.data);
88+
termPQExpBuffer(&conninfo_buf);
89+
appendPQExpBuffer(contents,"primary_conninfo = '%s'\n",escaped);
90+
free(escaped);
91+
92+
if (replication_slot)
93+
{
94+
/* unescaped: ReplicationSlotValidateName allows [a-z0-9_] only */
95+
appendPQExpBuffer(contents,"primary_slot_name = '%s'\n",
96+
replication_slot);
97+
}
98+
99+
if (PQExpBufferBroken(contents))
100+
{
101+
pg_log_error("out of memory");
102+
exit(1);
103+
}
104+
105+
PQconninfoFree(connOptions);
106+
107+
returncontents;
108+
}
109+
110+
/*
111+
* Write the configuration file in the directory specified in target_dir,
112+
* with the contents already collected in memory appended. Then write
113+
* the signal file into the target_dir. If the server does not support
114+
* recovery parameters as GUCs, the signal file is not necessary, and
115+
* configuration is written to recovery.conf.
116+
*/
117+
void
118+
WriteRecoveryConfig(PGconn*pgconn,char*target_dir,PQExpBuffercontents)
119+
{
120+
charfilename[MAXPGPATH];
121+
FILE*cf;
122+
booluse_recovery_conf;
123+
124+
Assert(pgconn!=NULL);
125+
126+
use_recovery_conf=
127+
PQserverVersion(pgconn)<MINIMUM_VERSION_FOR_RECOVERY_GUC;
128+
129+
snprintf(filename,MAXPGPATH,"%s/%s",target_dir,
130+
use_recovery_conf ?"recovery.conf" :"postgresql.auto.conf");
131+
132+
cf=fopen(filename,use_recovery_conf ?"a" :"w");
133+
if (cf==NULL)
134+
{
135+
pg_log_error("could not open file \"%s\": %m",filename);
136+
exit(1);
137+
}
138+
139+
if (fwrite(contents->data,contents->len,1,cf)!=1)
140+
{
141+
pg_log_error("could not write to file \"%s\": %m",filename);
142+
exit(1);
143+
}
144+
145+
fclose(cf);
146+
147+
if (!use_recovery_conf)
148+
{
149+
snprintf(filename,MAXPGPATH,"%s/%s",target_dir,"standby.signal");
150+
cf=fopen(filename,"w");
151+
if (cf==NULL)
152+
{
153+
pg_log_error("could not create file \"%s\": %m",filename);
154+
exit(1);
155+
}
156+
157+
fclose(cf);
158+
}
159+
}
160+
161+
/*
162+
* Escape a string so that it can be used as a value in a key-value pair
163+
* a configuration file.
164+
*/
165+
staticchar*
166+
escape_quotes(constchar*src)
167+
{
168+
char*result=escape_single_quotes_ascii(src);
169+
170+
if (!result)
171+
{
172+
pg_log_error("out of memory");
173+
exit(1);
174+
}
175+
returnresult;
176+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp