88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.67 2001/11/05 17:46:24 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.68 2002/01/11 18:16:04 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
4343#define SEQ_MINVALUE (-SEQ_MAXVALUE)
4444
4545/*
46- * We don't want to log each fetchingvalues fromsequences ,
46+ * We don't want to log each fetchingof a value froma sequence ,
4747 * so we pre-log a few fetches in advance. In the event of
4848 * crash we can lose as much as we pre-logged.
4949 */
@@ -199,24 +199,59 @@ DefineSequence(CreateSeqStmt *seq)
199199/* hack: ensure heap_insert will insert on the just-created page */
200200rel -> rd_targblock = 0 ;
201201
202- /* Now- form & insert sequence tuple */
202+ /* Now form & insert sequence tuple */
203203tuple = heap_formtuple (tupDesc ,value ,null );
204204heap_insert (rel ,tuple );
205205
206+ Assert (ItemPointerGetOffsetNumber (& (tuple -> t_self ))== FirstOffsetNumber );
207+
206208/*
207- * After crash REDO of heap_insert above would re-init page and our
208- * magic number would be lost. We have to log sequence creation. This
209- * means two log records instead of one -:(
209+ * Two special hacks here:
210+ *
211+ * 1. Since VACUUM does not process sequences, we have to force the tuple
212+ * to have xmin = FrozenTransactionId now. Otherwise it would become
213+ * invisible to SELECTs after 2G transactions. It is okay to do this
214+ * because if the current transaction aborts, no other xact will ever
215+ * examine the sequence tuple anyway.
216+ *
217+ * 2. Even though heap_insert emitted a WAL log record, we have to emit
218+ * an XLOG_SEQ_LOG record too, since (a) the heap_insert record will
219+ * not have the right xmin, and (b) REDO of the heap_insert record
220+ * would re-init page and sequence magic number would be lost. This
221+ * means two log records instead of one :-(
210222 */
211223LockBuffer (buf ,BUFFER_LOCK_EXCLUSIVE );
212224START_CRIT_SECTION ();
225+
226+ {
227+ /*
228+ * Note that the "tuple" structure is still just a local tuple record
229+ * created by heap_formtuple; its t_data pointer doesn't point at the
230+ * disk buffer. To scribble on the disk buffer we need to fetch the
231+ * item pointer. But do the same to the local tuple, since that will
232+ * be the source for the WAL log record, below.
233+ */
234+ ItemId itemId ;
235+ Item item ;
236+
237+ itemId = PageGetItemId ((Page )page ,FirstOffsetNumber );
238+ item = PageGetItem ((Page )page ,itemId );
239+
240+ ((HeapTupleHeader )item )-> t_xmin = FrozenTransactionId ;
241+ ((HeapTupleHeader )item )-> t_infomask |=HEAP_XMIN_COMMITTED ;
242+
243+ tuple -> t_data -> t_xmin = FrozenTransactionId ;
244+ tuple -> t_data -> t_infomask |=HEAP_XMIN_COMMITTED ;
245+ }
246+
213247{
214248xl_seq_rec xlrec ;
215249XLogRecPtr recptr ;
216250XLogRecData rdata [2 ];
217251Form_pg_sequence newseq = (Form_pg_sequence )GETSTRUCT (tuple );
218252
219253/* We do not log first nextval call, so "advance" sequence here */
254+ /* Note we are scribbling on local tuple, not the disk buffer */
220255newseq -> is_called = true;
221256newseq -> log_cnt = 0 ;
222257
@@ -239,8 +274,8 @@ DefineSequence(CreateSeqStmt *seq)
239274END_CRIT_SECTION ();
240275
241276LockBuffer (buf ,BUFFER_LOCK_UNLOCK );
242- ReleaseBuffer (buf );
243- heap_close (rel ,AccessExclusiveLock );
277+ WriteBuffer (buf );
278+ heap_close (rel ,NoLock );
244279}
245280
246281
@@ -628,7 +663,6 @@ read_info(char *caller, SeqTable elm, Buffer *buf)
628663elm -> increment = seq -> increment_by ;
629664
630665return seq ;
631-
632666}
633667
634668
@@ -858,6 +892,8 @@ seq_redo(XLogRecPtr lsn, XLogRecord *record)
858892
859893page = (Page )BufferGetPage (buffer );
860894
895+ /* Always reinit the page and reinstall the magic number */
896+ /* See comments in DefineSequence */
861897PageInit ((Page )page ,BufferGetPageSize (buffer ),sizeof (sequence_magic ));
862898sm = (sequence_magic * )PageGetSpecialPointer (page );
863899sm -> magic = SEQ_MAGIC ;