Commit e77054e0 authored by Bruce Momjian's avatar Bruce Momjian

This patch fixes a regression caused by my recent changes to heap

tuple header.  The fix is based on the thought that HEAP_MOVED_IN is
not needed any more as soon as HEAP_XMIN_COMMITTED has been set.  So
in tqual.c and vacuum.c the HEAP_MOVED bits are cleared when
HEAP_XMIN_COMMITTED is set.

Vacuum robustness is enhanced by rearranging ifs, so that we have a
chance to elog(ERROR, ...) before an assertion fails.

A new regression test is included.

Manfred Koizar
parent cdf4b9af
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.230 2002/06/20 20:29:27 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.231 2002/07/20 04:57:13 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1533,8 +1533,6 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, ...@@ -1533,8 +1533,6 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED)) if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED))
{ {
if (HeapTupleHeaderGetXvac(tuple.t_data) != myXID)
elog(ERROR, "Invalid XVAC in tuple header");
if (tuple.t_data->t_infomask & HEAP_MOVED_IN) if (tuple.t_data->t_infomask & HEAP_MOVED_IN)
elog(ERROR, "HEAP_MOVED_IN was not expected"); elog(ERROR, "HEAP_MOVED_IN was not expected");
...@@ -1545,6 +1543,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, ...@@ -1545,6 +1543,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
*/ */
if (tuple.t_data->t_infomask & HEAP_MOVED_OFF) if (tuple.t_data->t_infomask & HEAP_MOVED_OFF)
{ {
if (HeapTupleHeaderGetXvac(tuple.t_data) != myXID)
elog(ERROR, "Invalid XVAC in tuple header");
if (keep_tuples == 0) if (keep_tuples == 0)
continue; continue;
if (chain_tuple_moved) /* some chains was moved if (chain_tuple_moved) /* some chains was moved
...@@ -2008,7 +2008,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, ...@@ -2008,7 +2008,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
/* /*
* Mark new tuple as moved_in by vacuum and store vacuum XID * Mark new tuple as moved_in by vacuum and store vacuum XID
* in t_cmin !!! * in t_cid !!!
*/ */
newtup.t_data->t_infomask &= newtup.t_data->t_infomask &=
~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_OFF); ~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_OFF);
...@@ -2034,7 +2034,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, ...@@ -2034,7 +2034,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
/* /*
* Mark old tuple as moved_off by vacuum and store vacuum XID * Mark old tuple as moved_off by vacuum and store vacuum XID
* in t_cmin !!! * in t_cid !!!
*/ */
tuple.t_data->t_infomask &= tuple.t_data->t_infomask &=
~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN); ~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN);
...@@ -2087,12 +2087,12 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, ...@@ -2087,12 +2087,12 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid); tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
if (tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED) if (tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED)
continue; continue;
if (HeapTupleHeaderGetXvac(tuple.t_data) != myXID)
elog(ERROR, "Invalid XVAC in tuple header (4)");
if (tuple.t_data->t_infomask & HEAP_MOVED_IN) if (tuple.t_data->t_infomask & HEAP_MOVED_IN)
elog(ERROR, "HEAP_MOVED_IN was not expected (2)"); elog(ERROR, "HEAP_MOVED_IN was not expected (2)");
if (tuple.t_data->t_infomask & HEAP_MOVED_OFF) if (tuple.t_data->t_infomask & HEAP_MOVED_OFF)
{ {
if (HeapTupleHeaderGetXvac(tuple.t_data) != myXID)
elog(ERROR, "Invalid XVAC in tuple header (4)");
/* some chains was moved while */ /* some chains was moved while */
if (chain_tuple_moved) if (chain_tuple_moved)
{ /* cleaning this page */ { /* cleaning this page */
...@@ -2116,6 +2116,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, ...@@ -2116,6 +2116,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
keep_tuples--; keep_tuples--;
} }
} }
else
elog(ERROR, "HEAP_MOVED_OFF was expected (2)");
} }
} }
...@@ -2225,17 +2227,18 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, ...@@ -2225,17 +2227,18 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid); tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED)) if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED))
{ {
if (!(tuple.t_data->t_infomask & HEAP_MOVED))
elog(ERROR, "HEAP_MOVED_OFF/HEAP_MOVED_IN was expected");
if (HeapTupleHeaderGetXvac(tuple.t_data) != myXID) if (HeapTupleHeaderGetXvac(tuple.t_data) != myXID)
elog(ERROR, "Invalid XVAC in tuple header (2)"); elog(ERROR, "Invalid XVAC in tuple header (2)");
if (tuple.t_data->t_infomask & HEAP_MOVED_IN) if (tuple.t_data->t_infomask & HEAP_MOVED_IN)
{ {
tuple.t_data->t_infomask |= HEAP_XMIN_COMMITTED; tuple.t_data->t_infomask |= HEAP_XMIN_COMMITTED;
tuple.t_data->t_infomask &= ~HEAP_MOVED;
num_tuples++; num_tuples++;
} }
else if (tuple.t_data->t_infomask & HEAP_MOVED_OFF)
tuple.t_data->t_infomask |= HEAP_XMIN_INVALID;
else else
elog(ERROR, "HEAP_MOVED_OFF/HEAP_MOVED_IN was expected"); tuple.t_data->t_infomask |= HEAP_XMIN_INVALID;
} }
} }
LockBuffer(buf, BUFFER_LOCK_UNLOCK); LockBuffer(buf, BUFFER_LOCK_UNLOCK);
...@@ -2304,15 +2307,15 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, ...@@ -2304,15 +2307,15 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED)) if (!(tuple.t_data->t_infomask & HEAP_XMIN_COMMITTED))
{ {
if (HeapTupleHeaderGetXvac(tuple.t_data) != myXID)
elog(ERROR, "Invalid XVAC in tuple header (3)");
if (tuple.t_data->t_infomask & HEAP_MOVED_OFF) if (tuple.t_data->t_infomask & HEAP_MOVED_OFF)
{ {
if (HeapTupleHeaderGetXvac(tuple.t_data) != myXID)
elog(ERROR, "Invalid XVAC in tuple header (3)");
itemid->lp_flags &= ~LP_USED; itemid->lp_flags &= ~LP_USED;
num_tuples++; num_tuples++;
} }
else else
elog(ERROR, "HEAP_MOVED_OFF was expected (2)"); elog(ERROR, "HEAP_MOVED_OFF was expected (3)");
} }
} }
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.56 2002/06/20 20:29:41 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.57 2002/07/20 04:57:13 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -92,7 +92,10 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple) ...@@ -92,7 +92,10 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return false; return false;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
{
tuple->t_infomask |= HEAP_XMIN_COMMITTED; tuple->t_infomask |= HEAP_XMIN_COMMITTED;
tuple->t_infomask &= ~HEAP_MOVED;
}
else else
{ {
tuple->t_infomask |= HEAP_XMIN_INVALID; tuple->t_infomask |= HEAP_XMIN_INVALID;
...@@ -219,6 +222,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple) ...@@ -219,6 +222,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
return false; return false;
} }
tuple->t_infomask |= HEAP_XMIN_COMMITTED; tuple->t_infomask |= HEAP_XMIN_COMMITTED;
tuple->t_infomask &= ~HEAP_MOVED;
} }
} }
else if (tuple->t_infomask & HEAP_MOVED_IN) else if (tuple->t_infomask & HEAP_MOVED_IN)
...@@ -228,7 +232,10 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple) ...@@ -228,7 +232,10 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return false; return false;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
{
tuple->t_infomask |= HEAP_XMIN_COMMITTED; tuple->t_infomask |= HEAP_XMIN_COMMITTED;
tuple->t_infomask &= ~HEAP_MOVED;
}
else else
{ {
tuple->t_infomask |= HEAP_XMIN_INVALID; tuple->t_infomask |= HEAP_XMIN_INVALID;
...@@ -336,6 +343,7 @@ HeapTupleSatisfiesToast(HeapTupleHeader tuple) ...@@ -336,6 +343,7 @@ HeapTupleSatisfiesToast(HeapTupleHeader tuple)
return false; return false;
} }
tuple->t_infomask |= HEAP_XMIN_COMMITTED; tuple->t_infomask |= HEAP_XMIN_COMMITTED;
tuple->t_infomask &= ~HEAP_MOVED;
} }
} }
else if (tuple->t_infomask & HEAP_MOVED_IN) else if (tuple->t_infomask & HEAP_MOVED_IN)
...@@ -345,7 +353,10 @@ HeapTupleSatisfiesToast(HeapTupleHeader tuple) ...@@ -345,7 +353,10 @@ HeapTupleSatisfiesToast(HeapTupleHeader tuple)
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return false; return false;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
{
tuple->t_infomask |= HEAP_XMIN_COMMITTED; tuple->t_infomask |= HEAP_XMIN_COMMITTED;
tuple->t_infomask &= ~HEAP_MOVED;
}
else else
{ {
tuple->t_infomask |= HEAP_XMIN_INVALID; tuple->t_infomask |= HEAP_XMIN_INVALID;
...@@ -389,6 +400,7 @@ HeapTupleSatisfiesUpdate(HeapTuple htuple, CommandId curcid) ...@@ -389,6 +400,7 @@ HeapTupleSatisfiesUpdate(HeapTuple htuple, CommandId curcid)
return HeapTupleInvisible; return HeapTupleInvisible;
} }
tuple->t_infomask |= HEAP_XMIN_COMMITTED; tuple->t_infomask |= HEAP_XMIN_COMMITTED;
tuple->t_infomask &= ~HEAP_MOVED;
} }
} }
else if (tuple->t_infomask & HEAP_MOVED_IN) else if (tuple->t_infomask & HEAP_MOVED_IN)
...@@ -398,7 +410,10 @@ HeapTupleSatisfiesUpdate(HeapTuple htuple, CommandId curcid) ...@@ -398,7 +410,10 @@ HeapTupleSatisfiesUpdate(HeapTuple htuple, CommandId curcid)
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return HeapTupleInvisible; return HeapTupleInvisible;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
{
tuple->t_infomask |= HEAP_XMIN_COMMITTED; tuple->t_infomask |= HEAP_XMIN_COMMITTED;
tuple->t_infomask &= ~HEAP_MOVED;
}
else else
{ {
tuple->t_infomask |= HEAP_XMIN_INVALID; tuple->t_infomask |= HEAP_XMIN_INVALID;
...@@ -520,6 +535,7 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple) ...@@ -520,6 +535,7 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
return false; return false;
} }
tuple->t_infomask |= HEAP_XMIN_COMMITTED; tuple->t_infomask |= HEAP_XMIN_COMMITTED;
tuple->t_infomask &= ~HEAP_MOVED;
} }
} }
else if (tuple->t_infomask & HEAP_MOVED_IN) else if (tuple->t_infomask & HEAP_MOVED_IN)
...@@ -529,7 +545,10 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple) ...@@ -529,7 +545,10 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return false; return false;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
{
tuple->t_infomask |= HEAP_XMIN_COMMITTED; tuple->t_infomask |= HEAP_XMIN_COMMITTED;
tuple->t_infomask &= ~HEAP_MOVED;
}
else else
{ {
tuple->t_infomask |= HEAP_XMIN_INVALID; tuple->t_infomask |= HEAP_XMIN_INVALID;
...@@ -651,6 +670,7 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot) ...@@ -651,6 +670,7 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
return false; return false;
} }
tuple->t_infomask |= HEAP_XMIN_COMMITTED; tuple->t_infomask |= HEAP_XMIN_COMMITTED;
tuple->t_infomask &= ~HEAP_MOVED;
} }
} }
else if (tuple->t_infomask & HEAP_MOVED_IN) else if (tuple->t_infomask & HEAP_MOVED_IN)
...@@ -660,7 +680,10 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot) ...@@ -660,7 +680,10 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return false; return false;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
{
tuple->t_infomask |= HEAP_XMIN_COMMITTED; tuple->t_infomask |= HEAP_XMIN_COMMITTED;
tuple->t_infomask &= ~HEAP_MOVED;
}
else else
{ {
tuple->t_infomask |= HEAP_XMIN_INVALID; tuple->t_infomask |= HEAP_XMIN_INVALID;
...@@ -809,6 +832,7 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin) ...@@ -809,6 +832,7 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
return HEAPTUPLE_DEAD; return HEAPTUPLE_DEAD;
} }
tuple->t_infomask |= HEAP_XMIN_COMMITTED; tuple->t_infomask |= HEAP_XMIN_COMMITTED;
tuple->t_infomask &= ~HEAP_MOVED;
} }
else if (tuple->t_infomask & HEAP_MOVED_IN) else if (tuple->t_infomask & HEAP_MOVED_IN)
{ {
...@@ -817,7 +841,10 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin) ...@@ -817,7 +841,10 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return HEAPTUPLE_INSERT_IN_PROGRESS; return HEAPTUPLE_INSERT_IN_PROGRESS;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple))) if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
{
tuple->t_infomask |= HEAP_XMIN_COMMITTED; tuple->t_infomask |= HEAP_XMIN_COMMITTED;
tuple->t_infomask &= ~HEAP_MOVED;
}
else else
{ {
tuple->t_infomask |= HEAP_XMIN_INVALID; tuple->t_infomask |= HEAP_XMIN_INVALID;
......
...@@ -38,7 +38,7 @@ test: copy ...@@ -38,7 +38,7 @@ test: copy
# ---------- # ----------
# The third group of parallel test # The third group of parallel test
# ---------- # ----------
test: constraints triggers create_misc create_aggregate create_operator create_index inherit test: constraints triggers create_misc create_aggregate create_operator create_index inherit vacuum
# Depends on the above # Depends on the above
test: create_view test: create_view
......
# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.11 2002/07/18 04:43:51 momjian Exp $ # $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.12 2002/07/20 04:57:13 momjian Exp $
# This should probably be in an order similar to parallel_schedule. # This should probably be in an order similar to parallel_schedule.
test: boolean test: boolean
test: char test: char
...@@ -50,6 +50,7 @@ test: create_aggregate ...@@ -50,6 +50,7 @@ test: create_aggregate
test: create_operator test: create_operator
test: create_index test: create_index
test: inherit test: inherit
test: vacuum
test: create_view test: create_view
test: sanity_check test: sanity_check
test: errors test: errors
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment