aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/transam.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2001-08-25 18:52:43 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2001-08-25 18:52:43 +0000
commit2589735da08c4e597accb6eab5ae65b6339ee630 (patch)
tree829f7073292c6b55f86580863837441991638405 /src/backend/access/transam/transam.c
parent4699d81dc99ef1687e9396b57b0ed10f42699792 (diff)
downloadpostgresql-2589735da08c4e597accb6eab5ae65b6339ee630.tar.gz
postgresql-2589735da08c4e597accb6eab5ae65b6339ee630.zip
Replace implementation of pg_log as a relation accessed through the
buffer manager with 'pg_clog', a specialized access method modeled on pg_xlog. This simplifies startup (don't need to play games to open pg_log; among other things, OverrideTransactionSystem goes away), should improve performance a little, and opens the door to recycling commit log space by removing no-longer-needed segments of the commit log. Actual recycling is not there yet, but I felt I should commit this part separately since it'd still be useful if we chose not to do transaction ID wraparound.
Diffstat (limited to 'src/backend/access/transam/transam.c')
-rw-r--r--src/backend/access/transam/transam.c320
1 files changed, 42 insertions, 278 deletions
diff --git a/src/backend/access/transam/transam.c b/src/backend/access/transam/transam.c
index 65718b4cae9..3364ed66337 100644
--- a/src/backend/access/transam/transam.c
+++ b/src/backend/access/transam/transam.c
@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
* transam.c
- * postgres transaction log/time interface routines
+ * postgres transaction log interface routines
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.46 2001/08/23 23:06:37 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.47 2001/08/25 18:52:41 tgl Exp $
*
* NOTES
* This file contains the high level access-method interface to the
@@ -19,76 +19,27 @@
#include "postgres.h"
-#include "access/heapam.h"
+#include "access/clog.h"
#include "access/transam.h"
-#include "catalog/catname.h"
-#include "miscadmin.h"
-static int RecoveryCheckingEnabled(void);
-static void TransRecover(Relation logRelation);
static bool TransactionLogTest(TransactionId transactionId, XidStatus status);
static void TransactionLogUpdate(TransactionId transactionId,
XidStatus status);
/* ----------------
- * global variables holding pointers to relations used
- * by the transaction system. These are initialized by
- * InitializeTransactionLog().
- * ----------------
- */
-
-Relation LogRelation = (Relation) NULL;
-
-/* ----------------
* Single-item cache for results of TransactionLogTest.
* ----------------
*/
static TransactionId cachedTestXid = InvalidTransactionId;
static XidStatus cachedTestXidStatus;
-/* ----------------
- * transaction recovery state variables
- *
- * When the transaction system is initialized, we may
- * need to do recovery checking. This decision is decided
- * by the postmaster or the user by supplying the backend
- * with a special flag. In general, we want to do recovery
- * checking whenever we are running without a postmaster
- * or when the number of backends running under the postmaster
- * goes from zero to one. -cim 3/21/90
- * ----------------
- */
-static int RecoveryCheckingEnableState = 0;
-
-/* ----------------
- * recovery checking accessors
- * ----------------
- */
-static int
-RecoveryCheckingEnabled(void)
-{
- return RecoveryCheckingEnableState;
-}
-
-#ifdef NOT_USED
-static void
-SetRecoveryCheckingEnabled(bool state)
-{
- RecoveryCheckingEnableState = (state == true);
-}
-
-#endif
/* ----------------------------------------------------------------
* postgres log access method interface
*
* TransactionLogTest
* TransactionLogUpdate
- * ========
- * these functions do work for the interface
- * functions - they search/retrieve and append/update
- * information in the log and time relations.
* ----------------------------------------------------------------
*/
@@ -102,59 +53,42 @@ static bool /* true/false: does transaction id have
TransactionLogTest(TransactionId transactionId, /* transaction id to test */
XidStatus status) /* transaction status */
{
- BlockNumber blockNumber;
XidStatus xidstatus; /* recorded status of xid */
- bool fail = false; /* success/failure */
-
- /*
- * during initialization consider all transactions as having been
- * committed
- */
- if (!RelationIsValid(LogRelation))
- return (bool) (status == XID_COMMIT);
/*
- * before going to the buffer manager, check our single item cache to
+ * Before going to the commit log manager, check our single item cache to
* see if we didn't just check the transaction status a moment ago.
*/
if (TransactionIdEquals(transactionId, cachedTestXid))
- return (bool)
- (status == cachedTestXidStatus);
+ return (status == cachedTestXidStatus);
/*
- * compute the item pointer corresponding to the page containing our
- * transaction id. We save the item in our cache to speed up things
- * if we happen to ask for the same xid's status more than once.
+ * Also, check to see if the transaction ID is a permanent one.
*/
- TransComputeBlockNumber(LogRelation, transactionId, &blockNumber);
- xidstatus = TransBlockNumberGetXidStatus(LogRelation,
- blockNumber,
- transactionId,
- &fail);
-
- if (!fail)
+ if (! TransactionIdIsNormal(transactionId))
{
-
- /*
- * DO NOT cache status for transactions in unknown state !!!
- */
- if (xidstatus == XID_COMMIT || xidstatus == XID_ABORT)
- {
- TransactionIdStore(transactionId, &cachedTestXid);
- cachedTestXidStatus = xidstatus;
- }
- return (bool) (status == xidstatus);
+ if (TransactionIdEquals(transactionId, BootstrapTransactionId))
+ return (status == TRANSACTION_STATUS_COMMITTED);
+ if (TransactionIdEquals(transactionId, FrozenTransactionId))
+ return (status == TRANSACTION_STATUS_COMMITTED);
+ return (status == TRANSACTION_STATUS_ABORTED);
}
/*
- * here the block didn't contain the information we wanted
+ * Get the status.
*/
- elog(ERROR, "TransactionLogTest: failed to get xidstatus");
+ xidstatus = TransactionIdGetStatus(transactionId);
- /*
- * so lint is happy...
- */
- return false;
+ /*
+ * DO NOT cache status for unfinished transactions!
+ */
+ if (xidstatus != TRANSACTION_STATUS_IN_PROGRESS)
+ {
+ TransactionIdStore(transactionId, &cachedTestXid);
+ cachedTestXidStatus = xidstatus;
+ }
+
+ return (status == xidstatus);
}
/* --------------------------------
@@ -165,24 +99,10 @@ static void
TransactionLogUpdate(TransactionId transactionId, /* trans id to update */
XidStatus status) /* new trans status */
{
- BlockNumber blockNumber;
- bool fail = false; /* success/failure */
-
/*
- * during initialization we don't record any updates.
+ * update the commit log
*/
- if (!RelationIsValid(LogRelation))
- return;
-
- /*
- * update the log relation
- */
- TransComputeBlockNumber(LogRelation, transactionId, &blockNumber);
- TransBlockNumberSetXidStatus(LogRelation,
- blockNumber,
- transactionId,
- status,
- &fail);
+ TransactionIdSetStatus(transactionId, status);
/*
* update (invalidate) our single item TransactionLogTest cache.
@@ -191,85 +111,21 @@ TransactionLogUpdate(TransactionId transactionId, /* trans id to update */
cachedTestXidStatus = status;
}
-/* ----------------------------------------------------------------
- * transaction recovery code
- * ----------------------------------------------------------------
- */
-
/* --------------------------------
- * TransRecover
- *
- * preform transaction recovery checking.
- *
- * Note: this should only be preformed if no other backends
- * are running. This is known by the postmaster and
- * conveyed by the postmaster passing a "do recovery checking"
- * flag to the backend.
- *
- * here we get the last recorded transaction from the log,
- * get the "last" and "next" transactions from the variable relation
- * and then preform some integrity tests:
- *
- * 1) No transaction may exist higher then the "next" available
- * transaction recorded in the variable relation. If this is the
- * case then it means either the log or the variable relation
- * has become corrupted.
- *
- * 2) The last committed transaction may not be higher then the
- * next available transaction for the same reason.
- *
- * 3) The last recorded transaction may not be lower then the
- * last committed transaction. (the reverse is ok - it means
- * that some transactions have aborted since the last commit)
- *
- * Here is what the proper situation looks like. The line
- * represents the data stored in the log. 'c' indicates the
- * transaction was recorded as committed, 'a' indicates an
- * abortted transaction and '.' represents information not
- * recorded. These may correspond to in progress transactions.
- *
- * c c a c . . a . . . . . . . . . .
- * | |
- * last next
- *
- * Since "next" is only incremented by GetNewTransactionId() which
- * is called when transactions are started. Hence if there
- * are commits or aborts after "next", then it means we committed
- * or aborted BEFORE we started the transaction. This is the
- * rational behind constraint (1).
- *
- * Likewise, "last" should never greater then "next" for essentially
- * the same reason - it would imply we committed before we started.
- * This is the reasoning for (2).
- *
- * (3) implies we may never have a situation such as:
+ * AmiTransactionOverride
*
- * c c a c . . a c . . . . . . . . .
- * | |
- * last next
- *
- * where there is a 'c' greater then "last".
- *
- * Recovery checking is more difficult in the case where
- * several backends are executing concurrently because the
- * transactions may be executing in the other backends.
- * So, we only do recovery stuff when the backend is explicitly
- * passed a flag on the command line.
+ * This function is used to manipulate the bootstrap flag.
* --------------------------------
*/
-static void
-TransRecover(Relation logRelation)
+void
+AmiTransactionOverride(bool flag)
{
+ AMI_OVERRIDE = flag;
}
/* ----------------------------------------------------------------
* Interface functions
*
- * InitializeTransactionLog
- * ========
- * this function (called near cinit) initializes
- * the transaction log, time and variable relations.
- *
* TransactionId DidCommit
* TransactionId DidAbort
* TransactionId IsInProgress
@@ -279,104 +135,13 @@ TransRecover(Relation logRelation)
*
* TransactionId Commit
* TransactionId Abort
- * TransactionId SetInProgress
* ========
* these functions set the transaction status
- * of the specified xid. TransactionIdCommit() also
- * records the current time in the time relation
- * and updates the variable relation counter.
+ * of the specified xid.
*
* ----------------------------------------------------------------
*/
-/*
- * InitializeTransactionLog
- * Initializes transaction logging.
- */
-void
-InitializeTransactionLog(void)
-{
- Relation logRelation;
- MemoryContext oldContext;
-
- /*
- * don't do anything during bootstrapping
- */
- if (AMI_OVERRIDE)
- return;
-
- /*
- * disable the transaction system so the access methods don't
- * interfere during initialization.
- */
- OverrideTransactionSystem(true);
-
- /*
- * make sure allocations occur within the top memory context so that
- * our log management structures are protected from garbage collection
- * at the end of every transaction.
- */
- oldContext = MemoryContextSwitchTo(TopMemoryContext);
-
- /*
- * first open the log and time relations (these are created by amiint
- * so they are guaranteed to exist)
- */
- logRelation = heap_openr(LogRelationName, NoLock);
-
- /*
- * XXX TransactionLogUpdate requires that LogRelation is valid so we
- * temporarily set it so we can initialize things properly. This could
- * be done cleaner.
- */
- LogRelation = logRelation;
-
- /*
- * if we have a virgin database, we initialize the log relation by
- * committing the BootstrapTransactionId and we initialize the
- * variable relation by setting the next available transaction id to
- * FirstNormalTransactionId. OID initialization happens as a side
- * effect of bootstrapping in varsup.c.
- */
- SpinAcquire(OidGenLockId);
- if (!TransactionIdDidCommit(BootstrapTransactionId))
- {
- TransactionLogUpdate(BootstrapTransactionId, XID_COMMIT);
- Assert(!IsUnderPostmaster &&
- TransactionIdEquals(ShmemVariableCache->nextXid,
- FirstNormalTransactionId));
- ShmemVariableCache->nextXid = FirstNormalTransactionId;
- }
- else if (RecoveryCheckingEnabled())
- {
-
- /*
- * if we have a pre-initialized database and if the perform
- * recovery checking flag was passed then we do our database
- * integrity checking.
- */
- TransRecover(logRelation);
- }
- LogRelation = (Relation) NULL;
- SpinRelease(OidGenLockId);
-
- /*
- * now re-enable the transaction system
- */
- OverrideTransactionSystem(false);
-
- /*
- * instantiate the global variables
- */
- LogRelation = logRelation;
-
- /*
- * restore the memory context to the previous context before we return
- * from initialization.
- */
- MemoryContextSwitchTo(oldContext);
-}
-
/* --------------------------------
* TransactionId DidCommit
* TransactionId DidAbort
@@ -397,16 +162,15 @@ TransactionIdDidCommit(TransactionId transactionId)
if (AMI_OVERRIDE)
return true;
- return TransactionLogTest(transactionId, XID_COMMIT);
+ return TransactionLogTest(transactionId, TRANSACTION_STATUS_COMMITTED);
}
/*
- * TransactionIdDidAborted
+ * TransactionIdDidAbort
* True iff transaction associated with the identifier did abort.
*
* Note:
* Assumes transaction identifier is valid.
- * XXX Is this unneeded?
*/
bool /* true if given transaction aborted */
TransactionIdDidAbort(TransactionId transactionId)
@@ -414,7 +178,7 @@ TransactionIdDidAbort(TransactionId transactionId)
if (AMI_OVERRIDE)
return false;
- return TransactionLogTest(transactionId, XID_ABORT);
+ return TransactionLogTest(transactionId, TRANSACTION_STATUS_ABORTED);
}
/*
@@ -422,22 +186,22 @@ TransactionIdDidAbort(TransactionId transactionId)
* PROC structures of all running backend. - vadim 11/26/96
*
* Old comments:
- * true if given transaction neither committed nor aborted
-
+ * true if given transaction has neither committed nor aborted
+ */
+#ifdef NOT_USED
bool
TransactionIdIsInProgress(TransactionId transactionId)
{
if (AMI_OVERRIDE)
return false;
- return TransactionLogTest(transactionId, XID_INPROGRESS);
+ return TransactionLogTest(transactionId, TRANSACTION_STATUS_IN_PROGRESS);
}
- */
+#endif /* NOT_USED */
/* --------------------------------
* TransactionId Commit
* TransactionId Abort
- * TransactionId SetInProgress
* --------------------------------
*/
@@ -454,7 +218,7 @@ TransactionIdCommit(TransactionId transactionId)
if (AMI_OVERRIDE)
return;
- TransactionLogUpdate(transactionId, XID_COMMIT);
+ TransactionLogUpdate(transactionId, TRANSACTION_STATUS_COMMITTED);
}
/*
@@ -470,5 +234,5 @@ TransactionIdAbort(TransactionId transactionId)
if (AMI_OVERRIDE)
return;
- TransactionLogUpdate(transactionId, XID_ABORT);
+ TransactionLogUpdate(transactionId, TRANSACTION_STATUS_ABORTED);
}