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)
20572057 return (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)
20972139 elog (STOP , "heap_delete_undo: bad page LSN" );
20982140
20992141 offnum = 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 );
21162151 return ;
21172152 }
2153+
21182154 htup = (HeapTupleHeader ) PageGetItem (page , lp );
21192155
21202156 if (redo )
@@ -2189,6 +2225,16 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
21892225 return ;
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+
21922238 memcpy (tbuf + offsetof(HeapTupleHeaderData , t_bits ),
21932239 (char * )xlrec + SizeOfHeapInsert , newlen );
21942240 newlen += offsetof(HeapTupleHeaderData , t_bits );
@@ -2200,9 +2246,7 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
22002246 htup -> t_xmax = htup -> t_cmax = 0 ;
22012247 htup -> 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 );
22062250 if (offnum == InvalidOffsetNumber )
22072251 elog (STOP , "heap_insert_redo: failed to add tuple" );
22082252 PageSetLSN (page , lsn );
@@ -2258,6 +2302,9 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
22582302 xl_heap_update * xlrec = (xl_heap_update * ) XLogRecGetData (record );
22592303 Relation reln = XLogOpenRelation (redo , RM_HEAP_ID , xlrec -> target .node );
22602304 Buffer buffer ;
2305+ bool samepage =
2306+ (ItemPointerGetBlockNumber (& (xlrec -> newtid )) ==
2307+ ItemPointerGetBlockNumber (& (xlrec -> target .tid )));
22612308 Page page ;
22622309 OffsetNumber offnum ;
22632310 ItemId lp ;
@@ -2266,13 +2313,6 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
22662313 if (!RelationIsValid (reln ))
22672314 return ;
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
22782318 buffer = XLogReadBuffer (false, reln ,
@@ -2283,6 +2323,8 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
22832323 page = (Page ) BufferGetPage (buffer );
22842324 if (PageIsNew ((PageHeader ) page ))
22852325 {
2326+ if (samepage )
2327+ goto newsame ;
22862328 PageInit (page , BufferGetPageSize (buffer ), 0 );
22872329 PageSetLSN (page , lsn );
22882330 PageSetSUI (page , ThisStartUpID );
@@ -2295,29 +2337,26 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
22952337 if (XLByteLE (lsn , PageGetLSN (page ))) /* changes are applied */
22962338 {
22972339 UnlockAndReleaseBuffer (buffer );
2340+ if (samepage )
2341+ return ;
22982342 goto newt ;
22992343 }
23002344 }
23012345 else if (XLByteLT (PageGetLSN (page ), lsn )) /* changes are not applied ?! */
23022346 elog (STOP , "heap_update_undo: bad old tuple page LSN" );
23032347
23042348 offnum = 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+ goto newsame ;
2357+ PageSetLSN (page , lsn );
2358+ PageSetSUI (page , ThisStartUpID );
2359+ UnlockAndWriteBuffer (buffer );
23212360 goto newt ;
23222361 }
23232362 htup = (HeapTupleHeader ) PageGetItem (page , lp );
@@ -2338,6 +2377,8 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
23382377 htup -> t_infomask &= ~(HEAP_XMAX_COMMITTED |
23392378 HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE );
23402379 }
2380+ if (samepage )
2381+ goto newsame ;
23412382 PageSetLSN (page , lsn );
23422383 PageSetSUI (page , ThisStartUpID );
23432384 UnlockAndWriteBuffer (buffer );
@@ -2377,6 +2418,8 @@ newt:;
23772418 return ;
23782419
23792420 page = (Page ) BufferGetPage (buffer );
2421+
2422+ newsame :;
23802423 if (PageIsNew ((PageHeader ) page ))
23812424 {
23822425 PageInit (page , BufferGetPageSize (buffer ), 0 );
@@ -2401,6 +2444,16 @@ newt:;
24012444 return ;
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+
24042457 hsize = SizeOfHeapUpdate ;
24052458 if (move )
24062459 hsize += sizeof (TransactionId );
@@ -2431,9 +2484,8 @@ newt:;
24312484 htup -> 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 )));
24372489 if (offnum == InvalidOffsetNumber )
24382490 elog (STOP , "heap_update_redo: failed to add tuple" );
24392491 PageSetLSN (page , lsn );
0 commit comments