diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2001-08-26 16:56:03 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2001-08-26 16:56:03 +0000 |
| commit | bc7d37a525c02f4a0e983854c4222e9d063eeae2 (patch) | |
| tree | 46d1ff8c74eb0a6cec5c183732410a1b846fc5ba /src/backend/access | |
| parent | d1ee78f2962f09f0fe7c6c8ee16ad513ac113ba4 (diff) | |
| download | postgresql-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.c | 22 | ||||
| -rw-r--r-- | src/backend/access/transam/transam.c | 67 | ||||
| -rw-r--r-- | src/backend/access/transam/xid.c | 47 |
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)); +} |
