PostgreSQL資料庫集簇初始化——initdb初始化資料庫(檢查系統配置檔案)
設定環境變數(pg_data等),獲取系統配置檔案的原始檔路徑(postgres.bki、postgresql.conf. sample等檔案),並檢查該路徑下各檔案的可用性。
一、設定環境變數
set_pglocale_pgservice函式設定應用指定的locale和service目錄。對於第一個if判斷,如果在後端postgres中,則不需要設定LC_ALL,目前在initdb中則執行setlocale(LC_ALL, "")。如果定義了ENABLE_NLS,則需要呼叫get_locale_path,如果getenv("PGLOCALEDIR")為NULL,需要將PGLOCALEDIR和路徑放入extern char **environ所指向的記憶體,用於後續設定環境變數。如果getenv("PGSYSCONFDIR")為NULL,需要將PGSYSCONFDIR和路徑放入extern char **environ所指向的記憶體,用於後續設定環境變數。
1 void set_pglocale_pgservice(const char *argv0, const char *app){ 2 char path[MAXPGPATH]; 3 char my_exec_path[MAXPGPATH]; 4 char env_path[MAXPGPATH + sizeof("PGSYSCONFDIR=")]; /* longer than PGLOCALEDIR */ 5 /* don't set LC_ALL in the backend */ 6 if (strcmp(app, PG_TEXTDOMAIN("postgres")) != 0) 7 setlocale(LC_ALL, ""); 8 if (find_my_exec(argv0, my_exec_path) < 0) 9 return; 10 #ifdef ENABLE_NLS 11 get_locale_path(my_exec_path, path); 12 bindtextdomain(app, path); 13 textdomain(app); 14 if (getenv("PGLOCALEDIR") == NULL){ 15 /* set for libpq to use */ 16 snprintf(env_path, sizeof(env_path), "PGLOCALEDIR=%s", path); 17 canonicalize_path(env_path + 12); 18 putenv(strdup(env_path)); 19 } 20 #endif 21 if (getenv("PGSYSCONFDIR") == NULL){ 22 get_etc_path(my_exec_path, path); 23 /* set for libpq to use */ 24 snprintf(env_path, sizeof(env_path), "PGSYSCONFDIR=%s", path); 25 canonicalize_path(env_path + 13); 26 putenv(strdup(env_path)); 27 } 28 }
如果pg_data為空的話,則需要設定pg_data,後續的程式就是用於處理這樣的情況,從環境變數取出PGDATA。這裡屬於引數處理部分,因為可以不指定資料目錄,通過指定環境變數PGDATA來指定資料目錄。
1 if (strlen(pg_data) == 0){ 2 pgdenv = getenv("PGDATA"); 3 if (pgdenv && strlen(pgdenv)){ 4 /* PGDATA found */ 5 pg_data = xstrdup(pgdenv); 6 }else{ 7 fprintf(stderr, 8 _("%s: no data directory specified\n" 9 "You must identify the directory where the data for this database system\n" 10 "will reside. Do this with either the invocation option -D or the\n" 11 "environment variable PGDATA.\n"), 12 progname); 13 exit(1); 14 } 15 }
通過設定PGDATA環境變數來傳送資料目錄給其他程式,而不通過命令列以避免windows的dumb quoting檔案
1 /* we have to set PGDATA for postgres rather than pass it on the command 2 * line to avoid dumb quoting problems on Windows, and we would especially 3 * need quotes otherwise on Windows because paths there are most likely to 4 * have embedded spaces. */ 5 pgdenv = pg_malloc(8 + strlen(pg_data)); 6 sprintf(pgdenv, "PGDATA=%s", pg_data); 7 putenv(pgdenv);
二、獲取系統配置檔案的原始檔路徑
提取bin的路徑儲存到bin_path中,提取share的路徑儲存到share_path中(下面程式碼中沒有列出),獲取執行程式的使用者id
1 if ((ret = find_other_exec(argv[0], "postgres", PG_BACKEND_VERSIONSTR, backend_exec)) < 0){ 2 char full_path[MAXPGPATH]; 3 if (find_my_exec(argv[0], full_path) < 0) 4 strlcpy(full_path, progname, sizeof(full_path)); 5 if (ret == -1) 6 fprintf(stderr, 7 _("The program \"postgres\" is needed by %s " 8 "but was not found in the\n" 9 "same directory as \"%s\".\n" 10 "Check your installation.\n"), 11 progname, full_path); 12 else 13 fprintf(stderr, 14 _("The program \"postgres\" was found by \"%s\"\n" 15 "but was not the same version as %s.\n" 16 "Check your installation.\n"), 17 full_path, progname); 18 exit(1); 19 }
/* store binary directory */
strcpy(bin_path, backend_exec);
*last_dir_separator(bin_path) = '\0';
canonicalize_path(bin_path);
...
effective_user = get_id();
if (strlen(username) == 0)
username = effective_user;
設定初始化過程中的需要使用的一些檔案,將這些檔案的檔名設定到程式變數中。
1 set_input(&bki_file, "postgres.bki"); 2 set_input(&desc_file, "postgres.description"); 3 set_input(&shdesc_file, "postgres.shdescription"); 4 set_input(&hba_file, "pg_hba.conf.sample"); 5 set_input(&ident_file, "pg_ident.conf.sample"); 6 set_input(&conf_file, "postgresql.conf.sample"); 7 set_input(&conversion_file, "conversion_create.sql"); 8 set_input(&dictionary_file, "snowball_create.sql"); 9 set_input(&info_schema_file, "information_schema.sql"); 10 set_input(&features_file, "sql_features.txt"); 11 set_input(&system_views_file, "system_views.sql"); 12 ... 13 check_input(bki_file); 14 check_input(desc_file); 15 check_input(shdesc_file); 16 check_input(hba_file); 17 check_input(ident_file); 18 check_input(conf_file); 19 check_input(conversion_file); 20 check_input(dictionary_file); 21 check_input(info_schema_file); 22 check_input(features_file); 23 check_input(system_views_file);
三、設定本地化locale
先需要執行setlocale(LC_ALL,""),呼叫setlocales()函式
1 static void setlocales(void){ 2 /* set empty lc_* values to locale config if set */ 3 if (strlen(locale) > 0) { 4 if (strlen(lc_ctype) == 0) 5 lc_ctype = locale; 6 if (strlen(lc_collate) == 0) 7 lc_collate = locale; 8 if (strlen(lc_numeric) == 0) 9 lc_numeric = locale; 10 if (strlen(lc_time) == 0) 11 lc_time = locale; 12 if (strlen(lc_monetary) == 0) 13 lc_monetary = locale; 14 if (strlen(lc_messages) == 0) 15 lc_messages = locale; 16 } 17 /* override absent/invalid config settings from initdb's locale settings */ 18 if (strlen(lc_ctype) == 0 || !check_locale_name(lc_ctype)) 19 lc_ctype = xstrdup(setlocale(LC_CTYPE, NULL)); 20 if (strlen(lc_collate) == 0 || !check_locale_name(lc_collate)) 21 lc_collate = xstrdup(setlocale(LC_COLLATE, NULL)); 22 if (strlen(lc_numeric) == 0 || !check_locale_name(lc_numeric)) 23 lc_numeric = xstrdup(setlocale(LC_NUMERIC, NULL)); 24 if (strlen(lc_time) == 0 || !check_locale_name(lc_time)) 25 lc_time = xstrdup(setlocale(LC_TIME, NULL)); 26 if (strlen(lc_monetary) == 0 || !check_locale_name(lc_monetary)) 27 lc_monetary = xstrdup(setlocale(LC_MONETARY, NULL)); 28 if (strlen(lc_messages) == 0 || !check_locale_name(lc_messages)) 29 #if defined(LC_MESSAGES) && !defined(WIN32) 30 { 31 /* when available get the current locale setting */ 32 lc_messages = xstrdup(setlocale(LC_MESSAGES, NULL)); 33 } 34 #else 35 { 36 /* when not available, get the CTYPE setting */ 37 lc_messages = xstrdup(setlocale(LC_CTYPE, NULL)); 38 } 39 #endif 40 }
檢查encoding設定,如果沒有設定,就進行設定
1 if (strlen(encoding) == 0){ 2 int ctype_enc; 3 ctype_enc = pg_get_encoding_from_locale(lc_ctype); 4 if (ctype_enc == PG_SQL_ASCII && 5 !(pg_strcasecmp(lc_ctype, "C") == 0 || 6 pg_strcasecmp(lc_ctype, "POSIX") == 0)){ 7 /* Hmm, couldn't recognize the locale's codeset */ 8 fprintf(stderr, _("%s: could not find suitable encoding for locale %s\n"), 9 progname, lc_ctype); 10 fprintf(stderr, _("Rerun %s with the -E option.\n"), progname); 11 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), 12 progname); 13 exit(1); 14 } 15 else if (!pg_valid_server_encoding_id(ctype_enc)){ 16 /* We recognized it, but it's not a legal server encoding */ 17 fprintf(stderr, 18 _("%s: locale %s requires unsupported encoding %s\n"), 19 progname, lc_ctype, pg_encoding_to_char(ctype_enc)); 20 fprintf(stderr, 21 _("Encoding %s is not allowed as a server-side encoding.\n" 22 "Rerun %s with a different locale selection.\n"), 23 pg_encoding_to_char(ctype_enc), progname); 24 exit(1); 25 }else{ 26 encodingid = encodingid_to_string(ctype_enc); 27 printf(_("The default database encoding has accordingly been set to %s.\n"), 28 pg_encoding_to_char(ctype_enc)); 29 } 30 } 31 else 32 encodingid = get_encoding_id(encoding); 33 user_enc = atoi(encodingid); 34 if (!check_locale_encoding(lc_ctype, user_enc) || 35 !check_locale_encoding(lc_collate, user_enc)) 36 exit(1); /* check_locale_encoding printed the error */ 37 if (strlen(default_text_search_config) == 0) 38 { 39 default_text_search_config = find_matching_ts_config(lc_ctype); 40 if (default_text_search_config == NULL) 41 { 42 printf(_("%s: could not find suitable text search configuration for locale %s\n"), 43 progname, lc_ctype); 44 default_text_search_config = "simple"; 45 } 46 } 47 else 48 { 49 const char *checkmatch = find_matching_ts_config(lc_ctype); 50 51 if (checkmatch == NULL) 52 { 53 printf(_("%s: warning: suitable text search configuration for locale %s is unknown\n"), 54 progname, lc_ctype); 55 } 56 else if (strcmp(checkmatch, default_text_search_config) != 0) 57 { 58 printf(_("%s: warning: specified text search configuration \"%s\" might not match locale %s\n"), 59 progname, default_text_search_config, lc_ctype); 60 } 61 }