@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $ PostgreSQL : pgsql / src / backend / access / heap / heapam . c , v 1.285 2010 / 02 / 03 10 : 01 : 29 heikki Exp $
* $ PostgreSQL : pgsql / src / backend / access / heap / heapam . c , v 1.286 2010 / 02 / 08 04 : 33 : 52 tgl Exp $
*
*
*
*
* INTERFACE ROUTINES
* INTERFACE ROUTINES
@ -79,7 +79,7 @@ static HeapScanDesc heap_beginscan_internal(Relation relation,
bool allow_strat , bool allow_sync ,
bool allow_strat , bool allow_sync ,
bool is_bitmapscan ) ;
bool is_bitmapscan ) ;
static XLogRecPtr log_heap_update ( Relation reln , Buffer oldbuf ,
static XLogRecPtr log_heap_update ( Relation reln , Buffer oldbuf ,
ItemPointerData from , Buffer newbuf , HeapTuple newtup , bool move ,
ItemPointerData from , Buffer newbuf , HeapTuple newtup ,
bool all_visible_cleared , bool new_all_visible_cleared ) ;
bool all_visible_cleared , bool new_all_visible_cleared ) ;
static bool HeapSatisfiesHOTUpdate ( Relation relation , Bitmapset * hot_attrs ,
static bool HeapSatisfiesHOTUpdate ( Relation relation , Bitmapset * hot_attrs ,
HeapTuple oldtup , HeapTuple newtup ) ;
HeapTuple oldtup , HeapTuple newtup ) ;
@ -2785,7 +2785,7 @@ l2:
if ( ! relation - > rd_istemp )
if ( ! relation - > rd_istemp )
{
{
XLogRecPtr recptr = log_heap_update ( relation , buffer , oldtup . t_self ,
XLogRecPtr recptr = log_heap_update ( relation , buffer , oldtup . t_self ,
newbuf , heaptup , false ,
newbuf , heaptup ,
all_visible_cleared ,
all_visible_cleared ,
all_visible_cleared_new ) ;
all_visible_cleared_new ) ;
@ -3664,9 +3664,13 @@ recheck_xmax:
}
}
/*
/*
* Although xvac per se could only be set by VACUUM , it shares physical
* Although xvac per se could only be set by old - style VACUUM FULL , it
* storage space with cmax , and so could be wiped out by someone setting
* shares physical storage space with cmax , and so could be wiped out by
* xmax . Hence recheck after changing lock , same as for xmax itself .
* someone setting xmax . Hence recheck after changing lock , same as for
* xmax itself .
*
* Old - style VACUUM FULL is gone , but we have to keep this code as long
* as we support having MOVED_OFF / MOVED_IN tuples in the database .
*/
*/
recheck_xvac :
recheck_xvac :
if ( tuple - > t_infomask & HEAP_MOVED )
if ( tuple - > t_infomask & HEAP_MOVED )
@ -3785,8 +3789,7 @@ HeapTupleHeaderAdvanceLatestRemovedXid(HeapTupleHeader tuple,
TransactionId xmax = HeapTupleHeaderGetXmax ( tuple ) ;
TransactionId xmax = HeapTupleHeaderGetXmax ( tuple ) ;
TransactionId xvac = HeapTupleHeaderGetXvac ( tuple ) ;
TransactionId xvac = HeapTupleHeaderGetXvac ( tuple ) ;
if ( tuple - > t_infomask & HEAP_MOVED_OFF | |
if ( tuple - > t_infomask & HEAP_MOVED )
tuple - > t_infomask & HEAP_MOVED_IN )
{
{
if ( TransactionIdPrecedes ( * latestRemovedXid , xvac ) )
if ( TransactionIdPrecedes ( * latestRemovedXid , xvac ) )
* latestRemovedXid = xvac ;
* latestRemovedXid = xvac ;
@ -3844,7 +3847,7 @@ log_heap_clean(Relation reln, Buffer buffer,
OffsetNumber * redirected , int nredirected ,
OffsetNumber * redirected , int nredirected ,
OffsetNumber * nowdead , int ndead ,
OffsetNumber * nowdead , int ndead ,
OffsetNumber * nowunused , int nunused ,
OffsetNumber * nowunused , int nunused ,
TransactionId latestRemovedXid , bool redirect_move )
TransactionId latestRemovedXid )
{
{
xl_heap_clean xlrec ;
xl_heap_clean xlrec ;
uint8 info ;
uint8 info ;
@ -3915,7 +3918,7 @@ log_heap_clean(Relation reln, Buffer buffer,
rdata [ 3 ] . buffer_std = true ;
rdata [ 3 ] . buffer_std = true ;
rdata [ 3 ] . next = NULL ;
rdata [ 3 ] . next = NULL ;
info = redirect_move ? XLOG_HEAP2_CLEAN_MOVE : XLOG_HEAP2_CLEAN ;
info = XLOG_HEAP2_CLEAN ;
recptr = XLogInsert ( RM_HEAP2_ID , info , rdata ) ;
recptr = XLogInsert ( RM_HEAP2_ID , info , rdata ) ;
return recptr ;
return recptr ;
@ -3970,23 +3973,11 @@ log_heap_freeze(Relation reln, Buffer buffer,
*/
*/
static XLogRecPtr
static XLogRecPtr
log_heap_update ( Relation reln , Buffer oldbuf , ItemPointerData from ,
log_heap_update ( Relation reln , Buffer oldbuf , ItemPointerData from ,
Buffer newbuf , HeapTuple newtup , bool move ,
Buffer newbuf , HeapTuple newtup ,
bool all_visible_cleared , bool new_all_visible_cleared )
bool all_visible_cleared , bool new_all_visible_cleared )
{
{
/*
* Note : xlhdr is declared to have adequate size and correct alignment for
* an xl_heap_header . However the two tids , if present at all , will be
* packed in with no wasted space after the xl_heap_header ; they aren ' t
* necessarily aligned as implied by this struct declaration .
*/
struct
{
xl_heap_header hdr ;
TransactionId tid1 ;
TransactionId tid2 ;
} xlhdr ;
int hsize = SizeOfHeapHeader ;
xl_heap_update xlrec ;
xl_heap_update xlrec ;
xl_heap_header xlhdr ;
uint8 info ;
uint8 info ;
XLogRecPtr recptr ;
XLogRecPtr recptr ;
XLogRecData rdata [ 4 ] ;
XLogRecData rdata [ 4 ] ;
@ -3995,12 +3986,7 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
/* Caller should not call me on a temp relation */
/* Caller should not call me on a temp relation */
Assert ( ! reln - > rd_istemp ) ;
Assert ( ! reln - > rd_istemp ) ;
if ( move )
if ( HeapTupleIsHeapOnly ( newtup ) )
{
Assert ( ! HeapTupleIsHeapOnly ( newtup ) ) ;
info = XLOG_HEAP_MOVE ;
}
else if ( HeapTupleIsHeapOnly ( newtup ) )
info = XLOG_HEAP_HOT_UPDATE ;
info = XLOG_HEAP_HOT_UPDATE ;
else
else
info = XLOG_HEAP_UPDATE ;
info = XLOG_HEAP_UPDATE ;
@ -4022,30 +4008,16 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
rdata [ 1 ] . buffer_std = true ;
rdata [ 1 ] . buffer_std = true ;
rdata [ 1 ] . next = & ( rdata [ 2 ] ) ;
rdata [ 1 ] . next = & ( rdata [ 2 ] ) ;
xlhdr . hdr . t_infomask2 = newtup - > t_data - > t_infomask2 ;
xlhdr . t_infomask2 = newtup - > t_data - > t_infomask2 ;
xlhdr . hdr . t_infomask = newtup - > t_data - > t_infomask ;
xlhdr . t_infomask = newtup - > t_data - > t_infomask ;
xlhdr . hdr . t_hoff = newtup - > t_data - > t_hoff ;
xlhdr . t_hoff = newtup - > t_data - > t_hoff ;
if ( move ) /* remember xmax & xmin */
{
TransactionId xid [ 2 ] ; /* xmax, xmin */
if ( newtup - > t_data - > t_infomask & ( HEAP_XMAX_INVALID | HEAP_IS_LOCKED ) )
xid [ 0 ] = InvalidTransactionId ;
else
xid [ 0 ] = HeapTupleHeaderGetXmax ( newtup - > t_data ) ;
xid [ 1 ] = HeapTupleHeaderGetXmin ( newtup - > t_data ) ;
memcpy ( ( char * ) & xlhdr + hsize ,
( char * ) xid ,
2 * sizeof ( TransactionId ) ) ;
hsize + = 2 * sizeof ( TransactionId ) ;
}
/*
/*
* As with insert records , we need not store the rdata [ 2 ] segment if we
* As with insert records , we need not store the rdata [ 2 ] segment if we
* decide to store the whole buffer instead .
* decide to store the whole buffer instead .
*/
*/
rdata [ 2 ] . data = ( char * ) & xlhdr ;
rdata [ 2 ] . data = ( char * ) & xlhdr ;
rdata [ 2 ] . len = hsize ;
rdata [ 2 ] . len = SizeOfHeapHeader ;
rdata [ 2 ] . buffer = newbuf ;
rdata [ 2 ] . buffer = newbuf ;
rdata [ 2 ] . buffer_std = true ;
rdata [ 2 ] . buffer_std = true ;
rdata [ 2 ] . next = & ( rdata [ 3 ] ) ;
rdata [ 2 ] . next = & ( rdata [ 3 ] ) ;
@ -4070,19 +4042,6 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
return recptr ;
return recptr ;
}
}
/*
* Perform XLogInsert for a heap - move operation . Caller must already
* have modified the buffers and marked them dirty .
*/
XLogRecPtr
log_heap_move ( Relation reln , Buffer oldbuf , ItemPointerData from ,
Buffer newbuf , HeapTuple newtup ,
bool all_visible_cleared , bool new_all_visible_cleared )
{
return log_heap_update ( reln , oldbuf , from , newbuf , newtup , true ,
all_visible_cleared , new_all_visible_cleared ) ;
}
/*
/*
* Perform XLogInsert of a HEAP_NEWPAGE record to WAL . Caller is responsible
* Perform XLogInsert of a HEAP_NEWPAGE record to WAL . Caller is responsible
* for writing the page to disk after calling this routine .
* for writing the page to disk after calling this routine .
@ -4149,10 +4108,10 @@ heap_xlog_cleanup_info(XLogRecPtr lsn, XLogRecord *record)
}
}
/*
/*
* Handles CLEAN and CLEAN_MOVE record types
* Handles HEAP_CLEAN record type
*/
*/
static void
static void
heap_xlog_clean ( XLogRecPtr lsn , XLogRecord * record , bool clean_move )
heap_xlog_clean ( XLogRecPtr lsn , XLogRecord * record )
{
{
xl_heap_clean * xlrec = ( xl_heap_clean * ) XLogRecGetData ( record ) ;
xl_heap_clean * xlrec = ( xl_heap_clean * ) XLogRecGetData ( record ) ;
Buffer buffer ;
Buffer buffer ;
@ -4171,7 +4130,8 @@ heap_xlog_clean(XLogRecPtr lsn, XLogRecord *record, bool clean_move)
* no queries running for which the removed tuples are still visible .
* no queries running for which the removed tuples are still visible .
*/
*/
if ( InHotStandby )
if ( InHotStandby )
ResolveRecoveryConflictWithSnapshot ( xlrec - > latestRemovedXid , xlrec - > node ) ;
ResolveRecoveryConflictWithSnapshot ( xlrec - > latestRemovedXid ,
xlrec - > node ) ;
RestoreBkpBlocks ( lsn , record , true ) ;
RestoreBkpBlocks ( lsn , record , true ) ;
@ -4203,8 +4163,7 @@ heap_xlog_clean(XLogRecPtr lsn, XLogRecord *record, bool clean_move)
heap_page_prune_execute ( buffer ,
heap_page_prune_execute ( buffer ,
redirected , nredirected ,
redirected , nredirected ,
nowdead , ndead ,
nowdead , ndead ,
nowunused , nunused ,
nowunused , nunused ) ;
clean_move ) ;
freespace = PageGetHeapFreeSpace ( page ) ; /* needed to update FSM below */
freespace = PageGetHeapFreeSpace ( page ) ; /* needed to update FSM below */
@ -4489,10 +4448,10 @@ heap_xlog_insert(XLogRecPtr lsn, XLogRecord *record)
}
}
/*
/*
* Handles UPDATE , HOT_UPDATE & MOV E
* Handles UPDATE and HOT_UPDAT E
*/
*/
static void
static void
heap_xlog_update ( XLogRecPtr lsn , XLogRecord * record , bool move , bool hot_update )
heap_xlog_update ( XLogRecPtr lsn , XLogRecord * record , bool hot_update )
{
{
xl_heap_update * xlrec = ( xl_heap_update * ) XLogRecGetData ( record ) ;
xl_heap_update * xlrec = ( xl_heap_update * ) XLogRecGetData ( record ) ;
Buffer buffer ;
Buffer buffer ;
@ -4558,19 +4517,6 @@ heap_xlog_update(XLogRecPtr lsn, XLogRecord *record, bool move, bool hot_update)
htup = ( HeapTupleHeader ) PageGetItem ( page , lp ) ;
htup = ( HeapTupleHeader ) PageGetItem ( page , lp ) ;
if ( move )
{
htup - > t_infomask & = ~ ( HEAP_XMIN_COMMITTED |
HEAP_XMIN_INVALID |
HEAP_MOVED_IN ) ;
htup - > t_infomask | = HEAP_MOVED_OFF ;
HeapTupleHeaderClearHotUpdated ( htup ) ;
HeapTupleHeaderSetXvac ( htup , record - > xl_xid ) ;
/* Make sure there is no forward chain link in t_ctid */
htup - > t_ctid = xlrec - > target . tid ;
}
else
{
htup - > t_infomask & = ~ ( HEAP_XMAX_COMMITTED |
htup - > t_infomask & = ~ ( HEAP_XMAX_COMMITTED |
HEAP_XMAX_INVALID |
HEAP_XMAX_INVALID |
HEAP_XMAX_IS_MULTI |
HEAP_XMAX_IS_MULTI |
@ -4584,7 +4530,6 @@ heap_xlog_update(XLogRecPtr lsn, XLogRecord *record, bool move, bool hot_update)
HeapTupleHeaderSetCmax ( htup , FirstCommandId , false ) ;
HeapTupleHeaderSetCmax ( htup , FirstCommandId , false ) ;
/* Set forward chain link in t_ctid */
/* Set forward chain link in t_ctid */
htup - > t_ctid = xlrec - > newtid ;
htup - > t_ctid = xlrec - > newtid ;
}
/* Mark the page as a candidate for pruning */
/* Mark the page as a candidate for pruning */
PageSetPrunable ( page , record - > xl_xid ) ;
PageSetPrunable ( page , record - > xl_xid ) ;
@ -4655,8 +4600,6 @@ newsame:;
elog ( PANIC , " heap_update_redo: invalid max offset number " ) ;
elog ( PANIC , " heap_update_redo: invalid max offset number " ) ;
hsize = SizeOfHeapUpdate + SizeOfHeapHeader ;
hsize = SizeOfHeapUpdate + SizeOfHeapHeader ;
if ( move )
hsize + = ( 2 * sizeof ( TransactionId ) ) ;
newlen = record - > xl_len - hsize ;
newlen = record - > xl_len - hsize ;
Assert ( newlen < = MaxHeapTupleSize ) ;
Assert ( newlen < = MaxHeapTupleSize ) ;
@ -4674,22 +4617,8 @@ newsame:;
htup - > t_infomask = xlhdr . t_infomask ;
htup - > t_infomask = xlhdr . t_infomask ;
htup - > t_hoff = xlhdr . t_hoff ;
htup - > t_hoff = xlhdr . t_hoff ;
if ( move )
{
TransactionId xid [ 2 ] ; /* xmax, xmin */
memcpy ( ( char * ) xid ,
( char * ) xlrec + SizeOfHeapUpdate + SizeOfHeapHeader ,
2 * sizeof ( TransactionId ) ) ;
HeapTupleHeaderSetXmin ( htup , xid [ 1 ] ) ;
HeapTupleHeaderSetXmax ( htup , xid [ 0 ] ) ;
HeapTupleHeaderSetXvac ( htup , record - > xl_xid ) ;
}
else
{
HeapTupleHeaderSetXmin ( htup , record - > xl_xid ) ;
HeapTupleHeaderSetXmin ( htup , record - > xl_xid ) ;
HeapTupleHeaderSetCmin ( htup , FirstCommandId ) ;
HeapTupleHeaderSetCmin ( htup , FirstCommandId ) ;
}
/* Make sure there is no forward chain link in t_ctid */
/* Make sure there is no forward chain link in t_ctid */
htup - > t_ctid = xlrec - > newtid ;
htup - > t_ctid = xlrec - > newtid ;
@ -4857,13 +4786,10 @@ heap_redo(XLogRecPtr lsn, XLogRecord *record)
heap_xlog_delete ( lsn , record ) ;
heap_xlog_delete ( lsn , record ) ;
break ;
break ;
case XLOG_HEAP_UPDATE :
case XLOG_HEAP_UPDATE :
heap_xlog_update ( lsn , record , false , false ) ;
heap_xlog_update ( lsn , record , false ) ;
break ;
case XLOG_HEAP_MOVE :
heap_xlog_update ( lsn , record , true , false ) ;
break ;
break ;
case XLOG_HEAP_HOT_UPDATE :
case XLOG_HEAP_HOT_UPDATE :
heap_xlog_update ( lsn , record , false , true ) ;
heap_xlog_update ( lsn , record , true ) ;
break ;
break ;
case XLOG_HEAP_NEWPAGE :
case XLOG_HEAP_NEWPAGE :
heap_xlog_newpage ( lsn , record ) ;
heap_xlog_newpage ( lsn , record ) ;
@ -4895,10 +4821,7 @@ heap2_redo(XLogRecPtr lsn, XLogRecord *record)
heap_xlog_freeze ( lsn , record ) ;
heap_xlog_freeze ( lsn , record ) ;
break ;
break ;
case XLOG_HEAP2_CLEAN :
case XLOG_HEAP2_CLEAN :
heap_xlog_clean ( lsn , record , false ) ;
heap_xlog_clean ( lsn , record ) ;
break ;
case XLOG_HEAP2_CLEAN_MOVE :
heap_xlog_clean ( lsn , record , true ) ;
break ;
break ;
case XLOG_HEAP2_CLEANUP_INFO :
case XLOG_HEAP2_CLEANUP_INFO :
heap_xlog_cleanup_info ( lsn , record ) ;
heap_xlog_cleanup_info ( lsn , record ) ;
@ -4953,19 +4876,6 @@ heap_desc(StringInfo buf, uint8 xl_info, char *rec)
ItemPointerGetBlockNumber ( & ( xlrec - > newtid ) ) ,
ItemPointerGetBlockNumber ( & ( xlrec - > newtid ) ) ,
ItemPointerGetOffsetNumber ( & ( xlrec - > newtid ) ) ) ;
ItemPointerGetOffsetNumber ( & ( xlrec - > newtid ) ) ) ;
}
}
else if ( info = = XLOG_HEAP_MOVE )
{
xl_heap_update * xlrec = ( xl_heap_update * ) rec ;
if ( xl_info & XLOG_HEAP_INIT_PAGE )
appendStringInfo ( buf , " move(init): " ) ;
else
appendStringInfo ( buf , " move: " ) ;
out_target ( buf , & ( xlrec - > target ) ) ;
appendStringInfo ( buf , " ; new %u/%u " ,
ItemPointerGetBlockNumber ( & ( xlrec - > newtid ) ) ,
ItemPointerGetOffsetNumber ( & ( xlrec - > newtid ) ) ) ;
}
else if ( info = = XLOG_HEAP_HOT_UPDATE )
else if ( info = = XLOG_HEAP_HOT_UPDATE )
{
{
xl_heap_update * xlrec = ( xl_heap_update * ) rec ;
xl_heap_update * xlrec = ( xl_heap_update * ) rec ;
@ -5037,15 +4947,6 @@ heap2_desc(StringInfo buf, uint8 xl_info, char *rec)
xlrec - > node . relNode , xlrec - > block ,
xlrec - > node . relNode , xlrec - > block ,
xlrec - > latestRemovedXid ) ;
xlrec - > latestRemovedXid ) ;
}
}
else if ( info = = XLOG_HEAP2_CLEAN_MOVE )
{
xl_heap_clean * xlrec = ( xl_heap_clean * ) rec ;
appendStringInfo ( buf , " clean_move: rel %u/%u/%u; blk %u remxid %u " ,
xlrec - > node . spcNode , xlrec - > node . dbNode ,
xlrec - > node . relNode , xlrec - > block ,
xlrec - > latestRemovedXid ) ;
}
else if ( info = = XLOG_HEAP2_CLEANUP_INFO )
else if ( info = = XLOG_HEAP2_CLEANUP_INFO )
{
{
xl_heap_cleanup_info * xlrec = ( xl_heap_cleanup_info * ) rec ;
xl_heap_cleanup_info * xlrec = ( xl_heap_cleanup_info * ) rec ;