XLOG stuff for sequences.
authorVadim B. Mikheev <vadim4o@yahoo.com>
Thu, 30 Nov 2000 01:47:33 +0000 (01:47 +0000)
committerVadim B. Mikheev <vadim4o@yahoo.com>
Thu, 30 Nov 2000 01:47:33 +0000 (01:47 +0000)
CommitDelay in guc.c

src/backend/access/transam/rmgr.c
src/backend/access/transam/xact.c
src/backend/access/transam/xlog.c
src/backend/commands/sequence.c
src/backend/utils/misc/guc.c
src/include/access/htup.h
src/include/access/rmgr.h
src/include/access/xlog.h
src/include/catalog/catversion.h
src/include/commands/sequence.h

index 31a9a1a39d7193dc054f59df917f95d23f803685..ca8b77de573533f2e8d8d6ecc604f4d1ab8555b1 100644 (file)
@@ -7,8 +7,7 @@
 #include "access/xact.h"
 #include "access/xlog.h"
 #include "storage/smgr.h"
-
-#ifdef XLOG
+#include "commands/sequence.h"
 
 RmgrData   RmgrTable[] = {
 {"XLOG", xlog_redo, xlog_undo, xlog_desc},
@@ -25,15 +24,7 @@ RmgrData   RmgrTable[] = {
 {"Btree", btree_redo, btree_undo, btree_desc},
 {"Hash", hash_redo, hash_undo, hash_desc},
 {"Rtree", rtree_redo, rtree_undo, rtree_desc},
-{"Gist", gist_redo, gist_undo, gist_desc}
+{"Gist", gist_redo, gist_undo, gist_desc},
+{"Sequence", seq_redo, seq_undo, seq_desc}
 };
 
-#else /* not XLOG */
-
-/*
- * This is a dummy, but don't write RmgrTable[] = {} here,
- * that's not accepted by some compilers. -- petere
- */
-RmgrData   RmgrTable[1];
-
-#endif /* not XLOG */
index f1d264f130d43b92d9aadc4322d04064167becca..df679d277de75391a8cfff7ad347408a6ed2767c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.84 2000/11/21 21:15:57 petere Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.85 2000/11/30 01:47:31 vadim Exp $
  *
  * NOTES
  *     Transaction aborts can now occur two ways:
@@ -222,7 +222,7 @@ int         XactIsoLevel;
 #ifdef XLOG
 #include "access/xlogutils.h"
 
-int            CommitDelay = 5;    /* 1/200 sec */
+int            CommitDelay = 5;    /* 1/200000 sec */
 
 static void (*_RollbackFunc)(void*) = NULL;
 static void *_RollbackData = NULL;
index c70dbc7b4fbe8edef792a7ab01f1a542c52a10bf..b96159b41446f3d687c4c1147dcbdb1b2894a93e 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.36 2000/11/28 23:27:54 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.37 2000/11/30 01:47:31 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -240,17 +240,26 @@ static bool InRedo = false;
 XLogRecPtr
 XLogInsert(RmgrId rmid, uint8 info, char *hdr, uint32 hdrlen, char *buf, uint32 buflen)
 {
-   XLogCtlInsert *Insert = &XLogCtl->Insert;
-   XLogRecord *record;
-   XLogSubRecord *subrecord;
-   XLogRecPtr  RecPtr;
-   uint32      len = hdrlen + buflen,
-               freespace,
-               wlen;
-   uint16      curridx;
-   bool        updrqst = false;
+   XLogCtlInsert  *Insert = &XLogCtl->Insert;
+   XLogRecord     *record;
+   XLogSubRecord  *subrecord;
+   XLogRecPtr      RecPtr;
+   uint32          len = hdrlen + buflen,
+                   freespace,
+                   wlen;
+   uint16          curridx;
+   bool            updrqst = false;
+   bool            no_tran = (rmid == RM_XLOG_ID) ? true : false;
+
+   if (info & XLR_INFO_MASK)
+   {
+       if ((info & XLR_INFO_MASK) != XLOG_NO_TRAN)
+           elog(STOP, "XLogInsert: invalid info mask %02X", 
+               (info & XLR_INFO_MASK));
+       no_tran = true;
+       info &= ~XLR_INFO_MASK;
+   }
 
-   Assert(!(info & XLR_INFO_MASK));
    if (len == 0 || len > MAXLOGRECSZ)
        elog(STOP, "XLogInsert: invalid record len %u", len);
 
@@ -324,13 +333,14 @@ XLogInsert(RmgrId rmid, uint8 info, char *hdr, uint32 hdrlen, char *buf, uint32
    freespace -= SizeOfXLogRecord;
    record = (XLogRecord *) Insert->currpos;
    record->xl_prev = Insert->PrevRecord;
-   if (rmid != RM_XLOG_ID)
-       record->xl_xact_prev = MyLastRecPtr;
-   else
+   if (no_tran)
    {
        record->xl_xact_prev.xlogid = 0;
        record->xl_xact_prev.xrecoff = 0;
    }
+   else
+       record->xl_xact_prev = MyLastRecPtr;
+
    record->xl_xid = GetCurrentTransactionId();
    record->xl_len = (len > freespace) ? freespace : len;
    record->xl_info = (len > freespace) ? 
@@ -340,7 +350,7 @@ XLogInsert(RmgrId rmid, uint8 info, char *hdr, uint32 hdrlen, char *buf, uint32
    RecPtr.xrecoff =
        XLogCtl->xlblocks[curridx].xrecoff - BLCKSZ +
        Insert->currpos - ((char *) Insert->currpage);
-   if (MyLastRecPtr.xrecoff == 0 && rmid != RM_XLOG_ID)
+   if (MyLastRecPtr.xrecoff == 0 && !no_tran)
    {
        SpinAcquire(SInvalLock);
        MyProc->logRec = RecPtr;
index d6a6b1b4300cdaa526d25dd3d68311224c625e61..210657cdf067900ec2f527d258c37b828e3e5b36 100644 (file)
 #define SEQ_MAXVALUE   ((int4)0x7FFFFFFF)
 #define SEQ_MINVALUE   -(SEQ_MAXVALUE)
 
-typedef struct FormData_pg_sequence
-{
-   NameData    sequence_name;
-   int4        last_value;
-   int4        increment_by;
-   int4        max_value;
-   int4        min_value;
-   int4        cache_value;
-   char        is_cycled;
-   char        is_called;
-} FormData_pg_sequence;
-
-typedef FormData_pg_sequence *Form_pg_sequence;
+/*
+ * We don't want to log each fetching values from sequences,
+ * so we pre-log a few fetches in advance. In the event of
+ * crash we can lose as much as we pre-logged.
+ */
+#define    SEQ_LOG_VALS    32
 
 typedef struct sequence_magic
 {
@@ -138,6 +131,11 @@ DefineSequence(CreateSeqStmt *seq)
                coldef->colname = "cache_value";
                value[i - 1] = Int32GetDatum(new.cache_value);
                break;
+           case SEQ_COL_LOG:
+               typnam->name = "int4";
+               coldef->colname = "log_cnt";
+               value[i - 1] = Int32GetDatum((int32)1);
+               break;
            case SEQ_COL_CYCLE:
                typnam->name = "char";
                coldef->colname = "is_cycled";
@@ -196,10 +194,14 @@ nextval(PG_FUNCTION_ARGS)
    int32       incby,
                maxv,
                minv,
-               cache;
+               cache,
+               log,
+               fetch,
+               last;
    int32       result,
                next,
                rescnt = 0;
+   bool        logit = false;
 
    if (pg_aclcheck(seqname, GetUserId(), ACL_WR) != ACLCHECK_OK)
        elog(ERROR, "%s.nextval: you don't have permissions to set sequence %s",
@@ -219,16 +221,27 @@ nextval(PG_FUNCTION_ARGS)
    seq = read_info("nextval", elm, &buf);      /* lock page' buffer and
                                                 * read tuple */
 
-   next = result = seq->last_value;
+   last = next = result = seq->last_value;
    incby = seq->increment_by;
    maxv = seq->max_value;
    minv = seq->min_value;
-   cache = seq->cache_value;
+   fetch = cache = seq->cache_value;
+   log = seq->log_cnt;
 
    if (seq->is_called != 't')
+   {
        rescnt++;               /* last_value if not called */
+       fetch--;
+       log--;
+   }
 
-   while (rescnt < cache)      /* try to fetch cache numbers */
+   if (log < fetch)
+   {
+       fetch = log = fetch - log + SEQ_LOG_VALS;
+       logit = true;
+   }
+
+   while (fetch)       /* try to fetch cache [+ log ] numbers */
    {
 
        /*
@@ -242,7 +255,7 @@ nextval(PG_FUNCTION_ARGS)
                (maxv < 0 && next + incby > maxv))
            {
                if (rescnt > 0)
-                   break;      /* stop caching */
+                   break;      /* stop fetching */
                if (seq->is_cycled != 't')
                    elog(ERROR, "%s.nextval: got MAXVALUE (%d)",
                         elm->name, maxv);
@@ -258,7 +271,7 @@ nextval(PG_FUNCTION_ARGS)
                (minv >= 0 && next + incby < minv))
            {
                if (rescnt > 0)
-                   break;      /* stop caching */
+                   break;      /* stop fetching */
                if (seq->is_cycled != 't')
                    elog(ERROR, "%s.nextval: got MINVALUE (%d)",
                         elm->name, minv);
@@ -267,17 +280,43 @@ nextval(PG_FUNCTION_ARGS)
            else
                next += incby;
        }
-       rescnt++;               /* got result */
-       if (rescnt == 1)        /* if it's first one - */
-           result = next;      /* it's what to return */
+       fetch--;
+       if (rescnt < cache)
+       {
+           log--;
+           rescnt++;
+           last = next;
+           if (rescnt == 1)        /* if it's first result - */
+               result = next;      /* it's what to return */
+       }
    }
 
    /* save info in local cache */
    elm->last = result;         /* last returned number */
-   elm->cached = next;         /* last cached number */
+   elm->cached = last;         /* last fetched number */
+
+   if (logit)
+   {
+       xl_seq_rec  xlrec;
+       XLogRecPtr  recptr;
+
+       if (fetch)      /* not all numbers were fetched */
+           log -= fetch;
+
+       xlrec.node = elm->rel->rd_node;
+       xlrec.value = next;
+
+       recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG|XLOG_NO_TRAN,
+                   (char*) &xlrec, sizeof(xlrec), NULL, 0);
+
+       PageSetLSN(BufferGetPage(buf), recptr);
+       PageSetSUI(BufferGetPage(buf), ThisStartUpID);
+   }
 
    /* save info in sequence relation */
-   seq->last_value = next;     /* last fetched number */
+   seq->last_value = last;     /* last fetched number */
+   Assert(log >= 0);
+   seq->log_cnt = log;         /* how much is logged */
    seq->is_called = 't';
 
    LockBuffer(buf, BUFFER_LOCK_UNLOCK);
@@ -349,6 +388,21 @@ do_setval(char *seqname, int32 next, bool iscalled)
    /* save info in sequence relation */
    seq->last_value = next;     /* last fetched number */
    seq->is_called = iscalled ? 't' : 'f';
+   seq->log_cnt = (iscalled) ? 0 : 1;
+
+   {
+       xl_seq_rec  xlrec;
+       XLogRecPtr  recptr;
+
+       xlrec.node = elm->rel->rd_node;
+       xlrec.value = next;
+
+       recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_SET|XLOG_NO_TRAN,
+                   (char*) &xlrec, sizeof(xlrec), NULL, 0);
+
+       PageSetLSN(BufferGetPage(buf), recptr);
+       PageSetSUI(BufferGetPage(buf), ThisStartUpID);
+   }
 
    LockBuffer(buf, BUFFER_LOCK_UNLOCK);
 
@@ -638,7 +692,6 @@ init_params(CreateSeqStmt *seq, Form_pg_sequence new)
 
 }
 
-
 static int
 get_param(DefElem *def)
 {
@@ -651,3 +704,80 @@ get_param(DefElem *def)
    elog(ERROR, "DefineSequence: \"%s\" is to be integer", def->defname);
    return -1;
 }
+
+void seq_redo(XLogRecPtr lsn, XLogRecord *record)
+{
+   uint8               info = record->xl_info & ~XLR_INFO_MASK;
+   Relation            reln;
+   Buffer              buffer;
+   Page                page;
+   ItemId              lp;
+   HeapTupleData       tuple;
+   Form_pg_sequence    seq;
+   xl_seq_rec         *xlrec;
+
+   if (info != XLOG_SEQ_LOG && info != XLOG_SEQ_SET)
+       elog(STOP, "seq_redo: unknown op code %u", info);
+
+   xlrec = (xl_seq_rec*) XLogRecGetData(record);
+
+   reln = XLogOpenRelation(true, RM_SEQ_ID, xlrec->node);
+   if (!RelationIsValid(reln))
+       return;
+
+   buffer = XLogReadBuffer(false, reln, 0);
+   if (!BufferIsValid(buffer))
+       elog(STOP, "seq_redo: can't read block of %u/%u", 
+           xlrec->node.tblNode, xlrec->node.relNode);
+
+   page = (Page) BufferGetPage(buffer);
+   if (PageIsNew((PageHeader) page) ||
+       ((sequence_magic *) PageGetSpecialPointer(page))->magic != SEQ_MAGIC)
+       elog(STOP, "seq_redo: uninitialized page of %u/%u",
+           xlrec->node.tblNode, xlrec->node.relNode);
+
+   if (XLByteLE(lsn, PageGetLSN(page)))
+   {
+       UnlockAndReleaseBuffer(buffer);
+       return;
+   }
+
+   lp = PageGetItemId(page, FirstOffsetNumber);
+   Assert(ItemIdIsUsed(lp));
+   tuple.t_data = (HeapTupleHeader) PageGetItem((Page) page, lp);
+
+   seq = (Form_pg_sequence) GETSTRUCT(&tuple);
+
+   seq->last_value = xlrec->value;     /* last logged value */
+   seq->is_called = 't';
+   seq->log_cnt = 0;
+
+   PageSetLSN(page, lsn);
+   PageSetSUI(page, ThisStartUpID);
+   UnlockAndWriteBuffer(buffer);
+
+   return;
+}
+
+void seq_undo(XLogRecPtr lsn, XLogRecord *record)
+{
+}
+
+void seq_desc(char *buf, uint8 xl_info, char* rec)
+{
+   uint8               info = xl_info & ~XLR_INFO_MASK;
+   xl_seq_rec         *xlrec = (xl_seq_rec*) rec;
+
+   if (info == XLOG_SEQ_LOG)
+       strcat(buf, "log: ");
+   else if (info == XLOG_SEQ_SET)
+       strcat(buf, "set: ");
+   else
+   {
+       strcat(buf, "UNKNOWN");
+       return;
+   }
+
+   sprintf(buf + strlen(buf), "node %u/%u; value %d",
+       xlrec->node.tblNode, xlrec->node.relNode, xlrec->value);
+}
index 398fb25bf6818d7fb7eb9cb946f45a562c767383..046c304e24d99bc2a2055648c277033a53a561f0 100644 (file)
@@ -4,7 +4,7 @@
  * Support for grand unified configuration scheme, including SET
  * command, configuration file, and command line options.
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.24 2000/11/29 20:59:53 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.25 2000/11/30 01:47:32 vadim Exp $
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  * Written by Peter Eisentraut <peter_e@gmx.net>.
@@ -39,6 +39,8 @@ extern bool Log_connections;
 extern int CheckPointTimeout;
 extern int XLOGbuffers;
 extern int XLOG_DEBUG;
+extern int CommitDelay;
+
 #ifdef ENABLE_SYSLOG
 extern char *Syslog_facility;
 extern char *Syslog_ident;
@@ -266,15 +268,18 @@ ConfigureNamesInt[] =
    {"unix_socket_permissions", PGC_POSTMASTER,         &Unix_socket_permissions,
     0777, 0000, 0777},
 
-   {"checkpoint_timeout", PGC_POSTMASTER,         &CheckPointTimeout,
+   {"checkpoint_timeout",  PGC_POSTMASTER,         &CheckPointTimeout,
     300, 30, 1800},
 
-   {"wal_buffers", PGC_POSTMASTER,         &XLOGbuffers,
+   {"wal_buffers",         PGC_POSTMASTER,         &XLOGbuffers,
     8, 4, INT_MAX},
 
-   {"wal_debug", PGC_POSTMASTER,         &XLOG_DEBUG,
+   {"wal_debug",           PGC_SUSET,              &XLOG_DEBUG,
     0, 0, 16},
 
+   {"commit_delay",        PGC_USERSET,            &CommitDelay,
+    5, 0, 1000},
+
     {NULL, 0, NULL, 0, 0, 0}
 };
 
index 177176e434ab62eddb644886a727808128fcdd80..6484abf36d8eebc158df46429c1b65b7a17b1079 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: htup.h,v 1.39 2000/11/14 21:04:32 tgl Exp $
+ * $Id: htup.h,v 1.40 2000/11/30 01:47:32 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -186,9 +186,9 @@ extern long heap_sysoffset[];
  */
 typedef struct HeapTupleData
 {
-   uint32      t_len;          /* length of *t_data */
+   uint32          t_len;          /* length of *t_data */
    ItemPointerData t_self;     /* SelfItemPointer */
-   Oid         t_tableOid;     /* table the tuple came from */
+   Oid             t_tableOid;     /* table the tuple came from */
    MemoryContext   t_datamcxt; /* mcxt in which allocated */
    HeapTupleHeader t_data;     /* -> tuple header and data */
 } HeapTupleData;
index 221c52d2f2b5ea7bf0c9e1579a0abf74bfedfa24..af721e9fe763df848f735cc5e4d3e182a771b287 100644 (file)
@@ -21,6 +21,7 @@ typedef uint8 RmgrId;
 #define RM_HASH_ID             12
 #define RM_RTREE_ID                13
 #define RM_GIST_ID             14
-#define RM_MAX_ID              RM_GIST_ID
+#define RM_SEQ_ID              15
+#define RM_MAX_ID              RM_SEQ_ID
 
 #endif  /* RMGR_H */
index 4654296e116eefd1ef3c8ab75a9fa3b11927e3c4..785ac94c9b20a48d015dee294126dd850cdd8b00 100644 (file)
@@ -3,7 +3,7 @@
  *
  * PostgreSQL transaction log manager
  *
- * $Header: /cvsroot/pgsql/src/include/access/xlog.h,v 1.11 2000/11/25 20:33:53 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/include/access/xlog.h,v 1.12 2000/11/30 01:47:32 vadim Exp $
  */
 #ifndef XLOG_H
 #define XLOG_H
@@ -54,6 +54,12 @@ typedef struct XLogSubRecord
 #define XLR_TO_BE_CONTINUED        0x01
 #define    XLR_INFO_MASK           0x0F
 
+/*
+ * Sometimes we log records which are out of transaction control.
+ * Rmgr may use flag below for this purpose.
+ */
+#define    XLOG_NO_TRAN            XLR_INFO_MASK
+
 #define XLOG_PAGE_MAGIC 0x17345168
 
 typedef struct XLogPageHeaderData
index 85e4c02b53317a8cb92d99a230eedb27fa3ca4e5..93958d5ec059ea0fbdda8a66f226453056fdc5f7 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.64 2000/11/25 20:33:53 tgl Exp $
+ * $Id: catversion.h,v 1.65 2000/11/30 01:47:33 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 200011251
+#define CATALOG_VERSION_NO 200011291
 
 #endif
index 0429d2295324b28721d5cf6691a55a73d8385f5a..415364862b23190d4e37b2ddebe76b8376c8e011 100644 (file)
 #define SEQUENCE_H
 
 #include "nodes/parsenodes.h"
+#include "access/xlog.h"
+
+typedef struct FormData_pg_sequence
+{
+   NameData    sequence_name;
+   int4        last_value;
+   int4        increment_by;
+   int4        max_value;
+   int4        min_value;
+   int4        cache_value;
+   int4        log_cnt;
+   char        is_cycled;
+   char        is_called;
+} FormData_pg_sequence;
+
+typedef FormData_pg_sequence *Form_pg_sequence;
 
 /*
  * Columns of a sequence relation
 #define SEQ_COL_MAXVALUE       4
 #define SEQ_COL_MINVALUE       5
 #define SEQ_COL_CACHE          6
-#define SEQ_COL_CYCLE          7
-#define SEQ_COL_CALLED         8
+#define    SEQ_COL_LOG             7
+#define SEQ_COL_CYCLE          8
+#define SEQ_COL_CALLED         9
 
 #define SEQ_COL_FIRSTCOL       SEQ_COL_NAME
 #define SEQ_COL_LASTCOL            SEQ_COL_CALLED
 
+/* XLOG stuff */
+#define    XLOG_SEQ_LOG            0x00
+#define    XLOG_SEQ_SET            0x10
+
+typedef struct xl_seq_rec
+{
+   RelFileNode             node;
+   int4                    value;      /* last logged value */
+} xl_seq_rec;
+
 extern Datum nextval(PG_FUNCTION_ARGS);
 extern Datum currval(PG_FUNCTION_ARGS);
 extern Datum setval(PG_FUNCTION_ARGS);
@@ -35,4 +62,8 @@ extern Datum setval_and_iscalled(PG_FUNCTION_ARGS);
 extern void DefineSequence(CreateSeqStmt *stmt);
 extern void CloseSequences(void);
 
+extern void seq_redo(XLogRecPtr lsn, XLogRecord *rptr);
+extern void seq_undo(XLogRecPtr lsn, XLogRecord *rptr);
+extern void seq_desc(char *buf, uint8 xl_info, char* rec);
+
 #endif  /* SEQUENCE_H */