@@ -648,6 +648,7 @@ static bool XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
648
648
bool randAccess );
649
649
static int emode_for_corrupt_record (int emode , XLogRecPtr RecPtr );
650
650
static void XLogFileClose (void );
651
+ static void KeepFileRestoredFromArchive (char * path , char * xlogfname );
651
652
static bool RestoreArchivedFile (char * path , const char * xlogfname ,
652
653
const char * recovername , off_t expectedSize );
653
654
static void ExecuteRecoveryCommand (char * command , char * commandName ,
@@ -2842,74 +2843,12 @@ XLogFileRead(uint32 log, uint32 seg, int emode, TimeLineID tli,
2842
2843
*/
2843
2844
if (source == XLOG_FROM_ARCHIVE )
2844
2845
{
2845
- char xlogfpath [MAXPGPATH ];
2846
- bool reload = false;
2847
- struct stat statbuf ;
2848
-
2849
- XLogFilePath (xlogfpath , tli , log , seg );
2850
- if (stat (xlogfpath , & statbuf ) == 0 )
2851
- {
2852
- char oldpath [MAXPGPATH ];
2853
- #ifdef WIN32
2854
- static unsigned int deletedcounter = 1 ;
2855
- /*
2856
- * On Windows, if another process (e.g a walsender process) holds
2857
- * the file open in FILE_SHARE_DELETE mode, unlink will succeed,
2858
- * but the file will still show up in directory listing until the
2859
- * last handle is closed, and we cannot rename the new file in its
2860
- * place until that. To avoid that problem, rename the old file to
2861
- * a temporary name first. Use a counter to create a unique
2862
- * filename, because the same file might be restored from the
2863
- * archive multiple times, and a walsender could still be holding
2864
- * onto an old deleted version of it.
2865
- */
2866
- snprintf (oldpath , MAXPGPATH , "%s.deleted%u" ,
2867
- xlogfpath , deletedcounter ++ );
2868
- if (rename (xlogfpath , oldpath ) != 0 )
2869
- {
2870
- ereport (ERROR ,
2871
- (errcode_for_file_access (),
2872
- errmsg ("could not rename file \"%s\" to \"%s\": %m" ,
2873
- xlogfpath , oldpath )));
2874
- }
2875
- #else
2876
- strncpy (oldpath , xlogfpath , MAXPGPATH );
2877
- #endif
2878
- if (unlink (oldpath ) != 0 )
2879
- ereport (FATAL ,
2880
- (errcode_for_file_access (),
2881
- errmsg ("could not remove file \"%s\": %m" ,
2882
- xlogfpath )));
2883
- reload = true;
2884
- }
2885
-
2886
- if (rename (path , xlogfpath ) < 0 )
2887
- ereport (ERROR ,
2888
- (errcode_for_file_access (),
2889
- errmsg ("could not rename file \"%s\" to \"%s\": %m" ,
2890
- path , xlogfpath )));
2846
+ KeepFileRestoredFromArchive (path , xlogfname );
2891
2847
2892
2848
/*
2893
2849
* Set path to point at the new file in pg_xlog.
2894
2850
*/
2895
- strncpy (path , xlogfpath , MAXPGPATH );
2896
-
2897
- /*
2898
- * Create .done file forcibly to prevent the restored segment from
2899
- * being archived again later.
2900
- */
2901
- XLogArchiveForceDone (xlogfname );
2902
-
2903
- /*
2904
- * If the existing segment was replaced, since walsenders might have
2905
- * it open, request them to reload a currently-open segment.
2906
- */
2907
- if (reload )
2908
- WalSndRqstFileReload ();
2909
-
2910
- /* Signal walsender that new WAL has arrived */
2911
- if (AllowCascadeReplication ())
2912
- WalSndWakeup ();
2851
+ snprintf (path , MAXPGPATH , XLOGDIR "/%s" , xlogfname );
2913
2852
}
2914
2853
2915
2854
fd = BasicOpenFile (path , O_RDONLY | PG_BINARY , 0 );
@@ -3024,6 +2963,83 @@ XLogFileClose(void)
3024
2963
openLogFile = -1 ;
3025
2964
}
3026
2965
2966
+ /*
2967
+ * A file was restored from the archive under a temporary filename (path),
2968
+ * and now we want to keep it. Rename it under the permanent filename in
2969
+ * in pg_xlog (xlogfname), replacing any existing file with the same name.
2970
+ */
2971
+ static void
2972
+ KeepFileRestoredFromArchive (char * path , char * xlogfname )
2973
+ {
2974
+ char xlogfpath [MAXPGPATH ];
2975
+ bool reload = false;
2976
+ struct stat statbuf ;
2977
+
2978
+ snprintf (xlogfpath , MAXPGPATH , XLOGDIR "/%s" , xlogfname );
2979
+
2980
+ if (stat (xlogfpath , & statbuf ) == 0 )
2981
+ {
2982
+ char oldpath [MAXPGPATH ];
2983
+ #ifdef WIN32
2984
+ static unsigned int deletedcounter = 1 ;
2985
+ /*
2986
+ * On Windows, if another process (e.g a walsender process) holds
2987
+ * the file open in FILE_SHARE_DELETE mode, unlink will succeed,
2988
+ * but the file will still show up in directory listing until the
2989
+ * last handle is closed, and we cannot rename the new file in its
2990
+ * place until that. To avoid that problem, rename the old file to
2991
+ * a temporary name first. Use a counter to create a unique
2992
+ * filename, because the same file might be restored from the
2993
+ * archive multiple times, and a walsender could still be holding
2994
+ * onto an old deleted version of it.
2995
+ */
2996
+ snprintf (oldpath , MAXPGPATH , "%s.deleted%u" ,
2997
+ xlogfpath , deletedcounter ++ );
2998
+ if (rename (xlogfpath , oldpath ) != 0 )
2999
+ {
3000
+ ereport (ERROR ,
3001
+ (errcode_for_file_access (),
3002
+ errmsg ("could not rename file \"%s\" to \"%s\": %m" ,
3003
+ xlogfpath , oldpath )));
3004
+ }
3005
+ #else
3006
+ strncpy (oldpath , xlogfpath , MAXPGPATH );
3007
+ #endif
3008
+ if (unlink (oldpath ) != 0 )
3009
+ ereport (FATAL ,
3010
+ (errcode_for_file_access (),
3011
+ errmsg ("could not remove file \"%s\": %m" ,
3012
+ xlogfpath )));
3013
+ reload = true;
3014
+ }
3015
+
3016
+ if (rename (path , xlogfpath ) < 0 )
3017
+ ereport (ERROR ,
3018
+ (errcode_for_file_access (),
3019
+ errmsg ("could not rename file \"%s\" to \"%s\": %m" ,
3020
+ path , xlogfpath )));
3021
+
3022
+ /*
3023
+ * Create .done file forcibly to prevent the restored segment from
3024
+ * being archived again later.
3025
+ */
3026
+ XLogArchiveForceDone (xlogfname );
3027
+
3028
+ /*
3029
+ * If the existing file was replaced, since walsenders might have it
3030
+ * open, request them to reload a currently-open segment. This is only
3031
+ * required for WAL segments, walsenders don't hold other files open,
3032
+ * but there's no harm in doing this too often, and we don't know what
3033
+ * kind of a file we're dealing with here.
3034
+ */
3035
+ if (reload )
3036
+ WalSndRqstFileReload ();
3037
+
3038
+ /* Signal walsender that new WAL has arrived */
3039
+ if (AllowCascadeReplication ())
3040
+ WalSndWakeup ();
3041
+ }
3042
+
3027
3043
/*
3028
3044
* Attempt to retrieve the specified file from off-line archival storage.
3029
3045
* If successful, fill "path" with its complete path (note that this will be
@@ -4356,6 +4372,7 @@ readTimeLineHistory(TimeLineID targetTLI)
4356
4372
char histfname [MAXFNAMELEN ];
4357
4373
char fline [MAXPGPATH ];
4358
4374
FILE * fd ;
4375
+ bool fromArchive = false;
4359
4376
4360
4377
/* Timeline 1 does not have a history file, so no need to check */
4361
4378
if (targetTLI == 1 )
@@ -4364,7 +4381,8 @@ readTimeLineHistory(TimeLineID targetTLI)
4364
4381
if (InArchiveRecovery )
4365
4382
{
4366
4383
TLHistoryFileName (histfname , targetTLI );
4367
- RestoreArchivedFile (path , histfname , "RECOVERYHISTORY" , 0 );
4384
+ fromArchive =
4385
+ RestoreArchivedFile (path , histfname , "RECOVERYHISTORY" , 0 );
4368
4386
}
4369
4387
else
4370
4388
TLHistoryFilePath (path , targetTLI );
@@ -4433,6 +4451,13 @@ readTimeLineHistory(TimeLineID targetTLI)
4433
4451
(errmsg_internal ("history of timeline %u is %s" ,
4434
4452
targetTLI , nodeToString (result ))));
4435
4453
4454
+ /*
4455
+ * If the history file was fetched from archive, save it in pg_xlog for
4456
+ * future reference.
4457
+ */
4458
+ if (fromArchive )
4459
+ KeepFileRestoredFromArchive (path , histfname );
4460
+
4436
4461
return result ;
4437
4462
}
4438
4463
0 commit comments