XLOG (also known as WAL -:)) Bootstrap/Startup/Shutdown.
authorVadim B. Mikheev
Wed, 6 Oct 1999 21:58:18 +0000 (21:58 +0000)
committerVadim B. Mikheev
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 
 #include 
@@ -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,