/* -------------------------------------------------------------------------
 *
 * pgstat_function.c
 *	  Implementation of function statistics.
 *
 * This file contains the implementation of function statistics. It is kept
 * separate from pgstat.c to enforce the line between the statistics access /
 * storage implementation and the details about individual types of
 * statistics.
 *
 * Copyright (c) 2001-2023, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *	  src/backend/utils/activity/pgstat_function.c
 * -------------------------------------------------------------------------
 */

#include "postgres.h"

#include "fmgr.h"
#include "utils/inval.h"
#include "utils/pgstat_internal.h"
#include "utils/syscache.h"


/* ----------
 * GUC parameters
 * ----------
 */
int			pgstat_track_functions = TRACK_FUNC_OFF;


/*
 * Total time charged to functions so far in the current backend.
 * We use this to help separate "self" and "other" time charges.
 * (We assume this initializes to zero.)
 */
static instr_time total_func_time;


/*
 * Ensure that stats are dropped if transaction aborts.
 */
void
pgstat_create_function(Oid proid)
{
	pgstat_create_transactional(PGSTAT_KIND_FUNCTION,
								MyDatabaseId,
								proid);
}

/*
 * Ensure that stats are dropped if transaction commits.
 *
 * NB: This is only reliable because pgstat_init_function_usage() does some
 * extra work. If other places start emitting function stats they likely need
 * similar logic.
 */
void
pgstat_drop_function(Oid proid)
{
	pgstat_drop_transactional(PGSTAT_KIND_FUNCTION,
							  MyDatabaseId,
							  proid);
}

/*
 * Initialize function call usage data.
 * Called by the executor before invoking a function.
 */
void
pgstat_init_function_usage(FunctionCallInfo fcinfo,
						   PgStat_FunctionCallUsage *fcu)
{
	PgStat_EntryRef *entry_ref;
	PgStat_FunctionCounts *pending;
	bool		created_entry;

	if (pgstat_track_functions <= fcinfo->flinfo->fn_stats)
	{
		/* stats not wanted */
		fcu->fs = NULL;
		return;
	}

	entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_FUNCTION,
										  MyDatabaseId,
										  fcinfo->flinfo->fn_oid,
										  &created_entry);

	/*
	 * If no shared entry already exists, check if the function has been
	 * deleted concurrently. This can go unnoticed until here because
	 * executing a statement that just calls a function, does not trigger
	 * cache invalidation processing. The reason we care about this case is
	 * that otherwise we could create a new stats entry for an already dropped
	 * function (for relations etc this is not possible because emitting stats
	 * requires a lock for the relation to already have been acquired).
	 *
	 * It's somewhat ugly to have a behavioral difference based on
	 * track_functions being enabled/disabled. But it seems acceptable, given
	 * that there's already behavioral differences depending on whether the
	 * function is the caches etc.
	 *
	 * For correctness it'd be sufficient to set ->dropped to true. However,
	 * the accepted invalidation will commonly cause "low level" failures in
	 * PL code, with an OID in the error message. Making this harder to
	 * test...
	 */
	if (created_entry)
	{
		AcceptInvalidationMessages();
		if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(fcinfo->flinfo->fn_oid)))
		{
			pgstat_drop_entry(PGSTAT_KIND_FUNCTION, MyDatabaseId,
							  fcinfo->flinfo->fn_oid);
			ereport(ERROR, errcode(ERRCODE_UNDEFINED_FUNCTION),
					errmsg("function call to dropped function"));
		}
	}

	pending = entry_ref->pending;

	fcu->fs = pending;

	/* save stats for this function, later used to compensate for recursion */
	fcu->save_f_total_time = pending->total_time;

	/* save current backend-wide total time */
	fcu->save_total = total_func_time;

	/* get clock time as of function start */
	INSTR_TIME_SET_CURRENT(fcu->start);
}

/*
 * Calculate function call usage and update stat counters.
 * Called by the executor after invoking a function.
 *
 * In the case of a set-returning function that runs in value-per-call mode,
 * we will see multiple pgstat_init_function_usage/pgstat_end_function_usage
 * calls for what the user considers a single call of the function.  The
 * finalize flag should be TRUE on the last call.
 */
void
pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
{
	PgStat_FunctionCounts *fs = fcu->fs;
	instr_time	total;
	instr_time	others;
	instr_time	self;

	/* stats not wanted? */
	if (fs == NULL)
		return;

	/* total elapsed time in this function call */
	INSTR_TIME_SET_CURRENT(total);
	INSTR_TIME_SUBTRACT(total, fcu->start);

	/* self usage: elapsed minus anything already charged to other calls */
	others = total_func_time;
	INSTR_TIME_SUBTRACT(others, fcu->save_total);
	self = total;
	INSTR_TIME_SUBTRACT(self, others);

	/* update backend-wide total time */
	INSTR_TIME_ADD(total_func_time, self);

	/*
	 * Compute the new total_time as the total elapsed time added to the
	 * pre-call value of total_time.  This is necessary to avoid
	 * double-counting any time taken by recursive calls of myself.  (We do
	 * not need any similar kluge for self time, since that already excludes
	 * any recursive calls.)
	 */
	INSTR_TIME_ADD(total, fcu->save_f_total_time);

	/* update counters in function stats table */
	if (finalize)
		fs->numcalls++;
	fs->total_time = total;
	INSTR_TIME_ADD(fs->self_time, self);
}

/*
 * Flush out pending stats for the entry
 *
 * If nowait is true and the lock could not be immediately acquired, returns
 * false without flushing the entry.  Otherwise returns true.
 */
bool
pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
{
	PgStat_FunctionCounts *localent;
	PgStatShared_Function *shfuncent;

	localent = (PgStat_FunctionCounts *) entry_ref->pending;
	shfuncent = (PgStatShared_Function *) entry_ref->shared_stats;

	/* localent always has non-zero content */

	if (!pgstat_lock_entry(entry_ref, nowait))
		return false;

	shfuncent->stats.numcalls += localent->numcalls;
	shfuncent->stats.total_time +=
		INSTR_TIME_GET_MICROSEC(localent->total_time);
	shfuncent->stats.self_time +=
		INSTR_TIME_GET_MICROSEC(localent->self_time);

	pgstat_unlock_entry(entry_ref);

	return true;
}

/*
 * find any existing PgStat_FunctionCounts entry for specified function
 *
 * If no entry, return NULL, don't create a new one
 */
PgStat_FunctionCounts *
find_funcstat_entry(Oid func_id)
{
	PgStat_EntryRef *entry_ref;

	entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_FUNCTION, MyDatabaseId, func_id);

	if (entry_ref)
		return entry_ref->pending;
	return NULL;
}

/*
 * Support function for the SQL-callable pgstat* functions. Returns
 * the collected statistics for one function or NULL.
 */
PgStat_StatFuncEntry *
pgstat_fetch_stat_funcentry(Oid func_id)
{
	return (PgStat_StatFuncEntry *)
		pgstat_fetch_entry(PGSTAT_KIND_FUNCTION, MyDatabaseId, func_id);
}
