From 12d8fae4cd2c460a281c946c49629da1136ead08 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 27 Sep 2009 01:32:11 +0000 Subject: [PATCH] Simplify the bootstrap (BKI) code by getting rid of a useless table of all the strings seen during the bootstrap run. There might have been some actual point to doing that, many years ago, but as far as I can see the only value now is to conserve a bit of memory. Even if we cared about wasting a megabyte or so during the initdb run, it'd be far more effective to arrange to release memory at the end of each BKI command, instead of intentionally hanging onto strings that might never be used again. Not maintaining the table probably makes it faster too; but the main point of this patch is to get rid of a couple hundred lines of unnecessary and rather crufty code. --- src/backend/bootstrap/bootparse.y | 72 +++++------ src/backend/bootstrap/bootscanner.l | 15 +-- src/backend/bootstrap/bootstrap.c | 190 +--------------------------- src/include/bootstrap/bootstrap.h | 44 +++---- 4 files changed, 66 insertions(+), 255 deletions(-) diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y index 0b2733148e..b7624547aa 100644 --- a/src/backend/bootstrap/bootparse.y +++ b/src/backend/bootstrap/bootparse.y @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.98 2009/09/26 22:42:01 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.99 2009/09/27 01:32:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -87,7 +87,7 @@ do_end(void) } -int num_columns_read = 0; +static int num_columns_read = 0; %} @@ -105,16 +105,16 @@ int num_columns_read = 0; %type boot_index_params %type boot_index_param -%type boot_const boot_ident +%type boot_const boot_ident %type optbootstrap optsharedrelation optwithoutoids -%type boot_tuple boot_tuplelist %type oidspec optoideq optrowtypeoid -%token CONST_P ID +%token CONST_P ID %token OPEN XCLOSE XCREATE INSERT_TUPLE %token XDECLARE INDEX ON USING XBUILD INDICES UNIQUE XTOAST %token COMMA EQUALS LPAREN RPAREN %token OBJ_ID XBOOTSTRAP XSHARED_RELATION XWITHOUT_OIDS XROWTYPE_OID NULLVAL + %start TopLevel %nonassoc low @@ -147,7 +147,7 @@ Boot_OpenStmt: OPEN boot_ident { do_start(); - boot_openrel(LexIDStr($2)); + boot_openrel($2); do_end(); } ; @@ -156,7 +156,7 @@ Boot_CloseStmt: XCLOSE boot_ident %prec low { do_start(); - closerel(LexIDStr($2)); + closerel($2); do_end(); } | XCLOSE %prec high @@ -175,10 +175,10 @@ Boot_CreateStmt: elog(DEBUG4, "creating%s%s relation %s %u", $4 ? " bootstrap" : "", $5 ? " shared" : "", - LexIDStr($2), + $2, $3); } - boot_typelist + boot_column_list { do_end(); } @@ -198,7 +198,7 @@ Boot_CreateStmt: closerel(NULL); } - boot_reldesc = heap_create(LexIDStr($2), + boot_reldesc = heap_create($2, PG_CATALOG_NAMESPACE, $5 ? GLOBALTABLESPACE_OID : 0, $3, @@ -212,7 +212,7 @@ Boot_CreateStmt: { Oid id; - id = heap_create_with_catalog(LexIDStr($2), + id = heap_create_with_catalog($2, PG_CATALOG_NAMESPACE, $5 ? GLOBALTABLESPACE_OID : 0, $3, @@ -243,7 +243,7 @@ Boot_InsertStmt: elog(DEBUG4, "inserting row"); num_columns_read = 0; } - LPAREN boot_tuplelist RPAREN + LPAREN boot_column_val_list RPAREN { if (num_columns_read != numattr) elog(ERROR, "incorrect number of columns in row (expected %d, got %d)", @@ -260,10 +260,10 @@ Boot_DeclareIndexStmt: { do_start(); - DefineIndex(makeRangeVar(NULL, LexIDStr($6), -1), - LexIDStr($3), + DefineIndex(makeRangeVar(NULL, $6, -1), + $3, $4, - LexIDStr($8), + $8, NULL, $10, NULL, NIL, @@ -278,10 +278,10 @@ Boot_DeclareUniqueIndexStmt: { do_start(); - DefineIndex(makeRangeVar(NULL, LexIDStr($7), -1), - LexIDStr($4), + DefineIndex(makeRangeVar(NULL, $7, -1), + $4, $5, - LexIDStr($9), + $9, NULL, $11, NULL, NIL, @@ -296,7 +296,7 @@ Boot_DeclareToastStmt: { do_start(); - BootstrapToastTable(LexIDStr($6), $3, $4); + BootstrapToastTable($6, $3, $4); do_end(); } ; @@ -320,9 +320,9 @@ boot_index_param: boot_ident boot_ident { IndexElem *n = makeNode(IndexElem); - n->name = LexIDStr($1); + n->name = $1; n->expr = NULL; - n->opclass = list_make1(makeString(LexIDStr($2))); + n->opclass = list_make1(makeString($2)); n->ordering = SORTBY_DEFAULT; n->nulls_ordering = SORTBY_NULLS_DEFAULT; $$ = n; @@ -349,22 +349,22 @@ optrowtypeoid: | { $$ = InvalidOid; } ; -boot_typelist: - boot_type_thing - | boot_typelist COMMA boot_type_thing +boot_column_list: + boot_column_def + | boot_column_list COMMA boot_column_def ; -boot_type_thing: +boot_column_def: boot_ident EQUALS boot_ident { if (++numattr > MAXATTR) elog(FATAL, "too many columns"); - DefineAttr(LexIDStr($1),LexIDStr($3),numattr-1); + DefineAttr($1, $3, numattr-1); } ; oidspec: - boot_ident { $$ = atooid(LexIDStr($1)); } + boot_ident { $$ = atooid($1); } ; optoideq: @@ -372,27 +372,27 @@ optoideq: | { $$ = InvalidOid; } ; -boot_tuplelist: - boot_tuple - | boot_tuplelist boot_tuple - | boot_tuplelist COMMA boot_tuple +boot_column_val_list: + boot_column_val + | boot_column_val_list boot_column_val + | boot_column_val_list COMMA boot_column_val ; -boot_tuple: +boot_column_val: boot_ident - { InsertOneValue(LexIDStr($1), num_columns_read++); } + { InsertOneValue($1, num_columns_read++); } | boot_const - { InsertOneValue(LexIDStr($1), num_columns_read++); } + { InsertOneValue($1, num_columns_read++); } | NULLVAL { InsertOneNull(num_columns_read++); } ; boot_const : - CONST_P { $$=yylval.ival; } + CONST_P { $$ = yylval.str; } ; boot_ident : - ID { $$=yylval.ival; } + ID { $$ = yylval.str; } ; %% diff --git a/src/backend/bootstrap/bootscanner.l b/src/backend/bootstrap/bootscanner.l index d4bcffee53..92defef159 100644 --- a/src/backend/bootstrap/bootscanner.l +++ b/src/backend/bootstrap/bootscanner.l @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/bootstrap/bootscanner.l,v 1.49 2009/09/26 22:42:01 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/bootstrap/bootscanner.l,v 1.50 2009/09/27 01:32:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -104,21 +104,16 @@ insert { return(INSERT_TUPLE); } "toast" { return(XTOAST); } {arrayid} { - yylval.ival = EnterString(MapArrayTypeName((char*)yytext)); + yylval.str = pstrdup(MapArrayTypeName(yytext)); return(ID); } {id} { - char *newid = scanstr((char*)yytext); - yylval.ival = EnterString(newid); - pfree(newid); + yylval.str = scanstr(yytext); return(ID); } {sid} { - char *newid; yytext[strlen(yytext)-1] = '\0'; /* strip off quotes */ - newid = scanstr((char*)yytext+1); - yylval.ival = EnterString(newid); - pfree(newid); + yylval.str = scanstr(yytext+1); yytext[strlen(yytext)] = '"'; /* restore quotes */ return(ID); } @@ -126,7 +121,7 @@ insert { return(INSERT_TUPLE); } (-)?{D}+"."{D}*({Exp})? | (-)?{D}*"."{D}+({Exp})? | (-)?{D}+{Exp} { - yylval.ival = EnterString((char*)yytext); + yylval.str = pstrdup(yytext); return(CONST_P); } diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index ac560ee298..89991ea2fb 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.252 2009/08/02 22:14:51 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.253 2009/09/27 01:32:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,10 +53,7 @@ static void CheckerModeMain(void); static void BootstrapModeMain(void); static void bootstrap_signals(void); static void ShutdownAuxiliaryProcess(int code, Datum arg); -static hashnode *AddStr(char *str, int strlength, int mderef); static Form_pg_attribute AllocateAttribute(void); -static int CompHash(char *str, int len); -static hashnode *FindStr(char *str, int length, hashnode *mderef); static Oid gettype(char *type); static void cleanup(void); @@ -67,30 +64,11 @@ static void cleanup(void); Relation boot_reldesc; /* current relation descriptor */ +Form_pg_attribute attrtypes[MAXATTR]; /* points to attribute info */ +int numattr; /* number of attributes for cur. rel */ + + /* - * In the lexical analyzer, we need to get the reference number quickly from - * the string, and the string from the reference number. Thus we have - * as our data structure a hash table, where the hashing key taken from - * the particular string. The hash table is chained. One of the fields - * of the hash table node is an index into the array of character pointers. - * The unique index number that every string is assigned is simply the - * position of its string pointer in the array of string pointers. - */ - -#define STRTABLESIZE 10000 -#define HASHTABLESIZE 503 - -/* Hash function numbers */ -#define NUM 23 -#define NUMSQR 529 -#define NUMCUBE 12167 - -char *strtable[STRTABLESIZE]; -hashnode *hashtable[HASHTABLESIZE]; - -static int strtable_end = -1; /* Tells us last occupied string space */ - -/*- * Basic information associated with each type. This is used before * pg_type is created. * @@ -169,12 +147,9 @@ struct typmap static struct typmap **Typ = NULL; static struct typmap *Ap = NULL; +static Datum values[MAXATTR]; /* current row's attribute values */ static bool Nulls[MAXATTR]; -Form_pg_attribute attrtypes[MAXATTR]; /* points to attribute info */ -static Datum values[MAXATTR]; /* corresponding attribute values */ -int numattr; /* number of attributes for cur. rel */ - static MemoryContext nogc = NULL; /* special no-gc mem context */ /* @@ -501,10 +476,6 @@ BootstrapModeMain(void) attrtypes[i] = NULL; Nulls[i] = false; } - for (i = 0; i < STRTABLESIZE; ++i) - strtable[i] = NULL; - for (i = 0; i < HASHTABLESIZE; ++i) - hashtable[i] = NULL; /* * Process bootstrap input. @@ -1080,155 +1051,6 @@ MapArrayTypeName(char *s) return newStr; } -/* ---------------- - * EnterString - * returns the string table position of the identifier - * passed to it. We add it to the table if we can't find it. - * ---------------- - */ -int -EnterString(char *str) -{ - hashnode *node; - int len; - - len = strlen(str); - - node = FindStr(str, len, NULL); - if (node) - return node->strnum; - else - { - node = AddStr(str, len, 0); - return node->strnum; - } -} - -/* ---------------- - * LexIDStr - * when given an idnum into the 'string-table' return the string - * associated with the idnum - * ---------------- - */ -char * -LexIDStr(int ident_num) -{ - return strtable[ident_num]; -} - - -/* ---------------- - * CompHash - * - * Compute a hash function for a given string. We look at the first, - * the last, and the middle character of a string to try to get spread - * the strings out. The function is rather arbitrary, except that we - * are mod'ing by a prime number. - * ---------------- - */ -static int -CompHash(char *str, int len) -{ - int result; - - result = (NUM * str[0] + NUMSQR * str[len - 1] + NUMCUBE * str[(len - 1) / 2]); - - return result % HASHTABLESIZE; - -} - -/* ---------------- - * FindStr - * - * This routine looks for the specified string in the hash - * table. It returns a pointer to the hash node found, - * or NULL if the string is not in the table. - * ---------------- - */ -static hashnode * -FindStr(char *str, int length, hashnode *mderef) -{ - hashnode *node; - - node = hashtable[CompHash(str, length)]; - while (node != NULL) - { - /* - * We must differentiate between string constants that might have the - * same value as a identifier and the identifier itself. - */ - if (!strcmp(str, strtable[node->strnum])) - { - return node; /* no need to check */ - } - else - node = node->next; - } - /* Couldn't find it in the list */ - return NULL; -} - -/* ---------------- - * AddStr - * - * This function adds the specified string, along with its associated - * data, to the hash table and the string table. We return the node - * so that the calling routine can find out the unique id that AddStr - * has assigned to this string. - * ---------------- - */ -static hashnode * -AddStr(char *str, int strlength, int mderef) -{ - hashnode *temp, - *trail, - *newnode; - int hashresult; - int len; - - if (++strtable_end >= STRTABLESIZE) - elog(FATAL, "bootstrap string table overflow"); - - /* - * Some of the utilites (eg, define type, create relation) assume that the - * string they're passed is a NAMEDATALEN. We get array bound read - * violations from purify if we don't allocate at least NAMEDATALEN bytes - * for strings of this sort. Because we're lazy, we allocate at least - * NAMEDATALEN bytes all the time. - */ - - if ((len = strlength + 1) < NAMEDATALEN) - len = NAMEDATALEN; - - strtable[strtable_end] = malloc((unsigned) len); - strcpy(strtable[strtable_end], str); - - /* Now put a node in the hash table */ - - newnode = (hashnode *) malloc(sizeof(hashnode) * 1); - newnode->strnum = strtable_end; - newnode->next = NULL; - - /* Find out where it goes */ - - hashresult = CompHash(str, strlength); - if (hashtable[hashresult] == NULL) - hashtable[hashresult] = newnode; - else - { /* There is something in the list */ - trail = hashtable[hashresult]; - temp = trail->next; - while (temp != NULL) - { - trail = temp; - temp = temp->next; - } - trail->next = newnode; - } - return newnode; -} - - /* * index_register() -- record an index that has been set up for building diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h index acc6468f9d..3ae14b0faf 100644 --- a/src/include/bootstrap/bootstrap.h +++ b/src/include/bootstrap/bootstrap.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/bootstrap/bootstrap.h,v 1.52 2009/07/31 20:26:23 tgl Exp $ + * $PostgreSQL: pgsql/src/include/bootstrap/bootstrap.h,v 1.53 2009/09/27 01:32:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,38 +16,43 @@ #include "nodes/execnodes.h" +typedef enum +{ + CheckerProcess, + BootstrapProcess, + StartupProcess, + BgWriterProcess, + WalWriterProcess, + + NUM_AUXPROCTYPES /* Must be last! */ +} AuxProcType; + /* * MAXATTR is the maximum number of attributes in a relation supported * at bootstrap time (i.e., the max possible in a system table). */ #define MAXATTR 40 -typedef struct hashnode -{ - int strnum; /* Index into string table */ - struct hashnode *next; -} hashnode; - - extern Relation boot_reldesc; extern Form_pg_attribute attrtypes[MAXATTR]; extern int numattr; + + extern void AuxiliaryProcessMain(int argc, char *argv[]); -extern void index_register(Oid heap, Oid ind, IndexInfo *indexInfo); - extern void err_out(void); -extern void InsertOneTuple(Oid objectid); + extern void closerel(char *name); extern void boot_openrel(char *name); -extern char *LexIDStr(int ident_num); extern void DefineAttr(char *name, char *type, int attnum); +extern void InsertOneTuple(Oid objectid); extern void InsertOneValue(char *value, int i); extern void InsertOneNull(int i); + extern char *MapArrayTypeName(char *s); -extern char *CleanUpStr(char *s); -extern int EnterString(char *str); + +extern void index_register(Oid heap, Oid ind, IndexInfo *indexInfo); extern void build_indices(void); extern void boot_get_type_io_data(Oid typid, @@ -64,15 +69,4 @@ extern int boot_yyparse(void); extern int boot_yylex(void); extern void boot_yyerror(const char *str); -typedef enum -{ - CheckerProcess, - BootstrapProcess, - StartupProcess, - BgWriterProcess, - WalWriterProcess, - - NUM_AUXPROCTYPES /* Must be last! */ -} AuxProcType; - #endif /* BOOTSTRAP_H */