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

📄 bgwriter.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * bgwriter.c * * The background writer (bgwriter) is new in Postgres 8.0.  It attempts * to keep regular backends from having to write out dirty shared buffers * (which they would only do when needing to free a shared buffer to read in * another page).  In the best scenario all writes from shared buffers will * be issued by the background writer process.	However, regular backends are * still empowered to issue writes if the bgwriter fails to maintain enough * clean shared buffers. * * The bgwriter is also charged with handling all checkpoints.	It will * automatically dispatch a checkpoint after a certain amount of time has * elapsed since the last one, and it can be signaled to perform requested * checkpoints as well.  (The GUC parameter that mandates a checkpoint every * so many WAL segments is implemented by having backends signal the bgwriter * when they fill WAL segments; the bgwriter itself doesn't watch for the * condition.) * * The bgwriter is started by the postmaster as soon as the startup subprocess * finishes.  It remains alive until the postmaster commands it to terminate. * Normal termination is by SIGUSR2, which instructs the bgwriter to execute * a shutdown checkpoint and then exit(0).	(All backends must be stopped * before SIGUSR2 is issued!)  Emergency termination is by SIGQUIT; like any * backend, the bgwriter will simply abort and exit on SIGQUIT. * * If the bgwriter exits unexpectedly, the postmaster treats that the same * as a backend crash: shared memory may be corrupted, so remaining backends * should be killed by SIGQUIT and then a recovery cycle started.  (Even if * shared memory isn't corrupted, we have lost information about which * files need to be fsync'd for the next checkpoint, and so a system * restart needs to be forced.) * * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.21.2.1 2005/12/08 19:19:31 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <signal.h>#include <time.h>#include "access/xlog.h"#include "libpq/pqsignal.h"#include "miscadmin.h"#include "postmaster/bgwriter.h"#include "storage/bufmgr.h"#include "storage/fd.h"#include "storage/freespace.h"#include "storage/ipc.h"#include "storage/pmsignal.h"#include "storage/smgr.h"#include "tcop/tcopprot.h"#include "utils/guc.h"#include "utils/memutils.h"#include "utils/resowner.h"/*---------- * Shared memory area for communication between bgwriter and backends * * The ckpt counters allow backends to watch for completion of a checkpoint * request they send.  Here's how it works: *	* At start of a checkpoint, bgwriter increments ckpt_started. *	* On completion of a checkpoint, bgwriter sets ckpt_done to *	  equal ckpt_started. *	* On failure of a checkpoint, bgwrite first increments ckpt_failed, *	  then sets ckpt_done to equal ckpt_started. * All three fields are declared sig_atomic_t to ensure they can be read * and written without explicit locking.  The algorithm for backends is: *	1. Record current values of ckpt_failed and ckpt_started (in that *	   order!). *	2. Send signal to request checkpoint. *	3. Sleep until ckpt_started changes.  Now you know a checkpoint has *	   begun since you started this algorithm (although *not* that it was *	   specifically initiated by your signal). *	4. Record new value of ckpt_started. *	5. Sleep until ckpt_done >= saved value of ckpt_started.  (Use modulo *	   arithmetic here in case counters wrap around.)  Now you know a *	   checkpoint has started and completed, but not whether it was *	   successful. *	6. If ckpt_failed is different from the originally saved value, *	   assume request failed; otherwise it was definitely successful. * * An additional field is ckpt_time_warn; this is also sig_atomic_t for * simplicity, but is only used as a boolean.  If a backend is requesting * a checkpoint for which a checkpoints-too-close-together warning is * reasonable, it should set this field TRUE just before sending the signal. * * The requests array holds fsync requests sent by backends and not yet * absorbed by the bgwriter.  Unlike the checkpoint fields, the requests * fields are protected by BgWriterCommLock. *---------- */typedef struct{	RelFileNode rnode;	BlockNumber segno;	/* might add a request-type field later */} BgWriterRequest;typedef struct{	pid_t		bgwriter_pid;	/* PID of bgwriter (0 if not started) */	sig_atomic_t ckpt_started;	/* advances when checkpoint starts */	sig_atomic_t ckpt_done;		/* advances when checkpoint done */	sig_atomic_t ckpt_failed;	/* advances when checkpoint fails */	sig_atomic_t ckpt_time_warn;	/* warn if too soon since last ckpt? */	int			num_requests;	/* current # of requests */	int			max_requests;	/* allocated array size */	BgWriterRequest requests[1];	/* VARIABLE LENGTH ARRAY */} BgWriterShmemStruct;static BgWriterShmemStruct *BgWriterShmem;/* * GUC parameters */int			BgWriterDelay = 200;int			CheckPointTimeout = 300;int			CheckPointWarning = 30;/* * Flags set by interrupt handlers for later service in the main loop. */static volatile sig_atomic_t got_SIGHUP = false;static volatile sig_atomic_t checkpoint_requested = false;static volatile sig_atomic_t shutdown_requested = false;/* * Private state */static bool am_bg_writer = false;static bool ckpt_active = false;static time_t last_checkpoint_time;static void bg_quickdie(SIGNAL_ARGS);static void BgSigHupHandler(SIGNAL_ARGS);static void ReqCheckpointHandler(SIGNAL_ARGS);static void ReqShutdownHandler(SIGNAL_ARGS);/* * Main entry point for bgwriter process * * This is invoked from BootstrapMain, which has already created the basic * execution environment, but not enabled signals yet. */voidBackgroundWriterMain(void){	sigjmp_buf	local_sigjmp_buf;	MemoryContext bgwriter_context;	Assert(BgWriterShmem != NULL);	BgWriterShmem->bgwriter_pid = MyProcPid;	am_bg_writer = true;	/*	 * Properly accept or ignore signals the postmaster might send us	 *	 * Note: we deliberately ignore SIGTERM, because during a standard Unix	 * system shutdown cycle, init will SIGTERM all processes at once.	We	 * want to wait for the backends to exit, whereupon the postmaster will	 * tell us it's okay to shut down (via SIGUSR2).	 *	 * SIGUSR1 is presently unused; keep it spare in case someday we want this	 * process to participate in sinval messaging.	 */	pqsignal(SIGHUP, BgSigHupHandler);	/* set flag to read config file */	pqsignal(SIGINT, ReqCheckpointHandler);		/* request checkpoint */	pqsignal(SIGTERM, SIG_IGN); /* ignore SIGTERM */	pqsignal(SIGQUIT, bg_quickdie);		/* hard crash time */	pqsignal(SIGALRM, SIG_IGN);	pqsignal(SIGPIPE, SIG_IGN);	pqsignal(SIGUSR1, SIG_IGN); /* reserve for sinval */	pqsignal(SIGUSR2, ReqShutdownHandler);		/* request shutdown */	/*	 * Reset some signals that are accepted by postmaster but not here	 */	pqsignal(SIGCHLD, SIG_DFL);	pqsignal(SIGTTIN, SIG_DFL);	pqsignal(SIGTTOU, SIG_DFL);	pqsignal(SIGCONT, SIG_DFL);	pqsignal(SIGWINCH, SIG_DFL);	/* We allow SIGQUIT (quickdie) at all times */#ifdef HAVE_SIGPROCMASK	sigdelset(&BlockSig, SIGQUIT);#else	BlockSig &= ~(sigmask(SIGQUIT));#endif	/*	 * Initialize so that first time-driven checkpoint happens at the correct	 * time.	 */	last_checkpoint_time = time(NULL);	/*	 * Create a resource owner to keep track of our resources (currently	 * only buffer pins).	 */	CurrentResourceOwner = ResourceOwnerCreate(NULL, "Background Writer");	/*	 * Create a memory context that we will do all our work in.  We do this so	 * that we can reset the context during error recovery and thereby avoid	 * possible memory leaks.  Formerly this code just ran in	 * TopMemoryContext, but resetting that would be a really bad idea.	 */	bgwriter_context = AllocSetContextCreate(TopMemoryContext,											 "Background Writer",											 ALLOCSET_DEFAULT_MINSIZE,											 ALLOCSET_DEFAULT_INITSIZE,											 ALLOCSET_DEFAULT_MAXSIZE);	MemoryContextSwitchTo(bgwriter_context);	/*	 * If an exception is encountered, processing resumes here.	 *	 * See notes in postgres.c about the design of this coding.	 */	if (sigsetjmp(local_sigjmp_buf, 1) != 0)	{		/* Since not using PG_TRY, must reset error stack by hand */		error_context_stack = NULL;		/* Prevent interrupts while cleaning up */		HOLD_INTERRUPTS();		/* Report the error to the server log */		EmitErrorReport();		/*		 * These operations are really just a minimal subset of		 * AbortTransaction().	We don't have very many resources to worry		 * about in bgwriter, but we do have LWLocks, buffers, and temp files.		 */		LWLockReleaseAll();		AbortBufferIO();		UnlockBuffers();		/* buffer pins are released here: */		ResourceOwnerRelease(CurrentResourceOwner,							 RESOURCE_RELEASE_BEFORE_LOCKS,							 false, true);		/* we needn't bother with the other ResourceOwnerRelease phases */		AtEOXact_Buffers(false);		AtEOXact_Files();		/* Warn any waiting backends that the checkpoint failed. */		if (ckpt_active)		{			/* use volatile pointer to prevent code rearrangement */			volatile BgWriterShmemStruct *bgs = BgWriterShmem;			bgs->ckpt_failed++;			bgs->ckpt_done = bgs->ckpt_started;			ckpt_active = false;		}		/*		 * Now return to normal top-level context and clear ErrorContext for		 * next time.		 */		MemoryContextSwitchTo(bgwriter_context);		FlushErrorState();		/* Flush any leaked data in the top-level context */		MemoryContextResetAndDeleteChildren(bgwriter_context);		/* Now we can allow interrupts again */		RESUME_INTERRUPTS();		/*		 * Sleep at least 1 second after any error.  A write error is likely		 * to be repeated, and we don't want to be filling the error logs as		 * fast as we can.		 */		pg_usleep(1000000L);	}	/* We can now handle ereport(ERROR) */	PG_exception_stack = &local_sigjmp_buf;	/*	 * Unblock signals (they were blocked when the postmaster forked us)	 */	PG_SETMASK(&UnBlockSig);	/*	 * Loop forever	 */	for (;;)	{		bool		do_checkpoint = false;		bool		force_checkpoint = false;		time_t		now;		int			elapsed_secs;		long		udelay;		/*		 * Emergency bailout if postmaster has died.  This is to avoid the		 * necessity for manual cleanup of all postmaster children.		 */		if (!PostmasterIsAlive(true))			exit(1);		/*		 * Process any requests or signals received recently.		 */		AbsorbFsyncRequests();		if (got_SIGHUP)		{			got_SIGHUP = false;			ProcessConfigFile(PGC_SIGHUP);		}		if (checkpoint_requested)		{			checkpoint_requested = false;			do_checkpoint = true;			force_checkpoint = true;		}		if (shutdown_requested)		{			ShutdownXLOG(0, 0);			DumpFreeSpaceMap(0, 0);			/* Normal exit from the bgwriter is here */			proc_exit(0);		/* done */		}		/*		 * Do an unforced checkpoint if too much time has elapsed since the		 * last one.		 */		now = time(NULL);		elapsed_secs = now - last_checkpoint_time;		if (elapsed_secs >= CheckPointTimeout)			do_checkpoint = true;		/*		 * Do a checkpoint if requested, otherwise do one cycle of		 * dirty-buffer writing.

⌨️ 快捷键说明

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