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

📄 pgstat.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
voidpgstat_reset_counters(void){	PgStat_MsgResetcounter msg;	if (pgStatSock < 0)		return;	if (!superuser())		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("must be superuser to reset statistics counters")));	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETCOUNTER);	msg.m_databaseid = MyDatabaseId;	pgstat_send(&msg, sizeof(msg));}/* ---------- * pgstat_ping() - * *	Send some junk data to the collector to increase traffic. * ---------- */voidpgstat_ping(void){	PgStat_MsgDummy msg;	if (pgStatSock < 0)		return;	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_DUMMY);	pgstat_send(&msg, sizeof(msg));}/* * Enlarge a TabStatArray */static voidmore_tabstat_space(TabStatArray *tsarr){	PgStat_MsgTabstat *newMessages;	PgStat_MsgTabstat **msgArray;	int			newAlloc;	int			i;	AssertArg(PointerIsValid(tsarr));	newAlloc = tsarr->tsa_alloc + TABSTAT_QUANTUM;	/* Create (another) quantum of message buffers */	newMessages = (PgStat_MsgTabstat *)		MemoryContextAllocZero(TopMemoryContext,							   sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM);	/* Create or enlarge the pointer array */	if (tsarr->tsa_messages == NULL)		msgArray = (PgStat_MsgTabstat **)			MemoryContextAlloc(TopMemoryContext,							   sizeof(PgStat_MsgTabstat *) * newAlloc);	else		msgArray = (PgStat_MsgTabstat **)			repalloc(tsarr->tsa_messages,					 sizeof(PgStat_MsgTabstat *) * newAlloc);	for (i = 0; i < TABSTAT_QUANTUM; i++)		msgArray[tsarr->tsa_alloc + i] = newMessages++;	tsarr->tsa_messages = msgArray;	tsarr->tsa_alloc = newAlloc;	Assert(tsarr->tsa_used < tsarr->tsa_alloc);}/* ---------- * pgstat_initstats() - * *	Called from various places usually dealing with initialization *	of Relation or Scan structures. The data placed into these *	structures from here tell where later to count for buffer reads, *	scans and tuples fetched. * ---------- */voidpgstat_initstats(PgStat_Info *stats, Relation rel){	Oid			rel_id = rel->rd_id;	PgStat_TableEntry *useent;	TabStatArray *tsarr;	PgStat_MsgTabstat *tsmsg;	int			mb;	int			i;	/*	 * Initialize data not to count at all.	 */	stats->tabentry = NULL;	if (pgStatSock < 0 ||		!(pgstat_collect_tuplelevel ||		  pgstat_collect_blocklevel))		return;	tsarr = rel->rd_rel->relisshared ? &SharedTabStat : &RegularTabStat;	/*	 * Search the already-used message slots for this relation.	 */	for (mb = 0; mb < tsarr->tsa_used; mb++)	{		tsmsg = tsarr->tsa_messages[mb];		for (i = tsmsg->m_nentries; --i >= 0;)		{			if (tsmsg->m_entry[i].t_id == rel_id)			{				stats->tabentry = (void *) &(tsmsg->m_entry[i]);				return;			}		}		if (tsmsg->m_nentries >= PGSTAT_NUM_TABENTRIES)			continue;		/*		 * Not found, but found a message buffer with an empty slot instead.		 * Fine, let's use this one.		 */		i = tsmsg->m_nentries++;		useent = &tsmsg->m_entry[i];		MemSet(useent, 0, sizeof(PgStat_TableEntry));		useent->t_id = rel_id;		stats->tabentry = (void *) useent;		return;	}	/*	 * If we ran out of message buffers, we just allocate more.	 */	if (tsarr->tsa_used >= tsarr->tsa_alloc)		more_tabstat_space(tsarr);	/*	 * Use the first entry of the next message buffer.	 */	mb = tsarr->tsa_used++;	tsmsg = tsarr->tsa_messages[mb];	tsmsg->m_nentries = 1;	useent = &tsmsg->m_entry[0];	MemSet(useent, 0, sizeof(PgStat_TableEntry));	useent->t_id = rel_id;	stats->tabentry = (void *) useent;}/* ---------- * pgstat_count_xact_commit() - * *	Called from access/transam/xact.c to count transaction commits. * ---------- */voidpgstat_count_xact_commit(void){	if (!(pgstat_collect_querystring ||		  pgstat_collect_tuplelevel ||		  pgstat_collect_blocklevel))		return;	pgStatXactCommit++;	/*	 * If there was no relation activity yet, just make one existing message	 * buffer used without slots, causing the next report to tell new	 * xact-counters.	 */	if (RegularTabStat.tsa_alloc == 0)		more_tabstat_space(&RegularTabStat);	if (RegularTabStat.tsa_used == 0)	{		RegularTabStat.tsa_used++;		RegularTabStat.tsa_messages[0]->m_nentries = 0;	}}/* ---------- * pgstat_count_xact_rollback() - * *	Called from access/transam/xact.c to count transaction rollbacks. * ---------- */voidpgstat_count_xact_rollback(void){	if (!(pgstat_collect_querystring ||		  pgstat_collect_tuplelevel ||		  pgstat_collect_blocklevel))		return;	pgStatXactRollback++;	/*	 * If there was no relation activity yet, just make one existing message	 * buffer used without slots, causing the next report to tell new	 * xact-counters.	 */	if (RegularTabStat.tsa_alloc == 0)		more_tabstat_space(&RegularTabStat);	if (RegularTabStat.tsa_used == 0)	{		RegularTabStat.tsa_used++;		RegularTabStat.tsa_messages[0]->m_nentries = 0;	}}/* ---------- * pgstat_fetch_stat_dbentry() - * *	Support function for the SQL-callable pgstat* functions. Returns *	the collected statistics for one database or NULL. NULL doesn't mean *	that the database doesn't exist, it is just not yet known by the *	collector, so the caller is better off to report ZERO instead. * ---------- */PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid){	/*	 * If not done for this transaction, read the statistics collector stats	 * file into some hash tables.	 */	backend_read_statsfile();	/*	 * Lookup the requested database; return NULL if not found	 */	return (PgStat_StatDBEntry *) hash_search(pgStatDBHash,											  (void *) &dbid,											  HASH_FIND, NULL);}/* ---------- * pgstat_fetch_stat_tabentry() - * *	Support function for the SQL-callable pgstat* functions. Returns *	the collected statistics for one table or NULL. NULL doesn't mean *	that the table doesn't exist, it is just not yet known by the *	collector, so the caller is better off to report ZERO instead. * ---------- */PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid){	Oid			dbid;	PgStat_StatDBEntry *dbentry;	PgStat_StatTabEntry *tabentry;	/*	 * If not done for this transaction, read the statistics collector stats	 * file into some hash tables.	 */	backend_read_statsfile();	/*	 * Lookup our database, then look in its table hash table.	 */	dbid = MyDatabaseId;	dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,												 (void *) &dbid,												 HASH_FIND, NULL);	if (dbentry != NULL && dbentry->tables != NULL)	{		tabentry = (PgStat_StatTabEntry *) hash_search(dbentry->tables,													   (void *) &relid,													   HASH_FIND, NULL);		if (tabentry)			return tabentry;	}	/*	 * If we didn't find it, maybe it's a shared table.	 */	dbid = InvalidOid;	dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,												 (void *) &dbid,												 HASH_FIND, NULL);	if (dbentry != NULL && dbentry->tables != NULL)	{		tabentry = (PgStat_StatTabEntry *) hash_search(dbentry->tables,													   (void *) &relid,													   HASH_FIND, NULL);		if (tabentry)			return tabentry;	}	return NULL;}/* ---------- * pgstat_fetch_stat_beentry() - * *	Support function for the SQL-callable pgstat* functions. Returns *	the actual activity slot of one active backend. The caller is *	responsible for a check if the actual user is permitted to see *	that info (especially the querystring). * ---------- */PgStat_StatBeEntry *pgstat_fetch_stat_beentry(int beid){	backend_read_statsfile();	if (beid < 1 || beid > pgStatNumBackends)		return NULL;	return &pgStatBeTable[beid - 1];}/* ---------- * pgstat_fetch_stat_numbackends() - * *	Support function for the SQL-callable pgstat* functions. Returns *	the maximum current backend id. * ---------- */intpgstat_fetch_stat_numbackends(void){	backend_read_statsfile();	return pgStatNumBackends;}/* ------------------------------------------------------------ * Local support functions follow * ------------------------------------------------------------ *//* ---------- * pgstat_setheader() - * *		Set common header fields in a statistics message * ---------- */static voidpgstat_setheader(PgStat_MsgHdr *hdr, StatMsgType mtype){	hdr->m_type = mtype;	hdr->m_backendid = MyBackendId;	hdr->m_procpid = MyProcPid;}/* ---------- * pgstat_send() - * *		Send out one statistics message to the collector * ---------- */static voidpgstat_send(void *msg, int len){	if (pgStatSock < 0)		return;	((PgStat_MsgHdr *) msg)->m_size = len;#ifdef USE_ASSERT_CHECKING	if (send(pgStatSock, msg, len, 0) < 0)		elog(LOG, "could not send to statistics collector: %m");#else	send(pgStatSock, msg, len, 0);	/* We deliberately ignore any error from send() */#endif}/* ---------- * PgstatBufferMain() - * *	Start up the statistics buffer process.  This is the body of the *	postmaster child process. * *	The argc/argv parameters are valid only in EXEC_BACKEND case. * ---------- */NON_EXEC_STATIC voidPgstatBufferMain(int argc, char *argv[]){	IsUnderPostmaster = true;	/* we are a postmaster subprocess now */	MyProcPid = getpid();		/* reset MyProcPid */	/* Lose the postmaster's on-exit routines */	on_exit_reset();	/*	 * Ignore all signals usually bound to some action in the postmaster,	 * except for SIGCHLD and SIGQUIT --- see pgstat_recvbuffer.	 */	pqsignal(SIGHUP, SIG_IGN);	pqsignal(SIGINT, SIG_IGN);	pqsignal(SIGTERM, SIG_IGN);	pqsignal(SIGQUIT, pgstat_exit);	pqsignal(SIGALRM, SIG_IGN);	pqsignal(SIGPIPE, SIG_IGN);	pqsignal(SIGUSR1, SIG_IGN);	pqsignal(SIGUSR2, SIG_IGN);	pqsignal(SIGCHLD, pgstat_die);	pqsignal(SIGTTIN, SIG_DFL);	pqsignal(SIGTTOU, SIG_DFL);	pqsignal(SIGCONT, SIG_DFL);	pqsignal(SIGWINCH, SIG_DFL);	/* unblock will happen in pgstat_recvbuffer */#ifdef EXEC_BACKEND	pgstat_parseArgs(argc, argv);#endif	/*	 * Start a buffering process to read from the socket, so we have a little	 * more time to process incoming messages.	 *	 * NOTE: the process structure is: postmaster is parent of buffer process	 * is parent of collector process.	This way, the buffer can detect	 * collector failure via SIGCHLD, whereas otherwise it wouldn't notice	 * collector failure until it tried to write on the pipe.  That would mean	 * that after the postmaster started a new collector, we'd have two buffer	 * processes competing to read from the UDP socket --- not good.	 */	if (pgpipe(pgStatPipe) < 0)		ereport(ERROR,				(errcode_for_socket_access(),				 errmsg("could not create pipe for statistics buffer: %m")));	/* child becomes collector process */#ifdef EXEC_BACKEND	pgStatCollectorPid = pgstat_forkexec(STAT_PROC_COLLECTOR);#else	pgStatCollectorPid = fork();#endif	switch (pgStatCollectorPid)	{		case -1:			ereport(ERROR,					(errmsg("could not fork statistics collector: %m")));#ifndef EXEC_BACKEND		case 0:			/* child becomes collector process */			PgstatCollectorMain(0, NULL);			break;#endif		default:			/* parent becomes buffer process */			closesocket(pgStatPipe[0]);			pgstat_recvbuffer();	}	exit(0);}/* ---------- * PgstatCollectorMain() - * *	Start up the statistics collector itself.  This is the body of the *	postmaster grandchild process. * *	The argc/argv parameters are valid only in EXEC_BACKEND case. * ---------- */NON_EXEC_STATIC voidPgstatCollectorMain(int argc, char *argv[]){	PgStat_Msg	msg;	fd_set		rfds;	int			readPipe;	int			nready;	int			len = 0;	struct timeval timeout;	struct timeval next_statwrite;	bool		need_statwrite;	HASHCTL		hash_ctl;	MyProcPid = getpid();		/* reset MyProcPid */	/*	 * Reset signal handling.  With the exception of restoring default SIGCHLD	 * and SIGQUIT handling, this is a no-op in the non-EXEC_BACKEND case	 * because we'll have inherited these settings from the buffer process;	 * but it's not a no-op for EXEC_BACKEND.	 */	pqsignal(SIGHUP, SIG_IGN);	pqsignal(SIGINT, SIG_IGN);	pqsignal(SIGTERM, SIG_IGN);#ifndef WIN32	pqsignal(SIGQUIT, SIG_IGN);#else	/* kluge to allow buffer process to kill collector; FIXME */	pqsignal(SIGQUIT, pgstat_exit);#endif	pqsignal(SIGALRM, SIG_IGN);	pqsignal(SIGPIPE, SIG_IGN);	pqsignal(SIGUSR1, SIG_IGN);	pqsignal(SIGUSR2, SIG_IGN);	pqsignal(SIGCHLD, SIG_DFL);	pqsignal(SIGTTIN, SIG_DFL);	pqsignal(SIGTTOU, SIG_DFL);	pqsignal(SIGCONT, SIG_DFL);	pqsignal(SIGWINCH, SIG_DFL);	PG_SETMASK(&UnBlockSig);#ifdef EXEC_BACKEND	pgstat_parseArgs(argc, argv);#endif	/* Close unwanted files */	closesocket(pgStatPipe[1]);

⌨️ 快捷键说明

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