postgres 之 initdb 源码分析 一

1 版本 

  postgresql 9.3.2 beta 

执行initdb打印内容如下:

[wln@localhost bin]$ ./initdb  -D ./data
The files belonging to this database system will be owned by user "wln".
This user must also own the server process.

The database cluster will be initialized with locale "zh_CN.UTF-8".
The default database encoding has accordingly been set to "UTF8".
initdb: could not find suitable text search configuration for locale "zh_CN.UTF-8"
The default text search configuration will be set to "simple".

Data page checksums are disabled.

creating directory ./data ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
creating configuration files ... ok
creating template1 database in ./data/base/1 ... ok
initializing pg_authid ... ok
initializing dependencies ... ok
creating system views ... ok
loading system objects' descriptions ... ok
creating collations ... ok
creating conversions ... ok
creating dictionaries ... ok
setting privileges on built-in objects ... ok
creating information schema ... ok
loading PL/pgSQL server-side language ... ok
vacuuming database template1 ... ok
copying template1 to template0 ... ok
copying template1 to postgres ... ok
syncing data to disk ... ok

WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.

Success. You can now start the database server using:

    postgres -D ./data
or
    pg_ctl -D ./data -l logfile start


2 函数内容

2.1 main(int argc, char *argv[])

文件 src/bin/Initdb.c

int
main(int argc, char *argv[])
{
	static struct option long_options[] = {
		{"pgdata", required_argument, NULL, 'D'},
		{"encoding", required_argument, NULL, 'E'},
		{"locale", required_argument, NULL, 1},
		{"lc-collate", required_argument, NULL, 2},
		{"lc-ctype", required_argument, NULL, 3},
		{"lc-monetary", required_argument, NULL, 4},
		{"lc-numeric", required_argument, NULL, 5},
		{"lc-time", required_argument, NULL, 6},
		{"lc-messages", required_argument, NULL, 7},
		{"no-locale", no_argument, NULL, 8},
		{"text-search-config", required_argument, NULL, 'T'},
		{"auth", required_argument, NULL, 'A'},
		{"auth-local", required_argument, NULL, 10},
		{"auth-host", required_argument, NULL, 11},
		{"pwprompt", no_argument, NULL, 'W'},
		{"pwfile", required_argument, NULL, 9},
		{"username", required_argument, NULL, 'U'},
		{"help", no_argument, NULL, '?'},
		{"version", no_argument, NULL, 'V'},
		{"debug", no_argument, NULL, 'd'},
		{"show", no_argument, NULL, 's'},
		{"noclean", no_argument, NULL, 'n'},
		{"nosync", no_argument, NULL, 'N'},
		{"sync-only", no_argument, NULL, 'S'},
		{"xlogdir", required_argument, NULL, 'X'},
		{"data-checksums", no_argument, NULL, 'k'},
		{NULL, 0, NULL, 0}
	};

	/*
	 * options with no short version return a low integer, the rest return
	 * their short version value
	 */
	int		c;
	int		option_index;
	char	        *effective_user;
	char		bin_dir[MAXPGPATH];

	progname = get_progname(argv[0]);
	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("initdb"));

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

	/* process command-line options */

	while ((c = getopt_long(argc, argv, "dD:E:kL:nNU:WA:sST:X:", long_options, &option_index)) != -1)
	{
		switch (c)
		{
			case 'A':
				authmethodlocal = authmethodhost = pg_strdup(optarg);

				/*
				 * When ident is specified, use peer for local connections.
				 * Mirrored, when peer is specified, use ident for TCP/IP
				 * connections.
				 */
				if (strcmp(authmethodhost, "ident") == 0)
					authmethodlocal = "peer";
				else if (strcmp(authmethodlocal, "peer") == 0)
					authmethodhost = "ident";
				break;
			case 10:
				authmethodlocal = pg_strdup(optarg);
				break;
			case 11:
				authmethodhost = pg_strdup(optarg);
				break;
			case 'D':
				pg_data = pg_strdup(optarg);
				break;
			case 'E':
				encoding = pg_strdup(optarg);
				break;
			case 'W':
				pwprompt = true;
				break;
			case 'U':
				username = pg_strdup(optarg);
				break;
			case 'd':
				debug = true;
				printf(_("Running in debug mode.\n"));
				break;
			case 'n':
				noclean = true;
				printf(_("Running in noclean mode.  Mistakes will not be cleaned up.\n"));
				break;
			case 'N':
				do_sync = false;
				break;
			case 'S':
				sync_only = true;
				break;
			case 'k':
				data_checksums = true;
				break;
			case 'L':
				share_path = pg_strdup(optarg);
				break;
			case 1:
				locale = pg_strdup(optarg);
				break;
			case 2:
				lc_collate = pg_strdup(optarg);
				break;
			case 3:
				lc_ctype = pg_strdup(optarg);
				break;
			case 4:
				lc_monetary = pg_strdup(optarg);
				break;
			case 5:
				lc_numeric = pg_strdup(optarg);
				break;
			case 6:
				lc_time = pg_strdup(optarg);
				break;
			case 7:
				lc_messages = pg_strdup(optarg);
				break;
			case 8:
				locale = "C";
				break;
			case 9:
				pwfilename = pg_strdup(optarg);
				break;
			case 's':
				show_setting = true;
				break;
			case 'T':
				default_text_search_config = pg_strdup(optarg);
				break;
			case 'X':
				xlog_dir = pg_strdup(optarg);
				break;
			default:
				/* getopt_long already emitted a complaint */
				fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
						progname);
				exit(1);
		}
	}


	/*
	 * Non-option argument specifies data directory as long as it wasn't
	 * already specified with -D / --pgdata
	 */
	if (optind < argc && strlen(pg_data) == 0)
	{
		pg_data = pg_strdup(argv[optind]);
		optind++;
	}

	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);
	}

	/* If we only need to fsync, just to it and exit */
	if (sync_only)
	{
		setup_pgdata();
		perform_fsync();
		return 0;
	}

	if (pwprompt && pwfilename)
	{
		fprintf(stderr, _("%s: password prompt and password file cannot be specified together\n"), progname);
		exit(1);
	}

	check_authmethod_unspecified(&authmethodlocal);
	check_authmethod_unspecified(&authmethodhost);

	check_authmethod_valid(authmethodlocal, auth_methods_local, "local");
	check_authmethod_valid(authmethodhost, auth_methods_host, "host");

	check_need_password(authmethodlocal, authmethodhost);

	get_restricted_token();

	setup_pgdata();

	setup_bin_paths(argv[0]);

	effective_user = get_id();
	if (strlen(username) == 0)
		username = effective_user;

	printf(_("The files belonging to this database system will be owned "
			 "by user \"%s\".\n"
			 "This user must also own the server process.\n\n"),
		   effective_user);

	set_info_version();

	setup_data_file_paths();

	setup_locale_encoding();

	setup_text_search();

	printf("\n");

	if (data_checksums)
		printf(_("Data page checksums are enabled.\n"));
	else
		printf(_("Data page checksums are disabled.\n"));

	printf("\n");

	initialize_data_directory();

	if (do_sync)
		perform_fsync();
	else
		printf(_("\nSync to disk skipped.\nThe data directory might become corrupt if the operating system crashes.\n"));

	if (authwarning != NULL)
		fprintf(stderr, "%s", authwarning);

	/* Get directory specification used to start this executable */
	strlcpy(bin_dir, argv[0], sizeof(bin_dir));
	get_parent_directory(bin_dir);

	printf(_("\nSuccess. You can now start the database server using:\n\n"
			 "    %s%s%spostgres%s -D %s%s%s\n"
			 "or\n"
			 "    %s%s%spg_ctl%s -D %s%s%s -l logfile start\n\n"),
	   QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
		   QUOTE_PATH, pgdata_native, QUOTE_PATH,
	   QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
		   QUOTE_PATH, pgdata_native, QUOTE_PATH);

	return 0;

2.2 main函数解读

2.2.1 结构体option 

(文件Getopt_long.h)
struct option
{
	const char *name;
	int   has_arg;
	int   *flag;
	int   val;
};

2.2.2 函数 get_progname(char *)

--得到执行程序的名字

文件 path.c  (为了得到programe 字符指针的内容)
/*
 * Extracts the actual name of the program as called -
 * stripped of .exe suffix if any
 */
const char *
get_progname(const char *argv0)
{
	const char *nodir_name;
	char	   *progname;

	nodir_name =  last_dir_separator (argv0);
	if (nodir_name)
		nodir_name++;
	else
		nodir_name =  skip_drive (argv0);

	/*
	 * Make a copy in case argv[0] is modified by ps_status. Leaks memory, but
	 * called only once.
	 */
	progname = strdup(nodir_name);
	if (progname == NULL)
	{
		fprintf(stderr, "%s: out of memory\n", nodir_name);
		abort();				/* This could exit the postmaster */
	}

	return progname;
}

2.2.2.1 函数 last_dir_separator(char *)

文件 (src/port/Path.c, 为了得到last_dir_separator())
/*
 *	last_dir_separator
 *
 * Find the location of the last directory separator, return
 * NULL if not found.
 */
char *
last_dir_separator(const char *filename)
{
	const char *p,
			   *ret = NULL;

	for (p = skip_drive(filename); *p; p++)
		if (IS_DIR_SEP(*p))
			ret = p;
	return (char *) ret;
}

2.2.2.2 宏定义 skip_drive(argv)

#define skip_drive(path)(path)

2.2.2.3 宏定义 IS_DIR_SEP(argv)

文件 port.h (src/include/Port.h, 为了得到IS_DIR_SEP() )
#ifndef WIN32
#define IS_DIR_SEP(ch)	((ch) == '/'

参考


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PostgreSQL 是一个开源的关系型数据库系统,其查询引擎的源码位于 `src/backend/executor` 目录下。分析 PostgreSQL 的查询引擎源码需要对数据库内部的架构和相关算法有一定的了解。 以下是一个简要的概述,供你开始分析 PostgreSQL 查询引擎源码时的参考: 1. 查询解析和转换:`parse_analyze.c` 文件中包含了将 SQL 查询语句解析为内部数据结构(Parse Tree)的代码。在这个阶段,PostgreSQL 还会进行一些语法和语义检查,处理子查询、联接、投影等操作。 2. 查询优化:查询优化器位于 `optimizer/` 目录下,其中最重要的文件是 `optimize.c`。该阶段的目标是根据查询的成本模型、统计信息和索引等,生成最佳的执行计划候选项。优化器会考虑不同的连接方式、索引选择、谓词下推等操作。 3. 执行计划生成:执行计划生成器位于 `executor/` 目录下,重要的文件包括 `execMain.c` 和 `execProcnode.c`。在这个阶段,PostgreSQL 根据最佳执行计划生成相应的执行代码,包括表的访问方式、连接方式、排序方式等信息。 4. 执行计划执行:执行计划执行器也位于 `executor/` 目录下,其中的 `execMain.c` 是入口文件。在这个阶段,PostgreSQL 执行生成的执行计划,并返回结果给用户。 对于更详细的源码分析,你可以深入研究相关文件和函数,并参考 PostgreSQL 的官方文档、邮件列表和社区讨论。此外,还有一些在线资源和书籍提供了关于 PostgreSQL 内部架构和查询引擎的深入解析,可以帮助你更好地理解和分析源码

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值