@@ -66,6 +66,11 @@ typedef struct TablespaceList
6666 */
6767#define MINIMUM_VERSION_FOR_TEMP_SLOTS 100000
6868
69+ /*
70+ * recovery.conf is integrated into postgresql.conf from version 12.
71+ */
72+ #define MINIMUM_VERSION_FOR_RECOVERY_GUC 120000
73+
6974/*
7075 * Different ways to include WAL
7176 */
@@ -974,6 +979,7 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
974979 bool basetablespace = PQgetisnull (res , rownum , 0 );
975980 bool in_tarhdr = true;
976981 bool skip_file = false;
982+ bool is_recovery_guc_supported = true;
977983 bool is_postgresql_auto_conf = false;
978984 bool found_postgresql_auto_conf = false;
979985 int file_padding_len = 0 ;
@@ -984,6 +990,10 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
984990 gzFile ztarfile = NULL ;
985991#endif
986992
993+ /* recovery.conf is integrated into postgresql.conf in 12 and newer */
994+ if (PQserverVersion (conn ) < MINIMUM_VERSION_FOR_RECOVERY_GUC )
995+ is_recovery_guc_supported = false;
996+
987997 if (basetablespace )
988998 {
989999 /*
@@ -1130,30 +1140,47 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
11301140 {
11311141 char header [512 ];
11321142
1133- if (!found_postgresql_auto_conf )
1143+ /*
1144+ * If postgresql.auto.conf has not been found in the streamed
1145+ * data, add recovery configuration to postgresql.auto.conf if
1146+ * recovery parameters are GUCs. If the instance connected to
1147+ * is older than 12, create recovery.conf with this data
1148+ * otherwise.
1149+ */
1150+ if (!found_postgresql_auto_conf || !is_recovery_guc_supported )
11341151 {
11351152 int padding ;
11361153
1137- tarCreateHeader (header , "postgresql.auto.conf" , NULL ,
1154+ tarCreateHeader (header ,
1155+ is_recovery_guc_supported ? "postgresql.auto.conf" : "recovery.conf" ,
1156+ NULL ,
11381157 recoveryconfcontents -> len ,
11391158 pg_file_create_mode , 04000 , 02000 ,
11401159 time (NULL ));
11411160
11421161 padding = ((recoveryconfcontents -> len + 511 ) & ~511 ) - recoveryconfcontents -> len ;
11431162
11441163 WRITE_TAR_DATA (header , sizeof (header ));
1145- WRITE_TAR_DATA (recoveryconfcontents -> data , recoveryconfcontents -> len );
1164+ WRITE_TAR_DATA (recoveryconfcontents -> data ,
1165+ recoveryconfcontents -> len );
11461166 if (padding )
11471167 WRITE_TAR_DATA (zerobuf , padding );
11481168 }
11491169
1150- tarCreateHeader (header , "standby.signal" , NULL ,
1151- 0 , /* zero-length file */
1152- pg_file_create_mode , 04000 , 02000 ,
1153- time (NULL ));
1170+ /*
1171+ * standby.signal is supported only if recovery parameters are
1172+ * GUCs.
1173+ */
1174+ if (is_recovery_guc_supported )
1175+ {
1176+ tarCreateHeader (header , "standby.signal" , NULL ,
1177+ 0 , /* zero-length file */
1178+ pg_file_create_mode , 04000 , 02000 ,
1179+ time (NULL ));
11541180
1155- WRITE_TAR_DATA (header , sizeof (header ));
1156- WRITE_TAR_DATA (zerobuf , 511 );
1181+ WRITE_TAR_DATA (header , sizeof (header ));
1182+ WRITE_TAR_DATA (zerobuf , 511 );
1183+ }
11571184 }
11581185
11591186 /* 2 * 512 bytes empty data at end of file */
@@ -1252,16 +1279,24 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
12521279 * We have the complete header structure in tarhdr,
12531280 * look at the file metadata: we may want append
12541281 * recovery info into postgresql.auto.conf and skip
1255- * standby.signal file. In both cases we must
1256- * calculate tar padding
1282+ * standby.signal file if recovery parameters are
1283+ * integrated as GUCs, and recovery.conf otherwise. In
1284+ * both cases we must calculate tar padding.
12571285 */
1258- skip_file = (strcmp (& tarhdr [0 ], "standby.signal" ) == 0 );
1259- is_postgresql_auto_conf = (strcmp (& tarhdr [0 ], "postgresql.auto.conf" ) == 0 );
1286+ if (is_recovery_guc_supported )
1287+ {
1288+ skip_file = (strcmp (& tarhdr [0 ], "standby.signal" ) == 0 );
1289+ is_postgresql_auto_conf = (strcmp (& tarhdr [0 ], "postgresql.auto.conf" ) == 0 );
1290+ }
1291+ else
1292+ skip_file = (strcmp (& tarhdr [0 ], "recovery.conf" ) == 0 );
12601293
12611294 filesz = read_tar_number (& tarhdr [124 ], 12 );
12621295 file_padding_len = ((filesz + 511 ) & ~511 ) - filesz ;
12631296
1264- if (is_postgresql_auto_conf && writerecoveryconf )
1297+ if (is_recovery_guc_supported &&
1298+ is_postgresql_auto_conf &&
1299+ writerecoveryconf )
12651300 {
12661301 /* replace tar header */
12671302 char header [512 ];
@@ -1313,7 +1348,9 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
13131348 pos += bytes2write ;
13141349 filesz -= bytes2write ;
13151350 }
1316- else if (is_postgresql_auto_conf && writerecoveryconf )
1351+ else if (is_recovery_guc_supported &&
1352+ is_postgresql_auto_conf &&
1353+ writerecoveryconf )
13171354 {
13181355 /* append recovery config to postgresql.auto.conf */
13191356 int padding ;
@@ -1690,6 +1727,13 @@ GenerateRecoveryConf(PGconn *conn)
16901727 exit (1 );
16911728 }
16921729
1730+ /*
1731+ * In PostgreSQL 12 and newer versions, standby_mode is gone, replaced by
1732+ * standby.signal to trigger a standby state at recovery.
1733+ */
1734+ if (PQserverVersion (conn ) < MINIMUM_VERSION_FOR_RECOVERY_GUC )
1735+ appendPQExpBufferStr (recoveryconfcontents , "standby_mode = 'on'\n" );
1736+
16931737 connOptions = PQconninfo (conn );
16941738 if (connOptions == NULL )
16951739 {
@@ -1756,21 +1800,29 @@ GenerateRecoveryConf(PGconn *conn)
17561800
17571801/*
17581802 * Write the configuration file into the directory specified in basedir,
1759- * with the contents already collected in memory.
1760- * Then write the signal file into the basedir also.
1803+ * with the contents already collected in memory appended. Then write
1804+ * the signal file into the basedir. If the server does not support
1805+ * recovery parameters as GUCs, the signal file is not necessary, and
1806+ * configuration is written to recovery.conf.
17611807 */
17621808static void
17631809WriteRecoveryConf (void )
17641810{
17651811 char filename [MAXPGPATH ];
17661812 FILE * cf ;
1813+ bool is_recovery_guc_supported = true;
17671814
1768- snprintf (filename , MAXPGPATH , "%s/%s" , basedir , "postgresql.auto.conf" );
1815+ if (PQserverVersion (conn ) < MINIMUM_VERSION_FOR_RECOVERY_GUC )
1816+ is_recovery_guc_supported = false;
17691817
1770- cf = fopen (filename , "a" );
1818+ snprintf (filename , MAXPGPATH , "%s/%s" , basedir ,
1819+ is_recovery_guc_supported ? "postgresql.auto.conf" : "recovery.conf" );
1820+
1821+ cf = fopen (filename , is_recovery_guc_supported ? "a" : "w" );
17711822 if (cf == NULL )
17721823 {
1773- fprintf (stderr , _ ("%s: could not open file \"%s\": %s\n" ), progname , filename , strerror (errno ));
1824+ fprintf (stderr , _ ("%s: could not open file \"%s\": %s\n" ),
1825+ progname , filename , strerror (errno ));
17741826 exit (1 );
17751827 }
17761828
@@ -1784,15 +1836,18 @@ WriteRecoveryConf(void)
17841836
17851837 fclose (cf );
17861838
1787- snprintf (filename , MAXPGPATH , "%s/%s" , basedir , "standby.signal" );
1788- cf = fopen (filename , "w" );
1789- if (cf == NULL )
1839+ if (is_recovery_guc_supported )
17901840 {
1791- fprintf (stderr , _ ("%s: could not create file \"%s\": %s\n" ), progname , filename , strerror (errno ));
1792- exit (1 );
1793- }
1841+ snprintf (filename , MAXPGPATH , "%s/%s" , basedir , "standby.signal" );
1842+ cf = fopen (filename , "w" );
1843+ if (cf == NULL )
1844+ {
1845+ fprintf (stderr , _ ("%s: could not create file \"%s\": %s\n" ), progname , filename , strerror (errno ));
1846+ exit (1 );
1847+ }
17941848
1795- fclose (cf );
1849+ fclose (cf );
1850+ }
17961851}
17971852
17981853
0 commit comments