PG-456: Running pgindent to make source PostgreSQL compatible. (#269)
PG-456: Running pgindent to make source indentation/spacing PostgreSQLCompatible. PostgreSQL uses pgindent from time to time to make source code PostgreSQL style guide compatible, it is a very long time since we have not done that. Commit fixes a lot of indentation and spacing issues. Co-authored-by: Hamid Akhtar <hamid.akhtar@gmail.com>pull/276/head
parent
926eade1eb
commit
a9187117f9
320
guc.c
320
guc.c
|
@ -19,10 +19,10 @@
|
||||||
#include "pg_stat_monitor.h"
|
#include "pg_stat_monitor.h"
|
||||||
|
|
||||||
GucVariable conf[MAX_SETTINGS];
|
GucVariable conf[MAX_SETTINGS];
|
||||||
static void DefineIntGUC(GucVariable *conf);
|
static void DefineIntGUC(GucVariable * conf);
|
||||||
static void DefineIntGUCWithCheck(GucVariable *conf, GucIntCheckHook check);
|
static void DefineIntGUCWithCheck(GucVariable * conf, GucIntCheckHook check);
|
||||||
static void DefineBoolGUC(GucVariable *conf);
|
static void DefineBoolGUC(GucVariable * conf);
|
||||||
static void DefineEnumGUC(GucVariable *conf, const struct config_enum_entry *options);
|
static void DefineEnumGUC(GucVariable * conf, const struct config_enum_entry *options);
|
||||||
|
|
||||||
/* Check hooks to ensure histogram_min < histogram_max */
|
/* Check hooks to ensure histogram_min < histogram_max */
|
||||||
static bool check_histogram_min(int *newval, void **extra, GucSource source);
|
static bool check_histogram_min(int *newval, void **extra, GucSource source);
|
||||||
|
@ -34,196 +34,214 @@ static bool check_histogram_max(int *newval, void **extra, GucSource source);
|
||||||
void
|
void
|
||||||
init_guc(void)
|
init_guc(void)
|
||||||
{
|
{
|
||||||
int i = 0, j;
|
int i = 0,
|
||||||
|
j;
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_max",
|
.guc_name = "pg_stat_monitor.pgsm_max",
|
||||||
.guc_desc = "Sets the maximum size of shared memory in (MB) used for statement's metadata tracked by pg_stat_monitor.",
|
.guc_desc = "Sets the maximum size of shared memory in (MB) used for statement's metadata tracked by pg_stat_monitor.",
|
||||||
.guc_default = 100,
|
.guc_default = 100,
|
||||||
.guc_min = 1,
|
.guc_min = 1,
|
||||||
.guc_max = 1000,
|
.guc_max = 1000,
|
||||||
.guc_restart = true,
|
.guc_restart = true,
|
||||||
.guc_unit = GUC_UNIT_MB,
|
.guc_unit = GUC_UNIT_MB,
|
||||||
.guc_value = &PGSM_MAX
|
.guc_value = &PGSM_MAX
|
||||||
};
|
};
|
||||||
DefineIntGUC(&conf[i++]);
|
DefineIntGUC(&conf[i++]);
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_query_max_len",
|
.guc_name = "pg_stat_monitor.pgsm_query_max_len",
|
||||||
.guc_desc = "Sets the maximum length of query.",
|
.guc_desc = "Sets the maximum length of query.",
|
||||||
.guc_default = 2048,
|
.guc_default = 2048,
|
||||||
.guc_min = 1024,
|
.guc_min = 1024,
|
||||||
.guc_max = INT_MAX,
|
.guc_max = INT_MAX,
|
||||||
.guc_unit = 0,
|
.guc_unit = 0,
|
||||||
.guc_restart = true,
|
.guc_restart = true,
|
||||||
.guc_value = &PGSM_QUERY_MAX_LEN
|
.guc_value = &PGSM_QUERY_MAX_LEN
|
||||||
};
|
};
|
||||||
DefineIntGUC(&conf[i++]);
|
DefineIntGUC(&conf[i++]);
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_track_utility",
|
.guc_name = "pg_stat_monitor.pgsm_track_utility",
|
||||||
.guc_desc = "Selects whether utility commands are tracked.",
|
.guc_desc = "Selects whether utility commands are tracked.",
|
||||||
.guc_default = 1,
|
.guc_default = 1,
|
||||||
.guc_min = 0,
|
.guc_min = 0,
|
||||||
.guc_max = 0,
|
.guc_max = 0,
|
||||||
.guc_restart = false,
|
.guc_restart = false,
|
||||||
.guc_unit = 0,
|
.guc_unit = 0,
|
||||||
.guc_value = &PGSM_TRACK_UTILITY
|
.guc_value = &PGSM_TRACK_UTILITY
|
||||||
};
|
};
|
||||||
DefineBoolGUC(&conf[i++]);
|
DefineBoolGUC(&conf[i++]);
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_normalized_query",
|
.guc_name = "pg_stat_monitor.pgsm_normalized_query",
|
||||||
.guc_desc = "Selects whether save query in normalized format.",
|
.guc_desc = "Selects whether save query in normalized format.",
|
||||||
.guc_default = 0,
|
.guc_default = 0,
|
||||||
.guc_min = 0,
|
.guc_min = 0,
|
||||||
.guc_max = 0,
|
.guc_max = 0,
|
||||||
.guc_restart = false,
|
.guc_restart = false,
|
||||||
.guc_unit = 0,
|
.guc_unit = 0,
|
||||||
.guc_value = &PGSM_NORMALIZED_QUERY
|
.guc_value = &PGSM_NORMALIZED_QUERY
|
||||||
};
|
};
|
||||||
DefineBoolGUC(&conf[i++]);
|
DefineBoolGUC(&conf[i++]);
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_max_buckets",
|
.guc_name = "pg_stat_monitor.pgsm_max_buckets",
|
||||||
.guc_desc = "Sets the maximum number of buckets.",
|
.guc_desc = "Sets the maximum number of buckets.",
|
||||||
.guc_default = 10,
|
.guc_default = 10,
|
||||||
.guc_min = 1,
|
.guc_min = 1,
|
||||||
.guc_max = 10,
|
.guc_max = 10,
|
||||||
.guc_restart = true,
|
.guc_restart = true,
|
||||||
.guc_unit = 0,
|
.guc_unit = 0,
|
||||||
.guc_value = &PGSM_MAX_BUCKETS
|
.guc_value = &PGSM_MAX_BUCKETS
|
||||||
};
|
};
|
||||||
DefineIntGUC(&conf[i++]);
|
DefineIntGUC(&conf[i++]);
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_bucket_time",
|
.guc_name = "pg_stat_monitor.pgsm_bucket_time",
|
||||||
.guc_desc = "Sets the time in seconds per bucket.",
|
.guc_desc = "Sets the time in seconds per bucket.",
|
||||||
.guc_default = 60,
|
.guc_default = 60,
|
||||||
.guc_min = 1,
|
.guc_min = 1,
|
||||||
.guc_max = INT_MAX,
|
.guc_max = INT_MAX,
|
||||||
.guc_restart = true,
|
.guc_restart = true,
|
||||||
.guc_unit = 0,
|
.guc_unit = 0,
|
||||||
.guc_value = &PGSM_BUCKET_TIME
|
.guc_value = &PGSM_BUCKET_TIME
|
||||||
};
|
};
|
||||||
DefineIntGUC(&conf[i++]);
|
DefineIntGUC(&conf[i++]);
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_histogram_min",
|
.guc_name = "pg_stat_monitor.pgsm_histogram_min",
|
||||||
.guc_desc = "Sets the time in millisecond.",
|
.guc_desc = "Sets the time in millisecond.",
|
||||||
.guc_default = 0,
|
.guc_default = 0,
|
||||||
.guc_min = 0,
|
.guc_min = 0,
|
||||||
.guc_max = INT_MAX,
|
.guc_max = INT_MAX,
|
||||||
.guc_restart = true,
|
.guc_restart = true,
|
||||||
.guc_unit = 0,
|
.guc_unit = 0,
|
||||||
.guc_value = &PGSM_HISTOGRAM_MIN
|
.guc_value = &PGSM_HISTOGRAM_MIN
|
||||||
};
|
};
|
||||||
DefineIntGUCWithCheck(&conf[i++], check_histogram_min);
|
DefineIntGUCWithCheck(&conf[i++], check_histogram_min);
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_histogram_max",
|
.guc_name = "pg_stat_monitor.pgsm_histogram_max",
|
||||||
.guc_desc = "Sets the time in millisecond.",
|
.guc_desc = "Sets the time in millisecond.",
|
||||||
.guc_default = 100000,
|
.guc_default = 100000,
|
||||||
.guc_min = 10,
|
.guc_min = 10,
|
||||||
.guc_max = INT_MAX,
|
.guc_max = INT_MAX,
|
||||||
.guc_restart = true,
|
.guc_restart = true,
|
||||||
.guc_unit = 0,
|
.guc_unit = 0,
|
||||||
.guc_value = &PGSM_HISTOGRAM_MAX
|
.guc_value = &PGSM_HISTOGRAM_MAX
|
||||||
};
|
};
|
||||||
DefineIntGUCWithCheck(&conf[i++], check_histogram_max);
|
DefineIntGUCWithCheck(&conf[i++], check_histogram_max);
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_histogram_buckets",
|
.guc_name = "pg_stat_monitor.pgsm_histogram_buckets",
|
||||||
.guc_desc = "Sets the maximum number of histogram buckets",
|
.guc_desc = "Sets the maximum number of histogram buckets",
|
||||||
.guc_default = 10,
|
.guc_default = 10,
|
||||||
.guc_min = 2,
|
.guc_min = 2,
|
||||||
.guc_max = MAX_RESPONSE_BUCKET,
|
.guc_max = MAX_RESPONSE_BUCKET,
|
||||||
.guc_restart = true,
|
.guc_restart = true,
|
||||||
.guc_unit = 0,
|
.guc_unit = 0,
|
||||||
.guc_value = &PGSM_HISTOGRAM_BUCKETS
|
.guc_value = &PGSM_HISTOGRAM_BUCKETS
|
||||||
};
|
};
|
||||||
DefineIntGUC(&conf[i++]);
|
DefineIntGUC(&conf[i++]);
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_query_shared_buffer",
|
.guc_name = "pg_stat_monitor.pgsm_query_shared_buffer",
|
||||||
.guc_desc = "Sets the maximum size of shared memory in (MB) used for query tracked by pg_stat_monitor.",
|
.guc_desc = "Sets the maximum size of shared memory in (MB) used for query tracked by pg_stat_monitor.",
|
||||||
.guc_default = 20,
|
.guc_default = 20,
|
||||||
.guc_min = 1,
|
.guc_min = 1,
|
||||||
.guc_max = 10000,
|
.guc_max = 10000,
|
||||||
.guc_restart = true,
|
.guc_restart = true,
|
||||||
.guc_unit = GUC_UNIT_MB,
|
.guc_unit = GUC_UNIT_MB,
|
||||||
.guc_value = &PGSM_QUERY_SHARED_BUFFER
|
.guc_value = &PGSM_QUERY_SHARED_BUFFER
|
||||||
};
|
};
|
||||||
DefineIntGUC(&conf[i++]);
|
DefineIntGUC(&conf[i++]);
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_overflow_target",
|
.guc_name = "pg_stat_monitor.pgsm_overflow_target",
|
||||||
.guc_desc = "Sets the overflow target for pg_stat_monitor",
|
.guc_desc = "Sets the overflow target for pg_stat_monitor",
|
||||||
.guc_default = 1,
|
.guc_default = 1,
|
||||||
.guc_min = 0,
|
.guc_min = 0,
|
||||||
.guc_max = 1,
|
.guc_max = 1,
|
||||||
.guc_restart = true,
|
.guc_restart = true,
|
||||||
.guc_unit = 0,
|
.guc_unit = 0,
|
||||||
.guc_value = &PGSM_OVERFLOW_TARGET
|
.guc_value = &PGSM_OVERFLOW_TARGET
|
||||||
};
|
};
|
||||||
DefineIntGUC(&conf[i++]);
|
DefineIntGUC(&conf[i++]);
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_enable_query_plan",
|
.guc_name = "pg_stat_monitor.pgsm_enable_query_plan",
|
||||||
.guc_desc = "Enable/Disable query plan monitoring",
|
.guc_desc = "Enable/Disable query plan monitoring",
|
||||||
.guc_default = 0,
|
.guc_default = 0,
|
||||||
.guc_min = 0,
|
.guc_min = 0,
|
||||||
.guc_max = 0,
|
.guc_max = 0,
|
||||||
.guc_restart = false,
|
.guc_restart = false,
|
||||||
.guc_unit = 0,
|
.guc_unit = 0,
|
||||||
.guc_value = &PGSM_QUERY_PLAN
|
.guc_value = &PGSM_QUERY_PLAN
|
||||||
};
|
};
|
||||||
DefineBoolGUC(&conf[i++]);
|
DefineBoolGUC(&conf[i++]);
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_track",
|
.guc_name = "pg_stat_monitor.pgsm_track",
|
||||||
.guc_desc = "Selects which statements are tracked by pg_stat_monitor.",
|
.guc_desc = "Selects which statements are tracked by pg_stat_monitor.",
|
||||||
.n_options = 3,
|
.n_options = 3,
|
||||||
.guc_default = PGSM_TRACK_TOP,
|
.guc_default = PGSM_TRACK_TOP,
|
||||||
.guc_min = PSGM_TRACK_NONE,
|
.guc_min = PSGM_TRACK_NONE,
|
||||||
.guc_max = PGSM_TRACK_ALL,
|
.guc_max = PGSM_TRACK_ALL,
|
||||||
.guc_restart = false,
|
.guc_restart = false,
|
||||||
.guc_unit = 0,
|
.guc_unit = 0,
|
||||||
.guc_value = &PGSM_TRACK
|
.guc_value = &PGSM_TRACK
|
||||||
};
|
};
|
||||||
for (j = 0; j < conf[i].n_options; ++j) {
|
for (j = 0; j < conf[i].n_options; ++j)
|
||||||
|
{
|
||||||
strlcpy(conf[i].guc_options[j], track_options[j].name, sizeof(conf[i].guc_options[j]));
|
strlcpy(conf[i].guc_options[j], track_options[j].name, sizeof(conf[i].guc_options[j]));
|
||||||
}
|
}
|
||||||
DefineEnumGUC(&conf[i++], track_options);
|
DefineEnumGUC(&conf[i++], track_options);
|
||||||
|
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_extract_comments",
|
.guc_name = "pg_stat_monitor.pgsm_extract_comments",
|
||||||
.guc_desc = "Enable/Disable extracting comments from queries.",
|
.guc_desc = "Enable/Disable extracting comments from queries.",
|
||||||
.guc_default = 0,
|
.guc_default = 0,
|
||||||
.guc_min = 0,
|
.guc_min = 0,
|
||||||
.guc_max = 0,
|
.guc_max = 0,
|
||||||
.guc_restart = false,
|
.guc_restart = false,
|
||||||
.guc_unit = 0,
|
.guc_unit = 0,
|
||||||
.guc_value = &PGSM_EXTRACT_COMMENTS
|
.guc_value = &PGSM_EXTRACT_COMMENTS
|
||||||
};
|
};
|
||||||
DefineBoolGUC(&conf[i++]);
|
DefineBoolGUC(&conf[i++]);
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 130000
|
#if PG_VERSION_NUM >= 130000
|
||||||
conf[i] = (GucVariable) {
|
conf[i] = (GucVariable)
|
||||||
|
{
|
||||||
.guc_name = "pg_stat_monitor.pgsm_track_planning",
|
.guc_name = "pg_stat_monitor.pgsm_track_planning",
|
||||||
.guc_desc = "Selects whether planning statistics are tracked.",
|
.guc_desc = "Selects whether planning statistics are tracked.",
|
||||||
.guc_default = 0,
|
.guc_default = 0,
|
||||||
.guc_min = 0,
|
.guc_min = 0,
|
||||||
.guc_max = 0,
|
.guc_max = 0,
|
||||||
.guc_restart = false,
|
.guc_restart = false,
|
||||||
.guc_unit = 0,
|
.guc_unit = 0,
|
||||||
.guc_value = &PGSM_TRACK_PLANNING
|
.guc_value = &PGSM_TRACK_PLANNING
|
||||||
};
|
};
|
||||||
DefineBoolGUC(&conf[i++]);
|
DefineBoolGUC(&conf[i++]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DefineIntGUCWithCheck(GucVariable *conf, GucIntCheckHook check)
|
static void
|
||||||
|
DefineIntGUCWithCheck(GucVariable * conf, GucIntCheckHook check)
|
||||||
{
|
{
|
||||||
conf->type = PGC_INT;
|
conf->type = PGC_INT;
|
||||||
DefineCustomIntVariable(conf->guc_name,
|
DefineCustomIntVariable(conf->guc_name,
|
||||||
|
@ -241,21 +259,21 @@ static void DefineIntGUCWithCheck(GucVariable *conf, GucIntCheckHook check)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DefineIntGUC(GucVariable *conf)
|
DefineIntGUC(GucVariable * conf)
|
||||||
{
|
{
|
||||||
DefineIntGUCWithCheck(conf, NULL);
|
DefineIntGUCWithCheck(conf, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DefineBoolGUC(GucVariable *conf)
|
DefineBoolGUC(GucVariable * conf)
|
||||||
{
|
{
|
||||||
conf->type = PGC_BOOL;
|
conf->type = PGC_BOOL;
|
||||||
DefineCustomBoolVariable(conf->guc_name,
|
DefineCustomBoolVariable(conf->guc_name,
|
||||||
conf->guc_desc,
|
conf->guc_desc,
|
||||||
NULL,
|
NULL,
|
||||||
(bool*)conf->guc_value,
|
(bool *) conf->guc_value,
|
||||||
conf->guc_default,
|
conf->guc_default,
|
||||||
conf->guc_restart ? PGC_POSTMASTER : PGC_USERSET,
|
conf->guc_restart ? PGC_POSTMASTER : PGC_USERSET,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -263,29 +281,30 @@ DefineBoolGUC(GucVariable *conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DefineEnumGUC(GucVariable *conf, const struct config_enum_entry *options)
|
DefineEnumGUC(GucVariable * conf, const struct config_enum_entry *options)
|
||||||
{
|
{
|
||||||
conf->type = PGC_ENUM;
|
conf->type = PGC_ENUM;
|
||||||
DefineCustomEnumVariable(conf->guc_name,
|
DefineCustomEnumVariable(conf->guc_name,
|
||||||
conf->guc_desc,
|
conf->guc_desc,
|
||||||
NULL,
|
NULL,
|
||||||
conf->guc_value,
|
conf->guc_value,
|
||||||
conf->guc_default,
|
conf->guc_default,
|
||||||
options,
|
options,
|
||||||
conf->guc_restart ? PGC_POSTMASTER : PGC_USERSET,
|
conf->guc_restart ? PGC_POSTMASTER : PGC_USERSET,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
GucVariable*
|
GucVariable *
|
||||||
get_conf(int i)
|
get_conf(int i)
|
||||||
{
|
{
|
||||||
return &conf[i];
|
return &conf[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check_histogram_min(int *newval, void **extra, GucSource source)
|
static bool
|
||||||
|
check_histogram_min(int *newval, void **extra, GucSource source)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* During module initialization PGSM_HISTOGRAM_MIN is initialized before
|
* During module initialization PGSM_HISTOGRAM_MIN is initialized before
|
||||||
|
@ -294,7 +313,8 @@ static bool check_histogram_min(int *newval, void **extra, GucSource source)
|
||||||
return (PGSM_HISTOGRAM_MAX == 0 || *newval < PGSM_HISTOGRAM_MAX);
|
return (PGSM_HISTOGRAM_MAX == 0 || *newval < PGSM_HISTOGRAM_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check_histogram_max(int *newval, void **extra, GucSource source)
|
static bool
|
||||||
|
check_histogram_max(int *newval, void **extra, GucSource source)
|
||||||
{
|
{
|
||||||
return (*newval > PGSM_HISTOGRAM_MIN);
|
return (*newval > PGSM_HISTOGRAM_MIN);
|
||||||
}
|
}
|
||||||
|
|
105
hash_query.c
105
hash_query.c
|
@ -25,10 +25,11 @@ static HTAB *pgss_hash;
|
||||||
static HTAB *pgss_query_hash;
|
static HTAB *pgss_query_hash;
|
||||||
|
|
||||||
|
|
||||||
static HTAB*
|
static HTAB *
|
||||||
hash_init(const char *hash_name, int key_size, int entry_size, int hash_size)
|
hash_init(const char *hash_name, int key_size, int entry_size, int hash_size)
|
||||||
{
|
{
|
||||||
HASHCTL info;
|
HASHCTL info;
|
||||||
|
|
||||||
memset(&info, 0, sizeof(info));
|
memset(&info, 0, sizeof(info));
|
||||||
info.keysize = key_size;
|
info.keysize = key_size;
|
||||||
info.entrysize = entry_size;
|
info.entrysize = entry_size;
|
||||||
|
@ -46,8 +47,8 @@ pgss_startup(void)
|
||||||
pgss_hash = NULL;
|
pgss_hash = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create or attach to the shared memory state, including hash table
|
* Create or attach to the shared memory state, including hash table
|
||||||
*/
|
*/
|
||||||
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
|
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
pgss = ShmemInitStruct("pg_stat_monitor", sizeof(pgssSharedState), &found);
|
pgss = ShmemInitStruct("pg_stat_monitor", sizeof(pgssSharedState), &found);
|
||||||
|
@ -63,7 +64,7 @@ pgss_startup(void)
|
||||||
init_hook_stats();
|
init_hook_stats();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
set_qbuf((unsigned char *)ShmemAlloc(MAX_QUERY_BUF));
|
set_qbuf((unsigned char *) ShmemAlloc(MAX_QUERY_BUF));
|
||||||
|
|
||||||
pgss_hash = hash_init("pg_stat_monitor: bucket hashtable", sizeof(pgssHashKey), sizeof(pgssEntry), MAX_BUCKET_ENTRIES);
|
pgss_hash = hash_init("pg_stat_monitor: bucket hashtable", sizeof(pgssHashKey), sizeof(pgssEntry), MAX_BUCKET_ENTRIES);
|
||||||
pgss_query_hash = hash_init("pg_stat_monitor: queryID hashtable", sizeof(uint64), sizeof(pgssQueryEntry), MAX_BUCKET_ENTRIES);
|
pgss_query_hash = hash_init("pg_stat_monitor: queryID hashtable", sizeof(uint64), sizeof(pgssQueryEntry), MAX_BUCKET_ENTRIES);
|
||||||
|
@ -77,19 +78,19 @@ pgss_startup(void)
|
||||||
on_shmem_exit(pgss_shmem_shutdown, (Datum) 0);
|
on_shmem_exit(pgss_shmem_shutdown, (Datum) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pgssSharedState*
|
pgssSharedState *
|
||||||
pgsm_get_ss(void)
|
pgsm_get_ss(void)
|
||||||
{
|
{
|
||||||
return pgss;
|
return pgss;
|
||||||
}
|
}
|
||||||
|
|
||||||
HTAB*
|
HTAB *
|
||||||
pgsm_get_hash(void)
|
pgsm_get_hash(void)
|
||||||
{
|
{
|
||||||
return pgss_hash;
|
return pgss_hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
HTAB*
|
HTAB *
|
||||||
pgsm_get_query_hash(void)
|
pgsm_get_query_hash(void)
|
||||||
{
|
{
|
||||||
return pgss_query_hash;
|
return pgss_query_hash;
|
||||||
|
@ -117,7 +118,7 @@ pgss_shmem_shutdown(int code, Datum arg)
|
||||||
Size
|
Size
|
||||||
hash_memsize(void)
|
hash_memsize(void)
|
||||||
{
|
{
|
||||||
Size size;
|
Size size;
|
||||||
|
|
||||||
size = MAXALIGN(sizeof(pgssSharedState));
|
size = MAXALIGN(sizeof(pgssSharedState));
|
||||||
size += MAXALIGN(MAX_QUERY_BUF);
|
size += MAXALIGN(MAX_QUERY_BUF);
|
||||||
|
@ -130,7 +131,7 @@ hash_memsize(void)
|
||||||
pgssEntry *
|
pgssEntry *
|
||||||
hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key, int encoding)
|
hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key, int encoding)
|
||||||
{
|
{
|
||||||
pgssEntry *entry = NULL;
|
pgssEntry *entry = NULL;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
if (hash_get_num_entries(pgss_hash) >= MAX_BUCKET_ENTRIES)
|
if (hash_get_num_entries(pgss_hash) >= MAX_BUCKET_ENTRIES)
|
||||||
|
@ -164,7 +165,7 @@ hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key, int encoding)
|
||||||
* state is PGSS_FINISHED or PGSS_FINISHED).
|
* state is PGSS_FINISHED or PGSS_FINISHED).
|
||||||
* - Clear query buffer for new_bucket_id.
|
* - Clear query buffer for new_bucket_id.
|
||||||
* - If old_bucket_id != -1, move all pending hash table entries in
|
* - If old_bucket_id != -1, move all pending hash table entries in
|
||||||
* old_bucket_id to the new bucket id, also move pending queries from the
|
* old_bucket_id to the new bucket id, also move pending queries from the
|
||||||
* previous query buffer (query_buffer[old_bucket_id]) to the new one
|
* previous query buffer (query_buffer[old_bucket_id]) to the new one
|
||||||
* (query_buffer[new_bucket_id]).
|
* (query_buffer[new_bucket_id]).
|
||||||
*
|
*
|
||||||
|
@ -174,26 +175,30 @@ void
|
||||||
hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_buffer)
|
hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_buffer)
|
||||||
{
|
{
|
||||||
HASH_SEQ_STATUS hash_seq;
|
HASH_SEQ_STATUS hash_seq;
|
||||||
pgssEntry *entry = NULL;
|
pgssEntry *entry = NULL;
|
||||||
|
|
||||||
/* Store pending query ids from the previous bucket. */
|
/* Store pending query ids from the previous bucket. */
|
||||||
List *pending_entries = NIL;
|
List *pending_entries = NIL;
|
||||||
ListCell *pending_entry;
|
ListCell *pending_entry;
|
||||||
|
|
||||||
/* Iterate over the hash table. */
|
/* Iterate over the hash table. */
|
||||||
hash_seq_init(&hash_seq, pgss_hash);
|
hash_seq_init(&hash_seq, pgss_hash);
|
||||||
while ((entry = hash_seq_search(&hash_seq)) != NULL)
|
while ((entry = hash_seq_search(&hash_seq)) != NULL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Remove all entries if new_bucket_id == -1.
|
* Remove all entries if new_bucket_id == -1. Otherwise remove entry
|
||||||
* Otherwise remove entry in new_bucket_id if it has finished already.
|
* in new_bucket_id if it has finished already.
|
||||||
*/
|
*/
|
||||||
if (new_bucket_id < 0 ||
|
if (new_bucket_id < 0 ||
|
||||||
(entry->key.bucket_id == new_bucket_id &&
|
(entry->key.bucket_id == new_bucket_id &&
|
||||||
(entry->counters.state == PGSS_FINISHED || entry->counters.state == PGSS_ERROR)))
|
(entry->counters.state == PGSS_FINISHED || entry->counters.state == PGSS_ERROR)))
|
||||||
{
|
{
|
||||||
if (new_bucket_id == -1) {
|
if (new_bucket_id == -1)
|
||||||
/* pg_stat_monitor_reset(), remove entry from query hash table too. */
|
{
|
||||||
|
/*
|
||||||
|
* pg_stat_monitor_reset(), remove entry from query hash table
|
||||||
|
* too.
|
||||||
|
*/
|
||||||
hash_search(pgss_query_hash, &(entry->key.queryid), HASH_REMOVE, NULL);
|
hash_search(pgss_query_hash, &(entry->key.queryid), HASH_REMOVE, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,11 +206,10 @@ hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_bu
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we detect a pending query residing in the previous bucket id,
|
* If we detect a pending query residing in the previous bucket id, we
|
||||||
* we add it to a list of pending elements to be moved to the new
|
* add it to a list of pending elements to be moved to the new bucket
|
||||||
* bucket id.
|
* id. Can't update the hash table while iterating it inside this
|
||||||
* Can't update the hash table while iterating it inside this loop,
|
* loop, as this may introduce all sort of problems.
|
||||||
* as this may introduce all sort of problems.
|
|
||||||
*/
|
*/
|
||||||
if (old_bucket_id != -1 && entry->key.bucket_id == old_bucket_id)
|
if (old_bucket_id != -1 && entry->key.bucket_id == old_bucket_id)
|
||||||
{
|
{
|
||||||
|
@ -213,19 +217,23 @@ hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_bu
|
||||||
entry->counters.state == PGSS_PLAN ||
|
entry->counters.state == PGSS_PLAN ||
|
||||||
entry->counters.state == PGSS_EXEC)
|
entry->counters.state == PGSS_EXEC)
|
||||||
{
|
{
|
||||||
pgssEntry *bkp_entry = malloc(sizeof(pgssEntry));
|
pgssEntry *bkp_entry = malloc(sizeof(pgssEntry));
|
||||||
|
|
||||||
if (!bkp_entry)
|
if (!bkp_entry)
|
||||||
{
|
{
|
||||||
elog(DEBUG1, "hash_entry_dealloc: out of memory");
|
elog(DEBUG1, "hash_entry_dealloc: out of memory");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No memory, If the entry has calls > 1 then we change the state to finished,
|
* No memory, If the entry has calls > 1 then we change
|
||||||
* as the pending query will likely finish execution during the new bucket
|
* the state to finished, as the pending query will likely
|
||||||
* time window. The pending query will vanish in this case, can't list it
|
* finish execution during the new bucket time window. The
|
||||||
|
* pending query will vanish in this case, can't list it
|
||||||
* until it completes.
|
* until it completes.
|
||||||
*
|
*
|
||||||
* If there is only one call to the query and it's pending, remove the
|
* If there is only one call to the query and it's
|
||||||
* entry from the previous bucket and allow it to finish in the new bucket,
|
* pending, remove the entry from the previous bucket and
|
||||||
* in order to avoid the query living in the old bucket forever.
|
* allow it to finish in the new bucket, in order to avoid
|
||||||
|
* the query living in the old bucket forever.
|
||||||
*/
|
*/
|
||||||
if (entry->counters.calls.calls > 1)
|
if (entry->counters.calls.calls > 1)
|
||||||
entry->counters.state = PGSS_FINISHED;
|
entry->counters.state = PGSS_FINISHED;
|
||||||
|
@ -244,14 +252,16 @@ hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_bu
|
||||||
pending_entries = lappend(pending_entries, bkp_entry);
|
pending_entries = lappend(pending_entries, bkp_entry);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the entry has calls > 1 then we change the state to finished in
|
* If the entry has calls > 1 then we change the state to
|
||||||
* the previous bucket, as the pending query will likely finish execution
|
* finished in the previous bucket, as the pending query will
|
||||||
* during the new bucket time window. Can't remove it from the previous bucket
|
* likely finish execution during the new bucket time window.
|
||||||
* as it may have many calls and we would lose the query statistics.
|
* Can't remove it from the previous bucket as it may have
|
||||||
|
* many calls and we would lose the query statistics.
|
||||||
*
|
*
|
||||||
* If there is only one call to the query and it's pending, remove the entry
|
* If there is only one call to the query and it's pending,
|
||||||
* from the previous bucket and allow it to finish in the new bucket,
|
* remove the entry from the previous bucket and allow it to
|
||||||
* in order to avoid the query living in the old bucket forever.
|
* finish in the new bucket, in order to avoid the query
|
||||||
|
* living in the old bucket forever.
|
||||||
*/
|
*/
|
||||||
if (entry->counters.calls.calls > 1)
|
if (entry->counters.calls.calls > 1)
|
||||||
entry->counters.state = PGSS_FINISHED;
|
entry->counters.state = PGSS_FINISHED;
|
||||||
|
@ -262,13 +272,14 @@ hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_bu
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate over the list of pending queries in order
|
* Iterate over the list of pending queries in order to add them back to
|
||||||
* to add them back to the hash table with the updated bucket id.
|
* the hash table with the updated bucket id.
|
||||||
*/
|
*/
|
||||||
foreach (pending_entry, pending_entries) {
|
foreach(pending_entry, pending_entries)
|
||||||
bool found = false;
|
{
|
||||||
pgssEntry *new_entry;
|
bool found = false;
|
||||||
pgssEntry *old_entry = (pgssEntry *) lfirst(pending_entry);
|
pgssEntry *new_entry;
|
||||||
|
pgssEntry *old_entry = (pgssEntry *) lfirst(pending_entry);
|
||||||
|
|
||||||
new_entry = (pgssEntry *) hash_search(pgss_hash, &old_entry->key, HASH_ENTER_NULL, &found);
|
new_entry = (pgssEntry *) hash_search(pgss_hash, &old_entry->key, HASH_ENTER_NULL, &found);
|
||||||
if (new_entry == NULL)
|
if (new_entry == NULL)
|
||||||
|
@ -294,9 +305,9 @@ hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_bu
|
||||||
void
|
void
|
||||||
hash_entry_reset()
|
hash_entry_reset()
|
||||||
{
|
{
|
||||||
pgssSharedState *pgss = pgsm_get_ss();
|
pgssSharedState *pgss = pgsm_get_ss();
|
||||||
HASH_SEQ_STATUS hash_seq;
|
HASH_SEQ_STATUS hash_seq;
|
||||||
pgssEntry *entry;
|
pgssEntry *entry;
|
||||||
|
|
||||||
LWLockAcquire(pgss->lock, LW_EXCLUSIVE);
|
LWLockAcquire(pgss->lock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
|
|
1639
pg_stat_monitor.c
1639
pg_stat_monitor.c
File diff suppressed because it is too large
Load Diff
|
@ -104,27 +104,28 @@
|
||||||
#define MAX_ENUM_OPTIONS 6
|
#define MAX_ENUM_OPTIONS 6
|
||||||
typedef struct GucVariables
|
typedef struct GucVariables
|
||||||
{
|
{
|
||||||
enum config_type type; /* PGC_BOOL, PGC_INT, PGC_REAL, PGC_STRING, PGC_ENUM */
|
enum config_type type; /* PGC_BOOL, PGC_INT, PGC_REAL, PGC_STRING,
|
||||||
int guc_variable;
|
* PGC_ENUM */
|
||||||
char guc_name[TEXT_LEN];
|
int guc_variable;
|
||||||
char guc_desc[TEXT_LEN];
|
char guc_name[TEXT_LEN];
|
||||||
int guc_default;
|
char guc_desc[TEXT_LEN];
|
||||||
int guc_min;
|
int guc_default;
|
||||||
int guc_max;
|
int guc_min;
|
||||||
int guc_unit;
|
int guc_max;
|
||||||
int *guc_value;
|
int guc_unit;
|
||||||
bool guc_restart;
|
int *guc_value;
|
||||||
int n_options;
|
bool guc_restart;
|
||||||
char guc_options[MAX_ENUM_OPTIONS][32];
|
int n_options;
|
||||||
} GucVariable;
|
char guc_options[MAX_ENUM_OPTIONS][32];
|
||||||
|
} GucVariable;
|
||||||
|
|
||||||
|
|
||||||
#if PG_VERSION_NUM < 130000
|
#if PG_VERSION_NUM < 130000
|
||||||
typedef struct WalUsage
|
typedef struct WalUsage
|
||||||
{
|
{
|
||||||
long wal_records; /* # of WAL records produced */
|
long wal_records; /* # of WAL records produced */
|
||||||
long wal_fpi; /* # of WAL full page images produced */
|
long wal_fpi; /* # of WAL full page images produced */
|
||||||
uint64 wal_bytes; /* size of WAL records produced */
|
uint64 wal_bytes; /* size of WAL records produced */
|
||||||
} WalUsage;
|
} WalUsage;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -132,7 +133,7 @@ typedef enum OVERFLOW_TARGET
|
||||||
{
|
{
|
||||||
OVERFLOW_TARGET_NONE = 0,
|
OVERFLOW_TARGET_NONE = 0,
|
||||||
OVERFLOW_TARGET_DISK
|
OVERFLOW_TARGET_DISK
|
||||||
} OVERFLOW_TARGET;
|
} OVERFLOW_TARGET;
|
||||||
|
|
||||||
typedef enum pgssStoreKind
|
typedef enum pgssStoreKind
|
||||||
{
|
{
|
||||||
|
@ -163,19 +164,19 @@ typedef enum AGG_KEY
|
||||||
AGG_KEY_DATABASE = 0,
|
AGG_KEY_DATABASE = 0,
|
||||||
AGG_KEY_USER,
|
AGG_KEY_USER,
|
||||||
AGG_KEY_HOST
|
AGG_KEY_HOST
|
||||||
} AGG_KEY;
|
} AGG_KEY;
|
||||||
|
|
||||||
#define MAX_QUERY_LEN 1024
|
#define MAX_QUERY_LEN 1024
|
||||||
|
|
||||||
/* shared memory storage for the query */
|
/* shared memory storage for the query */
|
||||||
typedef struct CallTime
|
typedef struct CallTime
|
||||||
{
|
{
|
||||||
double total_time; /* total execution time, in msec */
|
double total_time; /* total execution time, in msec */
|
||||||
double min_time; /* minimum execution time in msec */
|
double min_time; /* minimum execution time in msec */
|
||||||
double max_time; /* maximum execution time in msec */
|
double max_time; /* maximum execution time in msec */
|
||||||
double mean_time; /* mean execution time in msec */
|
double mean_time; /* mean execution time in msec */
|
||||||
double sum_var_time; /* sum of variances in execution time in msec */
|
double sum_var_time; /* sum of variances in execution time in msec */
|
||||||
} CallTime;
|
} CallTime;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Entry type for queries hash table (query ID).
|
* Entry type for queries hash table (query ID).
|
||||||
|
@ -188,16 +189,16 @@ typedef struct CallTime
|
||||||
*/
|
*/
|
||||||
typedef struct pgssQueryEntry
|
typedef struct pgssQueryEntry
|
||||||
{
|
{
|
||||||
uint64 queryid; /* query identifier, also the key. */
|
uint64 queryid; /* query identifier, also the key. */
|
||||||
size_t query_pos; /* query location within query buffer */
|
size_t query_pos; /* query location within query buffer */
|
||||||
} pgssQueryEntry;
|
} pgssQueryEntry;
|
||||||
|
|
||||||
typedef struct PlanInfo
|
typedef struct PlanInfo
|
||||||
{
|
{
|
||||||
uint64 planid; /* plan identifier */
|
uint64 planid; /* plan identifier */
|
||||||
char plan_text[PLAN_TEXT_LEN]; /* plan text */
|
char plan_text[PLAN_TEXT_LEN]; /* plan text */
|
||||||
size_t plan_len; /* strlen(plan_text) */
|
size_t plan_len; /* strlen(plan_text) */
|
||||||
} PlanInfo;
|
} PlanInfo;
|
||||||
|
|
||||||
typedef struct pgssHashKey
|
typedef struct pgssHashKey
|
||||||
{
|
{
|
||||||
|
@ -208,63 +209,66 @@ typedef struct pgssHashKey
|
||||||
uint64 ip; /* client ip address */
|
uint64 ip; /* client ip address */
|
||||||
uint64 planid; /* plan identifier */
|
uint64 planid; /* plan identifier */
|
||||||
uint64 appid; /* hash of application name */
|
uint64 appid; /* hash of application name */
|
||||||
uint64 toplevel; /* query executed at top level */
|
uint64 toplevel; /* query executed at top level */
|
||||||
} pgssHashKey;
|
} pgssHashKey;
|
||||||
|
|
||||||
typedef struct QueryInfo
|
typedef struct QueryInfo
|
||||||
{
|
{
|
||||||
uint64 parentid; /* parent queryid of current query*/
|
uint64 parentid; /* parent queryid of current query */
|
||||||
int64 type; /* type of query, options are query, info, warning, error, fatal */
|
int64 type; /* type of query, options are query, info,
|
||||||
|
* warning, error, fatal */
|
||||||
char application_name[APPLICATIONNAME_LEN];
|
char application_name[APPLICATIONNAME_LEN];
|
||||||
char comments[COMMENTS_LEN];
|
char comments[COMMENTS_LEN];
|
||||||
char relations[REL_LST][REL_LEN]; /* List of relation involved in the query */
|
char relations[REL_LST][REL_LEN]; /* List of relation involved
|
||||||
int num_relations; /* Number of relation in the query */
|
* in the query */
|
||||||
CmdType cmd_type; /* query command type SELECT/UPDATE/DELETE/INSERT */
|
int num_relations; /* Number of relation in the query */
|
||||||
|
CmdType cmd_type; /* query command type
|
||||||
|
* SELECT/UPDATE/DELETE/INSERT */
|
||||||
} QueryInfo;
|
} QueryInfo;
|
||||||
|
|
||||||
typedef struct ErrorInfo
|
typedef struct ErrorInfo
|
||||||
{
|
{
|
||||||
int64 elevel; /* error elevel */
|
int64 elevel; /* error elevel */
|
||||||
char sqlcode[SQLCODE_LEN]; /* error sqlcode */
|
char sqlcode[SQLCODE_LEN]; /* error sqlcode */
|
||||||
char message[ERROR_MESSAGE_LEN]; /* error message text */
|
char message[ERROR_MESSAGE_LEN]; /* error message text */
|
||||||
} ErrorInfo;
|
} ErrorInfo;
|
||||||
|
|
||||||
typedef struct Calls
|
typedef struct Calls
|
||||||
{
|
{
|
||||||
int64 calls; /* # of times executed */
|
int64 calls; /* # of times executed */
|
||||||
int64 rows; /* total # of retrieved or affected rows */
|
int64 rows; /* total # of retrieved or affected rows */
|
||||||
double usage; /* usage factor */
|
double usage; /* usage factor */
|
||||||
} Calls;
|
} Calls;
|
||||||
|
|
||||||
|
|
||||||
typedef struct Blocks
|
typedef struct Blocks
|
||||||
{
|
{
|
||||||
int64 shared_blks_hit; /* # of shared buffer hits */
|
int64 shared_blks_hit; /* # of shared buffer hits */
|
||||||
int64 shared_blks_read; /* # of shared disk blocks read */
|
int64 shared_blks_read; /* # of shared disk blocks read */
|
||||||
int64 shared_blks_dirtied; /* # of shared disk blocks dirtied */
|
int64 shared_blks_dirtied; /* # of shared disk blocks dirtied */
|
||||||
int64 shared_blks_written; /* # of shared disk blocks written */
|
int64 shared_blks_written; /* # of shared disk blocks written */
|
||||||
int64 local_blks_hit; /* # of local buffer hits */
|
int64 local_blks_hit; /* # of local buffer hits */
|
||||||
int64 local_blks_read; /* # of local disk blocks read */
|
int64 local_blks_read; /* # of local disk blocks read */
|
||||||
int64 local_blks_dirtied; /* # of local disk blocks dirtied */
|
int64 local_blks_dirtied; /* # of local disk blocks dirtied */
|
||||||
int64 local_blks_written; /* # of local disk blocks written */
|
int64 local_blks_written; /* # of local disk blocks written */
|
||||||
int64 temp_blks_read; /* # of temp blocks read */
|
int64 temp_blks_read; /* # of temp blocks read */
|
||||||
int64 temp_blks_written; /* # of temp blocks written */
|
int64 temp_blks_written; /* # of temp blocks written */
|
||||||
double blk_read_time; /* time spent reading, in msec */
|
double blk_read_time; /* time spent reading, in msec */
|
||||||
double blk_write_time; /* time spent writing, in msec */
|
double blk_write_time; /* time spent writing, in msec */
|
||||||
} Blocks;
|
} Blocks;
|
||||||
|
|
||||||
typedef struct SysInfo
|
typedef struct SysInfo
|
||||||
{
|
{
|
||||||
float utime; /* user cpu time */
|
float utime; /* user cpu time */
|
||||||
float stime; /* system cpu time */
|
float stime; /* system cpu time */
|
||||||
} SysInfo;
|
} SysInfo;
|
||||||
|
|
||||||
typedef struct Wal_Usage
|
typedef struct Wal_Usage
|
||||||
{
|
{
|
||||||
int64 wal_records; /* # of WAL records generated */
|
int64 wal_records; /* # of WAL records generated */
|
||||||
int64 wal_fpi; /* # of WAL full page images generated */
|
int64 wal_fpi; /* # of WAL full page images generated */
|
||||||
uint64 wal_bytes; /* total amount of WAL bytes generated */
|
uint64 wal_bytes; /* total amount of WAL bytes generated */
|
||||||
} Wal_Usage;
|
} Wal_Usage;
|
||||||
|
|
||||||
typedef struct Counters
|
typedef struct Counters
|
||||||
{
|
{
|
||||||
|
@ -275,14 +279,15 @@ typedef struct Counters
|
||||||
|
|
||||||
Calls plancalls;
|
Calls plancalls;
|
||||||
CallTime plantime;
|
CallTime plantime;
|
||||||
PlanInfo planinfo;
|
PlanInfo planinfo;
|
||||||
|
|
||||||
Blocks blocks;
|
Blocks blocks;
|
||||||
SysInfo sysinfo;
|
SysInfo sysinfo;
|
||||||
ErrorInfo error;
|
ErrorInfo error;
|
||||||
Wal_Usage walusage;
|
Wal_Usage walusage;
|
||||||
int resp_calls[MAX_RESPONSE_BUCKET]; /* execution time's in msec */
|
int resp_calls[MAX_RESPONSE_BUCKET]; /* execution time's in
|
||||||
uint64 state; /* query state */
|
* msec */
|
||||||
|
uint64 state; /* query state */
|
||||||
} Counters;
|
} Counters;
|
||||||
|
|
||||||
/* Some global structure to get the cpu usage, really don't like the idea of global variable */
|
/* Some global structure to get the cpu usage, really don't like the idea of global variable */
|
||||||
|
@ -292,11 +297,11 @@ typedef struct Counters
|
||||||
*/
|
*/
|
||||||
typedef struct pgssEntry
|
typedef struct pgssEntry
|
||||||
{
|
{
|
||||||
pgssHashKey key; /* hash key of entry - MUST BE FIRST */
|
pgssHashKey key; /* hash key of entry - MUST BE FIRST */
|
||||||
Counters counters; /* the statistics for this query */
|
Counters counters; /* the statistics for this query */
|
||||||
int encoding; /* query text encoding */
|
int encoding; /* query text encoding */
|
||||||
slock_t mutex; /* protects the counters only */
|
slock_t mutex; /* protects the counters only */
|
||||||
size_t query_pos; /* query location within query buffer */
|
size_t query_pos; /* query location within query buffer */
|
||||||
} pgssEntry;
|
} pgssEntry;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -304,30 +309,33 @@ typedef struct pgssEntry
|
||||||
*/
|
*/
|
||||||
typedef struct pgssSharedState
|
typedef struct pgssSharedState
|
||||||
{
|
{
|
||||||
LWLock *lock; /* protects hashtable search/modification */
|
LWLock *lock; /* protects hashtable search/modification */
|
||||||
double cur_median_usage; /* current median usage in hashtable */
|
double cur_median_usage; /* current median usage in hashtable */
|
||||||
slock_t mutex; /* protects following fields only: */
|
slock_t mutex; /* protects following fields only: */
|
||||||
Size extent; /* current extent of query file */
|
Size extent; /* current extent of query file */
|
||||||
int64 n_writers; /* number of active writers to query file */
|
int64 n_writers; /* number of active writers to query file */
|
||||||
pg_atomic_uint64 current_wbucket;
|
pg_atomic_uint64 current_wbucket;
|
||||||
pg_atomic_uint64 prev_bucket_sec;
|
pg_atomic_uint64 prev_bucket_sec;
|
||||||
uint64 bucket_entry[MAX_BUCKETS];
|
uint64 bucket_entry[MAX_BUCKETS];
|
||||||
char bucket_start_time[MAX_BUCKETS][60]; /* start time of the bucket */
|
char bucket_start_time[MAX_BUCKETS][60]; /* start time of the
|
||||||
LWLock *errors_lock; /* protects errors hashtable search/modification */
|
* bucket */
|
||||||
|
LWLock *errors_lock; /* protects errors hashtable
|
||||||
|
* search/modification */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These variables are used when pgsm_overflow_target is ON.
|
* These variables are used when pgsm_overflow_target is ON.
|
||||||
*
|
*
|
||||||
* overflow is set to true when the query buffer overflows.
|
* overflow is set to true when the query buffer overflows.
|
||||||
*
|
*
|
||||||
* n_bucket_cycles counts the number of times we changed bucket
|
* n_bucket_cycles counts the number of times we changed bucket since the
|
||||||
* since the query buffer overflowed. When it reaches pgsm_max_buckets
|
* query buffer overflowed. When it reaches pgsm_max_buckets we remove the
|
||||||
* we remove the dump file, also reset the counter.
|
* dump file, also reset the counter.
|
||||||
*
|
*
|
||||||
* This allows us to avoid having a large file on disk that would also
|
* This allows us to avoid having a large file on disk that would also
|
||||||
* slowdown queries to the pg_stat_monitor view.
|
* slowdown queries to the pg_stat_monitor view.
|
||||||
*/
|
*/
|
||||||
bool overflow;
|
bool overflow;
|
||||||
size_t n_bucket_cycles;
|
size_t n_bucket_cycles;
|
||||||
} pgssSharedState;
|
} pgssSharedState;
|
||||||
|
|
||||||
#define ResetSharedState(x) \
|
#define ResetSharedState(x) \
|
||||||
|
@ -350,6 +358,7 @@ typedef struct LocationLen
|
||||||
int location; /* start offset in query text */
|
int location; /* start offset in query text */
|
||||||
int length; /* length in bytes, or -1 to ignore */
|
int length; /* length in bytes, or -1 to ignore */
|
||||||
} LocationLen;
|
} LocationLen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Working state for computing a query jumble and producing a normalized
|
* Working state for computing a query jumble and producing a normalized
|
||||||
* query string
|
* query string
|
||||||
|
@ -378,54 +387,56 @@ typedef struct JumbleState
|
||||||
|
|
||||||
/* Links to shared memory state */
|
/* Links to shared memory state */
|
||||||
|
|
||||||
bool SaveQueryText(uint64 bucketid,
|
bool SaveQueryText(uint64 bucketid,
|
||||||
uint64 queryid,
|
uint64 queryid,
|
||||||
unsigned char *buf,
|
unsigned char *buf,
|
||||||
const char *query,
|
const char *query,
|
||||||
uint64 query_len,
|
uint64 query_len,
|
||||||
size_t *query_pos);
|
size_t *query_pos);
|
||||||
|
|
||||||
/* guc.c */
|
/* guc.c */
|
||||||
void init_guc(void);
|
void init_guc(void);
|
||||||
GucVariable *get_conf(int i);
|
GucVariable *get_conf(int i);
|
||||||
|
|
||||||
/* hash_create.c */
|
/* hash_create.c */
|
||||||
bool IsHashInitialize(void);
|
bool IsHashInitialize(void);
|
||||||
void pgss_shmem_startup(void);
|
void pgss_shmem_startup(void);
|
||||||
void pgss_shmem_shutdown(int code, Datum arg);
|
void pgss_shmem_shutdown(int code, Datum arg);
|
||||||
int pgsm_get_bucket_size(void);
|
int pgsm_get_bucket_size(void);
|
||||||
pgssSharedState* pgsm_get_ss(void);
|
pgssSharedState *pgsm_get_ss(void);
|
||||||
HTAB *pgsm_get_plan_hash(void);
|
HTAB *pgsm_get_plan_hash(void);
|
||||||
HTAB *pgsm_get_hash(void);
|
HTAB *pgsm_get_hash(void);
|
||||||
HTAB *pgsm_get_query_hash(void);
|
HTAB *pgsm_get_query_hash(void);
|
||||||
HTAB *pgsm_get_plan_hash(void);
|
HTAB *pgsm_get_plan_hash(void);
|
||||||
void hash_entry_reset(void);
|
void hash_entry_reset(void);
|
||||||
void hash_query_entryies_reset(void);
|
void hash_query_entryies_reset(void);
|
||||||
void hash_query_entries();
|
void hash_query_entries();
|
||||||
void hash_query_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_buffer[]);
|
void hash_query_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_buffer[]);
|
||||||
void hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_buffer);
|
void hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_buffer);
|
||||||
pgssEntry* hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key, int encoding);
|
pgssEntry *hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key, int encoding);
|
||||||
Size hash_memsize(void);
|
Size hash_memsize(void);
|
||||||
|
|
||||||
int read_query_buffer(int bucket_id, uint64 queryid, char *query_txt, size_t pos);
|
int read_query_buffer(int bucket_id, uint64 queryid, char *query_txt, size_t pos);
|
||||||
uint64 read_query(unsigned char *buf, uint64 queryid, char * query, size_t pos);
|
uint64 read_query(unsigned char *buf, uint64 queryid, char *query, size_t pos);
|
||||||
void pgss_startup(void);
|
void pgss_startup(void);
|
||||||
void set_qbuf(unsigned char *);
|
void set_qbuf(unsigned char *);
|
||||||
|
|
||||||
/* hash_query.c */
|
/* hash_query.c */
|
||||||
void pgss_startup(void);
|
void pgss_startup(void);
|
||||||
|
|
||||||
/*---- GUC variables ----*/
|
/*---- GUC variables ----*/
|
||||||
typedef enum {
|
typedef enum
|
||||||
PSGM_TRACK_NONE = 0, /* track no statements */
|
{
|
||||||
PGSM_TRACK_TOP, /* only top level statements */
|
PSGM_TRACK_NONE = 0, /* track no statements */
|
||||||
PGSM_TRACK_ALL /* all statements, including nested ones */
|
PGSM_TRACK_TOP, /* only top level statements */
|
||||||
} PGSMTrackLevel;
|
PGSM_TRACK_ALL /* all statements, including nested ones */
|
||||||
|
} PGSMTrackLevel;
|
||||||
static const struct config_enum_entry track_options[] =
|
static const struct config_enum_entry track_options[] =
|
||||||
{
|
{
|
||||||
{"none", PSGM_TRACK_NONE, false},
|
{"none", PSGM_TRACK_NONE, false},
|
||||||
{"top", PGSM_TRACK_TOP, false},
|
{"top", PGSM_TRACK_TOP, false},
|
||||||
{"all", PGSM_TRACK_ALL, false},
|
{"all", PGSM_TRACK_ALL, false},
|
||||||
{NULL, 0, false}
|
{NULL, 0, false}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PGSM_MAX get_conf(0)->guc_variable
|
#define PGSM_MAX get_conf(0)->guc_variable
|
||||||
|
@ -447,12 +458,13 @@ static const struct config_enum_entry track_options[] =
|
||||||
|
|
||||||
/*---- Benchmarking ----*/
|
/*---- Benchmarking ----*/
|
||||||
#ifdef BENCHMARK
|
#ifdef BENCHMARK
|
||||||
/*
|
/*
|
||||||
* These enumerator values are used as index in the hook stats array.
|
* These enumerator values are used as index in the hook stats array.
|
||||||
* STATS_START and STATS_END are used only to delimit the range.
|
* STATS_START and STATS_END are used only to delimit the range.
|
||||||
* STATS_END is also the length of the valid items in the enum.
|
* STATS_END is also the length of the valid items in the enum.
|
||||||
*/
|
*/
|
||||||
enum pg_hook_stats_id {
|
enum pg_hook_stats_id
|
||||||
|
{
|
||||||
STATS_START = -1,
|
STATS_START = -1,
|
||||||
STATS_PGSS_POST_PARSE_ANALYZE,
|
STATS_PGSS_POST_PARSE_ANALYZE,
|
||||||
STATS_PGSS_EXECUTORSTART,
|
STATS_PGSS_EXECUTORSTART,
|
||||||
|
@ -469,21 +481,22 @@ enum pg_hook_stats_id {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Hold time to execute statistics for a hook. */
|
/* Hold time to execute statistics for a hook. */
|
||||||
struct pg_hook_stats_t {
|
struct pg_hook_stats_t
|
||||||
char hook_name[64];
|
{
|
||||||
double min_time;
|
char hook_name[64];
|
||||||
double max_time;
|
double min_time;
|
||||||
double total_time;
|
double max_time;
|
||||||
uint64 ncalls;
|
double total_time;
|
||||||
|
uint64 ncalls;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HOOK_STATS_SIZE MAXALIGN((size_t)STATS_END * sizeof(struct pg_hook_stats_t))
|
#define HOOK_STATS_SIZE MAXALIGN((size_t)STATS_END * sizeof(struct pg_hook_stats_t))
|
||||||
|
|
||||||
/* Allocate a pg_hook_stats_t array of size HOOK_STATS_SIZE on shared memory. */
|
/* Allocate a pg_hook_stats_t array of size HOOK_STATS_SIZE on shared memory. */
|
||||||
void init_hook_stats(void);
|
void init_hook_stats(void);
|
||||||
|
|
||||||
/* Update hook time execution statistics. */
|
/* Update hook time execution statistics. */
|
||||||
void update_hook_stats(enum pg_hook_stats_id hook_id, double time_elapsed);
|
void update_hook_stats(enum pg_hook_stats_id hook_id, double time_elapsed);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macro used to declare a hook function:
|
* Macro used to declare a hook function:
|
||||||
|
@ -509,7 +522,7 @@ void update_hook_stats(enum pg_hook_stats_id hook_id, double time_elapsed);
|
||||||
*/
|
*/
|
||||||
#define HOOK(name) name##_benchmark
|
#define HOOK(name) name##_benchmark
|
||||||
|
|
||||||
#else /* #ifdef BENCHMARK */
|
#else /* #ifdef BENCHMARK */
|
||||||
|
|
||||||
#define DECLARE_HOOK(hook, ...) \
|
#define DECLARE_HOOK(hook, ...) \
|
||||||
static hook(__VA_ARGS__);
|
static hook(__VA_ARGS__);
|
||||||
|
|
|
@ -44,13 +44,14 @@ PG_FUNCTION_INFO_V1(pg_stat_monitor_reset_errors);
|
||||||
|
|
||||||
static HTAB *pgsm_errors_ht = NULL;
|
static HTAB *pgsm_errors_ht = NULL;
|
||||||
|
|
||||||
void psgm_errors_init(void)
|
void
|
||||||
|
psgm_errors_init(void)
|
||||||
{
|
{
|
||||||
HASHCTL info;
|
HASHCTL info;
|
||||||
#if PG_VERSION_NUM >= 140000
|
#if PG_VERSION_NUM >= 140000
|
||||||
int flags = HASH_ELEM | HASH_STRINGS;
|
int flags = HASH_ELEM | HASH_STRINGS;
|
||||||
#else
|
#else
|
||||||
int flags = HASH_ELEM | HASH_BLOBS;
|
int flags = HASH_ELEM | HASH_BLOBS;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,26 +59,28 @@ void psgm_errors_init(void)
|
||||||
info.keysize = ERROR_MSG_MAX_LEN;
|
info.keysize = ERROR_MSG_MAX_LEN;
|
||||||
info.entrysize = sizeof(ErrorEntry);
|
info.entrysize = sizeof(ErrorEntry);
|
||||||
pgsm_errors_ht = ShmemInitHash("pg_stat_monitor: errors hashtable",
|
pgsm_errors_ht = ShmemInitHash("pg_stat_monitor: errors hashtable",
|
||||||
PSGM_ERRORS_MAX, /* initial size */
|
PSGM_ERRORS_MAX, /* initial size */
|
||||||
PSGM_ERRORS_MAX, /* maximum size */
|
PSGM_ERRORS_MAX, /* maximum size */
|
||||||
&info,
|
&info,
|
||||||
flags);
|
flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t pgsm_errors_size(void)
|
size_t
|
||||||
|
pgsm_errors_size(void)
|
||||||
{
|
{
|
||||||
return hash_estimate_size(PSGM_ERRORS_MAX, sizeof(ErrorEntry));
|
return hash_estimate_size(PSGM_ERRORS_MAX, sizeof(ErrorEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pgsm_log(PgsmLogSeverity severity, const char *format, ...)
|
void
|
||||||
|
pgsm_log(PgsmLogSeverity severity, const char *format,...)
|
||||||
{
|
{
|
||||||
char key[ERROR_MSG_MAX_LEN];
|
char key[ERROR_MSG_MAX_LEN];
|
||||||
ErrorEntry *entry;
|
ErrorEntry *entry;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int n;
|
int n;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
struct tm *lt;
|
struct tm *lt;
|
||||||
pgssSharedState *pgss;
|
pgssSharedState *pgss;
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
|
@ -94,9 +97,10 @@ void pgsm_log(PgsmLogSeverity severity, const char *format, ...)
|
||||||
if (!entry)
|
if (!entry)
|
||||||
{
|
{
|
||||||
LWLockRelease(pgss->errors_lock);
|
LWLockRelease(pgss->errors_lock);
|
||||||
/*
|
|
||||||
* We're out of memory, can't track this error message.
|
/*
|
||||||
*/
|
* We're out of memory, can't track this error message.
|
||||||
|
*/
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,13 +114,13 @@ void pgsm_log(PgsmLogSeverity severity, const char *format, ...)
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
lt = localtime(&tv.tv_sec);
|
lt = localtime(&tv.tv_sec);
|
||||||
snprintf(entry->time, sizeof(entry->time),
|
snprintf(entry->time, sizeof(entry->time),
|
||||||
"%04d-%02d-%02d %02d:%02d:%02d",
|
"%04d-%02d-%02d %02d:%02d:%02d",
|
||||||
lt->tm_year + 1900,
|
lt->tm_year + 1900,
|
||||||
lt->tm_mon + 1,
|
lt->tm_mon + 1,
|
||||||
lt->tm_mday,
|
lt->tm_mday,
|
||||||
lt->tm_hour,
|
lt->tm_hour,
|
||||||
lt->tm_min,
|
lt->tm_min,
|
||||||
lt->tm_sec);
|
lt->tm_sec);
|
||||||
|
|
||||||
entry->calls++;
|
entry->calls++;
|
||||||
|
|
||||||
|
@ -129,15 +133,15 @@ void pgsm_log(PgsmLogSeverity severity, const char *format, ...)
|
||||||
Datum
|
Datum
|
||||||
pg_stat_monitor_reset_errors(PG_FUNCTION_ARGS)
|
pg_stat_monitor_reset_errors(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
HASH_SEQ_STATUS hash_seq;
|
HASH_SEQ_STATUS hash_seq;
|
||||||
ErrorEntry *entry;
|
ErrorEntry *entry;
|
||||||
pgssSharedState *pgss = pgsm_get_ss();
|
pgssSharedState *pgss = pgsm_get_ss();
|
||||||
|
|
||||||
/* Safety check... */
|
/* Safety check... */
|
||||||
if (!IsSystemInitialized())
|
if (!IsSystemInitialized())
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||||
errmsg("pg_stat_monitor: must be loaded via shared_preload_libraries")));
|
errmsg("pg_stat_monitor: must be loaded via shared_preload_libraries")));
|
||||||
|
|
||||||
LWLockAcquire(pgss->errors_lock, LW_EXCLUSIVE);
|
LWLockAcquire(pgss->errors_lock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
|
@ -157,26 +161,26 @@ pg_stat_monitor_reset_errors(PG_FUNCTION_ARGS)
|
||||||
Datum
|
Datum
|
||||||
pg_stat_monitor_errors(PG_FUNCTION_ARGS)
|
pg_stat_monitor_errors(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
|
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||||
TupleDesc tupdesc;
|
TupleDesc tupdesc;
|
||||||
Tuplestorestate *tupstore;
|
Tuplestorestate *tupstore;
|
||||||
MemoryContext per_query_ctx;
|
MemoryContext per_query_ctx;
|
||||||
MemoryContext oldcontext;
|
MemoryContext oldcontext;
|
||||||
HASH_SEQ_STATUS hash_seq;
|
HASH_SEQ_STATUS hash_seq;
|
||||||
ErrorEntry *error_entry;
|
ErrorEntry *error_entry;
|
||||||
pgssSharedState *pgss = pgsm_get_ss();
|
pgssSharedState *pgss = pgsm_get_ss();
|
||||||
|
|
||||||
/* Safety check... */
|
/* Safety check... */
|
||||||
if (!IsSystemInitialized())
|
if (!IsSystemInitialized())
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||||
errmsg("pg_stat_monitor: must be loaded via shared_preload_libraries")));
|
errmsg("pg_stat_monitor: must be loaded via shared_preload_libraries")));
|
||||||
|
|
||||||
/* check to see if caller supports us returning a tuplestore */
|
/* check to see if caller supports us returning a tuplestore */
|
||||||
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
|
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("pg_stat_monitor: set-valued function called in context that cannot accept a set")));
|
errmsg("pg_stat_monitor: set-valued function called in context that cannot accept a set")));
|
||||||
|
|
||||||
/* Switch into long-lived context to construct returned data structures */
|
/* Switch into long-lived context to construct returned data structures */
|
||||||
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
|
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
|
||||||
|
@ -204,6 +208,7 @@ pg_stat_monitor_errors(PG_FUNCTION_ARGS)
|
||||||
Datum values[4];
|
Datum values[4];
|
||||||
bool nulls[4];
|
bool nulls[4];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
memset(values, 0, sizeof(values));
|
memset(values, 0, sizeof(values));
|
||||||
memset(nulls, 0, sizeof(nulls));
|
memset(nulls, 0, sizeof(nulls));
|
||||||
|
|
||||||
|
@ -219,5 +224,5 @@ pg_stat_monitor_errors(PG_FUNCTION_ARGS)
|
||||||
/* clean up and return the tuplestore */
|
/* clean up and return the tuplestore */
|
||||||
tuplestore_donestoring(tupstore);
|
tuplestore_donestoring(tupstore);
|
||||||
|
|
||||||
return (Datum)0;
|
return (Datum) 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue