OSDN Git Service

Update copyrights to 2003.
[pg-rex/syncrep.git] / src / backend / access / transam / transam.c
1 /*-------------------------------------------------------------------------
2  *
3  * transam.c
4  *        postgres transaction log interface routines
5  *
6  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.55 2003/08/04 02:39:57 momjian Exp $
12  *
13  * NOTES
14  *        This file contains the high level access-method interface to the
15  *        transaction system.
16  *
17  *-------------------------------------------------------------------------
18  */
19
20 #include "postgres.h"
21
22 #include "access/clog.h"
23 #include "access/transam.h"
24
25
26 /* ----------------
27  *              Flag indicating that we are bootstrapping.
28  *
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.
33  * ----------------
34  */
35 bool            AMI_OVERRIDE = false;
36
37
38 static bool TransactionLogTest(TransactionId transactionId, XidStatus status);
39 static void TransactionLogUpdate(TransactionId transactionId,
40                                          XidStatus status);
41
42 /* ----------------
43  *              Single-item cache for results of TransactionLogTest.
44  * ----------------
45  */
46 static TransactionId cachedTestXid = InvalidTransactionId;
47 static XidStatus cachedTestXidStatus;
48
49
50 /* ----------------------------------------------------------------
51  *              postgres log access method interface
52  *
53  *              TransactionLogTest
54  *              TransactionLogUpdate
55  * ----------------------------------------------------------------
56  */
57
58 /* --------------------------------
59  *              TransactionLogTest
60  * --------------------------------
61  */
62
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 */
67 {
68         XidStatus       xidstatus;              /* recorded status of xid */
69
70         /*
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.
73          */
74         if (TransactionIdEquals(transactionId, cachedTestXid))
75                 return (status == cachedTestXidStatus);
76
77         /*
78          * Also, check to see if the transaction ID is a permanent one.
79          */
80         if (!TransactionIdIsNormal(transactionId))
81         {
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);
87         }
88
89         /*
90          * Get the status.
91          */
92         xidstatus = TransactionIdGetStatus(transactionId);
93
94         /*
95          * DO NOT cache status for unfinished transactions!
96          */
97         if (xidstatus != TRANSACTION_STATUS_IN_PROGRESS)
98         {
99                 TransactionIdStore(transactionId, &cachedTestXid);
100                 cachedTestXidStatus = xidstatus;
101         }
102
103         return (status == xidstatus);
104 }
105
106 /* --------------------------------
107  *              TransactionLogUpdate
108  * --------------------------------
109  */
110 static void
111 TransactionLogUpdate(TransactionId transactionId,               /* trans id to update */
112                                          XidStatus status)      /* new trans status */
113 {
114         /*
115          * update the commit log
116          */
117         TransactionIdSetStatus(transactionId, status);
118
119         /*
120          * update (invalidate) our single item TransactionLogTest cache.
121          */
122         TransactionIdStore(transactionId, &cachedTestXid);
123         cachedTestXidStatus = status;
124 }
125
126 /* --------------------------------
127  *              AmiTransactionOverride
128  *
129  *              This function is used to manipulate the bootstrap flag.
130  * --------------------------------
131  */
132 void
133 AmiTransactionOverride(bool flag)
134 {
135         AMI_OVERRIDE = flag;
136 }
137
138 /* ----------------------------------------------------------------
139  *                                              Interface functions
140  *
141  *              TransactionId DidCommit
142  *              TransactionId DidAbort
143  *              TransactionId IsInProgress
144  *              ========
145  *                 these functions test the transaction status of
146  *                 a specified transaction id.
147  *
148  *              TransactionId Commit
149  *              TransactionId Abort
150  *              ========
151  *                 these functions set the transaction status
152  *                 of the specified xid.
153  *
154  * ----------------------------------------------------------------
155  */
156
157 /* --------------------------------
158  *              TransactionId DidCommit
159  *              TransactionId DidAbort
160  *              TransactionId IsInProgress
161  * --------------------------------
162  */
163
164 /*
165  * TransactionIdDidCommit
166  *              True iff transaction associated with the identifier did commit.
167  *
168  * Note:
169  *              Assumes transaction identifier is valid.
170  */
171 bool                                                    /* true if given transaction committed */
172 TransactionIdDidCommit(TransactionId transactionId)
173 {
174         if (AMI_OVERRIDE)
175         {
176                 Assert(transactionId == BootstrapTransactionId);
177                 return true;
178         }
179
180         return TransactionLogTest(transactionId, TRANSACTION_STATUS_COMMITTED);
181 }
182
183 /*
184  * TransactionIdDidAbort
185  *              True iff transaction associated with the identifier did abort.
186  *
187  * Note:
188  *              Assumes transaction identifier is valid.
189  */
190 bool                                                    /* true if given transaction aborted */
191 TransactionIdDidAbort(TransactionId transactionId)
192 {
193         if (AMI_OVERRIDE)
194         {
195                 Assert(transactionId == BootstrapTransactionId);
196                 return false;
197         }
198
199         return TransactionLogTest(transactionId, TRANSACTION_STATUS_ABORTED);
200 }
201
202 /*
203  * Now this func in shmem.c and gives quality answer by scanning
204  * PGPROC structures of all running backend. - vadim 11/26/96
205  *
206  * Old comments:
207  * true if given transaction has neither committed nor aborted
208  */
209 #ifdef NOT_USED
210 bool
211 TransactionIdIsInProgress(TransactionId transactionId)
212 {
213         if (AMI_OVERRIDE)
214         {
215                 Assert(transactionId == BootstrapTransactionId);
216                 return false;
217         }
218
219         return TransactionLogTest(transactionId, TRANSACTION_STATUS_IN_PROGRESS);
220 }
221 #endif   /* NOT_USED */
222
223 /* --------------------------------
224  *              TransactionId Commit
225  *              TransactionId Abort
226  * --------------------------------
227  */
228
229 /*
230  * TransactionIdCommit
231  *              Commits the transaction associated with the identifier.
232  *
233  * Note:
234  *              Assumes transaction identifier is valid.
235  */
236 void
237 TransactionIdCommit(TransactionId transactionId)
238 {
239         TransactionLogUpdate(transactionId, TRANSACTION_STATUS_COMMITTED);
240 }
241
242 /*
243  * TransactionIdAbort
244  *              Aborts the transaction associated with the identifier.
245  *
246  * Note:
247  *              Assumes transaction identifier is valid.
248  */
249 void
250 TransactionIdAbort(TransactionId transactionId)
251 {
252         TransactionLogUpdate(transactionId, TRANSACTION_STATUS_ABORTED);
253 }
254
255
256 /*
257  * TransactionIdPrecedes --- is id1 logically < id2?
258  */
259 bool
260 TransactionIdPrecedes(TransactionId id1, TransactionId id2)
261 {
262         /*
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.
265          */
266         int32           diff;
267
268         if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
269                 return (id1 < id2);
270
271         diff = (int32) (id1 - id2);
272         return (diff < 0);
273 }
274
275 /*
276  * TransactionIdPrecedesOrEquals --- is id1 logically <= id2?
277  */
278 bool
279 TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
280 {
281         int32           diff;
282
283         if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
284                 return (id1 <= id2);
285
286         diff = (int32) (id1 - id2);
287         return (diff <= 0);
288 }
289
290 /*
291  * TransactionIdFollows --- is id1 logically > id2?
292  */
293 bool
294 TransactionIdFollows(TransactionId id1, TransactionId id2)
295 {
296         int32           diff;
297
298         if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
299                 return (id1 > id2);
300
301         diff = (int32) (id1 - id2);
302         return (diff > 0);
303 }
304
305 /*
306  * TransactionIdFollowsOrEquals --- is id1 logically >= id2?
307  */
308 bool
309 TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
310 {
311         int32           diff;
312
313         if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
314                 return (id1 >= id2);
315
316         diff = (int32) (id1 - id2);
317         return (diff >= 0);
318 }