PostgreSQL备份工具pg_basebackup源码中主要函数分析

分类:编程技术 时间:2024-02-20 15:52 浏览:0 评论:0
0
本文主要讲解《PostgreSQL的备份工具pg_basebackup源码中主要函数分析》。有兴趣的朋友不妨看一下。文章介绍的方法简单、快捷、实用。让小编带你学习《PostgreSQL备份工具pg_basebackup源码中主要函数分析》!

1.数据结构

option
使用工具时存储选项的数据结构

#ifndef HAVE_STRUCT_OPTION//工具软件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 option_argument 2#endif /* * 在 OpenBSD 和某些版本的 Solaris 上,opterr 和朋友是在 * core libcratHer 中定义的,而不是在 getopt 模块部分中定义的。仅定义这些变量*如果配置发现它们就在那里。刚刚使用了libc的变量。这些。)*/#iFndef Have_int_opterrint OPTERR = 1,/*如果应打印错误消息*/option = 1,/*索引到父 Argv 向量*/& & optopt; /* 检查字符的有效性 */char *optarg; /* 与选项关联的参数 */#endif#define BADCH (int)'?'#define BADARG (int)':'#define EMSG ""

2.源码解读

pg_basebackup主函数,源码比较简单,获取选项,验证,调用BaseBackup()函数进行备份。

intmain(int argc, char ** argv){ 静态结构选项 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-率", required_argument, NULL, 'r'}, {"write-recovery-conf", no_argument, NULL, 'R'}, { "slot", required_argument, NULL, 'S'}, {"表空间映射", required_argument, NULL, 'T'}, {"wal-method", required_argument, NULL, 'X'},{“gzip”,no_argument,NULL,'z'},{“压缩”,required_argument,NULL,'Z'},{“标签”,required_argument,NULL,'l'},{“否” -clean", no_argument, NULL, 'n'}, {"no-sync", no_argument, NULL, 'N'}, { "dbname", required_argument, NULL, 'd'}, {"host", required_argument, NULL, 'h'},   {"端口", required_argument, NULL, 'p'}, {"用户名", required_argument, NULL, 'U'}, {"无密码", 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_argument, NULL, 2}, {"无验证校验和", no_argument, NULL, 3} , {NULL, 0, NULL, 0} };//(完整) options //选项 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) { 用法();退出(0); else if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") == 0) { //显示版本信息 put("pg_basebackup (PostgreSQL)) “ PG_VERSION);退出(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" ,                                                                                                                                                                                               create_slot = true;break;  case 'D': basedir = pg_strdup(optarg);break;case 'F': if (strcmp(optarg, "p") == 0 || strcmp(optarg) ,“普通”)= = 0) format = 'p';//不压缩 else if (strcmp(optarg, "t") == 0 || strcmp(optarg, "tar") == 0)  format = 't'; // Tar包装e else {fprintf(stderr, _ ("%s: 无效的输出格式\"%s\",必须是\"plain\"或\"tar\n"),                                                                                                                               );                        exit(1);break;case' R': writerrecoveryconf = true; break;   case 'S': /* * 指定复制槽名称时,使用永久槽。然后使用持久槽        */      replication_slot = pg_strdup(optarg);e; targ);p ; if (strcmp(optarg, "f") == 0 || strcmp(optarg, "fetch") == 0) {               includewal = FETCH_WAL;                                                                                                                                                                                           因为 g, "流")==0) {sp; else else { fprintf (stderr, ", \"stream\", 或 \"none\"\n") ,                     progname, optarg);bsp ; label = pg_strdup(optarg);break;case 'n':noclean = true;break;case ‘N’:做_同步=假;休息; case 'z':#ifdef HAVE_LIBZ 压缩级别 = Z_DEFAULT_COMPRESSION;#else 压缩级别 = 1; /* 下面将被拒绝 */#endifbreak; fprintf(stderr, _("%s: 无效的压缩级别 \"%s\"\n"), progname, optarg);exit (1);} Break; Case 'C': if (pg_strcasecmp (option, "" fast ") == 0) Fastcheckpoint = true; else if (pg_strcasecmp (option, "spread ") == 0) Fastc heckpoint = false; else else { fprintf(stderr) , _("%s: 无效的检查点参数 \"%s\",必须是 \"fast\" 或 \"spread\"\n"), progname, optarg); exit(1 );sp; break; case 'd':connection_string = pg_strdup(optarg);break;case 'h':dbhost = pg_strdup(optarg);            break;;break;case 'U':dbuser = pg_strdup(optarg);break;case'w':dbgetpassword = -1;   Case 's': Standby_Message_timeout = Atoi (Optarg)*1000; if (Standby_Message_timeout <0) {fprintf(stderr, _("%s: 无效状态间隔\"%s\"\n"), Progname , Optarg) ;            退出(1); showprogress = true; 中断; 情况 3:   verify_checksums = false;休息;默认值: /* getopt_long 已发出投诉 * 非法参数                    */                                                                                                                                                                                                                                                                                                通过; fprintf(stderr, _("%s: 命令行参数太多(第一个是 \"%s\")\n"),     progname, argv[optind]); fprintf(stderr, _("尝试 \"%s --help\" 获取更多信息。\n"),     progname);退出(1); } /* * 必需参数 */ if (basedir == NULL) {            fprintf (stderr, _("%s: 未指定目标目录\n"), progname); fprintf(stderr, _("尝试 \"%s --help\" 获取更多信息。\n"), progname);退出(1); } /* * 互斥参数 * 互斥参数 */ if (format == 'p' && compresslevel != 0) { fprintf(stderr, _("%s: 只有 tar 模式备份可以被压缩\n "),                                                                                                                                                                                                            .; 退出 (1);} if (format == 't' && infludewal == stream_wal && Strong (base, "-") == 0) {f printf (stderr, _ ("% s: 无法将 tar 模式下的预写 lhad lhad L OGS 流式传输到标准输出\n"),                                                                                                                                                                         if (replication_slot && includewal != STREAM_WAL) { fprintf(stderr, 复制槽只能与 WAL 流一起使用\n"), progname ); fprintf(stderr, _("尝试 \"%s --help\" 了解更多信息。\n"),               progname);{fprintf (stderr, _("%s: --no-slot 不能与 slot 一起使用名称 \ n"), 程序名); Fprintf (STDERR, _ ("尝试\"%s-Heelp\"了解更多信息。\n"),                 程序名);.;=假; } if (create_slot) { if (!replication_slot) { fprintf(stderr, %s 需要使用 --slot\n" 指定一个槽),            progname, "--create- slot"); fprintf(stderr, _( "尝试 \"%s --help\" 获取更多信息。\n"),progname); exit(1); if (no_slot) { fprintf(stderr, create-slot 和 --no-slot 是不兼容的选项\ n"),                      程序名); _("尝试 \"%s --help\" 获取更多信息。\n"),               程序名称);退出(1); if (xlog_dir) { if (format != 'p') fprintf(stderr,​ ​ _("%s: WAL 目录位置只能在纯模式下指定\n" ),                    progname); fprintf(stderr, _("尝试 \"%s --help\" 获取更多信息。 \ n "), Program); exit(1);}/*清理xlog目录名,检查它是绝对的*/规范化路径(xlog_dir); if (! is_abab., Solution_path (xlog_dir)) {fprintf (stderr, _ ("%s: WAL 目录位置必须是 "                                       nbsp; "绝对路径\n"), progname); } } #ifndef HAVE_LIBZ if (compresslevel != 0) { fprintf(stderr, "%s: 此版本不支持压缩\n"), progname);退出(1); }#endif /* 以复制模式连接到服务器 */ //以复制模式连接数据库 conn = GetConnection(); if (!conn) { { /* 错误信息已写入 GetConnection( )*/// 连接不成功 EXIT (1);} Atexit (Disconnect_atexit);/**设置 UMask 以便使用以下命令创建目录/文件与源数据目录中的directors/files相同*权限。   * 设置umask,以便可以使用与源数据目录相同的权限创建目录/文件 * * * pg_mode_mask 默认设置为仅所有者,然后在 GetConnection() 中更新,我们从服务器端获取模式带 * 检索eDataDirCreatePerm(),然后调用SetDataDirectoryCreatePerm()。 * pg_mode_mask默认设置为owner-only,在GetConnection()中更新, * 在此函数中,通过RetrieveDataDirCreatePerm()获取服务器端模式, * 然后调用SetDataDirectoryCreatePerm()函数。 */ 嗯问(pg_mode_mask); /* * 验证目标目录是否存在,或创建它。对于纯文本 * 备份,始终需要该目录。对于 tar 备份,需要它 * 除非我们要写入标准输出。 * 验证目标目录是否存在,不存在则创建。对于 tar 备份,除非写入 stdout,否则还需要一个目录。 */ if (format == 'p' || strcmp(basedir, "-") != 0) verify_dir_is_empty_or_create(basedir, &made_new_pgdata, &found_existing_pgdata); /* 确定远程服务器的 xlog 段大小 */ // 确定远程服务器的 xlog 段大小 if (!RetrieveWalSegSize(conn))   exit(1); /* 如果需要,创建 pg_wal 符号链接 */ //如果需要,创建一个 pg_wal 目录链接 if (xlog_dir) { char *linkloc; // verify_dir_is_empty_or _create(xlog_dir, &made_new_xlogdir, &found_existing_xlogdir); /* /* * 符号链接必须所在位置的表单名称。 * 在 10 年后的集群中,pg_xlog 已重命名为 pg_wal。 * 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: 无法创建符号链接 \"%s\": %s\n"),progname, linkloc, strerror(errno));退出(1);退出(1); fprintf(stderr, _("%s: 此平台不支持符号链接\n"), progname);退出(1);#endif free(linkloc); } //执行备份 BaseBackup(); //成功标记 success = true; return 0;}/* * set_pglocale_pgservice * * 设置应用程序特定的区域设置和服务目录 * 设置应用程序特定的区域设置和服务目录 * * 此函数采用 argv[0] 的值,而不是 argv[0] 的值一条完整的路径。 * 这个函数只提取argv[0]的值而不是完整路径 * * (你可能想知道为什么它在exec.c中。它需要这个模块的 * 服务并且不会引入任何新的依赖项,所以这看起来as * good as anyplace.) * (你可能会感到困惑:这个函数在exec.c文件中) * 这需要模块中的服务,并且不需要引入其他新的依赖项,因此看起来与其他没有什么不同地方。 */voidset_pglocale_pgservice(const char *argv0, const char *app){ char 路径[MAXPGPATH]; char my_exec_path[MAXPGPATH]; char env_path[MAXPGPATH + sizeof("PGSYSCONFDIR=")]; /* 长于t 在后台设置LC_ALL */ //不要在后台进程设置LC_ALL if (strcmp(app, PG_TEXTDOMAIN("postgres" )) != 0) { setlocale(LC_ALL, ""); /** 人们可以在这里重现 PostmasterMain() 的测试 * 以确定该进程是否是多线程的。与 postmaster 不同,* 没有前端程序调用 sigprocmask() 或其他 p* 提供信号处理程序之间的相互包含。虽然使用 fork() 的前端(如果是多线程的)会正式暴露于未定义的行为,但我们还没有看到具体的错误。因此,*在这里抱怨多线程可能只是迂腐。 * 这里可以重新执行PostmasterMain()测试来检查进程是否是多线程的。 * 与postmaster不同,没有前端程序调用sigprocmask(), * 否则需要配置多个信号控制器提供互斥。 * 如果是多线程模式,前台程序使用fork(),会导致不可预知的行为。我们不会出现如此严重的错误。 * 因此,这里对于多线程模式报的错误是Redundant。 */ } if (find_my_exec(argv0, my_exec_path) < 0) return;#ifdef ENABLE_NLS get_locale_path(my_exec_path, path);绑定文本域(应用程序,路径);文本域(应用程序); if (getenv("PGLOCALEDIR") == NULL) { //--------PGLOCALEDIR /* 设置 libpq 使用 */ //设置 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); /* 设置 libpq 使用 */ snprintf(env_path, sizeof(env_path), "PGSYSCONFDIR=%s", path);规范化 _path(env_path + 13) ; dup_path = strdup(env_path); if (dup_path) putenv(dup_path); }}

至此,相信大家对《PostgreSQL的备份工具pg_basebackup源码中main函数分析》感兴趣了,现在你有了更深入的了解,也许也练习一下吧!这是网站。更多相关内容,您可以进入相关渠道进行查询。关注我们并继续学习!

1. 本站所有资源来源于用户上传或网络,仅作为参考研究使用,如有侵权请邮件联系站长!
2. 本站积分货币获取途径以及用途的解读,想在本站混的好,请务必认真阅读!
3. 本站强烈打击盗版/破解等有损他人权益和违法作为,请各位会员支持正版!
4. 编程技术 > PostgreSQL备份工具pg_basebackup源码中主要函数分析

用户评论