88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.91 2000/10/24 09:56:07 vadim Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.92 2000/10/29 18:33:39 vadim Exp $
1212 *
1313 *
1414 * INTERFACE ROUTINES
@@ -2057,6 +2057,48 @@ log_heap_move(Relation reln, ItemPointerData from, HeapTuple newtup)
20572057return (log_heap_update (reln ,from ,newtup , true));
20582058}
20592059
2060+ static void
2061+ _heap_cleanup_page_ (Page page )
2062+ {
2063+ OffsetNumber maxoff = PageGetMaxOffsetNumber (page );
2064+ OffsetNumber offnum ;
2065+ ItemId lp ;
2066+ HeapTupleHeader htup ;
2067+
2068+ for (offnum = FirstOffsetNumber ;
2069+ offnum <=maxoff ;
2070+ offnum = OffsetNumberNext (offnum ))
2071+ {
2072+ lp = PageGetItemId (page ,offnum );
2073+
2074+ if (!ItemIdIsUsed (lp ))
2075+ continue ;
2076+
2077+ htup = (HeapTupleHeader )PageGetItem (page ,lp );
2078+
2079+ if (!HeapTupleSatisfiesNow (htup ))
2080+ lp -> lp_flags &= ~LP_USED ;
2081+ }
2082+
2083+ PageRepairFragmentation (page );
2084+
2085+ }
2086+
2087+ static OffsetNumber
2088+ _heap_add_tuple_ (Page page ,HeapTupleHeader htup ,uint32 len ,OffsetNumber offnum )
2089+ {
2090+ ItemId lp = PageGetItemId (page ,offnum );
2091+
2092+ if (len > PageGetFreeSpace (page )||
2093+ lp -> lp_flags & LP_USED || lp -> lp_len != 0 )
2094+ _heap_cleanup_page_ (page );
2095+
2096+ offnum = PageAddItem (page , (Item )htup ,len ,offnum ,
2097+ LP_USED |OverwritePageMode );
2098+
2099+ return (offnum );
2100+ }
2101+
20602102static void
20612103heap_xlog_delete (bool redo ,XLogRecPtr lsn ,XLogRecord * record )
20622104{
@@ -2097,24 +2139,18 @@ heap_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record)
20972139elog (STOP ,"heap_delete_undo: bad page LSN" );
20982140
20992141offnum = ItemPointerGetOffsetNumber (& (xlrec -> target .tid ));
2100- lp = PageGetItemId (page ,offnum );
2142+ if (PageGetMaxOffsetNumber (page ) >=offnum )
2143+ lp = PageGetItemId (page ,offnum );
21012144
2102- if (!ItemIdIsUsed (lp )|| ItemIdDeleted (lp ))
2145+ /* page removed by vacuum ? */
2146+ if (PageGetMaxOffsetNumber (page )< offnum || !ItemIdIsUsed (lp ))
21032147{
2104- if (redo )
2105- elog (STOP ,"heap_delete_redo: unused/deleted target tuple" );
2106- if (!InRecovery )
2107- elog (STOP ,"heap_delete_undo: unused/deleted target tuple in rollback" );
2108- if (ItemIdDeleted (lp ))
2109- {
2110- lp -> lp_flags &= ~LP_USED ;
2111- PageRepairFragmentation (page );
2112- UnlockAndWriteBuffer (buffer );
2113- }
2114- else
2115- UnlockAndReleaseBuffer (buffer );
2148+ PageSetLSN (page ,lsn );
2149+ PageSetSUI (page ,ThisStartUpID );
2150+ UnlockAndWriteBuffer (buffer );
21162151return ;
21172152}
2153+
21182154htup = (HeapTupleHeader )PageGetItem (page ,lp );
21192155
21202156if (redo )
@@ -2189,6 +2225,16 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
21892225return ;
21902226}
21912227
2228+ offnum = ItemPointerGetOffsetNumber (& (xlrec -> target .tid ));
2229+ /* page removed by vacuum ? */
2230+ if (PageGetMaxOffsetNumber (page )+ 1 < offnum )
2231+ {
2232+ PageSetLSN (page ,lsn );
2233+ PageSetSUI (page ,ThisStartUpID );
2234+ UnlockAndWriteBuffer (buffer );
2235+ return ;
2236+ }
2237+
21922238memcpy (tbuf + offsetof(HeapTupleHeaderData ,t_bits ),
21932239(char * )xlrec + SizeOfHeapInsert ,newlen );
21942240newlen += offsetof(HeapTupleHeaderData ,t_bits );
@@ -2200,9 +2246,7 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
22002246htup -> t_xmax = htup -> t_cmax = 0 ;
22012247htup -> t_infomask = HEAP_XMAX_INVALID |HEAP_XMIN_COMMITTED |xlrec -> mask ;
22022248
2203- offnum = PageAddItem (page , (Item )htup ,newlen ,
2204- ItemPointerGetOffsetNumber (& (xlrec -> target .tid )),
2205- LP_USED |OverwritePageMode );
2249+ offnum = _heap_add_tuple_ (page ,htup ,newlen ,offnum );
22062250if (offnum == InvalidOffsetNumber )
22072251elog (STOP ,"heap_insert_redo: failed to add tuple" );
22082252PageSetLSN (page ,lsn );
@@ -2258,6 +2302,9 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
22582302xl_heap_update * xlrec = (xl_heap_update * )XLogRecGetData (record );
22592303Relation reln = XLogOpenRelation (redo ,RM_HEAP_ID ,xlrec -> target .node );
22602304Buffer buffer ;
2305+ bool samepage =
2306+ (ItemPointerGetBlockNumber (& (xlrec -> newtid ))==
2307+ ItemPointerGetBlockNumber (& (xlrec -> target .tid )));
22612308Page page ;
22622309OffsetNumber offnum ;
22632310ItemId lp ;
@@ -2266,13 +2313,6 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
22662313if (!RelationIsValid (reln ))
22672314return ;
22682315
2269- /*
2270- * Currently UPDATE is DELETE + INSERT and so code below are near
2271- * exact sum of code in heap_xlog_delete & heap_xlog_insert. We could
2272- * re-structure code better, but keeping in mind upcoming overwriting
2273- * smgr separate heap_xlog_update code seems to be Good Thing.
2274- */
2275-
22762316/* Deal with old tuple version */
22772317
22782318buffer = XLogReadBuffer (false,reln ,
@@ -2283,6 +2323,8 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
22832323page = (Page )BufferGetPage (buffer );
22842324if (PageIsNew ((PageHeader )page ))
22852325{
2326+ if (samepage )
2327+ gotonewsame ;
22862328PageInit (page ,BufferGetPageSize (buffer ),0 );
22872329PageSetLSN (page ,lsn );
22882330PageSetSUI (page ,ThisStartUpID );
@@ -2295,29 +2337,26 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
22952337if (XLByteLE (lsn ,PageGetLSN (page )))/* changes are applied */
22962338{
22972339UnlockAndReleaseBuffer (buffer );
2340+ if (samepage )
2341+ return ;
22982342gotonewt ;
22992343}
23002344}
23012345else if (XLByteLT (PageGetLSN (page ),lsn ))/* changes are not applied ?! */
23022346elog (STOP ,"heap_update_undo: bad old tuple page LSN" );
23032347
23042348offnum = ItemPointerGetOffsetNumber (& (xlrec -> target .tid ));
2305- lp = PageGetItemId (page ,offnum );
2349+ if (PageGetMaxOffsetNumber (page ) >=offnum )
2350+ lp = PageGetItemId (page ,offnum );
23062351
2307- if (!ItemIdIsUsed (lp )|| ItemIdDeleted (lp ))
2352+ /* page removed by vacuum ? */
2353+ if (PageGetMaxOffsetNumber (page )< offnum || !ItemIdIsUsed (lp ))
23082354{
2309- if (redo )
2310- elog (STOP ,"heap_update_redo: unused/deleted old tuple" );
2311- if (!InRecovery )
2312- elog (STOP ,"heap_update_undo: unused/deleted old tuple in rollback" );
2313- if (ItemIdDeleted (lp ))
2314- {
2315- lp -> lp_flags &= ~LP_USED ;
2316- PageRepairFragmentation (page );
2317- UnlockAndWriteBuffer (buffer );
2318- }
2319- else
2320- UnlockAndReleaseBuffer (buffer );
2355+ if (samepage )
2356+ gotonewsame ;
2357+ PageSetLSN (page ,lsn );
2358+ PageSetSUI (page ,ThisStartUpID );
2359+ UnlockAndWriteBuffer (buffer );
23212360gotonewt ;
23222361}
23232362htup = (HeapTupleHeader )PageGetItem (page ,lp );
@@ -2338,6 +2377,8 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
23382377htup -> t_infomask &= ~(HEAP_XMAX_COMMITTED |
23392378HEAP_XMAX_INVALID |HEAP_MARKED_FOR_UPDATE );
23402379}
2380+ if (samepage )
2381+ gotonewsame ;
23412382PageSetLSN (page ,lsn );
23422383PageSetSUI (page ,ThisStartUpID );
23432384UnlockAndWriteBuffer (buffer );
@@ -2377,6 +2418,8 @@ newt:;
23772418return ;
23782419
23792420page = (Page )BufferGetPage (buffer );
2421+
2422+ newsame :;
23802423if (PageIsNew ((PageHeader )page ))
23812424{
23822425PageInit (page ,BufferGetPageSize (buffer ),0 );
@@ -2401,6 +2444,16 @@ newt:;
24012444return ;
24022445}
24032446
2447+ offnum = ItemPointerGetOffsetNumber (& (xlrec -> newtid ));
2448+ /* page removed by vacuum ? */
2449+ if (PageGetMaxOffsetNumber (page )+ 1 < offnum )
2450+ {
2451+ PageSetLSN (page ,lsn );
2452+ PageSetSUI (page ,ThisStartUpID );
2453+ UnlockAndWriteBuffer (buffer );
2454+ return ;
2455+ }
2456+
24042457hsize = SizeOfHeapUpdate ;
24052458if (move )
24062459hsize += sizeof (TransactionId );
@@ -2431,9 +2484,8 @@ newt:;
24312484htup -> t_infomask = HEAP_XMAX_INVALID |xlrec -> mask ;
24322485}
24332486
2434- offnum = PageAddItem (page , (Item )htup ,newlen ,
2435- ItemPointerGetOffsetNumber (& (xlrec -> newtid )),
2436- LP_USED |OverwritePageMode );
2487+ offnum = _heap_add_tuple_ (page ,htup ,newlen ,
2488+ ItemPointerGetOffsetNumber (& (xlrec -> newtid )));
24372489if (offnum == InvalidOffsetNumber )
24382490elog (STOP ,"heap_update_redo: failed to add tuple" );
24392491PageSetLSN (page ,lsn );