Skip to content

Commit e0f05cd

Browse files
committed
Improve some ancient, crufty code in bootstrap + initdb.
At some point back in the last century, somebody felt that reading all of pg_type twice was cheaper, or at least easier, than using repalloc() to resize the Typ[] array dynamically. That seems like an entirely wacko proposition, so rewrite the code to do it the other way. (To add insult to injury, there were two not-quite-identical copies of said code.) initdb.c's readfile() function had the same disease of preferring to do double the I/O to avoid resizing its output array. Here, we can make things easier by using the just-invented pg_get_line() function to handle reading individual lines without a predetermined notion of how long they are. On my machine, it's difficult to detect any net change in the overall runtime of initdb from these changes; but they should help on slower buildfarm machines (especially since a buildfarm cycle involves a lot of initdb's these days). My attention was drawn to these places by scan-build complaints, but on inspection they needed a lot more work than just suppressing dead stores :-(
1 parent a5cc4da commit e0f05cd

File tree

2 files changed

+74
-91
lines changed

2 files changed

+74
-91
lines changed

src/backend/bootstrap/bootstrap.c

Lines changed: 60 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,12 @@
5353
uint32 bootstrap_data_checksum_version = 0; /* No checksum */
5454

5555

56-
#define ALLOC(t, c) \
57-
((t *) MemoryContextAllocZero(TopMemoryContext, (unsigned)(c) * sizeof(t)))
58-
5956
static void CheckerModeMain(void);
6057
static void BootstrapModeMain(void);
6158
static void bootstrap_signals(void);
6259
static void ShutdownAuxiliaryProcess(int code, Datum arg);
6360
static Form_pg_attribute AllocateAttribute(void);
61+
static void populate_typ_array(void);
6462
static Oid gettype(char *type);
6563
static void cleanup(void);
6664

@@ -583,46 +581,24 @@ ShutdownAuxiliaryProcess(int code, Datum arg)
583581

584582
/* ----------------
585583
* boot_openrel
584+
*
585+
* Execute BKI OPEN command.
586586
* ----------------
587587
*/
588588
void
589589
boot_openrel(char *relname)
590590
{
591591
int i;
592-
struct typmap **app;
593-
Relation rel;
594-
TableScanDesc scan;
595-
HeapTuple tup;
596592

597593
if (strlen(relname) >= NAMEDATALEN)
598594
relname[NAMEDATALEN - 1] = '\0';
599595

596+
/*
597+
* pg_type must be filled before any OPEN command is executed, hence we
598+
* can now populate the Typ array if we haven't yet.
599+
*/
600600
if (Typ == NULL)
601-
{
602-
/* We can now load the pg_type data */
603-
rel = table_open(TypeRelationId, NoLock);
604-
scan = table_beginscan_catalog(rel, 0, NULL);
605-
i = 0;
606-
while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
607-
++i;
608-
table_endscan(scan);
609-
app = Typ = ALLOC(struct typmap *, i + 1);
610-
while (i-- > 0)
611-
*app++ = ALLOC(struct typmap, 1);
612-
*app = NULL;
613-
scan = table_beginscan_catalog(rel, 0, NULL);
614-
app = Typ;
615-
while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
616-
{
617-
(*app)->am_oid = ((Form_pg_type) GETSTRUCT(tup))->oid;
618-
memcpy((char *) &(*app)->am_typ,
619-
(char *) GETSTRUCT(tup),
620-
sizeof((*app)->am_typ));
621-
app++;
622-
}
623-
table_endscan(scan);
624-
table_close(rel, NoLock);
625-
}
601+
populate_typ_array();
626602

627603
if (boot_reldesc != NULL)
628604
closerel(NULL);
@@ -889,6 +865,52 @@ cleanup(void)
889865
closerel(NULL);
890866
}
891867

868+
/* ----------------
869+
* populate_typ_array
870+
*
871+
* Load the Typ array by reading pg_type.
872+
* ----------------
873+
*/
874+
static void
875+
populate_typ_array(void)
876+
{
877+
Relation rel;
878+
TableScanDesc scan;
879+
HeapTuple tup;
880+
int nalloc;
881+
int i;
882+
883+
Assert(Typ == NULL);
884+
885+
nalloc = 512;
886+
Typ = (struct typmap **)
887+
MemoryContextAlloc(TopMemoryContext, nalloc * sizeof(struct typmap *));
888+
889+
rel = table_open(TypeRelationId, NoLock);
890+
scan = table_beginscan_catalog(rel, 0, NULL);
891+
i = 0;
892+
while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
893+
{
894+
Form_pg_type typForm = (Form_pg_type) GETSTRUCT(tup);
895+
896+
/* make sure there will be room for a trailing NULL pointer */
897+
if (i >= nalloc - 1)
898+
{
899+
nalloc *= 2;
900+
Typ = (struct typmap **)
901+
repalloc(Typ, nalloc * sizeof(struct typmap *));
902+
}
903+
Typ[i] = (struct typmap *)
904+
MemoryContextAlloc(TopMemoryContext, sizeof(struct typmap));
905+
Typ[i]->am_oid = typForm->oid;
906+
memcpy(&(Typ[i]->am_typ), typForm, sizeof(Typ[i]->am_typ));
907+
i++;
908+
}
909+
Typ[i] = NULL; /* Fill trailing NULL pointer */
910+
table_endscan(scan);
911+
table_close(rel, NoLock);
912+
}
913+
892914
/* ----------------
893915
* gettype
894916
*
@@ -903,14 +925,10 @@ cleanup(void)
903925
static Oid
904926
gettype(char *type)
905927
{
906-
int i;
907-
Relation rel;
908-
TableScanDesc scan;
909-
HeapTuple tup;
910-
struct typmap **app;
911-
912928
if (Typ != NULL)
913929
{
930+
struct typmap **app;
931+
914932
for (app = Typ; *app != NULL; app++)
915933
{
916934
if (strncmp(NameStr((*app)->am_typ.typname), type, NAMEDATALEN) == 0)
@@ -922,33 +940,16 @@ gettype(char *type)
922940
}
923941
else
924942
{
943+
int i;
944+
925945
for (i = 0; i < n_types; i++)
926946
{
927947
if (strncmp(type, TypInfo[i].name, NAMEDATALEN) == 0)
928948
return i;
929949
}
950+
/* Not in TypInfo, so we'd better be able to read pg_type now */
930951
elog(DEBUG4, "external type: %s", type);
931-
rel = table_open(TypeRelationId, NoLock);
932-
scan = table_beginscan_catalog(rel, 0, NULL);
933-
i = 0;
934-
while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
935-
++i;
936-
table_endscan(scan);
937-
app = Typ = ALLOC(struct typmap *, i + 1);
938-
while (i-- > 0)
939-
*app++ = ALLOC(struct typmap, 1);
940-
*app = NULL;
941-
scan = table_beginscan_catalog(rel, 0, NULL);
942-
app = Typ;
943-
while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
944-
{
945-
(*app)->am_oid = ((Form_pg_type) GETSTRUCT(tup))->oid;
946-
memmove((char *) &(*app++)->am_typ,
947-
(char *) GETSTRUCT(tup),
948-
sizeof((*app)->am_typ));
949-
}
950-
table_endscan(scan);
951-
table_close(rel, NoLock);
952+
populate_typ_array();
952953
return gettype(type);
953954
}
954955
elog(ERROR, "unrecognized type \"%s\"", type);

src/bin/initdb/initdb.c

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -468,54 +468,36 @@ filter_lines_with_token(char **lines, const char *token)
468468
static char **
469469
readfile(const char *path)
470470
{
471+
char **result;
471472
FILE *infile;
472-
int maxlength = 1,
473-
linelen = 0;
474-
int nlines = 0;
473+
int maxlines;
475474
int n;
476-
char **result;
477-
char *buffer;
478-
int c;
475+
char *ln;
479476

480477
if ((infile = fopen(path, "r")) == NULL)
481478
{
482479
pg_log_error("could not open file \"%s\" for reading: %m", path);
483480
exit(1);
484481
}
485482

486-
/* pass over the file twice - the first time to size the result */
483+
maxlines = 1024;
484+
result = (char **) pg_malloc(maxlines * sizeof(char *));
487485

488-
while ((c = fgetc(infile)) != EOF)
486+
n = 0;
487+
while ((ln = pg_get_line(infile)) != NULL)
489488
{
490-
linelen++;
491-
if (c == '\n')
489+
/* make sure there will be room for a trailing NULL pointer */
490+
if (n >= maxlines - 1)
492491
{
493-
nlines++;
494-
if (linelen > maxlength)
495-
maxlength = linelen;
496-
linelen = 0;
492+
maxlines *= 2;
493+
result = (char **) pg_realloc(result, maxlines * sizeof(char *));
497494
}
498-
}
499-
500-
/* handle last line without a terminating newline (yuck) */
501-
if (linelen)
502-
nlines++;
503-
if (linelen > maxlength)
504-
maxlength = linelen;
505495

506-
/* set up the result and the line buffer */
507-
result = (char **) pg_malloc((nlines + 1) * sizeof(char *));
508-
buffer = (char *) pg_malloc(maxlength + 1);
509-
510-
/* now reprocess the file and store the lines */
511-
rewind(infile);
512-
n = 0;
513-
while (fgets(buffer, maxlength + 1, infile) != NULL && n < nlines)
514-
result[n++] = pg_strdup(buffer);
496+
result[n++] = ln;
497+
}
498+
result[n] = NULL;
515499

516500
fclose(infile);
517-
free(buffer);
518-
result[n] = NULL;
519501

520502
return result;
521503
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy