@ -111,11 +111,20 @@ static PgArchData *PgArch = NULL;
* completes , the file names are stored in ascending order of priority in
* arch_files . pgarch_readyXlog ( ) returns files from arch_files until it
* is empty , at which point another directory scan must be performed .
*
* We only need this data in the archiver process , so make it a palloc ' d
* struct rather than a bunch of static arrays .
*/
static binaryheap * arch_heap = NULL ;
static char arch_filenames [ NUM_FILES_PER_DIRECTORY_SCAN ] [ MAX_XFN_CHARS ] ;
static char * arch_files [ NUM_FILES_PER_DIRECTORY_SCAN ] ;
static int arch_files_size = 0 ;
struct arch_files_state
{
binaryheap * arch_heap ;
int arch_files_size ; /* number of live entries in arch_files[] */
char * arch_files [ NUM_FILES_PER_DIRECTORY_SCAN ] ;
/* buffers underlying heap, and later arch_files[], entries: */
char arch_filenames [ NUM_FILES_PER_DIRECTORY_SCAN ] [ MAX_XFN_CHARS + 1 ] ;
} ;
static struct arch_files_state * arch_files = NULL ;
/*
* Flags set by interrupt handlers for later service in the main loop .
@ -231,9 +240,13 @@ PgArchiverMain(void)
*/
PgArch - > pgprocno = MyProc - > pgprocno ;
/* Create workspace for pgarch_readyXlog() */
arch_files = palloc ( sizeof ( struct arch_files_state ) ) ;
arch_files - > arch_files_size = 0 ;
/* Initialize our max-heap for prioritizing files to archive. */
arch_heap = binaryheap_allocate ( NUM_FILES_PER_DIRECTORY_SCAN ,
ready_file_comparator , NULL ) ;
arch_files - > arch_ heap = binaryheap_allocate ( NUM_FILES_PER_DIRECTORY_SCAN ,
ready_file_comparator , NULL ) ;
pgarch_MainLoop ( ) ;
@ -363,7 +376,7 @@ pgarch_ArchiverCopyLoop(void)
char xlog [ MAX_XFN_CHARS + 1 ] ;
/* force directory scan in the first call to pgarch_readyXlog() */
arch_files_size = 0 ;
arch_files - > arch_files _size = 0 ;
/*
* loop through all xlogs with archive_status of . ready and archive
@ -658,7 +671,7 @@ pgarch_readyXlog(char *xlog)
SpinLockRelease ( & PgArch - > arch_lck ) ;
if ( force_dir_scan )
arch_files_size = 0 ;
arch_files - > arch_files _size = 0 ;
/*
* If we still have stored file names from the previous directory scan ,
@ -666,14 +679,14 @@ pgarch_readyXlog(char *xlog)
* is still present , as the archive_command for a previous file may
* have already marked it done .
*/
while ( arch_files_size > 0 )
while ( arch_files - > arch_files _size > 0 )
{
struct stat st ;
char status_file [ MAXPGPATH ] ;
char * arch_file ;
arch_files_size - - ;
arch_file = arch_files [ arch_files_size ] ;
arch_files - > arch_files _size- - ;
arch_file = arch_files - > arch_files [ arch_files - > arch_files_size ] ;
StatusFilePath ( status_file , arch_file , " .ready " ) ;
if ( stat ( status_file , & st ) = = 0 )
@ -687,6 +700,9 @@ pgarch_readyXlog(char *xlog)
errmsg ( " could not stat file \" %s \" : %m " , status_file ) ) ) ;
}
/* arch_heap is probably empty, but let's make sure */
binaryheap_reset ( arch_files - > arch_heap ) ;
/*
* Open the archive status directory and read through the list of files
* with the . ready suffix , looking for the earliest files .
@ -720,53 +736,53 @@ pgarch_readyXlog(char *xlog)
/*
* Store the file in our max - heap if it has a high enough priority .
*/
if ( arch_heap - > bh_size < NUM_FILES_PER_DIRECTORY_SCAN )
if ( arch_files - > arch_ heap - > bh_size < NUM_FILES_PER_DIRECTORY_SCAN )
{
/* If the heap isn't full yet, quickly add it. */
arch_file = arch_filenames [ arch_heap - > bh_size ] ;
arch_file = arch_files - > arch_file names [ arch_files - > arch_heap - > bh_size ] ;
strcpy ( arch_file , basename ) ;
binaryheap_add_unordered ( arch_heap , CStringGetDatum ( arch_file ) ) ;
binaryheap_add_unordered ( arch_files - > arch_ heap , CStringGetDatum ( arch_file ) ) ;
/* If we just filled the heap, make it a valid one. */
if ( arch_heap - > bh_size = = NUM_FILES_PER_DIRECTORY_SCAN )
binaryheap_build ( arch_heap ) ;
if ( arch_files - > arch_ heap - > bh_size = = NUM_FILES_PER_DIRECTORY_SCAN )
binaryheap_build ( arch_files - > arch_ heap ) ;
}
else if ( ready_file_comparator ( binaryheap_first ( arch_heap ) ,
else if ( ready_file_comparator ( binaryheap_first ( arch_files - > arch_ heap ) ,
CStringGetDatum ( basename ) , NULL ) > 0 )
{
/*
* Remove the lowest priority file and add the current one to
* the heap .
*/
arch_file = DatumGetCString ( binaryheap_remove_first ( arch_heap ) ) ;
arch_file = DatumGetCString ( binaryheap_remove_first ( arch_files - > arch_ heap ) ) ;
strcpy ( arch_file , basename ) ;
binaryheap_add ( arch_heap , CStringGetDatum ( arch_file ) ) ;
binaryheap_add ( arch_files - > arch_ heap , CStringGetDatum ( arch_file ) ) ;
}
}
FreeDir ( rldir ) ;
/* If no files were found, simply return. */
if ( arch_heap - > bh_size = = 0 )
if ( arch_files - > arch_ heap - > bh_size = = 0 )
return false ;
/*
* If we didn ' t fill the heap , we didn ' t make it a valid one . Do that
* now .
*/
if ( arch_heap - > bh_size < NUM_FILES_PER_DIRECTORY_SCAN )
binaryheap_build ( arch_heap ) ;
if ( arch_files - > arch_ heap - > bh_size < NUM_FILES_PER_DIRECTORY_SCAN )
binaryheap_build ( arch_files - > arch_ heap ) ;
/*
* Fill arch_files array with the files to archive in ascending order
* of priority .
*/
arch_files_size = arch_heap - > bh_size ;
for ( int i = 0 ; i < arch_files_size ; i + + )
arch_files [ i ] = DatumGetCString ( binaryheap_remove_first ( arch_heap ) ) ;
arch_files - > arch_files _size = arch_files - > arch_heap - > bh_size ;
for ( int i = 0 ; i < arch_files - > arch_files _size; i + + )
arch_files - > arch_files [ i ] = DatumGetCString ( binaryheap_remove_first ( arch_files - > arch_heap ) ) ;
/* Return the highest priority file. */
arch_files_size - - ;
strcpy ( xlog , arch_files [ arch_files_size ] ) ;
arch_files - > arch_files _size- - ;
strcpy ( xlog , arch_files - > arch_files [ arch_files - > arch_files_size ] ) ;
return true ;
}