PostgreSQL的 initdb 源代码分析之十三
继续分析:
/* Bootstrap template1 */
bootstrap_template1();
展开:
我这里读入的文件是:/home/pgsql/project/share/postgres.bki
/*
* run the BKI script in bootstrap mode to create template1
*/
static void
bootstrap_template1(void)
{
PG_CMD_DECL;
char **line;
char *talkargs = "";
char **bki_lines;
char headerline[MAXPGPATH];
char buf[]; printf(_("creating template1 database in %s/base/1 ... "), pg_data);
fflush(stdout); if (debug)
talkargs = "-d 5"; bki_lines = readfile(bki_file); /* Check that bki file appears to be of the right version */ snprintf(headerline, sizeof(headerline), "# PostgreSQL %s\n",
PG_MAJORVERSION); if (strcmp(headerline, *bki_lines) != )
{
fprintf(stderr,
_("%s: input file \"%s\" does not belong to PostgreSQL %s\n"
"Check your installation or specify the correct path "
"using the option -L.\n"),
progname, bki_file, PG_VERSION);
exit_nicely();
} /* Substitute for various symbols used in the BKI file */ sprintf(buf, "%d", NAMEDATALEN);
bki_lines = replace_token(bki_lines, "NAMEDATALEN", buf); sprintf(buf, "%d", (int) sizeof(Pointer));
bki_lines = replace_token(bki_lines, "SIZEOF_POINTER", buf); bki_lines = replace_token(bki_lines, "ALIGNOF_POINTER",
(sizeof(Pointer) == ) ? "i" : "d"); bki_lines = replace_token(bki_lines, "FLOAT4PASSBYVAL",
FLOAT4PASSBYVAL ? "true" : "false"); bki_lines = replace_token(bki_lines, "FLOAT8PASSBYVAL",
FLOAT8PASSBYVAL ? "true" : "false"); bki_lines = replace_token(bki_lines, "POSTGRES", username); bki_lines = replace_token(bki_lines, "ENCODING", encodingid); bki_lines = replace_token(bki_lines, "LC_COLLATE", escape_quotes(lc_collate)); bki_lines = replace_token(bki_lines, "LC_CTYPE", escape_quotes(lc_ctype)); /*
* Pass correct LC_xxx environment to bootstrap.
*
* The shell script arranged to restore the LC settings afterwards, but
* there doesn't seem to be any compelling reason to do that.
*/
snprintf(cmd, sizeof(cmd), "LC_COLLATE=%s", lc_collate);
putenv(xstrdup(cmd)); snprintf(cmd, sizeof(cmd), "LC_CTYPE=%s", lc_ctype);
putenv(xstrdup(cmd)); unsetenv("LC_ALL"); /* Also ensure backend isn't confused by this environment var: */
unsetenv("PGCLIENTENCODING"); snprintf(cmd, sizeof(cmd),
"\"%s\" --boot -x1 %s %s",
backend_exec, boot_options, talkargs); PG_CMD_OPEN; for (line = bki_lines; *line != NULL; line++)
{
PG_CMD_PUTS(*line);
free(*line);
} PG_CMD_CLOSE; free(bki_lines); check_ok();
}
其中, bki_lines = readfile(bki_file) ,是得到了要读取的文件的每一行。
再展开看 replace_token 函数:
这个函数就是用 replacement指向的字符串,替换在 lines所代表的文件内容行数组中所有token值。
比如:
sprintf(buf, "%d", NAMEDATALEN);
bki_lines = replace_token(bki_lines, "NAMEDATALEN", buf);
把 postgres.bki 文件中 类似于
insert OID = 19 ( name 11 10 NAMEDATALEN f b S f t \054 0 18 1003 namein nameout namerecv namesend - - - c p f 0 -1 0 0 _null_ _null_ )
这样的句子,在内存中替换为(根据宏定义、NAMEDATALEN为64):
insert OID = 19 ( name 11 10 64 f b S f t \054 0 18 1003 namein nameout namerecv namesend - - - c p f 0 -1 0 0 _null_ _null_ )
/*
* make a copy of the array of lines, with token replaced by replacement
* the first time it occurs on each line.
*
* This does most of what sed was used for in the shell script, but
* doesn't need any regexp stuff.
*/
static char **
replace_token(char **lines, const char *token, const char *replacement)
{
int numlines = ;
int i;
char **result;
int toklen,
replen,
diff; for (i = ; lines[i]; i++)
numlines++; result = (char **) pg_malloc(numlines * sizeof(char *)); toklen = strlen(token);
replen = strlen(replacement);
diff = replen - toklen; for (i = ; i < numlines; i++)
{
char *where;
char *newline;
int pre; /* just copy pointer if NULL or no change needed */
if (lines[i] == NULL || (where = strstr(lines[i], token)) == NULL)
{
result[i] = lines[i];
continue;
} /* if we get here a change is needed - set up new line */ newline = (char *) pg_malloc(strlen(lines[i]) + diff + ); pre = where - lines[i]; strncpy(newline, lines[i], pre); strcpy(newline + pre, replacement); strcpy(newline + pre + replen, lines[i] + pre + toklen); result[i] = newline;
} return result;
}
综合上述两段,加入调试信息后,可以看到:
---------------replace for NAMEDATALEN ------start
===============lines[] OLD is : insert OID = ( name NAMEDATALEN f b S f t \ namein nameout namerecv namesend - - - c p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( name f b S f t \ namein nameout namerecv namesend - - - c p f - _null_ _null_ ) ===============lines[] OLD is : insert ( proname - NAMEDATALEN - - f p c t f f t _null_ _null_) ===============result[] NEW is : insert ( proname - - - f p c t f f t _null_ _null_) ===============lines[] OLD is : insert ( typname - NAMEDATALEN - - f p c t f f t _null_ _null_) ===============result[] NEW is : insert ( typname - - - f p c t f f t _null_ _null_) ===============lines[] OLD is : insert ( attname - NAMEDATALEN - - f p c t f f t _null_ _null_) ===============result[] NEW is : insert ( attname - - - f p c t f f t _null_ _null_) ===============lines[] OLD is : insert ( relname - NAMEDATALEN - - f p c t f f t _null_ _null_) ===============result[] NEW is : insert ( relname - - - f p c t f f t _null_ _null_) ---------------replace for NAMEDATALEN ------end ---------------replace for SIZEOF_POINTER ------start
===============lines[] OLD is : insert OID = ( internal SIZEOF_POINTER t p P f t \ internal_in internal_out - - - - - ALIGNOF_POINTER p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( internal t p P f t \ internal_in internal_out - - - - - ALIGNOF_POINTER p f - _null_ _null_ ) ---------------replace for SIZEOF_POINTER ------end ---------------replace for ALIGNOF_POINTER ------start
===============lines[] OLD is : insert OID = ( internal t p P f t \ internal_in internal_out - - - - - ALIGNOF_POINTER p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( internal t p P f t \ internal_in internal_out - - - - - d p f - _null_ _null_ ) ---------------replace for ALIGNOF_POINTER ------end ---------------replace for FLOAT4PASSBYVAL ------start
===============lines[] OLD is : insert OID = ( float4 FLOAT4PASSBYVAL b N f t \ float4in float4out float4recv float4send - - - i p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( float4 true b N f t \ float4in float4out float4recv float4send - - - i p f - _null_ _null_ ) ===============lines[] OLD is : insert ( procost - - - FLOAT4PASSBYVAL p i t f f t _null_ _null_) ===============result[] NEW is : insert ( procost - - - true p i t f f t _null_ _null_) ===============lines[] OLD is : insert ( prorows - - - FLOAT4PASSBYVAL p i t f f t _null_ _null_) ===============result[] NEW is : insert ( prorows - - - true p i t f f t _null_ _null_) ===============lines[] OLD is : insert ( reltuples - - - FLOAT4PASSBYVAL p i t f f t _null_ _null_) ===============result[] NEW is : insert ( reltuples - - - true p i t f f t _null_ _null_) ---------------replace for FLOAT4PASSBYVAL ------end ---------------replace for FLOAT8PASSBYVAL ------start
===============lines[] OLD is : insert OID = ( int8 FLOAT8PASSBYVAL b N f t \ int8in int8out int8recv int8send - - - d p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( int8 true b N f t \ int8in int8out int8recv int8send - - - d p f - _null_ _null_ ) ===============lines[] OLD is : insert OID = ( float8 FLOAT8PASSBYVAL b N t t \ float8in float8out float8recv float8send - - - d p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( float8 true b N t t \ float8in float8out float8recv float8send - - - d p f - _null_ _null_ ) ===============lines[] OLD is : insert OID = ( money FLOAT8PASSBYVAL b N f t \ cash_in cash_out cash_recv cash_send - - - d p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( money true b N f t \ cash_in cash_out cash_recv cash_send - - - d p f - _null_ _null_ ) ===============lines[] OLD is : insert OID = ( time FLOAT8PASSBYVAL b D f t \ time_in time_out time_recv time_send timetypmodin timetypmodout - d p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( time true b D f t \ time_in time_out time_recv time_send timetypmodin timetypmodout - d p f - _null_ _null_ ) ===============lines[] OLD is : insert OID = ( timestamp FLOAT8PASSBYVAL b D f t \ timestamp_in timestamp_out timestamp_recv timestamp_send timestamptypmodin timestamptypmodout - d p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( timestamp true b D f t \ timestamp_in timestamp_out timestamp_recv timestamp_send timestamptypmodin timestamptypmodout - d p f - _null_ _null_ ) ===============lines[] OLD is : insert OID = ( timestamptz FLOAT8PASSBYVAL b D t t \ timestamptz_in timestamptz_out timestamptz_recv timestamptz_send timestamptztypmodin timestamptztypmodout - d p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( timestamptz true b D t t \ timestamptz_in timestamptz_out timestamptz_recv timestamptz_send timestamptztypmodin timestamptztypmodout - d p f - _null_ _null_ ) ---------------replace for FLOAT4PASSBYVAL ------end ---------------replace for POSTGRES ------start
===============lines[] OLD is : insert OID = ( "POSTGRES" t t t t t t t - _null_ _null_ ) ===============result[] NEW is : insert OID = ( "pgsql" t t t t t t t - _null_ _null_ ) ---------------replace for POSTGRES ------end ---------------replace for ENCODING ------start
===============lines[] OLD is : insert OID = ( template1 ENCODING "LC_COLLATE" "LC_CTYPE" t t - _null_) ===============result[] NEW is : insert OID = ( template1 "LC_COLLATE" "LC_CTYPE" t t - _null_) ---------------replace for ENCODING ------end ---------------replace for LC_COLLATE ------start
===============lines[] OLD is : insert OID = ( template1 "LC_COLLATE" "LC_CTYPE" t t - _null_) ===============result[] NEW is : insert OID = ( template1 "en_US.UTF-8" "LC_CTYPE" t t - _null_) ---------------replace for LC_COLLATE ------end ---------------replace for LC_CTYPE ------start
===============lines[] OLD is : insert OID = ( template1 "en_US.UTF-8" "LC_CTYPE" t t - _null_) ===============result[] NEW is : insert OID = ( template1 "en_US.UTF-8" "en_US.UTF-8" t t - _null_) ---------------replace for LC_CTYPE ------end
这些被替换以后的信息,如何被使用呢? 看前面的 bootstrap_template1 函数中的这一段:
/*
* Pass correct LC_xxx environment to bootstrap.
*
* The shell script arranged to restore the LC settings afterwards, but
* there doesn't seem to be any compelling reason to do that.
*/
snprintf(cmd, sizeof(cmd), "LC_COLLATE=%s", lc_collate);
putenv(xstrdup(cmd)); snprintf(cmd, sizeof(cmd), "LC_CTYPE=%s", lc_ctype);
putenv(xstrdup(cmd)); unsetenv("LC_ALL"); /* Also ensure backend isn't confused by this environment var: */
unsetenv("PGCLIENTENCODING"); snprintf(cmd, sizeof(cmd),
"\"%s\" --boot -x1 %s %s",
backend_exec, boot_options, talkargs);
我可以得到 cmd是: "/home/pgsql/project/bin/postgres" --boot -x1 -F
而后面的一段:
则是一次一次的逐行带参数执行 Postgresql.bki中所有行(包括被替换的和没有被替换的行)
可以理解为特殊的模式下,向postgresql 的template 数据库中逐条写入数据。
PG_CMD_OPEN;
for (line = bki_lines; *line != NULL; line++)
{
PG_CMD_PUTS(*line);
free(*line);
}
PG_CMD_CLOSE;
需要注意的是,对各个系统表的建立,都是在此处,通过执行 postgres.bki文件中的各行脚本来完成的。
PostgreSQL的 initdb 源代码分析之十三的更多相关文章
- PostgreSQL的 initdb 源代码分析之二十三
继续分析: vacuum_db(); 展开: cmd是:/home/pgsql/project/bin/postgres" --single -F -O -c search_path=pg_ ...
- PostgreSQL的initdb 源代码分析之六
继续分析 下面的是获取运行此程序的用户名称,主要还是为了防止在linux下用root来运行的情形. effective_user = get_id(); ) username = effective_ ...
- PostgreSQL的 initdb 源代码分析之二
继续分析 下面这一段,当 initdb --version 或者 initdb --help 才有意义. ) { ], || strcmp(argv[], ) { usage(progname); ...
- PostgreSQL的 initdb 源代码分析之二十四
继续分析: make_template0(); 展开: 无需再作解释,就是创建template0数据库 /* * copy template1 to template0 */ static void ...
- PostgreSQL的 initdb 源代码分析之十五
继续分析: if (pwprompt || pwfilename) get_set_pwd(); 由于我启动initdb的时候,没有设置口令相关的选项,故此略过. 接下来: setup_depend( ...
- PostgreSQL的 initdb 源代码分析之十二
继续分析 /* Now create all the text config files */ setup_config(); 将其展开: 实质就是,确定各种参数,分别写入 postgresql.co ...
- PostgreSQL的 initdb 源代码分析之十一
继续分析: /* Top level PG_VERSION is checked by bootstrapper, so make it first */ write_version_file(NUL ...
- PostgreSQL的 initdb 源代码分析之七
继续分析:由于我使用initdb的时候,没有指定 locale,所以会使用OS的缺省locale,这里是 en_US.UTF-8 printf(_("The files belonging ...
- PostgreSQL的initdb 源代码分析之五
接前面,继续分析: putenv("TZ=GMT") 设置了时区信息. find_other_exec(argv[0], "postgres", PG_BACK ...
随机推荐
- noip2000提高组题解
事实再次向我证明了RP的重要性... 第一题:进制转换 是我最没有把握AC的一道题目却是我唯一一道AC的题目,真是讽刺.看完题目几乎完全没有往正常的解法(取余倒序)去想,直接写了搜索,因为数据范围在2 ...
- 基于Live555,ffmpeg的RTSP播放器直播与点播
基于Live555,ffmpeg的RTSP播放器直播与点播 多路RTSP高清视频播放器下载地址:http://download.csdn.net/detail/u011352914/6604437多路 ...
- Delphi打开窗体时报"Corrupt Portfolio Stream"
今天在打开一个Delphi窗体时报了这么一个错误: Corrupt Portfolio Stream 查了一下,主要是由于Delphi窗体的*.ddp文件损坏引起的. 解决方法: 删除.ddp 文 ...
- mybatis Mapper XML 文件
MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% ...
- ie对行高line-height的诡异解释
切 游戏页面真地是要求太精细了,做按钮的时候我犯了一个错误,居然用span的内联元素的行高和padding来控制,虽然有很多好处,但是IE对 line-height的解释导致按钮经常下边会缺一小部分, ...
- CSS中样式覆盖优先顺序
原文地址:http://www.3lian.com/edu/2014/09-25/168393.html 层叠优先级是: 浏览器缺省 < 外部样式表 < 内部样式表 < 内联样式 其 ...
- Linux基本命令(5)管理使用者和设立权限的命令
管理使用者和设立权限的命令 命令 说明 命令 说明 chmod 用来改变权限 useradd 用来增加用户 su 用来修改用户 5.1 chmod命令 chmod命令用来改变许可权限.读取.写 ...
- Linux Systemd——在RHEL/CentOS 7中启动/停止/重启服务
RHEL/CentOS 7.0中一个最主要的改变,就是切换到了systemd.它用于替代红帽企业版Linux前任版本中的SysV和Upstart,对系统和服务进行管理.systemd兼容SysV和Li ...
- 深入学习Android有关网络连接的内容
基于实际项目中碰到的些许问题,开始重新深入学习Android网络连接有关知识. Android的4.1.2版本的AndroidHttpClient模块setSoTimeout之后实际超时时间和设置的时 ...
- ASM基本操作
1. 添加一个磁盘组 SQL> create diskgroup recover external redundancy disk 'ORCL:kel3'; Diskgroup created. ...