From 47937403676d913c0e740eec6b85113865c6c8ab Mon Sep 17 00:00:00 2001
From: "Vadim B. Mikheev" <vadim4o@yahoo.com>
Date: Wed, 6 Oct 1999 21:58:18 +0000
Subject: [PATCH] XLOG (also known as WAL -:)) Bootstrap/Startup/Shutdown.
 First step in cleaning up backend initialization code. Fix for FATAL: now
 FATAL is ERROR + exit.

---
 src/backend/access/transam/xlog.c     | 826 ++++++++++++++------------
 src/backend/bootstrap/bootstrap.c     |  85 ++-
 src/backend/postmaster/postmaster.c   | 521 ++++++++++------
 src/backend/storage/buffer/buf_init.c |  12 +-
 src/backend/storage/ipc/ipc.c         |  39 +-
 src/backend/storage/ipc/ipci.c        |  17 +-
 src/backend/storage/ipc/shmem.c       |   5 +-
 src/backend/storage/ipc/spin.c        |  91 +--
 src/backend/storage/lmgr/proc.c       |  36 +-
 src/backend/tcop/postgres.c           | 226 +++----
 src/backend/utils/error/elog.c        |  47 +-
 src/backend/utils/init/miscinit.c     |  23 +-
 src/backend/utils/init/postinit.c     | 189 ++----
 src/backend/utils/time/tqual.c        |  15 +-
 src/bin/initdb/initdb.sh              |  11 +-
 src/include/libpq/pqsignal.h          |  24 +-
 src/include/miscadmin.h               |  25 +-
 src/include/storage/ipc.h             |   8 +-
 src/include/storage/spin.h            |   6 +-
 src/include/tcop/tcopprot.h           |   3 +-
 20 files changed, 1176 insertions(+), 1033 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 2a7d60d3aac..09605cf9476 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -14,12 +14,14 @@
 
 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");
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index c20a63fc6dc..8871e14835a 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,6 +39,14 @@
 #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;
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 78d8bc5e30b..bb6d5b638eb 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -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"
@@ -98,10 +99,13 @@
 #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);
+}
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index bfd05617053..3fe2ec8be6e 100644
--- a/src/backend/storage/buffer/buf_init.c
+++ b/src/backend/storage/buffer/buf_init.c
@@ -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));
diff --git a/src/backend/storage/ipc/ipc.c b/src/backend/storage/ipc/ipc.c
index 59c991bd0a7..ff326becf1e 100644
--- a/src/backend/storage/ipc/ipc.c
+++ b/src/backend/storage/ipc/ipc.c
@@ -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
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index 16c5266c6cd..259a1f532c9 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -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);
 
 	/* ----------------
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index c23952c1910..e76829ec7c9 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -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
diff --git a/src/backend/storage/ipc/spin.c b/src/backend/storage/ipc/spin.c
index 4d9bd3f71b4..700f5bfaf6d 100644
--- a/src/backend/storage/ipc/spin.c
+++ b/src/backend/storage/ipc/spin.c
@@ -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 */
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 159edf0549b..0270b0e1165 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.61 1999/09/24 00:24:41 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.62 1999/10/06 21:58:07 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,7 +46,7 @@
  *		This is so that we can support more backends. (system-wide semaphore
  *		sets run out pretty fast.)				  -ay 4/95
  *
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.61 1999/09/24 00:24:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.62 1999/10/06 21:58:07 vadim Exp $
  */
 #include <sys/time.h>
 #include <unistd.h>
@@ -70,7 +70,7 @@
 #include "storage/proc.h"
 #include "utils/trace.h"
 
-static void HandleDeadLock(int sig);
+void HandleDeadLock(SIGNAL_ARGS);
 static void ProcFreeAllSemaphores(void);
 
 #define DeadlockCheckTimer pg_options[OPT_DEADLOCKTIMEOUT]
@@ -84,12 +84,6 @@ static void ProcFreeAllSemaphores(void);
  */
 SPINLOCK	ProcStructLock;
 
-/*
- * For cleanup routines.  Don't cleanup if the initialization
- * has not happened.
- */
-static bool ProcInitialized = FALSE;
-
 static PROC_HDR *ProcGlobal = NULL;
 
 PROC	   *MyProc = NULL;
@@ -167,8 +161,9 @@ InitProcGlobal(IPCKey key, int maxBackends)
 										   PROC_NSEMS_PER_SET,
 										   IPCProtection,
 										   IpcSemaphoreDefaultStartValue,
-										   0,
-										   &semstat);
+										   0);
+				if (semId < 0)
+					elog(FATAL, "InitProcGlobal: IpcSemaphoreCreate failed");
 				/* mark this sema set allocated */
 				ProcGlobal->freeSemMap[i] = (1 << PROC_NSEMS_PER_SET);
 			}
@@ -189,12 +184,6 @@ InitProcess(IPCKey key)
 	unsigned long location,
 				myOffset;
 
-	/* ------------------
-	 * Routine called if deadlock timer goes off. See ProcSleep()
-	 * ------------------
-	 */
-	pqsignal(SIGALRM, HandleDeadLock);
-
 	SpinAcquire(ProcStructLock);
 
 	/* attach to the free list */
@@ -203,7 +192,7 @@ InitProcess(IPCKey key)
 	if (!found)
 	{
 		/* this should not happen. InitProcGlobal() is called before this. */
-		elog(ERROR, "InitProcess: Proc Header uninitialized");
+		elog(STOP, "InitProcess: Proc Header uninitialized");
 	}
 
 	if (MyProc != NULL)
@@ -271,8 +260,7 @@ InitProcess(IPCKey key)
 								   PROC_NSEMS_PER_SET,
 								   IPCProtection,
 								   IpcSemaphoreDefaultStartValue,
-								   0,
-								   &semstat);
+								   0);
 
 		/*
 		 * we might be reusing a semaphore that belongs to a dead backend.
@@ -316,14 +304,12 @@ InitProcess(IPCKey key)
 	 */
 	location = MAKE_OFFSET(MyProc);
 	if ((!ShmemPIDLookup(MyProcPid, &location)) || (location != MAKE_OFFSET(MyProc)))
-		elog(FATAL, "InitProc: ShmemPID table broken");
+		elog(STOP, "InitProc: ShmemPID table broken");
 
 	MyProc->errType = NO_ERROR;
 	SHMQueueElemInit(&(MyProc->links));
 
 	on_shmem_exit(ProcKill, (caddr_t) MyProcPid);
-
-	ProcInitialized = TRUE;
 }
 
 /*
@@ -755,8 +741,8 @@ ProcAddLock(SHM_QUEUE *elem)
  * up my semaphore.
  * --------------------
  */
-static void
-HandleDeadLock(int sig)
+void
+HandleDeadLock(SIGNAL_ARGS)
 {
 	LOCK	   *mywaitlock;
 
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2a3e7e77300..29486bd6f39 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -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"
@@ -98,11 +99,20 @@
  */
 
 /*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;
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 11cf762e7d6..342a1029d16 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -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);
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 88baaf4a891..11ac3580260 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -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;
 }
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 1285c23e843..20db5c34bb7 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -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
@@ -53,12 +53,13 @@
 #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();
+}
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index 3c2a9c71e8c..97080e010f9 100644
--- a/src/backend/utils/time/tqual.c
+++ b/src/backend/utils/time/tqual.c
@@ -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)
diff --git a/src/bin/initdb/initdb.sh b/src/bin/initdb/initdb.sh
index 139c967b05c..63733a5f7ea 100644
--- a/src/bin/initdb/initdb.sh
+++ b/src/bin/initdb/initdb.sh
@@ -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"
diff --git a/src/include/libpq/pqsignal.h b/src/include/libpq/pqsignal.h
index 08da41d6524..be521ffe8d4 100644
--- a/src/include/libpq/pqsignal.h
+++ b/src/include/libpq/pqsignal.h
@@ -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
@@ -17,6 +17,28 @@
 #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);
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 12eb3f87bae..9faaac1bde7 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -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 */
diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h
index 8ae09e19905..a123448e2a5 100644
--- a/src/include/storage/ipc.h
+++ b/src/include/storage/ipc.h
@@ -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_;
 
diff --git a/src/include/storage/spin.h b/src/include/storage/spin.h
index be976c16b23..858f6e791fe 100644
--- a/src/include/storage/spin.h
+++ b/src/include/storage/spin.h
@@ -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);
 
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index d0351a5f958..65bad2234e3 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -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,
-- 
GitLab