aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r--src/backend/access/transam/xlog.c181
1 files changed, 149 insertions, 32 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 8c3cd117cb9..bae7af83c38 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.18 2000/10/20 11:01:04 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.19 2000/10/21 15:43:22 vadim Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,6 +27,8 @@
#include "storage/spin.h"
#include "storage/s_lock.h"
+#include "miscadmin.h"
+
void UpdateControlFile(void);
int XLOGShmemSize(void);
void XLOGShmemInit(void);
@@ -41,6 +43,9 @@ uint32 XLOGbuffers = 0;
XLogRecPtr MyLastRecPtr = {0, 0};
bool StopIfError = false;
bool InRecovery = false;
+StartUpID ThisStartUpID = 0;
+
+int XLOG_DEBUG = 1;
SPINLOCK ControlFileLockId;
SPINLOCK XidGenLockId;
@@ -93,6 +98,7 @@ typedef struct XLogCtlData
XLogRecPtr *xlblocks; /* 1st byte ptr-s + BLCKSZ */
uint32 XLogCacheByte;
uint32 XLogCacheBlck;
+ StartUpID ThisStartUpID;
#ifdef HAS_TEST_AND_SET
slock_t insert_lck;
slock_t info_lck;
@@ -137,16 +143,20 @@ static ControlFileData *ControlFile = NULL;
typedef struct CheckPoint
{
- XLogRecPtr redo; /* next RecPtr available when we */
- /* began to create CheckPoint */
- /* (i.e. REDO start point) */
- XLogRecPtr undo; /* first record of oldest in-progress */
- /* transaction when we started */
- /* (i.e. UNDO end point) */
- TransactionId nextXid;
- Oid nextOid;
+ XLogRecPtr redo; /* next RecPtr available when we */
+ /* began to create CheckPoint */
+ /* (i.e. REDO start point) */
+ XLogRecPtr undo; /* first record of oldest in-progress */
+ /* transaction when we started */
+ /* (i.e. UNDO end point) */
+ StartUpID ThisStartUpID;
+ TransactionId nextXid;
+ Oid nextOid;
+ bool Shutdown;
} CheckPoint;
+#define XLOG_CHECKPOINT 0x00
+
/*
* We break each log file in 16Mb segments
*/
@@ -190,6 +200,7 @@ 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 void xlog_outrec(char *buf, XLogRecord *record);
static XLgwrResult LgwrResult = {{0, 0}, {0, 0}};
static XLgwrRqst LgwrRqst = {{0, 0}, {0, 0}};
@@ -225,6 +236,13 @@ XLogInsert(RmgrId rmid, uint8 info, char *hdr, uint32 hdrlen, char *buf, uint32
if (len == 0 || len > MAXLOGRECSZ)
elog(STOP, "XLogInsert: invalid record len %u", len);
+ if (IsBootstrapProcessingMode())
+ {
+ RecPtr.xlogid = 0;
+ RecPtr.xrecoff = SizeOfXLogPHD; /* start of 1st checkpoint record */
+ return (RecPtr);
+ }
+
/* obtain xlog insert lock */
if (TAS(&(XLogCtl->insert_lck))) /* busy */
{
@@ -310,6 +328,23 @@ XLogInsert(RmgrId rmid, uint8 info, char *hdr, uint32 hdrlen, char *buf, uint32
MyProc->logRec = RecPtr;
SpinRelease(SInvalLock);
}
+ Insert->PrevRecord = RecPtr;
+
+ if (XLOG_DEBUG)
+ {
+ char buf[8192];
+
+ sprintf(buf, "INSERT @ %u/%u: ", RecPtr.xlogid, RecPtr.xrecoff);
+ xlog_outrec(buf, record);
+ if (hdr != NULL)
+ {
+ strcat(buf, " - ");
+ RmgrTable[record->xl_rmid].rm_desc(buf, record->xl_info, hdr);
+ }
+ strcat(buf, "\n");
+ write(2, buf, strlen(buf));
+ }
+
MyLastRecPtr = RecPtr; /* begin of record */
Insert->currpos += SizeOfXLogRecord;
if (freespace > 0)
@@ -330,7 +365,7 @@ XLogInsert(RmgrId rmid, uint8 info, char *hdr, uint32 hdrlen, char *buf, uint32
Insert->currpos += wlen;
}
Insert->currpos = ((char *) Insert->currpage) +
- DOUBLEALIGN(Insert->currpos - ((char *) Insert->currpage));
+ MAXALIGN(Insert->currpos - ((char *) Insert->currpage));
len = hdrlen + buflen;
}
@@ -391,7 +426,7 @@ nbuf:
/* we don't store info in subrecord' xl_info */
subrecord->xl_info = 0;
Insert->currpos = ((char *) Insert->currpage) +
- DOUBLEALIGN(Insert->currpos - ((char *) Insert->currpage));
+ MAXALIGN(Insert->currpos - ((char *) Insert->currpage));
}
freespace = ((char *) Insert->currpage) + BLCKSZ - Insert->currpos;
@@ -738,7 +773,7 @@ XLogFileInit(uint32 log, uint32 seg)
fd = BasicOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, S_IRUSR | S_IWUSR);
if (fd < 0)
- elog(STOP, "Open(logfile %u seg %u) failed: %d",
+ elog(STOP, "Init(logfile %u seg %u) failed: %d",
logId, logSeg, errno);
if (lseek(fd, XLogSegSize - 1, SEEK_SET) != (off_t) (XLogSegSize - 1))
@@ -777,6 +812,7 @@ XLogFileOpen(uint32 log, uint32 seg, bool econt)
logId, logSeg);
return (fd);
}
+ abort();
elog(STOP, "Open(logfile %u seg %u) failed: %d",
logId, logSeg, errno);
}
@@ -876,7 +912,7 @@ got_record:;
XLogSubRecord *subrecord;
uint32 len = record->xl_len;
- if (DOUBLEALIGN(record->xl_len) + RecPtr->xrecoff % BLCKSZ +
+ if (MAXALIGN(record->xl_len) + RecPtr->xrecoff % BLCKSZ +
SizeOfXLogRecord != BLCKSZ)
{
elog(emode, "ReadRecord: invalid fragmented record len %u in (%u, %u)",
@@ -938,7 +974,7 @@ got_record:;
buffer += subrecord->xl_len;
if (subrecord->xl_info & XLR_TO_BE_CONTINUED)
{
- if (DOUBLEALIGN(subrecord->xl_len) +
+ if (MAXALIGN(subrecord->xl_len) +
SizeOfXLogPHD + SizeOfXLogSubRecord != BLCKSZ)
{
elog(emode, "ReadRecord: invalid fragmented subrecord len %u in logfile %u seg %u off %u",
@@ -949,26 +985,26 @@ got_record:;
}
break;
}
- if (BLCKSZ - SizeOfXLogRecord >= DOUBLEALIGN(subrecord->xl_len) +
+ if (BLCKSZ - SizeOfXLogRecord >= MAXALIGN(subrecord->xl_len) +
SizeOfXLogPHD + SizeOfXLogSubRecord)
{
nextRecord = (XLogRecord *) ((char *) subrecord +
- DOUBLEALIGN(subrecord->xl_len) + SizeOfXLogSubRecord);
+ MAXALIGN(subrecord->xl_len) + SizeOfXLogSubRecord);
}
EndRecPtr.xlogid = readId;
EndRecPtr.xrecoff = readSeg * XLogSegSize + readOff * BLCKSZ +
SizeOfXLogPHD + SizeOfXLogSubRecord +
- DOUBLEALIGN(subrecord->xl_len);
+ MAXALIGN(subrecord->xl_len);
ReadRecPtr = *RecPtr;
return (record);
}
- if (BLCKSZ - SizeOfXLogRecord >= DOUBLEALIGN(record->xl_len) +
+ if (BLCKSZ - SizeOfXLogRecord >= MAXALIGN(record->xl_len) +
RecPtr->xrecoff % BLCKSZ + SizeOfXLogRecord)
nextRecord = (XLogRecord *) ((char *) record +
- DOUBLEALIGN(record->xl_len) + SizeOfXLogRecord);
+ MAXALIGN(record->xl_len) + SizeOfXLogRecord);
EndRecPtr.xlogid = RecPtr->xlogid;
EndRecPtr.xrecoff = RecPtr->xrecoff +
- DOUBLEALIGN(record->xl_len) + SizeOfXLogRecord;
+ MAXALIGN(record->xl_len) + SizeOfXLogRecord;
ReadRecPtr = *RecPtr;
return (record);
@@ -1130,7 +1166,7 @@ BootStrapXLOG()
char buffer[BLCKSZ];
CheckPoint checkPoint;
-#ifdef NOT_USED
+#ifdef XLOG
XLogPageHeader page = (XLogPageHeader) buffer;
XLogRecord *record;
@@ -1146,8 +1182,9 @@ BootStrapXLOG()
checkPoint.undo = checkPoint.redo;
checkPoint.nextXid = FirstTransactionId;
checkPoint.nextOid = BootstrapObjectIdData;
+ checkPoint.ThisStartUpID = 0;
-#ifdef NOT_USED
+#ifdef XLOG
memset(buffer, 0, BLCKSZ);
page->xlp_magic = XLOG_PAGE_MAGIC;
@@ -1213,7 +1250,7 @@ str_time(time_t tnow)
void
StartupXLOG()
{
-#ifdef NOT_USED
+#ifdef XLOG
XLogCtlInsert *Insert;
CheckPoint checkPoint;
XLogRecPtr RecPtr,
@@ -1291,7 +1328,7 @@ StartupXLOG()
elog(LOG, "Data Base System was interrupted being in production at %s",
str_time(ControlFile->time));
-#ifdef NOT_USED
+#ifdef XLOG
LastRec = RecPtr = ControlFile->checkPoint;
if (!XRecOffIsValid(RecPtr.xrecoff))
@@ -1312,17 +1349,20 @@ StartupXLOG()
checkPoint.nextXid, checkPoint.nextOid);
if (checkPoint.nextXid < FirstTransactionId ||
checkPoint.nextOid < BootstrapObjectIdData)
-#ifdef XLOG
+
+#ifdef XLOG_2
elog(STOP, "Invalid NextTransactionId/NextOid");
#else
elog(LOG, "Invalid NextTransactionId/NextOid");
#endif
-#ifdef XLOG
+#ifdef XLOG_2
ShmemVariableCache->nextXid = checkPoint.nextXid;
ShmemVariableCache->nextOid = checkPoint.nextOid;
#endif
+ ThisStartUpID = checkPoint.ThisStartUpID;
+
if (XLByteLT(RecPtr, checkPoint.redo))
elog(STOP, "Invalid redo in checkPoint record");
if (checkPoint.undo.xrecoff == 0)
@@ -1364,10 +1404,23 @@ StartupXLOG()
ReadRecPtr.xlogid, ReadRecPtr.xrecoff);
do
{
-#ifdef XLOG
+#ifdef XLOG_2
if (record->xl_xid >= ShmemVariableCache->nextXid)
ShmemVariableCache->nextXid = record->xl_xid + 1;
#endif
+ if (XLOG_DEBUG)
+ {
+ char buf[8192];
+
+ sprintf(buf, "REDO @ %u/%u: ", ReadRecPtr.xlogid, ReadRecPtr.xrecoff);
+ xlog_outrec(buf, record);
+ strcat(buf, " - ");
+ RmgrTable[record->xl_rmid].rm_desc(buf,
+ record->xl_info, XLogRecGetData(record));
+ strcat(buf, "\n");
+ write(2, buf, strlen(buf));
+ }
+
RmgrTable[record->xl_rmid].rm_redo(EndRecPtr, record);
record = ReadRecord(NULL, buffer);
} while (record->xl_len != 0);
@@ -1422,6 +1475,7 @@ StartupXLOG()
if (recovery > 0)
{
+#ifdef NOT_USED
int i;
/*
@@ -1429,22 +1483,38 @@ StartupXLOG()
*/
for (i = 0; i <= RM_MAX_ID; i++)
RmgrTable[record->xl_rmid].rm_redo(ReadRecPtr, NULL);
+#endif
CreateCheckPoint(true);
StopIfError = sie_saved;
}
-#endif /* NOT_USED */
+#endif /* XLOG */
ControlFile->state = DB_IN_PRODUCTION;
ControlFile->time = time(NULL);
UpdateControlFile();
+ ThisStartUpID++;
+ XLogCtl->ThisStartUpID = ThisStartUpID;
+
elog(LOG, "Data Base System is in production state at %s", str_time(time(NULL)));
return;
}
/*
+ * Postmaster uses it to set ThisStartUpID from XLogCtlData
+ * located in shmem after successful startup.
+ */
+void SetThisStartUpID(void);
+
+void
+SetThisStartUpID(void)
+{
+ ThisStartUpID = XLogCtl->ThisStartUpID;
+}
+
+/*
* This func must be called ONCE on system shutdown
*/
void
@@ -1461,7 +1531,7 @@ ShutdownXLOG()
void
CreateCheckPoint(bool shutdown)
{
-#ifdef NOT_USED
+#ifdef XLOG
CheckPoint checkPoint;
XLogRecPtr recptr;
XLogCtlInsert *Insert = &XLogCtl->Insert;
@@ -1475,6 +1545,8 @@ CreateCheckPoint(bool shutdown)
ControlFile->time = time(NULL);
UpdateControlFile();
}
+ checkPoint.ThisStartUpID = ThisStartUpID;
+ checkPoint.Shutdown = shutdown;
/* Get REDO record ptr */
while (TAS(&(XLogCtl->insert_lck)))
@@ -1517,20 +1589,21 @@ CreateCheckPoint(bool shutdown)
if (shutdown && checkPoint.undo.xrecoff != 0)
elog(STOP, "Active transaction while data base is shutting down");
- recptr = XLogInsert(RM_XLOG_ID, (char *) &checkPoint, sizeof(checkPoint), NULL, 0);
+ recptr = XLogInsert(RM_XLOG_ID, XLOG_CHECKPOINT, (char *) &checkPoint,
+ sizeof(checkPoint), NULL, 0);
if (shutdown && !XLByteEQ(checkPoint.redo, MyLastRecPtr))
elog(STOP, "XLog concurrent activity while data base is shutting down");
XLogFlush(recptr);
-#endif /* NOT_USED */
+#endif /* XLOG */
SpinAcquire(ControlFileLockId);
if (shutdown)
ControlFile->state = DB_SHUTDOWNED;
-#ifdef NOT_USED
+#ifdef XLOG
ControlFile->checkPoint = MyLastRecPtr;
#else
ControlFile->checkPoint.xlogid = 0;
@@ -1543,3 +1616,47 @@ CreateCheckPoint(bool shutdown)
return;
}
+
+void xlog_redo(XLogRecPtr lsn, XLogRecord *record);
+void xlog_undo(XLogRecPtr lsn, XLogRecord *record);
+void xlog_desc(char *buf, uint8 xl_info, char* rec);
+
+void
+xlog_redo(XLogRecPtr lsn, XLogRecord *record)
+{
+}
+
+void
+xlog_undo(XLogRecPtr lsn, XLogRecord *record)
+{
+}
+
+void
+xlog_desc(char *buf, uint8 xl_info, char* rec)
+{
+ uint8 info = xl_info & ~XLR_INFO_MASK;
+
+ if (info == XLOG_CHECKPOINT)
+ {
+ CheckPoint *checkpoint = (CheckPoint*) rec;
+ sprintf(buf + strlen(buf), "checkpoint: redo %u/%u; undo %u/%u; "
+ "sui %u; xid %u; oid %u; %s",
+ checkpoint->redo.xlogid, checkpoint->redo.xrecoff,
+ checkpoint->undo.xlogid, checkpoint->undo.xrecoff,
+ checkpoint->ThisStartUpID, checkpoint->nextXid,
+ checkpoint->nextOid,
+ (checkpoint->Shutdown) ? "shutdown" : "online");
+ }
+ else
+ strcat(buf, "UNKNOWN");
+}
+
+static void
+xlog_outrec(char *buf, XLogRecord *record)
+{
+ sprintf(buf + strlen(buf), "prev %u/%u; xprev %u/%u; xid %u: %s",
+ record->xl_prev.xlogid, record->xl_prev.xrecoff,
+ record->xl_xact_prev.xlogid, record->xl_xact_prev.xrecoff,
+ record->xl_xid,
+ RmgrTable[record->xl_rmid].rm_name);
+}