1. 程式人生 > 實用技巧 >PostgreSQL資料庫集簇初始化——initdb初始化資料庫(資料庫template1)

PostgreSQL資料庫集簇初始化——initdb初始化資料庫(資料庫template1)

  在bootstrap模式下建立資料庫template1,儲存在資料目錄的子目錄base/1/中。

1 /* Bootstrap template1 */
2 bootstrap_template1(short_version);
3 /* Make the per-database PG_VERSION for template1 only after init'ing it */
4 set_short_version(short_version, "base/1");

headerline陣列中儲存的內容為# PostgreSQL short_version\n,用於和*bki_lines中的內容進行對比,確保讀取的bki是正確的。下一步對bki進行讀取,並根據之前配置的內容對bki_lines中的內容進行替換。cmd的內容為"backend_exec" --boot -x1 boot_options talkargs。

#define PG_CMD_DECL char cmd[MAXPGPATH]; FILE *cmdfd

#define PG_CMD_OPEN \
do { \
cmdfd = popen_check(cmd, "w"); \
  if (cmdfd == NULL) \
    exit_nicely(); /* message already printed by popen_check */ \
} while (0)

#define PG_CMD_PUTS(line) \
do { \
  if (fputs(line, cmdfd) < 0 || fflush(cmdfd) < 0) \
    output_failed = true, output_errno = errno; \
} while (0)

#define PG_CMD_CLOSE \
do { \
  if (pclose_check(cmdfd)) \
    exit_nicely(); /* message already printed by pclose_check */ \
} while (0)

 1 /* run the BKI script in bootstrap mode to create template1 */
 2 static void bootstrap_template1(char *short_version) {
 3     PG_CMD_DECL;
 4     char      **line;
5 char *talkargs = ""; 6 char **bki_lines; 7 char headerline[MAXPGPATH]; 8 char buf[64]; 9 printf(_("creating template1 database in %s/base/1 ... "), pg_data); 10 fflush(stdout); 11 if (debug) 12 talkargs = "-d 5"; 13 bki_lines = readfile(bki_file); 14 /* Check that bki file appears to be of the right version */ 15 snprintf(headerline, sizeof(headerline), "# PostgreSQL %s\n",short_version); 16 if (strcmp(headerline, *bki_lines) != 0){ 17 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); 18 exit_nicely(); 19 } 20 21 /* Substitute for various symbols used in the BKI file */ 22 sprintf(buf, "%d", NAMEDATALEN); 23 bki_lines = replace_token(bki_lines, "NAMEDATALEN", buf); 24 sprintf(buf, "%d", (int) sizeof(Pointer)); 25 bki_lines = replace_token(bki_lines, "SIZEOF_POINTER", buf); 26 bki_lines = replace_token(bki_lines, "ALIGNOF_POINTER", (sizeof(Pointer) == 4) ? "i" : "d"); 27 bki_lines = replace_token(bki_lines, "FLOAT4PASSBYVAL",FLOAT4PASSBYVAL ? "true" : "false"); 28 bki_lines = replace_token(bki_lines, "FLOAT8PASSBYVAL", FLOAT8PASSBYVAL ? "true" : "false"); 29 bki_lines = replace_token(bki_lines, "POSTGRES",username); 30 bki_lines = replace_token(bki_lines, "ENCODING",encodingid); 31 bki_lines = replace_token(bki_lines, "LC_COLLATE",lc_collate); 32 bki_lines = replace_token(bki_lines, "LC_CTYPE", lc_ctype); 33 34 /* 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. */ 35 snprintf(cmd, sizeof(cmd), "LC_COLLATE=%s", lc_collate); 36 putenv(xstrdup(cmd)); 37 snprintf(cmd, sizeof(cmd), "LC_CTYPE=%s", lc_ctype); 38 putenv(xstrdup(cmd)); 39 unsetenv("LC_ALL"); 40 41 /* Also ensure backend isn't confused by this environment var: */ 42 unsetenv("PGCLIENTENCODING"); 43 snprintf(cmd, sizeof(cmd), "\"%s\" --boot -x1 %s %s", backend_exec, boot_options, talkargs); 44 45 PG_CMD_OPEN; 46 for (line = bki_lines; *line != NULL; line++){ 47 PG_CMD_PUTS(*line); 48 free(*line); 49 } 50 PG_CMD_CLOSE; 51 free(bki_lines); 52 check_ok(); 53 }

  popen_check使用了popen,popen()函式通過建立一個管道,呼叫fork()產生一個子程序,執行一個shell以執行命令來開啟一個程序。這個管道必須由pclose()函式關閉,而不是fclose()函式。pclose()函式關閉標準I/O流,等待命令執行結束,然後返回shell的終止狀態。如果shell不能被執行,則pclose()返回的終止狀態與shell已執行exit一樣。故使用popen產生子程序去執行comamnd中的命令。

 1 /* Open a subcommand with suitable error messaging */
 2 static FILE * popen_check(const char *command, const char *mode){
 3     FILE       *cmdfd;
 4     fflush(stdout);
 5     fflush(stderr);
 6     errno = 0;
 7     cmdfd = popen(command, mode);
 8     if (cmdfd == NULL)
 9         fprintf(stderr, _("%s: could not execute command \"%s\": %s\n"), progname, command, strerror(errno));
10     return cmdfd;
11 }