Skip to content

Commit 4eae047

Browse files
committed
Remove BKI file token pre-processing logic from initdb.
With this patch genbki replaces some token at compile time. Some others are initially populated with placeholder values from catalog/*.dat. Initdb run time UPDATEs these place holders plus the left over token with the respective configured values. Here are more details: - NAMEDATALEN, FLOAT8PASSBYVAL, SIZEOF_VOID_P, ALIGNOF_POINTER are replaced during compilation from genbki.pl by reading those from header files. - SIZEOF_VOID_P is available only after configuration (in pg_config.h). A new parameter include-conf had to be added to genbki to point to header files generated after configuration. - The pg_database.dat now has placeholder values which are filled in template1 during creation. Initdb uses UPDATE to set the right values for rolname in pg_authid and rest of the configured values in pg_database. - Earlier bki file was opened by initdb, and passed to postgres started in bootstrap mode. With this changes, the bki file is no longer opened in initdb, instead the file path is passed to bootstrap which solely handles the bki file. This means we have pass the file stream as yyin to allow the parsing from file directly. - Comparison of BKI file version and postgres build major version is moved from initdb to bootstrap. It only compares the version string to avoid needing platform compatability checks with EOL. - On Windows, in front end code, text mode is enforced. Please refer to src/port/open.c. In backend, bki file opens in binary mode. Add text mode flag explicitly to handle EOL properly.
1 parent 2f04720 commit 4eae047

9 files changed

Lines changed: 162 additions & 82 deletions

File tree

src/backend/bootstrap/bootstrap.c

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "catalog/pg_collation.h"
3030
#include "catalog/pg_type.h"
3131
#include "common/link-canary.h"
32+
#include "common/string.h"
3233
#include "libpq/pqsignal.h"
3334
#include "miscadmin.h"
3435
#include "nodes/makefuncs.h"
@@ -49,6 +50,8 @@ uint32 bootstrap_data_checksum_version = 0; /* No checksum */
4950

5051

5152
static void CheckerModeMain(void);
53+
static FILE *open_bki(char *bki_file);
54+
static bool verify_bki_hdr(FILE *fp);
5255
static void bootstrap_signals(void);
5356
static Form_pg_attribute AllocateAttribute(void);
5457
static void populate_typ_list(void);
@@ -206,6 +209,7 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
206209
char *progname = argv[0];
207210
int flag;
208211
char *userDoption = NULL;
212+
char *bki_file = NULL;
209213

210214
Assert(!IsUnderPostmaster);
211215

@@ -221,10 +225,13 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
221225
argv++;
222226
argc--;
223227

224-
while ((flag = getopt(argc, argv, "B:c:d:D:Fkr:X:-:")) != -1)
228+
while ((flag = getopt(argc, argv, "b:B:c:d:D:Fkr:X:-:")) != -1)
225229
{
226230
switch (flag)
227231
{
232+
case 'b':
233+
bki_file = pstrdup(optarg);
234+
break;
228235
case 'B':
229236
SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);
230237
break;
@@ -354,9 +361,29 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
354361
Nulls[i] = false;
355362
}
356363

364+
/* Point boot_yyin to bki file. */
365+
elog(DEBUG4, "Open bki file %s\n", bki_file);
366+
if ((boot_yyin = open_bki(bki_file)) == NULL)
367+
{
368+
write_stderr("Opening bki_file=%s failed with error=%d.",
369+
bki_file ? bki_file : "", errno);
370+
cleanup();
371+
proc_exit(1);
372+
}
373+
357374
/*
358-
* Process bootstrap input.
375+
* Verify bki header match with binary version. Bki parser ignore
376+
* commments hence no need to rewind boot_yyin.
359377
*/
378+
if (!verify_bki_hdr(boot_yyin))
379+
{
380+
write_stderr("Version in bki file(%s) does not match PostgreSQL version %s",
381+
bki_file, PG_VERSION);
382+
cleanup();
383+
proc_exit(1);
384+
}
385+
386+
/* Process bootstrap input from bki file (boot_yyin) */
360387
StartTransactionCommand();
361388
boot_yyparse();
362389
CommitTransactionCommand();
@@ -480,6 +507,59 @@ closerel(char *relname)
480507
}
481508
}
482509

510+
/* -----------------------
511+
* open_bki
512+
*
513+
* Open bki file with the flags
514+
* required per platform.
515+
* -----------------------
516+
*/
517+
static FILE *
518+
open_bki(char *bki_file)
519+
{
520+
#if defined(WIN32) && !defined(__CYGWIN__)
521+
/*
522+
* On Windows, in front end code, text mode open is enforced. Please refer
523+
* to src/port/open.c for more details. In backend, bki file opens in
524+
* binary mode. Add text mode flag explicitly to handle EOL properly.
525+
*/
526+
return fopen(bki_file, "rt");
527+
#else
528+
return fopen(bki_file, "r");
529+
#endif
530+
}
531+
532+
533+
/* -----------------------
534+
* verify_bki_hdr
535+
*
536+
* Verify that the bki file is generated for the
537+
* same major version as that of the bootstrap.
538+
* -----------------------
539+
*/
540+
static bool
541+
verify_bki_hdr(FILE *b)
542+
{
543+
StringInfoData line;
544+
char headerline[MAXPGPATH];
545+
bool ret = true;
546+
547+
initStringInfo(&line);
548+
if (!pg_get_line_buf(b, &line))
549+
{
550+
return false;
551+
}
552+
553+
snprintf(headerline, sizeof(headerline), "# PostgreSQL %s\n",
554+
PG_MAJORVERSION);
555+
if (strcmp(headerline, line.data) != 0)
556+
{
557+
ret = false;
558+
}
559+
560+
pfree(line.data);
561+
return ret;
562+
}
483563

484564

485565
/* ----------------

src/backend/catalog/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ generated-header-symlinks: $(top_builddir)/src/include/catalog/header-stamp
169169
# instead is cheating a bit, but it will achieve the goal of updating the
170170
# version number when it changes.
171171
bki-stamp: genbki.pl Catalog.pm $(POSTGRES_BKI_SRCS) $(POSTGRES_BKI_DATA) $(top_srcdir)/configure.ac $(top_srcdir)/src/include/access/transam.h
172-
$(PERL) $< --include-path=$(top_srcdir)/src/include/ \
172+
$(PERL) $< --include-path=$(top_srcdir)/src/include/ --include-conf=$(top_builddir)/src/include/ \
173173
--set-version=$(MAJORVERSION) $(POSTGRES_BKI_SRCS)
174174
touch $@
175175

src/backend/catalog/genbki.pl

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,23 @@
2525
my $output_path = '';
2626
my $major_version;
2727
my $include_path;
28+
my $include_conf;
2829

2930
my $num_errors = 0;
3031

3132
GetOptions(
3233
'output:s' => \$output_path,
3334
'set-version:s' => \$major_version,
34-
'include-path:s' => \$include_path) || usage();
35+
'include-path:s' => \$include_path,
36+
'include-conf:s' => \$include_conf) || usage();
3537

3638
# Sanity check arguments.
3739
die "No input files.\n" unless @ARGV;
3840
die "--set-version must be specified.\n" unless $major_version;
3941
die "Invalid version string: $major_version\n"
4042
unless $major_version =~ /^\d+$/;
4143
die "--include-path must be specified.\n" unless $include_path;
44+
die "--include-conf must be specified.\n" unless $include_conf;
4245

4346
# Make sure paths end with a slash.
4447
if ($output_path ne '' && substr($output_path, -1) ne '/')
@@ -180,6 +183,12 @@
180183
# Hash of next available OID, indexed by catalog name.
181184
my %GenbkiNextOids;
182185

186+
my $NameDataLen=Catalog::FindDefinedSymbol('pg_config_manual.h', $include_path,
187+
'NAMEDATALEN');
188+
my $SizeOfPointer=Catalog::FindDefinedSymbol('pg_config.h', $include_conf,
189+
'SIZEOF_VOID_P');
190+
my $Float8PassByVal=$SizeOfPointer >= 8 ? "true": "false";
191+
my $AlignOfPointer=$SizeOfPointer == 4 ? "i" : "d";
183192

184193
# Fetch some special data that we will substitute into the output file.
185194
# CAUTION: be wary about what symbols you substitute into the .bki file here!
@@ -634,6 +643,23 @@
634643
my $symbol = form_pg_type_symbol($bki_values{typname});
635644
$bki_values{oid_symbol} = $symbol
636645
if defined $symbol;
646+
647+
if ($bki_values{typlen} eq 'NAMEDATALEN')
648+
{
649+
$bki_values{typlen} = $NameDataLen;
650+
}
651+
if ($bki_values{typlen} eq 'SIZEOF_POINTER')
652+
{
653+
$bki_values{typlen} = $SizeOfPointer;
654+
}
655+
if ($bki_values{typalign} eq 'ALIGNOF_POINTER')
656+
{
657+
$bki_values{typalign} = $AlignOfPointer;
658+
}
659+
if ($bki_values{typbyval} eq 'FLOAT8PASSBYVAL')
660+
{
661+
$bki_values{typbyval} = $Float8PassByVal;
662+
}
637663
}
638664

639665
# Write to postgres.bki
@@ -812,6 +838,11 @@ sub gen_pg_attribute
812838
($row{attnotnull} eq 't'
813839
&& ($row{attlen} eq 'NAMEDATALEN' || $row{attlen} > 0));
814840

841+
if ($row{attnotnull} eq 't' && ($row{attlen} eq 'NAMEDATALEN'))
842+
{
843+
$row{attlen} = $NameDataLen;
844+
}
845+
815846
# If it's bootstrapped, put an entry in postgres.bki.
816847
print_bki_insert(\%row, $schema) if $table->{bootstrap};
817848

@@ -1106,6 +1137,7 @@ sub usage
11061137
--output Output directory (default '.')
11071138
--set-version PostgreSQL version number for initdb cross-check
11081139
--include-path Include path in source tree
1140+
--include-conf Include file path generated after configuration
11091141
11101142
genbki.pl generates postgres.bki and symbol definition
11111143
headers from specially formatted header files and .dat

src/backend/main/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ help(const char *progname)
372372
printf(_(" --check selects check mode (must be first argument)\n"));
373373
printf(_(" DBNAME database name (mandatory argument in bootstrapping mode)\n"));
374374
printf(_(" -r FILENAME send stdout and stderr to given file\n"));
375+
printf(_(" -b FILENAME path to bki file\n"));
375376

376377
printf(_("\nPlease read the documentation for the complete list of run-time\n"
377378
"configuration settings and how to set them on the command line or in\n"

src/bin/initdb/initdb.c

Lines changed: 37 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -764,15 +764,6 @@ get_id(void)
764764
return pg_strdup(username);
765765
}
766766

767-
static char *
768-
encodingid_to_string(int enc)
769-
{
770-
char result[20];
771-
772-
sprintf(result, "%d", enc);
773-
return pg_strdup(result);
774-
}
775-
776767
/*
777768
* get the encoding id for a given encoding name
778769
*/
@@ -1473,70 +1464,17 @@ bootstrap_template1(void)
14731464
{
14741465
PG_CMD_DECL;
14751466
PQExpBufferData cmd;
1476-
char **line;
1477-
char **bki_lines;
1478-
char headerline[MAXPGPATH];
1479-
char buf[64];
14801467

14811468
printf(_("running bootstrap script ... "));
14821469
fflush(stdout);
14831470

1484-
bki_lines = readfile(bki_file);
1485-
1486-
/* Check that bki file appears to be of the right version */
1487-
1488-
snprintf(headerline, sizeof(headerline), "# PostgreSQL %s\n",
1489-
PG_MAJORVERSION);
1490-
1491-
if (strcmp(headerline, *bki_lines) != 0)
1492-
{
1493-
pg_log_error("input file \"%s\" does not belong to PostgreSQL %s",
1494-
bki_file, PG_VERSION);
1495-
pg_log_error_hint("Specify the correct path using the option -L.");
1496-
exit(1);
1497-
}
1498-
1499-
/* Substitute for various symbols used in the BKI file */
1500-
1501-
sprintf(buf, "%d", NAMEDATALEN);
1502-
bki_lines = replace_token(bki_lines, "NAMEDATALEN", buf);
1503-
1504-
sprintf(buf, "%d", (int) sizeof(Pointer));
1505-
bki_lines = replace_token(bki_lines, "SIZEOF_POINTER", buf);
1506-
1507-
bki_lines = replace_token(bki_lines, "ALIGNOF_POINTER",
1508-
(sizeof(Pointer) == 4) ? "i" : "d");
1509-
1510-
bki_lines = replace_token(bki_lines, "FLOAT8PASSBYVAL",
1511-
FLOAT8PASSBYVAL ? "true" : "false");
1512-
1513-
bki_lines = replace_token(bki_lines, "POSTGRES",
1514-
escape_quotes_bki(username));
1515-
1516-
bki_lines = replace_token(bki_lines, "ENCODING",
1517-
encodingid_to_string(encodingid));
1518-
1519-
bki_lines = replace_token(bki_lines, "LC_COLLATE",
1520-
escape_quotes_bki(lc_collate));
1521-
1522-
bki_lines = replace_token(bki_lines, "LC_CTYPE",
1523-
escape_quotes_bki(lc_ctype));
1524-
1525-
bki_lines = replace_token(bki_lines, "ICU_LOCALE",
1526-
icu_locale ? escape_quotes_bki(icu_locale) : "_null_");
1527-
1528-
bki_lines = replace_token(bki_lines, "ICU_RULES",
1529-
icu_rules ? escape_quotes_bki(icu_rules) : "_null_");
1530-
1531-
sprintf(buf, "%c", locale_provider);
1532-
bki_lines = replace_token(bki_lines, "LOCALE_PROVIDER", buf);
1533-
15341471
/* Also ensure backend isn't confused by this environment var: */
15351472
unsetenv("PGCLIENTENCODING");
15361473

15371474
initPQExpBuffer(&cmd);
15381475

1539-
printfPQExpBuffer(&cmd, "\"%s\" --boot %s %s", backend_exec, boot_options, extra_options);
1476+
printfPQExpBuffer(&cmd, "\"%s\" --boot %s %s -b %s", backend_exec, boot_options,
1477+
extra_options, bki_file);
15401478
appendPQExpBuffer(&cmd, " -X %d", wal_segment_size_mb * (1024 * 1024));
15411479
if (data_checksums)
15421480
appendPQExpBuffer(&cmd, " -k");
@@ -1545,21 +1483,46 @@ bootstrap_template1(void)
15451483

15461484

15471485
PG_CMD_OPEN(cmd.data);
1548-
1549-
for (line = bki_lines; *line != NULL; line++)
1550-
{
1551-
PG_CMD_PUTS(*line);
1552-
free(*line);
1553-
}
1554-
15551486
PG_CMD_CLOSE();
15561487

15571488
termPQExpBuffer(&cmd);
1558-
free(bki_lines);
15591489

15601490
check_ok();
15611491
}
15621492

1493+
/*
1494+
* Placeholder values from catalog *.dat are used to create template1.
1495+
* Here we UPDATE with configured values from current initdb run.
1496+
*/
1497+
static void
1498+
update_params(FILE *cmdfd)
1499+
{
1500+
1501+
char *icu_locale_str = NULL;
1502+
char *icu_rules_str = NULL;
1503+
char *line = NULL;
1504+
1505+
if (icu_locale)
1506+
{
1507+
icu_locale_str = psprintf(",daticulocale=%s", escape_quotes_bki(icu_locale));
1508+
}
1509+
1510+
if (icu_rules)
1511+
{
1512+
icu_rules_str = psprintf(",daticulocale=%s", escape_quotes_bki(icu_rules));
1513+
}
1514+
1515+
line = psprintf("UPDATE pg_authid SET rolname='%s' WHERE rolname='POSTGRES'; \n\n"
1516+
"UPDATE pg_database SET encoding='%d', datcollate='%s', datctype='%s',"
1517+
"datlocprovider='%c' %s %s "
1518+
"WHERE datname='template1'; \n\n",
1519+
escape_quotes(username), encodingid, escape_quotes(lc_collate),
1520+
escape_quotes(lc_ctype), locale_provider,
1521+
icu_locale_str ? icu_locale_str : "",
1522+
icu_rules_str ? icu_rules_str : "");
1523+
PG_CMD_PUTS(line);
1524+
}
1525+
15631526
/*
15641527
* set up the shadow password table
15651528
*/
@@ -3028,6 +2991,8 @@ initialize_data_directory(void)
30282991

30292992
PG_CMD_OPEN(cmd.data);
30302993

2994+
update_params(cmdfd);
2995+
30312996
setup_auth(cmdfd);
30322997

30332998
setup_run_file(cmdfd, system_constraints_file);

src/include/bootstrap/bootstrap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,6 @@ extern int boot_yyparse(void);
5858

5959
extern int boot_yylex(void);
6060
extern void boot_yyerror(const char *message) pg_attribute_noreturn();
61+
extern FILE *boot_yyin;
6162

6263
#endif /* BOOTSTRAP_H */

src/include/catalog/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ generated_catalog_headers = custom_target('generated_catalog_headers',
123123
perl,
124124
files('../../backend/catalog/genbki.pl'),
125125
'--include-path=@SOURCE_ROOT@/src/include',
126+
'--include-conf=@BUILD_ROOT@/src/include',
126127
'--set-version=' + pg_version_major.to_string(),
127128
'--output=@OUTDIR@', '@INPUT@'
128129
],

0 commit comments

Comments
 (0)