mirror of
https://github.com/postgres/postgres.git
synced 2025-06-29 10:41:53 +03:00
New CHECKPOINT command.
Auto removing of offline log files and creating new file at checkpoint time.
This commit is contained in:
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* Transaction aborts can now occur two ways:
|
* Transaction aborts can now occur two ways:
|
||||||
@ -678,7 +678,7 @@ RecordTransactionCommit()
|
|||||||
leak = BufferPoolCheckLeak();
|
leak = BufferPoolCheckLeak();
|
||||||
|
|
||||||
#ifdef XLOG
|
#ifdef XLOG
|
||||||
if (MyLastRecPtr.xlogid != 0 || MyLastRecPtr.xrecoff != 0)
|
if (MyLastRecPtr.xrecoff != 0)
|
||||||
{
|
{
|
||||||
xl_xact_commit xlrec;
|
xl_xact_commit xlrec;
|
||||||
struct timeval delay;
|
struct timeval delay;
|
||||||
@ -701,7 +701,6 @@ RecordTransactionCommit()
|
|||||||
delay.tv_usec = CommitDelay;
|
delay.tv_usec = CommitDelay;
|
||||||
(void) select(0, NULL, NULL, NULL, &delay);
|
(void) select(0, NULL, NULL, NULL, &delay);
|
||||||
XLogFlush(recptr);
|
XLogFlush(recptr);
|
||||||
MyLastRecPtr.xlogid = 0;
|
|
||||||
MyLastRecPtr.xrecoff = 0;
|
MyLastRecPtr.xrecoff = 0;
|
||||||
|
|
||||||
TransactionIdCommit(xid);
|
TransactionIdCommit(xid);
|
||||||
@ -836,7 +835,7 @@ RecordTransactionAbort(void)
|
|||||||
TransactionIdAbort(xid);
|
TransactionIdAbort(xid);
|
||||||
|
|
||||||
#ifdef XLOG
|
#ifdef XLOG
|
||||||
if (MyLastRecPtr.xlogid != 0 || MyLastRecPtr.xrecoff != 0)
|
if (MyLastRecPtr.xrecoff != 0)
|
||||||
{
|
{
|
||||||
xl_xact_abort xlrec;
|
xl_xact_abort xlrec;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
@ -844,6 +843,8 @@ RecordTransactionAbort(void)
|
|||||||
xlrec.xtime = time(NULL);
|
xlrec.xtime = time(NULL);
|
||||||
recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT,
|
recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT,
|
||||||
(char*) &xlrec, SizeOfXactAbort, NULL, 0);
|
(char*) &xlrec, SizeOfXactAbort, NULL, 0);
|
||||||
|
|
||||||
|
MyProc->logRec.xrecoff = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1189,7 +1190,6 @@ AbortTransaction(void)
|
|||||||
AtEOXact_Files();
|
AtEOXact_Files();
|
||||||
|
|
||||||
/* Here we'll rollback xaction changes */
|
/* Here we'll rollback xaction changes */
|
||||||
MyLastRecPtr.xlogid = 0;
|
|
||||||
MyLastRecPtr.xrecoff = 0;
|
MyLastRecPtr.xrecoff = 0;
|
||||||
|
|
||||||
AtAbort_Locks();
|
AtAbort_Locks();
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 <errno.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
@ -48,7 +50,10 @@ StartUpID ThisStartUpID = 0;
|
|||||||
|
|
||||||
int XLOG_DEBUG = 1;
|
int XLOG_DEBUG = 1;
|
||||||
|
|
||||||
|
/* To read/update control file and create new log file */
|
||||||
SPINLOCK ControlFileLockId;
|
SPINLOCK ControlFileLockId;
|
||||||
|
|
||||||
|
/* To generate new xid */
|
||||||
SPINLOCK XidGenLockId;
|
SPINLOCK XidGenLockId;
|
||||||
|
|
||||||
extern VariableCache ShmemVariableCache;
|
extern VariableCache ShmemVariableCache;
|
||||||
@ -91,19 +96,20 @@ typedef struct XLogCtlWrite
|
|||||||
|
|
||||||
typedef struct XLogCtlData
|
typedef struct XLogCtlData
|
||||||
{
|
{
|
||||||
XLogCtlInsert Insert;
|
XLogCtlInsert Insert;
|
||||||
XLgwrRqst LgwrRqst;
|
XLgwrRqst LgwrRqst;
|
||||||
XLgwrResult LgwrResult;
|
XLgwrResult LgwrResult;
|
||||||
XLogCtlWrite Write;
|
XLogCtlWrite Write;
|
||||||
char *pages;
|
char *pages;
|
||||||
XLogRecPtr *xlblocks; /* 1st byte ptr-s + BLCKSZ */
|
XLogRecPtr *xlblocks; /* 1st byte ptr-s + BLCKSZ */
|
||||||
uint32 XLogCacheByte;
|
uint32 XLogCacheByte;
|
||||||
uint32 XLogCacheBlck;
|
uint32 XLogCacheBlck;
|
||||||
StartUpID ThisStartUpID;
|
StartUpID ThisStartUpID;
|
||||||
#ifdef HAS_TEST_AND_SET
|
#ifdef HAS_TEST_AND_SET
|
||||||
slock_t insert_lck;
|
slock_t insert_lck;
|
||||||
slock_t info_lck;
|
slock_t info_lck;
|
||||||
slock_t lgwr_lck;
|
slock_t lgwr_lck;
|
||||||
|
slock_t chkp_lck; /* checkpoint lock */
|
||||||
#endif
|
#endif
|
||||||
} XLogCtlData;
|
} XLogCtlData;
|
||||||
|
|
||||||
@ -133,6 +139,7 @@ typedef struct ControlFileData
|
|||||||
uint32 blcksz; /* block size for this DB */
|
uint32 blcksz; /* block size for this DB */
|
||||||
uint32 relseg_size; /* blocks per segment of large relation */
|
uint32 relseg_size; /* blocks per segment of large relation */
|
||||||
uint32 catalog_version_no; /* internal version number */
|
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
|
* 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", \
|
snprintf(path, MAXPGPATH, "%s%c%08X%08X", \
|
||||||
XLogDir, SEP_CHAR, log, seg)
|
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) \
|
#define PrevBufIdx(curridx) \
|
||||||
((curridx == 0) ? XLogCtl->XLogCacheBlck : (curridx - 1))
|
((curridx == 0) ? XLogCtl->XLogCacheBlck : (curridx - 1))
|
||||||
|
|
||||||
@ -198,7 +209,7 @@ typedef struct CheckPoint
|
|||||||
|
|
||||||
static void GetFreeXLBuffer(void);
|
static void GetFreeXLBuffer(void);
|
||||||
static void XLogWrite(char *buffer);
|
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 int XLogFileOpen(uint32 log, uint32 seg, bool econt);
|
||||||
static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, char *buffer);
|
static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, char *buffer);
|
||||||
static char *str_time(time_t tnow);
|
static char *str_time(time_t tnow);
|
||||||
@ -672,6 +683,7 @@ XLogWrite(char *buffer)
|
|||||||
char *from;
|
char *from;
|
||||||
uint32 wcnt = 0;
|
uint32 wcnt = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
bool usexistent;
|
||||||
|
|
||||||
for (; XLByteLT(LgwrResult.Write, LgwrRqst.Write);)
|
for (; XLByteLT(LgwrResult.Write, LgwrRqst.Write);)
|
||||||
{
|
{
|
||||||
@ -710,13 +722,18 @@ XLogWrite(char *buffer)
|
|||||||
logId = LgwrResult.Write.xlogid;
|
logId = LgwrResult.Write.xlogid;
|
||||||
logSeg = (LgwrResult.Write.xrecoff - 1) / XLogSegSize;
|
logSeg = (LgwrResult.Write.xrecoff - 1) / XLogSegSize;
|
||||||
logOff = 0;
|
logOff = 0;
|
||||||
logFile = XLogFileInit(logId, logSeg);
|
|
||||||
SpinAcquire(ControlFileLockId);
|
SpinAcquire(ControlFileLockId);
|
||||||
|
/* create/use new log file */
|
||||||
|
usexistent = true;
|
||||||
|
logFile = XLogFileInit(logId, logSeg, &usexistent);
|
||||||
ControlFile->logId = logId;
|
ControlFile->logId = logId;
|
||||||
ControlFile->logSeg = logSeg + 1;
|
ControlFile->logSeg = logSeg + 1;
|
||||||
ControlFile->time = time(NULL);
|
ControlFile->time = time(NULL);
|
||||||
UpdateControlFile();
|
UpdateControlFile();
|
||||||
SpinRelease(ControlFileLockId);
|
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)
|
if (logFile < 0)
|
||||||
@ -780,17 +797,39 @@ XLogWrite(char *buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
XLogFileInit(uint32 log, uint32 seg)
|
XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
|
||||||
{
|
{
|
||||||
char path[MAXPGPATH];
|
char path[MAXPGPATH];
|
||||||
|
char tpath[MAXPGPATH];
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
XLogFileName(path, log, seg);
|
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);
|
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)
|
if (fd < 0)
|
||||||
elog(STOP, "Init(logfile %u seg %u) failed: %d",
|
elog(STOP, "InitCreate(logfile %u seg %u) failed: %d",
|
||||||
logId, logSeg, errno);
|
logId, logSeg, errno);
|
||||||
|
|
||||||
if (lseek(fd, XLogSegSize - 1, SEEK_SET) != (off_t) (XLogSegSize - 1))
|
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",
|
elog(STOP, "Lseek(logfile %u seg %u off %u) failed: %d",
|
||||||
log, seg, 0, errno);
|
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);
|
return (fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -837,6 +885,49 @@ XLogFileOpen(uint32 log, uint32 seg, bool econt)
|
|||||||
return (fd);
|
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 *
|
static XLogRecord *
|
||||||
ReadRecord(XLogRecPtr *RecPtr, char *buffer)
|
ReadRecord(XLogRecPtr *RecPtr, char *buffer)
|
||||||
{
|
{
|
||||||
@ -1183,6 +1274,7 @@ BootStrapXLOG()
|
|||||||
int fd;
|
int fd;
|
||||||
char buffer[BLCKSZ];
|
char buffer[BLCKSZ];
|
||||||
CheckPoint checkPoint;
|
CheckPoint checkPoint;
|
||||||
|
bool usexistent = false;
|
||||||
|
|
||||||
#ifdef XLOG
|
#ifdef XLOG
|
||||||
XLogPageHeader page = (XLogPageHeader) buffer;
|
XLogPageHeader page = (XLogPageHeader) buffer;
|
||||||
@ -1217,7 +1309,7 @@ BootStrapXLOG()
|
|||||||
record->xl_rmid = RM_XLOG_ID;
|
record->xl_rmid = RM_XLOG_ID;
|
||||||
memcpy((char *) record + SizeOfXLogRecord, &checkPoint, sizeof(checkPoint));
|
memcpy((char *) record + SizeOfXLogRecord, &checkPoint, sizeof(checkPoint));
|
||||||
|
|
||||||
logFile = XLogFileInit(0, 0);
|
logFile = XLogFileInit(0, 0, &usexistent);
|
||||||
|
|
||||||
if (write(logFile, buffer, BLCKSZ) != BLCKSZ)
|
if (write(logFile, buffer, BLCKSZ) != BLCKSZ)
|
||||||
elog(STOP, "BootStrapXLOG failed to write logfile: %d", errno);
|
elog(STOP, "BootStrapXLOG failed to write logfile: %d", errno);
|
||||||
@ -1297,6 +1389,7 @@ StartupXLOG()
|
|||||||
S_INIT_LOCK(&(XLogCtl->insert_lck));
|
S_INIT_LOCK(&(XLogCtl->insert_lck));
|
||||||
S_INIT_LOCK(&(XLogCtl->info_lck));
|
S_INIT_LOCK(&(XLogCtl->info_lck));
|
||||||
S_INIT_LOCK(&(XLogCtl->lgwr_lck));
|
S_INIT_LOCK(&(XLogCtl->lgwr_lck));
|
||||||
|
S_INIT_LOCK(&(XLogCtl->chkp_lck));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open/read Control file
|
* Open/read Control file
|
||||||
@ -1556,6 +1649,8 @@ ShutdownXLOG()
|
|||||||
elog(LOG, "Data Base System shut down at %s", str_time(time(NULL)));
|
elog(LOG, "Data Base System shut down at %s", str_time(time(NULL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern XLogRecPtr GetUndoRecPtr(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
CreateCheckPoint(bool shutdown)
|
CreateCheckPoint(bool shutdown)
|
||||||
{
|
{
|
||||||
@ -1565,6 +1660,21 @@ CreateCheckPoint(bool shutdown)
|
|||||||
XLogCtlInsert *Insert = &XLogCtl->Insert;
|
XLogCtlInsert *Insert = &XLogCtl->Insert;
|
||||||
uint32 freespace;
|
uint32 freespace;
|
||||||
uint16 curridx;
|
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));
|
memset(&checkPoint, 0, sizeof(checkPoint));
|
||||||
if (shutdown)
|
if (shutdown)
|
||||||
@ -1579,7 +1689,7 @@ CreateCheckPoint(bool shutdown)
|
|||||||
/* Get REDO record ptr */
|
/* Get REDO record ptr */
|
||||||
while (TAS(&(XLogCtl->insert_lck)))
|
while (TAS(&(XLogCtl->insert_lck)))
|
||||||
{
|
{
|
||||||
struct timeval delay = {0, 5000};
|
struct timeval delay = {1, 0};
|
||||||
|
|
||||||
if (shutdown)
|
if (shutdown)
|
||||||
elog(STOP, "XLog insert lock is busy while data base is shutting down");
|
elog(STOP, "XLog insert lock is busy while data base is shutting down");
|
||||||
@ -1615,7 +1725,7 @@ CreateCheckPoint(bool shutdown)
|
|||||||
FlushBufferPool();
|
FlushBufferPool();
|
||||||
|
|
||||||
/* Get UNDO record ptr - should use oldest of PROC->logRec */
|
/* Get UNDO record ptr - should use oldest of PROC->logRec */
|
||||||
checkPoint.undo.xrecoff = 0;
|
checkPoint.undo = GetUndoRecPtr();
|
||||||
|
|
||||||
if (shutdown && checkPoint.undo.xrecoff != 0)
|
if (shutdown && checkPoint.undo.xrecoff != 0)
|
||||||
elog(STOP, "Active transaction while data base is shutting down");
|
elog(STOP, "Active transaction while data base is shutting down");
|
||||||
@ -1633,9 +1743,35 @@ CreateCheckPoint(bool shutdown)
|
|||||||
SpinAcquire(ControlFileLockId);
|
SpinAcquire(ControlFileLockId);
|
||||||
if (shutdown)
|
if (shutdown)
|
||||||
ControlFile->state = DB_SHUTDOWNED;
|
ControlFile->state = DB_SHUTDOWNED;
|
||||||
|
|
||||||
#ifdef XLOG
|
#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;
|
ControlFile->checkPoint = MyLastRecPtr;
|
||||||
|
|
||||||
|
_logId = ControlFile->logId;
|
||||||
|
_logSeg = ControlFile->logSeg - 1;
|
||||||
|
strcpy(archdir, ControlFile->archdir);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
ControlFile->checkPoint.xlogid = 0;
|
ControlFile->checkPoint.xlogid = 0;
|
||||||
ControlFile->checkPoint.xrecoff = SizeOfXLogPHD;
|
ControlFile->checkPoint.xrecoff = SizeOfXLogPHD;
|
||||||
@ -1645,6 +1781,33 @@ CreateCheckPoint(bool shutdown)
|
|||||||
UpdateControlFile();
|
UpdateControlFile();
|
||||||
SpinRelease(ControlFileLockId);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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:
|
case T_SetSessionStmt:
|
||||||
retval = _copySetSessionStmt(from);
|
retval = _copySetSessionStmt(from);
|
||||||
break;
|
break;
|
||||||
|
case T_CheckPointStmt:
|
||||||
|
retval = (void*)makeNode(CheckPointStmt);
|
||||||
|
break;
|
||||||
|
|
||||||
case T_A_Expr:
|
case T_A_Expr:
|
||||||
retval = _copyAExpr(from);
|
retval = _copyAExpr(from);
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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:
|
case T_SetSessionStmt:
|
||||||
retval = _equalSetSessionStmt(a, b);
|
retval = _equalSetSessionStmt(a, b);
|
||||||
break;
|
break;
|
||||||
|
case T_CheckPointStmt:
|
||||||
|
retval = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case T_A_Expr:
|
case T_A_Expr:
|
||||||
retval = _equalAExpr(a, b);
|
retval = _equalAExpr(a, b);
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -136,7 +136,7 @@ static void doNegateFloat(Value *v);
|
|||||||
RenameStmt, RevokeStmt, RuleActionStmt, RuleActionStmtOrEmpty,
|
RenameStmt, RevokeStmt, RuleActionStmt, RuleActionStmtOrEmpty,
|
||||||
RuleStmt, SelectStmt, SetSessionStmt, TransactionStmt, TruncateStmt,
|
RuleStmt, SelectStmt, SetSessionStmt, TransactionStmt, TruncateStmt,
|
||||||
UnlistenStmt, UpdateStmt, VacuumStmt, VariableResetStmt,
|
UnlistenStmt, UpdateStmt, VacuumStmt, VariableResetStmt,
|
||||||
VariableSetStmt, VariableShowStmt, ViewStmt
|
VariableSetStmt, VariableShowStmt, ViewStmt, CheckPointStmt
|
||||||
|
|
||||||
%type <node> select_no_parens, select_clause, simple_select
|
%type <node> select_no_parens, select_clause, simple_select
|
||||||
|
|
||||||
@ -336,7 +336,7 @@ static void doNegateFloat(Value *v);
|
|||||||
*/
|
*/
|
||||||
%token ABORT_TRANS, ACCESS, AFTER, AGGREGATE, ANALYZE,
|
%token ABORT_TRANS, ACCESS, AFTER, AGGREGATE, ANALYZE,
|
||||||
BACKWARD, BEFORE, BINARY, BIT,
|
BACKWARD, BEFORE, BINARY, BIT,
|
||||||
CACHE, CLUSTER, COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE,
|
CACHE, CHECKPOINT, CLUSTER, COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE,
|
||||||
DATABASE, DELIMITERS, DO,
|
DATABASE, DELIMITERS, DO,
|
||||||
EACH, ENCODING, EXCLUSIVE, EXPLAIN, EXTEND,
|
EACH, ENCODING, EXCLUSIVE, EXPLAIN, EXTEND,
|
||||||
FORCE, FORWARD, FUNCTION, HANDLER,
|
FORCE, FORWARD, FUNCTION, HANDLER,
|
||||||
@ -470,6 +470,7 @@ stmt : AlterSchemaStmt
|
|||||||
| VariableShowStmt
|
| VariableShowStmt
|
||||||
| VariableResetStmt
|
| VariableResetStmt
|
||||||
| ConstraintsSetStmt
|
| ConstraintsSetStmt
|
||||||
|
| CheckPointStmt
|
||||||
| /*EMPTY*/
|
| /*EMPTY*/
|
||||||
{ $$ = (Node *)NULL; }
|
{ $$ = (Node *)NULL; }
|
||||||
;
|
;
|
||||||
@ -957,6 +958,16 @@ constraints_set_mode: DEFERRED
|
|||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checkpoint statement
|
||||||
|
*/
|
||||||
|
CheckPointStmt: CHECKPOINT
|
||||||
|
{
|
||||||
|
CheckPointStmt *n = makeNode(CheckPointStmt);
|
||||||
|
$$ = (Node *)n;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* ALTER TABLE variations
|
* ALTER TABLE variations
|
||||||
@ -5389,6 +5400,7 @@ TokenId: ABSOLUTE { $$ = "absolute"; }
|
|||||||
| CACHE { $$ = "cache"; }
|
| CACHE { $$ = "cache"; }
|
||||||
| CASCADE { $$ = "cascade"; }
|
| CASCADE { $$ = "cascade"; }
|
||||||
| CHAIN { $$ = "chain"; }
|
| CHAIN { $$ = "chain"; }
|
||||||
|
| CHECKPOINT { $$ = "checkpoint"; }
|
||||||
| CLOSE { $$ = "close"; }
|
| CLOSE { $$ = "close"; }
|
||||||
| COMMENT { $$ = "comment"; }
|
| COMMENT { $$ = "comment"; }
|
||||||
| COMMIT { $$ = "commit"; }
|
| COMMIT { $$ = "commit"; }
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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},
|
{"character", CHARACTER},
|
||||||
{"characteristics", CHARACTERISTICS},
|
{"characteristics", CHARACTERISTICS},
|
||||||
{"check", CHECK},
|
{"check", CHECK},
|
||||||
|
{"checkpoint", CHECKPOINT},
|
||||||
{"close", CLOSE},
|
{"close", CLOSE},
|
||||||
{"cluster", CLUSTER},
|
{"cluster", CLUSTER},
|
||||||
{"coalesce", COALESCE},
|
{"coalesce", COALESCE},
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
snapshot->xcnt = count;
|
||||||
return snapshot;
|
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);
|
||||||
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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/acl.h"
|
||||||
#include "utils/ps_status.h"
|
#include "utils/ps_status.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
#include "access/xlog.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Error-checking support for DROP commands
|
* Error-checking support for DROP commands
|
||||||
@ -818,6 +818,14 @@ ProcessUtility(Node *parsetree,
|
|||||||
DropGroup((DropGroupStmt *) parsetree);
|
DropGroup((DropGroupStmt *) parsetree);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_CheckPointStmt:
|
||||||
|
{
|
||||||
|
set_ps_display(commandTag = "CHECKPOINT");
|
||||||
|
|
||||||
|
CreateCheckPoint(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case T_ReindexStmt:
|
case T_ReindexStmt:
|
||||||
{
|
{
|
||||||
ReindexStmt *stmt = (ReindexStmt *) parsetree;
|
ReindexStmt *stmt = (ReindexStmt *) parsetree;
|
||||||
|
@ -97,4 +97,6 @@ extern XLogRecPtr XLogInsert(RmgrId rmid, uint8 info,
|
|||||||
char *buf, uint32 buflen);
|
char *buf, uint32 buflen);
|
||||||
extern void XLogFlush(XLogRecPtr RecPtr);
|
extern void XLogFlush(XLogRecPtr RecPtr);
|
||||||
|
|
||||||
|
extern void CreateCheckPoint(bool shutdown);
|
||||||
|
|
||||||
#endif /* XLOG_H */
|
#endif /* XLOG_H */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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_DropGroupStmt,
|
||||||
T_ReindexStmt,
|
T_ReindexStmt,
|
||||||
T_SetSessionStmt,
|
T_SetSessionStmt,
|
||||||
|
T_CheckPointStmt,
|
||||||
|
|
||||||
T_A_Expr = 700,
|
T_A_Expr = 700,
|
||||||
T_Attr,
|
T_Attr,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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;
|
List *args;
|
||||||
} SetSessionStmt;
|
} SetSessionStmt;
|
||||||
|
|
||||||
|
typedef struct CheckPointStmt
|
||||||
|
{
|
||||||
|
NodeTag type;
|
||||||
|
} CheckPointStmt;
|
||||||
|
|
||||||
/* ----------------------
|
/* ----------------------
|
||||||
* Set Statement
|
* Set Statement
|
||||||
* ----------------------
|
* ----------------------
|
||||||
|
Reference in New Issue
Block a user