@@ -307,6 +307,7 @@ fill_seq_with_data(Relation rel, HeapTuple tuple)
307307 Buffer buf ;
308308 Page page ;
309309 sequence_magic * sm ;
310+ OffsetNumber offnum ;
310311
311312 /* Initialize first page of relation with special magic number */
312313
@@ -319,56 +320,33 @@ fill_seq_with_data(Relation rel, HeapTuple tuple)
319320 sm = (sequence_magic * ) PageGetSpecialPointer (page );
320321 sm -> magic = SEQ_MAGIC ;
321322
322- /* hack: ensure heap_insert will insert on the just-created page */
323- RelationSetTargetBlock (rel , 0 );
324-
325323 /* Now insert sequence tuple */
326- simple_heap_insert (rel , tuple );
327324
328- Assert ( ItemPointerGetOffsetNumber ( & ( tuple -> t_self )) == FirstOffsetNumber );
325+ LockBuffer ( buf , BUFFER_LOCK_EXCLUSIVE );
329326
330327 /*
331- * Two special hacks here:
332- *
333- * 1. Since VACUUM does not process sequences, we have to force the tuple
328+ * Since VACUUM does not process sequences, we have to force the tuple
334329 * to have xmin = FrozenTransactionId now. Otherwise it would become
335330 * invisible to SELECTs after 2G transactions. It is okay to do this
336331 * because if the current transaction aborts, no other xact will ever
337332 * examine the sequence tuple anyway.
338- *
339- * 2. Even though heap_insert emitted a WAL log record, we have to emit an
340- * XLOG_SEQ_LOG record too, since (a) the heap_insert record will not have
341- * the right xmin, and (b) REDO of the heap_insert record would re-init
342- * page and sequence magic number would be lost. This means two log
343- * records instead of one :-(
344333 */
345- LockBuffer (buf , BUFFER_LOCK_EXCLUSIVE );
334+ HeapTupleHeaderSetXmin (tuple -> t_data , FrozenTransactionId );
335+ HeapTupleHeaderSetXminFrozen (tuple -> t_data );
336+ HeapTupleHeaderSetCmin (tuple -> t_data , FirstCommandId );
337+ HeapTupleHeaderSetXmax (tuple -> t_data , InvalidTransactionId );
338+ tuple -> t_data -> t_infomask |= HEAP_XMAX_INVALID ;
339+ ItemPointerSet (& tuple -> t_data -> t_ctid , 0 , FirstOffsetNumber );
346340
347341 START_CRIT_SECTION ();
348342
349- {
350- /*
351- * Note that the "tuple" structure is still just a local tuple record
352- * created by heap_form_tuple; its t_data pointer doesn't point at the
353- * disk buffer. To scribble on the disk buffer we need to fetch the
354- * item pointer. But do the same to the local tuple, since that will
355- * be the source for the WAL log record, below.
356- */
357- ItemId itemId ;
358- Item item ;
359-
360- itemId = PageGetItemId ((Page ) page , FirstOffsetNumber );
361- item = PageGetItem ((Page ) page , itemId );
362-
363- HeapTupleHeaderSetXmin ((HeapTupleHeader ) item , FrozenTransactionId );
364- HeapTupleHeaderSetXminFrozen ((HeapTupleHeader ) item );
365-
366- HeapTupleHeaderSetXmin (tuple -> t_data , FrozenTransactionId );
367- HeapTupleHeaderSetXminFrozen (tuple -> t_data );
368- }
369-
370343 MarkBufferDirty (buf );
371344
345+ offnum = PageAddItem (page , (Item ) tuple -> t_data , tuple -> t_len ,
346+ InvalidOffsetNumber , false, false);
347+ if (offnum != FirstOffsetNumber )
348+ elog (ERROR , "failed to add sequence tuple to page" );
349+
372350 /* XLOG stuff */
373351 if (RelationNeedsWAL (rel ))
374352 {
@@ -1576,9 +1554,8 @@ seq_redo(XLogRecPtr lsn, XLogRecord *record)
15761554 page = (Page ) BufferGetPage (buffer );
15771555
15781556 /*
1579- * We must always reinit the page and reinstall the magic number (see
1580- * comments in fill_seq_with_data). However, since this WAL record type
1581- * is also used for updating sequences, it's possible that a hot-standby
1557+ * We always reinit the page. However, since this WAL record type is
1558+ * also used for updating sequences, it's possible that a hot-standby
15821559 * backend is examining the page concurrently; so we mustn't transiently
15831560 * trash the buffer. The solution is to build the correct new page
15841561 * contents in local workspace and then memcpy into the buffer. Then only
0 commit comments