~aglenyoung/+junk/postgres-9.3-dtrace

« back to all changes in this revision

Viewing changes to src/backend/access/heap/heapam.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt, Christoph Berg, Martin Pitt
  • Date: 2013-06-26 15:13:32 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20130626151332-p34yjpn0txbdsdzd
Tags: 9.3~beta2-1
[ Christoph Berg ]
* hurd-i386: Ignore testsuite failures so we have a working libpq5 (they
  don't implement semaphores so the server won't even start).
* Mark postgresql-9.3 as beta in the description, suggested by Joshua D.
  Drake.

[ Martin Pitt ]
* New upstream release 9.3 beta2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
120
120
static const struct
121
121
{
122
122
        LOCKMODE        hwlock;
123
 
        MultiXactStatus lockstatus;
124
 
        MultiXactStatus updstatus;
 
123
        MultiXactStatus lockstatus;
 
124
        MultiXactStatus updstatus;
125
125
}
126
 
tupleLockExtraInfo[MaxLockTupleMode + 1] =
 
126
 
 
127
                        tupleLockExtraInfo[MaxLockTupleMode + 1] =
127
128
{
128
 
        {       /* LockTupleKeyShare */
 
129
        {                                                       /* LockTupleKeyShare */
129
130
                AccessShareLock,
130
131
                MultiXactStatusForKeyShare,
131
 
                -1      /* KeyShare does not allow updating tuples */
 
132
                -1                                              /* KeyShare does not allow updating tuples */
132
133
        },
133
 
        {       /* LockTupleShare */
 
134
        {                                                       /* LockTupleShare */
134
135
                RowShareLock,
135
136
                MultiXactStatusForShare,
136
 
                -1      /* Share does not allow updating tuples */
 
137
                -1                                              /* Share does not allow updating tuples */
137
138
        },
138
 
        {       /* LockTupleNoKeyExclusive */
 
139
        {                                                       /* LockTupleNoKeyExclusive */
139
140
                ExclusiveLock,
140
141
                MultiXactStatusForNoKeyUpdate,
141
142
                MultiXactStatusNoKeyUpdate
142
143
        },
143
 
        {       /* LockTupleExclusive */
 
144
        {                                                       /* LockTupleExclusive */
144
145
                AccessExclusiveLock,
145
146
                MultiXactStatusForUpdate,
146
147
                MultiXactStatusUpdate
147
148
        }
148
149
};
 
150
 
149
151
/* Get the LOCKMODE for a given MultiXactStatus */
150
152
#define LOCKMODE_from_mxstatus(status) \
151
153
                        (tupleLockExtraInfo[TUPLOCK_from_mxstatus((status))].hwlock)
168
170
 */
169
171
static const int MultiXactStatusLock[MaxMultiXactStatus + 1] =
170
172
{
171
 
        LockTupleKeyShare,              /* ForKeyShare */
172
 
        LockTupleShare,                 /* ForShare */
173
 
        LockTupleNoKeyExclusive,                /* ForNoKeyUpdate */
174
 
        LockTupleExclusive,             /* ForUpdate */
175
 
        LockTupleNoKeyExclusive,                /* NoKeyUpdate */
176
 
        LockTupleExclusive              /* Update */
 
173
        LockTupleKeyShare,                      /* ForKeyShare */
 
174
        LockTupleShare,                         /* ForShare */
 
175
        LockTupleNoKeyExclusive,        /* ForNoKeyUpdate */
 
176
        LockTupleExclusive,                     /* ForUpdate */
 
177
        LockTupleNoKeyExclusive,        /* NoKeyUpdate */
 
178
        LockTupleExclusive                      /* Update */
177
179
};
178
180
 
179
181
/* Get the LockTupleMode for a given MultiXactStatus */
365
367
         * page. That's how index-only scans work fine in hot standby. A crucial
366
368
         * difference between index-only scans and heap scans is that the
367
369
         * index-only scan completely relies on the visibility map where as heap
368
 
         * scan looks at the page-level PD_ALL_VISIBLE flag. We are not sure if the
369
 
         * page-level flag can be trusted in the same way, because it might get
370
 
         * propagated somehow without being explicitly WAL-logged, e.g. via a full
371
 
         * page write. Until we can prove that beyond doubt, let's check each
 
370
         * scan looks at the page-level PD_ALL_VISIBLE flag. We are not sure if
 
371
         * the page-level flag can be trusted in the same way, because it might
 
372
         * get propagated somehow without being explicitly WAL-logged, e.g. via a
 
373
         * full page write. Until we can prove that beyond doubt, let's check each
372
374
         * tuple for visibility the hard way.
373
375
         */
374
376
        all_visible = PageIsAllVisible(dp) && !snapshot->takenDuringRecovery;
1880
1882
                 * tuple.  Check for XMIN match.
1881
1883
                 */
1882
1884
                if (TransactionIdIsValid(priorXmax) &&
1883
 
                        !TransactionIdEquals(priorXmax, HeapTupleHeaderGetXmin(tp.t_data)))
 
1885
                  !TransactionIdEquals(priorXmax, HeapTupleHeaderGetXmin(tp.t_data)))
1884
1886
                {
1885
1887
                        UnlockReleaseBuffer(buffer);
1886
1888
                        break;
2488
2490
                ((infomask & HEAP_XMAX_IS_MULTI) != 0 ? XLHL_XMAX_IS_MULTI : 0) |
2489
2491
                ((infomask & HEAP_XMAX_LOCK_ONLY) != 0 ? XLHL_XMAX_LOCK_ONLY : 0) |
2490
2492
                ((infomask & HEAP_XMAX_EXCL_LOCK) != 0 ? XLHL_XMAX_EXCL_LOCK : 0) |
2491
 
                /* note we ignore HEAP_XMAX_SHR_LOCK here */
 
2493
        /* note we ignore HEAP_XMAX_SHR_LOCK here */
2492
2494
                ((infomask & HEAP_XMAX_KEYSHR_LOCK) != 0 ? XLHL_XMAX_KEYSHR_LOCK : 0) |
2493
2495
                ((infomask2 & HEAP_KEYS_UPDATED) != 0 ?
2494
2496
                 XLHL_KEYS_UPDATED : 0);
2730
2732
        }
2731
2733
 
2732
2734
        /*
2733
 
         * If this is the first possibly-multixact-able operation in the
2734
 
         * current transaction, set my per-backend OldestMemberMXactId setting.
2735
 
         * We can be certain that the transaction will never become a member of
2736
 
         * any older MultiXactIds than that.  (We have to do this even if we
2737
 
         * end up just using our own TransactionId below, since some other
2738
 
         * backend could incorporate our XID into a MultiXact immediately
2739
 
         * afterwards.)
 
2735
         * If this is the first possibly-multixact-able operation in the current
 
2736
         * transaction, set my per-backend OldestMemberMXactId setting. We can be
 
2737
         * certain that the transaction will never become a member of any older
 
2738
         * MultiXactIds than that.      (We have to do this even if we end up just
 
2739
         * using our own TransactionId below, since some other backend could
 
2740
         * incorporate our XID into a MultiXact immediately afterwards.)
2740
2741
         */
2741
2742
        MultiXactIdSetOldestMember();
2742
2743
 
2846
2847
 
2847
2848
        result = heap_delete(relation, tid,
2848
2849
                                                 GetCurrentCommandId(true), InvalidSnapshot,
2849
 
                                                 true /* wait for commit */,
 
2850
                                                 true /* wait for commit */ ,
2850
2851
                                                 &hufd);
2851
2852
        switch (result)
2852
2853
        {
2936
2937
        bool            checked_lockers;
2937
2938
        bool            locker_remains;
2938
2939
        TransactionId xmax_new_tuple,
2939
 
                                  xmax_old_tuple;
 
2940
                                xmax_old_tuple;
2940
2941
        uint16          infomask_old_tuple,
2941
2942
                                infomask2_old_tuple,
2942
2943
                                infomask_new_tuple,
3006
3007
 
3007
3008
        /*
3008
3009
         * If we're not updating any "key" column, we can grab a weaker lock type.
3009
 
         * This allows for more concurrency when we are running simultaneously with
3010
 
         * foreign key checks.
 
3010
         * This allows for more concurrency when we are running simultaneously
 
3011
         * with foreign key checks.
3011
3012
         *
3012
 
         * Note that if a column gets detoasted while executing the update, but the
3013
 
         * value ends up being the same, this test will fail and we will use the
3014
 
         * stronger lock.  This is acceptable; the important case to optimize is
3015
 
         * updates that don't manipulate key columns, not those that
 
3013
         * Note that if a column gets detoasted while executing the update, but
 
3014
         * the value ends up being the same, this test will fail and we will use
 
3015
         * the stronger lock.  This is acceptable; the important case to optimize
 
3016
         * is updates that don't manipulate key columns, not those that
3016
3017
         * serendipitiously arrive at the same key values.
3017
3018
         */
3018
3019
        HeapSatisfiesHOTandKeyUpdate(relation, hot_attrs, key_attrs,
3026
3027
 
3027
3028
                /*
3028
3029
                 * If this is the first possibly-multixact-able operation in the
3029
 
                 * current transaction, set my per-backend OldestMemberMXactId setting.
3030
 
                 * We can be certain that the transaction will never become a member of
3031
 
                 * any older MultiXactIds than that.  (We have to do this even if we
3032
 
                 * end up just using our own TransactionId below, since some other
3033
 
                 * backend could incorporate our XID into a MultiXact immediately
3034
 
                 * afterwards.)
 
3030
                 * current transaction, set my per-backend OldestMemberMXactId
 
3031
                 * setting. We can be certain that the transaction will never become a
 
3032
                 * member of any older MultiXactIds than that.  (We have to do this
 
3033
                 * even if we end up just using our own TransactionId below, since
 
3034
                 * some other backend could incorporate our XID into a MultiXact
 
3035
                 * immediately afterwards.)
3035
3036
                 */
3036
3037
                MultiXactIdSetOldestMember();
3037
3038
        }
3064
3065
        }
3065
3066
        else if (result == HeapTupleBeingUpdated && wait)
3066
3067
        {
3067
 
                TransactionId   xwait;
 
3068
                TransactionId xwait;
3068
3069
                uint16          infomask;
3069
3070
                bool            can_continue = false;
3070
3071
 
3073
3074
                /*
3074
3075
                 * XXX note that we don't consider the "no wait" case here.  This
3075
3076
                 * isn't a problem currently because no caller uses that case, but it
3076
 
                 * should be fixed if such a caller is introduced.  It wasn't a problem
3077
 
                 * previously because this code would always wait, but now that some
3078
 
                 * tuple locks do not conflict with one of the lock modes we use, it is
3079
 
                 * possible that this case is interesting to handle specially.
 
3077
                 * should be fixed if such a caller is introduced.      It wasn't a
 
3078
                 * problem previously because this code would always wait, but now
 
3079
                 * that some tuple locks do not conflict with one of the lock modes we
 
3080
                 * use, it is possible that this case is interesting to handle
 
3081
                 * specially.
3080
3082
                 *
3081
 
                 * This may cause failures with third-party code that calls heap_update
3082
 
                 * directly.
 
3083
                 * This may cause failures with third-party code that calls
 
3084
                 * heap_update directly.
3083
3085
                 */
3084
3086
 
3085
3087
                /* must copy state data before unlocking buffer */
3109
3111
                 * gone (or even not sleep at all in some cases); we need to preserve
3110
3112
                 * it as locker, unless it is gone completely.
3111
3113
                 *
3112
 
                 * If it's not a multi, we need to check for sleeping conditions before
3113
 
                 * actually going to sleep.  If the update doesn't conflict with the
3114
 
                 * locks, we just continue without sleeping (but making sure it is
3115
 
                 * preserved).
 
3114
                 * If it's not a multi, we need to check for sleeping conditions
 
3115
                 * before actually going to sleep.      If the update doesn't conflict
 
3116
                 * with the locks, we just continue without sleeping (but making sure
 
3117
                 * it is preserved).
3116
3118
                 */
3117
3119
                if (infomask & HEAP_XMAX_IS_MULTI)
3118
3120
                {
3119
 
                        TransactionId   update_xact;
3120
 
                        int                             remain;
 
3121
                        TransactionId update_xact;
 
3122
                        int                     remain;
3121
3123
 
3122
3124
                        /* wait for multixact */
3123
3125
                        MultiXactIdWait((MultiXactId) xwait, mxact_status, &remain,
3135
3137
                                goto l2;
3136
3138
 
3137
3139
                        /*
3138
 
                         * Note that the multixact may not be done by now.  It could have
 
3140
                         * Note that the multixact may not be done by now.      It could have
3139
3141
                         * surviving members; our own xact or other subxacts of this
3140
3142
                         * backend, and also any other concurrent transaction that locked
3141
 
                         * the tuple with KeyShare if we only got TupleLockUpdate.  If this
3142
 
                         * is the case, we have to be careful to mark the updated tuple
3143
 
                         * with the surviving members in Xmax.
 
3143
                         * the tuple with KeyShare if we only got TupleLockUpdate.      If
 
3144
                         * this is the case, we have to be careful to mark the updated
 
3145
                         * tuple with the surviving members in Xmax.
3144
3146
                         *
3145
 
                         * Note that there could have been another update in the MultiXact.
3146
 
                         * In that case, we need to check whether it committed or aborted.
3147
 
                         * If it aborted we are safe to update it again; otherwise there is
3148
 
                         * an update conflict, and we have to return HeapTupleUpdated
3149
 
                         * below.
 
3147
                         * Note that there could have been another update in the
 
3148
                         * MultiXact. In that case, we need to check whether it committed
 
3149
                         * or aborted. If it aborted we are safe to update it again;
 
3150
                         * otherwise there is an update conflict, and we have to return
 
3151
                         * HeapTupleUpdated below.
3150
3152
                         *
3151
3153
                         * In the LockTupleExclusive case, we still need to preserve the
3152
3154
                         * surviving members: those would include the tuple locks we had
3167
3169
                else
3168
3170
                {
3169
3171
                        /*
3170
 
                         * If it's just a key-share locker, and we're not changing the
3171
 
                         * key columns, we don't need to wait for it to end; but we
3172
 
                         * need to preserve it as locker.
 
3172
                         * If it's just a key-share locker, and we're not changing the key
 
3173
                         * columns, we don't need to wait for it to end; but we need to
 
3174
                         * preserve it as locker.
3173
3175
                         */
3174
3176
                        if (HEAP_XMAX_IS_KEYSHR_LOCKED(infomask) && key_intact)
3175
3177
                        {
3176
3178
                                LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
3177
3179
 
3178
3180
                                /*
3179
 
                                 * recheck the locker; if someone else changed the tuple while we
3180
 
                                 * weren't looking, start over.
 
3181
                                 * recheck the locker; if someone else changed the tuple while
 
3182
                                 * we weren't looking, start over.
3181
3183
                                 */
3182
3184
                                if ((oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
3183
 
                                        !TransactionIdEquals(HeapTupleHeaderGetRawXmax(oldtup.t_data),
 
3185
                                        !TransactionIdEquals(
 
3186
                                                                        HeapTupleHeaderGetRawXmax(oldtup.t_data),
3184
3187
                                                                                 xwait))
3185
3188
                                        goto l2;
3186
3189
 
3194
3197
                                LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
3195
3198
 
3196
3199
                                /*
3197
 
                                 * xwait is done, but if xwait had just locked the tuple then some
3198
 
                                 * other xact could update this tuple before we get to this point.
3199
 
                                 * Check for xmax change, and start over if so.
 
3200
                                 * xwait is done, but if xwait had just locked the tuple then
 
3201
                                 * some other xact could update this tuple before we get to
 
3202
                                 * this point. Check for xmax change, and start over if so.
3200
3203
                                 */
3201
3204
                                if ((oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
3202
 
                                        !TransactionIdEquals(HeapTupleHeaderGetRawXmax(oldtup.t_data),
 
3205
                                        !TransactionIdEquals(
 
3206
                                                                        HeapTupleHeaderGetRawXmax(oldtup.t_data),
3203
3207
                                                                                 xwait))
3204
3208
                                        goto l2;
3205
3209
 
3247
3251
         * visible while we were busy locking the buffer, or during some
3248
3252
         * subsequent window during which we had it unlocked, we'll have to unlock
3249
3253
         * and re-lock, to avoid holding the buffer lock across an I/O.  That's a
3250
 
         * bit unfortunate, especially since we'll now have to recheck whether
3251
 
         * the tuple has been locked or updated under us, but hopefully it won't
 
3254
         * bit unfortunate, especially since we'll now have to recheck whether the
 
3255
         * tuple has been locked or updated under us, but hopefully it won't
3252
3256
         * happen very often.
3253
3257
         */
3254
3258
        if (vmbuffer == InvalidBuffer && PageIsAllVisible(page))
3656
3660
 
3657
3661
        /*
3658
3662
         * Extract the corresponding values.  XXX this is pretty inefficient if
3659
 
         * there are many indexed columns.      Should HeapSatisfiesHOTandKeyUpdate do a
3660
 
         * single heap_deform_tuple call on each tuple, instead?  But that doesn't
3661
 
         * work for system columns ...
 
3663
         * there are many indexed columns.      Should HeapSatisfiesHOTandKeyUpdate do
 
3664
         * a single heap_deform_tuple call on each tuple, instead?      But that
 
3665
         * doesn't work for system columns ...
3662
3666
         */
3663
3667
        value1 = heap_getattr(tup1, attrnum, tupdesc, &isnull1);
3664
3668
        value2 = heap_getattr(tup2, attrnum, tupdesc, &isnull2);
3720
3724
                                                         bool *satisfies_hot, bool *satisfies_key,
3721
3725
                                                         HeapTuple oldtup, HeapTuple newtup)
3722
3726
{
3723
 
        int             next_hot_attnum;
3724
 
        int             next_key_attnum;
3725
 
        bool    hot_result = true;
3726
 
        bool    key_result = true;
3727
 
        bool    key_done = false;
3728
 
        bool    hot_done = false;
 
3727
        int                     next_hot_attnum;
 
3728
        int                     next_key_attnum;
 
3729
        bool            hot_result = true;
 
3730
        bool            key_result = true;
 
3731
        bool            key_done = false;
 
3732
        bool            hot_done = false;
3729
3733
 
3730
3734
        next_hot_attnum = bms_first_member(hot_attrs);
3731
3735
        if (next_hot_attnum == -1)
3743
3747
 
3744
3748
        for (;;)
3745
3749
        {
3746
 
                int             check_now;
3747
 
                bool    changed;
 
3750
                int                     check_now;
 
3751
                bool            changed;
3748
3752
 
3749
3753
                /* both bitmapsets are now empty */
3750
3754
                if (key_done && hot_done)
3813
3817
 
3814
3818
        result = heap_update(relation, otid, tup,
3815
3819
                                                 GetCurrentCommandId(true), InvalidSnapshot,
3816
 
                                                 true /* wait for commit */,
 
3820
                                                 true /* wait for commit */ ,
3817
3821
                                                 &hufd, &lockmode);
3818
3822
        switch (result)
3819
3823
        {
3843
3847
static MultiXactStatus
3844
3848
get_mxact_status_for_lock(LockTupleMode mode, bool is_update)
3845
3849
{
3846
 
        MultiXactStatus         retval;
 
3850
        MultiXactStatus retval;
3847
3851
 
3848
3852
        if (is_update)
3849
3853
                retval = tupleLockExtraInfo[mode].updstatus;
3933
3937
                uint16          infomask;
3934
3938
                uint16          infomask2;
3935
3939
                bool            require_sleep;
3936
 
                ItemPointerData t_ctid;
 
3940
                ItemPointerData t_ctid;
3937
3941
 
3938
3942
                /* must copy state data before unlocking buffer */
3939
3943
                xwait = HeapTupleHeaderGetRawXmax(tuple->t_data);
3944
3948
                LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
3945
3949
 
3946
3950
                /*
3947
 
                 * If any subtransaction of the current top transaction already holds a
3948
 
                 * lock as strong or stronger than what we're requesting, we
 
3951
                 * If any subtransaction of the current top transaction already holds
 
3952
                 * a lock as strong or stronger than what we're requesting, we
3949
3953
                 * effectively hold the desired lock already.  We *must* succeed
3950
 
                 * without trying to take the tuple lock, else we will deadlock against
3951
 
                 * anyone wanting to acquire a stronger lock.
 
3954
                 * without trying to take the tuple lock, else we will deadlock
 
3955
                 * against anyone wanting to acquire a stronger lock.
3952
3956
                 */
3953
3957
                if (infomask & HEAP_XMAX_IS_MULTI)
3954
3958
                {
3955
 
                        int             i;
3956
 
                        int             nmembers;
 
3959
                        int                     i;
 
3960
                        int                     nmembers;
3957
3961
                        MultiXactMember *members;
3958
3962
 
3959
3963
                        /*
3960
 
                         * We don't need to allow old multixacts here; if that had been the
3961
 
                         * case, HeapTupleSatisfiesUpdate would have returned MayBeUpdated
3962
 
                         * and we wouldn't be here.
 
3964
                         * We don't need to allow old multixacts here; if that had been
 
3965
                         * the case, HeapTupleSatisfiesUpdate would have returned
 
3966
                         * MayBeUpdated and we wouldn't be here.
3963
3967
                         */
3964
3968
                        nmembers = GetMultiXactIdMembers(xwait, &members, false);
3965
3969
 
3967
3971
                        {
3968
3972
                                if (TransactionIdIsCurrentTransactionId(members[i].xid))
3969
3973
                                {
3970
 
                                        LockTupleMode   membermode;
 
3974
                                        LockTupleMode membermode;
3971
3975
 
3972
3976
                                        membermode = TUPLOCK_from_mxstatus(members[i].status);
3973
3977
 
4001
4005
                                if (!ConditionalLockTupleTuplock(relation, tid, mode))
4002
4006
                                        ereport(ERROR,
4003
4007
                                                        (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
4004
 
                                                         errmsg("could not obtain lock on row in relation \"%s\"",
4005
 
                                                                        RelationGetRelationName(relation))));
 
4008
                                        errmsg("could not obtain lock on row in relation \"%s\"",
 
4009
                                                   RelationGetRelationName(relation))));
4006
4010
                        }
4007
4011
                        else
4008
4012
                                LockTupleTuplock(relation, tid, mode);
4023
4027
                         * continue if the key hasn't been modified.
4024
4028
                         *
4025
4029
                         * However, if there are updates, we need to walk the update chain
4026
 
                         * to mark future versions of the row as locked, too.  That way, if
4027
 
                         * somebody deletes that future version, we're protected against
4028
 
                         * the key going away.  This locking of future versions could block
4029
 
                         * momentarily, if a concurrent transaction is deleting a key; or
4030
 
                         * it could return a value to the effect that the transaction
4031
 
                         * deleting the key has already committed.  So we do this before
4032
 
                         * re-locking the buffer; otherwise this would be prone to
4033
 
                         * deadlocks.
 
4030
                         * to mark future versions of the row as locked, too.  That way,
 
4031
                         * if somebody deletes that future version, we're protected
 
4032
                         * against the key going away.  This locking of future versions
 
4033
                         * could block momentarily, if a concurrent transaction is
 
4034
                         * deleting a key; or it could return a value to the effect that
 
4035
                         * the transaction deleting the key has already committed.      So we
 
4036
                         * do this before re-locking the buffer; otherwise this would be
 
4037
                         * prone to deadlocks.
4034
4038
                         *
4035
4039
                         * Note that the TID we're locking was grabbed before we unlocked
4036
 
                         * the buffer.  For it to change while we're not looking, the other
4037
 
                         * properties we're testing for below after re-locking the buffer
4038
 
                         * would also change, in which case we would restart this loop
4039
 
                         * above.
 
4040
                         * the buffer.  For it to change while we're not looking, the
 
4041
                         * other properties we're testing for below after re-locking the
 
4042
                         * buffer would also change, in which case we would restart this
 
4043
                         * loop above.
4040
4044
                         */
4041
4045
                        if (!(infomask2 & HEAP_KEYS_UPDATED))
4042
4046
                        {
4043
 
                                bool    updated;
 
4047
                                bool            updated;
4044
4048
 
4045
4049
                                updated = !HEAP_XMAX_IS_LOCKED_ONLY(infomask);
4046
4050
 
4047
4051
                                /*
4048
 
                                 * If there are updates, follow the update chain; bail out
4049
 
                                 * if that cannot be done.
 
4052
                                 * If there are updates, follow the update chain; bail out if
 
4053
                                 * that cannot be done.
4050
4054
                                 */
4051
4055
                                if (follow_updates && updated)
4052
4056
                                {
4053
 
                                        HTSU_Result             res;
 
4057
                                        HTSU_Result res;
4054
4058
 
4055
4059
                                        res = heap_lock_updated_tuple(relation, tuple, &t_ctid,
4056
4060
                                                                                                  GetCurrentTransactionId(),
4069
4073
                                /*
4070
4074
                                 * Make sure it's still an appropriate lock, else start over.
4071
4075
                                 * Also, if it wasn't updated before we released the lock, but
4072
 
                                 * is updated now, we start over too; the reason is that we now
4073
 
                                 * need to follow the update chain to lock the new versions.
 
4076
                                 * is updated now, we start over too; the reason is that we
 
4077
                                 * now need to follow the update chain to lock the new
 
4078
                                 * versions.
4074
4079
                                 */
4075
4080
                                if (!HeapTupleHeaderIsOnlyLocked(tuple->t_data) &&
4076
4081
                                        ((tuple->t_data->t_infomask2 & HEAP_KEYS_UPDATED) ||
4114
4119
                {
4115
4120
                        /*
4116
4121
                         * If we're requesting NoKeyExclusive, we might also be able to
4117
 
                         * avoid sleeping; just ensure that there's no other lock type than
4118
 
                         * KeyShare.  Note that this is a bit more involved than just
 
4122
                         * avoid sleeping; just ensure that there's no other lock type
 
4123
                         * than KeyShare.  Note that this is a bit more involved than just
4119
4124
                         * checking hint bits -- we need to expand the multixact to figure
4120
4125
                         * out lock modes for each one (unless there was only one such
4121
4126
                         * locker).
4122
4127
                         */
4123
4128
                        if (infomask & HEAP_XMAX_IS_MULTI)
4124
4129
                        {
4125
 
                                int             nmembers;
 
4130
                                int                     nmembers;
4126
4131
                                MultiXactMember *members;
4127
4132
 
4128
4133
                                /*
4129
 
                                 * We don't need to allow old multixacts here; if that had been
4130
 
                                 * the case, HeapTupleSatisfiesUpdate would have returned
 
4134
                                 * We don't need to allow old multixacts here; if that had
 
4135
                                 * been the case, HeapTupleSatisfiesUpdate would have returned
4131
4136
                                 * MayBeUpdated and we wouldn't be here.
4132
4137
                                 */
4133
4138
                                nmembers = GetMultiXactIdMembers(xwait, &members, false);
4135
4140
                                if (nmembers <= 0)
4136
4141
                                {
4137
4142
                                        /*
4138
 
                                         * No need to keep the previous xmax here. This is unlikely
4139
 
                                         * to happen.
 
4143
                                         * No need to keep the previous xmax here. This is
 
4144
                                         * unlikely to happen.
4140
4145
                                         */
4141
4146
                                        require_sleep = false;
4142
4147
                                }
4143
4148
                                else
4144
4149
                                {
4145
 
                                        int             i;
4146
 
                                        bool    allowed = true;
 
4150
                                        int                     i;
 
4151
                                        bool            allowed = true;
4147
4152
 
4148
4153
                                        for (i = 0; i < nmembers; i++)
4149
4154
                                        {
4180
4185
 
4181
4186
                                /* if the xmax changed in the meantime, start over */
4182
4187
                                if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
4183
 
                                        !TransactionIdEquals(HeapTupleHeaderGetRawXmax(tuple->t_data),
 
4188
                                        !TransactionIdEquals(
 
4189
                                                                        HeapTupleHeaderGetRawXmax(tuple->t_data),
4184
4190
                                                                                 xwait))
4185
4191
                                        goto l3;
4186
4192
                                /* otherwise, we're good */
4221
4227
                                if (follow_updates &&
4222
4228
                                        !HEAP_XMAX_IS_LOCKED_ONLY(infomask))
4223
4229
                                {
4224
 
                                        HTSU_Result             res;
 
4230
                                        HTSU_Result res;
4225
4231
 
4226
4232
                                        res = heap_lock_updated_tuple(relation, tuple, &t_ctid,
4227
4233
                                                                                                  GetCurrentTransactionId(),
4243
4249
                                 * for xmax change, and start over if so.
4244
4250
                                 */
4245
4251
                                if (!(tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
4246
 
                                        !TransactionIdEquals(HeapTupleHeaderGetRawXmax(tuple->t_data),
 
4252
                                        !TransactionIdEquals(
 
4253
                                                                        HeapTupleHeaderGetRawXmax(tuple->t_data),
4247
4254
                                                                                 xwait))
4248
4255
                                        goto l3;
4249
4256
 
4251
4258
                                 * Of course, the multixact might not be done here: if we're
4252
4259
                                 * requesting a light lock mode, other transactions with light
4253
4260
                                 * locks could still be alive, as well as locks owned by our
4254
 
                                 * own xact or other subxacts of this backend.  We need to
 
4261
                                 * own xact or other subxacts of this backend.  We need to
4255
4262
                                 * preserve the surviving MultiXact members.  Note that it
4256
4263
                                 * isn't absolutely necessary in the latter case, but doing so
4257
4264
                                 * is simpler.
4275
4282
                                if (follow_updates &&
4276
4283
                                        !HEAP_XMAX_IS_LOCKED_ONLY(infomask))
4277
4284
                                {
4278
 
                                        HTSU_Result             res;
 
4285
                                        HTSU_Result res;
4279
4286
 
4280
4287
                                        res = heap_lock_updated_tuple(relation, tuple, &t_ctid,
4281
4288
                                                                                                  GetCurrentTransactionId(),
4294
4301
                                /*
4295
4302
                                 * xwait is done, but if xwait had just locked the tuple then
4296
4303
                                 * some other xact could update this tuple before we get to
4297
 
                                 * this point.  Check for xmax change, and start over if so.
 
4304
                                 * this point.  Check for xmax change, and start over if so.
4298
4305
                                 */
4299
4306
                                if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
4300
 
                                        !TransactionIdEquals(HeapTupleHeaderGetRawXmax(tuple->t_data),
 
4307
                                        !TransactionIdEquals(
 
4308
                                                                        HeapTupleHeaderGetRawXmax(tuple->t_data),
4301
4309
                                                                                 xwait))
4302
4310
                                        goto l3;
4303
4311
 
4304
4312
                                /*
4305
 
                                 * Otherwise check if it committed or aborted.  Note we cannot
 
4313
                                 * Otherwise check if it committed or aborted.  Note we cannot
4306
4314
                                 * be here if the tuple was only locked by somebody who didn't
4307
4315
                                 * conflict with us; that should have been handled above.  So
4308
4316
                                 * that transaction must necessarily be gone by now.
4355
4363
         * for cases where it is a plain TransactionId.
4356
4364
         *
4357
4365
         * Note in particular that this covers the case where we already hold
4358
 
         * exclusive lock on the tuple and the caller only wants key share or share
4359
 
         * lock. It would certainly not do to give up the exclusive lock.
 
4366
         * exclusive lock on the tuple and the caller only wants key share or
 
4367
         * share lock. It would certainly not do to give up the exclusive lock.
4360
4368
         */
4361
4369
        if (!(old_infomask & (HEAP_XMAX_INVALID |
4362
4370
                                                  HEAP_XMAX_COMMITTED |
4379
4387
        }
4380
4388
 
4381
4389
        /*
4382
 
         * If this is the first possibly-multixact-able operation in the
4383
 
         * current transaction, set my per-backend OldestMemberMXactId setting.
4384
 
         * We can be certain that the transaction will never become a member of
4385
 
         * any older MultiXactIds than that.  (We have to do this even if we
4386
 
         * end up just using our own TransactionId below, since some other
4387
 
         * backend could incorporate our XID into a MultiXact immediately
4388
 
         * afterwards.)
 
4390
         * If this is the first possibly-multixact-able operation in the current
 
4391
         * transaction, set my per-backend OldestMemberMXactId setting. We can be
 
4392
         * certain that the transaction will never become a member of any older
 
4393
         * MultiXactIds than that.      (We have to do this even if we end up just
 
4394
         * using our own TransactionId below, since some other backend could
 
4395
         * incorporate our XID into a MultiXact immediately afterwards.)
4389
4396
         */
4390
4397
        MultiXactIdSetOldestMember();
4391
4398
 
4419
4426
        HeapTupleHeaderSetXmax(tuple->t_data, xid);
4420
4427
 
4421
4428
        /*
4422
 
         * Make sure there is no forward chain link in t_ctid.  Note that in the
 
4429
         * Make sure there is no forward chain link in t_ctid.  Note that in the
4423
4430
         * cases where the tuple has been updated, we must not overwrite t_ctid,
4424
4431
         * because it was set by the updater.  Moreover, if the tuple has been
4425
 
         * updated, we need to follow the update chain to lock the new versions
4426
 
         * of the tuple as well.
 
4432
         * updated, we need to follow the update chain to lock the new versions of
 
4433
         * the tuple as well.
4427
4434
         */
4428
4435
        if (HEAP_XMAX_IS_LOCKED_ONLY(new_infomask))
4429
4436
                tuple->t_data->t_ctid = *tid;
4514
4521
                                                  TransactionId *result_xmax, uint16 *result_infomask,
4515
4522
                                                  uint16 *result_infomask2)
4516
4523
{
4517
 
        TransactionId   new_xmax;
4518
 
        uint16                  new_infomask,
4519
 
                                        new_infomask2;
 
4524
        TransactionId new_xmax;
 
4525
        uint16          new_infomask,
 
4526
                                new_infomask2;
4520
4527
 
4521
4528
l5:
4522
4529
        new_infomask = 0;
4562
4569
        }
4563
4570
        else if (old_infomask & HEAP_XMAX_IS_MULTI)
4564
4571
        {
4565
 
                MultiXactStatus         new_status;
 
4572
                MultiXactStatus new_status;
4566
4573
 
4567
4574
                /*
4568
 
                 * Currently we don't allow XMAX_COMMITTED to be set for multis,
4569
 
                 * so cross-check.
 
4575
                 * Currently we don't allow XMAX_COMMITTED to be set for multis, so
 
4576
                 * cross-check.
4570
4577
                 */
4571
4578
                Assert(!(old_infomask & HEAP_XMAX_COMMITTED));
4572
4579
 
4587
4594
 
4588
4595
                /*
4589
4596
                 * If the XMAX is already a MultiXactId, then we need to expand it to
4590
 
                 * include add_to_xmax; but if all the members were lockers and are all
4591
 
                 * gone, we can do away with the IS_MULTI bit and just set add_to_xmax
4592
 
                 * as the only locker/updater.  If all lockers are gone and we have an
4593
 
                 * updater that aborted, we can also do without a multi.
 
4597
                 * include add_to_xmax; but if all the members were lockers and are
 
4598
                 * all gone, we can do away with the IS_MULTI bit and just set
 
4599
                 * add_to_xmax as the only locker/updater.      If all lockers are gone
 
4600
                 * and we have an updater that aborted, we can also do without a
 
4601
                 * multi.
4594
4602
                 *
4595
4603
                 * The cost of doing GetMultiXactIdMembers would be paid by
4596
4604
                 * MultiXactIdExpand if we weren't to do this, so this check is not
4624
4632
                 * It's a committed update, so we need to preserve him as updater of
4625
4633
                 * the tuple.
4626
4634
                 */
4627
 
                MultiXactStatus         status;
4628
 
                MultiXactStatus         new_status;
 
4635
                MultiXactStatus status;
 
4636
                MultiXactStatus new_status;
4629
4637
 
4630
4638
                if (old_infomask2 & HEAP_KEYS_UPDATED)
4631
4639
                        status = MultiXactStatusUpdate;
4633
4641
                        status = MultiXactStatusNoKeyUpdate;
4634
4642
 
4635
4643
                new_status = get_mxact_status_for_lock(mode, is_update);
 
4644
 
4636
4645
                /*
4637
4646
                 * since it's not running, it's obviously impossible for the old
4638
4647
                 * updater to be identical to the current one, so we need not check
4648
4657
                 * create a new MultiXactId that includes both the old locker or
4649
4658
                 * updater and our own TransactionId.
4650
4659
                 */
4651
 
                MultiXactStatus         status;
4652
 
                MultiXactStatus         new_status;
 
4660
                MultiXactStatus status;
 
4661
                MultiXactStatus new_status;
4653
4662
 
4654
4663
                if (HEAP_XMAX_IS_LOCKED_ONLY(old_infomask))
4655
4664
                {
4668
4677
                        {
4669
4678
                                /*
4670
4679
                                 * LOCK_ONLY can be present alone only when a page has been
4671
 
                                 * upgraded by pg_upgrade.  But in that case,
4672
 
                                 * TransactionIdIsInProgress() should have returned false.  We
 
4680
                                 * upgraded by pg_upgrade.      But in that case,
 
4681
                                 * TransactionIdIsInProgress() should have returned false.      We
4673
4682
                                 * assume it's no longer locked in this case.
4674
4683
                                 */
4675
4684
                                elog(WARNING, "LOCK_ONLY found for Xid in progress %u", xmax);
4696
4705
                 */
4697
4706
                if (xmax == add_to_xmax)
4698
4707
                {
4699
 
                        LockTupleMode   old_mode = TUPLOCK_from_mxstatus(status);
4700
 
                        bool                    old_isupd = ISUPDATE_from_mxstatus(status);
 
4708
                        LockTupleMode old_mode = TUPLOCK_from_mxstatus(status);
 
4709
                        bool            old_isupd = ISUPDATE_from_mxstatus(status);
4701
4710
 
4702
4711
                        /*
4703
4712
                         * We can do this if the new LockTupleMode is higher or equal than
4728
4737
                 * It's a committed update, so we gotta preserve him as updater of the
4729
4738
                 * tuple.
4730
4739
                 */
4731
 
                MultiXactStatus         status;
4732
 
                MultiXactStatus         new_status;
 
4740
                MultiXactStatus status;
 
4741
                MultiXactStatus new_status;
4733
4742
 
4734
4743
                if (old_infomask2 & HEAP_KEYS_UPDATED)
4735
4744
                        status = MultiXactStatusUpdate;
4737
4746
                        status = MultiXactStatusNoKeyUpdate;
4738
4747
 
4739
4748
                new_status = get_mxact_status_for_lock(mode, is_update);
 
4749
 
4740
4750
                /*
4741
4751
                 * since it's not running, it's obviously impossible for the old
4742
4752
                 * updater to be identical to the current one, so we need not check
4774
4784
heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
4775
4785
                                                        LockTupleMode mode)
4776
4786
{
4777
 
        ItemPointerData tupid;
4778
 
        HeapTupleData   mytup;
4779
 
        Buffer                  buf;
4780
 
        uint16                  new_infomask,
4781
 
                                        new_infomask2,
4782
 
                                        old_infomask;
4783
 
        TransactionId   xmax,
4784
 
                                        new_xmax;
 
4787
        ItemPointerData tupid;
 
4788
        HeapTupleData mytup;
 
4789
        Buffer          buf;
 
4790
        uint16          new_infomask,
 
4791
                                new_infomask2,
 
4792
                                old_infomask;
 
4793
        TransactionId xmax,
 
4794
                                new_xmax;
4785
4795
 
4786
4796
        ItemPointerCopy(tid, &tupid);
4787
4797
 
4802
4812
                xmax = HeapTupleHeaderGetRawXmax(mytup.t_data);
4803
4813
 
4804
4814
                /*
4805
 
                 * If this tuple is updated and the key has been modified (or deleted),
4806
 
                 * what we do depends on the status of the updating transaction: if
4807
 
                 * it's live, we sleep until it finishes; if it has committed, we have
4808
 
                 * to fail (i.e. return HeapTupleUpdated); if it aborted, we ignore it.
4809
 
                 * For updates that didn't touch the key, we can just plough ahead.
 
4815
                 * If this tuple is updated and the key has been modified (or
 
4816
                 * deleted), what we do depends on the status of the updating
 
4817
                 * transaction: if it's live, we sleep until it finishes; if it has
 
4818
                 * committed, we have to fail (i.e. return HeapTupleUpdated); if it
 
4819
                 * aborted, we ignore it. For updates that didn't touch the key, we
 
4820
                 * can just plough ahead.
4810
4821
                 */
4811
4822
                if (!(old_infomask & HEAP_XMAX_INVALID) &&
4812
4823
                        (mytup.t_data->t_infomask2 & HEAP_KEYS_UPDATED))
4813
4824
                {
4814
 
                        TransactionId   update_xid;
 
4825
                        TransactionId update_xid;
4815
4826
 
4816
4827
                        /*
4817
4828
                         * Note: we *must* check TransactionIdIsInProgress before
4832
4843
                                goto l4;
4833
4844
                        }
4834
4845
                        else if (TransactionIdDidAbort(update_xid))
4835
 
                                ;       /* okay to proceed */
 
4846
                                ;                               /* okay to proceed */
4836
4847
                        else if (TransactionIdDidCommit(update_xid))
4837
4848
                        {
4838
4849
                                UnlockReleaseBuffer(buf);
4861
4872
                {
4862
4873
                        xl_heap_lock_updated xlrec;
4863
4874
                        XLogRecPtr      recptr;
4864
 
                        XLogRecData     rdata[2];
 
4875
                        XLogRecData rdata[2];
4865
4876
                        Page            page = BufferGetPage(buf);
4866
4877
 
4867
4878
                        xlrec.target.node = rel->rd_node;
4889
4900
 
4890
4901
                /* if we find the end of update chain, we're done. */
4891
4902
                if (mytup.t_data->t_infomask & HEAP_XMAX_INVALID ||
4892
 
                        ItemPointerEquals(&mytup.t_self, &mytup.t_data->t_ctid)  ||
 
4903
                        ItemPointerEquals(&mytup.t_self, &mytup.t_data->t_ctid) ||
4893
4904
                        HeapTupleHeaderIsOnlyLocked(mytup.t_data))
4894
4905
                {
4895
4906
                        UnlockReleaseBuffer(buf);
4904
4915
 
4905
4916
/*
4906
4917
 * heap_lock_updated_tuple
4907
 
 *              Follow update chain when locking an updated tuple, acquiring locks (row
4908
 
 *              marks) on the updated versions.
 
4918
 *              Follow update chain when locking an updated tuple, acquiring locks (row
 
4919
 *              marks) on the updated versions.
4909
4920
 *
4910
4921
 * The initial tuple is assumed to be already locked.
4911
4922
 *
4912
4923
 * This function doesn't check visibility, it just inconditionally marks the
4913
 
 * tuple(s) as locked.  If any tuple in the updated chain is being deleted
 
4924
 * tuple(s) as locked.  If any tuple in the updated chain is being deleted
4914
4925
 * concurrently (or updated with the key being modified), sleep until the
4915
4926
 * transaction doing it is finished.
4916
4927
 *
4932
4943
        {
4933
4944
                /*
4934
4945
                 * If this is the first possibly-multixact-able operation in the
4935
 
                 * current transaction, set my per-backend OldestMemberMXactId setting.
4936
 
                 * We can be certain that the transaction will never become a member of
4937
 
                 * any older MultiXactIds than that.  (We have to do this even if we
4938
 
                 * end up just using our own TransactionId below, since some other
4939
 
                 * backend could incorporate our XID into a MultiXact immediately
4940
 
                 * afterwards.)
 
4946
                 * current transaction, set my per-backend OldestMemberMXactId
 
4947
                 * setting. We can be certain that the transaction will never become a
 
4948
                 * member of any older MultiXactIds than that.  (We have to do this
 
4949
                 * even if we end up just using our own TransactionId below, since
 
4950
                 * some other backend could incorporate our XID into a MultiXact
 
4951
                 * immediately afterwards.)
4941
4952
                 */
4942
4953
                MultiXactIdSetOldestMember();
4943
4954
 
5117
5128
                HeapTupleHeaderSetXmax(tuple, InvalidTransactionId);
5118
5129
 
5119
5130
                /*
5120
 
                 * The tuple might be marked either XMAX_INVALID or XMAX_COMMITTED
5121
 
                 * + LOCKED.  Normalize to INVALID just to be sure no one gets
5122
 
                 * confused.  Also get rid of the HEAP_KEYS_UPDATED bit.
 
5131
                 * The tuple might be marked either XMAX_INVALID or XMAX_COMMITTED +
 
5132
                 * LOCKED.      Normalize to INVALID just to be sure no one gets confused.
 
5133
                 * Also get rid of the HEAP_KEYS_UPDATED bit.
5123
5134
                 */
5124
5135
                tuple->t_infomask &= ~HEAP_XMAX_BITS;
5125
5136
                tuple->t_infomask |= HEAP_XMAX_INVALID;
5172
5183
GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask,
5173
5184
                                           uint16 *new_infomask2)
5174
5185
{
5175
 
        int             nmembers;
5176
 
        MultiXactMember *members;
5177
 
        int             i;
5178
 
        uint16  bits = HEAP_XMAX_IS_MULTI;
5179
 
        uint16  bits2 = 0;
5180
 
        bool    has_update = false;
5181
 
        LockTupleMode   strongest = LockTupleKeyShare;
 
5186
        int                     nmembers;
 
5187
        MultiXactMember *members;
 
5188
        int                     i;
 
5189
        uint16          bits = HEAP_XMAX_IS_MULTI;
 
5190
        uint16          bits2 = 0;
 
5191
        bool            has_update = false;
 
5192
        LockTupleMode strongest = LockTupleKeyShare;
5182
5193
 
5183
5194
        /*
5184
5195
         * We only use this in multis we just created, so they cannot be values
5188
5199
 
5189
5200
        for (i = 0; i < nmembers; i++)
5190
5201
        {
5191
 
                LockTupleMode   mode;
 
5202
                LockTupleMode mode;
5192
5203
 
5193
5204
                /*
5194
5205
                 * Remember the strongest lock mode held by any member of the
5249
5260
static TransactionId
5250
5261
MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask)
5251
5262
{
5252
 
        TransactionId   update_xact = InvalidTransactionId;
5253
 
        MultiXactMember *members;
5254
 
        int                             nmembers;
 
5263
        TransactionId update_xact = InvalidTransactionId;
 
5264
        MultiXactMember *members;
 
5265
        int                     nmembers;
5255
5266
 
5256
5267
        Assert(!(t_infomask & HEAP_XMAX_LOCK_ONLY));
5257
5268
        Assert(t_infomask & HEAP_XMAX_IS_MULTI);
5258
5269
 
5259
5270
        /*
5260
 
         * Since we know the LOCK_ONLY bit is not set, this cannot be a
5261
 
         * multi from pre-pg_upgrade.
 
5271
         * Since we know the LOCK_ONLY bit is not set, this cannot be a multi from
 
5272
         * pre-pg_upgrade.
5262
5273
         */
5263
5274
        nmembers = GetMultiXactIdMembers(xmax, &members, false);
5264
5275
 
5265
5276
        if (nmembers > 0)
5266
5277
        {
5267
 
                int             i;
 
5278
                int                     i;
5268
5279
 
5269
5280
                for (i = 0; i < nmembers; i++)
5270
5281
                {
5284
5295
                                   members[i].status == MultiXactStatusUpdate);
5285
5296
                        update_xact = members[i].xid;
5286
5297
#ifndef USE_ASSERT_CHECKING
 
5298
 
5287
5299
                        /*
5288
5300
                         * in an assert-enabled build, walk the whole array to ensure
5289
5301
                         * there's no other updater.
5300
5312
 
5301
5313
/*
5302
5314
 * HeapTupleGetUpdateXid
5303
 
 *              As above, but use a HeapTupleHeader
 
5315
 *              As above, but use a HeapTupleHeader
5304
5316
 *
5305
5317
 * See also HeapTupleHeaderGetUpdateXid, which can be used without previously
5306
5318
 * checking the hint bits.
5314
5326
 
5315
5327
/*
5316
5328
 * Do_MultiXactIdWait
5317
 
 *              Actual implementation for the two functions below.
 
5329
 *              Actual implementation for the two functions below.
5318
5330
 *
5319
5331
 * We do this by sleeping on each member using XactLockTableWait.  Any
5320
5332
 * members that belong to the current backend are *not* waited for, however;
5432
5444
 * heap_tuple_needs_freeze
5433
5445
 *
5434
5446
 * Check to see whether any of the XID fields of a tuple (xmin, xmax, xvac)
5435
 
 * are older than the specified cutoff XID or MultiXactId.  If so, return TRUE.
 
5447
 * are older than the specified cutoff XID or MultiXactId.      If so, return TRUE.
5436
5448
 *
5437
5449
 * It doesn't matter whether the tuple is alive or dead, we are checking
5438
5450
 * to see if a tuple needs to be removed or frozen to avoid wraparound.
6091
6103
{
6092
6104
        xl_heap_freeze *xlrec = (xl_heap_freeze *) XLogRecGetData(record);
6093
6105
        TransactionId cutoff_xid = xlrec->cutoff_xid;
6094
 
        MultiXactId     cutoff_multi = xlrec->cutoff_multi;
 
6106
        MultiXactId cutoff_multi = xlrec->cutoff_multi;
6095
6107
        Buffer          buffer;
6096
6108
        Page            page;
6097
6109
 
6361
6373
                return;
6362
6374
        page = (Page) BufferGetPage(buffer);
6363
6375
 
6364
 
        if (lsn <= PageGetLSN(page))            /* changes are applied */
 
6376
        if (lsn <= PageGetLSN(page))    /* changes are applied */
6365
6377
        {
6366
6378
                UnlockReleaseBuffer(buffer);
6367
6379
                return;
6729
6741
                goto newt;
6730
6742
        page = (Page) BufferGetPage(obuffer);
6731
6743
 
6732
 
        if (lsn <= PageGetLSN(page))            /* changes are applied */
 
6744
        if (lsn <= PageGetLSN(page))    /* changes are applied */
6733
6745
        {
6734
6746
                if (samepage)
6735
6747
                {
6931
6943
                return;
6932
6944
        page = (Page) BufferGetPage(buffer);
6933
6945
 
6934
 
        if (lsn <= PageGetLSN(page))            /* changes are applied */
 
6946
        if (lsn <= PageGetLSN(page))    /* changes are applied */
6935
6947
        {
6936
6948
                UnlockReleaseBuffer(buffer);
6937
6949
                return;
6962
6974
heap_xlog_lock_updated(XLogRecPtr lsn, XLogRecord *record)
6963
6975
{
6964
6976
        xl_heap_lock_updated *xlrec =
6965
 
                (xl_heap_lock_updated *) XLogRecGetData(record);
 
6977
        (xl_heap_lock_updated *) XLogRecGetData(record);
6966
6978
        Buffer          buffer;
6967
6979
        Page            page;
6968
6980
        OffsetNumber offnum;
6983
6995
                return;
6984
6996
        page = (Page) BufferGetPage(buffer);
6985
6997
 
6986
 
        if (lsn <= PageGetLSN(page))            /* changes are applied */
 
6998
        if (lsn <= PageGetLSN(page))    /* changes are applied */
6987
6999
        {
6988
7000
                UnlockReleaseBuffer(buffer);
6989
7001
                return;
7033
7045
                return;
7034
7046
        page = (Page) BufferGetPage(buffer);
7035
7047
 
7036
 
        if (lsn <= PageGetLSN(page))            /* changes are applied */
 
7048
        if (lsn <= PageGetLSN(page))    /* changes are applied */
7037
7049
        {
7038
7050
                UnlockReleaseBuffer(buffer);
7039
7051
                return;