diff -r -C6 ./src/backend/access/heap/heapam.c ../postgresql-9.0.1_hb2/src/backend/access/heap/heapam.c *** ./src/backend/access/heap/heapam.c 2010-10-01 10:25:44.000000000 -0400 --- ../postgresql-9.0.1_hb2/src/backend/access/heap/heapam.c 2010-12-16 12:29:20.000000000 -0500 *************** *** 1731,1744 **** --- 1731,1751 ---- if (valid) *tid = ctid; /* * If there's a valid t_ctid link, follow it, else we're done. */ + #ifndef DISABLE_HINT_BITS if ((tp.t_data->t_infomask & (HEAP_XMAX_INVALID | HEAP_IS_LOCKED)) || ItemPointerEquals(&tp.t_self, &tp.t_data->t_ctid)) + #else + /* this is probalby wrong -- merlin */ + if ((tp.t_data->t_infomask & (HEAP_IS_LOCKED)) || + ItemPointerEquals(&tp.t_self, &tp.t_data->t_ctid)) + + #endif { UnlockReleaseBuffer(buffer); break; } ctid = tp.t_data->t_ctid; *************** *** 1755,1766 **** --- 1762,1774 ---- * If the transaction aborted, we guarantee the XMAX_INVALID hint bit will * be set on exit. If the transaction committed, we set the XMAX_COMMITTED * hint bit if possible --- but beware that that may not yet be possible, * if the transaction committed asynchronously. Hence callers should look * only at XMAX_INVALID. */ + #ifndef DISABLE_HINT_BITS static void UpdateXmaxHintBits(HeapTupleHeader tuple, Buffer buffer, TransactionId xid) { Assert(TransactionIdEquals(HeapTupleHeaderGetXmax(tuple), xid)); if (!(tuple->t_infomask & (HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID))) *************** *** 1770,1781 **** --- 1778,1792 ---- xid); else HeapTupleSetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId); } } + #else + #define UpdateXmaxHintBits(a,b,c) do{;}while(0) + #endif /* * GetBulkInsertState - prepare status object for a bulk insert */ BulkInsertState *************** *** 1861,1873 **** --- 1872,1886 ---- /* check there is not space for an OID */ Assert(!(tup->t_data->t_infomask & HEAP_HASOID)); } tup->t_data->t_infomask &= ~(HEAP_XACT_MASK); tup->t_data->t_infomask2 &= ~(HEAP2_XACT_MASK); + #ifndef DISABLE_HINT_BITS tup->t_data->t_infomask |= HEAP_XMAX_INVALID; + #endif HeapTupleHeaderSetXmin(tup->t_data, xid); HeapTupleHeaderSetCmin(tup->t_data, cid); HeapTupleHeaderSetXmax(tup->t_data, 0); /* for cleanliness */ tup->t_tableOid = RelationGetRelid(relation); /* *************** *** 2161,2174 **** --- 2174,2192 ---- } /* * We may overwrite if previous xmax aborted, or if it committed but * only locked the tuple without updating it. */ + #ifndef DISABLE_HINT_BITS if (tp.t_data->t_infomask & (HEAP_XMAX_INVALID | HEAP_IS_LOCKED)) + #else + if (tp.t_data->t_infomask & HEAP_IS_LOCKED ) + + #endif result = HeapTupleMayBeUpdated; else result = HeapTupleUpdated; } if (crosscheck != InvalidSnapshot && result == HeapTupleMayBeUpdated) *************** *** 2210,2226 **** --- 2228,2250 ---- { all_visible_cleared = true; PageClearAllVisible(page); } /* store transaction information of xact deleting the tuple */ + #ifndef DISABLE_HINT_BITS tp.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID | HEAP_XMAX_IS_MULTI | HEAP_IS_LOCKED | HEAP_MOVED); + #else + tp.t_data->t_infomask &= ~(HEAP_XMAX_IS_MULTI | + HEAP_IS_LOCKED | + HEAP_MOVED); + #endif HeapTupleHeaderClearHotUpdated(tp.t_data); HeapTupleHeaderSetXmax(tp.t_data, xid); HeapTupleHeaderSetCmax(tp.t_data, cid, iscombo); /* Make sure there is no forward chain link in t_ctid */ tp.t_data->t_ctid = tp.t_self; *************** *** 2513,2526 **** --- 2537,2554 ---- } /* * We may overwrite if previous xmax aborted, or if it committed but * only locked the tuple without updating it. */ + #ifndef DISABLE_HINT_BITS if (oldtup.t_data->t_infomask & (HEAP_XMAX_INVALID | HEAP_IS_LOCKED)) + #else + if (oldtup.t_data->t_infomask & (HEAP_IS_LOCKED)) + #endif result = HeapTupleMayBeUpdated; else result = HeapTupleUpdated; } if (crosscheck != InvalidSnapshot && result == HeapTupleMayBeUpdated) *************** *** 2559,2571 **** --- 2587,2603 ---- /* check there is not space for an OID */ Assert(!(newtup->t_data->t_infomask & HEAP_HASOID)); } newtup->t_data->t_infomask &= ~(HEAP_XACT_MASK); newtup->t_data->t_infomask2 &= ~(HEAP2_XACT_MASK); + #ifndef DISABLE_HINT_BITS newtup->t_data->t_infomask |= (HEAP_XMAX_INVALID | HEAP_UPDATED); + #else + newtup->t_data->t_infomask |= (HEAP_UPDATED); + #endif HeapTupleHeaderSetXmin(newtup->t_data, xid); HeapTupleHeaderSetCmin(newtup->t_data, cid); HeapTupleHeaderSetXmax(newtup->t_data, 0); /* for cleanliness */ newtup->t_tableOid = RelationGetRelid(relation); /* *************** *** 2601,2614 **** --- 2633,2650 ---- newtupsize = MAXALIGN(newtup->t_len); if (need_toast || newtupsize > pagefree) { /* Clear obsolete visibility flags ... */ + #ifndef DISABLE_HINT_BITS oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID | + #else + oldtup.t_data->t_infomask &= ~( + #endif HEAP_XMAX_IS_MULTI | HEAP_IS_LOCKED | HEAP_MOVED); HeapTupleClearHotUpdated(&oldtup); /* ... and store info about transaction updating this tuple */ HeapTupleHeaderSetXmax(oldtup.t_data, xid); *************** *** 2747,2760 **** --- 2783,2800 ---- RelationPutHeapTuple(relation, newbuf, heaptup); /* insert new tuple */ if (!already_marked) { /* Clear obsolete visibility flags ... */ + #ifndef DISABLE_HINT_BITS oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID | + #else + oldtup.t_data->t_infomask &= ~( + #endif HEAP_XMAX_IS_MULTI | HEAP_IS_LOCKED | HEAP_MOVED); /* ... and store info about transaction updating this tuple */ HeapTupleHeaderSetXmax(oldtup.t_data, xid); HeapTupleHeaderSetCmax(oldtup.t_data, cid, iscombo); *************** *** 3237,3250 **** --- 3277,3294 ---- /* * We may lock if previous xmax aborted, or if it committed but only * locked the tuple without updating it. The case where we didn't * wait because we are joining an existing shared lock is correctly * handled, too. */ + #ifndef DISABLE_HINT_BITS if (tuple->t_data->t_infomask & (HEAP_XMAX_INVALID | HEAP_IS_LOCKED)) + #else + if (tuple->t_data->t_infomask & (HEAP_IS_LOCKED)) + #endif result = HeapTupleMayBeUpdated; else result = HeapTupleUpdated; } if (result != HeapTupleMayBeUpdated) *************** *** 3269,3283 **** * Note in particular that this covers the case where we already hold * exclusive lock on the tuple and the caller only wants shared lock. It * would certainly not do to give up the exclusive lock. */ xmax = HeapTupleHeaderGetXmax(tuple->t_data); old_infomask = tuple->t_data->t_infomask; ! if (!(old_infomask & (HEAP_XMAX_INVALID | HEAP_XMAX_COMMITTED | HEAP_XMAX_IS_MULTI)) && (mode == LockTupleShared ? (old_infomask & HEAP_IS_LOCKED) : (old_infomask & HEAP_XMAX_EXCL_LOCK)) && TransactionIdIsCurrentTransactionId(xmax)) { --- 3313,3330 ---- * Note in particular that this covers the case where we already hold * exclusive lock on the tuple and the caller only wants shared lock. It * would certainly not do to give up the exclusive lock. */ xmax = HeapTupleHeaderGetXmax(tuple->t_data); old_infomask = tuple->t_data->t_infomask; ! #ifndef DISABLE_HINT_BITS if (!(old_infomask & (HEAP_XMAX_INVALID | HEAP_XMAX_COMMITTED | + #else + if (!(old_infomask & ( + #endif HEAP_XMAX_IS_MULTI)) && (mode == LockTupleShared ? (old_infomask & HEAP_IS_LOCKED) : (old_infomask & HEAP_XMAX_EXCL_LOCK)) && TransactionIdIsCurrentTransactionId(xmax)) { *************** *** 3291,3305 **** /* * Compute the new xmax and infomask to store into the tuple. Note we do * not modify the tuple just yet, because that would leave it in the wrong * state if multixact.c elogs. */ xid = GetCurrentTransactionId(); ! new_infomask = old_infomask & ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID | HEAP_XMAX_IS_MULTI | HEAP_IS_LOCKED | HEAP_MOVED); if (mode == LockTupleShared) { --- 3338,3355 ---- /* * Compute the new xmax and infomask to store into the tuple. Note we do * not modify the tuple just yet, because that would leave it in the wrong * state if multixact.c elogs. */ xid = GetCurrentTransactionId(); ! #ifndef DISABLE_HINT_BITS new_infomask = old_infomask & ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID | + #else + new_infomask = old_infomask & ~( + #endif HEAP_XMAX_IS_MULTI | HEAP_IS_LOCKED | HEAP_MOVED); if (mode == LockTupleShared) { *************** *** 3327,3340 **** --- 3377,3392 ---- * * There is a similar race condition possible when the old xmax was a * regular TransactionId. We test TransactionIdIsInProgress again * just to narrow the window, but it's still possible to end up * creating an unnecessary MultiXactId. Fortunately this is harmless. */ + #ifndef DISABLE_HINT_BITS if (!(old_infomask & (HEAP_XMAX_INVALID | HEAP_XMAX_COMMITTED))) { + #endif if (old_infomask & HEAP_XMAX_IS_MULTI) { /* * If the XMAX is already a MultiXactId, then we need to * expand it to include our own TransactionId. */ *************** *** 3357,3376 **** --- 3409,3430 ---- * Can get here iff HeapTupleSatisfiesUpdate saw the old xmax * as running, but it finished before * TransactionIdIsInProgress() got to run. Treat it like * there's no locker in the tuple. */ } + #ifndef DISABLE_HINT_BITS } else { /* * There was no previous locker, so just insert our own * TransactionId. */ } + #endif } else { /* We want an exclusive lock on the tuple */ new_infomask |= HEAP_XMAX_EXCL_LOCK; } *************** *** 3598,3611 **** --- 3652,3667 ---- HeapTupleHeaderSetXmin(tuple, FrozenTransactionId); /* * Might as well fix the hint bits too; usually XMIN_COMMITTED will * already be set here, but there's a small chance not. */ + #ifndef DISABLE_HINT_BITS Assert(!(tuple->t_infomask & HEAP_XMIN_INVALID)); tuple->t_infomask |= HEAP_XMIN_COMMITTED; + #endif changed = true; } /* * When we release shared lock, it's possible for someone else to change * xmax before we get the lock back, so repeat the check after acquiring *************** *** 3632,3645 **** --- 3688,3703 ---- /* * The tuple might be marked either XMAX_INVALID or XMAX_COMMITTED * + LOCKED. Normalize to INVALID just to be sure no one gets * confused. */ + #ifndef DISABLE_HINT_BITS tuple->t_infomask &= ~HEAP_XMAX_COMMITTED; tuple->t_infomask |= HEAP_XMAX_INVALID; + #endif HeapTupleHeaderClearHotUpdated(tuple); changed = true; } } else { *************** *** 3697,3710 **** --- 3755,3770 ---- HeapTupleHeaderSetXvac(tuple, FrozenTransactionId); /* * Might as well fix the hint bits too; usually XMIN_COMMITTED * will already be set here, but there's a small chance not. */ + #ifndef DISABLE_HINT_BITS Assert(!(tuple->t_infomask & HEAP_XMIN_INVALID)); tuple->t_infomask |= HEAP_XMIN_COMMITTED; + #endif changed = true; } } return changed; } *************** *** 4332,4345 **** --- 4392,4409 ---- if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) elog(PANIC, "heap_delete_redo: invalid lp"); htup = (HeapTupleHeader) PageGetItem(page, lp); + #ifndef DISABLE_HINT_BITS htup->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID | + #else + htup->t_infomask &= ~( + #endif HEAP_XMAX_IS_MULTI | HEAP_IS_LOCKED | HEAP_MOVED); HeapTupleHeaderClearHotUpdated(htup); HeapTupleHeaderSetXmax(htup, record->xl_xid); HeapTupleHeaderSetCmax(htup, FirstCommandId, false); *************** *** 4533,4546 **** --- 4597,4614 ---- if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) elog(PANIC, "heap_update_redo: invalid lp"); htup = (HeapTupleHeader) PageGetItem(page, lp); + #ifndef DISABLE_HINT_BITS htup->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID | + #else + htup->t_infomask &= ~( + #endif HEAP_XMAX_IS_MULTI | HEAP_IS_LOCKED | HEAP_MOVED); if (hot_update) HeapTupleHeaderSetHotUpdated(htup); else *************** *** 4707,4720 **** --- 4775,4792 ---- if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) elog(PANIC, "heap_lock_redo: invalid lp"); htup = (HeapTupleHeader) PageGetItem(page, lp); + #ifndef DISABLE_HINT_BITS htup->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID | + #else + htup->t_infomask &= ~( + #endif HEAP_XMAX_IS_MULTI | HEAP_IS_LOCKED | HEAP_MOVED); if (xlrec->xid_is_mxact) htup->t_infomask |= HEAP_XMAX_IS_MULTI; if (xlrec->shared_lock) diff -r -C6 ./src/backend/access/heap/rewriteheap.c ../postgresql-9.0.1_hb2/src/backend/access/heap/rewriteheap.c *** ./src/backend/access/heap/rewriteheap.c 2010-10-01 10:25:44.000000000 -0400 --- ../postgresql-9.0.1_hb2/src/backend/access/heap/rewriteheap.c 2010-12-16 12:30:06.000000000 -0500 *************** *** 351,363 **** --- 351,367 ---- */ ItemPointerSetInvalid(&new_tuple->t_data->t_ctid); /* * If the tuple has been updated, check the old-to-new mapping hash table. */ + #ifndef DISABLE_HINT_BITS if (!(old_tuple->t_data->t_infomask & (HEAP_XMAX_INVALID | + #else + if (!(old_tuple->t_data->t_infomask & ( + #endif HEAP_IS_LOCKED)) && !(ItemPointerEquals(&(old_tuple->t_self), &(old_tuple->t_data->t_ctid)))) { OldToNewMapping mapping; diff -r -C6 ./src/backend/commands/sequence.c ../postgresql-9.0.1_hb2/src/backend/commands/sequence.c *** ./src/backend/commands/sequence.c 2010-10-01 10:25:44.000000000 -0400 --- ../postgresql-9.0.1_hb2/src/backend/commands/sequence.c 2010-12-16 12:31:09.000000000 -0500 *************** *** 260,275 **** Item item; itemId = PageGetItemId((Page) page, FirstOffsetNumber); item = PageGetItem((Page) page, itemId); HeapTupleHeaderSetXmin((HeapTupleHeader) item, FrozenTransactionId); ((HeapTupleHeader) item)->t_infomask |= HEAP_XMIN_COMMITTED; ! HeapTupleHeaderSetXmin(tuple->t_data, FrozenTransactionId); tuple->t_data->t_infomask |= HEAP_XMIN_COMMITTED; } MarkBufferDirty(buf); /* XLOG stuff */ if (!rel->rd_istemp) --- 260,278 ---- Item item; itemId = PageGetItemId((Page) page, FirstOffsetNumber); item = PageGetItem((Page) page, itemId); HeapTupleHeaderSetXmin((HeapTupleHeader) item, FrozenTransactionId); + #ifndef DISABLE_HINT_BITS ((HeapTupleHeader) item)->t_infomask |= HEAP_XMIN_COMMITTED; ! #endif HeapTupleHeaderSetXmin(tuple->t_data, FrozenTransactionId); + #ifndef DISABLE_HINT_BITS tuple->t_data->t_infomask |= HEAP_XMIN_COMMITTED; + #endif } MarkBufferDirty(buf); /* XLOG stuff */ if (!rel->rd_istemp) diff -r -C6 ./src/backend/commands/vacuumlazy.c ../postgresql-9.0.1_hb2/src/backend/commands/vacuumlazy.c *** ./src/backend/commands/vacuumlazy.c 2010-10-01 10:25:44.000000000 -0400 --- ../postgresql-9.0.1_hb2/src/backend/commands/vacuumlazy.c 2010-12-16 15:24:59.000000000 -0500 *************** *** 591,613 **** * that. */ if (all_visible) { TransactionId xmin; if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED)) { all_visible = false; break; } ! /* ! * The inserter definitely committed. But is it old ! * enough that everyone sees it as committed? ! */ xmin = HeapTupleHeaderGetXmin(tuple.t_data); if (!TransactionIdPrecedes(xmin, OldestXmin)) { all_visible = false; break; } } --- 591,622 ---- * that. */ if (all_visible) { TransactionId xmin; + #ifndef DISABLE_HINT_BITS if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED)) { all_visible = false; break; } ! /* ! * The inserter definitely committed. But is it old ! * enough that everyone sees it as committed? ! */ ! xmin = HeapTupleHeaderGetXmin(tuple.t_data); ! #else xmin = HeapTupleHeaderGetXmin(tuple.t_data); + if (!TransactionIdDidCommit(xmin)) + { + all_visible = false; + break; + } + #endif if (!TransactionIdPrecedes(xmin, OldestXmin)) { all_visible = false; break; } } diff -r -C6 ./src/backend/utils/time/combocid.c ../postgresql-9.0.1_hb2/src/backend/utils/time/combocid.c *** ./src/backend/utils/time/combocid.c 2010-10-01 10:25:44.000000000 -0400 --- ../postgresql-9.0.1_hb2/src/backend/utils/time/combocid.c 2010-12-16 12:35:59.000000000 -0500 *************** *** 149,161 **** --- 149,165 ---- /* * If we're marking a tuple deleted that was inserted by (any * subtransaction of) our transaction, we need to use a combo command id. * Test for HEAP_XMIN_COMMITTED first, because it's cheaper than a * TransactionIdIsCurrentTransactionId call. */ + #ifndef DISABLE_HINT_BITS if (!(tup->t_infomask & HEAP_XMIN_COMMITTED) && + #else + if (!(0) && + #endif TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tup))) { CommandId cmin = HeapTupleHeaderGetCmin(tup); *cmax = GetComboCommandId(cmin, *cmax); *iscombo = true; diff -r -C6 ./src/backend/utils/time/tqual.c ../postgresql-9.0.1_hb2/src/backend/utils/time/tqual.c *** ./src/backend/utils/time/tqual.c 2010-10-01 10:25:44.000000000 -0400 --- ../postgresql-9.0.1_hb2/src/backend/utils/time/tqual.c 2010-12-16 12:38:24.000000000 -0500 *************** *** 101,112 **** --- 101,113 ---- * Normal commits may be asynchronous, so for those we need to get the LSN * of the transaction and then check whether this is flushed. * * The caller should pass xid as the XID of the transaction to check, or * InvalidTransactionId if no check is needed. */ + #ifndef DISABLE_HINT_BITS static inline void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid) { if (TransactionIdIsValid(xid)) { *************** *** 130,142 **** --- 131,147 ---- void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid) { SetHintBits(tuple, buffer, infomask, xid); } + #else + #define SetHintBits(a,b,c,d) do{;}while(0) + + #endif /* * HeapTupleSatisfiesSelf * True iff heap tuple is valid "for itself". * * Here, we consider the effects of: *************** *** 159,175 **** * (Xmax != my-transaction && the row was deleted by another transaction * Xmax is not committed))) that has not been committed */ bool HeapTupleSatisfiesSelf(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; ! /* Used by pre-9.0 binary upgrades */ if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) --- 164,181 ---- * (Xmax != my-transaction && the row was deleted by another transaction * Xmax is not committed))) that has not been committed */ bool HeapTupleSatisfiesSelf(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { + #ifndef DISABLE_HINT_BITS if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; ! #endif /* Used by pre-9.0 binary upgrades */ if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) *************** *** 205,219 **** return false; } } } else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple))) { if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return true; ! if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */ return true; Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI)); if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) --- 211,226 ---- return false; } } } else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple))) { + #ifndef DISABLE_HINT_BITS if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return true; ! #endif if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */ return true; Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI)); if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) *************** *** 235,259 **** { /* it must have aborted or crashed */ SetHintBits(tuple, buffer, HEAP_XMIN_INVALID, InvalidTransactionId); return false; } } /* by here, the inserting transaction has committed */ - if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return true; if (tuple->t_infomask & HEAP_XMAX_COMMITTED) { if (tuple->t_infomask & HEAP_IS_LOCKED) return true; return false; /* updated by other */ } if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { /* MultiXacts are currently only allowed to lock tuples */ Assert(tuple->t_infomask & HEAP_IS_LOCKED); return true; --- 242,267 ---- { /* it must have aborted or crashed */ SetHintBits(tuple, buffer, HEAP_XMIN_INVALID, InvalidTransactionId); return false; } + #ifndef DISABLE_HINT_BITS } /* by here, the inserting transaction has committed */ if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return true; if (tuple->t_infomask & HEAP_XMAX_COMMITTED) { if (tuple->t_infomask & HEAP_IS_LOCKED) return true; return false; /* updated by other */ } + #endif if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { /* MultiXacts are currently only allowed to lock tuples */ Assert(tuple->t_infomask & HEAP_IS_LOCKED); return true; *************** *** 282,294 **** if (tuple->t_infomask & HEAP_IS_LOCKED) { SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId); return true; } - SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED, HeapTupleHeaderGetXmax(tuple)); return false; } /* --- 290,301 ---- *************** *** 332,348 **** * the serializability guarantees we provide don't extend to xacts * that do catalog accesses. this is unfortunate, but not critical. */ bool HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; ! /* Used by pre-9.0 binary upgrades */ if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) --- 339,356 ---- * the serializability guarantees we provide don't extend to xacts * that do catalog accesses. this is unfortunate, but not critical. */ bool HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { + #ifndef DISABLE_HINT_BITS if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; ! #endif /* Used by pre-9.0 binary upgrades */ if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) *************** *** 380,395 **** } } else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple))) { if (HeapTupleHeaderGetCmin(tuple) >= GetCurrentCommandId(false)) return false; /* inserted after scan started */ ! if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return true; ! if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */ return true; Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI)); if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) --- 388,403 ---- } } else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple))) { if (HeapTupleHeaderGetCmin(tuple) >= GetCurrentCommandId(false)) return false; /* inserted after scan started */ ! #ifndef DISABLE_HINT_BITS if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return true; ! #endif if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */ return true; Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI)); if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) *************** *** 414,425 **** --- 422,434 ---- { /* it must have aborted or crashed */ SetHintBits(tuple, buffer, HEAP_XMIN_INVALID, InvalidTransactionId); return false; } + #ifndef DISABLE_HINT_BITS } /* by here, the inserting transaction has committed */ if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return true; *************** *** 427,438 **** --- 436,448 ---- if (tuple->t_infomask & HEAP_XMAX_COMMITTED) { if (tuple->t_infomask & HEAP_IS_LOCKED) return true; return false; } + #endif if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { /* MultiXacts are currently only allowed to lock tuples */ Assert(tuple->t_infomask & HEAP_IS_LOCKED); return true; *************** *** 457,476 **** SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId); return true; } /* xmax transaction committed */ ! if (tuple->t_infomask & HEAP_IS_LOCKED) { SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId); return true; } ! SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED, HeapTupleHeaderGetXmax(tuple)); return false; } /* --- 467,486 ---- SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId); return true; } /* xmax transaction committed */ ! #ifndef DISABLE_HINT_BITS if (tuple->t_infomask & HEAP_IS_LOCKED) { SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId); return true; } ! #endif SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED, HeapTupleHeaderGetXmax(tuple)); return false; } /* *************** *** 498,514 **** * table. */ bool HeapTupleSatisfiesToast(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; ! /* Used by pre-9.0 binary upgrades */ if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) --- 508,525 ---- * table. */ bool HeapTupleSatisfiesToast(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { + #ifndef DISABLE_HINT_BITS if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; ! #endif /* Used by pre-9.0 binary upgrades */ if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) *************** *** 542,554 **** --- 553,567 ---- SetHintBits(tuple, buffer, HEAP_XMIN_INVALID, InvalidTransactionId); return false; } } } + #ifndef DISABLE_HINT_BITS } + #endif /* otherwise assume the tuple is valid for TOAST. */ return true; } /* *************** *** 579,595 **** * distinguish that case must test for it themselves.) */ HTSU_Result HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid, Buffer buffer) { if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return HeapTupleInvisible; ! /* Used by pre-9.0 binary upgrades */ if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) --- 592,609 ---- * distinguish that case must test for it themselves.) */ HTSU_Result HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid, Buffer buffer) { + #ifndef DISABLE_HINT_BITS if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return HeapTupleInvisible; ! #endif /* Used by pre-9.0 binary upgrades */ if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) *************** *** 627,642 **** } } else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple))) { if (HeapTupleHeaderGetCmin(tuple) >= curcid) return HeapTupleInvisible; /* inserted after scan started */ ! if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return HeapTupleMayBeUpdated; ! if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */ return HeapTupleMayBeUpdated; Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI)); if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) --- 641,656 ---- } } else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple))) { if (HeapTupleHeaderGetCmin(tuple) >= curcid) return HeapTupleInvisible; /* inserted after scan started */ ! #ifndef DISABLE_HINT_BITS if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return HeapTupleMayBeUpdated; ! #endif if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */ return HeapTupleMayBeUpdated; Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI)); if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) *************** *** 661,672 **** --- 675,687 ---- { /* it must have aborted or crashed */ SetHintBits(tuple, buffer, HEAP_XMIN_INVALID, InvalidTransactionId); return HeapTupleInvisible; } + #ifndef DISABLE_HINT_BITS } /* by here, the inserting transaction has committed */ if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return HeapTupleMayBeUpdated; *************** *** 674,686 **** if (tuple->t_infomask & HEAP_XMAX_COMMITTED) { if (tuple->t_infomask & HEAP_IS_LOCKED) return HeapTupleMayBeUpdated; return HeapTupleUpdated; /* updated by other */ } ! if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { /* MultiXacts are currently only allowed to lock tuples */ Assert(tuple->t_infomask & HEAP_IS_LOCKED); if (MultiXactIdIsRunning(HeapTupleHeaderGetXmax(tuple))) --- 689,701 ---- if (tuple->t_infomask & HEAP_XMAX_COMMITTED) { if (tuple->t_infomask & HEAP_IS_LOCKED) return HeapTupleMayBeUpdated; return HeapTupleUpdated; /* updated by other */ } ! #endif if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { /* MultiXacts are currently only allowed to lock tuples */ Assert(tuple->t_infomask & HEAP_IS_LOCKED); if (MultiXactIdIsRunning(HeapTupleHeaderGetXmax(tuple))) *************** *** 747,764 **** */ bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { snapshot->xmin = snapshot->xmax = InvalidTransactionId; ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; ! /* Used by pre-9.0 binary upgrades */ if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) --- 762,779 ---- */ bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { snapshot->xmin = snapshot->xmax = InvalidTransactionId; ! #ifndef DISABLE_HINT_BITS if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; ! #endif /* Used by pre-9.0 binary upgrades */ if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) *************** *** 794,811 **** return false; } } } else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple))) { if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return true; if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */ return true; ! Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI)); if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) { /* deleting subtransaction must have aborted */ SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, --- 809,827 ---- return false; } } } else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple))) { + #ifndef DISABLE_HINT_BITS if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return true; if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */ return true; ! #endif Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI)); if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) { /* deleting subtransaction must have aborted */ SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, *************** *** 828,839 **** --- 844,856 ---- { /* it must have aborted or crashed */ SetHintBits(tuple, buffer, HEAP_XMIN_INVALID, InvalidTransactionId); return false; } + #ifndef DISABLE_HINT_BITS } /* by here, the inserting transaction has committed */ if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return true; *************** *** 841,853 **** if (tuple->t_infomask & HEAP_XMAX_COMMITTED) { if (tuple->t_infomask & HEAP_IS_LOCKED) return true; return false; /* updated by other */ } ! if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { /* MultiXacts are currently only allowed to lock tuples */ Assert(tuple->t_infomask & HEAP_IS_LOCKED); return true; } --- 858,870 ---- if (tuple->t_infomask & HEAP_XMAX_COMMITTED) { if (tuple->t_infomask & HEAP_IS_LOCKED) return true; return false; /* updated by other */ } ! #endif if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { /* MultiXacts are currently only allowed to lock tuples */ Assert(tuple->t_infomask & HEAP_IS_LOCKED); return true; } *************** *** 909,925 **** * can't see it.) */ bool HeapTupleSatisfiesMVCC(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; ! /* Used by pre-9.0 binary upgrades */ if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) --- 926,943 ---- * can't see it.) */ bool HeapTupleSatisfiesMVCC(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { + #ifndef DISABLE_HINT_BITS if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; ! #endif /* Used by pre-9.0 binary upgrades */ if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) *************** *** 957,972 **** } } else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple))) { if (HeapTupleHeaderGetCmin(tuple) >= snapshot->curcid) return false; /* inserted after scan started */ ! if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return true; ! if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */ return true; Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI)); if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) --- 975,990 ---- } } else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple))) { if (HeapTupleHeaderGetCmin(tuple) >= snapshot->curcid) return false; /* inserted after scan started */ ! #ifndef DISABLE_HINT_BITS if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return true; ! #endif if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */ return true; Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI)); if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) *************** *** 991,1026 **** { /* it must have aborted or crashed */ SetHintBits(tuple, buffer, HEAP_XMIN_INVALID, InvalidTransactionId); return false; } } /* * By here, the inserting transaction has committed - have to check * when... */ if (XidInMVCCSnapshot(HeapTupleHeaderGetXmin(tuple), snapshot)) return false; /* treat as still in progress */ ! if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return true; ! if (tuple->t_infomask & HEAP_IS_LOCKED) return true; if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { /* MultiXacts are currently only allowed to lock tuples */ Assert(tuple->t_infomask & HEAP_IS_LOCKED); return true; } ! if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED)) { if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) { if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid) return true; /* deleted after scan started */ else return false; /* deleted before scan started */ --- 1009,1047 ---- { /* it must have aborted or crashed */ SetHintBits(tuple, buffer, HEAP_XMIN_INVALID, InvalidTransactionId); return false; } + #ifndef DISABLE_HINT_BITS } + #endif /* * By here, the inserting transaction has committed - have to check * when... */ if (XidInMVCCSnapshot(HeapTupleHeaderGetXmin(tuple), snapshot)) return false; /* treat as still in progress */ ! #ifndef DISABLE_HINT_BITS if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return true; ! #endif if (tuple->t_infomask & HEAP_IS_LOCKED) return true; if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { /* MultiXacts are currently only allowed to lock tuples */ Assert(tuple->t_infomask & HEAP_IS_LOCKED); return true; } ! #ifndef DISABLE_HINT_BITS if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED)) { + #endif if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) { if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid) return true; /* deleted after scan started */ else return false; /* deleted before scan started */ *************** *** 1037,1049 **** --- 1058,1072 ---- return true; } /* xmax transaction committed */ SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED, HeapTupleHeaderGetXmax(tuple)); + #ifndef DISABLE_HINT_BITS } + #endif /* * OK, the deleting transaction committed too ... but when? */ if (XidInMVCCSnapshot(HeapTupleHeaderGetXmax(tuple), snapshot)) return true; /* treat as still in progress */ *************** *** 1071,1088 **** /* * Has inserting transaction committed? * * If the inserting transaction aborted, then the tuple was never visible * to any other transaction, so we can delete it immediately. */ if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return HEAPTUPLE_DEAD; ! /* Used by pre-9.0 binary upgrades */ ! else if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) return HEAPTUPLE_DELETE_IN_PROGRESS; if (TransactionIdIsInProgress(xvac)) --- 1094,1115 ---- /* * Has inserting transaction committed? * * If the inserting transaction aborted, then the tuple was never visible * to any other transaction, so we can delete it immediately. */ + #ifndef DISABLE_HINT_BITS if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return HEAPTUPLE_DEAD; ! /* Used by pre-9.0 binary upgrades */ ! else if (tuple->t_infomask & HEAP_MOVED_OFF) ! #else ! if (tuple->t_infomask & HEAP_MOVED_OFF) ! #endif { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) return HEAPTUPLE_DELETE_IN_PROGRESS; if (TransactionIdIsInProgress(xvac)) *************** *** 1114,1127 **** --- 1141,1156 ---- InvalidTransactionId); return HEAPTUPLE_DEAD; } } else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple))) { + #ifndef DISABLE_HINT_BITS if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return HEAPTUPLE_INSERT_IN_PROGRESS; + #endif if (tuple->t_infomask & HEAP_IS_LOCKED) return HEAPTUPLE_INSERT_IN_PROGRESS; /* inserted and then deleted by same xact */ return HEAPTUPLE_DELETE_IN_PROGRESS; } else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple))) *************** *** 1139,1171 **** /* * At this point the xmin is known committed, but we might not have * been able to set the hint bit yet; so we can no longer Assert that * it's set. */ } /* * Okay, the inserter committed, so it was good at some point. Now what * about the deleting transaction? */ if (tuple->t_infomask & HEAP_XMAX_INVALID) return HEAPTUPLE_LIVE; ! if (tuple->t_infomask & HEAP_IS_LOCKED) { /* * "Deleting" xact really only locked it, so the tuple is live in any * case. However, we should make sure that either XMAX_COMMITTED or * XMAX_INVALID gets set once the xact is gone, to reduce the costs of * examining the tuple for future xacts. Also, marking dead * MultiXacts as invalid here provides defense against MultiXactId * wraparound (see also comments in heap_freeze_tuple()). */ if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED)) { if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { if (MultiXactIdIsRunning(HeapTupleHeaderGetXmax(tuple))) return HEAPTUPLE_LIVE; } else --- 1168,1203 ---- /* * At this point the xmin is known committed, but we might not have * been able to set the hint bit yet; so we can no longer Assert that * it's set. */ + #ifndef DISABLE_HINT_BITS } /* * Okay, the inserter committed, so it was good at some point. Now what * about the deleting transaction? */ if (tuple->t_infomask & HEAP_XMAX_INVALID) return HEAPTUPLE_LIVE; ! #endif if (tuple->t_infomask & HEAP_IS_LOCKED) { /* * "Deleting" xact really only locked it, so the tuple is live in any * case. However, we should make sure that either XMAX_COMMITTED or * XMAX_INVALID gets set once the xact is gone, to reduce the costs of * examining the tuple for future xacts. Also, marking dead * MultiXacts as invalid here provides defense against MultiXactId * wraparound (see also comments in heap_freeze_tuple()). */ + #ifndef DISABLE_HINT_BITS if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED)) { + #endif if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { if (MultiXactIdIsRunning(HeapTupleHeaderGetXmax(tuple))) return HEAPTUPLE_LIVE; } else *************** *** 1178,1202 **** * We don't really care whether xmax did commit, abort or crash. * We know that xmax did lock the tuple, but it did not and will * never actually update it. */ SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId); } return HEAPTUPLE_LIVE; } if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { /* MultiXacts are currently only allowed to lock tuples */ Assert(tuple->t_infomask & HEAP_IS_LOCKED); return HEAPTUPLE_LIVE; } ! if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED)) { if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple))) return HEAPTUPLE_DELETE_IN_PROGRESS; else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple))) SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED, HeapTupleHeaderGetXmax(tuple)); else --- 1210,1237 ---- * We don't really care whether xmax did commit, abort or crash. * We know that xmax did lock the tuple, but it did not and will * never actually update it. */ SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId); + #ifndef DISABLE_HINT_BITS } + #endif return HEAPTUPLE_LIVE; } if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { /* MultiXacts are currently only allowed to lock tuples */ Assert(tuple->t_infomask & HEAP_IS_LOCKED); return HEAPTUPLE_LIVE; } ! #ifndef DISABLE_HINT_BITS if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED)) { + #endif if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple))) return HEAPTUPLE_DELETE_IN_PROGRESS; else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple))) SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED, HeapTupleHeaderGetXmax(tuple)); else *************** *** 1211,1224 **** /* * At this point the xmax is known committed, but we might not have * been able to set the hint bit yet; so we can no longer Assert that * it's set. */ } ! /* * Deleter committed, but check special cases. */ if (TransactionIdEquals(HeapTupleHeaderGetXmin(tuple), HeapTupleHeaderGetXmax(tuple))) --- 1246,1260 ---- /* * At this point the xmax is known committed, but we might not have * been able to set the hint bit yet; so we can no longer Assert that * it's set. */ + #ifndef DISABLE_HINT_BITS } ! #endif /* * Deleter committed, but check special cases. */ if (TransactionIdEquals(HeapTupleHeaderGetXmin(tuple), HeapTupleHeaderGetXmax(tuple))) diff -r -C6 ./src/include/access/htup.h ../postgresql-9.0.1_hb2/src/include/access/htup.h *** ./src/include/access/htup.h 2010-10-01 10:25:44.000000000 -0400 --- ../postgresql-9.0.1_hb2/src/include/access/htup.h 2010-12-16 12:17:56.000000000 -0500 *************** *** 166,181 **** --- 166,185 ---- /* bit 0x0010 is available */ #define HEAP_COMBOCID 0x0020 /* t_cid is a combo cid */ #define HEAP_XMAX_EXCL_LOCK 0x0040 /* xmax is exclusive locker */ #define HEAP_XMAX_SHARED_LOCK 0x0080 /* xmax is shared locker */ /* if either LOCK bit is set, xmax hasn't deleted the tuple, only locked it */ #define HEAP_IS_LOCKED (HEAP_XMAX_EXCL_LOCK | HEAP_XMAX_SHARED_LOCK) + + #ifndef DISABLE_HINT_BITS #define HEAP_XMIN_COMMITTED 0x0100 /* t_xmin committed */ #define HEAP_XMIN_INVALID 0x0200 /* t_xmin invalid/aborted */ #define HEAP_XMAX_COMMITTED 0x0400 /* t_xmax committed */ #define HEAP_XMAX_INVALID 0x0800 /* t_xmax invalid/aborted */ + #endif + #define HEAP_XMAX_IS_MULTI 0x1000 /* t_xmax is a MultiXactId */ #define HEAP_UPDATED 0x2000 /* this is UPDATEd version of row */ #define HEAP_MOVED_OFF 0x4000 /* moved to another place by pre-9.0 * VACUUM FULL; kept for binary * upgrade support */ #define HEAP_MOVED_IN 0x8000 /* moved from another place by pre-9.0 *************** *** 309,325 **** --- 313,337 ---- /* * Note that we stop considering a tuple HOT-updated as soon as it is known * aborted or the would-be updating transaction is known aborted. For best * efficiency, check tuple visibility before using this macro, so that the * INVALID bits will be as up to date as possible. */ + #ifndef DISABLE_HINT_BITS #define HeapTupleHeaderIsHotUpdated(tup) \ ( \ ((tup)->t_infomask2 & HEAP_HOT_UPDATED) != 0 && \ ((tup)->t_infomask & (HEAP_XMIN_INVALID | HEAP_XMAX_INVALID)) == 0 \ ) + #else + + #define HeapTupleHeaderIsHotUpdated(tup) \ + ( \ + ((tup)->t_infomask2 & HEAP_HOT_UPDATED) != 0 \ + ) + #endif #define HeapTupleHeaderSetHotUpdated(tup) \ ( \ (tup)->t_infomask2 |= HEAP_HOT_UPDATED \ ) diff -r -C6 ./src/include/utils/tqual.h ../postgresql-9.0.1_hb2/src/include/utils/tqual.h *** ./src/include/utils/tqual.h 2010-10-01 10:25:44.000000000 -0400 --- ../postgresql-9.0.1_hb2/src/include/utils/tqual.h 2010-12-16 12:08:09.000000000 -0500 *************** *** 81,90 **** --- 81,94 ---- /* Special "satisfies" routines with different APIs */ extern HTSU_Result HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid, Buffer buffer); extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin, Buffer buffer); + #ifndef DISABLE_HINT_BITS extern void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid); + #else + #define HeapTupleSetHintBits(a,b,c,d) do{;}while(0) + #endif #endif /* TQUAL_H */