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

📄 pgstat.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	argc = 3;	StrNCpy(postgres_exec_path, argv[argc++], MAXPGPATH);}#endif   /* EXEC_BACKEND *//* ---------- * pgstat_start() - * *	Called from postmaster at startup or after an existing collector *	died.  Attempt to fire up a fresh statistics collector. * *	Returns PID of child process, or 0 if fail. * *	Note: if fail, we will be called again from the postmaster main loop. * ---------- */intpgstat_start(void){	time_t		curtime;	pid_t		pgStatPid;	/*	 * Do nothing if no collector needed	 */	if (!pgstat_collect_startcollector)		return 0;	/*	 * Do nothing if too soon since last collector start.  This is a safety	 * valve to protect against continuous respawn attempts if the collector	 * is dying immediately at launch.	Note that since we will be re-called	 * from the postmaster main loop, we will get another chance later.	 */	curtime = time(NULL);	if ((unsigned int) (curtime - last_pgstat_start_time) <		(unsigned int) PGSTAT_RESTART_INTERVAL)		return 0;	last_pgstat_start_time = curtime;	/*	 * Check that the socket is there, else pgstat_init failed.	 */	if (pgStatSock < 0)	{		ereport(LOG,				(errmsg("statistics collector startup skipped")));		/*		 * We can only get here if someone tries to manually turn		 * pgstat_collect_startcollector on after it had been off.		 */		pgstat_collect_startcollector = false;		return 0;	}	/*	 * Okay, fork off the collector.	 */#ifdef EXEC_BACKEND	switch ((pgStatPid = pgstat_forkexec(STAT_PROC_BUFFER)))#else	switch ((pgStatPid = fork_process()))#endif	{		case -1:			ereport(LOG,					(errmsg("could not fork statistics buffer: %m")));			return 0;#ifndef EXEC_BACKEND		case 0:			/* in postmaster child ... */			/* Close the postmaster's sockets */			ClosePostmasterPorts(false);			/* Drop our connection to postmaster's shared memory, as well */			PGSharedMemoryDetach();			PgstatBufferMain(0, NULL);			break;#endif		default:			return (int) pgStatPid;	}	/* shouldn't get here */	return 0;}/* ---------- * pgstat_beterm() - * *	Called from postmaster to tell collector a backend terminated. * ---------- */voidpgstat_beterm(int pid){	PgStat_MsgBeterm msg;	if (pgStatSock < 0)		return;	/* can't use pgstat_setheader() because it's not called in a backend */	MemSet(&(msg.m_hdr), 0, sizeof(msg.m_hdr));	msg.m_hdr.m_type = PGSTAT_MTYPE_BETERM;	msg.m_hdr.m_procpid = pid;	pgstat_send(&msg, sizeof(msg));}/* ---------- * pgstat_report_autovac() - * *	Called from autovacuum.c to report startup of an autovacuum process. *	We are called before InitPostgres is done, so can't rely on MyDatabaseId; *	the db OID must be passed in, instead. * ---------- */voidpgstat_report_autovac(Oid dboid){	PgStat_MsgAutovacStart msg;	if (pgStatSock < 0)		return;	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_AUTOVAC_START);	msg.m_databaseid = dboid;	msg.m_start_time = GetCurrentTimestamp();	pgstat_send(&msg, sizeof(msg));}/* ------------------------------------------------------------ * Public functions used by backends follow *------------------------------------------------------------ *//* ---------- * pgstat_bestart() - * *	Tell the collector that this new backend is soon ready to process *	queries. Called from InitPostgres. * ---------- */voidpgstat_bestart(void){	PgStat_MsgBestart msg;	if (pgStatSock < 0)		return;	/*	 * We may not have a MyProcPort (eg, if this is the autovacuum process).	 * Send an all-zeroes client address, which is dealt with specially in	 * pg_stat_get_backend_client_addr and pg_stat_get_backend_client_port.	 */	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_BESTART);	msg.m_databaseid = MyDatabaseId;	msg.m_userid = GetSessionUserId();	if (MyProcPort)		memcpy(&msg.m_clientaddr, &MyProcPort->raddr, sizeof(msg.m_clientaddr));	else		MemSet(&msg.m_clientaddr, 0, sizeof(msg.m_clientaddr));	pgstat_send(&msg, sizeof(msg));	/*	 * Set up a process-exit hook to ensure we flush the last batch of	 * statistics to the collector.	 */	on_shmem_exit(pgstat_beshutdown_hook, 0);}/* --------- * pgstat_report_vacuum() - * *	Tell the collector about the table we just vacuumed. * --------- */voidpgstat_report_vacuum(Oid tableoid, bool shared,					 bool analyze, PgStat_Counter tuples){	PgStat_MsgVacuum msg;	if (pgStatSock < 0 ||		!pgstat_collect_tuplelevel)		return;	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_VACUUM);	msg.m_databaseid = shared ? InvalidOid : MyDatabaseId;	msg.m_tableoid = tableoid;	msg.m_analyze = analyze;	msg.m_tuples = tuples;	pgstat_send(&msg, sizeof(msg));}/* -------- * pgstat_report_analyze() - * *	Tell the collector about the table we just analyzed. * -------- */voidpgstat_report_analyze(Oid tableoid, bool shared, PgStat_Counter livetuples,					  PgStat_Counter deadtuples){	PgStat_MsgAnalyze msg;	if (pgStatSock < 0 ||		!pgstat_collect_tuplelevel)		return;	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_ANALYZE);	msg.m_databaseid = shared ? InvalidOid : MyDatabaseId;	msg.m_tableoid = tableoid;	msg.m_live_tuples = livetuples;	msg.m_dead_tuples = deadtuples;	pgstat_send(&msg, sizeof(msg));}/* * Flush any remaining statistics counts out to the collector at process * exit.   Without this, operations triggered during backend exit (such as * temp table deletions) won't be counted. */static voidpgstat_beshutdown_hook(int code, Datum arg){	pgstat_report_tabstat();}/* ---------- * pgstat_report_activity() - * *	Called from tcop/postgres.c to tell the collector what the backend *	is actually doing (usually "<IDLE>" or the start of the query to *	be executed). * ---------- */voidpgstat_report_activity(const char *what){	PgStat_MsgActivity msg;	int			len;	if (!pgstat_collect_querystring || pgStatSock < 0)		return;	len = strlen(what);	len = pg_mbcliplen(what, len, PGSTAT_ACTIVITY_SIZE - 1);	memcpy(msg.m_what, what, len);	msg.m_what[len] = '\0';	len += offsetof(PgStat_MsgActivity, m_what) +1;	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_ACTIVITY);	pgstat_send(&msg, len);}/* ---------- * pgstat_report_tabstat() - * *	Called from tcop/postgres.c to send the so far collected *	per table access statistics to the collector. * ---------- */voidpgstat_report_tabstat(void){	int			i;	if (pgStatSock < 0 ||		!(pgstat_collect_querystring ||		  pgstat_collect_tuplelevel ||		  pgstat_collect_blocklevel))	{		/* Not reporting stats, so just flush whatever we have */		RegularTabStat.tsa_used = 0;		SharedTabStat.tsa_used = 0;		return;	}	/*	 * For each message buffer used during the last query set the header	 * fields and send it out.	 */	for (i = 0; i < RegularTabStat.tsa_used; i++)	{		PgStat_MsgTabstat *tsmsg = RegularTabStat.tsa_messages[i];		int			n;		int			len;		n = tsmsg->m_nentries;		len = offsetof(PgStat_MsgTabstat, m_entry[0]) +			n * sizeof(PgStat_TableEntry);		tsmsg->m_xact_commit = pgStatXactCommit;		tsmsg->m_xact_rollback = pgStatXactRollback;		pgStatXactCommit = 0;		pgStatXactRollback = 0;		pgstat_setheader(&tsmsg->m_hdr, PGSTAT_MTYPE_TABSTAT);		tsmsg->m_databaseid = MyDatabaseId;		pgstat_send(tsmsg, len);	}	RegularTabStat.tsa_used = 0;	/* Ditto, for shared relations */	for (i = 0; i < SharedTabStat.tsa_used; i++)	{		PgStat_MsgTabstat *tsmsg = SharedTabStat.tsa_messages[i];		int			n;		int			len;		n = tsmsg->m_nentries;		len = offsetof(PgStat_MsgTabstat, m_entry[0]) +			n * sizeof(PgStat_TableEntry);		/* We don't report transaction commit/abort here */		tsmsg->m_xact_commit = 0;		tsmsg->m_xact_rollback = 0;		pgstat_setheader(&tsmsg->m_hdr, PGSTAT_MTYPE_TABSTAT);		tsmsg->m_databaseid = InvalidOid;		pgstat_send(tsmsg, len);	}	SharedTabStat.tsa_used = 0;}/* ---------- * pgstat_vacuum_tabstat() - * *	Will tell the collector about objects he can get rid of. * ---------- */voidpgstat_vacuum_tabstat(void){	List	   *oidlist;	Relation	rel;	HeapScanDesc scan;	HeapTuple	tup;	PgStat_MsgTabpurge msg;	HASH_SEQ_STATUS hstat;	PgStat_StatDBEntry *dbentry;	PgStat_StatTabEntry *tabentry;	int			len;	if (pgStatSock < 0)		return;	/*	 * If not done for this transaction, read the statistics collector stats	 * file into some hash tables.	 */	backend_read_statsfile();	/*	 * Read pg_database and make a list of OIDs of all existing databases	 */	oidlist = NIL;	rel = heap_open(DatabaseRelationId, AccessShareLock);	scan = heap_beginscan(rel, SnapshotNow, 0, NULL);	while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)	{		oidlist = lappend_oid(oidlist, HeapTupleGetOid(tup));	}	heap_endscan(scan);	heap_close(rel, AccessShareLock);	/*	 * Search the database hash table for dead databases and tell the	 * collector to drop them.	 */	hash_seq_init(&hstat, pgStatDBHash);	while ((dbentry = (PgStat_StatDBEntry *) hash_seq_search(&hstat)) != NULL)	{		Oid			dbid = dbentry->databaseid;		if (!list_member_oid(oidlist, dbid))			pgstat_drop_database(dbid);	}	/* Clean up */	list_free(oidlist);	/*	 * Lookup our own database entry; if not found, nothing more to do.	 */	dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,												 (void *) &MyDatabaseId,												 HASH_FIND, NULL);	if (dbentry == NULL || dbentry->tables == NULL)		return;	/*	 * Similarly to above, make a list of all known relations in this DB.	 */	oidlist = NIL;	rel = heap_open(RelationRelationId, AccessShareLock);	scan = heap_beginscan(rel, SnapshotNow, 0, NULL);	while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)	{		oidlist = lappend_oid(oidlist, HeapTupleGetOid(tup));	}	heap_endscan(scan);	heap_close(rel, AccessShareLock);	/*	 * Initialize our messages table counter to zero	 */	msg.m_nentries = 0;	/*	 * Check for all tables listed in stats hashtable if they still exist.	 */	hash_seq_init(&hstat, dbentry->tables);	while ((tabentry = (PgStat_StatTabEntry *) hash_seq_search(&hstat)) != NULL)	{		if (list_member_oid(oidlist, tabentry->tableid))			continue;		/*		 * Not there, so add this table's Oid to the message		 */		msg.m_tableid[msg.m_nentries++] = tabentry->tableid;		/*		 * If the message is full, send it out and reinitialize to empty		 */		if (msg.m_nentries >= PGSTAT_NUM_TABPURGE)		{			len = offsetof(PgStat_MsgTabpurge, m_tableid[0])				+msg.m_nentries * sizeof(Oid);			pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_TABPURGE);			msg.m_databaseid = MyDatabaseId;			pgstat_send(&msg, len);			msg.m_nentries = 0;		}	}	/*	 * Send the rest	 */	if (msg.m_nentries > 0)	{		len = offsetof(PgStat_MsgTabpurge, m_tableid[0])			+msg.m_nentries * sizeof(Oid);		pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_TABPURGE);		msg.m_databaseid = MyDatabaseId;		pgstat_send(&msg, len);	}	/* Clean up */	list_free(oidlist);}/* ---------- * pgstat_drop_database() - * *	Tell the collector that we just dropped a database. *	(If the message gets lost, we will still clean the dead DB eventually *	via future invocations of pgstat_vacuum_tabstat().) * ---------- */static voidpgstat_drop_database(Oid databaseid){	PgStat_MsgDropdb msg;	if (pgStatSock < 0)		return;	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_DROPDB);	msg.m_databaseid = databaseid;	pgstat_send(&msg, sizeof(msg));}/* ---------- * pgstat_drop_relation() - * *	Tell the collector that we just dropped a relation. *	(If the message gets lost, we will still clean the dead entry eventually *	via future invocations of pgstat_vacuum_tabstat().) * ---------- */voidpgstat_drop_relation(Oid relid){	PgStat_MsgTabpurge msg;	int			len;	if (pgStatSock < 0)		return;	msg.m_tableid[0] = relid;	msg.m_nentries = 1;	len = offsetof(PgStat_MsgTabpurge, m_tableid[0]) + sizeof(Oid);	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_TABPURGE);	msg.m_databaseid = MyDatabaseId;	pgstat_send(&msg, len);}/* ---------- * pgstat_reset_counters() - * *	Tell the statistics collector to reset counters for our database. * ---------- */

⌨️ 快捷键说明

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