~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/backend/postmaster/pgarch.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * pgarch.c
 
4
 *
 
5
 *      PostgreSQL WAL archiver
 
6
 *
 
7
 *      All functions relating to archiver are included here
 
8
 *
 
9
 *      - All functions executed by archiver process
 
10
 *
 
11
 *      - archiver is forked from postmaster, and the two
 
12
 *      processes then communicate using signals. All functions
 
13
 *      executed by postmaster are included in this file.
 
14
 *
 
15
 *      Initial author: Simon Riggs             simon@2ndquadrant.com
 
16
 *
 
17
 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
 
18
 * Portions Copyright (c) 1994, Regents of the University of California
 
19
 *
 
20
 *
 
21
 * IDENTIFICATION
 
22
 *        src/backend/postmaster/pgarch.c
 
23
 *
 
24
 *-------------------------------------------------------------------------
 
25
 */
 
26
#include "postgres.h"
 
27
 
 
28
#include <fcntl.h>
 
29
#include <signal.h>
 
30
#include <time.h>
 
31
#include <sys/time.h>
 
32
#include <sys/wait.h>
 
33
#include <unistd.h>
 
34
 
 
35
#include "access/xlog_internal.h"
 
36
#include "libpq/pqsignal.h"
 
37
#include "miscadmin.h"
 
38
#include "postmaster/fork_process.h"
 
39
#include "postmaster/pgarch.h"
 
40
#include "postmaster/postmaster.h"
 
41
#include "storage/fd.h"
 
42
#include "storage/ipc.h"
 
43
#include "storage/pg_shmem.h"
 
44
#include "storage/pmsignal.h"
 
45
#include "utils/guc.h"
 
46
#include "utils/ps_status.h"
 
47
 
 
48
 
 
49
/* ----------
 
50
 * Timer definitions.
 
51
 * ----------
 
52
 */
 
53
#define PGARCH_AUTOWAKE_INTERVAL 60             /* How often to force a poll of the
 
54
                                                                                 * archive status directory; in
 
55
                                                                                 * seconds. */
 
56
#define PGARCH_RESTART_INTERVAL 10              /* How often to attempt to restart a
 
57
                                                                                 * failed archiver; in seconds. */
 
58
 
 
59
/* ----------
 
60
 * Archiver control info.
 
61
 *
 
62
 * We expect that archivable files within pg_xlog will have names between
 
63
 * MIN_XFN_CHARS and MAX_XFN_CHARS in length, consisting only of characters
 
64
 * appearing in VALID_XFN_CHARS.  The status files in archive_status have
 
65
 * corresponding names with ".ready" or ".done" appended.
 
66
 * ----------
 
67
 */
 
68
#define MIN_XFN_CHARS   16
 
69
#define MAX_XFN_CHARS   40
 
70
#define VALID_XFN_CHARS "0123456789ABCDEF.history.backup"
 
71
 
 
72
#define NUM_ARCHIVE_RETRIES 3
 
73
 
 
74
 
 
75
/* ----------
 
76
 * Local data
 
77
 * ----------
 
78
 */
 
79
static time_t last_pgarch_start_time;
 
80
static time_t last_sigterm_time = 0;
 
81
 
 
82
/*
 
83
 * Flags set by interrupt handlers for later service in the main loop.
 
84
 */
 
85
static volatile sig_atomic_t got_SIGHUP = false;
 
86
static volatile sig_atomic_t got_SIGTERM = false;
 
87
static volatile sig_atomic_t wakened = false;
 
88
static volatile sig_atomic_t ready_to_stop = false;
 
89
 
 
90
/* ----------
 
91
 * Local function forward declarations
 
92
 * ----------
 
93
 */
 
94
#ifdef EXEC_BACKEND
 
95
static pid_t pgarch_forkexec(void);
 
96
#endif
 
97
 
 
98
NON_EXEC_STATIC void PgArchiverMain(int argc, char *argv[]);
 
99
static void pgarch_exit(SIGNAL_ARGS);
 
100
static void ArchSigHupHandler(SIGNAL_ARGS);
 
101
static void ArchSigTermHandler(SIGNAL_ARGS);
 
102
static void pgarch_waken(SIGNAL_ARGS);
 
103
static void pgarch_waken_stop(SIGNAL_ARGS);
 
104
static void pgarch_MainLoop(void);
 
105
static void pgarch_ArchiverCopyLoop(void);
 
106
static bool pgarch_archiveXlog(char *xlog);
 
107
static bool pgarch_readyXlog(char *xlog);
 
108
static void pgarch_archiveDone(char *xlog);
 
109
 
 
110
 
 
111
/* ------------------------------------------------------------
 
112
 * Public functions called from postmaster follow
 
113
 * ------------------------------------------------------------
 
114
 */
 
115
 
 
116
/*
 
117
 * pgarch_start
 
118
 *
 
119
 *      Called from postmaster at startup or after an existing archiver
 
120
 *      died.  Attempt to fire up a fresh archiver process.
 
121
 *
 
122
 *      Returns PID of child process, or 0 if fail.
 
123
 *
 
124
 *      Note: if fail, we will be called again from the postmaster main loop.
 
125
 */
 
126
int
 
127
pgarch_start(void)
 
128
{
 
129
        time_t          curtime;
 
130
        pid_t           pgArchPid;
 
131
 
 
132
        /*
 
133
         * Do nothing if no archiver needed
 
134
         */
 
135
        if (!XLogArchivingActive())
 
136
                return 0;
 
137
 
 
138
        /*
 
139
         * Do nothing if too soon since last archiver start.  This is a safety
 
140
         * valve to protect against continuous respawn attempts if the archiver is
 
141
         * dying immediately at launch. Note that since we will be re-called from
 
142
         * the postmaster main loop, we will get another chance later.
 
143
         */
 
144
        curtime = time(NULL);
 
145
        if ((unsigned int) (curtime - last_pgarch_start_time) <
 
146
                (unsigned int) PGARCH_RESTART_INTERVAL)
 
147
                return 0;
 
148
        last_pgarch_start_time = curtime;
 
149
 
 
150
#ifdef EXEC_BACKEND
 
151
        switch ((pgArchPid = pgarch_forkexec()))
 
152
#else
 
153
        switch ((pgArchPid = fork_process()))
 
154
#endif
 
155
        {
 
156
                case -1:
 
157
                        ereport(LOG,
 
158
                                        (errmsg("could not fork archiver: %m")));
 
159
                        return 0;
 
160
 
 
161
#ifndef EXEC_BACKEND
 
162
                case 0:
 
163
                        /* in postmaster child ... */
 
164
                        /* Close the postmaster's sockets */
 
165
                        ClosePostmasterPorts(false);
 
166
 
 
167
                        /* Lose the postmaster's on-exit routines */
 
168
                        on_exit_reset();
 
169
 
 
170
                        /* Drop our connection to postmaster's shared memory, as well */
 
171
                        PGSharedMemoryDetach();
 
172
 
 
173
                        PgArchiverMain(0, NULL);
 
174
                        break;
 
175
#endif
 
176
 
 
177
                default:
 
178
                        return (int) pgArchPid;
 
179
        }
 
180
 
 
181
        /* shouldn't get here */
 
182
        return 0;
 
183
}
 
184
 
 
185
/* ------------------------------------------------------------
 
186
 * Local functions called by archiver follow
 
187
 * ------------------------------------------------------------
 
188
 */
 
189
 
 
190
 
 
191
#ifdef EXEC_BACKEND
 
192
 
 
193
/*
 
194
 * pgarch_forkexec() -
 
195
 *
 
196
 * Format up the arglist for, then fork and exec, archive process
 
197
 */
 
198
static pid_t
 
199
pgarch_forkexec(void)
 
200
{
 
201
        char       *av[10];
 
202
        int                     ac = 0;
 
203
 
 
204
        av[ac++] = "postgres";
 
205
 
 
206
        av[ac++] = "--forkarch";
 
207
 
 
208
        av[ac++] = NULL;                        /* filled in by postmaster_forkexec */
 
209
 
 
210
        av[ac] = NULL;
 
211
        Assert(ac < lengthof(av));
 
212
 
 
213
        return postmaster_forkexec(ac, av);
 
214
}
 
215
#endif   /* EXEC_BACKEND */
 
216
 
 
217
 
 
218
/*
 
219
 * PgArchiverMain
 
220
 *
 
221
 *      The argc/argv parameters are valid only in EXEC_BACKEND case.  However,
 
222
 *      since we don't use 'em, it hardly matters...
 
223
 */
 
224
NON_EXEC_STATIC void
 
225
PgArchiverMain(int argc, char *argv[])
 
226
{
 
227
        IsUnderPostmaster = true;       /* we are a postmaster subprocess now */
 
228
 
 
229
        MyProcPid = getpid();           /* reset MyProcPid */
 
230
 
 
231
        MyStartTime = time(NULL);       /* record Start Time for logging */
 
232
 
 
233
        /*
 
234
         * If possible, make this process a group leader, so that the postmaster
 
235
         * can signal any child processes too.
 
236
         */
 
237
#ifdef HAVE_SETSID
 
238
        if (setsid() < 0)
 
239
                elog(FATAL, "setsid() failed: %m");
 
240
#endif
 
241
 
 
242
        /*
 
243
         * Ignore all signals usually bound to some action in the postmaster,
 
244
         * except for SIGHUP, SIGTERM, SIGUSR1, SIGUSR2, and SIGQUIT.
 
245
         */
 
246
        pqsignal(SIGHUP, ArchSigHupHandler);
 
247
        pqsignal(SIGINT, SIG_IGN);
 
248
        pqsignal(SIGTERM, ArchSigTermHandler);
 
249
        pqsignal(SIGQUIT, pgarch_exit);
 
250
        pqsignal(SIGALRM, SIG_IGN);
 
251
        pqsignal(SIGPIPE, SIG_IGN);
 
252
        pqsignal(SIGUSR1, pgarch_waken);
 
253
        pqsignal(SIGUSR2, pgarch_waken_stop);
 
254
        pqsignal(SIGCHLD, SIG_DFL);
 
255
        pqsignal(SIGTTIN, SIG_DFL);
 
256
        pqsignal(SIGTTOU, SIG_DFL);
 
257
        pqsignal(SIGCONT, SIG_DFL);
 
258
        pqsignal(SIGWINCH, SIG_DFL);
 
259
        PG_SETMASK(&UnBlockSig);
 
260
 
 
261
        /*
 
262
         * Identify myself via ps
 
263
         */
 
264
        init_ps_display("archiver process", "", "", "");
 
265
 
 
266
        pgarch_MainLoop();
 
267
 
 
268
        exit(0);
 
269
}
 
270
 
 
271
/* SIGQUIT signal handler for archiver process */
 
272
static void
 
273
pgarch_exit(SIGNAL_ARGS)
 
274
{
 
275
        /* SIGQUIT means curl up and die ... */
 
276
        exit(1);
 
277
}
 
278
 
 
279
/* SIGHUP signal handler for archiver process */
 
280
static void
 
281
ArchSigHupHandler(SIGNAL_ARGS)
 
282
{
 
283
        /* set flag to re-read config file at next convenient time */
 
284
        got_SIGHUP = true;
 
285
}
 
286
 
 
287
/* SIGTERM signal handler for archiver process */
 
288
static void
 
289
ArchSigTermHandler(SIGNAL_ARGS)
 
290
{
 
291
        /*
 
292
         * The postmaster never sends us SIGTERM, so we assume that this means
 
293
         * that init is trying to shut down the whole system.  If we hang around
 
294
         * too long we'll get SIGKILL'd.  Set flag to prevent starting any more
 
295
         * archive commands.
 
296
         */
 
297
        got_SIGTERM = true;
 
298
}
 
299
 
 
300
/* SIGUSR1 signal handler for archiver process */
 
301
static void
 
302
pgarch_waken(SIGNAL_ARGS)
 
303
{
 
304
        /* set flag that there is work to be done */
 
305
        wakened = true;
 
306
}
 
307
 
 
308
/* SIGUSR2 signal handler for archiver process */
 
309
static void
 
310
pgarch_waken_stop(SIGNAL_ARGS)
 
311
{
 
312
        /* set flag to do a final cycle and shut down afterwards */
 
313
        ready_to_stop = true;
 
314
}
 
315
 
 
316
/*
 
317
 * pgarch_MainLoop
 
318
 *
 
319
 * Main loop for archiver
 
320
 */
 
321
static void
 
322
pgarch_MainLoop(void)
 
323
{
 
324
        time_t          last_copy_time = 0;
 
325
        bool            time_to_stop;
 
326
 
 
327
        /*
 
328
         * We run the copy loop immediately upon entry, in case there are
 
329
         * unarchived files left over from a previous database run (or maybe the
 
330
         * archiver died unexpectedly).  After that we wait for a signal or
 
331
         * timeout before doing more.
 
332
         */
 
333
        wakened = true;
 
334
 
 
335
        do
 
336
        {
 
337
                /* When we get SIGUSR2, we do one more archive cycle, then exit */
 
338
                time_to_stop = ready_to_stop;
 
339
 
 
340
                /* Check for config update */
 
341
                if (got_SIGHUP)
 
342
                {
 
343
                        got_SIGHUP = false;
 
344
                        ProcessConfigFile(PGC_SIGHUP);
 
345
                }
 
346
 
 
347
                /*
 
348
                 * If we've gotten SIGTERM, we normally just sit and do nothing until
 
349
                 * SIGUSR2 arrives.  However, that means a random SIGTERM would
 
350
                 * disable archiving indefinitely, which doesn't seem like a good
 
351
                 * idea.  If more than 60 seconds pass since SIGTERM, exit anyway, so
 
352
                 * that the postmaster can start a new archiver if needed.
 
353
                 */
 
354
                if (got_SIGTERM)
 
355
                {
 
356
                        time_t          curtime = time(NULL);
 
357
 
 
358
                        if (last_sigterm_time == 0)
 
359
                                last_sigterm_time = curtime;
 
360
                        else if ((unsigned int) (curtime - last_sigterm_time) >=
 
361
                                         (unsigned int) 60)
 
362
                                break;
 
363
                }
 
364
 
 
365
                /* Do what we're here for */
 
366
                if (wakened || time_to_stop)
 
367
                {
 
368
                        wakened = false;
 
369
                        pgarch_ArchiverCopyLoop();
 
370
                        last_copy_time = time(NULL);
 
371
                }
 
372
 
 
373
                /*
 
374
                 * There shouldn't be anything for the archiver to do except to wait
 
375
                 * for a signal ... however, the archiver exists to protect our data,
 
376
                 * so she wakes up occasionally to allow herself to be proactive.
 
377
                 *
 
378
                 * On some platforms, signals won't interrupt the sleep.  To ensure we
 
379
                 * respond reasonably promptly when someone signals us, break down the
 
380
                 * sleep into 1-second increments, and check for interrupts after each
 
381
                 * nap.
 
382
                 */
 
383
                while (!(wakened || ready_to_stop || got_SIGHUP ||
 
384
                                 !PostmasterIsAlive(true)))
 
385
                {
 
386
                        time_t          curtime;
 
387
 
 
388
                        pg_usleep(1000000L);
 
389
                        curtime = time(NULL);
 
390
                        if ((unsigned int) (curtime - last_copy_time) >=
 
391
                                (unsigned int) PGARCH_AUTOWAKE_INTERVAL)
 
392
                                wakened = true;
 
393
                }
 
394
 
 
395
                /*
 
396
                 * The archiver quits either when the postmaster dies (not expected)
 
397
                 * or after completing one more archiving cycle after receiving
 
398
                 * SIGUSR2.
 
399
                 */
 
400
        } while (PostmasterIsAlive(true) && !time_to_stop);
 
401
}
 
402
 
 
403
/*
 
404
 * pgarch_ArchiverCopyLoop
 
405
 *
 
406
 * Archives all outstanding xlogs then returns
 
407
 */
 
408
static void
 
409
pgarch_ArchiverCopyLoop(void)
 
410
{
 
411
        char            xlog[MAX_XFN_CHARS + 1];
 
412
 
 
413
        /*
 
414
         * loop through all xlogs with archive_status of .ready and archive
 
415
         * them...mostly we expect this to be a single file, though it is possible
 
416
         * some backend will add files onto the list of those that need archiving
 
417
         * while we are still copying earlier archives
 
418
         */
 
419
        while (pgarch_readyXlog(xlog))
 
420
        {
 
421
                int                     failures = 0;
 
422
 
 
423
                for (;;)
 
424
                {
 
425
                        /*
 
426
                         * Do not initiate any more archive commands after receiving
 
427
                         * SIGTERM, nor after the postmaster has died unexpectedly. The
 
428
                         * first condition is to try to keep from having init SIGKILL the
 
429
                         * command, and the second is to avoid conflicts with another
 
430
                         * archiver spawned by a newer postmaster.
 
431
                         */
 
432
                        if (got_SIGTERM || !PostmasterIsAlive(true))
 
433
                                return;
 
434
 
 
435
                        /*
 
436
                         * Check for config update.  This is so that we'll adopt a new
 
437
                         * setting for archive_command as soon as possible, even if there
 
438
                         * is a backlog of files to be archived.
 
439
                         */
 
440
                        if (got_SIGHUP)
 
441
                        {
 
442
                                got_SIGHUP = false;
 
443
                                ProcessConfigFile(PGC_SIGHUP);
 
444
                        }
 
445
 
 
446
                        /* can't do anything if no command ... */
 
447
                        if (!XLogArchiveCommandSet())
 
448
                        {
 
449
                                ereport(WARNING,
 
450
                                                (errmsg("archive_mode enabled, yet archive_command is not set")));
 
451
                                return;
 
452
                        }
 
453
 
 
454
                        if (pgarch_archiveXlog(xlog))
 
455
                        {
 
456
                                /* successful */
 
457
                                pgarch_archiveDone(xlog);
 
458
                                break;                  /* out of inner retry loop */
 
459
                        }
 
460
                        else
 
461
                        {
 
462
                                if (++failures >= NUM_ARCHIVE_RETRIES)
 
463
                                {
 
464
                                        ereport(WARNING,
 
465
                                                        (errmsg("transaction log file \"%s\" could not be archived: too many failures",
 
466
                                                                        xlog)));
 
467
                                        return;         /* give up archiving for now */
 
468
                                }
 
469
                                pg_usleep(1000000L);    /* wait a bit before retrying */
 
470
                        }
 
471
                }
 
472
        }
 
473
}
 
474
 
 
475
/*
 
476
 * pgarch_archiveXlog
 
477
 *
 
478
 * Invokes system(3) to copy one archive file to wherever it should go
 
479
 *
 
480
 * Returns true if successful
 
481
 */
 
482
static bool
 
483
pgarch_archiveXlog(char *xlog)
 
484
{
 
485
        char            xlogarchcmd[MAXPGPATH];
 
486
        char            pathname[MAXPGPATH];
 
487
        char            activitymsg[MAXFNAMELEN + 16];
 
488
        char       *dp;
 
489
        char       *endp;
 
490
        const char *sp;
 
491
        int                     rc;
 
492
 
 
493
        snprintf(pathname, MAXPGPATH, XLOGDIR "/%s", xlog);
 
494
 
 
495
        /*
 
496
         * construct the command to be executed
 
497
         */
 
498
        dp = xlogarchcmd;
 
499
        endp = xlogarchcmd + MAXPGPATH - 1;
 
500
        *endp = '\0';
 
501
 
 
502
        for (sp = XLogArchiveCommand; *sp; sp++)
 
503
        {
 
504
                if (*sp == '%')
 
505
                {
 
506
                        switch (sp[1])
 
507
                        {
 
508
                                case 'p':
 
509
                                        /* %p: relative path of source file */
 
510
                                        sp++;
 
511
                                        strlcpy(dp, pathname, endp - dp);
 
512
                                        make_native_path(dp);
 
513
                                        dp += strlen(dp);
 
514
                                        break;
 
515
                                case 'f':
 
516
                                        /* %f: filename of source file */
 
517
                                        sp++;
 
518
                                        strlcpy(dp, xlog, endp - dp);
 
519
                                        dp += strlen(dp);
 
520
                                        break;
 
521
                                case '%':
 
522
                                        /* convert %% to a single % */
 
523
                                        sp++;
 
524
                                        if (dp < endp)
 
525
                                                *dp++ = *sp;
 
526
                                        break;
 
527
                                default:
 
528
                                        /* otherwise treat the % as not special */
 
529
                                        if (dp < endp)
 
530
                                                *dp++ = *sp;
 
531
                                        break;
 
532
                        }
 
533
                }
 
534
                else
 
535
                {
 
536
                        if (dp < endp)
 
537
                                *dp++ = *sp;
 
538
                }
 
539
        }
 
540
        *dp = '\0';
 
541
 
 
542
        ereport(DEBUG3,
 
543
                        (errmsg_internal("executing archive command \"%s\"",
 
544
                                                         xlogarchcmd)));
 
545
 
 
546
        /* Report archive activity in PS display */
 
547
        snprintf(activitymsg, sizeof(activitymsg), "archiving %s", xlog);
 
548
        set_ps_display(activitymsg, false);
 
549
 
 
550
        rc = system(xlogarchcmd);
 
551
        if (rc != 0)
 
552
        {
 
553
                /*
 
554
                 * If either the shell itself, or a called command, died on a signal,
 
555
                 * abort the archiver.  We do this because system() ignores SIGINT and
 
556
                 * SIGQUIT while waiting; so a signal is very likely something that
 
557
                 * should have interrupted us too.      If we overreact it's no big deal,
 
558
                 * the postmaster will just start the archiver again.
 
559
                 *
 
560
                 * Per the Single Unix Spec, shells report exit status > 128 when a
 
561
                 * called command died on a signal.
 
562
                 */
 
563
                int                     lev = (WIFSIGNALED(rc) || WEXITSTATUS(rc) > 128) ? FATAL : LOG;
 
564
 
 
565
                if (WIFEXITED(rc))
 
566
                {
 
567
                        ereport(lev,
 
568
                                        (errmsg("archive command failed with exit code %d",
 
569
                                                        WEXITSTATUS(rc)),
 
570
                                         errdetail("The failed archive command was: %s",
 
571
                                                           xlogarchcmd)));
 
572
                }
 
573
                else if (WIFSIGNALED(rc))
 
574
                {
 
575
#if defined(WIN32)
 
576
                        ereport(lev,
 
577
                                  (errmsg("archive command was terminated by exception 0x%X",
 
578
                                                  WTERMSIG(rc)),
 
579
                                   errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
 
580
                                   errdetail("The failed archive command was: %s",
 
581
                                                         xlogarchcmd)));
 
582
#elif defined(HAVE_DECL_SYS_SIGLIST) && HAVE_DECL_SYS_SIGLIST
 
583
                        ereport(lev,
 
584
                                        (errmsg("archive command was terminated by signal %d: %s",
 
585
                                                        WTERMSIG(rc),
 
586
                          WTERMSIG(rc) < NSIG ? sys_siglist[WTERMSIG(rc)] : "(unknown)"),
 
587
                                         errdetail("The failed archive command was: %s",
 
588
                                                           xlogarchcmd)));
 
589
#else
 
590
                        ereport(lev,
 
591
                                        (errmsg("archive command was terminated by signal %d",
 
592
                                                        WTERMSIG(rc)),
 
593
                                         errdetail("The failed archive command was: %s",
 
594
                                                           xlogarchcmd)));
 
595
#endif
 
596
                }
 
597
                else
 
598
                {
 
599
                        ereport(lev,
 
600
                                (errmsg("archive command exited with unrecognized status %d",
 
601
                                                rc),
 
602
                                 errdetail("The failed archive command was: %s",
 
603
                                                   xlogarchcmd)));
 
604
                }
 
605
 
 
606
                snprintf(activitymsg, sizeof(activitymsg), "failed on %s", xlog);
 
607
                set_ps_display(activitymsg, false);
 
608
 
 
609
                return false;
 
610
        }
 
611
        ereport(DEBUG1,
 
612
                        (errmsg("archived transaction log file \"%s\"", xlog)));
 
613
 
 
614
        snprintf(activitymsg, sizeof(activitymsg), "last was %s", xlog);
 
615
        set_ps_display(activitymsg, false);
 
616
 
 
617
        return true;
 
618
}
 
619
 
 
620
/*
 
621
 * pgarch_readyXlog
 
622
 *
 
623
 * Return name of the oldest xlog file that has not yet been archived.
 
624
 * No notification is set that file archiving is now in progress, so
 
625
 * this would need to be extended if multiple concurrent archival
 
626
 * tasks were created. If a failure occurs, we will completely
 
627
 * re-copy the file at the next available opportunity.
 
628
 *
 
629
 * It is important that we return the oldest, so that we archive xlogs
 
630
 * in order that they were written, for two reasons:
 
631
 * 1) to maintain the sequential chain of xlogs required for recovery
 
632
 * 2) because the oldest ones will sooner become candidates for
 
633
 * recycling at time of checkpoint
 
634
 *
 
635
 * NOTE: the "oldest" comparison will presently consider all segments of
 
636
 * a timeline with a smaller ID to be older than all segments of a timeline
 
637
 * with a larger ID; the net result being that past timelines are given
 
638
 * higher priority for archiving.  This seems okay, or at least not
 
639
 * obviously worth changing.
 
640
 */
 
641
static bool
 
642
pgarch_readyXlog(char *xlog)
 
643
{
 
644
        /*
 
645
         * open xlog status directory and read through list of xlogs that have the
 
646
         * .ready suffix, looking for earliest file. It is possible to optimise
 
647
         * this code, though only a single file is expected on the vast majority
 
648
         * of calls, so....
 
649
         */
 
650
        char            XLogArchiveStatusDir[MAXPGPATH];
 
651
        char            newxlog[MAX_XFN_CHARS + 6 + 1];
 
652
        DIR                *rldir;
 
653
        struct dirent *rlde;
 
654
        bool            found = false;
 
655
 
 
656
        snprintf(XLogArchiveStatusDir, MAXPGPATH, XLOGDIR "/archive_status");
 
657
        rldir = AllocateDir(XLogArchiveStatusDir);
 
658
        if (rldir == NULL)
 
659
                ereport(ERROR,
 
660
                                (errcode_for_file_access(),
 
661
                                 errmsg("could not open archive status directory \"%s\": %m",
 
662
                                                XLogArchiveStatusDir)));
 
663
 
 
664
        while ((rlde = ReadDir(rldir, XLogArchiveStatusDir)) != NULL)
 
665
        {
 
666
                int                     basenamelen = (int) strlen(rlde->d_name) - 6;
 
667
 
 
668
                if (basenamelen >= MIN_XFN_CHARS &&
 
669
                        basenamelen <= MAX_XFN_CHARS &&
 
670
                        strspn(rlde->d_name, VALID_XFN_CHARS) >= basenamelen &&
 
671
                        strcmp(rlde->d_name + basenamelen, ".ready") == 0)
 
672
                {
 
673
                        if (!found)
 
674
                        {
 
675
                                strcpy(newxlog, rlde->d_name);
 
676
                                found = true;
 
677
                        }
 
678
                        else
 
679
                        {
 
680
                                if (strcmp(rlde->d_name, newxlog) < 0)
 
681
                                        strcpy(newxlog, rlde->d_name);
 
682
                        }
 
683
                }
 
684
        }
 
685
        FreeDir(rldir);
 
686
 
 
687
        if (found)
 
688
        {
 
689
                /* truncate off the .ready */
 
690
                newxlog[strlen(newxlog) - 6] = '\0';
 
691
                strcpy(xlog, newxlog);
 
692
        }
 
693
        return found;
 
694
}
 
695
 
 
696
/*
 
697
 * pgarch_archiveDone
 
698
 *
 
699
 * Emit notification that an xlog file has been successfully archived.
 
700
 * We do this by renaming the status file from NNN.ready to NNN.done.
 
701
 * Eventually, a checkpoint process will notice this and delete both the
 
702
 * NNN.done file and the xlog file itself.
 
703
 */
 
704
static void
 
705
pgarch_archiveDone(char *xlog)
 
706
{
 
707
        char            rlogready[MAXPGPATH];
 
708
        char            rlogdone[MAXPGPATH];
 
709
 
 
710
        StatusFilePath(rlogready, xlog, ".ready");
 
711
        StatusFilePath(rlogdone, xlog, ".done");
 
712
        if (rename(rlogready, rlogdone) < 0)
 
713
                ereport(WARNING,
 
714
                                (errcode_for_file_access(),
 
715
                                 errmsg("could not rename file \"%s\" to \"%s\": %m",
 
716
                                                rlogready, rlogdone)));
 
717
}