Header And Logo

PostgreSQL
| The world's most advanced open source database.

tqual.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * tqual.c
00004  *    POSTGRES "time qualification" code, ie, tuple visibility rules.
00005  *
00006  * NOTE: all the HeapTupleSatisfies routines will update the tuple's
00007  * "hint" status bits if we see that the inserting or deleting transaction
00008  * has now committed or aborted (and it is safe to set the hint bits).
00009  * If the hint bits are changed, MarkBufferDirtyHint is called on
00010  * the passed-in buffer.  The caller must hold not only a pin, but at least
00011  * shared buffer content lock on the buffer containing the tuple.
00012  *
00013  * NOTE: must check TransactionIdIsInProgress (which looks in PGXACT array)
00014  * before TransactionIdDidCommit/TransactionIdDidAbort (which look in
00015  * pg_clog).  Otherwise we have a race condition: we might decide that a
00016  * just-committed transaction crashed, because none of the tests succeed.
00017  * xact.c is careful to record commit/abort in pg_clog before it unsets
00018  * MyPgXact->xid in PGXACT array.  That fixes that problem, but it also
00019  * means there is a window where TransactionIdIsInProgress and
00020  * TransactionIdDidCommit will both return true.  If we check only
00021  * TransactionIdDidCommit, we could consider a tuple committed when a
00022  * later GetSnapshotData call will still think the originating transaction
00023  * is in progress, which leads to application-level inconsistency.  The
00024  * upshot is that we gotta check TransactionIdIsInProgress first in all
00025  * code paths, except for a few cases where we are looking at
00026  * subtransactions of our own main transaction and so there can't be any
00027  * race condition.
00028  *
00029  * Summary of visibility functions:
00030  *
00031  *   HeapTupleSatisfiesMVCC()
00032  *        visible to supplied snapshot, excludes current command
00033  *   HeapTupleSatisfiesNow()
00034  *        visible to instant snapshot, excludes current command
00035  *   HeapTupleSatisfiesUpdate()
00036  *        like HeapTupleSatisfiesNow(), but with user-supplied command
00037  *        counter and more complex result
00038  *   HeapTupleSatisfiesSelf()
00039  *        visible to instant snapshot and current command
00040  *   HeapTupleSatisfiesDirty()
00041  *        like HeapTupleSatisfiesSelf(), but includes open transactions
00042  *   HeapTupleSatisfiesVacuum()
00043  *        visible to any running transaction, used by VACUUM
00044  *   HeapTupleSatisfiesToast()
00045  *        visible unless part of interrupted vacuum, used for TOAST
00046  *   HeapTupleSatisfiesAny()
00047  *        all tuples are visible
00048  *
00049  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00050  * Portions Copyright (c) 1994, Regents of the University of California
00051  *
00052  * IDENTIFICATION
00053  *    src/backend/utils/time/tqual.c
00054  *
00055  *-------------------------------------------------------------------------
00056  */
00057 
00058 #include "postgres.h"
00059 
00060 #include "access/htup_details.h"
00061 #include "access/multixact.h"
00062 #include "access/subtrans.h"
00063 #include "access/transam.h"
00064 #include "access/xact.h"
00065 #include "storage/bufmgr.h"
00066 #include "storage/procarray.h"
00067 #include "utils/tqual.h"
00068 
00069 
00070 /* Static variables representing various special snapshot semantics */
00071 SnapshotData SnapshotNowData = {HeapTupleSatisfiesNow};
00072 SnapshotData SnapshotSelfData = {HeapTupleSatisfiesSelf};
00073 SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny};
00074 SnapshotData SnapshotToastData = {HeapTupleSatisfiesToast};
00075 
00076 /* local functions */
00077 static bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot);
00078 
00079 
00080 /*
00081  * SetHintBits()
00082  *
00083  * Set commit/abort hint bits on a tuple, if appropriate at this time.
00084  *
00085  * It is only safe to set a transaction-committed hint bit if we know the
00086  * transaction's commit record has been flushed to disk, or if the table is
00087  * temporary or unlogged and will be obliterated by a crash anyway.  We
00088  * cannot change the LSN of the page here because we may hold only a share
00089  * lock on the buffer, so we can't use the LSN to interlock this; we have to
00090  * just refrain from setting the hint bit until some future re-examination
00091  * of the tuple.
00092  *
00093  * We can always set hint bits when marking a transaction aborted.  (Some
00094  * code in heapam.c relies on that!)
00095  *
00096  * Also, if we are cleaning up HEAP_MOVED_IN or HEAP_MOVED_OFF entries, then
00097  * we can always set the hint bits, since pre-9.0 VACUUM FULL always used
00098  * synchronous commits and didn't move tuples that weren't previously
00099  * hinted.  (This is not known by this subroutine, but is applied by its
00100  * callers.)  Note: old-style VACUUM FULL is gone, but we have to keep this
00101  * module's support for MOVED_OFF/MOVED_IN flag bits for as long as we
00102  * support in-place update from pre-9.0 databases.
00103  *
00104  * Normal commits may be asynchronous, so for those we need to get the LSN
00105  * of the transaction and then check whether this is flushed.
00106  *
00107  * The caller should pass xid as the XID of the transaction to check, or
00108  * InvalidTransactionId if no check is needed.
00109  */
00110 static inline void
00111 SetHintBits(HeapTupleHeader tuple, Buffer buffer,
00112             uint16 infomask, TransactionId xid)
00113 {
00114     if (TransactionIdIsValid(xid))
00115     {
00116         /* NB: xid must be known committed here! */
00117         XLogRecPtr  commitLSN = TransactionIdGetCommitLSN(xid);
00118 
00119         if (XLogNeedsFlush(commitLSN) && BufferIsPermanent(buffer))
00120             return;             /* not flushed yet, so don't set hint */
00121     }
00122 
00123     tuple->t_infomask |= infomask;
00124     MarkBufferDirtyHint(buffer);
00125 }
00126 
00127 /*
00128  * HeapTupleSetHintBits --- exported version of SetHintBits()
00129  *
00130  * This must be separate because of C99's brain-dead notions about how to
00131  * implement inline functions.
00132  */
00133 void
00134 HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
00135                      uint16 infomask, TransactionId xid)
00136 {
00137     SetHintBits(tuple, buffer, infomask, xid);
00138 }
00139 
00140 
00141 /*
00142  * HeapTupleSatisfiesSelf
00143  *      True iff heap tuple is valid "for itself".
00144  *
00145  *  Here, we consider the effects of:
00146  *      all committed transactions (as of the current instant)
00147  *      previous commands of this transaction
00148  *      changes made by the current command
00149  *
00150  * Note:
00151  *      Assumes heap tuple is valid.
00152  *
00153  * The satisfaction of "itself" requires the following:
00154  *
00155  * ((Xmin == my-transaction &&              the row was updated by the current transaction, and
00156  *      (Xmax is null                       it was not deleted
00157  *       [|| Xmax != my-transaction)])          [or it was deleted by another transaction]
00158  * ||
00159  *
00160  * (Xmin is committed &&                    the row was modified by a committed transaction, and
00161  *      (Xmax is null ||                    the row has not been deleted, or
00162  *          (Xmax != my-transaction &&          the row was deleted by another transaction
00163  *           Xmax is not committed)))           that has not been committed
00164  */
00165 bool
00166 HeapTupleSatisfiesSelf(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
00167 {
00168     if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
00169     {
00170         if (tuple->t_infomask & HEAP_XMIN_INVALID)
00171             return false;
00172 
00173         /* Used by pre-9.0 binary upgrades */
00174         if (tuple->t_infomask & HEAP_MOVED_OFF)
00175         {
00176             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
00177 
00178             if (TransactionIdIsCurrentTransactionId(xvac))
00179                 return false;
00180             if (!TransactionIdIsInProgress(xvac))
00181             {
00182                 if (TransactionIdDidCommit(xvac))
00183                 {
00184                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00185                                 InvalidTransactionId);
00186                     return false;
00187                 }
00188                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00189                             InvalidTransactionId);
00190             }
00191         }
00192         /* Used by pre-9.0 binary upgrades */
00193         else if (tuple->t_infomask & HEAP_MOVED_IN)
00194         {
00195             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
00196 
00197             if (!TransactionIdIsCurrentTransactionId(xvac))
00198             {
00199                 if (TransactionIdIsInProgress(xvac))
00200                     return false;
00201                 if (TransactionIdDidCommit(xvac))
00202                     SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00203                                 InvalidTransactionId);
00204                 else
00205                 {
00206                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00207                                 InvalidTransactionId);
00208                     return false;
00209                 }
00210             }
00211         }
00212         else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
00213         {
00214             if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid */
00215                 return true;
00216 
00217             if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))        /* not deleter */
00218                 return true;
00219 
00220             if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
00221             {
00222                 TransactionId   xmax;
00223 
00224                 xmax = HeapTupleGetUpdateXid(tuple);
00225                 if (!TransactionIdIsValid(xmax))
00226                     return true;
00227 
00228                 /* updating subtransaction must have aborted */
00229                 if (!TransactionIdIsCurrentTransactionId(xmax))
00230                     return true;
00231                 else
00232                     return false;
00233             }
00234 
00235             if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
00236             {
00237                 /* deleting subtransaction must have aborted */
00238                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
00239                             InvalidTransactionId);
00240                 return true;
00241             }
00242 
00243             return false;
00244         }
00245         else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
00246             return false;
00247         else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
00248             SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00249                         HeapTupleHeaderGetXmin(tuple));
00250         else
00251         {
00252             /* it must have aborted or crashed */
00253             SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00254                         InvalidTransactionId);
00255             return false;
00256         }
00257     }
00258 
00259     /* by here, the inserting transaction has committed */
00260 
00261     if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid or aborted */
00262         return true;
00263 
00264     if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
00265     {
00266         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00267             return true;
00268         return false;           /* updated by other */
00269     }
00270 
00271     if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
00272     {
00273         TransactionId   xmax;
00274 
00275         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00276             return true;
00277 
00278         xmax = HeapTupleGetUpdateXid(tuple);
00279         if (!TransactionIdIsValid(xmax))
00280             return true;
00281         if (TransactionIdIsCurrentTransactionId(xmax))
00282             return false;
00283         if (TransactionIdIsInProgress(xmax))
00284             return true;
00285         if (TransactionIdDidCommit(xmax))
00286             return false;
00287         return true;
00288     }
00289 
00290     if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
00291     {
00292         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00293             return true;
00294         return false;
00295     }
00296 
00297     if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
00298         return true;
00299 
00300     if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
00301     {
00302         /* it must have aborted or crashed */
00303         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
00304                     InvalidTransactionId);
00305         return true;
00306     }
00307 
00308     /* xmax transaction committed */
00309 
00310     if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00311     {
00312         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
00313                     InvalidTransactionId);
00314         return true;
00315     }
00316 
00317     SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
00318                 HeapTupleHeaderGetRawXmax(tuple));
00319     return false;
00320 }
00321 
00322 /*
00323  * HeapTupleSatisfiesNow
00324  *      True iff heap tuple is valid "now".
00325  *
00326  *  Here, we consider the effects of:
00327  *      all committed transactions (as of the current instant)
00328  *      previous commands of this transaction
00329  *
00330  * Note we do _not_ include changes made by the current command.  This
00331  * solves the "Halloween problem" wherein an UPDATE might try to re-update
00332  * its own output tuples, http://en.wikipedia.org/wiki/Halloween_Problem.
00333  *
00334  * Note:
00335  *      Assumes heap tuple is valid.
00336  *
00337  * The satisfaction of "now" requires the following:
00338  *
00339  * ((Xmin == my-transaction &&              inserted by the current transaction
00340  *   Cmin < my-command &&                   before this command, and
00341  *   (Xmax is null ||                       the row has not been deleted, or
00342  *    (Xmax == my-transaction &&            it was deleted by the current transaction
00343  *     Cmax >= my-command)))                but not before this command,
00344  * ||                                       or
00345  *  (Xmin is committed &&                   the row was inserted by a committed transaction, and
00346  *      (Xmax is null ||                    the row has not been deleted, or
00347  *       (Xmax == my-transaction &&         the row is being deleted by this transaction
00348  *        Cmax >= my-command) ||            but it's not deleted "yet", or
00349  *       (Xmax != my-transaction &&         the row was deleted by another transaction
00350  *        Xmax is not committed))))         that has not been committed
00351  *
00352  */
00353 bool
00354 HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
00355 {
00356     if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
00357     {
00358         if (tuple->t_infomask & HEAP_XMIN_INVALID)
00359             return false;
00360 
00361         /* Used by pre-9.0 binary upgrades */
00362         if (tuple->t_infomask & HEAP_MOVED_OFF)
00363         {
00364             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
00365 
00366             if (TransactionIdIsCurrentTransactionId(xvac))
00367                 return false;
00368             if (!TransactionIdIsInProgress(xvac))
00369             {
00370                 if (TransactionIdDidCommit(xvac))
00371                 {
00372                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00373                                 InvalidTransactionId);
00374                     return false;
00375                 }
00376                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00377                             InvalidTransactionId);
00378             }
00379         }
00380         /* Used by pre-9.0 binary upgrades */
00381         else if (tuple->t_infomask & HEAP_MOVED_IN)
00382         {
00383             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
00384 
00385             if (!TransactionIdIsCurrentTransactionId(xvac))
00386             {
00387                 if (TransactionIdIsInProgress(xvac))
00388                     return false;
00389                 if (TransactionIdDidCommit(xvac))
00390                     SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00391                                 InvalidTransactionId);
00392                 else
00393                 {
00394                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00395                                 InvalidTransactionId);
00396                     return false;
00397                 }
00398             }
00399         }
00400         else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
00401         {
00402             if (HeapTupleHeaderGetCmin(tuple) >= GetCurrentCommandId(false))
00403                 return false;   /* inserted after scan started */
00404 
00405             if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid */
00406                 return true;
00407 
00408             if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))        /* not deleter */
00409                 return true;
00410 
00411             if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
00412             {
00413                 TransactionId   xmax;
00414 
00415                 xmax = HeapTupleGetUpdateXid(tuple);
00416                 if (!TransactionIdIsValid(xmax))
00417                     return true;
00418 
00419                 /* updating subtransaction must have aborted */
00420                 if (!TransactionIdIsCurrentTransactionId(xmax))
00421                     return true;
00422                 else
00423                     return false;
00424             }
00425 
00426             if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
00427             {
00428                 /* deleting subtransaction must have aborted */
00429                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
00430                             InvalidTransactionId);
00431                 return true;
00432             }
00433 
00434             if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId(false))
00435                 return true;    /* deleted after scan started */
00436             else
00437                 return false;   /* deleted before scan started */
00438         }
00439         else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
00440             return false;
00441         else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
00442             SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00443                         HeapTupleHeaderGetXmin(tuple));
00444         else
00445         {
00446             /* it must have aborted or crashed */
00447             SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00448                         InvalidTransactionId);
00449             return false;
00450         }
00451     }
00452 
00453     /* by here, the inserting transaction has committed */
00454 
00455     if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid or aborted */
00456         return true;
00457 
00458     if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
00459     {
00460         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00461             return true;
00462         return false;
00463     }
00464 
00465     if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
00466     {
00467         TransactionId   xmax;
00468 
00469         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00470             return true;
00471 
00472         xmax = HeapTupleGetUpdateXid(tuple);
00473         if (!TransactionIdIsValid(xmax))
00474             return true;
00475         if (TransactionIdIsCurrentTransactionId(xmax))
00476         {
00477             if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId(false))
00478                 return true;    /* deleted after scan started */
00479             else
00480                 return false;   /* deleted before scan started */
00481         }
00482         if (TransactionIdIsInProgress(xmax))
00483             return true;
00484         if (TransactionIdDidCommit(xmax))
00485             return false;
00486         return true;
00487     }
00488 
00489     if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
00490     {
00491         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00492             return true;
00493         if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId(false))
00494             return true;        /* deleted after scan started */
00495         else
00496             return false;       /* deleted before scan started */
00497     }
00498 
00499     if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
00500         return true;
00501 
00502     if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
00503     {
00504         /* it must have aborted or crashed */
00505         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
00506                     InvalidTransactionId);
00507         return true;
00508     }
00509 
00510     /* xmax transaction committed */
00511 
00512     if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00513     {
00514         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
00515                     InvalidTransactionId);
00516         return true;
00517     }
00518 
00519     SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
00520                 HeapTupleHeaderGetRawXmax(tuple));
00521     return false;
00522 }
00523 
00524 /*
00525  * HeapTupleSatisfiesAny
00526  *      Dummy "satisfies" routine: any tuple satisfies SnapshotAny.
00527  */
00528 bool
00529 HeapTupleSatisfiesAny(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
00530 {
00531     return true;
00532 }
00533 
00534 /*
00535  * HeapTupleSatisfiesToast
00536  *      True iff heap tuple is valid as a TOAST row.
00537  *
00538  * This is a simplified version that only checks for VACUUM moving conditions.
00539  * It's appropriate for TOAST usage because TOAST really doesn't want to do
00540  * its own time qual checks; if you can see the main table row that contains
00541  * a TOAST reference, you should be able to see the TOASTed value.  However,
00542  * vacuuming a TOAST table is independent of the main table, and in case such
00543  * a vacuum fails partway through, we'd better do this much checking.
00544  *
00545  * Among other things, this means you can't do UPDATEs of rows in a TOAST
00546  * table.
00547  */
00548 bool
00549 HeapTupleSatisfiesToast(HeapTupleHeader tuple, Snapshot snapshot,
00550                         Buffer buffer)
00551 {
00552     if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
00553     {
00554         if (tuple->t_infomask & HEAP_XMIN_INVALID)
00555             return false;
00556 
00557         /* Used by pre-9.0 binary upgrades */
00558         if (tuple->t_infomask & HEAP_MOVED_OFF)
00559         {
00560             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
00561 
00562             if (TransactionIdIsCurrentTransactionId(xvac))
00563                 return false;
00564             if (!TransactionIdIsInProgress(xvac))
00565             {
00566                 if (TransactionIdDidCommit(xvac))
00567                 {
00568                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00569                                 InvalidTransactionId);
00570                     return false;
00571                 }
00572                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00573                             InvalidTransactionId);
00574             }
00575         }
00576         /* Used by pre-9.0 binary upgrades */
00577         else if (tuple->t_infomask & HEAP_MOVED_IN)
00578         {
00579             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
00580 
00581             if (!TransactionIdIsCurrentTransactionId(xvac))
00582             {
00583                 if (TransactionIdIsInProgress(xvac))
00584                     return false;
00585                 if (TransactionIdDidCommit(xvac))
00586                     SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00587                                 InvalidTransactionId);
00588                 else
00589                 {
00590                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00591                                 InvalidTransactionId);
00592                     return false;
00593                 }
00594             }
00595         }
00596     }
00597 
00598     /* otherwise assume the tuple is valid for TOAST. */
00599     return true;
00600 }
00601 
00602 /*
00603  * HeapTupleSatisfiesUpdate
00604  *
00605  *  Same logic as HeapTupleSatisfiesNow, but returns a more detailed result
00606  *  code, since UPDATE needs to know more than "is it visible?".  Also,
00607  *  tuples of my own xact are tested against the passed CommandId not
00608  *  CurrentCommandId.
00609  *
00610  *  The possible return codes are:
00611  *
00612  *  HeapTupleInvisible: the tuple didn't exist at all when the scan started,
00613  *  e.g. it was created by a later CommandId.
00614  *
00615  *  HeapTupleMayBeUpdated: The tuple is valid and visible, so it may be
00616  *  updated.
00617  *
00618  *  HeapTupleSelfUpdated: The tuple was updated by the current transaction,
00619  *  after the current scan started.
00620  *
00621  *  HeapTupleUpdated: The tuple was updated by a committed transaction.
00622  *
00623  *  HeapTupleBeingUpdated: The tuple is being updated by an in-progress
00624  *  transaction other than the current transaction.  (Note: this includes
00625  *  the case where the tuple is share-locked by a MultiXact, even if the
00626  *  MultiXact includes the current transaction.  Callers that want to
00627  *  distinguish that case must test for it themselves.)
00628  */
00629 HTSU_Result
00630 HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
00631                          Buffer buffer)
00632 {
00633     if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
00634     {
00635         if (tuple->t_infomask & HEAP_XMIN_INVALID)
00636             return HeapTupleInvisible;
00637 
00638         /* Used by pre-9.0 binary upgrades */
00639         if (tuple->t_infomask & HEAP_MOVED_OFF)
00640         {
00641             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
00642 
00643             if (TransactionIdIsCurrentTransactionId(xvac))
00644                 return HeapTupleInvisible;
00645             if (!TransactionIdIsInProgress(xvac))
00646             {
00647                 if (TransactionIdDidCommit(xvac))
00648                 {
00649                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00650                                 InvalidTransactionId);
00651                     return HeapTupleInvisible;
00652                 }
00653                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00654                             InvalidTransactionId);
00655             }
00656         }
00657         /* Used by pre-9.0 binary upgrades */
00658         else if (tuple->t_infomask & HEAP_MOVED_IN)
00659         {
00660             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
00661 
00662             if (!TransactionIdIsCurrentTransactionId(xvac))
00663             {
00664                 if (TransactionIdIsInProgress(xvac))
00665                     return HeapTupleInvisible;
00666                 if (TransactionIdDidCommit(xvac))
00667                     SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00668                                 InvalidTransactionId);
00669                 else
00670                 {
00671                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00672                                 InvalidTransactionId);
00673                     return HeapTupleInvisible;
00674                 }
00675             }
00676         }
00677         else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
00678         {
00679             if (HeapTupleHeaderGetCmin(tuple) >= curcid)
00680                 return HeapTupleInvisible;      /* inserted after scan started */
00681 
00682             if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid */
00683                 return HeapTupleMayBeUpdated;
00684 
00685             if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))         /* not deleter */
00686                 return HeapTupleMayBeUpdated;
00687 
00688             if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
00689             {
00690                 TransactionId   xmax;
00691 
00692                 xmax = HeapTupleGetUpdateXid(tuple);
00693                 if (!TransactionIdIsValid(xmax))
00694                     return HeapTupleMayBeUpdated;
00695 
00696                 /* updating subtransaction must have aborted */
00697                 if (!TransactionIdIsCurrentTransactionId(xmax))
00698                     return HeapTupleMayBeUpdated;
00699                 else
00700                 {
00701                     if (HeapTupleHeaderGetCmax(tuple) >= curcid)
00702                         return HeapTupleSelfUpdated;    /* updated after scan started */
00703                     else
00704                         return HeapTupleInvisible;  /* updated before scan started */
00705                 }
00706             }
00707 
00708             if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
00709             {
00710                 /* deleting subtransaction must have aborted */
00711                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
00712                             InvalidTransactionId);
00713                 return HeapTupleMayBeUpdated;
00714             }
00715 
00716             if (HeapTupleHeaderGetCmax(tuple) >= curcid)
00717                 return HeapTupleSelfUpdated;    /* updated after scan started */
00718             else
00719                 return HeapTupleInvisible;      /* updated before scan started */
00720         }
00721         else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
00722             return HeapTupleInvisible;
00723         else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
00724             SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00725                         HeapTupleHeaderGetXmin(tuple));
00726         else
00727         {
00728             /* it must have aborted or crashed */
00729             SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00730                         InvalidTransactionId);
00731             return HeapTupleInvisible;
00732         }
00733     }
00734 
00735     /* by here, the inserting transaction has committed */
00736 
00737     if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid or aborted */
00738         return HeapTupleMayBeUpdated;
00739 
00740     if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
00741     {
00742         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00743             return HeapTupleMayBeUpdated;
00744         return HeapTupleUpdated;    /* updated by other */
00745     }
00746 
00747     if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
00748     {
00749         TransactionId   xmax;
00750 
00751         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00752         {
00753             /*
00754              * If it's only locked but neither EXCL_LOCK nor KEYSHR_LOCK
00755              * is set, it cannot possibly be running.  Otherwise need to
00756              * check.
00757              */
00758             if ((tuple->t_infomask & (HEAP_XMAX_EXCL_LOCK |
00759                                       HEAP_XMAX_KEYSHR_LOCK)) &&
00760                 MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
00761                 return HeapTupleBeingUpdated;
00762 
00763             SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
00764             return HeapTupleMayBeUpdated;
00765         }
00766 
00767         xmax = HeapTupleGetUpdateXid(tuple);
00768         if (!TransactionIdIsValid(xmax))
00769         {
00770             if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
00771                 return HeapTupleBeingUpdated;
00772 
00773             SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
00774             return HeapTupleMayBeUpdated;
00775         }
00776 
00777         if (TransactionIdIsCurrentTransactionId(xmax))
00778         {
00779             if (HeapTupleHeaderGetCmax(tuple) >= curcid)
00780                 return HeapTupleSelfUpdated;        /* updated after scan started */
00781             else
00782                 return HeapTupleInvisible;  /* updated before scan started */
00783         }
00784 
00785         if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
00786             return HeapTupleBeingUpdated;
00787 
00788         if (TransactionIdDidCommit(xmax))
00789             return HeapTupleUpdated;
00790         /* it must have aborted or crashed */
00791         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
00792         return HeapTupleMayBeUpdated;
00793     }
00794 
00795     if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
00796     {
00797         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00798             return HeapTupleMayBeUpdated;
00799         if (HeapTupleHeaderGetCmax(tuple) >= curcid)
00800             return HeapTupleSelfUpdated;        /* updated after scan started */
00801         else
00802             return HeapTupleInvisible;  /* updated before scan started */
00803     }
00804 
00805     if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
00806         return HeapTupleBeingUpdated;
00807 
00808     if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
00809     {
00810         /* it must have aborted or crashed */
00811         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
00812                     InvalidTransactionId);
00813         return HeapTupleMayBeUpdated;
00814     }
00815 
00816     /* xmax transaction committed */
00817 
00818     if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00819     {
00820         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
00821                     InvalidTransactionId);
00822         return HeapTupleMayBeUpdated;
00823     }
00824 
00825     SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
00826                 HeapTupleHeaderGetRawXmax(tuple));
00827     return HeapTupleUpdated;    /* updated by other */
00828 }
00829 
00830 /*
00831  * HeapTupleSatisfiesDirty
00832  *      True iff heap tuple is valid including effects of open transactions.
00833  *
00834  *  Here, we consider the effects of:
00835  *      all committed and in-progress transactions (as of the current instant)
00836  *      previous commands of this transaction
00837  *      changes made by the current command
00838  *
00839  * This is essentially like HeapTupleSatisfiesSelf as far as effects of
00840  * the current transaction and committed/aborted xacts are concerned.
00841  * However, we also include the effects of other xacts still in progress.
00842  *
00843  * A special hack is that the passed-in snapshot struct is used as an
00844  * output argument to return the xids of concurrent xacts that affected the
00845  * tuple.  snapshot->xmin is set to the tuple's xmin if that is another
00846  * transaction that's still in progress; or to InvalidTransactionId if the
00847  * tuple's xmin is committed good, committed dead, or my own xact.  Similarly
00848  * for snapshot->xmax and the tuple's xmax.
00849  */
00850 bool
00851 HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Snapshot snapshot,
00852                         Buffer buffer)
00853 {
00854     snapshot->xmin = snapshot->xmax = InvalidTransactionId;
00855 
00856     if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
00857     {
00858         if (tuple->t_infomask & HEAP_XMIN_INVALID)
00859             return false;
00860 
00861         /* Used by pre-9.0 binary upgrades */
00862         if (tuple->t_infomask & HEAP_MOVED_OFF)
00863         {
00864             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
00865 
00866             if (TransactionIdIsCurrentTransactionId(xvac))
00867                 return false;
00868             if (!TransactionIdIsInProgress(xvac))
00869             {
00870                 if (TransactionIdDidCommit(xvac))
00871                 {
00872                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00873                                 InvalidTransactionId);
00874                     return false;
00875                 }
00876                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00877                             InvalidTransactionId);
00878             }
00879         }
00880         /* Used by pre-9.0 binary upgrades */
00881         else if (tuple->t_infomask & HEAP_MOVED_IN)
00882         {
00883             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
00884 
00885             if (!TransactionIdIsCurrentTransactionId(xvac))
00886             {
00887                 if (TransactionIdIsInProgress(xvac))
00888                     return false;
00889                 if (TransactionIdDidCommit(xvac))
00890                     SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00891                                 InvalidTransactionId);
00892                 else
00893                 {
00894                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00895                                 InvalidTransactionId);
00896                     return false;
00897                 }
00898             }
00899         }
00900         else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
00901         {
00902             if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid */
00903                 return true;
00904 
00905             if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))         /* not deleter */
00906                 return true;
00907 
00908             if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
00909             {
00910                 TransactionId   xmax;
00911 
00912                 xmax = HeapTupleGetUpdateXid(tuple);
00913                 if (!TransactionIdIsValid(xmax))
00914                     return true;
00915 
00916                 /* updating subtransaction must have aborted */
00917                 if (!TransactionIdIsCurrentTransactionId(xmax))
00918                     return true;
00919                 else
00920                     return false;
00921             }
00922 
00923             if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
00924             {
00925                 /* deleting subtransaction must have aborted */
00926                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
00927                             InvalidTransactionId);
00928                 return true;
00929             }
00930 
00931             return false;
00932         }
00933         else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
00934         {
00935             snapshot->xmin = HeapTupleHeaderGetXmin(tuple);
00936             /* XXX shouldn't we fall through to look at xmax? */
00937             return true;        /* in insertion by other */
00938         }
00939         else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
00940             SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
00941                         HeapTupleHeaderGetXmin(tuple));
00942         else
00943         {
00944             /* it must have aborted or crashed */
00945             SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
00946                         InvalidTransactionId);
00947             return false;
00948         }
00949     }
00950 
00951     /* by here, the inserting transaction has committed */
00952 
00953     if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid or aborted */
00954         return true;
00955 
00956     if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
00957     {
00958         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00959             return true;
00960         return false;           /* updated by other */
00961     }
00962 
00963     if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
00964     {
00965         TransactionId   xmax;
00966 
00967         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00968             return true;
00969 
00970         xmax = HeapTupleGetUpdateXid(tuple);
00971         if (!TransactionIdIsValid(xmax))
00972             return true;
00973         if (TransactionIdIsCurrentTransactionId(xmax))
00974             return false;
00975         if (TransactionIdIsInProgress(xmax))
00976         {
00977             snapshot->xmax = xmax;
00978             return true;
00979         }
00980         if (TransactionIdDidCommit(xmax))
00981             return false;
00982         return true;
00983     }
00984 
00985     if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
00986     {
00987         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
00988             return true;
00989         return false;
00990     }
00991 
00992     if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
00993     {
00994         snapshot->xmax = HeapTupleHeaderGetRawXmax(tuple);
00995         return true;
00996     }
00997 
00998     if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
00999     {
01000         /* it must have aborted or crashed */
01001         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
01002                     InvalidTransactionId);
01003         return true;
01004     }
01005 
01006     /* xmax transaction committed */
01007 
01008     if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
01009     {
01010         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
01011                     InvalidTransactionId);
01012         return true;
01013     }
01014 
01015     SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
01016                 HeapTupleHeaderGetRawXmax(tuple));
01017     return false;               /* updated by other */
01018 }
01019 
01020 /*
01021  * HeapTupleSatisfiesMVCC
01022  *      True iff heap tuple is valid for the given MVCC snapshot.
01023  *
01024  *  Here, we consider the effects of:
01025  *      all transactions committed as of the time of the given snapshot
01026  *      previous commands of this transaction
01027  *
01028  *  Does _not_ include:
01029  *      transactions shown as in-progress by the snapshot
01030  *      transactions started after the snapshot was taken
01031  *      changes made by the current command
01032  *
01033  * This is the same as HeapTupleSatisfiesNow, except that transactions that
01034  * were in progress or as yet unstarted when the snapshot was taken will
01035  * be treated as uncommitted, even if they have committed by now.
01036  *
01037  * (Notice, however, that the tuple status hint bits will be updated on the
01038  * basis of the true state of the transaction, even if we then pretend we
01039  * can't see it.)
01040  */
01041 bool
01042 HeapTupleSatisfiesMVCC(HeapTupleHeader tuple, Snapshot snapshot,
01043                        Buffer buffer)
01044 {
01045     if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
01046     {
01047         if (tuple->t_infomask & HEAP_XMIN_INVALID)
01048             return false;
01049 
01050         /* Used by pre-9.0 binary upgrades */
01051         if (tuple->t_infomask & HEAP_MOVED_OFF)
01052         {
01053             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
01054 
01055             if (TransactionIdIsCurrentTransactionId(xvac))
01056                 return false;
01057             if (!TransactionIdIsInProgress(xvac))
01058             {
01059                 if (TransactionIdDidCommit(xvac))
01060                 {
01061                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
01062                                 InvalidTransactionId);
01063                     return false;
01064                 }
01065                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
01066                             InvalidTransactionId);
01067             }
01068         }
01069         /* Used by pre-9.0 binary upgrades */
01070         else if (tuple->t_infomask & HEAP_MOVED_IN)
01071         {
01072             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
01073 
01074             if (!TransactionIdIsCurrentTransactionId(xvac))
01075             {
01076                 if (TransactionIdIsInProgress(xvac))
01077                     return false;
01078                 if (TransactionIdDidCommit(xvac))
01079                     SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
01080                                 InvalidTransactionId);
01081                 else
01082                 {
01083                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
01084                                 InvalidTransactionId);
01085                     return false;
01086                 }
01087             }
01088         }
01089         else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
01090         {
01091             if (HeapTupleHeaderGetCmin(tuple) >= snapshot->curcid)
01092                 return false;   /* inserted after scan started */
01093 
01094             if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid */
01095                 return true;
01096 
01097             if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))         /* not deleter */
01098                 return true;
01099 
01100             if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
01101             {
01102                 TransactionId   xmax;
01103 
01104                 xmax = HeapTupleGetUpdateXid(tuple);
01105                 if (!TransactionIdIsValid(xmax))
01106                     return true;
01107 
01108                 /* updating subtransaction must have aborted */
01109                 if (!TransactionIdIsCurrentTransactionId(xmax))
01110                     return true;
01111                 else if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
01112                     return true;    /* updated after scan started */
01113                 else
01114                     return false;   /* updated before scan started */
01115             }
01116 
01117             if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
01118             {
01119                 /* deleting subtransaction must have aborted */
01120                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
01121                             InvalidTransactionId);
01122                 return true;
01123             }
01124 
01125             if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
01126                 return true;    /* deleted after scan started */
01127             else
01128                 return false;   /* deleted before scan started */
01129         }
01130         else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
01131             return false;
01132         else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
01133             SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
01134                         HeapTupleHeaderGetXmin(tuple));
01135         else
01136         {
01137             /* it must have aborted or crashed */
01138             SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
01139                         InvalidTransactionId);
01140             return false;
01141         }
01142     }
01143 
01144     /*
01145      * By here, the inserting transaction has committed - have to check
01146      * when...
01147      */
01148     if (XidInMVCCSnapshot(HeapTupleHeaderGetXmin(tuple), snapshot))
01149         return false;           /* treat as still in progress */
01150 
01151     if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid or aborted */
01152         return true;
01153 
01154     if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
01155         return true;
01156 
01157     if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
01158     {
01159         TransactionId   xmax;
01160 
01161         /* already checked above */
01162         Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
01163 
01164         xmax = HeapTupleGetUpdateXid(tuple);
01165         if (!TransactionIdIsValid(xmax))
01166             return true;
01167         if (TransactionIdIsCurrentTransactionId(xmax))
01168         {
01169             if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
01170                 return true;    /* deleted after scan started */
01171             else
01172                 return false;   /* deleted before scan started */
01173         }
01174         if (TransactionIdIsInProgress(xmax))
01175             return true;
01176         if (TransactionIdDidCommit(xmax))
01177         {
01178             /* updating transaction committed, but when? */
01179             if (XidInMVCCSnapshot(xmax, snapshot))
01180                 return true;    /* treat as still in progress */
01181             return false;
01182         }
01183         return true;
01184     }
01185 
01186     if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
01187     {
01188         if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
01189         {
01190             if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
01191                 return true;    /* deleted after scan started */
01192             else
01193                 return false;   /* deleted before scan started */
01194         }
01195 
01196         if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
01197             return true;
01198 
01199         if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
01200         {
01201             /* it must have aborted or crashed */
01202             SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
01203                         InvalidTransactionId);
01204             return true;
01205         }
01206 
01207         /* xmax transaction committed */
01208         SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
01209                     HeapTupleHeaderGetRawXmax(tuple));
01210     }
01211 
01212     /*
01213      * OK, the deleting transaction committed too ... but when?
01214      */
01215     if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
01216         return true;            /* treat as still in progress */
01217 
01218     return false;
01219 }
01220 
01221 
01222 /*
01223  * HeapTupleSatisfiesVacuum
01224  *
01225  *  Determine the status of tuples for VACUUM purposes.  Here, what
01226  *  we mainly want to know is if a tuple is potentially visible to *any*
01227  *  running transaction.  If so, it can't be removed yet by VACUUM.
01228  *
01229  * OldestXmin is a cutoff XID (obtained from GetOldestXmin()).  Tuples
01230  * deleted by XIDs >= OldestXmin are deemed "recently dead"; they might
01231  * still be visible to some open transaction, so we can't remove them,
01232  * even if we see that the deleting transaction has committed.
01233  */
01234 HTSV_Result
01235 HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
01236                          Buffer buffer)
01237 {
01238     /*
01239      * Has inserting transaction committed?
01240      *
01241      * If the inserting transaction aborted, then the tuple was never visible
01242      * to any other transaction, so we can delete it immediately.
01243      */
01244     if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
01245     {
01246         if (tuple->t_infomask & HEAP_XMIN_INVALID)
01247             return HEAPTUPLE_DEAD;
01248         /* Used by pre-9.0 binary upgrades */
01249         else if (tuple->t_infomask & HEAP_MOVED_OFF)
01250         {
01251             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
01252 
01253             if (TransactionIdIsCurrentTransactionId(xvac))
01254                 return HEAPTUPLE_DELETE_IN_PROGRESS;
01255             if (TransactionIdIsInProgress(xvac))
01256                 return HEAPTUPLE_DELETE_IN_PROGRESS;
01257             if (TransactionIdDidCommit(xvac))
01258             {
01259                 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
01260                             InvalidTransactionId);
01261                 return HEAPTUPLE_DEAD;
01262             }
01263             SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
01264                         InvalidTransactionId);
01265         }
01266         /* Used by pre-9.0 binary upgrades */
01267         else if (tuple->t_infomask & HEAP_MOVED_IN)
01268         {
01269             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
01270 
01271             if (TransactionIdIsCurrentTransactionId(xvac))
01272                 return HEAPTUPLE_INSERT_IN_PROGRESS;
01273             if (TransactionIdIsInProgress(xvac))
01274                 return HEAPTUPLE_INSERT_IN_PROGRESS;
01275             if (TransactionIdDidCommit(xvac))
01276                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
01277                             InvalidTransactionId);
01278             else
01279             {
01280                 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
01281                             InvalidTransactionId);
01282                 return HEAPTUPLE_DEAD;
01283             }
01284         }
01285         else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
01286         {
01287             if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid */
01288                 return HEAPTUPLE_INSERT_IN_PROGRESS;
01289             if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
01290                 return HEAPTUPLE_INSERT_IN_PROGRESS;
01291             /* inserted and then deleted by same xact */
01292             return HEAPTUPLE_DELETE_IN_PROGRESS;
01293         }
01294         else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
01295             SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
01296                         HeapTupleHeaderGetXmin(tuple));
01297         else
01298         {
01299             /*
01300              * Not in Progress, Not Committed, so either Aborted or crashed
01301              */
01302             SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
01303                         InvalidTransactionId);
01304             return HEAPTUPLE_DEAD;
01305         }
01306 
01307         /*
01308          * At this point the xmin is known committed, but we might not have
01309          * been able to set the hint bit yet; so we can no longer Assert that
01310          * it's set.
01311          */
01312     }
01313 
01314     /*
01315      * Okay, the inserter committed, so it was good at some point.  Now what
01316      * about the deleting transaction?
01317      */
01318     if (tuple->t_infomask & HEAP_XMAX_INVALID)
01319         return HEAPTUPLE_LIVE;
01320 
01321     if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
01322     {
01323         /*
01324          * "Deleting" xact really only locked it, so the tuple is live in any
01325          * case.  However, we should make sure that either XMAX_COMMITTED or
01326          * XMAX_INVALID gets set once the xact is gone, to reduce the costs of
01327          * examining the tuple for future xacts.  Also, marking dead
01328          * MultiXacts as invalid here provides defense against MultiXactId
01329          * wraparound (see also comments in heap_freeze_tuple()).
01330          */
01331         if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
01332         {
01333             if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
01334             {
01335                 /*
01336                  * If it's only locked but neither EXCL_LOCK nor KEYSHR_LOCK
01337                  * are set, it cannot possibly be running; otherwise have to
01338                  * check.
01339                  */
01340                 if ((tuple->t_infomask & (HEAP_XMAX_EXCL_LOCK |
01341                                           HEAP_XMAX_KEYSHR_LOCK)) &&
01342                     MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
01343                     return HEAPTUPLE_LIVE;
01344                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
01345 
01346             }
01347             else
01348             {
01349                 if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
01350                     return HEAPTUPLE_LIVE;
01351                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
01352                             InvalidTransactionId);
01353             }
01354         }
01355 
01356         /*
01357          * We don't really care whether xmax did commit, abort or crash.
01358          * We know that xmax did lock the tuple, but it did not and will
01359          * never actually update it.
01360          */
01361 
01362         return HEAPTUPLE_LIVE;
01363     }
01364 
01365     if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
01366     {
01367         TransactionId xmax;
01368 
01369         if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
01370         {
01371             /* already checked above */
01372             Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
01373 
01374             xmax = HeapTupleGetUpdateXid(tuple);
01375             if (!TransactionIdIsValid(xmax))
01376                 return HEAPTUPLE_LIVE;
01377             if (TransactionIdIsInProgress(xmax))
01378                 return HEAPTUPLE_DELETE_IN_PROGRESS;
01379             else if (TransactionIdDidCommit(xmax))
01380                 /* there are still lockers around -- can't return DEAD here */
01381                 return HEAPTUPLE_RECENTLY_DEAD;
01382             /* updating transaction aborted */
01383             return HEAPTUPLE_LIVE;
01384         }
01385 
01386         Assert(!(tuple->t_infomask & HEAP_XMAX_COMMITTED));
01387 
01388         xmax = HeapTupleGetUpdateXid(tuple);
01389         if (!TransactionIdIsValid(xmax))
01390             return HEAPTUPLE_LIVE;
01391         /* multi is not running -- updating xact cannot be */
01392         Assert(!TransactionIdIsInProgress(xmax));
01393         if (TransactionIdDidCommit(xmax))
01394         {
01395             if (!TransactionIdPrecedes(xmax, OldestXmin))
01396                 return HEAPTUPLE_RECENTLY_DEAD;
01397             else
01398                 return HEAPTUPLE_DEAD;
01399         }
01400         else
01401         {
01402             /*
01403              * Not in Progress, Not Committed, so either Aborted or crashed.
01404              */
01405             SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
01406             return HEAPTUPLE_LIVE;
01407         }
01408 
01409         /*
01410          * Deleter committed, but perhaps it was recent enough that some open
01411          * transactions could still see the tuple.
01412          */
01413 
01414         /* Otherwise, it's dead and removable */
01415         return HEAPTUPLE_DEAD;
01416     }
01417 
01418     if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
01419     {
01420         if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
01421             return HEAPTUPLE_DELETE_IN_PROGRESS;
01422         else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
01423             SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
01424                         HeapTupleHeaderGetRawXmax(tuple));
01425         else
01426         {
01427             /*
01428              * Not in Progress, Not Committed, so either Aborted or crashed
01429              */
01430             SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
01431                         InvalidTransactionId);
01432             return HEAPTUPLE_LIVE;
01433         }
01434 
01435         /*
01436          * At this point the xmax is known committed, but we might not have
01437          * been able to set the hint bit yet; so we can no longer Assert that
01438          * it's set.
01439          */
01440     }
01441 
01442     /*
01443      * Deleter committed, but perhaps it was recent enough that some open
01444      * transactions could still see the tuple.
01445      */
01446     if (!TransactionIdPrecedes(HeapTupleHeaderGetRawXmax(tuple), OldestXmin))
01447         return HEAPTUPLE_RECENTLY_DEAD;
01448 
01449     /* Otherwise, it's dead and removable */
01450     return HEAPTUPLE_DEAD;
01451 }
01452 
01453 /*
01454  * HeapTupleIsSurelyDead
01455  *
01456  *  Determine whether a tuple is surely dead.  We sometimes use this
01457  *  in lieu of HeapTupleSatisifesVacuum when the tuple has just been
01458  *  tested by HeapTupleSatisfiesMVCC and, therefore, any hint bits that
01459  *  can be set should already be set.  We assume that if no hint bits
01460  *  either for xmin or xmax, the transaction is still running.  This is
01461  *  therefore faster than HeapTupleSatisfiesVacuum, because we don't
01462  *  consult CLOG (and also because we don't need to give an exact answer,
01463  *  just whether or not the tuple is surely dead).
01464  */
01465 bool
01466 HeapTupleIsSurelyDead(HeapTupleHeader tuple, TransactionId OldestXmin)
01467 {
01468     /*
01469      * If the inserting transaction is marked invalid, then it aborted, and
01470      * the tuple is definitely dead.  If it's marked neither committed nor
01471      * invalid, then we assume it's still alive (since the presumption is that
01472      * all relevant hint bits were just set moments ago).
01473      */
01474     if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
01475         return (tuple->t_infomask & HEAP_XMIN_INVALID) != 0 ? true : false;
01476 
01477     /*
01478      * If the inserting transaction committed, but any deleting transaction
01479      * aborted, the tuple is still alive.
01480      */
01481     if (tuple->t_infomask & HEAP_XMAX_INVALID)
01482         return false;
01483 
01484     /*
01485      * If the XMAX is just a lock, the tuple is still alive.
01486      */
01487     if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
01488         return false;
01489 
01490     /*
01491      * If the Xmax is a MultiXact, it might be dead or alive, but we cannot
01492      * know without checking pg_multixact.
01493      */
01494     if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
01495         return false;
01496 
01497     /* If deleter isn't known to have committed, assume it's still running. */
01498     if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
01499         return false;
01500 
01501     /* Deleter committed, so tuple is dead if the XID is old enough. */
01502     return TransactionIdPrecedes(HeapTupleHeaderGetRawXmax(tuple), OldestXmin);
01503 }
01504 
01505 /*
01506  * XidInMVCCSnapshot
01507  *      Is the given XID still-in-progress according to the snapshot?
01508  *
01509  * Note: GetSnapshotData never stores either top xid or subxids of our own
01510  * backend into a snapshot, so these xids will not be reported as "running"
01511  * by this function.  This is OK for current uses, because we actually only
01512  * apply this for known-committed XIDs.
01513  */
01514 static bool
01515 XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
01516 {
01517     uint32      i;
01518 
01519     /*
01520      * Make a quick range check to eliminate most XIDs without looking at the
01521      * xip arrays.  Note that this is OK even if we convert a subxact XID to
01522      * its parent below, because a subxact with XID < xmin has surely also got
01523      * a parent with XID < xmin, while one with XID >= xmax must belong to a
01524      * parent that was not yet committed at the time of this snapshot.
01525      */
01526 
01527     /* Any xid < xmin is not in-progress */
01528     if (TransactionIdPrecedes(xid, snapshot->xmin))
01529         return false;
01530     /* Any xid >= xmax is in-progress */
01531     if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
01532         return true;
01533 
01534     /*
01535      * Snapshot information is stored slightly differently in snapshots taken
01536      * during recovery.
01537      */
01538     if (!snapshot->takenDuringRecovery)
01539     {
01540         /*
01541          * If the snapshot contains full subxact data, the fastest way to
01542          * check things is just to compare the given XID against both subxact
01543          * XIDs and top-level XIDs.  If the snapshot overflowed, we have to
01544          * use pg_subtrans to convert a subxact XID to its parent XID, but
01545          * then we need only look at top-level XIDs not subxacts.
01546          */
01547         if (!snapshot->suboverflowed)
01548         {
01549             /* full data, so search subxip */
01550             int32       j;
01551 
01552             for (j = 0; j < snapshot->subxcnt; j++)
01553             {
01554                 if (TransactionIdEquals(xid, snapshot->subxip[j]))
01555                     return true;
01556             }
01557 
01558             /* not there, fall through to search xip[] */
01559         }
01560         else
01561         {
01562             /* overflowed, so convert xid to top-level */
01563             xid = SubTransGetTopmostTransaction(xid);
01564 
01565             /*
01566              * If xid was indeed a subxact, we might now have an xid < xmin,
01567              * so recheck to avoid an array scan.  No point in rechecking
01568              * xmax.
01569              */
01570             if (TransactionIdPrecedes(xid, snapshot->xmin))
01571                 return false;
01572         }
01573 
01574         for (i = 0; i < snapshot->xcnt; i++)
01575         {
01576             if (TransactionIdEquals(xid, snapshot->xip[i]))
01577                 return true;
01578         }
01579     }
01580     else
01581     {
01582         int32       j;
01583 
01584         /*
01585          * In recovery we store all xids in the subxact array because it is by
01586          * far the bigger array, and we mostly don't know which xids are
01587          * top-level and which are subxacts. The xip array is empty.
01588          *
01589          * We start by searching subtrans, if we overflowed.
01590          */
01591         if (snapshot->suboverflowed)
01592         {
01593             /* overflowed, so convert xid to top-level */
01594             xid = SubTransGetTopmostTransaction(xid);
01595 
01596             /*
01597              * If xid was indeed a subxact, we might now have an xid < xmin,
01598              * so recheck to avoid an array scan.  No point in rechecking
01599              * xmax.
01600              */
01601             if (TransactionIdPrecedes(xid, snapshot->xmin))
01602                 return false;
01603         }
01604 
01605         /*
01606          * We now have either a top-level xid higher than xmin or an
01607          * indeterminate xid. We don't know whether it's top level or subxact
01608          * but it doesn't matter. If it's present, the xid is visible.
01609          */
01610         for (j = 0; j < snapshot->subxcnt; j++)
01611         {
01612             if (TransactionIdEquals(xid, snapshot->subxip[j]))
01613                 return true;
01614         }
01615     }
01616 
01617     return false;
01618 }
01619 
01620 /*
01621  * Is the tuple really only locked?  That is, is it not updated?
01622  *
01623  * It's easy to check just infomask bits if the locker is not a multi; but
01624  * otherwise we need to verify that the updating transaction has not aborted.
01625  *
01626  * This function is here because it follows the same time qualification rules
01627  * laid out at the top of this file.
01628  */
01629 bool
01630 HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
01631 {
01632     TransactionId   xmax;
01633 
01634     /* if there's no valid Xmax, then there's obviously no update either */
01635     if (tuple->t_infomask & HEAP_XMAX_INVALID)
01636         return true;
01637 
01638     if (tuple->t_infomask & HEAP_XMAX_LOCK_ONLY)
01639         return true;
01640 
01641     /* invalid xmax means no update */
01642     if (!TransactionIdIsValid(HeapTupleHeaderGetRawXmax(tuple)))
01643         return true;
01644 
01645     /*
01646      * if HEAP_XMAX_LOCK_ONLY is not set and not a multi, then this
01647      * must necessarily have been updated
01648      */
01649     if (!(tuple->t_infomask & HEAP_XMAX_IS_MULTI))
01650         return false;
01651 
01652     /* ... but if it's a multi, then perhaps the updating Xid aborted. */
01653     xmax = HeapTupleGetUpdateXid(tuple);
01654     if (!TransactionIdIsValid(xmax))    /* shouldn't happen .. */
01655         return true;
01656 
01657     if (TransactionIdIsCurrentTransactionId(xmax))
01658         return false;
01659     if (TransactionIdIsInProgress(xmax))
01660         return false;
01661     if (TransactionIdDidCommit(xmax))
01662         return false;
01663 
01664     /*
01665      * not current, not in progress, not committed -- must have aborted or
01666      * crashed
01667      */
01668     return true;
01669 }