@@ -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)
974979bool basetablespace = PQgetisnull (res ,rownum ,0 );
975980bool in_tarhdr = true;
976981bool skip_file = false;
982+ bool is_recovery_guc_supported = true;
977983bool is_postgresql_auto_conf = false;
978984bool found_postgresql_auto_conf = false;
979985int file_padding_len = 0 ;
@@ -984,6 +990,10 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
984990gzFile 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+
987997if (basetablespace )
988998{
989999/*
@@ -1130,30 +1140,47 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
11301140{
11311141char 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{
11351152int padding ;
11361153
1137- tarCreateHeader (header ,"postgresql.auto.conf" ,NULL ,
1154+ tarCreateHeader (header ,
1155+ is_recovery_guc_supported ?"postgresql.auto.conf" :"recovery.conf" ,
1156+ NULL ,
11381157recoveryconfcontents -> len ,
11391158pg_file_create_mode ,04000 ,02000 ,
11401159time (NULL ));
11411160
11421161padding = ((recoveryconfcontents -> len + 511 )& ~511 )- recoveryconfcontents -> len ;
11431162
11441163WRITE_TAR_DATA (header ,sizeof (header ));
1145- WRITE_TAR_DATA (recoveryconfcontents -> data ,recoveryconfcontents -> len );
1164+ WRITE_TAR_DATA (recoveryconfcontents -> data ,
1165+ recoveryconfcontents -> len );
11461166if (padding )
11471167WRITE_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
12611294filesz = read_tar_number (& tarhdr [124 ],12 );
12621295file_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 */
12671302char header [512 ];
@@ -1313,7 +1348,9 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
13131348pos += bytes2write ;
13141349filesz -= 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 */
13191356int padding ;
@@ -1690,6 +1727,13 @@ GenerateRecoveryConf(PGconn *conn)
16901727exit (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+
16931737connOptions = PQconninfo (conn );
16941738if (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{
17651811char filename [MAXPGPATH ];
17661812FILE * 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" );
17711822if (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 ));
17741826exit (1 );
17751827}
17761828
@@ -1784,15 +1836,18 @@ WriteRecoveryConf(void)
17841836
17851837fclose (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