Header And Logo

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

Defines | Functions | Variables

pg_archivecleanup.c File Reference

#include "postgres_fe.h"
#include <ctype.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>
Include dependency graph for pg_archivecleanup.c:

Go to the source code of this file.

Defines

#define XLOG_DATA_FNAME_LEN   24
#define XLogFileName(fname, tli, log, seg)   snprintf(fname, XLOG_DATA_FNAME_LEN + 1, "%08X%08X%08X", tli, log, seg)
#define XLOG_BACKUP_FNAME_LEN   40

Functions

static void Initialize (void)
static void TrimExtension (char *filename, char *extension)
static void CleanupPriorWALFiles (void)
static void SetWALFileNameForCleanup (void)
static void usage (void)
int main (int argc, char **argv)

Variables

char * optarg
int optind
const char * progname
bool debug = false
bool dryrun = false
char * additional_ext = NULL
char * archiveLocation
char * restartWALFileName
char WALFilePath [MAXPGPATH]
char exclusiveCleanupFileName [MAXPGPATH]

Define Documentation

#define XLOG_BACKUP_FNAME_LEN   40

Definition at line 69 of file pg_archivecleanup.c.

Referenced by SetWALFileNameForCleanup().

#define XLOG_DATA_FNAME_LEN   24

Definition at line 65 of file pg_archivecleanup.c.

Referenced by CleanupPriorWALFiles(), and SetWALFileNameForCleanup().

#define XLogFileName (   fname,
  tli,
  log,
  seg 
)    snprintf(fname, XLOG_DATA_FNAME_LEN + 1, "%08X%08X%08X", tli, log, seg)

Function Documentation

static void CleanupPriorWALFiles ( void   )  [static]

Definition at line 111 of file pg_archivecleanup.c.

References additional_ext, archiveLocation, closedir(), dirent::d_name, debug, dryrun, exclusiveCleanupFileName, MAXPGPATH, NULL, opendir(), progname, readdir(), snprintf(), strerror(), TrimExtension(), unlink(), walfile, WALFilePath, and XLOG_DATA_FNAME_LEN.

Referenced by main().

{
    int         rc;
    DIR        *xldir;
    struct dirent *xlde;
    char        walfile[MAXPGPATH];

    if ((xldir = opendir(archiveLocation)) != NULL)
    {
        while ((xlde = readdir(xldir)) != NULL)
        {
            strncpy(walfile, xlde->d_name, MAXPGPATH);
            TrimExtension(walfile, additional_ext);

            /*
             * We ignore the timeline part of the XLOG segment identifiers in
             * deciding whether a segment is still needed.  This ensures that
             * we won't prematurely remove a segment from a parent timeline.
             * We could probably be a little more proactive about removing
             * segments of non-parent timelines, but that would be a whole lot
             * more complicated.
             *
             * We use the alphanumeric sorting property of the filenames to
             * decide which ones are earlier than the exclusiveCleanupFileName
             * file. Note that this means files are not removed in the order
             * they were originally written, in case this worries you.
             */
            if (strlen(walfile) == XLOG_DATA_FNAME_LEN &&
                strspn(walfile, "0123456789ABCDEF") == XLOG_DATA_FNAME_LEN &&
                strcmp(walfile + 8, exclusiveCleanupFileName + 8) < 0)
            {
                /*
                 * Use the original file name again now, including any
                 * extension that might have been chopped off before testing
                 * the sequence.
                 */
                snprintf(WALFilePath, MAXPGPATH, "%s/%s",
                         archiveLocation, xlde->d_name);

                if (dryrun)
                {
                    /*
                     * Prints the name of the file to be removed and skips the
                     * actual removal.  The regular printout is so that the
                     * user can pipe the output into some other program.
                     */
                    printf("%s\n", WALFilePath);
                    if (debug)
                        fprintf(stderr,
                                "%s: file \"%s\" would be removed\n",
                                progname, WALFilePath);
                    continue;
                }

                if (debug)
                    fprintf(stderr, "%s: removing file \"%s\"\n",
                            progname, WALFilePath);

                rc = unlink(WALFilePath);
                if (rc != 0)
                {
                    fprintf(stderr, "%s: ERROR: could not remove file \"%s\": %s\n",
                            progname, WALFilePath, strerror(errno));
                    break;
                }
            }
        }
        closedir(xldir);
    }
    else
        fprintf(stderr, "%s: could not open archive location \"%s\": %s\n",
                progname, archiveLocation, strerror(errno));
}

static void Initialize ( void   )  [static]

Definition at line 77 of file pg_archivecleanup.c.

References archiveLocation, and progname.

Referenced by main().

{
    /*
     * This code assumes that archiveLocation is a directory, so we use stat
     * to test if it's accessible.
     */
    struct stat stat_buf;

    if (stat(archiveLocation, &stat_buf) != 0 ||
        !S_ISDIR(stat_buf.st_mode))
    {
        fprintf(stderr, "%s: archive location \"%s\" does not exist\n",
                progname, archiveLocation);
        exit(2);
    }
}

int main ( int  argc,
char **  argv 
)

Definition at line 271 of file pg_archivecleanup.c.

References additional_ext, archiveLocation, CleanupPriorWALFiles(), debug, dryrun, exclusiveCleanupFileName, get_progname(), getopt(), Initialize(), MAXPGPATH, optarg, optind, progname, restartWALFileName, SetWALFileNameForCleanup(), snprintf(), usage(), and WALFilePath.

{
    int         c;

    progname = get_progname(argv[0]);

    if (argc > 1)
    {
        if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
        {
            usage();
            exit(0);
        }
        if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
        {
            puts("pg_archivecleanup (PostgreSQL) " PG_VERSION);
            exit(0);
        }
    }

    while ((c = getopt(argc, argv, "x:dn")) != -1)
    {
        switch (c)
        {
            case 'd':           /* Debug mode */
                debug = true;
                break;
            case 'n':           /* Dry-Run mode */
                dryrun = true;
                break;
            case 'x':
                additional_ext = strdup(optarg);        /* Extension to remove from
                                                 * xlogfile names */
                break;
            default:
                fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
                exit(2);
                break;
        }
    }

    /*
     * We will go to the archiveLocation to check restartWALFileName.
     * restartWALFileName may not exist anymore, which would not be an error,
     * so we separate the archiveLocation and restartWALFileName so we can
     * check separately whether archiveLocation exists, if not that is an
     * error
     */
    if (optind < argc)
    {
        archiveLocation = argv[optind];
        optind++;
    }
    else
    {
        fprintf(stderr, "%s: must specify archive location\n", progname);
        fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
        exit(2);
    }

    if (optind < argc)
    {
        restartWALFileName = argv[optind];
        optind++;
    }
    else
    {
        fprintf(stderr, "%s: must specify restartfilename\n", progname);
        fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
        exit(2);
    }

    if (optind < argc)
    {
        fprintf(stderr, "%s: too many parameters\n", progname);
        fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
        exit(2);
    }

    /*
     * Check archive exists and other initialization if required.
     */
    Initialize();

    /*
     * Check filename is a valid name, then process to find cut-off
     */
    SetWALFileNameForCleanup();

    if (debug)
    {
        snprintf(WALFilePath, MAXPGPATH, "%s/%s",
                 archiveLocation, exclusiveCleanupFileName);
        fprintf(stderr, "%s: keep WAL file \"%s\" and later\n",
                progname, WALFilePath);
    }

    /*
     * Remove WAL files older than cut-off
     */
    CleanupPriorWALFiles();

    exit(0);
}

static void SetWALFileNameForCleanup ( void   )  [static]

Definition at line 192 of file pg_archivecleanup.c.

References additional_ext, exclusiveCleanupFileName, progname, restartWALFileName, TrimExtension(), XLOG_BACKUP_FNAME_LEN, XLOG_DATA_FNAME_LEN, and XLogFileName.

Referenced by main().

{
    bool        fnameOK = false;

    TrimExtension(restartWALFileName, additional_ext);

    /*
     * If restartWALFileName is a WAL file name then just use it directly. If
     * restartWALFileName is a .backup filename, make sure we use the prefix
     * of the filename, otherwise we will remove wrong files since
     * 000000010000000000000010.00000020.backup is after
     * 000000010000000000000010.
     */
    if (strlen(restartWALFileName) == XLOG_DATA_FNAME_LEN &&
        strspn(restartWALFileName, "0123456789ABCDEF") == XLOG_DATA_FNAME_LEN)
    {
        strcpy(exclusiveCleanupFileName, restartWALFileName);
        fnameOK = true;
    }
    else if (strlen(restartWALFileName) == XLOG_BACKUP_FNAME_LEN)
    {
        int         args;
        uint32      tli = 1,
                    log = 0,
                    seg = 0,
                    offset = 0;

        args = sscanf(restartWALFileName, "%08X%08X%08X.%08X.backup", &tli, &log, &seg, &offset);
        if (args == 4)
        {
            fnameOK = true;

            /*
             * Use just the prefix of the filename, ignore everything after
             * first period
             */
            XLogFileName(exclusiveCleanupFileName, tli, log, seg);
        }
    }

    if (!fnameOK)
    {
        fprintf(stderr, "%s: invalid filename input\n", progname);
        fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
        exit(2);
    }
}

static void TrimExtension ( char *  filename,
char *  extension 
) [static]

Definition at line 95 of file pg_archivecleanup.c.

References NULL.

Referenced by CleanupPriorWALFiles(), and SetWALFileNameForCleanup().

{
    int         flen;
    int         elen;

    if (extension == NULL)
        return;

    elen = strlen(extension);
    flen = strlen(filename);

    if (flen > elen && strcmp(filename + flen - elen, extension) == 0)
        filename[flen - elen] = '\0';
}

static void usage ( void   )  [static]

Definition at line 246 of file pg_archivecleanup.c.

References progname.

Referenced by ExplainNode(), main(), parse_psql_options(), parseCommandLine(), pltcl_SPI_execute(), and pltcl_SPI_execute_plan().

{
    printf("%s removes older WAL files from PostgreSQL archives.\n\n", progname);
    printf("Usage:\n");
    printf("  %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n", progname);
    printf("\nOptions:\n");
    printf("  -d             generate debug output (verbose mode)\n");
    printf("  -n             dry run, show the names of the files that would be removed\n");
    printf("  -V, --version  output version information, then exit\n");
    printf("  -x EXT         clean up files if they have this extension\n");
    printf("  -?, --help     show this help, then exit\n");
    printf("\n"
           "For use as archive_cleanup_command in recovery.conf when standby_mode = on:\n"
           "  archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
           "e.g.\n"
           "  archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n");
    printf("\n"
           "Or for use as a standalone archive cleaner:\n"
           "e.g.\n"
           "  pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n");
    printf("\nReport bugs to <[email protected]>.\n");
}


Variable Documentation

char* additional_ext = NULL

Definition at line 40 of file pg_archivecleanup.c.

Referenced by CleanupPriorWALFiles(), main(), and SetWALFileNameForCleanup().

bool debug = false
bool dryrun = false

Definition at line 39 of file pg_archivecleanup.c.

Referenced by CleanupPriorWALFiles(), and main().

char exclusiveCleanupFileName[MAXPGPATH]
char* optarg

Definition at line 51 of file getopt.c.

int optind
const char* progname

Definition at line 35 of file pg_archivecleanup.c.

Referenced by _check_database_version(), _connectDB(), adjust_data_dir(), advice(), AuxiliaryProcessMain(), BackendRun(), BaseBackup(), bootstrap_template1(), check_authmethod_valid(), check_input(), check_locale_encoding(), check_locale_name(), check_need_password(), checkDataDir(), CheckServerVersionForStreaming(), CleanupPriorWALFiles(), close_walfile(), connectDatabase(), ConnectDatabase(), convert_sourcefiles_in(), create_data_directory(), create_xlog_symlink(), CustomizableCleanupPriorWALFiles(), CustomizableInitialize(), do_advice(), do_help(), do_init(), do_kill(), do_promote(), do_reload(), do_restart(), do_start(), do_status(), do_stop(), dolink(), dumpCreateDB(), dumpDatabases(), dumpTablespaces(), eitol(), escape_quotes(), executeCommand(), executeQuery(), existsTimeLineHistoryFile(), exit_nicely(), fatal_error(), file_line_count(), file_size(), find_other_exec_or_die(), FindEndOfXLOG(), FindStreamingStart(), fsync_fname(), GenerateRecoveryConf(), get_encoding_id(), get_id(), get_opts(), get_pgpid(), get_progname(), get_restricted_token(), get_set_pwd(), GetConnection(), handle_args(), HandleCopyStream(), help(), infile(), Initialize(), KillExistingArchiveStatus(), KillExistingXLOG(), load_resultmap(), main(), make_directory(), memcheck(), mkdatadir(), mkdirs(), open_result_files(), open_walfile(), popen_check(), PostgresMain(), PostmasterMain(), pre_sync_fname(), process_postgres_switches(), reached_end_position(), read_post_opts(), ReadControlFile(), readfile(), ReceiveAndUnpackTarFile(), ReceiveTarFile(), ReceiveXlogStream(), regression_main(), RewriteControlFile(), rulesub(), run_schedule(), runPgDump(), sendFeedback(), set_dump_section(), set_mode(), set_null_conf(), set_sig(), setup_bin_paths(), setup_collation(), setup_locale_encoding(), setup_pgdata(), setup_text_search(), SetWALFileNameForCleanup(), spawn_process(), StartLogStreamer(), stop_postmaster(), stop_streaming(), StreamLog(), test_postmaster_connection(), usage(), verify_dir_is_empty_or_create(), vwrite_msg(), walkdir(), write_version_file(), WriteEmptyXLOG(), writefile(), WriteRecoveryConf(), writeTarData(), writeTimeLineHistoryFile(), writezone(), and yearistype().

Definition at line 43 of file pg_archivecleanup.c.

Referenced by main(), and SetWALFileNameForCleanup().

char WALFilePath[MAXPGPATH]