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.
This commit is contained in:
Tom Lane 2009-09-27 01:32:11 +00:00
parent 23cf415a65
commit 12d8fae4cd
4 changed files with 66 additions and 255 deletions

View File

@ -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 <list> boot_index_params
%type <ielem> boot_index_param
%type <ival> boot_const boot_ident
%type <str> boot_const boot_ident
%type <ival> optbootstrap optsharedrelation optwithoutoids
%type <ival> boot_tuple boot_tuplelist
%type <oidval> oidspec optoideq optrowtypeoid
%token <ival> CONST_P ID
%token <str> 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; }
;
%%

View File

@ -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);
}

View File

@ -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

View File

@ -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 */