加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

postgres 之 initdb 源码分析 一

发布时间:2020-12-13 17:28:44 所属栏目:百科 来源:网络整理
导读:1 版本 postgresql 9.3.2 beta 执行initdb打印内容如下: [wln@localhost bin]$ ./initdb -D ./dataThe 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 in

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",'E'},{"locale",1},{"lc-collate",2},{"lc-ctype",3},{"lc-monetary",4},{"lc-numeric",5},{"lc-time",6},{"lc-messages",7},{"no-locale",no_argument,8},{"text-search-config",'T'},{"auth",'A'},{"auth-local",10},{"auth-host",11},{"pwprompt",'W'},{"pwfile",9},{"username",'U'},{"help",'?'},{"version",'V'},{"debug",'d'},{"show",'s'},{"noclean",'n'},{"nosync",'N'},{"sync-only",'S'},{"xlogdir",'X'},{"data-checksums",'k'},{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,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 togethern"),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.nn"),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:nn"
			 "    %s%s%spostgres%s -D %s%s%sn"
			 "orn"
			 "    %s%s%spg_ctl%s -D %s%s%s -l logfile startnn"),QUOTE_PATH,bin_dir,(strlen(bin_dir) > 0) ? DIR_SEP : "",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 memoryn",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) == '/'

参考
(1) http://www.cnblogs.com/gaojian/tag/initdb/

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读