⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xlog.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
/*------------------------------------------------------------------------- * * xlog.c *		PostgreSQL transaction log manager * * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.292.2.4 2008/05/13 20:54:02 mha Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <ctype.h>#include <fcntl.h>#include <signal.h>#include <time.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/wait.h>#include <unistd.h>#include "access/clog.h"#include "access/heapam.h"#include "access/multixact.h"#include "access/subtrans.h"#include "access/transam.h"#include "access/tuptoaster.h"#include "access/twophase.h"#include "access/xact.h"#include "access/xlog_internal.h"#include "access/xlogdefs.h"#include "access/xlogutils.h"#include "catalog/catversion.h"#include "catalog/pg_control.h"#include "catalog/pg_type.h"#include "funcapi.h"#include "miscadmin.h"#include "pgstat.h"#include "postmaster/bgwriter.h"#include "storage/bufpage.h"#include "storage/fd.h"#include "storage/ipc.h"#include "storage/pmsignal.h"#include "storage/procarray.h"#include "storage/smgr.h"#include "storage/spin.h"#include "utils/builtins.h"#include "utils/pg_locale.h"#include "utils/ps_status.h"/* File path names (all relative to $PGDATA) */#define BACKUP_LABEL_FILE		"backup_label"#define BACKUP_LABEL_OLD		"backup_label.old"#define RECOVERY_COMMAND_FILE	"recovery.conf"#define RECOVERY_COMMAND_DONE	"recovery.done"/* User-settable parameters */int			CheckPointSegments = 3;int			XLOGbuffers = 8;int			XLogArchiveTimeout = 0;bool		XLogArchiveMode = false;char	   *XLogArchiveCommand = NULL;char	   *XLOG_sync_method = NULL;const char	XLOG_sync_method_default[] = DEFAULT_SYNC_METHOD_STR;bool		fullPageWrites = true;bool		log_checkpoints = false;#ifdef WAL_DEBUGbool		XLOG_DEBUG = false;#endif/* * XLOGfileslop is the maximum number of preallocated future XLOG segments. * When we are done with an old XLOG segment file, we will recycle it as a * future XLOG segment as long as there aren't already XLOGfileslop future * segments; else we'll delete it.  This could be made a separate GUC * variable, but at present I think it's sufficient to hardwire it as * 2*CheckPointSegments+1.	Under normal conditions, a checkpoint will free * no more than 2*CheckPointSegments log segments, and we want to recycle all * of them; the +1 allows boundary cases to happen without wasting a * delete/create-segment cycle. */#define XLOGfileslop	(2*CheckPointSegments + 1)/* these are derived from XLOG_sync_method by assign_xlog_sync_method */int			sync_method = DEFAULT_SYNC_METHOD;static int	open_sync_bit = DEFAULT_SYNC_FLAGBIT;#define XLOG_SYNC_BIT  (enableFsync ? open_sync_bit : 0)/* * Statistics for current checkpoint are collected in this global struct. * Because only the background writer or a stand-alone backend can perform * checkpoints, this will be unused in normal backends. */CheckpointStatsData CheckpointStats;/* * ThisTimeLineID will be same in all backends --- it identifies current * WAL timeline for the database system. */TimeLineID	ThisTimeLineID = 0;/* Are we doing recovery from XLOG? */bool		InRecovery = false;/* Are we recovering using offline XLOG archives? */static bool InArchiveRecovery = false;/* Was the last xlog file restored from archive, or local? */static bool restoredFromArchive = false;/* options taken from recovery.conf */static char *recoveryRestoreCommand = NULL;static bool recoveryTarget = false;static bool recoveryTargetExact = false;static bool recoveryTargetInclusive = true;static bool recoveryLogRestartpoints = false;static TransactionId recoveryTargetXid;static TimestampTz recoveryTargetTime;static TimestampTz recoveryLastXTime = 0;/* if recoveryStopsHere returns true, it saves actual stop xid/time here */static TransactionId recoveryStopXid;static TimestampTz recoveryStopTime;static bool recoveryStopAfter;/* * During normal operation, the only timeline we care about is ThisTimeLineID. * During recovery, however, things are more complicated.  To simplify life * for rmgr code, we keep ThisTimeLineID set to the "current" timeline as we * scan through the WAL history (that is, it is the line that was active when * the currently-scanned WAL record was generated).  We also need these * timeline values: * * recoveryTargetTLI: the desired timeline that we want to end in. * * expectedTLIs: an integer list of recoveryTargetTLI and the TLIs of * its known parents, newest first (so recoveryTargetTLI is always the * first list member).	Only these TLIs are expected to be seen in the WAL * segments we read, and indeed only these TLIs will be considered as * candidate WAL files to open at all. * * curFileTLI: the TLI appearing in the name of the current input WAL file. * (This is not necessarily the same as ThisTimeLineID, because we could * be scanning data that was copied from an ancestor timeline when the current * file was created.)  During a sequential scan we do not allow this value * to decrease. */static TimeLineID recoveryTargetTLI;static List *expectedTLIs;static TimeLineID curFileTLI;/* * ProcLastRecPtr points to the start of the last XLOG record inserted by the * current backend.  It is updated for all inserts.  XactLastRecEnd points to * end+1 of the last record, and is reset when we end a top-level transaction, * or start a new one; so it can be used to tell if the current transaction has * created any XLOG records. */static XLogRecPtr ProcLastRecPtr = {0, 0};XLogRecPtr	XactLastRecEnd = {0, 0};/* * RedoRecPtr is this backend's local copy of the REDO record pointer * (which is almost but not quite the same as a pointer to the most recent * CHECKPOINT record).	We update this from the shared-memory copy, * XLogCtl->Insert.RedoRecPtr, whenever we can safely do so (ie, when we * hold the Insert lock).  See XLogInsert for details.	We are also allowed * to update from XLogCtl->Insert.RedoRecPtr if we hold the info_lck; * see GetRedoRecPtr.  A freshly spawned backend obtains the value during * InitXLOGAccess. */static XLogRecPtr RedoRecPtr;/*---------- * Shared-memory data structures for XLOG control * * LogwrtRqst indicates a byte position that we need to write and/or fsync * the log up to (all records before that point must be written or fsynced). * LogwrtResult indicates the byte positions we have already written/fsynced. * These structs are identical but are declared separately to indicate their * slightly different functions. * * We do a lot of pushups to minimize the amount of access to lockable * shared memory values.  There are actually three shared-memory copies of * LogwrtResult, plus one unshared copy in each backend.  Here's how it works: *		XLogCtl->LogwrtResult is protected by info_lck *		XLogCtl->Write.LogwrtResult is protected by WALWriteLock *		XLogCtl->Insert.LogwrtResult is protected by WALInsertLock * One must hold the associated lock to read or write any of these, but * of course no lock is needed to read/write the unshared LogwrtResult. * * XLogCtl->LogwrtResult and XLogCtl->Write.LogwrtResult are both "always * right", since both are updated by a write or flush operation before * it releases WALWriteLock.  The point of keeping XLogCtl->Write.LogwrtResult * is that it can be examined/modified by code that already holds WALWriteLock * without needing to grab info_lck as well. * * XLogCtl->Insert.LogwrtResult may lag behind the reality of the other two, * but is updated when convenient.	Again, it exists for the convenience of * code that is already holding WALInsertLock but not the other locks. * * The unshared LogwrtResult may lag behind any or all of these, and again * is updated when convenient. * * The request bookkeeping is simpler: there is a shared XLogCtl->LogwrtRqst * (protected by info_lck), but we don't need to cache any copies of it. * * Note that this all works because the request and result positions can only * advance forward, never back up, and so we can easily determine which of two * values is "more up to date". * * info_lck is only held long enough to read/update the protected variables, * so it's a plain spinlock.  The other locks are held longer (potentially * over I/O operations), so we use LWLocks for them.  These locks are: * * WALInsertLock: must be held to insert a record into the WAL buffers. * * WALWriteLock: must be held to write WAL buffers to disk (XLogWrite or * XLogFlush). * * ControlFileLock: must be held to read/update control file or create * new log file. * * CheckpointLock: must be held to do a checkpoint (ensures only one * checkpointer at a time; currently, with all checkpoints done by the * bgwriter, this is just pro forma). * *---------- */typedef struct XLogwrtRqst{	XLogRecPtr	Write;			/* last byte + 1 to write out */	XLogRecPtr	Flush;			/* last byte + 1 to flush */} XLogwrtRqst;typedef struct XLogwrtResult{	XLogRecPtr	Write;			/* last byte + 1 written out */	XLogRecPtr	Flush;			/* last byte + 1 flushed */} XLogwrtResult;/* * Shared state data for XLogInsert. */typedef struct XLogCtlInsert{	XLogwrtResult LogwrtResult; /* a recent value of LogwrtResult */	XLogRecPtr	PrevRecord;		/* start of previously-inserted record */	int			curridx;		/* current block index in cache */	XLogPageHeader currpage;	/* points to header of block in cache */	char	   *currpos;		/* current insertion point in cache */	XLogRecPtr	RedoRecPtr;		/* current redo point for insertions */	bool		forcePageWrites;	/* forcing full-page writes for PITR? */} XLogCtlInsert;/* * Shared state data for XLogWrite/XLogFlush. */typedef struct XLogCtlWrite{	XLogwrtResult LogwrtResult; /* current value of LogwrtResult */	int			curridx;		/* cache index of next block to write */	time_t		lastSegSwitchTime;		/* time of last xlog segment switch */} XLogCtlWrite;/* * Total shared-memory state for XLOG. */typedef struct XLogCtlData{	/* Protected by WALInsertLock: */	XLogCtlInsert Insert;	/* Protected by info_lck: */	XLogwrtRqst LogwrtRqst;	XLogwrtResult LogwrtResult;	uint32		ckptXidEpoch;	/* nextXID & epoch of latest checkpoint */	TransactionId ckptXid;	XLogRecPtr	asyncCommitLSN; /* LSN of newest async commit */	/* Protected by WALWriteLock: */	XLogCtlWrite Write;	/*	 * These values do not change after startup, although the pointed-to pages	 * and xlblocks values certainly do.  Permission to read/write the pages	 * and xlblocks values depends on WALInsertLock and WALWriteLock.	 */	char	   *pages;			/* buffers for unwritten XLOG pages */	XLogRecPtr *xlblocks;		/* 1st byte ptr-s + XLOG_BLCKSZ */	Size		XLogCacheByte;	/* # bytes in xlog buffers */	int			XLogCacheBlck;	/* highest allocated xlog buffer index */	TimeLineID	ThisTimeLineID;	slock_t		info_lck;		/* locks shared variables shown above */} XLogCtlData;static XLogCtlData *XLogCtl = NULL;/* * We maintain an image of pg_control in shared memory. */static ControlFileData *ControlFile = NULL;/* * Macros for managing XLogInsert state.  In most cases, the calling routine * has local copies of XLogCtl->Insert and/or XLogCtl->Insert->curridx, * so these are passed as parameters instead of being fetched via XLogCtl. *//* Free space remaining in the current xlog page buffer */#define INSERT_FREESPACE(Insert)  \	(XLOG_BLCKSZ - ((Insert)->currpos - (char *) (Insert)->currpage))/* Construct XLogRecPtr value for current insertion point */#define INSERT_RECPTR(recptr,Insert,curridx)  \	( \	  (recptr).xlogid = XLogCtl->xlblocks[curridx].xlogid, \	  (recptr).xrecoff = \		XLogCtl->xlblocks[curridx].xrecoff - INSERT_FREESPACE(Insert) \	)#define PrevBufIdx(idx)		\		(((idx) == 0) ? XLogCtl->XLogCacheBlck : ((idx) - 1))#define NextBufIdx(idx)		\		(((idx) == XLogCtl->XLogCacheBlck) ? 0 : ((idx) + 1))/* * Private, possibly out-of-date copy of shared LogwrtResult. * See discussion above. */static XLogwrtResult LogwrtResult = {{0, 0}, {0, 0}};/* * openLogFile is -1 or a kernel FD for an open log file segment. * When it's open, openLogOff is the current seek offset in the file. * openLogId/openLogSeg identify the segment.  These variables are only * used to write the XLOG, and so will normally refer to the active segment. */static int	openLogFile = -1;static uint32 openLogId = 0;static uint32 openLogSeg = 0;static uint32 openLogOff = 0;/* * These variables are used similarly to the ones above, but for reading * the XLOG.  Note, however, that readOff generally represents the offset * of the page just read, not the seek position of the FD itself, which * will be just past that page. */static int	readFile = -1;static uint32 readId = 0;static uint32 readSeg = 0;static uint32 readOff = 0;/* Buffer for currently read page (XLOG_BLCKSZ bytes) */static char *readBuf = NULL;/* Buffer for current ReadRecord result (expandable) */static char *readRecordBuf = NULL;static uint32 readRecordBufSize = 0;/* State information for XLOG reading */static XLogRecPtr ReadRecPtr;	/* start of last record read */static XLogRecPtr EndRecPtr;	/* end+1 of last record read */static XLogRecord *nextRecord = NULL;static TimeLineID lastPageTLI = 0;static bool InRedo = false;static void XLogArchiveNotify(const char *xlog);static void XLogArchiveNotifySeg(uint32 log, uint32 seg);static bool XLogArchiveCheckDone(const char *xlog);static void XLogArchiveCleanup(const char *xlog);static void readRecoveryCommandFile(void);static void exitArchiveRecovery(TimeLineID endTLI,					uint32 endLogId, uint32 endLogSeg);static bool recoveryStopsHere(XLogRecord *record, bool *includeThis);static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags);static bool XLogCheckBuffer(XLogRecData *rdata, bool doPageWrites,				XLogRecPtr *lsn, BkpBlock *bkpb);static bool AdvanceXLInsertBuffer(bool new_segment);static void XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch);static int XLogFileInit(uint32 log, uint32 seg,			 bool *use_existent, bool use_lock);static bool InstallXLogFileSegment(uint32 *log, uint32 *seg, char *tmppath,					   bool find_free, int *max_advance,					   bool use_lock);static int	XLogFileOpen(uint32 log, uint32 seg);static int	XLogFileRead(uint32 log, uint32 seg, int emode);static void XLogFileClose(void);static bool RestoreArchivedFile(char *path, const char *xlogfname,					const char *recovername, off_t expectedSize);static void PreallocXlogFiles(XLogRecPtr endptr);static void RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr);static void CleanupBackupHistory(void);static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode);static bool ValidXLOGHeader(XLogPageHeader hdr, int emode);static XLogRecord *ReadCheckpointRecord(XLogRecPtr RecPtr, int whichChkpt);static List *readTimeLineHistory(TimeLineID targetTLI);static bool existsTimeLineHistory(TimeLineID probeTLI);static TimeLineID findNewestTimeLine(TimeLineID startTLI);static void writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,					 TimeLineID endTLI,					 uint32 endLogId, uint32 endLogSeg);static void WriteControlFile(void);static void ReadControlFile(void);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -