]> granicus.if.org Git - postgresql/commitdiff
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 */