]> granicus.if.org Git - postgresql/commitdiff
XLOG (also known as WAL -:)) Bootstrap/Startup/Shutdown.
authorVadim B. Mikheev <vadim4o@yahoo.com>
Wed, 6 Oct 1999 21:58:18 +0000 (21:58 +0000)
committerVadim B. Mikheev <vadim4o@yahoo.com>
Wed, 6 Oct 1999 21:58:18 +0000 (21:58 +0000)
First step in cleaning up backend initialization code.
Fix for FATAL: now FATAL is ERROR + exit.

20 files changed:
src/backend/access/transam/xlog.c
src/backend/bootstrap/bootstrap.c
src/backend/postmaster/postmaster.c
src/backend/storage/buffer/buf_init.c
src/backend/storage/ipc/ipc.c
src/backend/storage/ipc/ipci.c
src/backend/storage/ipc/shmem.c
src/backend/storage/ipc/spin.c
src/backend/storage/lmgr/proc.c
src/backend/tcop/postgres.c
src/backend/utils/error/elog.c
src/backend/utils/init/miscinit.c
src/backend/utils/init/postinit.c
src/backend/utils/time/tqual.c
src/bin/initdb/initdb.sh
src/include/libpq/pqsignal.h
src/include/miscadmin.h
src/include/storage/ipc.h
src/include/storage/spin.h
src/include/tcop/tcopprot.h

index 2a7d60d3aacac61e65a46dc416dd49541253b64d..09605cf94767820884304e3ee1e365836bf4949e 100644 (file)
 
 void           UpdateControlFile(void);
 int                    XLOGShmemSize(void);
+void           XLOGShmemInit(void);
 void           BootStrapXLOG(void);
 void           StartupXLOG(void);
+void           ShutdownXLOG(void);
 void           CreateCheckPoint(bool shutdown);
 
-char      *XLogDir = NULL;
-char      *ControlFilePath = NULL;
+char           XLogDir[MAXPGPATH+1];
+char           ControlFilePath[MAXPGPATH+1];
 uint32         XLOGbuffers = 0;
 XLogRecPtr     MyLastRecPtr = {0, 0};
 bool           StopIfError = false;
@@ -81,7 +83,8 @@ static XLogCtlData               *XLogCtl = NULL;
 
 typedef enum DBState
 {
-       DB_SHUTDOWNED = 1,
+       DB_STARTUP = 0,
+       DB_SHUTDOWNED,
        DB_SHUTDOWNING,
        DB_IN_RECOVERY,
        DB_IN_PRODUCTION
@@ -114,9 +117,9 @@ typedef struct CheckPoint
 } CheckPoint;
 
 /* 
- * We break each log file in 64Mb segments 
+ * We break each log file in 16Mb segments 
  */
-#define XLogSegSize            (64*1024*1024)
+#define XLogSegSize            (16*1024*1024)
 #define        XLogLastSeg             (0xffffffff / XLogSegSize)
 #define        XLogFileSize    (XLogLastSeg * XLogSegSize)
 
@@ -166,6 +169,7 @@ static void                         XLogWrite(char *buffer);
 static int                             XLogFileInit(uint32 log, uint32 seg);
 static int                             XLogFileOpen(uint32 log, uint32 seg, bool econt);
 static XLogRecord         *ReadRecord(XLogRecPtr *RecPtr, char *buffer);
+static char                       *str_time(time_t tnow);
 
 static XLgwrResult             LgwrResult = {{0, 0}, {0, 0}};
 static XLgwrRqst               LgwrRqst = {{0, 0}, {0, 0}};
@@ -173,14 +177,14 @@ static XLgwrRqst          LgwrRqst = {{0, 0}, {0, 0}};
 static int                             logFile = -1;
 static uint32                  logId = 0;
 static uint32                  logSeg = 0;
-static off_t                   logOff = 0;
+static uint32                  logOff = 0;
 
 static XLogRecPtr              ReadRecPtr;
 static XLogRecPtr              EndRecPtr;
 static int                             readFile = -1;
 static uint32                  readId = 0;
 static uint32                  readSeg = 0;
-static off_t                   readOff = (off_t) -1;
+static uint32                  readOff = 0;
 static char                            readBuf[BLCKSZ];
 static XLogRecord         *nextRecord = NULL;
 
@@ -262,7 +266,13 @@ XLogInsert(RmgrId rmid, char *hdr, uint32 hdrlen, char *buf, uint32 buflen)
        freespace -= SizeOfXLogRecord;
        record = (XLogRecord*) Insert->currpos;
        record->xl_prev = Insert->PrevRecord;
-       record->xl_xact_prev = MyLastRecPtr;
+       if (rmid != RM_XLOG_ID)
+               record->xl_xact_prev = MyLastRecPtr;
+       else
+       {
+               record->xl_xact_prev.xlogid = 0;
+               record->xl_xact_prev.xrecoff = 0;
+       }
        record->xl_xid = GetCurrentTransactionId();
        record->xl_len = (len > freespace) ? freespace : len;
        record->xl_info = (len > freespace) ? XLR_TO_BE_CONTINUED : 0;
@@ -271,7 +281,7 @@ XLogInsert(RmgrId rmid, char *hdr, uint32 hdrlen, char *buf, uint32 buflen)
        RecPtr.xrecoff = 
                XLogCtl->xlblocks[curridx].xrecoff - BLCKSZ + 
                Insert->currpos - ((char*) Insert->currpage);
-       if (MyLastRecPtr.xrecoff == 0)
+       if (MyLastRecPtr.xrecoff == 0 && rmid != RM_XLOG_ID)
        {
                SpinAcquire(SInvalLock);
                MyProc->logRec = RecPtr;
@@ -489,7 +499,7 @@ XLogFlush(XLogRecPtr record)
        {
                logId = LgwrResult.Write.xlogid;
                logSeg = (LgwrResult.Write.xrecoff - 1) / XLogSegSize;
-               logOff = (off_t) 0;
+               logOff = 0;
                logFile = XLogFileOpen(logId, logSeg, false);
        }
 
@@ -612,7 +622,7 @@ XLogWrite(char *buffer)
                        }
                        logId = LgwrResult.Write.xlogid;
                        logSeg = (LgwrResult.Write.xrecoff - 1) / XLogSegSize;
-                       logOff = (off_t) 0;
+                       logOff = 0;
                        logFile = XLogFileInit(logId, logSeg);
                        SpinAcquire(ControlFileLockId);
                        ControlFile->logId = logId;
@@ -626,14 +636,14 @@ XLogWrite(char *buffer)
                {
                        logId = LgwrResult.Write.xlogid;
                        logSeg = (LgwrResult.Write.xrecoff - 1) / XLogSegSize;
-                       logOff = (off_t) 0;
+                       logOff = 0;
                        logFile = XLogFileOpen(logId, logSeg, false);
                }
 
                if (logOff != (LgwrResult.Write.xrecoff - BLCKSZ) % XLogSegSize)
                {
                        logOff = (LgwrResult.Write.xrecoff - BLCKSZ) % XLogSegSize;
-                       if (lseek(logFile, logOff, SEEK_SET) < 0)
+                       if (lseek(logFile, (off_t)logOff, SEEK_SET) < 0)
                                elog(STOP, "Lseek(logfile %u seg %u off %u) failed: %d", 
                                                        logId, logSeg, logOff, errno);
                }
@@ -717,6 +727,10 @@ tryAgain:
                elog(STOP, "Fsync(logfile %u seg %u) failed: %d", 
                                        logId, logSeg, errno);
 
+       if (lseek(fd, 0, SEEK_SET) < 0)
+                       elog(STOP, "Lseek(logfile %u seg %u off %u) failed: %d", 
+                                               log, seg, 0, errno);
+
        return(fd);
 }
 
@@ -753,376 +767,56 @@ tryAgain:
        return(fd);
 }
 
-void
-UpdateControlFile()
-{
-       int             fd;
-
-tryAgain:
-       fd = open(ControlFilePath, O_RDWR);
-       if (fd < 0 && (errno == EMFILE || errno == ENFILE))
-       {
-               fd = errno;
-               if (!ReleaseDataFile())
-                       elog(STOP, "Open(cntlfile) failed: %d (and no one data file can be closed)", 
-                                               fd);
-               goto tryAgain;
-       }
-       if (fd < 0)
-               elog(STOP, "Open(cntlfile) failed: %d", errno);
-
-       if (write(fd, ControlFile, BLCKSZ) != BLCKSZ)
-               elog(STOP, "Write(cntlfile) failed: %d", errno);
-
-       if (fsync(fd) != 0)
-               elog(STOP, "Fsync(cntlfile) failed: %d", errno);
-
-       close(fd);
-
-       return;
-}
-
-int
-XLOGShmemSize()
-{
-       if (XLOGbuffers < MinXLOGbuffers)
-               XLOGbuffers = MinXLOGbuffers;
-
-       return(sizeof(XLogCtlData) + BLCKSZ * XLOGbuffers + 
-                       sizeof(XLogRecPtr) * XLOGbuffers + BLCKSZ);
-}
-
-/*
- * This func must be called ONCE on system install
- */
-void
-BootStrapXLOG()
+static XLogRecord*
+ReadRecord(XLogRecPtr *RecPtr, char *buffer)
 {
-       int                             fd;
-       char                    buffer[BLCKSZ];
-       XLogPageHeader  page = (XLogPageHeader)buffer;
-       CheckPoint              checkPoint;
        XLogRecord         *record;
+       XLogRecPtr              tmpRecPtr = EndRecPtr;
+       bool                    nextmode = (RecPtr == NULL);
+       int                             emode = (nextmode) ? LOG : STOP;
+       bool                    noBlck = false;
 
-       fd = open(ControlFilePath, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
-       if (fd < 0)
-               elog(STOP, "BootStrapXLOG failed to create control file: %d", errno);
-
-       logFile = XLogFileInit(0, 0);
-
-       checkPoint.redo.xlogid = 0;
-       checkPoint.redo.xrecoff = SizeOfXLogPHD;
-       checkPoint.undo = checkPoint.redo;
-       checkPoint.nextXid = FirstTransactionId;
-       checkPoint.nextOid =  BootstrapObjectIdData;
-
-       memset(buffer, 0, BLCKSZ);
-       page->xlp_magic = XLOG_PAGE_MAGIC;
-       page->xlp_info = 0;
-       record = (XLogRecord*) ((char*)page + SizeOfXLogPHD);
-       record->xl_prev.xlogid = 0; record->xl_prev.xrecoff = 0;
-       record->xl_xact_prev = record->xl_prev;
-       record->xl_xid = InvalidTransactionId;
-       record->xl_len = sizeof(checkPoint);
-       record->xl_info = 0;
-       record->xl_rmid = RM_XLOG_ID;
-       memcpy((char*)record + SizeOfXLogRecord, &checkPoint, sizeof(checkPoint));
-
-       if (write(logFile, buffer, BLCKSZ) != BLCKSZ)
-               elog(STOP, "BootStrapXLOG failed to write logfile: %d", errno);
-
-       if (fsync(logFile) != 0)
-               elog(STOP, "BootStrapXLOG failed to fsync logfile: %d", errno);
-
-       close(logFile);
-       logFile = -1;
-
-       memset(buffer, 0, BLCKSZ);
-       ControlFile = (ControlFileData*) buffer;
-       ControlFile->logId = 0;
-       ControlFile->logSeg = 1;
-       ControlFile->checkPoint = checkPoint.redo;
-       ControlFile->time = time(NULL);
-       ControlFile->state = DB_SHUTDOWNED;
-
-       if (write(fd, buffer, BLCKSZ) != BLCKSZ)
-               elog(STOP, "BootStrapXLOG failed to write control file: %d", errno);
-
-       if (fsync(fd) != 0)
-               elog(STOP, "BootStrapXLOG failed to fsync control file: %d", errno);
-
-       close(fd);
-
-       return;
-
-}
-
-/*
- * This func must be called ONCE on system startup
- */
-void
-StartupXLOG()
-{
-       XLogCtlInsert      *Insert = &XLogCtl->Insert;
-       CheckPoint                      checkPoint;
-       XLogRecPtr                      RecPtr,
-                                               LastRec;
-       XLogRecord                 *record;
-       char                            buffer[MAXLOGRECSZ+SizeOfXLogRecord];
-       int                                     fd;
-       bool                            found;
-       bool                            recovery = false;
-       bool                            sie_saved = false;
-
-       elog(LOG, "Starting up XLOG manager...");
-
-       if (XLOGbuffers < MinXLOGbuffers)
-               XLOGbuffers = MinXLOGbuffers;
-
-       ControlFile = (ControlFileData*) 
-               ShmemInitStruct("Control File", BLCKSZ, &found);
-       Assert(!found);
-       XLogCtl = (XLogCtlData*)
-               ShmemInitStruct("XLOG Ctl", sizeof(XLogCtlData) + BLCKSZ * XLOGbuffers + 
-                                               sizeof(XLogRecPtr) * XLOGbuffers, &found);
-       Assert(!found);
-
-       XLogCtl->xlblocks = (XLogRecPtr*) (((char *)XLogCtl) + sizeof(XLogCtlData));
-       XLogCtl->pages = ((char *)XLogCtl->xlblocks + sizeof(XLogRecPtr) * XLOGbuffers);
-       XLogCtl->XLogCacheByte = BLCKSZ * XLOGbuffers;
-       XLogCtl->XLogCacheBlck = XLOGbuffers - 1;
-       memset(XLogCtl->xlblocks, 0, sizeof(XLogRecPtr) * XLOGbuffers);
-       XLogCtl->LgwrRqst = LgwrRqst;
-       XLogCtl->LgwrResult = LgwrResult;
-       XLogCtl->Insert.LgwrResult = LgwrResult;
-       XLogCtl->Insert.curridx = 0;
-       XLogCtl->Insert.currpage = (XLogPageHeader) (XLogCtl->pages);
-       XLogCtl->Write.LgwrResult = LgwrResult;
-       XLogCtl->Write.curridx = 0;
-
-       /*
-        * Open/read Control file
-        */
-tryAgain:
-       fd = open(ControlFilePath, O_RDWR);
-       if (fd < 0 && (errno == EMFILE || errno == ENFILE))
+       if (nextmode)
        {
-               fd = errno;
-               if (!ReleaseDataFile())
-                       elog(STOP, "Open(cntlfile) failed: %d (and no one data file can be closed)", 
-                                               fd);
-               goto tryAgain;
+               RecPtr = &tmpRecPtr;
+               if (nextRecord != NULL)
+               {
+                       record = nextRecord;
+                       goto got_record;
+               }
+               if (tmpRecPtr.xrecoff % BLCKSZ != 0)
+                       tmpRecPtr.xrecoff += (BLCKSZ - tmpRecPtr.xrecoff % BLCKSZ);
+               if (tmpRecPtr.xrecoff >= XLogFileSize)
+               {
+                       (tmpRecPtr.xlogid)++;
+                       tmpRecPtr.xrecoff = 0;
+               }
+               tmpRecPtr.xrecoff += SizeOfXLogPHD;
        }
-       if (fd < 0)
-               elog(STOP, "Open(cntlfile) failed: %d", errno);
-
-       if (read(fd, ControlFile, BLCKSZ) != BLCKSZ)
-               elog(STOP, "Read(cntlfile) failed: %d", errno);
-
-       close(fd);
-
-       if (ControlFile->logSeg == 0 || 
-               ControlFile->time <= 0 || 
-               ControlFile->state < DB_SHUTDOWNED || 
-               ControlFile->state > DB_IN_PRODUCTION || 
-               ControlFile->checkPoint.xlogid == 0 || 
-               ControlFile->checkPoint.xrecoff == 0)
-               elog(STOP, "Control file context is broken");
+       else if (!XRecOffIsValid(RecPtr->xrecoff))
+               elog(STOP, "ReadRecord: invalid record offset in (%u, %u)",
+                                       RecPtr->xlogid, RecPtr->xrecoff);
 
-       if (ControlFile->state == DB_SHUTDOWNED)
-               elog(LOG, "Data Base System was properly shutdowned at %s",
-                                       ctime(&(ControlFile->time)));
-       else if (ControlFile->state == DB_SHUTDOWNING)
-               elog(LOG, "Data Base System was interrupted while shutting down at %s",
-                                       ctime(&(ControlFile->time)));
-       else if (ControlFile->state == DB_IN_RECOVERY)
+       if (readFile >= 0 && (RecPtr->xlogid != readId || 
+               RecPtr->xrecoff / XLogSegSize != readSeg))
        {
-               elog(LOG, "Data Base System was interrupted being in recovery at %s\n"
-                                 "This propably means that some data blocks are corrupted\n"
-                                 "And you will have to use last backup for recovery",
-                                       ctime(&(ControlFile->time)));
+               close(readFile);
+               readFile = -1;
        }
-       else if (ControlFile->state == DB_IN_PRODUCTION)
-               elog(LOG, "Data Base System was interrupted being in production at %s",
-                                       ctime(&(ControlFile->time)));
-
-       LastRec = RecPtr = ControlFile->checkPoint;
-       if (!XRecOffIsValid(RecPtr.xrecoff))
-               elog(STOP, "Invalid checkPoint in control file");
-       elog(LOG, "CheckPoint record at (%u, %u)", RecPtr.xlogid, RecPtr.xrecoff);
-
-       record = ReadRecord(&RecPtr, buffer);
-       if (record->xl_rmid != RM_XLOG_ID)
-               elog(STOP, "Invalid RMID in checkPoint record");
-       if (record->xl_len != sizeof(checkPoint))
-               elog(STOP, "Invalid length of checkPoint record");
-       checkPoint = *((CheckPoint*)((char*)record + SizeOfXLogRecord));
-
-       elog(LOG, "Redo record at (%u, %u); Undo record at (%u, %u)",
-                               checkPoint.redo.xlogid, checkPoint.redo.xrecoff,
-                               checkPoint.undo.xlogid, checkPoint.undo.xrecoff);
-       elog(LOG, "NextTransactionId: %u; NextOid: %u)",
-                               checkPoint.nextXid, checkPoint.nextOid);
-       if (checkPoint.nextXid < FirstTransactionId || 
-               checkPoint.nextOid < BootstrapObjectIdData)
-               elog(LOG, "Invalid NextTransactionId/NextOid");
-
-       ShmemVariableCache->nextXid = checkPoint.nextXid;
-       ShmemVariableCache->nextOid = checkPoint.nextOid;
-
-       if (XLByteLT(RecPtr, checkPoint.redo))
-               elog(STOP, "Invalid redo in checkPoint record");
-       if (checkPoint.undo.xrecoff == 0)
-               checkPoint.undo = RecPtr;
-       if (XLByteLT(RecPtr, checkPoint.undo))
-               elog(STOP, "Invalid undo in checkPoint record");
-
-       if (XLByteLT(checkPoint.undo, RecPtr) || XLByteLT(checkPoint.redo, RecPtr))
+       readId = RecPtr->xlogid;
+       readSeg = RecPtr->xrecoff / XLogSegSize;
+       if (readFile < 0)
        {
-               if (ControlFile->state == DB_SHUTDOWNED)
-                       elog(STOP, "Invalid Redo/Undo record in Shutdowned state");
-               recovery = true;
+               noBlck = true;
+               readFile = XLogFileOpen(readId, readSeg, nextmode);
+               if (readFile < 0)
+                       goto next_record_is_invalid;
        }
-       else if (ControlFile->state != DB_SHUTDOWNED)
-               recovery = true;
 
-       if (recovery)
-       {
-               elog(LOG, "The DataBase system was not properly shutdowned\n"
-                                       "Automatic recovery is in progress...");
-               ControlFile->state = DB_IN_RECOVERY;
-               ControlFile->time = time(NULL);
-               UpdateControlFile();
-
-               sie_saved = StopIfError;
-               StopIfError = true;
-
-               /* Is REDO required ? */
-               if (XLByteLT(checkPoint.redo, RecPtr))
-                       record = ReadRecord(&(checkPoint.redo), buffer);
-               else    /* read past CheckPoint record */
-                       record = ReadRecord(NULL, buffer);
-
-               /* REDO */
-               if (record->xl_len != 0)
-               {
-                       elog(LOG, "Redo starts at (%u, %u)", 
-                                               ReadRecPtr.xlogid, ReadRecPtr.xrecoff);
-                       do
-                       {
-                               if (record->xl_xid >= ShmemVariableCache->nextXid)
-                                       ShmemVariableCache->nextXid = record->xl_xid + 1;
-                               RmgrTable[record->xl_rmid].rm_redo(EndRecPtr, record);
-                               record = ReadRecord(NULL, buffer);
-                       } while (record->xl_len != 0);
-                       elog(LOG, "Redo done at (%u, %u)", 
-                                               ReadRecPtr.xlogid, ReadRecPtr.xrecoff);
-                       LastRec = ReadRecPtr;
-               }
-               else
-                       elog(LOG, "Redo is not required");
-               /* UNDO */
-               RecPtr = ReadRecPtr;
-               if (XLByteLT(checkPoint.undo, RecPtr))
-               {
-                       elog(LOG, "Undo starts at (%u, %u)", 
-                                               RecPtr.xlogid, RecPtr.xrecoff);
-                       do
-                       {
-                               record = ReadRecord(&RecPtr, buffer);
-                               if (TransactionIdIsValid(record->xl_xid) && 
-                                       !TransactionIdDidCommit(record->xl_xid))
-                                       RmgrTable[record->xl_rmid].rm_undo(record);
-                               RecPtr = record->xl_prev;
-                       } while (XLByteLE(checkPoint.undo, RecPtr));
-                       elog(LOG, "Undo done at (%u, %u)", 
-                                               ReadRecPtr.xlogid, ReadRecPtr.xrecoff);
-               }
-               else
-                       elog(LOG, "Undo is not required");
-       }
-
-       /* Init xlog buffer cache */
-       record = ReadRecord(&LastRec, buffer);
-       logId = EndRecPtr.xlogid;
-       logSeg = (EndRecPtr.xrecoff - 1) / XLogSegSize;
-       logOff = 0;
-       logFile = XLogFileOpen(logId, logSeg, false);
-       XLogCtl->xlblocks[0].xlogid = logId;
-       XLogCtl->xlblocks[0].xrecoff = 
-                       ((EndRecPtr.xrecoff - 1) / BLCKSZ + 1) * BLCKSZ;
-       Insert->currpos = ((char*) Insert->currpage) + 
-               (EndRecPtr.xrecoff + BLCKSZ - XLogCtl->xlblocks[0].xrecoff);
-
-       if (recovery)
-       {
-               int             i;
-
-               /* 
-                * Let resource managers know that recovery is done
-                */
-               for (i = 0; i <= RM_MAX_ID; i++)
-                       RmgrTable[record->xl_rmid].rm_redo(ReadRecPtr, NULL);
-               CreateCheckPoint(true);
-               StopIfError = sie_saved;
-       }
-
-       ControlFile->state = DB_IN_PRODUCTION;
-       ControlFile->time = time(NULL);
-       UpdateControlFile();
-
-       return;
-}
-
-static XLogRecord*
-ReadRecord(XLogRecPtr *RecPtr, char *buffer)
-{
-       XLogRecord         *record;
-       XLogRecPtr              tmpRecPtr = EndRecPtr;
-       bool                    nextmode = (RecPtr == NULL);
-       int                             emode = (nextmode) ? LOG : STOP;
-
-       if (nextmode)
-       {
-               RecPtr = &tmpRecPtr;
-               if (nextRecord != NULL)
-               {
-                       record = nextRecord;
-                       goto got_record;
-               }
-               if (tmpRecPtr.xrecoff % BLCKSZ != 0)
-                       tmpRecPtr.xrecoff += (BLCKSZ - tmpRecPtr.xrecoff % BLCKSZ);
-               if (tmpRecPtr.xrecoff >= XLogFileSize)
-               {
-                       (tmpRecPtr.xlogid)++;
-                       tmpRecPtr.xrecoff = 0;
-               }
-               tmpRecPtr.xrecoff += SizeOfXLogPHD;
-       }
-       else if (!XRecOffIsValid(RecPtr->xrecoff))
-               elog(STOP, "ReadRecord: invalid record offset in (%u, %u)",
-                                       RecPtr->xlogid, RecPtr->xrecoff);
-
-       if (readFile >= 0 && (RecPtr->xlogid != readId || 
-               RecPtr->xrecoff / XLogSegSize != readSeg))
-       {
-               close(readFile);
-               readFile = -1;
-       }
-       readId = RecPtr->xlogid;
-       readSeg = RecPtr->xrecoff / XLogSegSize;
-       if (readFile < 0)
-       {
-               readOff = (off_t) -1;
-               readFile = XLogFileOpen(readId, readSeg, nextmode);
-               if (readFile < 0)
-                       goto next_record_is_invalid;
-       }
-
-       if (readOff < 0 || readOff != (RecPtr->xrecoff % XLogSegSize) / BLCKSZ)
+       if (noBlck || readOff != (RecPtr->xrecoff % XLogSegSize) / BLCKSZ)
        {
                readOff = (RecPtr->xrecoff % XLogSegSize) / BLCKSZ;
-               if (lseek(readFile, readOff * BLCKSZ, SEEK_SET) < 0)
+               if (lseek(readFile, (off_t)(readOff * BLCKSZ), SEEK_SET) < 0)
                        elog(STOP, "ReadRecord: lseek(logfile %u seg %u off %u) failed: %d", 
                                                readId, readSeg, readOff, errno);
                if (read(readFile, readBuf, BLCKSZ) != BLCKSZ)
@@ -1186,7 +880,7 @@ got_record:;
                                        readId++;
                                }
                                close(readFile);
-                               readOff = (off_t) 0;
+                               readOff = 0;
                                readFile = XLogFileOpen(readId, readSeg, nextmode);
                                if (readFile < 0)
                                        goto next_record_is_invalid;
@@ -1280,7 +974,7 @@ next_record_is_invalid:;
                elog(LOG, "Formating logfile %u seg %u block %u at offset %u",
                                        readId, readSeg, readOff, EndRecPtr.xrecoff % BLCKSZ);
                readFile = XLogFileOpen(readId, readSeg, false);
-               if (lseek(readFile, readOff * BLCKSZ, SEEK_SET) < 0)
+               if (lseek(readFile, (off_t)(readOff * BLCKSZ), SEEK_SET) < 0)
                        elog(STOP, "ReadRecord: lseek(logfile %u seg %u off %u) failed: %d", 
                                                readId, readSeg, readOff, errno);
                if (read(readFile, readBuf, BLCKSZ) != BLCKSZ)
@@ -1288,7 +982,7 @@ next_record_is_invalid:;
                                                readId, readSeg, readOff, errno);
                memset(readBuf + EndRecPtr.xrecoff % BLCKSZ, 0, 
                                BLCKSZ - EndRecPtr.xrecoff % BLCKSZ);
-               if (lseek(readFile, readOff * BLCKSZ, SEEK_SET) < 0)
+               if (lseek(readFile, (off_t)(readOff * BLCKSZ), SEEK_SET) < 0)
                        elog(STOP, "ReadRecord: lseek(logfile %u seg %u off %u) failed: %d", 
                                                readId, readSeg, readOff, errno);
                if (write(readFile, readBuf, BLCKSZ) != BLCKSZ)
@@ -1303,15 +997,17 @@ next_record_is_invalid:;
                readId = tmpRecPtr.xlogid;
                readSeg = tmpRecPtr.xrecoff / XLogSegSize;
                readOff = (tmpRecPtr.xrecoff % XLogSegSize) / BLCKSZ;
+               Assert(readOff > 0);
        }
        if (readOff > 0)
        {
-               elog(LOG, "Formating logfile %u seg %u block %u at offset 0",
-                                       readId, readSeg, readOff);
+               if (!XLByteEQ(tmpRecPtr, EndRecPtr))
+                       elog(LOG, "Formating logfile %u seg %u block %u at offset 0",
+                                               readId, readSeg, readOff);
                readOff *= BLCKSZ;
                memset(readBuf, 0, BLCKSZ);
                readFile = XLogFileOpen(readId, readSeg, false);
-               if (lseek(readFile, readOff, SEEK_SET) < 0)
+               if (lseek(readFile, (off_t)readOff, SEEK_SET) < 0)
                        elog(STOP, "ReadRecord: lseek(logfile %u seg %u off %u) failed: %d", 
                                                readId, readSeg, readOff, errno);
                while (readOff < XLogSegSize)
@@ -1357,6 +1053,381 @@ next_record_is_invalid:;
        return(record);
 }
 
+void
+UpdateControlFile()
+{
+       int             fd;
+
+tryAgain:
+       fd = open(ControlFilePath, O_RDWR);
+       if (fd < 0 && (errno == EMFILE || errno == ENFILE))
+       {
+               fd = errno;
+               if (!ReleaseDataFile())
+                       elog(STOP, "Open(cntlfile) failed: %d (and no one data file can be closed)", 
+                                               fd);
+               goto tryAgain;
+       }
+       if (fd < 0)
+               elog(STOP, "Open(cntlfile) failed: %d", errno);
+
+       if (write(fd, ControlFile, BLCKSZ) != BLCKSZ)
+               elog(STOP, "Write(cntlfile) failed: %d", errno);
+
+       if (fsync(fd) != 0)
+               elog(STOP, "Fsync(cntlfile) failed: %d", errno);
+
+       close(fd);
+
+       return;
+}
+
+int
+XLOGShmemSize()
+{
+       if (XLOGbuffers < MinXLOGbuffers)
+               XLOGbuffers = MinXLOGbuffers;
+
+       return(sizeof(XLogCtlData) + BLCKSZ * XLOGbuffers + 
+                       sizeof(XLogRecPtr) * XLOGbuffers + BLCKSZ);
+}
+
+void
+XLOGShmemInit(void)
+{
+       bool                            found;
+
+       if (XLOGbuffers < MinXLOGbuffers)
+               XLOGbuffers = MinXLOGbuffers;
+
+       ControlFile = (ControlFileData*) 
+               ShmemInitStruct("Control File", BLCKSZ, &found);
+       Assert(!found);
+       XLogCtl = (XLogCtlData*)
+               ShmemInitStruct("XLOG Ctl", sizeof(XLogCtlData) + BLCKSZ * XLOGbuffers + 
+                                               sizeof(XLogRecPtr) * XLOGbuffers, &found);
+       Assert(!found);
+}
+
+/*
+ * This func must be called ONCE on system install
+ */
+void
+BootStrapXLOG()
+{
+       int                             fd;
+       char                    buffer[BLCKSZ];
+       XLogPageHeader  page = (XLogPageHeader)buffer;
+       CheckPoint              checkPoint;
+       XLogRecord         *record;
+
+       fd = open(ControlFilePath, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
+       if (fd < 0)
+               elog(STOP, "BootStrapXLOG failed to create control file (%s): %d", 
+                                       ControlFilePath, errno);
+
+       logFile = XLogFileInit(0, 0);
+
+       checkPoint.redo.xlogid = 0;
+       checkPoint.redo.xrecoff = SizeOfXLogPHD;
+       checkPoint.undo = checkPoint.redo;
+       checkPoint.nextXid = FirstTransactionId;
+       checkPoint.nextOid =  BootstrapObjectIdData;
+
+       memset(buffer, 0, BLCKSZ);
+       page->xlp_magic = XLOG_PAGE_MAGIC;
+       page->xlp_info = 0;
+       record = (XLogRecord*) ((char*)page + SizeOfXLogPHD);
+       record->xl_prev.xlogid = 0; record->xl_prev.xrecoff = 0;
+       record->xl_xact_prev = record->xl_prev;
+       record->xl_xid = InvalidTransactionId;
+       record->xl_len = sizeof(checkPoint);
+       record->xl_info = 0;
+       record->xl_rmid = RM_XLOG_ID;
+       memcpy((char*)record + SizeOfXLogRecord, &checkPoint, sizeof(checkPoint));
+
+       if (write(logFile, buffer, BLCKSZ) != BLCKSZ)
+               elog(STOP, "BootStrapXLOG failed to write logfile: %d", errno);
+
+       if (fsync(logFile) != 0)
+               elog(STOP, "BootStrapXLOG failed to fsync logfile: %d", errno);
+
+       close(logFile);
+       logFile = -1;
+
+       memset(buffer, 0, BLCKSZ);
+       ControlFile = (ControlFileData*) buffer;
+       ControlFile->logId = 0;
+       ControlFile->logSeg = 1;
+       ControlFile->checkPoint = checkPoint.redo;
+       ControlFile->time = time(NULL);
+       ControlFile->state = DB_SHUTDOWNED;
+
+       if (write(fd, buffer, BLCKSZ) != BLCKSZ)
+               elog(STOP, "BootStrapXLOG failed to write control file: %d", errno);
+
+       if (fsync(fd) != 0)
+               elog(STOP, "BootStrapXLOG failed to fsync control file: %d", errno);
+
+       close(fd);
+
+       return;
+
+}
+
+static char*
+str_time(time_t tnow)
+{
+       char   *result = ctime(&tnow);
+       char   *p = strchr(result, '\n');
+
+       if (p != NULL)
+               *p = 0;
+
+       return(result);
+}
+
+/*
+ * This func must be called ONCE on system startup
+ */
+void
+StartupXLOG()
+{
+       XLogCtlInsert      *Insert;
+       CheckPoint                      checkPoint;
+       XLogRecPtr                      RecPtr,
+                                               LastRec;
+       XLogRecord                 *record;
+       char                            buffer[MAXLOGRECSZ+SizeOfXLogRecord];
+       int                                     fd;
+       int                                     recovery = 0;
+       bool                            sie_saved = false;
+
+       elog(LOG, "Data Base System is starting up at %s", str_time(time(NULL)));
+
+       XLogCtl->xlblocks = (XLogRecPtr*) (((char *)XLogCtl) + sizeof(XLogCtlData));
+       XLogCtl->pages = ((char *)XLogCtl->xlblocks + sizeof(XLogRecPtr) * XLOGbuffers);
+       XLogCtl->XLogCacheByte = BLCKSZ * XLOGbuffers;
+       XLogCtl->XLogCacheBlck = XLOGbuffers - 1;
+       memset(XLogCtl->xlblocks, 0, sizeof(XLogRecPtr) * XLOGbuffers);
+       XLogCtl->LgwrRqst = LgwrRqst;
+       XLogCtl->LgwrResult = LgwrResult;
+       XLogCtl->Insert.LgwrResult = LgwrResult;
+       XLogCtl->Insert.curridx = 0;
+       XLogCtl->Insert.currpage = (XLogPageHeader) (XLogCtl->pages);
+       XLogCtl->Write.LgwrResult = LgwrResult;
+       XLogCtl->Write.curridx = 0;
+       S_INIT_LOCK(&(XLogCtl->insert_lck));
+       S_INIT_LOCK(&(XLogCtl->info_lck));
+       S_INIT_LOCK(&(XLogCtl->lgwr_lck));
+
+       /*
+        * Open/read Control file
+        */
+tryAgain:
+       fd = open(ControlFilePath, O_RDWR);
+       if (fd < 0 && (errno == EMFILE || errno == ENFILE))
+       {
+               fd = errno;
+               if (!ReleaseDataFile())
+                       elog(STOP, "Open(cntlfile) failed: %d (and no one data file can be closed)", 
+                                               fd);
+               goto tryAgain;
+       }
+       if (fd < 0)
+               elog(STOP, "Open(cntlfile) failed: %d", errno);
+
+       if (read(fd, ControlFile, BLCKSZ) != BLCKSZ)
+               elog(STOP, "Read(cntlfile) failed: %d", errno);
+
+       close(fd);
+
+       if (ControlFile->logSeg == 0 || 
+               ControlFile->time <= 0 || 
+               ControlFile->state < DB_SHUTDOWNED || 
+               ControlFile->state > DB_IN_PRODUCTION || 
+               !XRecOffIsValid(ControlFile->checkPoint.xrecoff))
+               elog(STOP, "Control file context is broken");
+
+       if (ControlFile->state == DB_SHUTDOWNED)
+               elog(LOG, "Data Base System was shutdowned at %s",
+                                       str_time(ControlFile->time));
+       else if (ControlFile->state == DB_SHUTDOWNING)
+               elog(LOG, "Data Base System was interrupted when shutting down at %s",
+                                       str_time(ControlFile->time));
+       else if (ControlFile->state == DB_IN_RECOVERY)
+       {
+               elog(LOG, "Data Base System was interrupted being in recovery at %s\n"
+                                 "\tThis propably means that some data blocks are corrupted\n"
+                                 "\tAnd you will have to use last backup for recovery",
+                                       str_time(ControlFile->time));
+       }
+       else if (ControlFile->state == DB_IN_PRODUCTION)
+               elog(LOG, "Data Base System was interrupted being in production at %s",
+                                       str_time(ControlFile->time));
+
+       LastRec = RecPtr = ControlFile->checkPoint;
+       if (!XRecOffIsValid(RecPtr.xrecoff))
+               elog(STOP, "Invalid checkPoint in control file");
+       elog(LOG, "CheckPoint record at (%u, %u)", RecPtr.xlogid, RecPtr.xrecoff);
+
+       record = ReadRecord(&RecPtr, buffer);
+       if (record->xl_rmid != RM_XLOG_ID)
+               elog(STOP, "Invalid RMID in checkPoint record");
+       if (record->xl_len != sizeof(checkPoint))
+               elog(STOP, "Invalid length of checkPoint record");
+       checkPoint = *((CheckPoint*)((char*)record + SizeOfXLogRecord));
+
+       elog(LOG, "Redo record at (%u, %u); Undo record at (%u, %u)",
+                               checkPoint.redo.xlogid, checkPoint.redo.xrecoff,
+                               checkPoint.undo.xlogid, checkPoint.undo.xrecoff);
+       elog(LOG, "NextTransactionId: %u; NextOid: %u",
+                               checkPoint.nextXid, checkPoint.nextOid);
+       if (checkPoint.nextXid < FirstTransactionId || 
+               checkPoint.nextOid < BootstrapObjectIdData)
+#ifdef XLOG
+               elog(STOP, "Invalid NextTransactionId/NextOid");
+#else
+               elog(LOG, "Invalid NextTransactionId/NextOid");
+#endif
+
+#ifdef XLOG
+       ShmemVariableCache->nextXid = checkPoint.nextXid;
+       ShmemVariableCache->nextOid = checkPoint.nextOid;
+#endif
+
+       if (XLByteLT(RecPtr, checkPoint.redo))
+               elog(STOP, "Invalid redo in checkPoint record");
+       if (checkPoint.undo.xrecoff == 0)
+               checkPoint.undo = RecPtr;
+       if (XLByteLT(RecPtr, checkPoint.undo))
+               elog(STOP, "Invalid undo in checkPoint record");
+
+       if (XLByteLT(checkPoint.undo, RecPtr) || XLByteLT(checkPoint.redo, RecPtr))
+       {
+               if (ControlFile->state == DB_SHUTDOWNED)
+                       elog(STOP, "Invalid Redo/Undo record in Shutdowned state");
+               recovery = 2;
+       }
+       else if (ControlFile->state != DB_SHUTDOWNED)
+               recovery = 2;
+
+       if (recovery > 0)
+       {
+               elog(LOG, "The DataBase system was not properly shutdowned\n"
+                                       "\tAutomatic recovery is in progress...");
+               ControlFile->state = DB_IN_RECOVERY;
+               ControlFile->time = time(NULL);
+               UpdateControlFile();
+
+               sie_saved = StopIfError;
+               StopIfError = true;
+
+               /* Is REDO required ? */
+               if (XLByteLT(checkPoint.redo, RecPtr))
+                       record = ReadRecord(&(checkPoint.redo), buffer);
+               else    /* read past CheckPoint record */
+                       record = ReadRecord(NULL, buffer);
+
+               /* REDO */
+               if (record->xl_len != 0)
+               {
+                       elog(LOG, "Redo starts at (%u, %u)", 
+                                               ReadRecPtr.xlogid, ReadRecPtr.xrecoff);
+                       do
+                       {
+#ifdef XLOG
+                               if (record->xl_xid >= ShmemVariableCache->nextXid)
+                                       ShmemVariableCache->nextXid = record->xl_xid + 1;
+#endif
+                               RmgrTable[record->xl_rmid].rm_redo(EndRecPtr, record);
+                               record = ReadRecord(NULL, buffer);
+                       } while (record->xl_len != 0);
+                       elog(LOG, "Redo done at (%u, %u)", 
+                                               ReadRecPtr.xlogid, ReadRecPtr.xrecoff);
+                       LastRec = ReadRecPtr;
+               }
+               else
+               {
+                       elog(LOG, "Redo is not required");
+                       recovery--;
+               }
+
+               /* UNDO */
+               RecPtr = ReadRecPtr;
+               if (XLByteLT(checkPoint.undo, RecPtr))
+               {
+                       elog(LOG, "Undo starts at (%u, %u)", 
+                                               RecPtr.xlogid, RecPtr.xrecoff);
+                       do
+                       {
+                               record = ReadRecord(&RecPtr, buffer);
+                               if (TransactionIdIsValid(record->xl_xid) && 
+                                       !TransactionIdDidCommit(record->xl_xid))
+                                       RmgrTable[record->xl_rmid].rm_undo(record);
+                               RecPtr = record->xl_prev;
+                       } while (XLByteLE(checkPoint.undo, RecPtr));
+                       elog(LOG, "Undo done at (%u, %u)", 
+                                               ReadRecPtr.xlogid, ReadRecPtr.xrecoff);
+               }
+               else
+               {
+                       elog(LOG, "Undo is not required");
+                       recovery--;
+               }
+       }
+
+       /* Init xlog buffer cache */
+       record = ReadRecord(&LastRec, buffer);
+       logId = EndRecPtr.xlogid;
+       logSeg = (EndRecPtr.xrecoff - 1) / XLogSegSize;
+       logOff = 0;
+       logFile = XLogFileOpen(logId, logSeg, false);
+       XLogCtl->xlblocks[0].xlogid = logId;
+       XLogCtl->xlblocks[0].xrecoff = 
+                       ((EndRecPtr.xrecoff - 1) / BLCKSZ + 1) * BLCKSZ;
+       Insert = &XLogCtl->Insert;
+       memcpy((char*)(Insert->currpage), readBuf, BLCKSZ);
+       Insert->currpos = ((char*) Insert->currpage) + 
+               (EndRecPtr.xrecoff + BLCKSZ - XLogCtl->xlblocks[0].xrecoff);
+       Insert->PrevRecord = ControlFile->checkPoint;
+
+       if (recovery > 0)
+       {
+               int             i;
+
+               /* 
+                * Let resource managers know that recovery is done
+                */
+               for (i = 0; i <= RM_MAX_ID; i++)
+                       RmgrTable[record->xl_rmid].rm_redo(ReadRecPtr, NULL);
+               CreateCheckPoint(true);
+               StopIfError = sie_saved;
+       }
+
+       ControlFile->state = DB_IN_PRODUCTION;
+       ControlFile->time = time(NULL);
+       UpdateControlFile();
+
+       elog(LOG, "Data Base System is in production state at %s", str_time(time(NULL)));
+
+       return;
+}
+
+/*
+ * This func must be called ONCE on system shutdown
+ */
+void
+ShutdownXLOG()
+{
+
+       elog(LOG, "Data Base System is shutting down at %s", str_time(time(NULL)));
+
+       CreateCheckPoint(true);
+
+       elog(LOG, "Data Base System is shutdowned at %s", str_time(time(NULL)));
+}
+
 void
 CreateCheckPoint(bool shutdown)
 {
@@ -1375,7 +1446,7 @@ CreateCheckPoint(bool shutdown)
        }
 
        /* Get REDO record ptr */
-       while (!TAS(&(XLogCtl->insert_lck)))
+       while (TAS(&(XLogCtl->insert_lck)))
        {
                struct timeval delay = {0, 5000};
 
@@ -1410,6 +1481,7 @@ CreateCheckPoint(bool shutdown)
        FlushBufferPool();
 
        /* Get UNDO record ptr */
+       checkPoint.undo.xrecoff = 0;
 
        if (shutdown && checkPoint.undo.xrecoff != 0)
                elog(STOP, "Active transaction while data base is shutting down");
index c20a63fc6dcb1e5f5c46f35c54553dc0c97f2cb8..8871e14835a27a7413f8e4c8b5150667605416b5 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.68 1999/09/27 20:26:58 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.69 1999/10/06 21:58:02 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
 #define ALLOC(t, c)            (t *)calloc((unsigned)(c), sizeof(t))
 #define FIRST_TYPE_OID 16              /* OID of the first type */
 
+extern void            BaseInit(void);
+extern void            StartupXLOG(void);
+extern void            ShutdownXLOG(void);
+extern void            BootStrapXLOG(void);
+
+extern char            XLogDir[];
+extern char            ControlFilePath[];
+
 extern int     Int_yyparse(void);
 static hashnode *AddStr(char *str, int strlength, int mderef);
 static Form_pg_attribute AllocateAttribute(void);
@@ -218,22 +226,13 @@ BootstrapMain(int argc, char *argv[])
  */
 {
        int                     i;
-       int                     portFd = -1;
        char       *dbName;
        int                     flag;
-       int                     override = 1;   /* use BootstrapProcessing or
-                                                                * InitProcessing mode */
+       bool            xloginit = false;
 
        extern int      optind;
        extern char *optarg;
 
-       /* ----------------
-        *      initialize signal handlers
-        * ----------------
-        */
-       pqsignal(SIGINT, (sig_func) die);
-       pqsignal(SIGHUP, (sig_func) die);
-       pqsignal(SIGTERM, (sig_func) die);
 
        /* --------------------
         *      initialize globals
@@ -252,8 +251,9 @@ BootstrapMain(int argc, char *argv[])
        Noversion = false;
        dbName = NULL;
        DataDir = getenv("PGDATA"); /* Null if no PGDATA variable */
+       IsUnderPostmaster = false;
 
-       while ((flag = getopt(argc, argv, "D:dCOQP:F")) != EOF)
+       while ((flag = getopt(argc, argv, "D:dCQxpB:F")) != EOF)
        {
                switch (flag)
                {
@@ -270,14 +270,17 @@ BootstrapMain(int argc, char *argv[])
                        case 'F':
                                disableFsync = true;
                                break;
-                       case 'O':
-                               override = true;
-                               break;
                        case 'Q':
                                Quiet = true;
                                break;
-                       case 'P':                       /* specify port */
-                               portFd = atoi(optarg);
+                       case 'x':
+                               xloginit = true;
+                               break;
+                       case 'p':
+                               IsUnderPostmaster = true;
+                               break;
+                       case 'B':
+                               NBuffers = atoi(optarg);
                                break;
                        default:
                                usage();
@@ -290,6 +293,8 @@ BootstrapMain(int argc, char *argv[])
        else if (argc - optind == 1)
                dbName = argv[optind];
 
+       SetProcessingMode(BootstrapProcessing);
+
        if (!DataDir)
        {
                fprintf(stderr, "%s does not know where to find the database system "
@@ -311,24 +316,50 @@ BootstrapMain(int argc, char *argv[])
                }
        }
 
-       /* ----------------
-        *      initialize input fd
-        * ----------------
+       BaseInit();
+
+       if (!IsUnderPostmaster)
+       {
+               pqsignal(SIGINT, (sig_func) die);
+               pqsignal(SIGHUP, (sig_func) die);
+               pqsignal(SIGTERM, (sig_func) die);
+       }
+
+       /*
+        * Bootstrap under Postmaster means two things:
+        * (xloginit) ? StartupXLOG : ShutdownXLOG
+        *
+        * If !under Postmaster and xloginit then BootStrapXLOG.
         */
-       if (IsUnderPostmaster && portFd < 0)
+       if (IsUnderPostmaster || xloginit)
        {
-               fputs("backend: failed, no -P option with -postmaster opt.\n", stderr);
-               proc_exit(1);
+               sprintf(XLogDir, "%s%cpg_xlog", DataDir, SEP_CHAR);
+               sprintf(ControlFilePath, "%s%cpg_control", DataDir, SEP_CHAR);
        }
 
-       /* ----------------
-        *      backend initialization
-        * ----------------
+       if (IsUnderPostmaster && xloginit)
+       {
+               StartupXLOG();
+               proc_exit(0);
+       }
+
+       if (!IsUnderPostmaster && xloginit)
+       {
+               BootStrapXLOG();
+       }
+
+       /*
+        * backend initialization
         */
-       SetProcessingMode((override) ? BootstrapProcessing : InitProcessing);
        InitPostgres(dbName);
        LockDisable(true);
 
+       if (IsUnderPostmaster && !xloginit)
+       {
+               ShutdownXLOG();
+               proc_exit(0);
+       }
+
        for (i = 0; i < MAXATTR; i++)
        {
                attrtypes[i] = (Form_pg_attribute) NULL;
index 78d8bc5e30bcaf06d65bf0ad2dff9548281021ba..bb6d5b638eb1c8bef11913da27bf6b6edd137579 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.120 1999/09/30 02:45:17 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.121 1999/10/06 21:58:03 vadim Exp $
  *
  * NOTES
  *
@@ -87,6 +87,7 @@
 #include "storage/fd.h"
 #include "storage/ipc.h"
 #include "storage/proc.h"
+#include "access/xlog.h"
 #include "tcop/tcopprot.h"
 #include "utils/trace.h"
 #include "version.h"
 #define INVALID_SOCK   (-1)
 #define ARGV_SIZE      64
 
- /*
-  * Max time in seconds for socket to linger (close() to block) waiting
-  * for frontend to retrieve its message from us.
-  */
+#ifdef HAVE_SIGPROCMASK
+sigset_t       UnBlockSig,
+                       BlockSig;
+#else
+int                    UnBlockSig,
+                       BlockSig;
+#endif
 
 /*
  * Info for garbage collection.  Whenever a process dies, the Postmaster
@@ -124,7 +128,6 @@ static Dllist *BackendList;
 static Dllist *PortList;
 
 static unsigned short PostPortName = 0;
-static short ActiveBackends = FALSE;
 
  /*
   * This is a boolean indicating that there is at least one backend that
@@ -209,18 +212,16 @@ static bool SecureNetServer = false; /* if not zero, postmaster listens for only
                                       * non-local connections */
 #endif
 
-/*
- * GH: For !HAVE_SIGPROCMASK (NEXTSTEP), TRH implemented an
- * alternative interface.
- */
-#ifdef HAVE_SIGPROCMASK
-static sigset_t oldsigmask,
-                       newsigmask;
+static pid_t   StartupPID = 0,
+                               ShutdownPID = 0;
 
-#else
-static int     orgsigmask = sigblock(0);
+#define                        NoShutdown              0
+#define                        SmartShutdown   1
+#define                        FastShutdown    2
 
-#endif
+static int             Shutdown = NoShutdown;
+
+static bool            FatalError = false;
 
 /*
  * State for assigning random salts and cancel keys.
@@ -234,30 +235,35 @@ extern char *optarg;
 extern int     optind,
                        opterr;
 
-
 /*
  * postmaster.c - function prototypes
  */
-static void pmdaemonize(void);
-static Port *ConnCreate(int serverFd);
-static void ConnFree(Port *port);
-static void reset_shared(unsigned short port);
-static void pmdie(SIGNAL_ARGS);
-static void reaper(SIGNAL_ARGS);
-static void dumpstatus(SIGNAL_ARGS);
-static void CleanupProc(int pid, int exitstatus);
-static int     DoBackend(Port *port);
-static void ExitPostmaster(int status);
-static void usage(const char *);
-static int     ServerLoop(void);
-static int     BackendStartup(Port *port);
-static int     readStartupPacket(void *arg, PacketLen len, void *pkt);
-static int     processCancelRequest(Port *port, PacketLen len, void *pkt);
-static int     initMasks(fd_set *rmask, fd_set *wmask);
-static long PostmasterRandom(void);
-static void RandomSalt(char *salt);
-static void SignalChildren(SIGNAL_ARGS);
-static int     CountChildren(void);
+static void            pmdaemonize(void);
+static Port       *ConnCreate(int serverFd);
+static void            ConnFree(Port *port);
+static void    reset_shared(unsigned short port);
+static void    pmdie(SIGNAL_ARGS);
+static void    reaper(SIGNAL_ARGS);
+static void    dumpstatus(SIGNAL_ARGS);
+static void    CleanupProc(int pid, int exitstatus);
+static int             DoBackend(Port *port);
+static void    ExitPostmaster(int status);
+static void    usage(const char *);
+static int             ServerLoop(void);
+static int             BackendStartup(Port *port);
+static int             readStartupPacket(void *arg, PacketLen len, void *pkt);
+static int             processCancelRequest(Port *port, PacketLen len, void *pkt);
+static int             initMasks(fd_set *rmask, fd_set *wmask);
+static long    PostmasterRandom(void);
+static void    RandomSalt(char *salt);
+static void    SignalChildren(SIGNAL_ARGS);
+static int             CountChildren(void);
+
+extern int             BootstrapMain(int argc, char *argv[]);
+static pid_t   SSDataBase(bool startup);
+#define        StartupDataBase()       SSDataBase(true)
+#define        ShutdownDataBase()      SSDataBase(false)
+
 #ifdef USE_SSL
 static void InitSSL(void);
 #endif
@@ -613,18 +619,23 @@ PostmasterMain(int argc, char *argv[])
        /*
         * Set up signal handlers for the postmaster process.
         */
-
-       pqsignal(SIGHUP, pmdie);        /* send SIGHUP, don't die */
-       pqsignal(SIGINT, pmdie);        /* die */
-       pqsignal(SIGQUIT, pmdie);       /* send SIGTERM and die */
-       pqsignal(SIGTERM, pmdie);       /* send SIGTERM,SIGKILL and die */
-       pqsignal(SIGPIPE, SIG_IGN); /* ignored */
-       pqsignal(SIGUSR1, pmdie);       /* send SIGUSR1 and die */
-       pqsignal(SIGUSR2, pmdie);       /* send SIGUSR2, don't die */
-       pqsignal(SIGCHLD, reaper);      /* handle child termination */
-       pqsignal(SIGTTIN, SIG_IGN); /* ignored */
-       pqsignal(SIGTTOU, SIG_IGN); /* ignored */
-       pqsignal(SIGWINCH, dumpstatus);         /* dump port status */
+       PG_INITMASK();
+       PG_SETMASK(&BlockSig);
+
+       pqsignal(SIGHUP, pmdie);                /* send SIGHUP, don't die */
+       pqsignal(SIGINT, pmdie);                /* send SIGTERM and ShutdownDataBase */
+       pqsignal(SIGQUIT, pmdie);               /* send SIGUSR1 and die */
+       pqsignal(SIGTERM, pmdie);               /* wait for children and ShutdownDataBase */
+       pqsignal(SIGALRM, SIG_IGN);             /* ignored */
+       pqsignal(SIGPIPE, SIG_IGN);     /* ignored */
+       pqsignal(SIGUSR1, SIG_IGN);             /* ignored */
+       pqsignal(SIGUSR2, pmdie);               /* send SIGUSR2, don't die */
+       pqsignal(SIGCHLD, reaper);              /* handle child termination */
+       pqsignal(SIGTTIN, SIG_IGN);     /* ignored */
+       pqsignal(SIGTTOU, SIG_IGN);     /* ignored */
+       pqsignal(SIGWINCH, dumpstatus); /* dump port status */
+
+       StartupPID = StartupDataBase();
 
        status = ServerLoop();
 
@@ -702,12 +713,6 @@ ServerLoop(void)
 
        nSockets = initMasks(&readmask, &writemask);
 
-#ifdef HAVE_SIGPROCMASK
-       sigprocmask(0, NULL, &oldsigmask);
-       sigemptyset(&newsigmask);
-       sigaddset(&newsigmask, SIGCHLD);
-#endif
-
        for (;;)
        {
                Port       *port;
@@ -717,25 +722,25 @@ ServerLoop(void)
                int no_select = 0;
 #endif
 
-#ifdef HAVE_SIGPROCMASK
-               sigprocmask(SIG_SETMASK, &oldsigmask, 0);
-#else
-               sigsetmask(orgsigmask);
-#endif
-
                memmove((char *) &rmask, (char *) &readmask, sizeof(fd_set));
                memmove((char *) &wmask, (char *) &writemask, sizeof(fd_set));
 
 #ifdef USE_SSL
                for (curr = DLGetHead(PortList); curr; curr = DLGetSucc(curr))
-                 if (((Port *)DLE_VAL(curr))->ssl &&
-                     SSL_pending(((Port *)DLE_VAL(curr))->ssl) > 0) {
-                   no_select = 1;
-                   break;
-                 }
+               {
+                       if (((Port *)DLE_VAL(curr))->ssl &&
+                               SSL_pending(((Port *)DLE_VAL(curr))->ssl) > 0)
+                       {
+                           no_select = 1;
+                           break;
+                       }
+               }
+               PG_SETMASK(&UnBlockSig);
                if (no_select) 
                  FD_ZERO(&rmask); /* So we don't accept() anything below */
                else
+#else
+               PG_SETMASK(&UnBlockSig);
 #endif
                if (select(nSockets, &rmask, &wmask, (fd_set *) NULL,
                                   (struct timeval *) NULL) < 0)
@@ -765,16 +770,9 @@ ServerLoop(void)
                }
 
                /*
-                * [TRH] To avoid race conditions, block SIGCHLD signals while we
-                * are handling the request. (both reaper() and ConnCreate()
-                * manipulate the BackEnd list, and reaper() calls free() which is
-                * usually non-reentrant.)
+                * Block all signals
                 */
-#ifdef HAVE_SIGPROCMASK
-               sigprocmask(SIG_BLOCK, &newsigmask, &oldsigmask);
-#else
-               sigblock(sigmask(SIGCHLD));             /* XXX[TRH] portability */
-#endif
+               PG_SETMASK(&BlockSig);
 
                /* new connection pending on our well-known port's socket */
 
@@ -817,8 +815,8 @@ ServerLoop(void)
                        }
                        else
 #endif
-                         if (FD_ISSET(port->sock, &rmask))
-                       readyread = 1;
+                       if (FD_ISSET(port->sock, &rmask))
+                               readyread = 1;
 
                        if (readyread)
                        {
@@ -852,13 +850,25 @@ ServerLoop(void)
 
                        if (status == STATUS_OK && port->pktInfo.state == Idle)
                        {
-                               /* Can't start backend if max backend count is exceeded. */
-                               if (CountChildren() >= MaxBackends)
+                               /* 
+                                * Can't start backend if max backend count is exceeded.
+                                * 
+                                * The same when shutdowning data base.
+                                */
+                               if (Shutdown > NoShutdown)
+                                       PacketSendError(&port->pktInfo,
+                                                                       "The Data Base System is shutting down");
+                               else if (StartupPID)
+                                       PacketSendError(&port->pktInfo,
+                                                                       "The Data Base System is starting up");
+                               else if (FatalError)
+                                       PacketSendError(&port->pktInfo,
+                                                                       "The Data Base System is in recovery mode");
+                               else if (CountChildren() >= MaxBackends)
                                        PacketSendError(&port->pktInfo,
                                                                        "Sorry, too many clients already");
                                else
                                {
-
                                        /*
                                         * If the backend start fails then keep the connection
                                         * open to report it.  Otherwise, pretend there is an
@@ -1113,6 +1123,7 @@ ConnCreate(int serverFd)
        {
                fprintf(stderr, "%s: ConnCreate: malloc failed\n",
                                progname);
+               SignalChildren(SIGUSR1);
                ExitPostmaster(1);
        }
 
@@ -1154,7 +1165,6 @@ reset_shared(unsigned short port)
 {
        ipc_key = port * 1000 + shmem_seq * 100;
        CreateSharedMemoryAndSemaphores(ipc_key, MaxBackends);
-       ActiveBackends = FALSE;
        shmem_seq += 1;
        if (shmem_seq >= 10)
                shmem_seq -= 10;
@@ -1166,49 +1176,94 @@ reset_shared(unsigned short port)
 static void
 pmdie(SIGNAL_ARGS)
 {
-       int                     i;
-
+       PG_SETMASK(&BlockSig);
+       
        TPRINTF(TRACE_VERBOSE, "pmdie %d", postgres_signal_arg);
 
-       /*
-        * Kill self and/or children processes depending on signal number.
-        */
        switch (postgres_signal_arg)
        {
                case SIGHUP:
-                       /* Send SIGHUP to all children (update options flags) */
+                       /* 
+                        * Send SIGHUP to all children (update options flags)
+                        */
+                       if (Shutdown > SmartShutdown)
+                               return;
                        SignalChildren(SIGHUP);
-                       /* Don't die */
                        return;
-               case SIGINT:
-                       /* Die without killing children */
-                       break;
-               case SIGQUIT:
-                       /* Shutdown all children with SIGTERM */
-                       SignalChildren(SIGTERM);
-                       /* Don't die */
+               case SIGUSR2:
+                       /* 
+                        * Send SIGUSR2 to all children (AsyncNotifyHandler) 
+                        */
+                       if (Shutdown > SmartShutdown)
+                               return;
+                       SignalChildren(SIGUSR2);
                        return;
+
                case SIGTERM:
-                       /* Shutdown all children with SIGTERM and SIGKILL, then die */
-                       SignalChildren(SIGTERM);
-                       for (i = 0; i < 10; i++)
+                       /*
+                        * Smart Shutdown:
+                        *
+                        * let children to end their work and ShutdownDataBase.
+                        */
+                       if (Shutdown >= SmartShutdown)
+                               return;
+                       Shutdown = SmartShutdown;
+                       if (DLGetHead(BackendList))                     /* let reaper() handle this */
+                               return;
+                       /*
+                        * No children left. Shutdown data base system.
+                        */
+                       if (StartupPID > 0 || FatalError)       /* let reaper() handle this */
+                               return;
+                       if (ShutdownPID > 0)
+                               abort();
+
+                       ShutdownPID = ShutdownDataBase();
+                       return;
+
+               case SIGINT:
+                       /*
+                        * Fast Shutdown:
+                        * 
+                        * abort all children with SIGTERM (rollback active
+                        * transactions and exit) and ShutdownDataBase.
+                        */
+                       if (Shutdown >= FastShutdown)
+                               return;
+                       if (DLGetHead(BackendList))                     /* let reaper() handle this */
                        {
-                               if (!DLGetHead(BackendList))
-                                       break;
-                               sleep(1);
+                               if (!FatalError)
+                                       SignalChildren(SIGTERM);
+                               return;
                        }
-                       if (DLGetHead(BackendList))
-                               SignalChildren(SIGKILL);
-                       break;
-               case SIGUSR1:
-                       /* Quick die all children with SIGUSR1 and die */
-                       SignalChildren(SIGUSR1);
-                       break;
-               case SIGUSR2:
-                       /* Send SIGUSR2 to all children (AsyncNotifyHandler) */
-                       SignalChildren(SIGUSR2);
-                       /* Don't die */
+                       if (Shutdown > NoShutdown)
+                               return;
+                       Shutdown = FastShutdown;
+                       /*
+                        * No children left. Shutdown data base system.
+                        */
+                       if (StartupPID > 0 || FatalError)       /* let reaper() handle this */
+                               return;
+                       if (ShutdownPID > 0)
+                               abort();
+
+                       ShutdownPID = ShutdownDataBase();       /* flag for reaper() */
                        return;
+
+               case SIGQUIT:
+                       /* 
+                        * Immediate Shutdown:
+                        * 
+                        * abort all children with SIGUSR1 and exit without
+                        * attempt to properly shutdown data base system.
+                        */
+                       if (ShutdownPID > 0)
+                               kill(ShutdownPID, SIGQUIT);
+                       else if (StartupPID > 0)
+                               kill(StartupPID, SIGQUIT);
+                       else if (DLGetHead(BackendList))
+                               SignalChildren(SIGUSR1);
+                       break;
        }
 
        /* exit postmaster */
@@ -1224,29 +1279,82 @@ reaper(SIGNAL_ARGS)
 /* GH: replace waitpid for !HAVE_WAITPID. Does this work ? */
 #ifdef HAVE_WAITPID
        int                     status;                 /* backend exit status */
-
 #else
-       union wait      statusp;                /* backend exit status */
-
+       union wait      status;                 /* backend exit status */
 #endif
+       int                     exitstatus;
        int                     pid;                    /* process id of dead backend */
 
+       PG_SETMASK(&BlockSig);
+
        if (DebugLvl)
                fprintf(stderr, "%s: reaping dead processes...\n",
                                progname);
 #ifdef HAVE_WAITPID
        while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
        {
-               CleanupProc(pid, status);
-               pqsignal(SIGCHLD, reaper);
-       }
+               exitstatus = status;
 #else
-       while ((pid = wait3(&statusp, WNOHANG, NULL)) > 0)
+       while ((pid = wait3(&status, WNOHANG, NULL)) > 0)
        {
-               CleanupProc(pid, statusp.w_status);
-               pqsignal(SIGCHLD, reaper);
-       }
+               exitstatus = status.w_status;
 #endif
+               if (ShutdownPID > 0)
+               {
+                       if (pid != ShutdownPID)
+                               abort();
+                       if (exitstatus != 0)
+                               abort();
+                       proc_exit(0);
+               }
+               if (StartupPID > 0)
+               {
+                       if (pid != StartupPID)
+                               abort();
+                       if (exitstatus != 0)
+                               abort();
+                       StartupPID = 0;
+                       FatalError = false;
+                       if (Shutdown > NoShutdown)
+                       {
+                               if (ShutdownPID > 0)
+                                       abort();
+                               ShutdownPID = ShutdownDataBase();
+                       }
+                       pqsignal(SIGCHLD, reaper);
+                       return;
+               }
+               CleanupProc(pid, exitstatus);
+       }
+       pqsignal(SIGCHLD, reaper);
+
+       if (FatalError)
+       {
+               /*
+                * Wait for all children exit then StartupDataBase.
+                */
+               if (DLGetHead(BackendList))
+                       return;
+               if (StartupPID > 0 || ShutdownPID > 0)
+                       return;
+               if (DebugLvl)
+                       fprintf(stderr, "%s: CleanupProc: reinitializing shared memory and semaphores\n",
+                                       progname);
+               shmem_exit(0);
+               reset_shared(PostPortName);
+               StartupPID = StartupDataBase();
+               return;
+       }
+
+       if (Shutdown > NoShutdown)
+       {
+               if (DLGetHead(BackendList))
+                       return;
+               if (StartupPID > 0 || ShutdownPID > 0)
+                       return;
+               ShutdownPID = ShutdownDataBase();
+       }
+
 }
 
 /*
@@ -1260,8 +1368,8 @@ static void
 CleanupProc(int pid,
                        int exitstatus)         /* child's exit status. */
 {
-       Dlelem     *prev,
-                          *curr;
+       Dlelem     *curr,
+                          *next;
        Backend    *bp;
        int                     sig;
 
@@ -1298,18 +1406,19 @@ CleanupProc(int pid,
                return;
        }
 
+       FatalError = true;
        curr = DLGetHead(BackendList);
        while (curr)
        {
+               next = DLGetSucc(curr);
                bp = (Backend *) DLE_VAL(curr);
 
-               /* -----------------
+               /*
                 * SIGUSR1 is the special signal that says exit
                 * without proc_exit and let the user know what's going on.
                 * ProcSemaphoreKill() cleans up the backends semaphore.  If
                 * SendStop is set (-s on command line), then we send a SIGSTOP so
                 * that we can core dumps from all backends by hand.
-                * -----------------
                 */
                sig = (SendStop) ? SIGSTOP : SIGUSR1;
                if (bp->pid != pid)
@@ -1322,36 +1431,25 @@ CleanupProc(int pid,
                                                bp->pid);
                        kill(bp->pid, sig);
                }
-               ProcRemove(bp->pid);
-
-               prev = DLGetPred(curr);
-               DLRemove(curr);
-               free(bp);
-               DLFreeElem(curr);
-               if (!prev)
-               {                                               /* removed head */
-                       curr = DLGetHead(BackendList);
-                       continue;
+               else
+               {
+                       /*
+                        * I don't like that we call ProcRemove() here, assuming that 
+                        * shmem may be corrupted! But is there another way to free 
+                        * backend semaphores? Actually, I believe that we need not
+                        * in per backend semaphore at all (we use them to wait on lock
+                        * only, couldn't we just sigpause?), so probably we'll
+                        * remove this call from here someday.  -- vadim 04-10-1999
+                        */
+                       ProcRemove(pid);
+
+                       DLRemove(curr);
+                       free(bp);
+                       DLFreeElem(curr);
                }
-               curr = DLGetSucc(prev);
+               curr = next;
        }
 
-       /*
-        * Nothing up my sleeve here, ActiveBackends means that since the last
-        * time we recreated shared memory and sems another frontend has
-        * requested and received a connection and I have forked off another
-        * backend.  This prevents me from reinitializing shared stuff more
-        * than once for the set of backends that caused the failure and were
-        * killed off.
-        */
-       if (ActiveBackends == TRUE && Reinit)
-       {
-               if (DebugLvl)
-                       fprintf(stderr, "%s: CleanupProc: reinitializing shared memory and semaphores\n",
-                                       progname);
-               shmem_exit(0);
-               reset_shared(PostPortName);
-       }
 }
 
 /*
@@ -1516,8 +1614,6 @@ BackendStartup(Port *port)
        bn->cancel_key = MyCancelKey;
        DLAddHead(BackendList, DLNewElem(bn));
 
-       ActiveBackends = TRUE;
-
        return STATUS_OK;
 }
 
@@ -1586,27 +1682,9 @@ DoBackend(Port *port)
        /* We don't want the postmaster's proc_exit() handlers */
        on_exit_reset();        
 
-       /* ----------------
-        *      register signal handlers.
-        *      Thanks to the postmaster, these are currently blocked.
-        * ----------------
+       /* 
+        * Signal handlers setting is moved to tcop/postgres...
         */
-       pqsignal(SIGINT, die);
-
-       pqsignal(SIGHUP, die);
-       pqsignal(SIGTERM, die);
-       pqsignal(SIGPIPE, die);
-       pqsignal(SIGUSR1, quickdie);
-       pqsignal(SIGUSR2, Async_NotifyHandler);
-       pqsignal(SIGFPE, FloatExceptionHandler);
-
-       pqsignal(SIGCHLD, SIG_DFL);
-       pqsignal(SIGTTIN, SIG_DFL);
-       pqsignal(SIGTTOU, SIG_DFL);
-       pqsignal(SIGCONT, SIG_DFL);
-
-       /* OK, let's unblock our signals, all together now... */
-       sigprocmask(SIG_SETMASK, &oldsigmask, 0);
 
        /* Close the postmaster sockets */
        if (NetServer) 
@@ -1739,6 +1817,8 @@ ExitPostmaster(int status)
        /*
         * Not sure of the semantics here.      When the Postmaster dies, should
         * the backends all be killed? probably not.
+        *
+        * MUST         -- vadim 05-10-1999
         */
        if (ServerSock_INET != INVALID_SOCK)
                StreamClose(ServerSock_INET);
@@ -1752,8 +1832,11 @@ ExitPostmaster(int status)
 static void
 dumpstatus(SIGNAL_ARGS)
 {
-       Dlelem     *curr = DLGetHead(PortList);
+       Dlelem     *curr;
 
+       PG_SETMASK(&BlockSig);
+
+       curr = DLGetHead(PortList);
        while (curr)
        {
                Port       *port = DLE_VAL(curr);
@@ -1837,7 +1920,6 @@ CountChildren(void)
        return cnt;
 }
 
-
 #ifdef USE_SSL
 /*
  * Initialize SSL library and structures
@@ -1868,3 +1950,88 @@ static void InitSSL(void) {
   }
 }
 #endif
+
+static pid_t
+SSDataBase(bool startup)
+{
+       pid_t           pid;
+       int                     i;
+       static char     ssEntry[4][2 * ARGV_SIZE];
+
+       for (i = 0; i < 4; ++i)
+               MemSet(ssEntry[i], 0, 2 * ARGV_SIZE);
+
+       sprintf(ssEntry[0], "POSTPORT=%d", PostPortName);
+       putenv(ssEntry[0]);
+       sprintf(ssEntry[1], "POSTID=%d", NextBackendTag);
+       putenv(ssEntry[1]);
+       if (!getenv("PGDATA"))
+       {
+               sprintf(ssEntry[2], "PGDATA=%s", DataDir);
+               putenv(ssEntry[2]);
+       }
+       sprintf(ssEntry[3], "IPC_KEY=%d", ipc_key);
+       putenv(ssEntry[3]);
+
+       fflush(stdout);
+       fflush(stderr);
+
+       if ((pid = fork()) == 0)        /* child */
+       {
+               char       *av[ARGV_SIZE * 2];
+               int                     ac = 0;
+               char            execbuf[MAXPATHLEN];
+               char            nbbuf[ARGV_SIZE];
+               char            dbbuf[ARGV_SIZE];
+
+               on_exit_reset();        
+               if (NetServer) 
+                       StreamClose(ServerSock_INET);
+#ifndef __CYGWIN32__
+               StreamClose(ServerSock_UNIX);
+#endif
+
+               StrNCpy(execbuf, Execfile, MAXPATHLEN);
+               av[ac++] = execbuf;
+
+               av[ac++] = "-d";
+
+               sprintf(nbbuf, "-B%u", NBuffers);
+               av[ac++] = nbbuf;
+
+               if (startup)
+                       av[ac++] = "-x";
+
+               av[ac++] = "-p";
+
+               StrNCpy(dbbuf, "template1", ARGV_SIZE);
+               av[ac++] = dbbuf;
+
+               av[ac] = (char *) NULL;
+
+               optind = 1;
+
+               pqsignal(SIGQUIT, SIG_DFL);
+#ifdef HAVE_SIGPROCMASK
+               sigdelset(&BlockSig, SIGQUIT);
+#else
+               BlockSig &= ~(sigmask(SIGQUIT));
+#endif
+               PG_SETMASK(&BlockSig);
+       
+               BootstrapMain(ac, av);
+               exit(0);
+       }
+
+       /* in parent */
+       if (pid < 0)
+       {
+               fprintf(stderr, "%s Data Base: fork failed: %s\n",
+                       ((startup) ? "Startup" : "Shutdown"), strerror(errno));
+               ExitPostmaster(1);
+       }
+
+       NextBackendTag -= 1;
+
+       return(pid);
+}
index bfd0561705374792ec28c2e700e970cb1ac043bf..3fe2ec8be6e89511e44a3999f353493949c204b8 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.30 1999/09/24 00:24:29 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.31 1999/10/06 21:58:04 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -230,16 +230,18 @@ InitBufferPool(IPCKey key)
 
 #ifndef HAS_TEST_AND_SET
        {
-               int                     status;
                extern IpcSemaphoreId WaitIOSemId;
                extern IpcSemaphoreId WaitCLSemId;
 
                WaitIOSemId = IpcSemaphoreCreate(IPCKeyGetWaitIOSemaphoreKey(key),
-                                                                                1, IPCProtection, 0, 1, &status);
+                                                                                1, IPCProtection, 0, 1);
+               if (WaitIOSemId < 0)
+                       elog(FATAL, "InitBufferPool: IpcSemaphoreCreate(WaitIOSemId) failed");
                WaitCLSemId = IpcSemaphoreCreate(IPCKeyGetWaitCLSemaphoreKey(key),
                                                                                 1, IPCProtection,
-                                                                                IpcSemaphoreDefaultStartValue,
-                                                                                1, &status);
+                                                                                IpcSemaphoreDefaultStartValue, 1);
+               if (WaitCLSemId < 0)
+                       elog(FATAL, "InitBufferPool: IpcSemaphoreCreate(WaitCLSemId) failed");
        }
 #endif
        PrivateRefCount = (long *) calloc(NBuffers, sizeof(long));
index 59c991bd0a7164f9ee083a562017262aeb12b534..ff326becf1e4519c1eac07d5edf19f55344d3637 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.38 1999/07/17 20:17:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.39 1999/10/06 21:58:06 vadim Exp $
  *
  * NOTES
  *
@@ -284,18 +284,6 @@ IPCPrivateMemoryKill(int status,
        }
 }
 
-
-/****************************************************************************/
-/*      IpcSemaphoreCreate(semKey, semNum, permission, semStartValue)                  */
-/*                                                                                                                                                     */
-/*       - returns a semaphore identifier:                                                                             */
-/*                                                                                                                                                     */
-/* if key doesn't exist: return a new id,      status:= IpcSemIdNotExist    */
-/* if key exists:               return the old id,    status:= IpcSemIdExist           */
-/* if semNum > MAX :    return # of argument, status:=IpcInvalidArgument       */
-/*                                                                                                                                                     */
-/****************************************************************************/
-
 /*
  * Note:
  * XXX This should be split into two different calls.  One should
@@ -312,8 +300,7 @@ IpcSemaphoreCreate(IpcSemaphoreKey semKey,
                                   int semNum,
                                   int permission,
                                   int semStartValue,
-                                  int removeOnExit,
-                                  int *status)
+                                  int removeOnExit)
 {
        int                     i;
        int                     errStatus;
@@ -321,20 +308,14 @@ IpcSemaphoreCreate(IpcSemaphoreKey semKey,
        u_short         array[IPC_NMAXSEM];
        union semun semun;
 
-       /* get a semaphore if non-existent */
        /* check arguments      */
        if (semNum > IPC_NMAXSEM || semNum <= 0)
-       {
-               *status = IpcInvalidArgument;
-               return 2;                               /* returns the number of the invalid
-                                                                * argument   */
-       }
+               return(-1);
 
        semId = semget(semKey, 0, 0);
 
        if (semId == -1)
        {
-               *status = IpcSemIdNotExist;             /* there doesn't exist a semaphore */
 #ifdef DEBUG_IPC
                EPRINTF("calling semget with %d, %d , %d\n",
                                semKey,
@@ -348,7 +329,7 @@ IpcSemaphoreCreate(IpcSemaphoreKey semKey,
                        EPRINTF("IpcSemaphoreCreate: semget failed (%s) "
                                        "key=%d, num=%d, permission=%o",
                                        strerror(errno), semKey, semNum, permission);
-                       proc_exit(3);
+                       return(-1);
                }
                for (i = 0; i < semNum; i++)
                        array[i] = semStartValue;
@@ -358,22 +339,16 @@ IpcSemaphoreCreate(IpcSemaphoreKey semKey,
                {
                        EPRINTF("IpcSemaphoreCreate: semctl failed (%s) id=%d",
                                        strerror(errno), semId);
+                       semctl(semId, 0, IPC_RMID, semun);
+                       return(-1);
                }
 
                if (removeOnExit)
                        on_shmem_exit(IPCPrivateSemaphoreKill, (caddr_t) semId);
-
-       }
-       else
-       {
-               /* there is a semaphore id for this key */
-               *status = IpcSemIdExist;
        }
 
 #ifdef DEBUG_IPC
-       EPRINTF("\nIpcSemaphoreCreate, status %d, returns %d\n",
-                       *status,
-                       semId);
+       EPRINTF("\nIpcSemaphoreCreate, returns %d\n", semId);
        fflush(stdout);
        fflush(stderr);
 #endif
index 16c5266c6cde9d6fe1c521d857d30ce26fda6b98..259a1f532c940dae14eb54769969923fa946aa00 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.30 1999/07/17 20:17:44 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.31 1999/10/06 21:58:06 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -54,17 +54,17 @@ void
 CreateSharedMemoryAndSemaphores(IPCKey key, int maxBackends)
 {
        int                     size;
+       extern int      XLOGShmemSize(void);
+       extern void     XLOGShmemInit(void);
 
 #ifdef HAS_TEST_AND_SET
-       /* ---------------
-        *      create shared memory for slocks
-        * --------------
+       /*
+        * Create shared memory for slocks
         */
        CreateAndInitSLockMemory(IPCKeyGetSLockSharedMemoryKey(key));
 #endif
-       /* ----------------
-        *      kill and create the buffer manager buffer pool (and semaphore)
-        * ----------------
+       /*
+        * Kill and create the buffer manager buffer pool (and semaphore)
         */
        CreateSpinlocks(IPCKeyGetSpinLockSemaphoreKey(key));
 
@@ -73,7 +73,7 @@ CreateSharedMemoryAndSemaphores(IPCKey key, int maxBackends)
         * moderately-accurate estimates for the big hogs, plus 100K for the
         * stuff that's too small to bother with estimating.
         */
-       size = BufferShmemSize() + LockShmemSize(maxBackends);
+       size = BufferShmemSize() + LockShmemSize(maxBackends) + XLOGShmemSize();
 #ifdef STABLE_MEMORY_STORAGE
        size += MMShmemSize();
 #endif
@@ -89,6 +89,7 @@ CreateSharedMemoryAndSemaphores(IPCKey key, int maxBackends)
        ShmemCreate(IPCKeyGetBufferMemoryKey(key), size);
        ShmemIndexReset();
        InitShmem(key, size);
+       XLOGShmemInit();
        InitBufferPool(key);
 
        /* ----------------
index c23952c19105efe0368d5123124362d3197cbda0..e76829ec7c943d26a94191958e60811ada56af34 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.46 1999/09/24 00:24:35 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.47 1999/10/06 21:58:06 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -187,8 +187,7 @@ InitShmem(unsigned int key, unsigned int size)
         * bootstrap initialize spin locks so we can start to use the
         * allocator and shmem index.
         */
-       if (!InitSpinLocks(ShmemBootstrap, IPCKeyGetSpinLockSemaphoreKey(key)))
-               return FALSE;
+       InitSpinLocks();
 
        /*
         * We have just allocated additional space for two spinlocks. Now
index 4d9bd3f71b49fc8746a3fb8028b702f6775970da..700f5bfaf6d24346b2542f7a12db4ae7f1c5e2a6 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.20 1999/07/16 04:59:44 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.21 1999/10/06 21:58:06 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,15 +40,15 @@ IpcSemaphoreId SpinLockId;
 #ifdef HAS_TEST_AND_SET
 /* real spin lock implementations */
 
-bool
+void
 CreateSpinlocks(IPCKey key)
 {
        /* the spin lock shared memory must have been created by now */
-       return TRUE;
+       return;
 }
 
-bool
-InitSpinLocks(int init, IPCKey key)
+void
+InitSpinLocks(void)
 {
        extern SPINLOCK ShmemLock;
        extern SPINLOCK ShmemIndexLock;
@@ -57,7 +57,8 @@ InitSpinLocks(int init, IPCKey key)
        extern SPINLOCK ProcStructLock;
        extern SPINLOCK SInvalLock;
        extern SPINLOCK OidGenLockId;
-
+       extern SPINLOCK XidGenLockId;
+       extern SPINLOCK ControlFileLockId;
 #ifdef STABLE_MEMORY_STORAGE
        extern SPINLOCK MMCacheLock;
 
@@ -71,12 +72,14 @@ InitSpinLocks(int init, IPCKey key)
        ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID;
        SInvalLock = (SPINLOCK) SINVALLOCKID;
        OidGenLockId = (SPINLOCK) OIDGENLOCKID;
+       XidGenLockId = (SPINLOCK) XIDGENLOCKID;
+       ControlFileLockId = (SPINLOCK) CNTLFILELOCKID;
 
 #ifdef STABLE_MEMORY_STORAGE
        MMCacheLock = (SPINLOCK) MMCACHELOCKID;
 #endif
 
-       return TRUE;
+       return;
 }
 
 #ifdef LOCKDEBUG
@@ -224,55 +227,17 @@ SpinIsLocked(SPINLOCK lock)
  *             the spinlocks
  *
  */
-bool
+void
 CreateSpinlocks(IPCKey key)
 {
 
-       int                     status;
-       IpcSemaphoreId semid;
-
-       semid = IpcSemaphoreCreate(key, MAX_SPINS, IPCProtection,
-                                                          IpcSemaphoreDefaultStartValue, 1, &status);
-       if (status == IpcSemIdExist)
-       {
-               IpcSemaphoreKill(key);
-               elog(NOTICE, "Destroying old spinlock semaphore");
-               semid = IpcSemaphoreCreate(key, MAX_SPINS, IPCProtection,
-                                                         IpcSemaphoreDefaultStartValue, 1, &status);
-       }
+       SpinLockId = IpcSemaphoreCreate(key, MAX_SPINS, IPCProtection,
+                                                          IpcSemaphoreDefaultStartValue, 1);
 
-       if (semid >= 0)
-       {
-               SpinLockId = semid;
-               return TRUE;
-       }
-       /* cannot create spinlocks */
-       elog(FATAL, "CreateSpinlocks: cannot create spin locks");
-       return FALSE;
-}
-
-/*
- * Attach to existing spinlock set
- */
-static bool
-AttachSpinLocks(IPCKey key)
-{
-       IpcSemaphoreId id;
+       if (SpinLockId <= 0)
+               elog(STOP, "CreateSpinlocks: cannot create spin locks");
 
-       id = semget(key, MAX_SPINS, 0);
-       if (id < 0)
-       {
-               if (errno == EEXIST)
-               {
-                       /* key is the name of someone else's semaphore */
-                       elog(FATAL, "AttachSpinlocks: SPIN_KEY belongs to someone else");
-               }
-               /* cannot create spinlocks */
-               elog(FATAL, "AttachSpinlocks: cannot create spin locks");
-               return FALSE;
-       }
-       SpinLockId = id;
-       return TRUE;
+       return;
 }
 
 /*
@@ -287,8 +252,8 @@ AttachSpinLocks(IPCKey key)
  * (SJCacheLock) for it.  Same story for the main memory storage mgr.
  *
  */
-bool
-InitSpinLocks(int init, IPCKey key)
+void
+InitSpinLocks(void)
 {
        extern SPINLOCK ShmemLock;
        extern SPINLOCK ShmemIndexLock;
@@ -297,26 +262,14 @@ InitSpinLocks(int init, IPCKey key)
        extern SPINLOCK ProcStructLock;
        extern SPINLOCK SInvalLock;
        extern SPINLOCK OidGenLockId;
+       extern SPINLOCK XidGenLockId;
+       extern SPINLOCK ControlFileLockId;
 
 #ifdef STABLE_MEMORY_STORAGE
        extern SPINLOCK MMCacheLock;
 
 #endif
 
-       if (!init || key != IPC_PRIVATE)
-       {
-
-               /*
-                * if bootstrap and key is IPC_PRIVATE, it means that we are
-                * running backend by itself.  no need to attach spinlocks
-                */
-               if (!AttachSpinLocks(key))
-               {
-                       elog(FATAL, "InitSpinLocks: couldnt attach spin locks");
-                       return FALSE;
-               }
-       }
-
        /* These five (or six) spinlocks have fixed location is shmem */
        ShmemLock = (SPINLOCK) SHMEMLOCKID;
        ShmemIndexLock = (SPINLOCK) SHMEMINDEXLOCKID;
@@ -325,12 +278,14 @@ InitSpinLocks(int init, IPCKey key)
        ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID;
        SInvalLock = (SPINLOCK) SINVALLOCKID;
        OidGenLockId = (SPINLOCK) OIDGENLOCKID;
+       XidGenLockId = (SPINLOCK) XIDGENLOCKID;
+       ControlFileLockId = (SPINLOCK) CNTLFILELOCKID;
 
 #ifdef STABLE_MEMORY_STORAGE
        MMCacheLock = (SPINLOCK) MMCACHELOCKID;
 #endif
 
-       return TRUE;
+       return;
 }
 
 #endif  /* HAS_TEST_AND_SET */
index 159edf0549b6c519f7eea4f2f3863c39776ab0aa..0270b0e116534b18f808b81dd7313ac1054a47b7 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.61 1999/09/24 00:24:41 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.62 1999/10/06 21:58:07 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,7 +46,7 @@
  *             This is so that we can support more backends. (system-wide semaphore
  *             sets run out pretty fast.)                                -ay 4/95
  *
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.61 1999/09/24 00:24:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.62 1999/10/06 21:58:07 vadim Exp $
  */
 #include <sys/time.h>
 #include <unistd.h>
@@ -70,7 +70,7 @@
 #include "storage/proc.h"
 #include "utils/trace.h"
 
-static void HandleDeadLock(int sig);
+void HandleDeadLock(SIGNAL_ARGS);
 static void ProcFreeAllSemaphores(void);
 
 #define DeadlockCheckTimer pg_options[OPT_DEADLOCKTIMEOUT]
@@ -84,12 +84,6 @@ static void ProcFreeAllSemaphores(void);
  */
 SPINLOCK       ProcStructLock;
 
-/*
- * For cleanup routines.  Don't cleanup if the initialization
- * has not happened.
- */
-static bool ProcInitialized = FALSE;
-
 static PROC_HDR *ProcGlobal = NULL;
 
 PROC      *MyProc = NULL;
@@ -167,8 +161,9 @@ InitProcGlobal(IPCKey key, int maxBackends)
                                                                                   PROC_NSEMS_PER_SET,
                                                                                   IPCProtection,
                                                                                   IpcSemaphoreDefaultStartValue,
-                                                                                  0,
-                                                                                  &semstat);
+                                                                                  0);
+                               if (semId < 0)
+                                       elog(FATAL, "InitProcGlobal: IpcSemaphoreCreate failed");
                                /* mark this sema set allocated */
                                ProcGlobal->freeSemMap[i] = (1 << PROC_NSEMS_PER_SET);
                        }
@@ -189,12 +184,6 @@ InitProcess(IPCKey key)
        unsigned long location,
                                myOffset;
 
-       /* ------------------
-        * Routine called if deadlock timer goes off. See ProcSleep()
-        * ------------------
-        */
-       pqsignal(SIGALRM, HandleDeadLock);
-
        SpinAcquire(ProcStructLock);
 
        /* attach to the free list */
@@ -203,7 +192,7 @@ InitProcess(IPCKey key)
        if (!found)
        {
                /* this should not happen. InitProcGlobal() is called before this. */
-               elog(ERROR, "InitProcess: Proc Header uninitialized");
+               elog(STOP, "InitProcess: Proc Header uninitialized");
        }
 
        if (MyProc != NULL)
@@ -271,8 +260,7 @@ InitProcess(IPCKey key)
                                                                   PROC_NSEMS_PER_SET,
                                                                   IPCProtection,
                                                                   IpcSemaphoreDefaultStartValue,
-                                                                  0,
-                                                                  &semstat);
+                                                                  0);
 
                /*
                 * we might be reusing a semaphore that belongs to a dead backend.
@@ -316,14 +304,12 @@ InitProcess(IPCKey key)
         */
        location = MAKE_OFFSET(MyProc);
        if ((!ShmemPIDLookup(MyProcPid, &location)) || (location != MAKE_OFFSET(MyProc)))
-               elog(FATAL, "InitProc: ShmemPID table broken");
+               elog(STOP, "InitProc: ShmemPID table broken");
 
        MyProc->errType = NO_ERROR;
        SHMQueueElemInit(&(MyProc->links));
 
        on_shmem_exit(ProcKill, (caddr_t) MyProcPid);
-
-       ProcInitialized = TRUE;
 }
 
 /*
@@ -755,8 +741,8 @@ ProcAddLock(SHM_QUEUE *elem)
  * up my semaphore.
  * --------------------
  */
-static void
-HandleDeadLock(int sig)
+void
+HandleDeadLock(SIGNAL_ARGS)
 {
        LOCK       *mywaitlock;
 
index 2a3e7e77300ae222f67dca9fdb204aa4ce37f4cd..29486bd6f390be2208d533037548a33f0e37617c 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.130 1999/09/29 16:06:10 wieck Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.131 1999/10/06 21:58:08 vadim Exp $
  *
  * NOTES
  *       this is the "main" module of the postgres backend and
@@ -58,6 +58,7 @@
 #include "tcop/pquery.h"
 #include "tcop/tcopprot.h"
 #include "tcop/utility.h"
+#include "storage/proc.h"
 #include "utils/ps_status.h"
 #include "utils/temprel.h"
 #include "utils/trace.h"
  */
 
 /*static bool  EnableRewrite = true; , never changes why have it*/
-CommandDest whereToSendOutput;
+CommandDest whereToSendOutput = Debug;
 
 /* Define status buffer needed by PS_SET_STATUS */
 PS_DEFINE_BUFFER;
 
+extern void            BaseInit(void);
+extern void            StartupXLOG(void);
+extern void            ShutdownXLOG(void);
+
+extern void            HandleDeadLock(SIGNAL_ARGS);
+
+extern char            XLogDir[];
+extern char            ControlFilePath[];
+
 extern int     lockingOff;
 extern int     NBuffers;
 
@@ -115,21 +125,8 @@ char               relname[80];            /* current relation name */
 /* note: these declarations had better match tcopprot.h */
 DLLIMPORT sigjmp_buf Warn_restart;
 
-bool           InError = true;
-
-/*
- * Note: InError is a flag to elog() telling whether it is safe to longjmp
- * back to PostgresMain.  It is "false", allowing an error longjmp, during
- * normal processing.  It is "true" during startup, when we have not yet
- * set the Warn_restart jmp_buf, and also "true" in the interval when we
- * have executed a longjmp back to PostgresMain and not yet finished cleaning
- * up after the error.  In either case, elog(ERROR) should be treated as a
- * fatal exit condition rather than attempting to recover --- since there is
- * noplace to recover to in the first case, and we don't want to risk an
- * infinite loop of "error recoveries" in the second case.
- *
- * Therefore, InError starts out "true" at program load time, as shown above.
- */
+bool           InError = false;
+bool           ExitAfterAbort = false;
 
 extern int     NBuffers;
 
@@ -773,6 +770,7 @@ handle_warn(SIGNAL_ARGS)
 void
 quickdie(SIGNAL_ARGS)
 {
+       PG_SETMASK(&BlockSig);
        elog(NOTICE, "Message from PostgreSQL backend:"
                 "\n\tThe Postmaster has informed me that some other backend"
                 " died abnormally and possibly corrupted shared memory."
@@ -787,13 +785,25 @@ quickdie(SIGNAL_ARGS)
         * storage.  Just nail the windows shut and get out of town.
         */
 
-       exit(0);
+       exit(1);
 }
 
+/*
+ * Abort transaction and exit
+ */
 void
 die(SIGNAL_ARGS)
 {
-       ExitPostgres(0);
+       PG_SETMASK(&BlockSig);
+       /*
+        * If ERROR/FATAL is in progress...
+        */
+       if (InError)
+       {
+               ExitAfterAbort = true;
+               return;
+       }
+       elog(FATAL, "The system is shutting down");
 }
 
 /* signal handler for floating point exception */
@@ -907,6 +917,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
 #endif
        DataDir = getenv("PGDATA");
 
+       SetProcessingMode(InitProcessing);
+
        /*
         * Try to get initial values for date styles and formats. Does not do
         * a complete job, but should be good enough for backend. Cannot call
@@ -1265,10 +1277,68 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
                                break;
                }
 
-       /* ----------------
-        *      get user name (needed now in case it is the default database name)
-        *      and check command line validity
-        * ----------------
+       if (ShowStats &&
+               (ShowParserStats || ShowPlannerStats || ShowExecutorStats))
+       {
+               fprintf(stderr, "-s can not be used together with -t.\n");
+               proc_exit(1);
+       }
+
+       if (!DataDir)
+       {
+               fprintf(stderr, "%s does not know where to find the database system "
+                               "data.  You must specify the directory that contains the "
+                               "database system either by specifying the -D invocation "
+                        "option or by setting the PGDATA environment variable.\n\n",
+                               argv[0]);
+               proc_exit(1);
+       }
+
+       /*
+        * 1. Set BlockSig and UnBlockSig masks. 
+        * 2. Set up signal handlers.
+        * 3. Allow only SIGUSR1 signal (we never block it) 
+        *    during initialization.
+        *
+        * Note that postmaster already blocked ALL signals to make us happy.
+        */
+       if (!IsUnderPostmaster)
+       {
+               PG_INITMASK();
+               PG_SETMASK(&BlockSig);
+       }
+
+#ifdef HAVE_SIGPROCMASK
+       sigdelset(&BlockSig, SIGUSR1);
+#else
+       BlockSig &= ~(sigmask(SIGUSR1));
+#endif
+
+       pqsignal(SIGHUP, read_pg_options);              /* update pg_options from file */
+       pqsignal(SIGINT, QueryCancelHandler);   /* cancel current query */
+       pqsignal(SIGQUIT, handle_warn);                 /* handle error */
+       pqsignal(SIGTERM, die);
+       pqsignal(SIGALRM, HandleDeadLock);
+       /* 
+        * Ignore failure to write to frontend. Note: if frontend closes 
+        * connection, we will notice it and exit cleanly when control next 
+        * returns to outer loop.  This seems safer than forcing exit in the 
+        * midst of output during who-knows-what operation...
+        */
+       pqsignal(SIGPIPE, SIG_IGN);
+       pqsignal(SIGUSR1, quickdie);
+       pqsignal(SIGUSR2, Async_NotifyHandler); /* flush also sinval cache */
+       pqsignal(SIGFPE, FloatExceptionHandler);
+       pqsignal(SIGCHLD, SIG_IGN);                             /* ignored, sent by LockOwners */
+       pqsignal(SIGTTIN, SIG_DFL);
+       pqsignal(SIGTTOU, SIG_DFL);
+       pqsignal(SIGCONT, SIG_DFL);
+
+       PG_SETMASK(&BlockSig);          /* block everything except SIGUSR1 */
+
+       /*
+        * Get user name (needed now in case it is the default database name)
+        * and check command line validity
         */
        SetPgUserName();
        userName = GetPgUserName();
@@ -1281,10 +1351,14 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
                        usage(argv[0]);
                        proc_exit(1);
                }
+               pq_init();                              /* initialize libpq at backend startup */
+               whereToSendOutput = Remote;
+               BaseInit();
        }
        else
        {
                /* interactive case: database name can be last arg on command line */
+               whereToSendOutput = Debug;
                if (errs || argc - optind > 1)
                {
                        usage(argv[0]);
@@ -1298,23 +1372,10 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
                                        argv[0]);
                        proc_exit(1);
                }
-       }
-
-       if (ShowStats &&
-               (ShowParserStats || ShowPlannerStats || ShowExecutorStats))
-       {
-               fprintf(stderr, "-s can not be used together with -t.\n");
-               proc_exit(1);
-       }
-
-       if (!DataDir)
-       {
-               fprintf(stderr, "%s does not know where to find the database system "
-                               "data.  You must specify the directory that contains the "
-                               "database system either by specifying the -D invocation "
-                        "option or by setting the PGDATA environment variable.\n\n",
-                               argv[0]);
-               proc_exit(1);
+               BaseInit();
+               sprintf(XLogDir, "%s%cpg_xlog", DataDir, SEP_CHAR);
+               sprintf(ControlFilePath, "%s%cpg_control", DataDir, SEP_CHAR);
+               StartupXLOG();
        }
 
        /*
@@ -1367,19 +1428,15 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
                                remote_info = remote_host = "unknown";
                                break;
                }
-       }
-
-       /* ----------------
-        *      set process params for ps
-        * ----------------
-        */
-       if (IsUnderPostmaster)
-       {
+               /*
+                * Set process params for ps
+                */
                PS_INIT_STATUS(real_argc, real_argv, argv[0],
                                           remote_info, userName, DBName);
                PS_SET_STATUS("startup");
        }
 
+
        /* ----------------
         *      print flags
         * ----------------
@@ -1409,23 +1466,10 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
                }
        }
 
-       /* ----------------
-        *      initialize I/O
-        * ----------------
-        */
-       if (IsUnderPostmaster)
-       {
-               pq_init();                              /* initialize libpq at backend startup */
-               whereToSendOutput = Remote;
-       }
-       else
-               whereToSendOutput = Debug;
 
-       /* ----------------
-        *      general initialization
-        * ----------------
+       /*
+        * general initialization
         */
-       SetProcessingMode(InitProcessing);
 
        if (Verbose)
                TPRINTF(TRACE_VERBOSE, "InitPostgres");
@@ -1445,30 +1489,9 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
 
        parser_input = makeStringInfo(); /* initialize input buffer */
 
-       /* ----------------
-        *      Set up handler for cancel-request signal, and
-        *      send this backend's cancellation info to the frontend.
-        *      This should not be done until we are sure startup is successful.
-        * ----------------
-        */
-
-       pqsignal(SIGHUP, read_pg_options);      /* update pg_options from file */
-       pqsignal(SIGINT, QueryCancelHandler);           /* cancel current query */
-       pqsignal(SIGQUIT, handle_warn);         /* handle error */
-       pqsignal(SIGTERM, die);
-       pqsignal(SIGPIPE, SIG_IGN); /* ignore failure to write to frontend */
-
-       /*
-        * Note: if frontend closes connection, we will notice it and exit
-        * cleanly when control next returns to outer loop.  This seems safer
-        * than forcing exit in the midst of output during who-knows-what
-        * operation...
+       /* 
+        * Send this backend's cancellation info to the frontend. 
         */
-       pqsignal(SIGUSR1, quickdie);
-       pqsignal(SIGUSR2, Async_NotifyHandler);         /* flush also sinval cache */
-       pqsignal(SIGCHLD, SIG_IGN); /* ignored, sent by LockOwners */
-       pqsignal(SIGFPE, FloatExceptionHandler);
-
        if (whereToSendOutput == Remote &&
                PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
        {
@@ -1485,40 +1508,41 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
        if (!IsUnderPostmaster)
        {
                puts("\nPOSTGRES backend interactive interface ");
-               puts("$Revision: 1.130 $ $Date: 1999/09/29 16:06:10 $\n");
+               puts("$Revision: 1.131 $ $Date: 1999/10/06 21:58:08 $\n");
        }
 
-       /* ----------------
+       /*
         * Initialize the deferred trigger manager
-        * ----------------
         */
        if (DeferredTriggerInit() != 0)
                ExitPostgres(1);
 
-       /* ----------------
-        *      POSTGRES main processing loop begins here
-        *
-        *      if an exception is encountered, processing resumes here
-        *      so we abort the current transaction and start a new one.
+       /*
+        * POSTGRES main processing loop begins here
         *
-        *      Note:  elog(ERROR) does a siglongjmp() to transfer control here.
-        *      See comments with the declaration of InError, above.
-        * ----------------
+        * If an exception is encountered, processing resumes here
+        * so we abort the current transaction and start a new one.
         */
 
+       SetProcessingMode(NormalProcessing);
+
        if (sigsetjmp(Warn_restart, 1) != 0)
        {
-               InError = true;
-
                time(&tim);
 
                if (Verbose)
                        TPRINTF(TRACE_VERBOSE, "AbortCurrentTransaction");
 
                AbortCurrentTransaction();
+               InError = false;
+               if (ExitAfterAbort)
+               {
+                       ProcReleaseLocks();             /* Just to be sure... */
+                       ExitPostgres(0);
+               }
        }
 
-       InError = false;
+       PG_SETMASK(&UnBlockSig);
 
        /*
         * Non-error queries loop here.
@@ -1636,6 +1660,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
                                 */
                        case 'X':
                        case EOF:
+                               if (!IsUnderPostmaster)
+                                       ShutdownXLOG();
                                pq_close();
                                proc_exit(0);
                                break;
index 11cf762e7d64a51e80a9686820df76e230297bd9..342a1029d1639ea100a6788acca86f92f597532d 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.48 1999/09/11 19:06:31 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.49 1999/10/06 21:58:09 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -37,6 +37,7 @@
 extern int     errno;
 extern int     sys_nerr;
 
+extern CommandDest     whereToSendOutput;
 
 #ifdef USE_SYSLOG
 /*
@@ -107,6 +108,19 @@ elog(int lev, const char *fmt, ...)
        if (lev <= DEBUG && Debugfile < 0)
                return;                                 /* ignore debug msgs if noplace to send */
 
+       if (lev == ERROR || lev == FATAL)
+       {
+               if (IsInitProcessingMode())
+               {
+                       extern TransactionState CurrentTransactionState;
+
+                       if (CurrentTransactionState->state != TRANS_DEFAULT && 
+                               CurrentTransactionState->state != TRANS_DISABLED)
+                               abort();
+                       lev = FATAL;
+               }
+       }
+
        /* choose message prefix and indent level */
        switch (lev)
        {
@@ -304,7 +318,7 @@ elog(int lev, const char *fmt, ...)
 
 #ifndef PG_STANDALONE
 
-       if (lev > DEBUG && IsUnderPostmaster)
+       if (lev > DEBUG && whereToSendOutput == Remote)
        {
                /* Send IPC message to the front-end program */
                char            msgtype;
@@ -336,7 +350,7 @@ elog(int lev, const char *fmt, ...)
                pq_flush();
        }
 
-       if (lev > DEBUG && ! IsUnderPostmaster)
+       if (lev > DEBUG && whereToSendOutput != Remote)
        {
                /* We are running as an interactive backend, so just send
                 * the message to stderr.
@@ -355,36 +369,29 @@ elog(int lev, const char *fmt, ...)
        /*
         * Perform error recovery action as specified by lev.
         */
-       if (lev == ERROR)
+       if (lev == ERROR || lev == FATAL)
        {
                if (InError)
                {
                        /* error reported during error recovery; don't loop forever */
                        elog(REALLYFATAL, "elog: error during error recovery, giving up!");
                }
-               /* exit to main loop */
+               InError = true;
                ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */
+               if (lev == FATAL)
+               {
+                       if (IsInitProcessingMode())
+                               ExitPostgres(0);
+                       ExitAfterAbort = true;
+               }
+               /* exit to main loop */
                siglongjmp(Warn_restart, 1);
        }
 
-       if (lev == FATAL)
-       {
-               /*
-                * Assume that if we have detected the failure we can exit with a
-                * normal exit status.  This will prevent the postmaster from
-                * cleaning up when it's not needed.
-                */
-               fflush(stdout);
-               fflush(stderr);
-               ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */
-               ProcReleaseLocks();             /* get rid of real locks we hold */
-               proc_exit(0);
-       }
-
        if (lev > FATAL)
        {
                /*
-                * Serious crash time.  Postmaster will observe nonzero
+                * Serious crash time. Postmaster will observe nonzero
                 * process exit status and kill the other backends too.
                 */
                fflush(stdout);
index 88baaf4a8915d11a332913515c7496e242d71ca1..11ac358026072f4508a1f0488376c596bbfb7dfc 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.34 1999/07/17 20:18:08 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.35 1999/10/06 21:58:10 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -133,20 +133,7 @@ StatusPostmasterExit(int status)
  *             processing mode support stuff (used to be in pmod.c)
  * ----------------------------------------------------------------
  */
-static ProcessingMode Mode = NoProcessing;
-
-#ifdef NOT_USED
-/*
- * IsNoProcessingMode
- *             True iff processing mode is NoProcessing.
- */
-bool
-IsNoProcessingMode()
-{
-       return (bool) (Mode == NoProcessing);
-}
-
-#endif
+static ProcessingMode Mode = InitProcessing;
 
 /*
  * IsBootstrapProcessingMode
@@ -186,13 +173,13 @@ IsNormalProcessingMode()
  *             BadArg if called with invalid mode.
  *
  * Note:
- *             Mode is NoProcessing before the first time this is called.
+ *             Mode is InitProcessing before the first time this is called.
  */
 void
 SetProcessingMode(ProcessingMode mode)
 {
-       AssertArg(mode == NoProcessing || mode == BootstrapProcessing ||
-                         mode == InitProcessing || mode == NormalProcessing);
+       AssertArg(mode == BootstrapProcessing || mode == InitProcessing || 
+                               mode == NormalProcessing);
 
        Mode = mode;
 }
index 1285c23e8434680ce476567504998507d8dacccc..20db5c34bb71129b7b1f8254c22825962c4bc182 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.50 1999/09/28 11:41:09 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.51 1999/10/06 21:58:10 vadim Exp $
  *
  * NOTES
  *             InitPostgres() is the function called from PostgresMain
 #include "mb/pg_wchar.h"
 #endif
 
+void           BaseInit(void);
+
 static void VerifySystemDatabase(void);
 static void VerifyMyDatabase(void);
 static void ReverifyMyDatabase(char *name);
 static void InitCommunication(void);
 static void InitMyDatabaseInfo(char *name);
-static void InitStdio(void);
 static void InitUserid(void);
 
 
@@ -385,37 +386,6 @@ InitCommunication()
        {
                if (MyBackendTag == -1)
                        elog(FATAL, "InitCommunication: missing POSTID");
-
-               /*
-                * Enable this if you are trying to force the backend to run as if
-                * it is running under the postmaster.
-                *
-                * This goto forces Postgres to attach to shared memory instead of
-                * using malloc'ed memory (which is the normal behavior if run
-                * directly).
-                *
-                * To enable emulation, run the following shell commands (in addition
-                * to enabling this goto)
-                *
-                * % setenv POSTID 1 % setenv POSTPORT 4321 % setenv IPC_KEY 4321000
-                * % postmaster & % kill -9 %1
-                *
-                * Upon doing this, Postmaster will have allocated the shared memory
-                * resources that Postgres will attach to if you enable
-                * EMULATE_UNDER_POSTMASTER.
-                *
-                * This comment may well age with time - it is current as of 8
-                * January 1990
-                *
-                * Greg
-                */
-
-#ifdef EMULATE_UNDER_POSTMASTER
-
-               goto forcesharedmemory;
-
-#endif
-
        }
        else if (IsUnderPostmaster)
        {
@@ -439,12 +409,6 @@ InitCommunication()
         *      initialize shared memory and semaphores appropriately.
         * ----------------
         */
-#ifdef EMULATE_UNDER_POSTMASTER
-
-forcesharedmemory:
-
-#endif
-
        if (!IsUnderPostmaster)         /* postmaster already did this */
        {
                PostgresIpcKey = key;
@@ -452,21 +416,6 @@ forcesharedmemory:
        }
 }
 
-
-/* --------------------------------
- *             InitStdio
- *
- *             this routine consists of a bunch of code fragments
- *             that used to be randomly scattered through cinit().
- *             they all seem to do stuff associated with io.
- * --------------------------------
- */
-static void
-InitStdio()
-{
-       DebugFileOpen();
-}
-
 /* --------------------------------
  * InitPostgres
  *             Initialize POSTGRES.
@@ -477,8 +426,6 @@ InitStdio()
  */
 extern int     NBuffers;
 
-bool           PostgresIsInitialized = false;
-
 int                    lockingOff = 0;         /* backend -L switch */
 
 /*
@@ -488,37 +435,11 @@ InitPostgres(char *name)          /* database name */
 {
        bool            bootstrap;              /* true if BootstrapProcessing */
 
-       /* ----------------
-        *      see if we're running in BootstrapProcessing mode
-        * ----------------
+       /*
+        * See if we're running in BootstrapProcessing mode
         */
        bootstrap = IsBootstrapProcessingMode();
 
-       /* ----------------
-        *      turn on the exception handler.  Note: we cannot use elog, Assert,
-        *      AssertState, etc. until after exception handling is on.
-        * ----------------
-        */
-       EnableExceptionHandling(true);
-
-       /* ----------------
-        *      A stupid check to make sure we don't call this more than once.
-        *      But things like ReinitPostgres() get around this by just diddling
-        *      the PostgresIsInitialized flag.
-        * ----------------
-        */
-       AssertState(!PostgresIsInitialized);
-
-       /* ----------------
-        *      Memory system initialization.
-        *      (we may call palloc after EnableMemoryContext())
-        *
-        *      Note EnableMemoryContext() must happen before EnablePortalManager().
-        * ----------------
-        */
-       EnableMemoryContext(true);      /* initializes the "top context" */
-       EnablePortalManager(true);      /* memory for portal/transaction stuff */
-
        /* ----------------
         *      initialize the backend local portal stack used by
         *      internal PQ function calls.  see src/lib/libpq/be-dumpdata.c
@@ -528,14 +449,6 @@ InitPostgres(char *name)           /* database name */
         */
        be_portalinit();
 
-       /* ----------------
-        *       attach to shared memory and semaphores, and initialize our
-        *       input/output/debugging file descriptors.
-        * ----------------
-        */
-       InitCommunication();
-       InitStdio();
-
        /*
         * initialize the local buffer manager
         */
@@ -574,13 +487,9 @@ InitPostgres(char *name)           /* database name */
         * Will try that, but may not work... - thomas 1997-11-01
         */
 
-       /* Does not touch files (?) - thomas 1997-11-01 */
-       smgrinit();
-
-       /* ----------------
-        *      initialize the transaction system and the relation descriptor cache.
-        *      Note we have to make certain the lock manager is off while we do this.
-        * ----------------
+       /*
+        * Initialize the transaction system and the relation descriptor cache.
+        * Note we have to make certain the lock manager is off while we do this.
         */
        AmiTransactionOverride(IsBootstrapProcessingMode());
        LockDisable(true);
@@ -598,20 +507,18 @@ InitPostgres(char *name)          /* database name */
 
        LockDisable(false);
 
-       /* ----------------
+       /*
         * Set up my per-backend PROC struct in shared memory.
-        * ----------------
         */
        InitProcess(PostgresIpcKey);
 
-       /* ----------------
-        *      Initialize my entry in the shared-invalidation manager's
-        *      array of per-backend data.  (Formerly this came before
-        *      InitProcess, but now it must happen after, because it uses
-        *      MyProc.)  Once I have done this, I am visible to other backends!
+       /*
+        * Initialize my entry in the shared-invalidation manager's
+        * array of per-backend data.  (Formerly this came before
+        * InitProcess, but now it must happen after, because it uses
+        * MyProc.)  Once I have done this, I am visible to other backends!
         *
-        *      Sets up MyBackendId, a unique backend identifier.
-        * ----------------
+        * Sets up MyBackendId, a unique backend identifier.
         */
        InitSharedInvalidationState();
 
@@ -622,16 +529,14 @@ InitPostgres(char *name)          /* database name */
                         MyBackendId);
        }
 
-       /* ----------------
-        *      initialize the access methods.
-        *      Does not touch files (?) - thomas 1997-11-01
-        * ----------------
+       /*
+        * Initialize the access methods.
+        * Does not touch files (?) - thomas 1997-11-01
         */
        initam();
 
-       /* ----------------
-        *      initialize all the system catalog caches.
-        * ----------------
+       /*
+        * Initialize all the system catalog caches.
         */
        zerocaches();
 
@@ -641,34 +546,19 @@ InitPostgres(char *name)          /* database name */
         */
        InitCatalogCache();
 
-       /* ----------------
-        *       set ourselves to the proper user id and figure out our postgres
-        *       user id.  If we ever add security so that we check for valid
-        *       postgres users, we might do it here.
-        * ----------------
+       /*
+        * Set ourselves to the proper user id and figure out our postgres
+        * user id.  If we ever add security so that we check for valid
+        * postgres users, we might do it here.
         */
        InitUserid();
 
-       /* ----------------
-        *       initialize local data in cache invalidation stuff
-        * ----------------
+       /*
+        * Initialize local data in cache invalidation stuff
         */
        if (!bootstrap)
                InitLocalInvalidateData();
 
-       /* ----------------
-        *      ok, all done, now let's make sure we don't do it again.
-        * ----------------
-        */
-       PostgresIsInitialized = true;
-
-       /* ----------------
-        *      Done with "InitPostgres", now change to NormalProcessing unless
-        *      we're in BootstrapProcessing mode.
-        * ----------------
-        */
-       if (!bootstrap)
-               SetProcessingMode(NormalProcessing);
        if (lockingOff)
                LockDisable(true);
 
@@ -680,3 +570,30 @@ InitPostgres(char *name)           /* database name */
        if (!bootstrap)
                ReverifyMyDatabase(name);
 }
+
+void
+BaseInit(void)
+{
+
+       /*
+        * Turn on the exception handler. Note: we cannot use elog, Assert,
+        * AssertState, etc. until after exception handling is on.
+        */
+       EnableExceptionHandling(true);
+
+       /*
+        * Memory system initialization - we may call palloc after 
+        * EnableMemoryContext()).      Note that EnableMemoryContext() 
+        * must happen before EnablePortalManager().
+        */
+       EnableMemoryContext(true);      /* initializes the "top context" */
+       EnablePortalManager(true);      /* memory for portal/transaction stuff */
+
+       /*
+        * Attach to shared memory and semaphores, and initialize our
+        * input/output/debugging file descriptors.
+        */
+       InitCommunication();
+       DebugFileOpen();
+       smgrinit();
+}
index 3c2a9c71e8c4046e0b1bdc1630f4a1a35ff4aa82..97080e010f9554edd1bfda3b5b4351a766409900 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.31 1999/07/15 22:40:15 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.32 1999/10/06 21:58:11 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,8 +18,6 @@
 
 #include "utils/tqual.h"
 
-extern bool PostgresIsInitialized;
-
 SnapshotData SnapshotDirtyData;
 Snapshot       SnapshotDirty = &SnapshotDirtyData;
 
@@ -194,17 +192,6 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
        if (AMI_OVERRIDE)
                return true;
 
-       /*
-        * If the transaction system isn't yet initialized, then we assume
-        * that transactions committed.  We only look at system catalogs
-        * during startup, so this is less awful than it seems, but it's still
-        * pretty awful.
-        */
-
-       if (!PostgresIsInitialized)
-               return ((bool) (TransactionIdIsValid(tuple->t_xmin) &&
-                                               !TransactionIdIsValid(tuple->t_xmax)));
-
        if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
        {
                if (tuple->t_infomask & HEAP_XMIN_INVALID)
index 139c967b05cb5d5b0203dc6dd1fb1d0065649d2d..63733a5f7eafeac1099d6be9e476d90eb0861dc2 100644 (file)
@@ -26,7 +26,7 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.60 1999/05/20 16:50:06 wieck Exp $
+#    $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.61 1999/10/06 21:58:12 vadim Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -300,6 +300,12 @@ else
         mkdir $PGDATA/base
         if [ $? -ne 0 ]; then exit 5; fi
     fi
+    if [ ! -d $PGDATA/pg_xlog ]; then
+        echo "Creating Postgres database XLOG directory $PGDATA/pg_xlog"
+        echo
+        mkdir $PGDATA/pg_xlog
+        if [ $? -ne 0 ]; then exit 5; fi
+    fi
 fi
 
 #----------------------------------------------------------------------------
@@ -316,6 +322,7 @@ else
 fi
 
 BACKENDARGS="-boot -C -F -D$PGDATA $BACKEND_TALK_ARG"
+FIRSTRUN="-boot -x -C -F -D$PGDATA $BACKEND_TALK_ARG"
 
 echo "Creating template database in $PGDATA/base/template1"
 [ "$debug" -ne 0 ] && echo "Running: postgres $BACKENDARGS template1"
@@ -323,7 +330,7 @@ echo "Creating template database in $PGDATA/base/template1"
 cat $TEMPLATE \
 | sed -e "s/postgres PGUID/$POSTGRES_SUPERUSERNAME $POSTGRES_SUPERUID/" \
       -e "s/PGUID/$POSTGRES_SUPERUID/" \
-| postgres $BACKENDARGS template1
+| postgres $FIRSTRUN template1
 
 if [ $? -ne 0 ]; then
     echo "$CMDNAME: could not create template database"
index 08da41d6524ee082ec43045e661f21c50dca9450..be521ffe8d4afb01fd22605ca8b824dab50b8875 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pqsignal.h,v 1.9 1999/02/13 23:21:36 momjian Exp $
+ * $Id: pqsignal.h,v 1.10 1999/10/06 21:58:16 vadim Exp $
  *
  * NOTES
  *       This shouldn't be in libpq, but the monitor and some other
 #ifndef PQSIGNAL_H
 #define PQSIGNAL_H
 
+#ifdef HAVE_SIGPROCMASK
+extern sigset_t                UnBlockSig,
+                                       BlockSig;
+#define        PG_INITMASK()   ( \
+                                                       sigemptyset(&UnBlockSig), \
+                                                       sigfillset(&BlockSig) \
+                                               )
+#define        PG_SETMASK(mask)        sigprocmask(SIG_SETMASK, mask, NULL)
+#else
+extern int                     UnBlockSig,
+                                       BlockSig;
+#define PG_INITMASK()  ( \
+                                                       UnBlockSig = 0, \
+                                                       BlockSig = sigmask(SIGHUP) | sigmask(SIGQUIT) | \
+                                                                               sigmask(SIGTERM) | sigmask(SIGALRM) | \
+                                                                               sigmask(SIGINT) | sigmask(SIGUSR1) | \
+                                                                               sigmask(SIGUSR2) | sigmask(SIGCHLD) | \
+                                                                               sigmask(SIGWINCH) | sigmask(SIGFPE) \
+                                               )
+#define        PG_SETMASK(mask)        sigsetmask(*((int*)(mask)))
+#endif
+
 typedef void (*pqsigfunc) (int);
 
 extern pqsigfunc pqsignal(int signo, pqsigfunc func);
index 12eb3f87bae754a5cb85395cb2ce8e8f8ab2b940..9faaac1bde7afd6ff36026ed39ff990f914395c7 100644 (file)
@@ -11,7 +11,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: miscadmin.h,v 1.42 1999/09/27 20:27:26 momjian Exp $
+ * $Id: miscadmin.h,v 1.43 1999/10/06 21:58:13 vadim Exp $
  *
  * NOTES
  *       some of the information in this file will be moved to
@@ -143,28 +143,25 @@ extern int        CheckPathAccess(char *path, char *name, int open_mode);
  *****************************************************************************/
 /*
  * Description:
- *             There are four processing modes in POSTGRES.  They are NoProcessing
- * or "none," BootstrapProcessing or "bootstrap," InitProcessing or
+ *             There are three processing modes in POSTGRES.  They are 
+ * "BootstrapProcessing or "bootstrap," InitProcessing or
  * "initialization," and NormalProcessing or "normal."
  *
- *             If a POSTGRES binary is in normal mode, then all code may be executed
- * normally.  In the none mode, only bookkeeping code may be called.  In
- * particular, access method calls may not occur in this mode since the
- * execution state is outside a transaction.
- *
- *             The final two processing modes are used during special times.  When the
+ * The first two processing modes are used during special times. When the
  * system state indicates bootstrap processing, transactions are all given
- * transaction id "one" and are consequently guarenteed to commit.     This mode
+ * transaction id "one" and are consequently guarenteed to commit. This mode
  * is used during the initial generation of template databases.
  *
- * Finally, the execution state is in initialization mode until all normal
- * initialization is complete. Some code behaves differently when executed in
- * this mode to enable system bootstrapping.
+ * Initialization mode until all normal initialization is complete.    
+ * Some code behaves differently when executed in this mode to enable 
+ * system bootstrapping.
+ *
+ * If a POSTGRES binary is in normal mode, then all code may be executed
+ * normally. 
  */
 
 typedef enum ProcessingMode
 {
-       NoProcessing,                           /* "nothing" can be done */
        BootstrapProcessing,            /* bootstrap creation of template database */
        InitProcessing,                         /* initializing system */
        NormalProcessing                        /* normal processing */
index 8ae09e1990500226bb2502d7e51b9e08be3a6bfa..a123448e2a5ca40d11a2a0f204657802c8346bc1 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: ipc.h,v 1.35 1999/07/15 23:04:10 momjian Exp $
+ * $Id: ipc.h,v 1.36 1999/10/06 21:58:17 vadim Exp $
  *
  * NOTES
  *       This file is very architecture-specific.      This stuff should actually
@@ -79,7 +79,7 @@ extern void on_exit_reset(void);
 
 extern IpcSemaphoreId IpcSemaphoreCreate(IpcSemaphoreKey semKey,
                                   int semNum, int permission, int semStartValue,
-                                  int removeOnExit, int *status);
+                                  int removeOnExit);
 extern void IpcSemaphoreKill(IpcSemaphoreKey key);
 extern void IpcSemaphoreLock(IpcSemaphoreId semId, int sem, int lock);
 extern void IpcSemaphoreUnlock(IpcSemaphoreId semId, int sem, int lock);
@@ -105,6 +105,8 @@ typedef enum _LockId_
        BUFMGRLOCKID,
        LOCKLOCKID,
        OIDGENLOCKID,
+       XIDGENLOCKID,
+       CNTLFILELOCKID,
        SHMEMLOCKID,
        SHMEMINDEXLOCKID,
        LOCKMGRLOCKID,
@@ -147,6 +149,8 @@ typedef enum _LockId_
 
        PROCSTRUCTLOCKID,
        OIDGENLOCKID,
+       XIDGENLOCKID,
+       CNTLFILELOCKID,
        FIRSTFREELOCKID
 } _LockId_;
 
index be976c16b23590d679db977f7297eb44d0a28b2b..858f6e791fe70d316a7cf05795f72889e13b8b77 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: spin.h,v 1.9 1999/07/15 23:04:16 momjian Exp $
+ * $Id: spin.h,v 1.10 1999/10/06 21:58:17 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,8 +27,8 @@
 
 typedef int SPINLOCK;
 
-extern bool CreateSpinlocks(IPCKey key);
-extern bool InitSpinLocks(int init, IPCKey key);
+extern void CreateSpinlocks(IPCKey key);
+extern void InitSpinLocks(void);
 extern void SpinAcquire(SPINLOCK lockid);
 extern void SpinRelease(SPINLOCK lockid);
 
index d0351a5f958b3f7f79b84510fe3794eb379b87bf..65bad2234e33f8b66a11928e36c87b96a72c3842 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: tcopprot.h,v 1.21 1999/05/26 12:56:58 momjian Exp $
+ * $Id: tcopprot.h,v 1.22 1999/10/06 21:58:18 vadim Exp $
  *
  * OLD COMMENTS
  *       This file was created so that other c files could get the two
@@ -38,6 +38,7 @@
 #endif
 extern DLLIMPORT sigjmp_buf Warn_restart;
 extern bool InError;
+extern bool    ExitAfterAbort;
 
 #ifndef BOOTSTRAP_INCLUDE
 extern List *pg_parse_and_plan(char *query_string, Oid *typev, int nargs,