1 /*-------------------------------------------------------------------------
4 * postgres transaction log interface routines
6 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.55 2003/08/04 02:39:57 momjian Exp $
14 * This file contains the high level access-method interface to the
17 *-------------------------------------------------------------------------
22 #include "access/clog.h"
23 #include "access/transam.h"
27 * Flag indicating that we are bootstrapping.
29 * Transaction ID generation is disabled during bootstrap; we just use
30 * BootstrapTransactionId. Also, the transaction ID status-check routines
31 * are short-circuited; they claim that BootstrapTransactionId has already
32 * committed, allowing tuples already inserted to be seen immediately.
35 bool AMI_OVERRIDE = false;
38 static bool TransactionLogTest(TransactionId transactionId, XidStatus status);
39 static void TransactionLogUpdate(TransactionId transactionId,
43 * Single-item cache for results of TransactionLogTest.
46 static TransactionId cachedTestXid = InvalidTransactionId;
47 static XidStatus cachedTestXidStatus;
50 /* ----------------------------------------------------------------
51 * postgres log access method interface
54 * TransactionLogUpdate
55 * ----------------------------------------------------------------
58 /* --------------------------------
60 * --------------------------------
63 static bool /* true/false: does transaction id have
64 * specified status? */
65 TransactionLogTest(TransactionId transactionId, /* transaction id to test */
66 XidStatus status) /* transaction status */
68 XidStatus xidstatus; /* recorded status of xid */
71 * Before going to the commit log manager, check our single item cache
72 * to see if we didn't just check the transaction status a moment ago.
74 if (TransactionIdEquals(transactionId, cachedTestXid))
75 return (status == cachedTestXidStatus);
78 * Also, check to see if the transaction ID is a permanent one.
80 if (!TransactionIdIsNormal(transactionId))
82 if (TransactionIdEquals(transactionId, BootstrapTransactionId))
83 return (status == TRANSACTION_STATUS_COMMITTED);
84 if (TransactionIdEquals(transactionId, FrozenTransactionId))
85 return (status == TRANSACTION_STATUS_COMMITTED);
86 return (status == TRANSACTION_STATUS_ABORTED);
92 xidstatus = TransactionIdGetStatus(transactionId);
95 * DO NOT cache status for unfinished transactions!
97 if (xidstatus != TRANSACTION_STATUS_IN_PROGRESS)
99 TransactionIdStore(transactionId, &cachedTestXid);
100 cachedTestXidStatus = xidstatus;
103 return (status == xidstatus);
106 /* --------------------------------
107 * TransactionLogUpdate
108 * --------------------------------
111 TransactionLogUpdate(TransactionId transactionId, /* trans id to update */
112 XidStatus status) /* new trans status */
115 * update the commit log
117 TransactionIdSetStatus(transactionId, status);
120 * update (invalidate) our single item TransactionLogTest cache.
122 TransactionIdStore(transactionId, &cachedTestXid);
123 cachedTestXidStatus = status;
126 /* --------------------------------
127 * AmiTransactionOverride
129 * This function is used to manipulate the bootstrap flag.
130 * --------------------------------
133 AmiTransactionOverride(bool flag)
138 /* ----------------------------------------------------------------
139 * Interface functions
141 * TransactionId DidCommit
142 * TransactionId DidAbort
143 * TransactionId IsInProgress
145 * these functions test the transaction status of
146 * a specified transaction id.
148 * TransactionId Commit
149 * TransactionId Abort
151 * these functions set the transaction status
152 * of the specified xid.
154 * ----------------------------------------------------------------
157 /* --------------------------------
158 * TransactionId DidCommit
159 * TransactionId DidAbort
160 * TransactionId IsInProgress
161 * --------------------------------
165 * TransactionIdDidCommit
166 * True iff transaction associated with the identifier did commit.
169 * Assumes transaction identifier is valid.
171 bool /* true if given transaction committed */
172 TransactionIdDidCommit(TransactionId transactionId)
176 Assert(transactionId == BootstrapTransactionId);
180 return TransactionLogTest(transactionId, TRANSACTION_STATUS_COMMITTED);
184 * TransactionIdDidAbort
185 * True iff transaction associated with the identifier did abort.
188 * Assumes transaction identifier is valid.
190 bool /* true if given transaction aborted */
191 TransactionIdDidAbort(TransactionId transactionId)
195 Assert(transactionId == BootstrapTransactionId);
199 return TransactionLogTest(transactionId, TRANSACTION_STATUS_ABORTED);
203 * Now this func in shmem.c and gives quality answer by scanning
204 * PGPROC structures of all running backend. - vadim 11/26/96
207 * true if given transaction has neither committed nor aborted
211 TransactionIdIsInProgress(TransactionId transactionId)
215 Assert(transactionId == BootstrapTransactionId);
219 return TransactionLogTest(transactionId, TRANSACTION_STATUS_IN_PROGRESS);
221 #endif /* NOT_USED */
223 /* --------------------------------
224 * TransactionId Commit
225 * TransactionId Abort
226 * --------------------------------
230 * TransactionIdCommit
231 * Commits the transaction associated with the identifier.
234 * Assumes transaction identifier is valid.
237 TransactionIdCommit(TransactionId transactionId)
239 TransactionLogUpdate(transactionId, TRANSACTION_STATUS_COMMITTED);
244 * Aborts the transaction associated with the identifier.
247 * Assumes transaction identifier is valid.
250 TransactionIdAbort(TransactionId transactionId)
252 TransactionLogUpdate(transactionId, TRANSACTION_STATUS_ABORTED);
257 * TransactionIdPrecedes --- is id1 logically < id2?
260 TransactionIdPrecedes(TransactionId id1, TransactionId id2)
263 * If either ID is a permanent XID then we can just do unsigned
264 * comparison. If both are normal, do a modulo-2^31 comparison.
268 if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
271 diff = (int32) (id1 - id2);
276 * TransactionIdPrecedesOrEquals --- is id1 logically <= id2?
279 TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
283 if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
286 diff = (int32) (id1 - id2);
291 * TransactionIdFollows --- is id1 logically > id2?
294 TransactionIdFollows(TransactionId id1, TransactionId id2)
298 if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
301 diff = (int32) (id1 - id2);
306 * TransactionIdFollowsOrEquals --- is id1 logically >= id2?
309 TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
313 if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
316 diff = (int32) (id1 - id2);