Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "postgres.h"
00021
00022 #include "access/clog.h"
00023 #include "access/subtrans.h"
00024 #include "access/transam.h"
00025 #include "utils/snapmgr.h"
00026
00027
00028
00029
00030
00031
00032
00033 static TransactionId cachedFetchXid = InvalidTransactionId;
00034 static XidStatus cachedFetchXidStatus;
00035 static XLogRecPtr cachedCommitLSN;
00036
00037
00038 static XidStatus TransactionLogFetch(TransactionId transactionId);
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 static XidStatus
00052 TransactionLogFetch(TransactionId transactionId)
00053 {
00054 XidStatus xidstatus;
00055 XLogRecPtr xidlsn;
00056
00057
00058
00059
00060
00061 if (TransactionIdEquals(transactionId, cachedFetchXid))
00062 return cachedFetchXidStatus;
00063
00064
00065
00066
00067 if (!TransactionIdIsNormal(transactionId))
00068 {
00069 if (TransactionIdEquals(transactionId, BootstrapTransactionId))
00070 return TRANSACTION_STATUS_COMMITTED;
00071 if (TransactionIdEquals(transactionId, FrozenTransactionId))
00072 return TRANSACTION_STATUS_COMMITTED;
00073 return TRANSACTION_STATUS_ABORTED;
00074 }
00075
00076
00077
00078
00079 xidstatus = TransactionIdGetStatus(transactionId, &xidlsn);
00080
00081
00082
00083
00084
00085 if (xidstatus != TRANSACTION_STATUS_IN_PROGRESS &&
00086 xidstatus != TRANSACTION_STATUS_SUB_COMMITTED)
00087 {
00088 cachedFetchXid = transactionId;
00089 cachedFetchXidStatus = xidstatus;
00090 cachedCommitLSN = xidlsn;
00091 }
00092
00093 return xidstatus;
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 bool
00125 TransactionIdDidCommit(TransactionId transactionId)
00126 {
00127 XidStatus xidstatus;
00128
00129 xidstatus = TransactionLogFetch(transactionId);
00130
00131
00132
00133
00134 if (xidstatus == TRANSACTION_STATUS_COMMITTED)
00135 return true;
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED)
00152 {
00153 TransactionId parentXid;
00154
00155 if (TransactionIdPrecedes(transactionId, TransactionXmin))
00156 return false;
00157 parentXid = SubTransGetParent(transactionId);
00158 if (!TransactionIdIsValid(parentXid))
00159 {
00160 elog(WARNING, "no pg_subtrans entry for subcommitted XID %u",
00161 transactionId);
00162 return false;
00163 }
00164 return TransactionIdDidCommit(parentXid);
00165 }
00166
00167
00168
00169
00170 return false;
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180 bool
00181 TransactionIdDidAbort(TransactionId transactionId)
00182 {
00183 XidStatus xidstatus;
00184
00185 xidstatus = TransactionLogFetch(transactionId);
00186
00187
00188
00189
00190 if (xidstatus == TRANSACTION_STATUS_ABORTED)
00191 return true;
00192
00193
00194
00195
00196
00197
00198
00199 if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED)
00200 {
00201 TransactionId parentXid;
00202
00203 if (TransactionIdPrecedes(transactionId, TransactionXmin))
00204 return true;
00205 parentXid = SubTransGetParent(transactionId);
00206 if (!TransactionIdIsValid(parentXid))
00207 {
00208
00209 elog(WARNING, "no pg_subtrans entry for subcommitted XID %u",
00210 transactionId);
00211 return true;
00212 }
00213 return TransactionIdDidAbort(parentXid);
00214 }
00215
00216
00217
00218
00219 return false;
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 bool
00238 TransactionIdIsKnownCompleted(TransactionId transactionId)
00239 {
00240 if (TransactionIdEquals(transactionId, cachedFetchXid))
00241 {
00242
00243 return true;
00244 }
00245
00246 return false;
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 void
00260 TransactionIdCommitTree(TransactionId xid, int nxids, TransactionId *xids)
00261 {
00262 TransactionIdSetTreeStatus(xid, nxids, xids,
00263 TRANSACTION_STATUS_COMMITTED,
00264 InvalidXLogRecPtr);
00265 }
00266
00267
00268
00269
00270
00271 void
00272 TransactionIdAsyncCommitTree(TransactionId xid, int nxids, TransactionId *xids,
00273 XLogRecPtr lsn)
00274 {
00275 TransactionIdSetTreeStatus(xid, nxids, xids,
00276 TRANSACTION_STATUS_COMMITTED, lsn);
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 void
00290 TransactionIdAbortTree(TransactionId xid, int nxids, TransactionId *xids)
00291 {
00292 TransactionIdSetTreeStatus(xid, nxids, xids,
00293 TRANSACTION_STATUS_ABORTED, InvalidXLogRecPtr);
00294 }
00295
00296
00297
00298
00299 bool
00300 TransactionIdPrecedes(TransactionId id1, TransactionId id2)
00301 {
00302
00303
00304
00305
00306 int32 diff;
00307
00308 if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
00309 return (id1 < id2);
00310
00311 diff = (int32) (id1 - id2);
00312 return (diff < 0);
00313 }
00314
00315
00316
00317
00318 bool
00319 TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
00320 {
00321 int32 diff;
00322
00323 if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
00324 return (id1 <= id2);
00325
00326 diff = (int32) (id1 - id2);
00327 return (diff <= 0);
00328 }
00329
00330
00331
00332
00333 bool
00334 TransactionIdFollows(TransactionId id1, TransactionId id2)
00335 {
00336 int32 diff;
00337
00338 if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
00339 return (id1 > id2);
00340
00341 diff = (int32) (id1 - id2);
00342 return (diff > 0);
00343 }
00344
00345
00346
00347
00348 bool
00349 TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
00350 {
00351 int32 diff;
00352
00353 if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
00354 return (id1 >= id2);
00355
00356 diff = (int32) (id1 - id2);
00357 return (diff >= 0);
00358 }
00359
00360
00361
00362
00363
00364 TransactionId
00365 TransactionIdLatest(TransactionId mainxid,
00366 int nxids, const TransactionId *xids)
00367 {
00368 TransactionId result;
00369
00370
00371
00372
00373
00374
00375
00376
00377 result = mainxid;
00378 while (--nxids >= 0)
00379 {
00380 if (TransactionIdPrecedes(result, xids[nxids]))
00381 result = xids[nxids];
00382 }
00383 return result;
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 XLogRecPtr
00402 TransactionIdGetCommitLSN(TransactionId xid)
00403 {
00404 XLogRecPtr result;
00405
00406
00407
00408
00409
00410
00411
00412 if (TransactionIdEquals(xid, cachedFetchXid))
00413 return cachedCommitLSN;
00414
00415
00416 if (!TransactionIdIsNormal(xid))
00417 return InvalidXLogRecPtr;
00418
00419
00420
00421
00422 (void) TransactionIdGetStatus(xid, &result);
00423
00424 return result;
00425 }