Header And Logo

PostgreSQL
| The world's most advanced open source database.

pgarch.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * pgarch.c
00004  *
00005  *  PostgreSQL WAL archiver
00006  *
00007  *  All functions relating to archiver are included here
00008  *
00009  *  - All functions executed by archiver process
00010  *
00011  *  - archiver is forked from postmaster, and the two
00012  *  processes then communicate using signals. All functions
00013  *  executed by postmaster are included in this file.
00014  *
00015  *  Initial author: Simon Riggs     [email protected]
00016  *
00017  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00018  * Portions Copyright (c) 1994, Regents of the University of California
00019  *
00020  *
00021  * IDENTIFICATION
00022  *    src/backend/postmaster/pgarch.c
00023  *
00024  *-------------------------------------------------------------------------
00025  */
00026 #include "postgres.h"
00027 
00028 #include <fcntl.h>
00029 #include <signal.h>
00030 #include <time.h>
00031 #include <sys/time.h>
00032 #include <sys/wait.h>
00033 #include <unistd.h>
00034 
00035 #include "access/xlog.h"
00036 #include "access/xlog_internal.h"
00037 #include "libpq/pqsignal.h"
00038 #include "miscadmin.h"
00039 #include "postmaster/fork_process.h"
00040 #include "postmaster/pgarch.h"
00041 #include "postmaster/postmaster.h"
00042 #include "storage/fd.h"
00043 #include "storage/ipc.h"
00044 #include "storage/latch.h"
00045 #include "storage/pg_shmem.h"
00046 #include "storage/pmsignal.h"
00047 #include "utils/guc.h"
00048 #include "utils/ps_status.h"
00049 
00050 
00051 /* ----------
00052  * Timer definitions.
00053  * ----------
00054  */
00055 #define PGARCH_AUTOWAKE_INTERVAL 60     /* How often to force a poll of the
00056                                          * archive status directory; in
00057                                          * seconds. */
00058 #define PGARCH_RESTART_INTERVAL 10      /* How often to attempt to restart a
00059                                          * failed archiver; in seconds. */
00060 
00061 /* ----------
00062  * Archiver control info.
00063  *
00064  * We expect that archivable files within pg_xlog will have names between
00065  * MIN_XFN_CHARS and MAX_XFN_CHARS in length, consisting only of characters
00066  * appearing in VALID_XFN_CHARS.  The status files in archive_status have
00067  * corresponding names with ".ready" or ".done" appended.
00068  * ----------
00069  */
00070 #define MIN_XFN_CHARS   16
00071 #define MAX_XFN_CHARS   40
00072 #define VALID_XFN_CHARS "0123456789ABCDEF.history.backup"
00073 
00074 #define NUM_ARCHIVE_RETRIES 3
00075 
00076 
00077 /* ----------
00078  * Local data
00079  * ----------
00080  */
00081 static time_t last_pgarch_start_time;
00082 static time_t last_sigterm_time = 0;
00083 
00084 /*
00085  * Flags set by interrupt handlers for later service in the main loop.
00086  */
00087 static volatile sig_atomic_t got_SIGHUP = false;
00088 static volatile sig_atomic_t got_SIGTERM = false;
00089 static volatile sig_atomic_t wakened = false;
00090 static volatile sig_atomic_t ready_to_stop = false;
00091 
00092 /*
00093  * Latch used by signal handlers to wake up the sleep in the main loop.
00094  */
00095 static Latch mainloop_latch;
00096 
00097 /* ----------
00098  * Local function forward declarations
00099  * ----------
00100  */
00101 #ifdef EXEC_BACKEND
00102 static pid_t pgarch_forkexec(void);
00103 #endif
00104 
00105 NON_EXEC_STATIC void PgArchiverMain(int argc, char *argv[]) __attribute__((noreturn));
00106 static void pgarch_exit(SIGNAL_ARGS);
00107 static void ArchSigHupHandler(SIGNAL_ARGS);
00108 static void ArchSigTermHandler(SIGNAL_ARGS);
00109 static void pgarch_waken(SIGNAL_ARGS);
00110 static void pgarch_waken_stop(SIGNAL_ARGS);
00111 static void pgarch_MainLoop(void);
00112 static void pgarch_ArchiverCopyLoop(void);
00113 static bool pgarch_archiveXlog(char *xlog);
00114 static bool pgarch_readyXlog(char *xlog);
00115 static void pgarch_archiveDone(char *xlog);
00116 
00117 
00118 /* ------------------------------------------------------------
00119  * Public functions called from postmaster follow
00120  * ------------------------------------------------------------
00121  */
00122 
00123 /*
00124  * pgarch_start
00125  *
00126  *  Called from postmaster at startup or after an existing archiver
00127  *  died.  Attempt to fire up a fresh archiver process.
00128  *
00129  *  Returns PID of child process, or 0 if fail.
00130  *
00131  *  Note: if fail, we will be called again from the postmaster main loop.
00132  */
00133 int
00134 pgarch_start(void)
00135 {
00136     time_t      curtime;
00137     pid_t       pgArchPid;
00138 
00139     /*
00140      * Do nothing if no archiver needed
00141      */
00142     if (!XLogArchivingActive())
00143         return 0;
00144 
00145     /*
00146      * Do nothing if too soon since last archiver start.  This is a safety
00147      * valve to protect against continuous respawn attempts if the archiver is
00148      * dying immediately at launch. Note that since we will be re-called from
00149      * the postmaster main loop, we will get another chance later.
00150      */
00151     curtime = time(NULL);
00152     if ((unsigned int) (curtime - last_pgarch_start_time) <
00153         (unsigned int) PGARCH_RESTART_INTERVAL)
00154         return 0;
00155     last_pgarch_start_time = curtime;
00156 
00157 #ifdef EXEC_BACKEND
00158     switch ((pgArchPid = pgarch_forkexec()))
00159 #else
00160     switch ((pgArchPid = fork_process()))
00161 #endif
00162     {
00163         case -1:
00164             ereport(LOG,
00165                     (errmsg("could not fork archiver: %m")));
00166             return 0;
00167 
00168 #ifndef EXEC_BACKEND
00169         case 0:
00170             /* in postmaster child ... */
00171             /* Close the postmaster's sockets */
00172             ClosePostmasterPorts(false);
00173 
00174             /* Lose the postmaster's on-exit routines */
00175             on_exit_reset();
00176 
00177             /* Drop our connection to postmaster's shared memory, as well */
00178             PGSharedMemoryDetach();
00179 
00180             PgArchiverMain(0, NULL);
00181             break;
00182 #endif
00183 
00184         default:
00185             return (int) pgArchPid;
00186     }
00187 
00188     /* shouldn't get here */
00189     return 0;
00190 }
00191 
00192 /* ------------------------------------------------------------
00193  * Local functions called by archiver follow
00194  * ------------------------------------------------------------
00195  */
00196 
00197 
00198 #ifdef EXEC_BACKEND
00199 
00200 /*
00201  * pgarch_forkexec() -
00202  *
00203  * Format up the arglist for, then fork and exec, archive process
00204  */
00205 static pid_t
00206 pgarch_forkexec(void)
00207 {
00208     char       *av[10];
00209     int         ac = 0;
00210 
00211     av[ac++] = "postgres";
00212 
00213     av[ac++] = "--forkarch";
00214 
00215     av[ac++] = NULL;            /* filled in by postmaster_forkexec */
00216 
00217     av[ac] = NULL;
00218     Assert(ac < lengthof(av));
00219 
00220     return postmaster_forkexec(ac, av);
00221 }
00222 #endif   /* EXEC_BACKEND */
00223 
00224 
00225 /*
00226  * PgArchiverMain
00227  *
00228  *  The argc/argv parameters are valid only in EXEC_BACKEND case.  However,
00229  *  since we don't use 'em, it hardly matters...
00230  */
00231 NON_EXEC_STATIC void
00232 PgArchiverMain(int argc, char *argv[])
00233 {
00234     IsUnderPostmaster = true;   /* we are a postmaster subprocess now */
00235 
00236     MyProcPid = getpid();       /* reset MyProcPid */
00237 
00238     MyStartTime = time(NULL);   /* record Start Time for logging */
00239 
00240     /*
00241      * If possible, make this process a group leader, so that the postmaster
00242      * can signal any child processes too.
00243      */
00244 #ifdef HAVE_SETSID
00245     if (setsid() < 0)
00246         elog(FATAL, "setsid() failed: %m");
00247 #endif
00248 
00249     InitializeLatchSupport();       /* needed for latch waits */
00250 
00251     InitLatch(&mainloop_latch); /* initialize latch used in main loop */
00252 
00253     /*
00254      * Ignore all signals usually bound to some action in the postmaster,
00255      * except for SIGHUP, SIGTERM, SIGUSR1, SIGUSR2, and SIGQUIT.
00256      */
00257     pqsignal(SIGHUP, ArchSigHupHandler);
00258     pqsignal(SIGINT, SIG_IGN);
00259     pqsignal(SIGTERM, ArchSigTermHandler);
00260     pqsignal(SIGQUIT, pgarch_exit);
00261     pqsignal(SIGALRM, SIG_IGN);
00262     pqsignal(SIGPIPE, SIG_IGN);
00263     pqsignal(SIGUSR1, pgarch_waken);
00264     pqsignal(SIGUSR2, pgarch_waken_stop);
00265     pqsignal(SIGCHLD, SIG_DFL);
00266     pqsignal(SIGTTIN, SIG_DFL);
00267     pqsignal(SIGTTOU, SIG_DFL);
00268     pqsignal(SIGCONT, SIG_DFL);
00269     pqsignal(SIGWINCH, SIG_DFL);
00270     PG_SETMASK(&UnBlockSig);
00271 
00272     /*
00273      * Identify myself via ps
00274      */
00275     init_ps_display("archiver process", "", "", "");
00276 
00277     pgarch_MainLoop();
00278 
00279     exit(0);
00280 }
00281 
00282 /* SIGQUIT signal handler for archiver process */
00283 static void
00284 pgarch_exit(SIGNAL_ARGS)
00285 {
00286     /* SIGQUIT means curl up and die ... */
00287     exit(1);
00288 }
00289 
00290 /* SIGHUP signal handler for archiver process */
00291 static void
00292 ArchSigHupHandler(SIGNAL_ARGS)
00293 {
00294     int         save_errno = errno;
00295 
00296     /* set flag to re-read config file at next convenient time */
00297     got_SIGHUP = true;
00298     SetLatch(&mainloop_latch);
00299 
00300     errno = save_errno;
00301 }
00302 
00303 /* SIGTERM signal handler for archiver process */
00304 static void
00305 ArchSigTermHandler(SIGNAL_ARGS)
00306 {
00307     int         save_errno = errno;
00308 
00309     /*
00310      * The postmaster never sends us SIGTERM, so we assume that this means
00311      * that init is trying to shut down the whole system.  If we hang around
00312      * too long we'll get SIGKILL'd.  Set flag to prevent starting any more
00313      * archive commands.
00314      */
00315     got_SIGTERM = true;
00316     SetLatch(&mainloop_latch);
00317 
00318     errno = save_errno;
00319 }
00320 
00321 /* SIGUSR1 signal handler for archiver process */
00322 static void
00323 pgarch_waken(SIGNAL_ARGS)
00324 {
00325     int         save_errno = errno;
00326 
00327     /* set flag that there is work to be done */
00328     wakened = true;
00329     SetLatch(&mainloop_latch);
00330 
00331     errno = save_errno;
00332 }
00333 
00334 /* SIGUSR2 signal handler for archiver process */
00335 static void
00336 pgarch_waken_stop(SIGNAL_ARGS)
00337 {
00338     int         save_errno = errno;
00339 
00340     /* set flag to do a final cycle and shut down afterwards */
00341     ready_to_stop = true;
00342     SetLatch(&mainloop_latch);
00343 
00344     errno = save_errno;
00345 }
00346 
00347 /*
00348  * pgarch_MainLoop
00349  *
00350  * Main loop for archiver
00351  */
00352 static void
00353 pgarch_MainLoop(void)
00354 {
00355     pg_time_t   last_copy_time = 0;
00356     bool        time_to_stop;
00357 
00358     /*
00359      * We run the copy loop immediately upon entry, in case there are
00360      * unarchived files left over from a previous database run (or maybe the
00361      * archiver died unexpectedly).  After that we wait for a signal or
00362      * timeout before doing more.
00363      */
00364     wakened = true;
00365 
00366     /*
00367      * There shouldn't be anything for the archiver to do except to wait for a
00368      * signal ... however, the archiver exists to protect our data, so she
00369      * wakes up occasionally to allow herself to be proactive.
00370      */
00371     do
00372     {
00373         ResetLatch(&mainloop_latch);
00374 
00375         /* When we get SIGUSR2, we do one more archive cycle, then exit */
00376         time_to_stop = ready_to_stop;
00377 
00378         /* Check for config update */
00379         if (got_SIGHUP)
00380         {
00381             got_SIGHUP = false;
00382             ProcessConfigFile(PGC_SIGHUP);
00383         }
00384 
00385         /*
00386          * If we've gotten SIGTERM, we normally just sit and do nothing until
00387          * SIGUSR2 arrives.  However, that means a random SIGTERM would
00388          * disable archiving indefinitely, which doesn't seem like a good
00389          * idea.  If more than 60 seconds pass since SIGTERM, exit anyway, so
00390          * that the postmaster can start a new archiver if needed.
00391          */
00392         if (got_SIGTERM)
00393         {
00394             time_t      curtime = time(NULL);
00395 
00396             if (last_sigterm_time == 0)
00397                 last_sigterm_time = curtime;
00398             else if ((unsigned int) (curtime - last_sigterm_time) >=
00399                      (unsigned int) 60)
00400                 break;
00401         }
00402 
00403         /* Do what we're here for */
00404         if (wakened || time_to_stop)
00405         {
00406             wakened = false;
00407             pgarch_ArchiverCopyLoop();
00408             last_copy_time = time(NULL);
00409         }
00410 
00411         /*
00412          * Sleep until a signal is received, or until a poll is forced by
00413          * PGARCH_AUTOWAKE_INTERVAL having passed since last_copy_time, or
00414          * until postmaster dies.
00415          */
00416         if (!time_to_stop)      /* Don't wait during last iteration */
00417         {
00418             pg_time_t   curtime = (pg_time_t) time(NULL);
00419             int         timeout;
00420 
00421             timeout = PGARCH_AUTOWAKE_INTERVAL - (curtime - last_copy_time);
00422             if (timeout > 0)
00423             {
00424                 int         rc;
00425 
00426                 rc = WaitLatch(&mainloop_latch,
00427                              WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
00428                                timeout * 1000L);
00429                 if (rc & WL_TIMEOUT)
00430                     wakened = true;
00431             }
00432             else
00433                 wakened = true;
00434         }
00435 
00436         /*
00437          * The archiver quits either when the postmaster dies (not expected)
00438          * or after completing one more archiving cycle after receiving
00439          * SIGUSR2.
00440          */
00441     } while (PostmasterIsAlive() && !time_to_stop);
00442 }
00443 
00444 /*
00445  * pgarch_ArchiverCopyLoop
00446  *
00447  * Archives all outstanding xlogs then returns
00448  */
00449 static void
00450 pgarch_ArchiverCopyLoop(void)
00451 {
00452     char        xlog[MAX_XFN_CHARS + 1];
00453 
00454     /*
00455      * loop through all xlogs with archive_status of .ready and archive
00456      * them...mostly we expect this to be a single file, though it is possible
00457      * some backend will add files onto the list of those that need archiving
00458      * while we are still copying earlier archives
00459      */
00460     while (pgarch_readyXlog(xlog))
00461     {
00462         int         failures = 0;
00463 
00464         for (;;)
00465         {
00466             /*
00467              * Do not initiate any more archive commands after receiving
00468              * SIGTERM, nor after the postmaster has died unexpectedly. The
00469              * first condition is to try to keep from having init SIGKILL the
00470              * command, and the second is to avoid conflicts with another
00471              * archiver spawned by a newer postmaster.
00472              */
00473             if (got_SIGTERM || !PostmasterIsAlive())
00474                 return;
00475 
00476             /*
00477              * Check for config update.  This is so that we'll adopt a new
00478              * setting for archive_command as soon as possible, even if there
00479              * is a backlog of files to be archived.
00480              */
00481             if (got_SIGHUP)
00482             {
00483                 got_SIGHUP = false;
00484                 ProcessConfigFile(PGC_SIGHUP);
00485             }
00486 
00487             /* can't do anything if no command ... */
00488             if (!XLogArchiveCommandSet())
00489             {
00490                 ereport(WARNING,
00491                         (errmsg("archive_mode enabled, yet archive_command is not set")));
00492                 return;
00493             }
00494 
00495             if (pgarch_archiveXlog(xlog))
00496             {
00497                 /* successful */
00498                 pgarch_archiveDone(xlog);
00499                 break;          /* out of inner retry loop */
00500             }
00501             else
00502             {
00503                 if (++failures >= NUM_ARCHIVE_RETRIES)
00504                 {
00505                     ereport(WARNING,
00506                             (errmsg("archiving transaction log file \"%s\" failed too many times, will try again later",
00507                                     xlog)));
00508                     return;     /* give up archiving for now */
00509                 }
00510                 pg_usleep(1000000L);    /* wait a bit before retrying */
00511             }
00512         }
00513     }
00514 }
00515 
00516 /*
00517  * pgarch_archiveXlog
00518  *
00519  * Invokes system(3) to copy one archive file to wherever it should go
00520  *
00521  * Returns true if successful
00522  */
00523 static bool
00524 pgarch_archiveXlog(char *xlog)
00525 {
00526     char        xlogarchcmd[MAXPGPATH];
00527     char        pathname[MAXPGPATH];
00528     char        activitymsg[MAXFNAMELEN + 16];
00529     char       *dp;
00530     char       *endp;
00531     const char *sp;
00532     int         rc;
00533 
00534     snprintf(pathname, MAXPGPATH, XLOGDIR "/%s", xlog);
00535 
00536     /*
00537      * construct the command to be executed
00538      */
00539     dp = xlogarchcmd;
00540     endp = xlogarchcmd + MAXPGPATH - 1;
00541     *endp = '\0';
00542 
00543     for (sp = XLogArchiveCommand; *sp; sp++)
00544     {
00545         if (*sp == '%')
00546         {
00547             switch (sp[1])
00548             {
00549                 case 'p':
00550                     /* %p: relative path of source file */
00551                     sp++;
00552                     strlcpy(dp, pathname, endp - dp);
00553                     make_native_path(dp);
00554                     dp += strlen(dp);
00555                     break;
00556                 case 'f':
00557                     /* %f: filename of source file */
00558                     sp++;
00559                     strlcpy(dp, xlog, endp - dp);
00560                     dp += strlen(dp);
00561                     break;
00562                 case '%':
00563                     /* convert %% to a single % */
00564                     sp++;
00565                     if (dp < endp)
00566                         *dp++ = *sp;
00567                     break;
00568                 default:
00569                     /* otherwise treat the % as not special */
00570                     if (dp < endp)
00571                         *dp++ = *sp;
00572                     break;
00573             }
00574         }
00575         else
00576         {
00577             if (dp < endp)
00578                 *dp++ = *sp;
00579         }
00580     }
00581     *dp = '\0';
00582 
00583     ereport(DEBUG3,
00584             (errmsg_internal("executing archive command \"%s\"",
00585                              xlogarchcmd)));
00586 
00587     /* Report archive activity in PS display */
00588     snprintf(activitymsg, sizeof(activitymsg), "archiving %s", xlog);
00589     set_ps_display(activitymsg, false);
00590 
00591     rc = system(xlogarchcmd);
00592     if (rc != 0)
00593     {
00594         /*
00595          * If either the shell itself, or a called command, died on a signal,
00596          * abort the archiver.  We do this because system() ignores SIGINT and
00597          * SIGQUIT while waiting; so a signal is very likely something that
00598          * should have interrupted us too.  If we overreact it's no big deal,
00599          * the postmaster will just start the archiver again.
00600          *
00601          * Per the Single Unix Spec, shells report exit status > 128 when a
00602          * called command died on a signal.
00603          */
00604         int         lev = (WIFSIGNALED(rc) || WEXITSTATUS(rc) > 128) ? FATAL : LOG;
00605 
00606         if (WIFEXITED(rc))
00607         {
00608             ereport(lev,
00609                     (errmsg("archive command failed with exit code %d",
00610                             WEXITSTATUS(rc)),
00611                      errdetail("The failed archive command was: %s",
00612                                xlogarchcmd)));
00613         }
00614         else if (WIFSIGNALED(rc))
00615         {
00616 #if defined(WIN32)
00617             ereport(lev,
00618                   (errmsg("archive command was terminated by exception 0x%X",
00619                           WTERMSIG(rc)),
00620                    errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
00621                    errdetail("The failed archive command was: %s",
00622                              xlogarchcmd)));
00623 #elif defined(HAVE_DECL_SYS_SIGLIST) && HAVE_DECL_SYS_SIGLIST
00624             ereport(lev,
00625                     (errmsg("archive command was terminated by signal %d: %s",
00626                             WTERMSIG(rc),
00627               WTERMSIG(rc) < NSIG ? sys_siglist[WTERMSIG(rc)] : "(unknown)"),
00628                      errdetail("The failed archive command was: %s",
00629                                xlogarchcmd)));
00630 #else
00631             ereport(lev,
00632                     (errmsg("archive command was terminated by signal %d",
00633                             WTERMSIG(rc)),
00634                      errdetail("The failed archive command was: %s",
00635                                xlogarchcmd)));
00636 #endif
00637         }
00638         else
00639         {
00640             ereport(lev,
00641                 (errmsg("archive command exited with unrecognized status %d",
00642                         rc),
00643                  errdetail("The failed archive command was: %s",
00644                            xlogarchcmd)));
00645         }
00646 
00647         snprintf(activitymsg, sizeof(activitymsg), "failed on %s", xlog);
00648         set_ps_display(activitymsg, false);
00649 
00650         return false;
00651     }
00652     ereport(DEBUG1,
00653             (errmsg("archived transaction log file \"%s\"", xlog)));
00654 
00655     snprintf(activitymsg, sizeof(activitymsg), "last was %s", xlog);
00656     set_ps_display(activitymsg, false);
00657 
00658     return true;
00659 }
00660 
00661 /*
00662  * pgarch_readyXlog
00663  *
00664  * Return name of the oldest xlog file that has not yet been archived.
00665  * No notification is set that file archiving is now in progress, so
00666  * this would need to be extended if multiple concurrent archival
00667  * tasks were created. If a failure occurs, we will completely
00668  * re-copy the file at the next available opportunity.
00669  *
00670  * It is important that we return the oldest, so that we archive xlogs
00671  * in order that they were written, for two reasons:
00672  * 1) to maintain the sequential chain of xlogs required for recovery
00673  * 2) because the oldest ones will sooner become candidates for
00674  * recycling at time of checkpoint
00675  *
00676  * NOTE: the "oldest" comparison will presently consider all segments of
00677  * a timeline with a smaller ID to be older than all segments of a timeline
00678  * with a larger ID; the net result being that past timelines are given
00679  * higher priority for archiving.  This seems okay, or at least not
00680  * obviously worth changing.
00681  */
00682 static bool
00683 pgarch_readyXlog(char *xlog)
00684 {
00685     /*
00686      * open xlog status directory and read through list of xlogs that have the
00687      * .ready suffix, looking for earliest file. It is possible to optimise
00688      * this code, though only a single file is expected on the vast majority
00689      * of calls, so....
00690      */
00691     char        XLogArchiveStatusDir[MAXPGPATH];
00692     char        newxlog[MAX_XFN_CHARS + 6 + 1];
00693     DIR        *rldir;
00694     struct dirent *rlde;
00695     bool        found = false;
00696 
00697     snprintf(XLogArchiveStatusDir, MAXPGPATH, XLOGDIR "/archive_status");
00698     rldir = AllocateDir(XLogArchiveStatusDir);
00699     if (rldir == NULL)
00700         ereport(ERROR,
00701                 (errcode_for_file_access(),
00702                  errmsg("could not open archive status directory \"%s\": %m",
00703                         XLogArchiveStatusDir)));
00704 
00705     while ((rlde = ReadDir(rldir, XLogArchiveStatusDir)) != NULL)
00706     {
00707         int         basenamelen = (int) strlen(rlde->d_name) - 6;
00708 
00709         if (basenamelen >= MIN_XFN_CHARS &&
00710             basenamelen <= MAX_XFN_CHARS &&
00711             strspn(rlde->d_name, VALID_XFN_CHARS) >= basenamelen &&
00712             strcmp(rlde->d_name + basenamelen, ".ready") == 0)
00713         {
00714             if (!found)
00715             {
00716                 strcpy(newxlog, rlde->d_name);
00717                 found = true;
00718             }
00719             else
00720             {
00721                 if (strcmp(rlde->d_name, newxlog) < 0)
00722                     strcpy(newxlog, rlde->d_name);
00723             }
00724         }
00725     }
00726     FreeDir(rldir);
00727 
00728     if (found)
00729     {
00730         /* truncate off the .ready */
00731         newxlog[strlen(newxlog) - 6] = '\0';
00732         strcpy(xlog, newxlog);
00733     }
00734     return found;
00735 }
00736 
00737 /*
00738  * pgarch_archiveDone
00739  *
00740  * Emit notification that an xlog file has been successfully archived.
00741  * We do this by renaming the status file from NNN.ready to NNN.done.
00742  * Eventually, a checkpoint process will notice this and delete both the
00743  * NNN.done file and the xlog file itself.
00744  */
00745 static void
00746 pgarch_archiveDone(char *xlog)
00747 {
00748     char        rlogready[MAXPGPATH];
00749     char        rlogdone[MAXPGPATH];
00750 
00751     StatusFilePath(rlogready, xlog, ".ready");
00752     StatusFilePath(rlogdone, xlog, ".done");
00753     if (rename(rlogready, rlogdone) < 0)
00754         ereport(WARNING,
00755                 (errcode_for_file_access(),
00756                  errmsg("could not rename file \"%s\" to \"%s\": %m",
00757                         rlogready, rlogdone)));
00758 }