91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PostgreSQL的備份工具pg_basebackup源碼中的主函數分析

發布時間:2021-11-09 15:21:46 來源:億速云 閱讀:256 作者:iii 欄目:關系型數據庫

本篇內容主要講解“PostgreSQL的備份工具pg_basebackup源碼中的主函數分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“PostgreSQL的備份工具pg_basebackup源碼中的主函數分析”吧!

一、數據結構

option
使用工具時存儲選項的數據結構

#ifndef HAVE_STRUCT_OPTION
//工具軟件選項
struct option
{
    const char *name;//名稱
    int         has_arg;//是否包含參數,no_argument/required_argument/optional_argument
    int        *flag;//標記
    int         val;//參數值
};
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#endif
/*
 * On OpenBSD and some versions of Solaris, opterr and friends are defined in
 * core libc rather than in a separate getopt module.  Define these variables
 * only if configure found they aren't there by default; otherwise, this
 * module and its callers will just use libc's variables.  (We assume that
 * testing opterr is sufficient for all of these.)
 */
#ifndef HAVE_INT_OPTERR
int         opterr = 1,         /* if error message should be printed */
            optind = 1,         /* index into parent argv vector */
            optopt;             /* character checked for validity */
char       *optarg;             /* argument associated with option */
#endif
#define BADCH   (int)'?'
#define BADARG  (int)':'
#define EMSG    ""

二、源碼解讀

pg_basebackup主函數,源碼較為簡單,獲取選項,校驗,調用BaseBackup()函數進行備份.

int
main(int argc, char **argv)
{
    static struct option long_options[] = {
        {"help", no_argument, NULL, '?'},
        {"version", no_argument, NULL, 'V'},
        {"pgdata", required_argument, NULL, 'D'},
        {"format", required_argument, NULL, 'F'},
        {"checkpoint", required_argument, NULL, 'c'},
        {"create-slot", no_argument, NULL, 'C'},
        {"max-rate", required_argument, NULL, 'r'},
        {"write-recovery-conf", no_argument, NULL, 'R'},
        {"slot", required_argument, NULL, 'S'},
        {"tablespace-mapping", required_argument, NULL, 'T'},
        {"wal-method", required_argument, NULL, 'X'},
        {"gzip", no_argument, NULL, 'z'},
        {"compress", required_argument, NULL, 'Z'},
        {"label", required_argument, NULL, 'l'},
        {"no-clean", no_argument, NULL, 'n'},
        {"no-sync", no_argument, NULL, 'N'},
        {"dbname", required_argument, NULL, 'd'},
        {"host", required_argument, NULL, 'h'},
        {"port", required_argument, NULL, 'p'},
        {"username", required_argument, NULL, 'U'},
        {"no-password", no_argument, NULL, 'w'},
        {"password", no_argument, NULL, 'W'},
        {"status-interval", required_argument, NULL, 's'},
        {"verbose", no_argument, NULL, 'v'},
        {"progress", no_argument, NULL, 'P'},
        {"waldir", required_argument, NULL, 1},
        {"no-slot", no_argument, NULL, 2},
        {"no-verify-checksums", no_argument, NULL, 3},
        {NULL, 0, NULL, 0}
    };//(完整)選項
    //選項的ASCII值
    int         c;
    //選項索引編號
    int         option_index;
    //程序名稱
    progname = get_progname(argv[0]);
    set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_basebackup"));
    if (argc > 1)
    {
        //顯示幫助信息
        if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
        {
            usage();
            exit(0);
        }
        else if (strcmp(argv[1], "-V") == 0
                 || strcmp(argv[1], "--version") == 0)
        {
            //顯示版本信息
            puts("pg_basebackup (PostgreSQL) " PG_VERSION);
            exit(0);
        }
    }
    atexit(cleanup_directories_atexit);
    //getopt_long --> 獲取選項
    while ((c = getopt_long(argc, argv, "CD:F:r:RS:T:X:l:nNzZ:d:c:h:p:U:s:wWkvP",
                            long_options, &option_index)) != -1)
    {
        switch (c)//根據選項設置參數
        {
            case 'C':
                create_slot = true;
                break;
            case 'D':
                basedir = pg_strdup(optarg);
                break;
            case 'F':
                if (strcmp(optarg, "p") == 0 || strcmp(optarg, "plain") == 0)
                    format = 'p';//不壓縮
                else if (strcmp(optarg, "t") == 0 || strcmp(optarg, "tar") == 0)
                    format = 't';//tar包
                else
                {
                    fprintf(stderr,
                            _("%s: invalid output format \"%s\", must be \"plain\" or \"tar\"\n"),
                            progname, optarg);
                    exit(1);
                }
                break;
            case 'r':
                maxrate = parse_max_rate(optarg);
                break;
            case 'R':
                writerecoveryconf = true;
                break;
            case 'S':
                /*
                 * When specifying replication slot name, use a permanent
                 * slot.
                 * 指定復制槽名稱,則使用持久化槽
                 */
                replication_slot = pg_strdup(optarg);
                temp_replication_slot = false;
                break;
            case 2:
                no_slot = true;
                break;
            case 'T':
                tablespace_list_append(optarg);
                break;
            case 'X':
                if (strcmp(optarg, "n") == 0 ||
                    strcmp(optarg, "none") == 0)
                {
                    includewal = NO_WAL;
                }
                else if (strcmp(optarg, "f") == 0 ||
                         strcmp(optarg, "fetch") == 0)
                {
                    includewal = FETCH_WAL;
                }
                else if (strcmp(optarg, "s") == 0 ||
                         strcmp(optarg, "stream") == 0)
                {
                    includewal = STREAM_WAL;
                }
                else
                {
                    fprintf(stderr,
                            _("%s: invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"\n"),
                            progname, optarg);
                    exit(1);
                }
                break;
            case 1:
                xlog_dir = pg_strdup(optarg);
                break;
            case 'l':
                label = pg_strdup(optarg);
                break;
            case 'n':
                noclean = true;
                break;
            case 'N':
                do_sync = false;
                break;
            case 'z':
#ifdef HAVE_LIBZ
                compresslevel = Z_DEFAULT_COMPRESSION;
#else
                compresslevel = 1;  /* will be rejected below */
#endif
                break;
            case 'Z':
                compresslevel = atoi(optarg);
                if (compresslevel < 0 || compresslevel > 9)
                {
                    fprintf(stderr, _("%s: invalid compression level \"%s\"\n"),
                            progname, optarg);
                    exit(1);
                }
                break;
            case 'c':
                if (pg_strcasecmp(optarg, "fast") == 0)
                    fastcheckpoint = true;
                else if (pg_strcasecmp(optarg, "spread") == 0)
                    fastcheckpoint = false;
                else
                {
                    fprintf(stderr, _("%s: invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"\n"),
                            progname, optarg);
                    exit(1);
                }
                break;
            case 'd':
                connection_string = pg_strdup(optarg);
                break;
            case 'h':
                dbhost = pg_strdup(optarg);
                break;
            case 'p':
                dbport = pg_strdup(optarg);
                break;
            case 'U':
                dbuser = pg_strdup(optarg);
                break;
            case 'w':
                dbgetpassword = -1;
                break;
            case 'W':
                dbgetpassword = 1;
                break;
            case 's':
                standby_message_timeout = atoi(optarg) * 1000;
                if (standby_message_timeout < 0)
                {
                    fprintf(stderr, _("%s: invalid status interval \"%s\"\n"),
                            progname, optarg);
                    exit(1);
                }
                break;
            case 'v':
                verbose++;
                break;
            case 'P':
                showprogress = true;
                break;
            case 3:
                verify_checksums = false;
                break;
            default:
                /*
                 * getopt_long already emitted a complaint
                 * 非法參數
                 */
                fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                        progname);
                exit(1);
        }
    }
    /*
     * Any non-option arguments?
     * 不識別的參數
     */
    if (optind < argc)
    {
        fprintf(stderr,
                _("%s: too many command-line arguments (first is \"%s\")\n"),
                progname, argv[optind]);
        fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                progname);
        exit(1);
    }
    /*
     * Required arguments
     * 必須的參數
     */
    if (basedir == NULL)
    {
        fprintf(stderr, _("%s: no target directory specified\n"), progname);
        fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                progname);
        exit(1);
    }
    /*
     * Mutually exclusive arguments
     * 互斥的參數
     */
    if (format == 'p' && compresslevel != 0)
    {
        fprintf(stderr,
                _("%s: only tar mode backups can be compressed\n"),
                progname);
        fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                progname);
        exit(1);
    }
    if (format == 't' && includewal == STREAM_WAL && strcmp(basedir, "-") == 0)
    {
        fprintf(stderr,
                _("%s: cannot stream write-ahead logs in tar mode to stdout\n"),
                progname);
        fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                progname);
        exit(1);
    }
    if (replication_slot && includewal != STREAM_WAL)
    {
        fprintf(stderr,
                _("%s: replication slots can only be used with WAL streaming\n"),
                progname);
        fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                progname);
        exit(1);
    }
    if (no_slot)
    {
        if (replication_slot)
        {
            fprintf(stderr,
                    _("%s: --no-slot cannot be used with slot name\n"),
                    progname);
            fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                    progname);
            exit(1);
        }
        temp_replication_slot = false;
    }
    if (create_slot)
    {
        if (!replication_slot)
        {
            fprintf(stderr,
                    _("%s: %s needs a slot to be specified using --slot\n"),
                    progname, "--create-slot");
            fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                    progname);
            exit(1);
        }
        if (no_slot)
        {
            fprintf(stderr,
                    _("%s: --create-slot and --no-slot are incompatible options\n"),
                    progname);
            fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                    progname);
            exit(1);
        }
    }
    if (xlog_dir)
    {
        if (format != 'p')
        {
            fprintf(stderr,
                    _("%s: WAL directory location can only be specified in plain mode\n"),
                    progname);
            fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                    progname);
            exit(1);
        }
        /* clean up xlog directory name, check it's absolute */
        canonicalize_path(xlog_dir);
        if (!is_absolute_path(xlog_dir))
        {
            fprintf(stderr, _("%s: WAL directory location must be "
                              "an absolute path\n"), progname);
            fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                    progname);
            exit(1);
        }
    }
#ifndef HAVE_LIBZ
    if (compresslevel != 0)
    {
        fprintf(stderr,
                _("%s: this build does not support compression\n"),
                progname);
        exit(1);
    }
#endif
    /* connection in replication mode to server */
    //以復制模式連接到數據庫
    conn = GetConnection();
    if (!conn)
    {
        /* Error message already written in GetConnection() */
        //連接不成功
        exit(1);
    }
    atexit(disconnect_atexit);
    /*
     * Set umask so that directories/files are created with the same
     * permissions as directories/files in the source data directory.
     * 設置umask以便目錄/文件可以源數據目錄的相同的權限創建
     *
     * pg_mode_mask is set to owner-only by default and then updated in
     * GetConnection() where we get the mode from the server-side with
     * RetrieveDataDirCreatePerm() and then call SetDataDirectoryCreatePerm().
     * pg_mode_mask默認設置為owner-only,在GetConnection()更新,
     *   在該函數中通過RetrieveDataDirCreatePerm()獲得服務器端的模式,
     *   然后調用SetDataDirectoryCreatePerm()函數.
     */
    umask(pg_mode_mask);
    /*
     * Verify that the target directory exists, or create it. For plaintext
     * backups, always require the directory. For tar backups, require it
     * unless we are writing to stdout.
     * 驗證目標目錄是否存在,如不存在則創建該目錄.
     * 對于普通的備份,通常需要目錄.
     * 對于tar備份,除非寫入到stdout,也需要目錄.
     */
    if (format == 'p' || strcmp(basedir, "-") != 0)
        verify_dir_is_empty_or_create(basedir, &made_new_pgdata, &found_existing_pgdata);
    /* determine remote server's xlog segment size */
    //確定遠程服務器的xlog segment大小
    if (!RetrieveWalSegSize(conn))
        exit(1);
    /* Create pg_wal symlink, if required */
    //如需要,創建pg_wal目錄鏈接
    if (xlog_dir)
    {
        char       *linkloc;
        //
        verify_dir_is_empty_or_create(xlog_dir, &made_new_xlogdir, &found_existing_xlogdir);
        /*
         * Form name of the place where the symlink must go. pg_xlog has been
         * renamed to pg_wal in post-10 clusters.
         * pg_xlog在PG 10+后已重命名為pg_wal
         */
        linkloc = psprintf("%s/%s", basedir,
                           PQserverVersion(conn) < MINIMUM_VERSION_FOR_PG_WAL ?
                           "pg_xlog" : "pg_wal");
#ifdef HAVE_SYMLINK
        if (symlink(xlog_dir, linkloc) != 0)
        {
            fprintf(stderr, _("%s: could not create symbolic link \"%s\": %s\n"),
                    progname, linkloc, strerror(errno));
            exit(1);
        }
#else
        fprintf(stderr, _("%s: symlinks are not supported on this platform\n"), progname);
        exit(1);
#endif
        free(linkloc);
    }
    //執行備份
    BaseBackup();
    //成功標記
    success = true;
    return 0;
}
/*
 *  set_pglocale_pgservice
 *
 *  Set application-specific locale and service directory
 *  設置應用相關的locale和service目錄
 *
 *  This function takes the value of argv[0] rather than a full path.
 *  該函數只提取argv[0]的值而不是全路徑
 *
 * (You may be wondering why this is in exec.c.  It requires this module's
 * services and doesn't introduce any new dependencies, so this seems as
 * good as anyplace.)
 * (你可能會感覺疑惑:該函數在exec.c文件中)
 * 這需要該模塊中的服務,而不需要介紹其他新的依賴,因此看起來與其他地方沒有什么區別.
 */
void
set_pglocale_pgservice(const char *argv0, const char *app)
{
    char        path[MAXPGPATH];
    char        my_exec_path[MAXPGPATH];
    char        env_path[MAXPGPATH + sizeof("PGSYSCONFDIR=")];  /* longer than
                                                                 * PGLOCALEDIR */
    char       *dup_path;
    /* don't set LC_ALL in the backend */
    //不要在后臺進程中設置LC_ALL
    if (strcmp(app, PG_TEXTDOMAIN("postgres")) != 0)
    {
        setlocale(LC_ALL, "");
        /*
         * One could make a case for reproducing here PostmasterMain()'s test
         * for whether the process is multithreaded.  Unlike the postmaster,
         * no frontend program calls sigprocmask() or otherwise provides for
         * mutual exclusion between signal handlers.  While frontends using
         * fork(), if multithreaded, are formally exposed to undefined
         * behavior, we have not witnessed a concrete bug.  Therefore,
         * complaining about multithreading here may be mere pedantry.
         * 在這里可以重新執行PostmasterMain()的測試,檢查進程是否多線程.
         * 與postmaster不同,沒有前臺程序調用sigprocmask(),
         *   否則的話需要為多個信號控制器提供mutual exclusion.
         * 如為多線程方式,則前臺程序使用fork(),會導致不可預測的行為,我們不會有這種嚴重的bug.
         * 因此,在這里對于多線程方式報錯是多余的.
         */
    }
    if (find_my_exec(argv0, my_exec_path) < 0)
        return;
#ifdef ENABLE_NLS
    get_locale_path(my_exec_path, path);
    bindtextdomain(app, path);
    textdomain(app);
    if (getenv("PGLOCALEDIR") == NULL)
    {
        //------ PGLOCALEDIR
        /* set for libpq to use */
        //設置libpq
        snprintf(env_path, sizeof(env_path), "PGLOCALEDIR=%s", path);
        canonicalize_path(env_path + 12);
        dup_path = strdup(env_path);
        if (dup_path)
            putenv(dup_path);
    }
#endif
    if (getenv("PGSYSCONFDIR") == NULL)
    {
        //---- PGSYSCONFDIR
        get_etc_path(my_exec_path, path);
        /* set for libpq to use */
        snprintf(env_path, sizeof(env_path), "PGSYSCONFDIR=%s", path);
        canonicalize_path(env_path + 13);
        dup_path = strdup(env_path);
        if (dup_path)
            putenv(dup_path);
    }
}

到此,相信大家對“PostgreSQL的備份工具pg_basebackup源碼中的主函數分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

肥城市| 旬邑县| 济源市| 德令哈市| 买车| 宁津县| 滦平县| 宁都县| 怀化市| 海安县| 镇安县| 芮城县| 肥城市| 田阳县| 台中市| 登封市| 托克逊县| 缙云县| 青川县| 托里县| 土默特左旗| 南乐县| 洞口县| 壤塘县| 昆山市| 苏尼特右旗| 嵊泗县| 呼玛县| 黑龙江省| 五台县| 金川县| 神农架林区| 浠水县| 东乌珠穆沁旗| 崇州市| 衢州市| 崇礼县| 调兵山市| 阳朔县| 繁昌县| 北海市|