From f0e37a85319e6c113ecd3303cddeb6edd5a6ac44 Mon Sep 17 00:00:00 2001 From: "Vadim B. Mikheev" Date: Sun, 5 Nov 2000 22:50:21 +0000 Subject: [PATCH] New CHECKPOINT command. Auto removing of offline log files and creating new file at checkpoint time. --- src/backend/access/transam/xact.c | 10 +- src/backend/access/transam/xlog.c | 207 ++++++++++++++++++++++++++---- src/backend/nodes/copyfuncs.c | 5 +- src/backend/nodes/equalfuncs.c | 5 +- src/backend/parser/gram.y | 20 ++- src/backend/parser/keywords.c | 3 +- src/backend/storage/ipc/sinval.c | 39 +++++- src/backend/tcop/utility.c | 12 +- src/include/access/xlog.h | 2 + src/include/nodes/nodes.h | 3 +- src/include/nodes/parsenodes.h | 7 +- 11 files changed, 274 insertions(+), 39 deletions(-) diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 28d3555d43..cc4209fa51 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -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(); diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 13dba31918..ffd7040a45 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -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 #include #include +#include +#include #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; } diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 406e85ce62..93866787f3 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -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); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 08087136a1..7ed95db967 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -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); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 2fbfa853dd..70245ecd01 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -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 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"; } diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index 3562537c0a..d8f32e39d0 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -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}, diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c index 62023afa01..c610147fc5 100644 --- a/src/backend/storage/ipc/sinval.c +++ b/src/backend/storage/ipc/sinval.c @@ -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); +} diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 3c4c40c84c..dd8bfe017a 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -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; diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index 02998755c3..ec7215b6ae 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -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 */ diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 9a939a7334..727db39d82 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -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, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 6ac6d0be4d..269fa9592b 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -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 * ----------------------