Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+60-59
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

+14-32
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)