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.c65
1 files changed, 60 insertions, 5 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f384bbbe716..48e8b425dee 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.188 2005/04/23 18:49:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.189 2005/04/28 21:47:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,6 +23,7 @@
#include <sys/time.h>
#include "access/clog.h"
+#include "access/multixact.h"
#include "access/subtrans.h"
#include "access/xact.h"
#include "access/xlog.h"
@@ -3534,11 +3535,13 @@ BootStrapXLOG(void)
checkPoint.ThisTimeLineID = ThisTimeLineID;
checkPoint.nextXid = FirstNormalTransactionId;
checkPoint.nextOid = FirstBootstrapObjectId;
+ checkPoint.nextMulti = FirstMultiXactId;
checkPoint.time = time(NULL);
ShmemVariableCache->nextXid = checkPoint.nextXid;
ShmemVariableCache->nextOid = checkPoint.nextOid;
ShmemVariableCache->oidCount = 0;
+ MultiXactSetNextMXact(checkPoint.nextMulti);
/* Set up the XLOG page header */
page->xlp_magic = XLOG_PAGE_MAGIC;
@@ -3613,6 +3616,7 @@ BootStrapXLOG(void)
/* Bootstrap the commit log, too */
BootStrapCLOG();
BootStrapSUBTRANS();
+ BootStrapMultiXact();
}
static char *
@@ -4187,8 +4191,8 @@ StartupXLOG(void)
checkPoint.undo.xlogid, checkPoint.undo.xrecoff,
wasShutdown ? "TRUE" : "FALSE")));
ereport(LOG,
- (errmsg("next transaction ID: %u; next OID: %u",
- checkPoint.nextXid, checkPoint.nextOid)));
+ (errmsg("next transaction ID: %u; next OID: %u; next MultiXactId: %u",
+ checkPoint.nextXid, checkPoint.nextOid, checkPoint.nextMulti)));
if (!TransactionIdIsNormal(checkPoint.nextXid))
ereport(PANIC,
(errmsg("invalid next transaction ID")));
@@ -4196,6 +4200,7 @@ StartupXLOG(void)
ShmemVariableCache->nextXid = checkPoint.nextXid;
ShmemVariableCache->nextOid = checkPoint.nextOid;
ShmemVariableCache->oidCount = 0;
+ MultiXactSetNextMXact(checkPoint.nextMulti);
/*
* We must replay WAL entries using the same TimeLineID they were
@@ -4546,9 +4551,10 @@ StartupXLOG(void)
ControlFile->time = time(NULL);
UpdateControlFile();
- /* Start up the commit log, too */
+ /* Start up the commit log and related stuff, too */
StartupCLOG();
StartupSUBTRANS();
+ StartupMultiXact();
ereport(LOG,
(errmsg("database system is ready")));
@@ -4737,6 +4743,7 @@ ShutdownXLOG(int code, Datum arg)
CreateCheckPoint(true, true);
ShutdownCLOG();
ShutdownSUBTRANS();
+ ShutdownMultiXact();
CritSectionCount--;
ereport(LOG,
@@ -4919,6 +4926,8 @@ CreateCheckPoint(bool shutdown, bool force)
checkPoint.nextOid += ShmemVariableCache->oidCount;
LWLockRelease(OidGenLock);
+ checkPoint.nextMulti = MultiXactGetCheckptMulti(shutdown);
+
/*
* Having constructed the checkpoint record, ensure all shmem disk
* buffers and commit-log buffers are flushed to disk.
@@ -4938,6 +4947,7 @@ CreateCheckPoint(bool shutdown, bool force)
CheckPointCLOG();
CheckPointSUBTRANS();
+ CheckPointMultiXact();
FlushBufferPool();
START_CRIT_SECTION();
@@ -5054,6 +5064,33 @@ XLogPutNextOid(Oid nextOid)
rdata.len = sizeof(Oid);
rdata.next = NULL;
(void) XLogInsert(RM_XLOG_ID, XLOG_NEXTOID, &rdata);
+ /*
+ * We need not flush the NEXTOID record immediately, because any of the
+ * just-allocated OIDs could only reach disk as part of a tuple insert
+ * or update that would have its own XLOG record that must follow the
+ * NEXTOID record. Therefore, the standard buffer LSN interlock applied
+ * to those records will ensure no such OID reaches disk before the
+ * NEXTOID record does.
+ */
+}
+
+/*
+ * Write a NEXT_MULTIXACT log record
+ */
+void
+XLogPutNextMultiXactId(MultiXactId nextMulti)
+{
+ XLogRecData rdata;
+
+ rdata.buffer = InvalidBuffer;
+ rdata.data = (char *) (&nextMulti);
+ rdata.len = sizeof(MultiXactId);
+ rdata.next = NULL;
+ (void) XLogInsert(RM_XLOG_ID, XLOG_NEXTMULTI, &rdata);
+ /*
+ * We do not flush here either; this assumes that heap_lock_tuple() will
+ * always generate a WAL record. See notes therein.
+ */
}
/*
@@ -5075,6 +5112,14 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
ShmemVariableCache->oidCount = 0;
}
}
+ else if (info == XLOG_NEXTMULTI)
+ {
+ MultiXactId nextMulti;
+
+ memcpy(&nextMulti, XLogRecGetData(record), sizeof(MultiXactId));
+
+ MultiXactAdvanceNextMXact(nextMulti);
+ }
else if (info == XLOG_CHECKPOINT_SHUTDOWN)
{
CheckPoint checkPoint;
@@ -5084,6 +5129,7 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
ShmemVariableCache->nextXid = checkPoint.nextXid;
ShmemVariableCache->nextOid = checkPoint.nextOid;
ShmemVariableCache->oidCount = 0;
+ MultiXactSetNextMXact(checkPoint.nextMulti);
/*
* TLI may change in a shutdown checkpoint, but it shouldn't
@@ -5115,6 +5161,7 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
ShmemVariableCache->nextOid = checkPoint.nextOid;
ShmemVariableCache->oidCount = 0;
}
+ MultiXactAdvanceNextMXact(checkPoint.nextMulti);
/* TLI should not change in an on-line checkpoint */
if (checkPoint.ThisTimeLineID != ThisTimeLineID)
ereport(PANIC,
@@ -5139,11 +5186,12 @@ xlog_desc(char *buf, uint8 xl_info, char *rec)
CheckPoint *checkpoint = (CheckPoint *) rec;
sprintf(buf + strlen(buf), "checkpoint: redo %X/%X; undo %X/%X; "
- "tli %u; xid %u; oid %u; %s",
+ "tli %u; xid %u; oid %u; multi %u; %s",
checkpoint->redo.xlogid, checkpoint->redo.xrecoff,
checkpoint->undo.xlogid, checkpoint->undo.xrecoff,
checkpoint->ThisTimeLineID, checkpoint->nextXid,
checkpoint->nextOid,
+ checkpoint->nextMulti,
(info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
}
else if (info == XLOG_NEXTOID)
@@ -5153,6 +5201,13 @@ xlog_desc(char *buf, uint8 xl_info, char *rec)
memcpy(&nextOid, rec, sizeof(Oid));
sprintf(buf + strlen(buf), "nextOid: %u", nextOid);
}
+ else if (info == XLOG_NEXTMULTI)
+ {
+ MultiXactId multi;
+
+ memcpy(&multi, rec, sizeof(MultiXactId));
+ sprintf(buf + strlen(buf), "nextMultiXact: %u", multi);
+ }
else
strcat(buf, "UNKNOWN");
}