]> granicus.if.org Git - postgresql/commitdiff
New CHECKPOINT command.
authorVadim B. Mikheev <vadim4o@yahoo.com>
Sun, 5 Nov 2000 22:50:21 +0000 (22:50 +0000)
committerVadim B. Mikheev <vadim4o@yahoo.com>
Sun, 5 Nov 2000 22:50:21 +0000 (22:50 +0000)
Auto removing of offline log files and creating new file
at checkpoint time.

src/backend/access/transam/xact.c
src/backend/access/transam/xlog.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/backend/parser/keywords.c
src/backend/storage/ipc/sinval.c
src/backend/tcop/utility.c
src/include/access/xlog.h
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h

index 28d3555d438940e253b14f4a45a0a4513a7a8194..cc4209fa51fc73151b39d992fa8874ec23a0f9a5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.79 2000/10/29 18:33:41 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.80 2000/11/05 22:50:19 vadim Exp $
  *
  * NOTES
  *             Transaction aborts can now occur two ways:
@@ -678,7 +678,7 @@ RecordTransactionCommit()
        leak = BufferPoolCheckLeak();
 
 #ifdef XLOG
-       if (MyLastRecPtr.xlogid != 0 || MyLastRecPtr.xrecoff != 0)
+       if (MyLastRecPtr.xrecoff != 0)
        {
                xl_xact_commit  xlrec;
                struct timeval  delay;
@@ -701,7 +701,6 @@ RecordTransactionCommit()
                delay.tv_usec = CommitDelay;
                (void) select(0, NULL, NULL, NULL, &delay);
                XLogFlush(recptr);
-               MyLastRecPtr.xlogid = 0;
                MyLastRecPtr.xrecoff = 0;
 
                TransactionIdCommit(xid);
@@ -836,7 +835,7 @@ RecordTransactionAbort(void)
                TransactionIdAbort(xid);
 
 #ifdef XLOG
-       if (MyLastRecPtr.xlogid != 0 || MyLastRecPtr.xrecoff != 0)
+       if (MyLastRecPtr.xrecoff != 0)
        {
                xl_xact_abort   xlrec;
                XLogRecPtr              recptr;
@@ -844,6 +843,8 @@ RecordTransactionAbort(void)
                xlrec.xtime = time(NULL);
                recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT,
                        (char*) &xlrec, SizeOfXactAbort, NULL, 0);
+
+               MyProc->logRec.xrecoff = 0;
        }
 #endif
 
@@ -1189,7 +1190,6 @@ AbortTransaction(void)
        AtEOXact_Files();
 
        /* Here we'll rollback xaction changes */
-       MyLastRecPtr.xlogid = 0;
        MyLastRecPtr.xrecoff = 0;
 
        AtAbort_Locks();
index 13dba319185162838201049a69c3bcaec5cee3c0..ffd7040a459be3311e43e5ac4caad02405626f78 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.23 2000/11/03 11:39:35 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.24 2000/11/05 22:50:19 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,8 @@
 #include <errno.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+#include <sys/types.h>
+#include <dirent.h>
 
 #include "postgres.h"
 
@@ -48,7 +50,10 @@ StartUpID    ThisStartUpID = 0;
 
 int                    XLOG_DEBUG = 1;
 
+/* To read/update control file and create new log file */
 SPINLOCK       ControlFileLockId;
+
+/* To generate new xid */
 SPINLOCK       XidGenLockId;
 
 extern VariableCache ShmemVariableCache;
@@ -91,19 +96,20 @@ typedef struct XLogCtlWrite
 
 typedef struct XLogCtlData
 {
-       XLogCtlInsert Insert;
-       XLgwrRqst       LgwrRqst;
-       XLgwrResult LgwrResult;
-       XLogCtlWrite Write;
-       char       *pages;
-       XLogRecPtr *xlblocks;           /* 1st byte ptr-s + BLCKSZ */
-       uint32          XLogCacheByte;
-       uint32          XLogCacheBlck;
-       StartUpID       ThisStartUpID;
+       XLogCtlInsert   Insert;
+       XLgwrRqst               LgwrRqst;
+       XLgwrResult             LgwrResult;
+       XLogCtlWrite    Write;
+       char               *pages;
+       XLogRecPtr         *xlblocks;           /* 1st byte ptr-s + BLCKSZ */
+       uint32                  XLogCacheByte;
+       uint32                  XLogCacheBlck;
+       StartUpID               ThisStartUpID;
 #ifdef HAS_TEST_AND_SET
-       slock_t         insert_lck;
-       slock_t         info_lck;
-       slock_t         lgwr_lck;
+       slock_t                 insert_lck;
+       slock_t                 info_lck;
+       slock_t                 lgwr_lck;
+       slock_t                 chkp_lck;               /* checkpoint lock */
 #endif
 } XLogCtlData;
 
@@ -133,6 +139,7 @@ typedef struct ControlFileData
        uint32          blcksz;                 /* block size for this DB */
        uint32          relseg_size;    /* blocks per segment of large relation */
        uint32          catalog_version_no;             /* internal version number */
+       char            archdir[MAXPGPATH];             /* where to move offline log files */
 
        /*
         * MORE DATA FOLLOWS AT THE END OF THIS STRUCTURE - locations of data
@@ -170,6 +177,10 @@ typedef struct CheckPoint
                        snprintf(path, MAXPGPATH, "%s%c%08X%08X",       \
                                         XLogDir, SEP_CHAR, log, seg)
 
+#define XLogTempFileName(path, log, seg)       \
+                       snprintf(path, MAXPGPATH, "%s%cT%08X%08X",      \
+                                        XLogDir, SEP_CHAR, log, seg)
+
 #define PrevBufIdx(curridx)            \
                ((curridx == 0) ? XLogCtl->XLogCacheBlck : (curridx - 1))
 
@@ -198,7 +209,7 @@ typedef struct CheckPoint
 
 static void GetFreeXLBuffer(void);
 static void XLogWrite(char *buffer);
-static int     XLogFileInit(uint32 log, uint32 seg);
+static int     XLogFileInit(uint32 log, uint32 seg, bool *usexistent);
 static int     XLogFileOpen(uint32 log, uint32 seg, bool econt);
 static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, char *buffer);
 static char *str_time(time_t tnow);
@@ -672,6 +683,7 @@ XLogWrite(char *buffer)
        char       *from;
        uint32          wcnt = 0;
        int                     i = 0;
+       bool            usexistent;
 
        for (; XLByteLT(LgwrResult.Write, LgwrRqst.Write);)
        {
@@ -710,13 +722,18 @@ XLogWrite(char *buffer)
                        logId = LgwrResult.Write.xlogid;
                        logSeg = (LgwrResult.Write.xrecoff - 1) / XLogSegSize;
                        logOff = 0;
-                       logFile = XLogFileInit(logId, logSeg);
                        SpinAcquire(ControlFileLockId);
+                       /* create/use new log file */
+                       usexistent = true;
+                       logFile = XLogFileInit(logId, logSeg, &usexistent);
                        ControlFile->logId = logId;
                        ControlFile->logSeg = logSeg + 1;
                        ControlFile->time = time(NULL);
                        UpdateControlFile();
                        SpinRelease(ControlFileLockId);
+                       if (!usexistent)        /* there was no file */
+                               elog(LOG, "XLogWrite: had to create new log file - "
+                                       "you probably should do checkpoints more often");
                }
 
                if (logFile < 0)
@@ -780,17 +797,39 @@ XLogWrite(char *buffer)
 }
 
 static int
-XLogFileInit(uint32 log, uint32 seg)
+XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
 {
        char            path[MAXPGPATH];
+       char            tpath[MAXPGPATH];
        int                     fd;
 
        XLogFileName(path, log, seg);
+
+       /*
+        * Try to use existent file (checkpoint maker
+        * creates it sometime).
+        */
+       if (*usexistent)
+       {
+               fd = BasicOpenFile(path, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
+               if (fd < 0)
+               {
+                       if (errno != ENOENT)
+                               elog(STOP, "InitOpen(logfile %u seg %u) failed: %d",
+                                       logId, logSeg, errno);
+               }
+               else
+                       return(fd);
+               *usexistent = false;
+       }
+
+       XLogTempFileName(tpath, log, seg);
+       unlink(tpath);
        unlink(path);
 
-       fd = BasicOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, S_IRUSR | S_IWUSR);
+       fd = BasicOpenFile(tpath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, S_IRUSR | S_IWUSR);
        if (fd < 0)
-               elog(STOP, "Init(logfile %u seg %u) failed: %d",
+               elog(STOP, "InitCreate(logfile %u seg %u) failed: %d",
                         logId, logSeg, errno);
 
        if (lseek(fd, XLogSegSize - 1, SEEK_SET) != (off_t) (XLogSegSize - 1))
@@ -809,6 +848,15 @@ XLogFileInit(uint32 log, uint32 seg)
                elog(STOP, "Lseek(logfile %u seg %u off %u) failed: %d",
                         log, seg, 0, errno);
 
+       close(fd);
+       link(tpath, path);
+       unlink(tpath);
+
+       fd = BasicOpenFile(path, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
+       if (fd < 0)
+               elog(STOP, "InitReopen(logfile %u seg %u) failed: %d",
+                        logId, logSeg, errno);
+
        return (fd);
 }
 
@@ -837,6 +885,49 @@ XLogFileOpen(uint32 log, uint32 seg, bool econt)
        return (fd);
 }
 
+/*
+ * (Re)move offline log files older or equal to passwd one
+ */
+static void
+MoveOfflineLogs(char *archdir, uint32 _logId, uint32 _logSeg)
+{
+       DIR                        *xldir;
+       struct dirent  *xlde;
+       char                    lastoff[32];
+       char                    path[MAXPGPATH];
+
+       Assert(archdir[0] == 0);        /* ! implemented yet */
+
+       xldir = opendir(XLogDir);
+       if (xldir == NULL)
+               elog(STOP, "MoveOfflineLogs: cannot open xlog dir: %d", errno);
+
+       sprintf(lastoff, "%08X%08X", _logId, _logSeg);
+
+       errno = 0;
+       while ((xlde = readdir(xldir)) != NULL)
+       {
+               if (strlen(xlde->d_name) != 16 || 
+                       strspn(xlde->d_name, "0123456789ABCDEF") != 16)
+                       continue;
+               if (strcmp(xlde->d_name, lastoff) > 0)
+               {
+                       elog(LOG, "MoveOfflineLogs: skip %s", xlde->d_name);
+                       errno = 0;
+                       continue;
+               }
+               elog(LOG, "MoveOfflineLogs: %s %s", (archdir[0]) ? 
+                       "archive" : "remove", xlde->d_name);
+               sprintf(path, "%s%c%s", XLogDir, SEP_CHAR, xlde->d_name);
+               if (archdir[0] != 0)
+                       unlink(path);
+               errno = 0;
+       }
+       if (errno)
+               elog(STOP, "MoveOfflineLogs: cannot read xlog dir: %d", errno);
+       closedir(xldir);
+}
+
 static XLogRecord *
 ReadRecord(XLogRecPtr *RecPtr, char *buffer)
 {
@@ -1183,6 +1274,7 @@ BootStrapXLOG()
        int                     fd;
        char            buffer[BLCKSZ];
        CheckPoint      checkPoint;
+       bool            usexistent = false;
 
 #ifdef XLOG
        XLogPageHeader page = (XLogPageHeader) buffer;
@@ -1217,7 +1309,7 @@ BootStrapXLOG()
        record->xl_rmid = RM_XLOG_ID;
        memcpy((char *) record + SizeOfXLogRecord, &checkPoint, sizeof(checkPoint));
 
-       logFile = XLogFileInit(0, 0);
+       logFile = XLogFileInit(0, 0, &usexistent);
 
        if (write(logFile, buffer, BLCKSZ) != BLCKSZ)
                elog(STOP, "BootStrapXLOG failed to write logfile: %d", errno);
@@ -1297,6 +1389,7 @@ StartupXLOG()
        S_INIT_LOCK(&(XLogCtl->insert_lck));
        S_INIT_LOCK(&(XLogCtl->info_lck));
        S_INIT_LOCK(&(XLogCtl->lgwr_lck));
+       S_INIT_LOCK(&(XLogCtl->chkp_lck));
 
        /*
         * Open/read Control file
@@ -1556,6 +1649,8 @@ ShutdownXLOG()
        elog(LOG, "Data Base System shut down at %s", str_time(time(NULL)));
 }
 
+extern XLogRecPtr      GetUndoRecPtr(void);
+
 void
 CreateCheckPoint(bool shutdown)
 {
@@ -1565,6 +1660,21 @@ CreateCheckPoint(bool shutdown)
        XLogCtlInsert *Insert = &XLogCtl->Insert;
        uint32          freespace;
        uint16          curridx;
+       uint32          _logId;
+       uint32          _logSeg;
+       char            archdir[MAXPGPATH];
+
+       if (MyLastRecPtr.xrecoff != 0)
+               elog(ERROR, "CreateCheckPoint: cannot be called inside transaction block");
+       while (TAS(&(XLogCtl->chkp_lck)))
+       {
+               struct timeval delay = {2, 0};
+
+               if (shutdown)
+                       elog(STOP, "Checkpoint lock is busy while data base is shutting down");
+               (void) select(0, NULL, NULL, NULL, &delay);
+       }
 
        memset(&checkPoint, 0, sizeof(checkPoint));
        if (shutdown)
@@ -1579,7 +1689,7 @@ CreateCheckPoint(bool shutdown)
        /* Get REDO record ptr */
        while (TAS(&(XLogCtl->insert_lck)))
        {
-               struct timeval delay = {0, 5000};
+               struct timeval delay = {1, 0};
 
                if (shutdown)
                        elog(STOP, "XLog insert lock is busy while data base is shutting down");
@@ -1615,7 +1725,7 @@ CreateCheckPoint(bool shutdown)
        FlushBufferPool();
 
        /* Get UNDO record ptr - should use oldest of PROC->logRec */
-       checkPoint.undo.xrecoff = 0;
+       checkPoint.undo = GetUndoRecPtr();
 
        if (shutdown && checkPoint.undo.xrecoff != 0)
                elog(STOP, "Active transaction while data base is shutting down");
@@ -1633,9 +1743,35 @@ CreateCheckPoint(bool shutdown)
        SpinAcquire(ControlFileLockId);
        if (shutdown)
                ControlFile->state = DB_SHUTDOWNED;
-
 #ifdef XLOG
+       else    /* create new log file */
+       {
+               if (recptr.xrecoff % XLogSegSize >= 
+                       (uint32) (0.75 * XLogSegSize))
+               {
+                       int             lf;
+                       bool    usexistent = true;
+
+                       _logId = recptr.xlogid;
+                       _logSeg = recptr.xrecoff / XLogSegSize;
+                       if (_logSeg >= XLogLastSeg)
+                       {
+                               _logId++;
+                               _logSeg = 0;
+                       }
+                       else
+                               _logSeg++;
+                       lf = XLogFileInit(_logId, _logSeg, &usexistent);
+                       close(lf);
+               }
+       }
+
        ControlFile->checkPoint = MyLastRecPtr;
+
+       _logId = ControlFile->logId;
+       _logSeg = ControlFile->logSeg - 1;
+       strcpy(archdir, ControlFile->archdir);
+
 #else
        ControlFile->checkPoint.xlogid = 0;
        ControlFile->checkPoint.xrecoff = SizeOfXLogPHD;
@@ -1645,6 +1781,33 @@ CreateCheckPoint(bool shutdown)
        UpdateControlFile();
        SpinRelease(ControlFileLockId);
 
+#ifdef XLOG
+       /*
+        * Delete offline log files. Get oldest online
+        * log file from undo rec if it's valid.
+        */
+       if (checkPoint.undo.xrecoff != 0)
+       {
+               _logId = checkPoint.undo.xlogid;
+               _logSeg = checkPoint.undo.xrecoff / XLogSegSize;
+       }
+       if (_logId || _logSeg)
+       {
+               if (_logSeg)
+                       _logSeg--;
+               else
+               {
+                       _logId--;
+                       _logSeg = 0;
+               }
+               MoveOfflineLogs(archdir, _logId, _logSeg);
+       }
+
+       S_UNLOCK(&(XLogCtl->chkp_lck));
+
+       MyLastRecPtr.xrecoff = 0;       /* to avoid commit record */
+#endif
+
        return;
 }
 
index 406e85ce623aefa7193805a547d682028a6e4474..93866787f37443ca6466f4ee812c2d741330f933 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.129 2000/11/05 00:15:52 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.130 2000/11/05 22:50:19 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2895,6 +2895,9 @@ copyObject(void *from)
                case T_SetSessionStmt:
                        retval = _copySetSessionStmt(from);
                        break;
+               case T_CheckPointStmt:
+                       retval = (void*)makeNode(CheckPointStmt);
+                       break;
 
                case T_A_Expr:
                        retval = _copyAExpr(from);
index 08087136a10d96675b88700d86091599cdc73c43..7ed95db9679052be7a785889ddd0a49f67010b9e 100644 (file)
@@ -20,7 +20,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.79 2000/11/05 00:15:52 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.80 2000/11/05 22:50:19 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2049,6 +2049,9 @@ equal(void *a, void *b)
                case T_SetSessionStmt:
                        retval = _equalSetSessionStmt(a, b);
                        break;
+               case T_CheckPointStmt:
+                       retval = true;
+                       break;
 
                case T_A_Expr:
                        retval = _equalAExpr(a, b);
index 2fbfa853dd300663a4c211fcf8c638d0f796a90a..70245ecd010f402c90fdc3f70325f782a5e34ba2 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.204 2000/11/05 00:15:54 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.205 2000/11/05 22:50:20 vadim Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -136,7 +136,7 @@ static void doNegateFloat(Value *v);
                RenameStmt, RevokeStmt, RuleActionStmt, RuleActionStmtOrEmpty,
                RuleStmt, SelectStmt, SetSessionStmt, TransactionStmt, TruncateStmt,
                UnlistenStmt, UpdateStmt, VacuumStmt, VariableResetStmt,
-               VariableSetStmt, VariableShowStmt, ViewStmt
+               VariableSetStmt, VariableShowStmt, ViewStmt, CheckPointStmt
 
 %type <node>   select_no_parens, select_clause, simple_select
 
@@ -291,7 +291,7 @@ static void doNegateFloat(Value *v);
 /* Keywords (in SQL92 reserved words) */
 %token ABSOLUTE, ACTION, ADD, ALL, ALTER, AND, ANY, AS, ASC,
                BEGIN_TRANS, BETWEEN, BOTH, BY,
-               CASCADE, CASE, CAST, CHAR, CHARACTER, CHECK, CLOSE,
+               CASCADE, CASE, CAST, CHAR, CHARACTER, CHECK, CLOSE, 
                COALESCE, COLLATE, COLUMN, COMMIT,
                CONSTRAINT, CONSTRAINTS, CREATE, CROSS, CURRENT_DATE,
                CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
@@ -336,7 +336,7 @@ static void doNegateFloat(Value *v);
  */
 %token ABORT_TRANS, ACCESS, AFTER, AGGREGATE, ANALYZE,
                BACKWARD, BEFORE, BINARY, BIT,
-               CACHE, CLUSTER, COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE,
+               CACHE, CHECKPOINT, CLUSTER, COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE,
                DATABASE, DELIMITERS, DO,
                EACH, ENCODING, EXCLUSIVE, EXPLAIN, EXTEND,
                FORCE, FORWARD, FUNCTION, HANDLER,
@@ -470,6 +470,7 @@ stmt :      AlterSchemaStmt
                | VariableShowStmt
                | VariableResetStmt
                | ConstraintsSetStmt
+               | CheckPointStmt
                | /*EMPTY*/
                        { $$ = (Node *)NULL; }
                ;
@@ -957,6 +958,16 @@ constraints_set_mode:      DEFERRED
                ;
 
 
+/*
+ * Checkpoint statement
+ */
+CheckPointStmt: CHECKPOINT
+                               {
+                                       CheckPointStmt *n = makeNode(CheckPointStmt);
+                                       $$ = (Node *)n;
+                               }
+                       ;
+
 /*****************************************************************************
  *
  *     ALTER TABLE variations
@@ -5389,6 +5400,7 @@ TokenId:  ABSOLUTE                                                { $$ = "absolute"; }
                | CACHE                                                 { $$ = "cache"; }
                | CASCADE                                               { $$ = "cascade"; }
                | CHAIN                                                 { $$ = "chain"; }
+               | CHECKPOINT                                    { $$ = "checkpoint"; }
                | CLOSE                                                 { $$ = "close"; }
                | COMMENT                                               { $$ = "comment"; }
                | COMMIT                                                { $$ = "commit"; }
index 3562537c0a8e4b383dfc3c4b18788c3b42923d10..d8f32e39d02e6fc4a17375980cfb14902ddecc57 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.81 2000/09/12 05:09:44 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.82 2000/11/05 22:50:20 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -60,6 +60,7 @@ static ScanKeyword ScanKeywords[] = {
        {"character", CHARACTER},
        {"characteristics", CHARACTERISTICS},
        {"check", CHECK},
+       {"checkpoint", CHECKPOINT},
        {"close", CLOSE},
        {"cluster", CLUSTER},
        {"coalesce", COALESCE},
index 62023afa01c0bd6564dbf9062d68e595ea16e03c..c610147fc5f650effe221149163bb5748c584c01 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.21 2000/04/12 17:15:37 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.22 2000/11/05 22:50:20 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -369,3 +369,40 @@ GetSnapshotData(bool serializable)
        snapshot->xcnt = count;
        return snapshot;
 }
+
+/*
+ * GetUndoRecPtr -- returns oldest PROC->logRec.
+ */
+XLogRecPtr     GetUndoRecPtr(void);
+
+XLogRecPtr
+GetUndoRecPtr(void)
+{
+       SISeg      *segP = shmInvalBuffer;
+       ProcState  *stateP = segP->procState;
+       XLogRecPtr      urec = {0, 0};
+       XLogRecPtr      tempr;
+       int                     index;
+
+       SpinAcquire(SInvalLock);
+
+       for (index = 0; index < segP->maxBackends; index++)
+       {
+               SHMEM_OFFSET pOffset = stateP[index].procStruct;
+
+               if (pOffset != INVALID_OFFSET)
+               {
+                       PROC       *proc = (PROC *) MAKE_PTR(pOffset);
+                       tempr = proc->logRec;
+                       if (tempr.xrecoff == 0)
+                               continue;
+                       if (urec.xrecoff != 0 && XLByteLT(urec, tempr))
+                               continue;
+                       urec = tempr;
+               }
+       }
+
+       SpinRelease(SInvalLock);
+
+       return(urec);
+}
index 3c4c40c84ccf96873b12f4317a476881e0dd6a68..dd8bfe017a6100c23054d9c38f14544f40bd7e71 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.98 2000/10/22 23:32:41 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.99 2000/11/05 22:50:21 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,7 +44,7 @@
 #include "utils/acl.h"
 #include "utils/ps_status.h"
 #include "utils/syscache.h"
-
+#include "access/xlog.h"
 
 /*
  * Error-checking support for DROP commands
@@ -818,6 +818,14 @@ ProcessUtility(Node *parsetree,
                        DropGroup((DropGroupStmt *) parsetree);
                        break;
 
+               case T_CheckPointStmt:
+                       {
+                               set_ps_display(commandTag = "CHECKPOINT");
+
+                               CreateCheckPoint(false);
+                       }
+                       break;
+
                case T_ReindexStmt:
                        {
                                ReindexStmt *stmt = (ReindexStmt *) parsetree;
index 02998755c328e889f53a0d8d9057c9cf9637861e..ec7215b6ae96ee2d6ddf8d544e84b666d17d52b6 100644 (file)
@@ -97,4 +97,6 @@ extern XLogRecPtr XLogInsert(RmgrId rmid, uint8 info,
                        char *buf, uint32 buflen);
 extern void XLogFlush(XLogRecPtr RecPtr);
 
+extern void CreateCheckPoint(bool shutdown);
+
 #endif  /* XLOG_H */
index 9a939a73345c2919cf800d2d33b50cd6f247dc50..727db39d8279571a92da22ca227ec63c35849eec 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodes.h,v 1.81 2000/10/31 10:22:12 petere Exp $
+ * $Id: nodes.h,v 1.82 2000/11/05 22:50:21 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -202,6 +202,7 @@ typedef enum NodeTag
        T_DropGroupStmt,
        T_ReindexStmt,
        T_SetSessionStmt,
+       T_CheckPointStmt,
 
        T_A_Expr = 700,
        T_Attr,
index 6ac6d0be4dad013ca1428ef4b527f6c553c9a347..269fa9592be9a32eb22da81bc720017194fa3938 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.118 2000/11/05 00:15:53 tgl Exp $
+ * $Id: parsenodes.h,v 1.119 2000/11/05 22:50:21 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -695,6 +695,11 @@ typedef struct SetSessionStmt
        List       *args;
 } SetSessionStmt;
 
+typedef struct CheckPointStmt
+{
+       NodeTag         type;
+} CheckPointStmt;
+
 /* ----------------------
  * Set Statement
  * ----------------------