diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-09-05 16:20:04 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-09-05 16:20:04 -0400 |
commit | e0f05cd5ba76a75e2ce3b85ba050e48e857dca00 (patch) | |
tree | 5c0ba4e65ab145e66f8c1ccadf026a3f4cbea957 /src/backend/bootstrap/bootstrap.c | |
parent | a5cc4dab6d1d694f113912a2aca7012a95262f0b (diff) | |
download | postgresql-e0f05cd5ba76a75e2ce3b85ba050e48e857dca00.tar.gz postgresql-e0f05cd5ba76a75e2ce3b85ba050e48e857dca00.zip |
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 :-(
Diffstat (limited to 'src/backend/bootstrap/bootstrap.c')
-rw-r--r-- | src/backend/bootstrap/bootstrap.c | 119 |
1 files changed, 60 insertions, 59 deletions
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 45b7efbe465..76b2f5066f6 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -53,14 +53,12 @@ uint32 bootstrap_data_checksum_version = 0; /* No checksum */ -#define ALLOC(t, c) \ - ((t *) MemoryContextAllocZero(TopMemoryContext, (unsigned)(c) * sizeof(t))) - static void CheckerModeMain(void); static void BootstrapModeMain(void); static void bootstrap_signals(void); static void ShutdownAuxiliaryProcess(int code, Datum arg); static Form_pg_attribute AllocateAttribute(void); +static void populate_typ_array(void); static Oid gettype(char *type); static void cleanup(void); @@ -583,46 +581,24 @@ ShutdownAuxiliaryProcess(int code, Datum arg) /* ---------------- * boot_openrel + * + * Execute BKI OPEN command. * ---------------- */ void boot_openrel(char *relname) { int i; - struct typmap **app; - Relation rel; - TableScanDesc scan; - HeapTuple tup; if (strlen(relname) >= NAMEDATALEN) relname[NAMEDATALEN - 1] = '\0'; + /* + * pg_type must be filled before any OPEN command is executed, hence we + * can now populate the Typ array if we haven't yet. + */ if (Typ == NULL) - { - /* We can now load the pg_type data */ - rel = table_open(TypeRelationId, NoLock); - scan = table_beginscan_catalog(rel, 0, NULL); - i = 0; - while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) - ++i; - table_endscan(scan); - app = Typ = ALLOC(struct typmap *, i + 1); - while (i-- > 0) - *app++ = ALLOC(struct typmap, 1); - *app = NULL; - scan = table_beginscan_catalog(rel, 0, NULL); - app = Typ; - while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) - { - (*app)->am_oid = ((Form_pg_type) GETSTRUCT(tup))->oid; - memcpy((char *) &(*app)->am_typ, - (char *) GETSTRUCT(tup), - sizeof((*app)->am_typ)); - app++; - } - table_endscan(scan); - table_close(rel, NoLock); - } + populate_typ_array(); if (boot_reldesc != NULL) closerel(NULL); @@ -890,6 +866,52 @@ cleanup(void) } /* ---------------- + * populate_typ_array + * + * Load the Typ array by reading pg_type. + * ---------------- + */ +static void +populate_typ_array(void) +{ + Relation rel; + TableScanDesc scan; + HeapTuple tup; + int nalloc; + int i; + + Assert(Typ == NULL); + + nalloc = 512; + Typ = (struct typmap **) + MemoryContextAlloc(TopMemoryContext, nalloc * sizeof(struct typmap *)); + + rel = table_open(TypeRelationId, NoLock); + scan = table_beginscan_catalog(rel, 0, NULL); + i = 0; + while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) + { + Form_pg_type typForm = (Form_pg_type) GETSTRUCT(tup); + + /* make sure there will be room for a trailing NULL pointer */ + if (i >= nalloc - 1) + { + nalloc *= 2; + Typ = (struct typmap **) + repalloc(Typ, nalloc * sizeof(struct typmap *)); + } + Typ[i] = (struct typmap *) + MemoryContextAlloc(TopMemoryContext, sizeof(struct typmap)); + Typ[i]->am_oid = typForm->oid; + memcpy(&(Typ[i]->am_typ), typForm, sizeof(Typ[i]->am_typ)); + i++; + } + Typ[i] = NULL; /* Fill trailing NULL pointer */ + table_endscan(scan); + table_close(rel, NoLock); +} + +/* ---------------- * gettype * * NB: this is really ugly; it will return an integer index into TypInfo[], @@ -903,14 +925,10 @@ cleanup(void) static Oid gettype(char *type) { - int i; - Relation rel; - TableScanDesc scan; - HeapTuple tup; - struct typmap **app; - if (Typ != NULL) { + struct typmap **app; + for (app = Typ; *app != NULL; app++) { if (strncmp(NameStr((*app)->am_typ.typname), type, NAMEDATALEN) == 0) @@ -922,33 +940,16 @@ gettype(char *type) } else { + int i; + for (i = 0; i < n_types; i++) { if (strncmp(type, TypInfo[i].name, NAMEDATALEN) == 0) return i; } + /* Not in TypInfo, so we'd better be able to read pg_type now */ elog(DEBUG4, "external type: %s", type); - rel = table_open(TypeRelationId, NoLock); - scan = table_beginscan_catalog(rel, 0, NULL); - i = 0; - while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) - ++i; - table_endscan(scan); - app = Typ = ALLOC(struct typmap *, i + 1); - while (i-- > 0) - *app++ = ALLOC(struct typmap, 1); - *app = NULL; - scan = table_beginscan_catalog(rel, 0, NULL); - app = Typ; - while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) - { - (*app)->am_oid = ((Form_pg_type) GETSTRUCT(tup))->oid; - memmove((char *) &(*app++)->am_typ, - (char *) GETSTRUCT(tup), - sizeof((*app)->am_typ)); - } - table_endscan(scan); - table_close(rel, NoLock); + populate_typ_array(); return gettype(type); } elog(ERROR, "unrecognized type \"%s\"", type); |