📄 bootstrap.c
字号:
/*------------------------------------------------------------------------- * * bootstrap.c * routines to support running postgres in 'bootstrap' mode * bootstrap mode is used to create the initial template database * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.166 2003/09/02 19:04:12 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <unistd.h>#include <time.h>#include <signal.h>#include <setjmp.h>#ifdef HAVE_GETOPT_H#include <getopt.h>#endif#define BOOTSTRAP_INCLUDE /* mask out stuff in tcop/tcopprot.h */#include "access/genam.h"#include "access/heapam.h"#include "access/xlog.h"#include "bootstrap/bootstrap.h"#include "catalog/catname.h"#include "catalog/index.h"#include "catalog/pg_type.h"#include "executor/executor.h"#include "libpq/pqsignal.h"#include "miscadmin.h"#include "storage/freespace.h"#include "storage/ipc.h"#include "storage/pg_shmem.h"#include "storage/proc.h"#include "tcop/tcopprot.h"#include "utils/builtins.h"#include "utils/fmgroids.h"#include "utils/guc.h"#include "utils/lsyscache.h"#include "utils/relcache.h"#define ALLOC(t, c) ((t *) calloc((unsigned)(c), sizeof(t)))extern int Int_yyparse(void);static hashnode *AddStr(char *str, int strlength, int mderef);static Form_pg_attribute AllocateAttribute(void);static bool BootstrapAlreadySeen(Oid id);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);/* ---------------- * global variables * ---------------- */Relation boot_reldesc; /* current relation descriptor *//* * 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 12167char *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. * * XXX several of these input/output functions do catalog scans * (e.g., F_REGPROCIN scans pg_proc). this obviously creates some * order dependencies in the catalog creation process. */struct typinfo{ char name[NAMEDATALEN]; Oid oid; Oid elem; int16 len; Oid inproc; Oid outproc;};static struct typinfo Procid[] = { {"bool", BOOLOID, 0, 1, F_BOOLIN, F_BOOLOUT}, {"bytea", BYTEAOID, 0, -1, F_BYTEAIN, F_BYTEAOUT}, {"char", CHAROID, 0, 1, F_CHARIN, F_CHAROUT}, {"name", NAMEOID, 0, NAMEDATALEN, F_NAMEIN, F_NAMEOUT}, {"int2", INT2OID, 0, 2, F_INT2IN, F_INT2OUT}, {"int2vector", INT2VECTOROID, 0, INDEX_MAX_KEYS * 2, F_INT2VECTORIN, F_INT2VECTOROUT}, {"int4", INT4OID, 0, 4, F_INT4IN, F_INT4OUT}, {"regproc", REGPROCOID, 0, 4, F_REGPROCIN, F_REGPROCOUT}, {"regclass", REGCLASSOID, 0, 4, F_REGCLASSIN, F_REGCLASSOUT}, {"regtype", REGTYPEOID, 0, 4, F_REGTYPEIN, F_REGTYPEOUT}, {"text", TEXTOID, 0, -1, F_TEXTIN, F_TEXTOUT}, {"oid", OIDOID, 0, 4, F_OIDIN, F_OIDOUT}, {"tid", TIDOID, 0, 6, F_TIDIN, F_TIDOUT}, {"xid", XIDOID, 0, 4, F_XIDIN, F_XIDOUT}, {"cid", CIDOID, 0, 4, F_CIDIN, F_CIDOUT}, {"oidvector", OIDVECTOROID, 0, INDEX_MAX_KEYS * 4, F_OIDVECTORIN, F_OIDVECTOROUT}, {"smgr", 210, 0, 2, F_SMGRIN, F_SMGROUT}, {"_int4", 1007, INT4OID, -1, F_ARRAY_IN, F_ARRAY_OUT}, {"_aclitem", 1034, 1033, -1, F_ARRAY_IN, F_ARRAY_OUT}};static int n_types = sizeof(Procid) / sizeof(struct typinfo);struct typmap{ /* a hack */ Oid am_oid; FormData_pg_type am_typ;};static struct typmap **Typ = (struct typmap **) NULL;static struct typmap *Ap = (struct typmap *) NULL;static int Warnings = 0;static char Blanks[MAXATTR];static char *relname; /* current relation name */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 */extern int optind;extern char *optarg;/* * At bootstrap time, we first declare all the indices to be built, and * then build them. The IndexList structure stores enough information * to allow us to build the indices after they've been declared. */typedef struct _IndexList{ Oid il_heap; Oid il_ind; IndexInfo *il_info; struct _IndexList *il_next;} IndexList;static IndexList *ILHead = (IndexList *) NULL;/* ---------------------------------------------------------------- * misc functions * ---------------------------------------------------------------- *//* ---------------- * error handling / abort routines * ---------------- */voiderr_out(void){ Warnings++; cleanup();}/* usage: * usage help for the bootstrap backend */static voidusage(void){ fprintf(stderr, gettext("Usage:\n" " postgres -boot [OPTION]... DBNAME\n" " -c NAME=VALUE set run-time parameter\n" " -d 1-5 debug level\n" " -D datadir data directory\n" " -F turn off fsync\n" " -o file send debug output to file\n" " -x num internal use\n")); proc_exit(1);}intBootstrapMain(int argc, char *argv[])/* ---------------------------------------------------------------- * The main loop for handling the backend in bootstrap mode * the bootstrap mode is used to initialize the template database * the bootstrap backend doesn't speak SQL, but instead expects * commands in a special bootstrap language. * * The arguments passed in to BootstrapMain are the run-time arguments * without the argument '-boot', the caller is required to have * removed -boot from the run-time args * ---------------------------------------------------------------- */{ int i; char *dbname; int flag; int xlogop = BS_XLOG_NOP; char *potential_DataDir = NULL; /* * initialize globals */ MyProcPid = getpid(); /* * Fire up essential subsystems: error and memory management * * If we are running under the postmaster, this is done already. */ if (!IsUnderPostmaster /* when exec || ExecBackend */ ) MemoryContextInit(); /* * process command arguments */ /* Set defaults, to be overriden by explicit options below */ dbname = NULL; if (!IsUnderPostmaster /* when exec || ExecBackend */ ) { InitializeGUCOptions(); potential_DataDir = getenv("PGDATA"); /* Null if no PGDATA * variable */ } while ((flag = getopt(argc, argv, "B:c:d:D:Fo:p:x:-:")) != -1) { switch (flag) { case 'D': potential_DataDir = optarg; break; case 'd': { /* Turn on debugging for the bootstrap process. */ char *debugstr = palloc(strlen("debug") + strlen(optarg) + 1); sprintf(debugstr, "debug%s", optarg); SetConfigOption("log_min_messages", debugstr, PGC_POSTMASTER, PGC_S_ARGV); SetConfigOption("client_min_messages", debugstr, PGC_POSTMASTER, PGC_S_ARGV); pfree(debugstr); break; } break; case 'F': SetConfigOption("fsync", "false", PGC_POSTMASTER, PGC_S_ARGV); break; case 'o': StrNCpy(OutputFileName, optarg, MAXPGPATH); break; case 'x': xlogop = atoi(optarg); break; case 'p': { /* indicates fork from postmaster */#ifdef EXEC_BACKEND char *p; sscanf(optarg, "%d,%p,", &UsedShmemSegID, &UsedShmemSegAddr); p = strchr(optarg, ','); if (p) p = strchr(p + 1, ','); if (p) dbname = strdup(p + 1);#else dbname = strdup(optarg);#endif break; } case 'B': SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV); break; case 'c': case '-': { char *name, *value; ParseLongOption(optarg, &name, &value); if (!value) { if (flag == '-') ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("--%s requires a value", optarg))); else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("-c %s requires a value", optarg))); } SetConfigOption(name, value, PGC_POSTMASTER, PGC_S_ARGV); free(name); if (value) free(value); break; } default: usage(); break; } } if (!dbname && argc - optind == 1) { dbname = argv[optind]; optind++; } if (!dbname || argc != optind) usage(); if (IsUnderPostmaster && ExecBackend && MyProc /* ordinary backend */ ) AttachSharedMemoryAndSemaphores(); if (!IsUnderPostmaster /* when exec || ExecBackend */ ) { if (!potential_DataDir) { fprintf(stderr, gettext("%s does not know where to find the database system data.\n" "You must specify the directory that contains the database system\n" "either by specifying the -D invocation option or by setting the\n" "PGDATA environment variable.\n"), argv[0]); proc_exit(1); } SetDataDir(potential_DataDir); } /* Validate we have been given a reasonable-looking DataDir */ Assert(DataDir); ValidatePgVersion(DataDir); /* Acquire configuration parameters */ if (IsUnderPostmaster) {#ifdef EXEC_BACKEND read_nondefault_variables();#endif } else ProcessConfigFile(PGC_POSTMASTER); if (IsUnderPostmaster) { /* * Properly accept or ignore signals the postmaster might send us */ pqsignal(SIGHUP, SIG_IGN); pqsignal(SIGINT, SIG_IGN); /* ignore query-cancel */ pqsignal(SIGTERM, die); pqsignal(SIGQUIT, quickdie); pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, SIG_IGN); pqsignal(SIGUSR2, SIG_IGN); /* * Reset some signals that are accepted by postmaster but not here */ pqsignal(SIGCHLD, SIG_DFL); pqsignal(SIGTTIN, SIG_DFL); pqsignal(SIGTTOU, SIG_DFL); pqsignal(SIGCONT, SIG_DFL); pqsignal(SIGWINCH, SIG_DFL); /* * Unblock signals (they were blocked when the postmaster forked * us) */ PG_SETMASK(&UnBlockSig); } else { /* Set up appropriately for interactive use */ pqsignal(SIGHUP, die); pqsignal(SIGINT, die); pqsignal(SIGTERM, die); pqsignal(SIGQUIT, die); /* * Create lockfile for data directory. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -