summaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2001-08-26 16:56:03 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2001-08-26 16:56:03 +0000
commitbc7d37a525c02f4a0e983854c4222e9d063eeae2 (patch)
tree46d1ff8c74eb0a6cec5c183732410a1b846fc5ba /src/backend/access
parentd1ee78f2962f09f0fe7c6c8ee16ad513ac113ba4 (diff)
downloadpostgresql-bc7d37a525c02f4a0e983854c4222e9d063eeae2.tar.gz
Transaction IDs wrap around, per my proposal of 13-Aug-01. More
documentation to come, but the code is all here. initdb forced.
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/transam/clog.c22
-rw-r--r--src/backend/access/transam/transam.c67
-rw-r--r--src/backend/access/transam/xid.c47
3 files changed, 111 insertions, 25 deletions
diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 07581e4444..a403838bd7 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/access/transam/clog.c,v 1.2 2001/08/25 23:24:39 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/clog.c,v 1.3 2001/08/26 16:55:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -762,8 +762,12 @@ ExtendCLOG(TransactionId newestXact)
{
int pageno;
- /* No work except at first XID of a page */
- if (TransactionIdToPgIndex(newestXact) != 0)
+ /*
+ * No work except at first XID of a page. But beware: just after
+ * wraparound, the first XID of page zero is FirstNormalTransactionId.
+ */
+ if (TransactionIdToPgIndex(newestXact) != 0 &&
+ !TransactionIdEquals(newestXact, FirstNormalTransactionId))
return;
pageno = TransactionIdToPage(newestXact);
@@ -818,6 +822,18 @@ TruncateCLOG(TransactionId oldestXact)
S_LOCK(&(ClogCtl->control_lck));
restart:;
+ /*
+ * While we are holding the lock, make an important safety check:
+ * the planned cutoff point must be <= the current CLOG endpoint page.
+ * Otherwise we have already wrapped around, and proceeding with the
+ * truncation would risk removing the current CLOG segment.
+ */
+ if (CLOGPagePrecedes(ClogCtl->latest_page_number, cutoffPage))
+ {
+ S_UNLOCK(&(ClogCtl->control_lck));
+ elog(LOG, "unable to truncate commit log: apparent wraparound");
+ return;
+ }
for (slotno = 0; slotno < NUM_CLOG_BUFFERS; slotno++)
{
diff --git a/src/backend/access/transam/transam.c b/src/backend/access/transam/transam.c
index 3364ed6633..2a73c045b7 100644
--- a/src/backend/access/transam/transam.c
+++ b/src/backend/access/transam/transam.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.47 2001/08/25 18:52:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.48 2001/08/26 16:55:59 tgl Exp $
*
* NOTES
* This file contains the high level access-method interface to the
@@ -236,3 +236,68 @@ TransactionIdAbort(TransactionId transactionId)
TransactionLogUpdate(transactionId, TRANSACTION_STATUS_ABORTED);
}
+
+
+/*
+ * TransactionIdPrecedes --- is id1 logically < id2?
+ */
+bool
+TransactionIdPrecedes(TransactionId id1, TransactionId id2)
+{
+ /*
+ * If either ID is a permanent XID then we can just do unsigned
+ * comparison. If both are normal, do a modulo-2^31 comparison.
+ */
+ int32 diff;
+
+ if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
+ return (id1 < id2);
+
+ diff = (int32) (id1 - id2);
+ return (diff < 0);
+}
+
+/*
+ * TransactionIdPrecedesOrEquals --- is id1 logically <= id2?
+ */
+bool
+TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
+{
+ int32 diff;
+
+ if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
+ return (id1 <= id2);
+
+ diff = (int32) (id1 - id2);
+ return (diff <= 0);
+}
+
+/*
+ * TransactionIdFollows --- is id1 logically > id2?
+ */
+bool
+TransactionIdFollows(TransactionId id1, TransactionId id2)
+{
+ int32 diff;
+
+ if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
+ return (id1 > id2);
+
+ diff = (int32) (id1 - id2);
+ return (diff > 0);
+}
+
+/*
+ * TransactionIdFollowsOrEquals --- is id1 logically >= id2?
+ */
+bool
+TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
+{
+ int32 diff;
+
+ if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
+ return (id1 >= id2);
+
+ diff = (int32) (id1 - id2);
+ return (diff >= 0);
+}
diff --git a/src/backend/access/transam/xid.c b/src/backend/access/transam/xid.c
index 689fc33cea..babe7c9a48 100644
--- a/src/backend/access/transam/xid.c
+++ b/src/backend/access/transam/xid.c
@@ -6,23 +6,18 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: xid.c,v 1.32 2001/08/23 23:06:37 tgl Exp $
- *
- * OLD COMMENTS
- * XXX WARNING
- * Much of this file will change when we change our representation
- * of transaction ids -cim 3/23/90
- *
- * It is time to make the switch from 5 byte to 4 byte transaction ids
- * This file was totally reworked. -mer 5/22/92
+ * $Id: xid.c,v 1.33 2001/08/26 16:55:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include <limits.h>
+
#include "access/xact.h"
+
#define PG_GETARG_TRANSACTIONID(n) DatumGetTransactionId(PG_GETARG_DATUM(n))
#define PG_RETURN_TRANSACTIONID(x) return TransactionIdGetDatum(x)
@@ -30,9 +25,9 @@
Datum
xidin(PG_FUNCTION_ARGS)
{
- char *representation = PG_GETARG_CSTRING(0);
+ char *str = PG_GETARG_CSTRING(0);
- PG_RETURN_TRANSACTIONID((TransactionId) atol(representation));
+ PG_RETURN_TRANSACTIONID((TransactionId) strtoul(str, NULL, 0));
}
Datum
@@ -40,21 +35,15 @@ xidout(PG_FUNCTION_ARGS)
{
TransactionId transactionId = PG_GETARG_TRANSACTIONID(0);
/* maximum 32 bit unsigned integer representation takes 10 chars */
- char *representation = palloc(11);
+ char *str = palloc(11);
- snprintf(representation, 11, "%lu", (unsigned long) transactionId);
+ snprintf(str, 11, "%lu", (unsigned long) transactionId);
- PG_RETURN_CSTRING(representation);
+ PG_RETURN_CSTRING(str);
}
-/* ----------------------------------------------------------------
- * xideq
- * ----------------------------------------------------------------
- */
-
/*
- * xideq - returns 1, iff xid1 == xid2
- * 0 else;
+ * xideq - are two xids equal?
*/
Datum
xideq(PG_FUNCTION_ARGS)
@@ -64,3 +53,19 @@ xideq(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(TransactionIdEquals(xid1, xid2));
}
+
+/*
+ * xid_age - compute age of an XID (relative to current xact)
+ */
+Datum
+xid_age(PG_FUNCTION_ARGS)
+{
+ TransactionId xid = PG_GETARG_TRANSACTIONID(0);
+ TransactionId now = GetCurrentTransactionId();
+
+ /* Permanent XIDs are always infinitely old */
+ if (! TransactionIdIsNormal(xid))
+ PG_RETURN_INT32(INT_MAX);
+
+ PG_RETURN_INT32((int32) (now - xid));
+}