0003-Add-ANALYZE-OSCACHE-VERBOSE-relation.patch
text/x-patch
Filename: 0003-Add-ANALYZE-OSCACHE-VERBOSE-relation.patch
Type: text/x-patch
Part: 2
From 76ed77241453adfb10894eed6b03ea799a36923b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Villemain?= <cedric@2ndquadrant.fr>
Date: Thu, 26 May 2011 00:35:13 +0200
Subject: [PATCH 3/7] Add "ANALYZE OSCACHE [VERBOSE] [relation];"
it updates the oscache column in pg_class
with, currently, dummy functions
---
src/backend/commands/analyze.c | 124 ++++++++++++++++++++++++++++++++++-
src/backend/parser/gram.y | 22 +++++--
src/backend/storage/buffer/bufmgr.c | 13 ++++
src/include/nodes/parsenodes.h | 3 +-
src/include/parser/kwlist.h | 1 +
src/include/storage/bufmgr.h | 2 +
6 files changed, 156 insertions(+), 9 deletions(-)
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
new file mode 100644
index 57188bc..a78f46c
*** a/src/backend/commands/analyze.c
--- b/src/backend/commands/analyze.c
*************** static BufferAccessStrategy vac_strategy
*** 85,90 ****
--- 85,91 ----
static void do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, bool inh);
+ static void do_oscache_analyze_rel(Relation onerel, bool inh);
static void BlockSampler_Init(BlockSampler bs, BlockNumber nblocks,
int samplesize);
static bool BlockSampler_HasMore(BlockSampler bs);
*************** analyze_rel(Oid relid, VacuumStmt *vacst
*** 228,240 ****
/*
* Do the normal non-recursive ANALYZE.
*/
! do_analyze_rel(onerel, vacstmt, false);
/*
* If there are child tables, do recursive ANALYZE.
*/
if (onerel->rd_rel->relhassubclass)
! do_analyze_rel(onerel, vacstmt, true);
/*
* Close source relation now, but keep lock so that no one deletes it
--- 229,249 ----
/*
* Do the normal non-recursive ANALYZE.
*/
! if (vacstmt->options & (VACOPT_OSCACHE))
! do_oscache_analyze_rel(onerel, false);
! else
! do_analyze_rel(onerel, vacstmt, false);
/*
* If there are child tables, do recursive ANALYZE.
*/
if (onerel->rd_rel->relhassubclass)
! {
! if (vacstmt->options & (VACOPT_OSCACHE))
! do_oscache_analyze_rel(onerel, true);
! else
! do_analyze_rel(onerel, vacstmt, true);
! }
/*
* Close source relation now, but keep lock so that no one deletes it
*************** cleanup:
*** 623,628 ****
--- 632,748 ----
/* Restore current context and release memory */
MemoryContextSwitchTo(caller_context);
+ MemoryContextDelete(anl_context);
+ anl_context = NULL;
+ }
+
+ /*
+ * do_analyze_rel() -- analyze one relation, recursively or not
+ */
+ static void
+ do_oscache_analyze_rel(Relation onerel, bool inh)
+ {
+ int ind;
+ Relation *Irel;
+ int nindexes;
+ bool hasindex;
+ AnlIndexData *indexdata;
+ PGRUsage ru0;
+ TimestampTz starttime = 0;
+ MemoryContext caller_context;
+ int save_nestlevel;
+
+ if (inh)
+ ereport(elevel,
+ (errmsg("cache analyzing \"%s.%s\" inheritance tree",
+ get_namespace_name(RelationGetNamespace(onerel)),
+ RelationGetRelationName(onerel))));
+ else
+ ereport(elevel,
+ (errmsg("cache analyzing \"%s.%s\"",
+ get_namespace_name(RelationGetNamespace(onerel)),
+ RelationGetRelationName(onerel))));
+
+ /*
+ * Set up a working context so that we can easily free whatever junk gets
+ * created.
+ */
+ anl_context = AllocSetContextCreate(CurrentMemoryContext,
+ "Analyze",
+ ALLOCSET_DEFAULT_MINSIZE,
+ ALLOCSET_DEFAULT_INITSIZE,
+ ALLOCSET_DEFAULT_MAXSIZE);
+ caller_context = MemoryContextSwitchTo(anl_context);
+
+ /*
+ * Arrange to make GUC variable changes local to this command.
+ */
+ save_nestlevel = NewGUCNestLevel();
+
+ /* measure elapsed time iff autovacuum logging requires it */
+ if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
+ {
+ pg_rusage_init(&ru0);
+ if (Log_autovacuum_min_duration > 0)
+ starttime = GetCurrentTimestamp();
+ }
+
+ /*
+ * Open all indexes of the relation, and see if there are any analyzable
+ * columns in the indexes. We do not analyze index columns if there was
+ * an explicit column list in the ANALYZE command, however. If we are
+ * doing a recursive scan, we don't want to touch the parent's indexes at
+ * all.
+ */
+ if (!inh)
+ vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel);
+ else
+ {
+ Irel = NULL;
+ nindexes = 0;
+ }
+ hasindex = (nindexes > 0);
+ indexdata = NULL;
+
+ /*
+ * Update cache stats in pg_class.
+ */
+ oscache_update_relstats(onerel,
+ RelationGetRelationOSCacheInFork(onerel, MAIN_FORKNUM),
+ InvalidTransactionId);
+
+ /*
+ * Same for indexes.
+ */
+ for (ind = 0; ind < nindexes; ind++)
+ {
+ oscache_update_relstats(Irel[ind],
+ RelationGetRelationOSCacheInFork(Irel[ind], MAIN_FORKNUM),
+ InvalidTransactionId);
+ }
+
+ /* Done with indexes */
+ vac_close_indexes(nindexes, Irel, NoLock);
+
+ /* Log the action if appropriate */
+ if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
+ {
+ if (Log_autovacuum_min_duration == 0 ||
+ TimestampDifferenceExceeds(starttime, GetCurrentTimestamp(),
+ Log_autovacuum_min_duration))
+ ereport(LOG,
+ (errmsg("automatic cache analyze of table \"%s.%s.%s\" system usage: %s",
+ get_database_name(MyDatabaseId),
+ get_namespace_name(RelationGetNamespace(onerel)),
+ RelationGetRelationName(onerel),
+ pg_rusage_show(&ru0))));
+ }
+
+ /* Roll back any GUC changes executed by index functions */
+ AtEOXact_GUC(false, save_nestlevel);
+
+ /* Restore current context and release memory */
+ MemoryContextSwitchTo(caller_context);
MemoryContextDelete(anl_context);
anl_context = NULL;
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
new file mode 100644
index 1d39674..c312227
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
*************** static void SplitColQualList(List *qualL
*** 342,348 ****
%type <boolean> opt_instead
%type <boolean> opt_unique opt_concurrently opt_verbose opt_full
! %type <boolean> opt_freeze opt_default opt_recheck
%type <defelt> opt_binary opt_oids copy_delimiter
%type <boolean> copy_from
--- 342,348 ----
%type <boolean> opt_instead
%type <boolean> opt_unique opt_concurrently opt_verbose opt_full
! %type <boolean> opt_freeze opt_oscache opt_default opt_recheck
%type <defelt> opt_binary opt_oids copy_delimiter
%type <boolean> copy_from
*************** static void SplitColQualList(List *qualL
*** 529,535 ****
NULLS_P NUMERIC
OBJECT_P OF OFF OFFSET OIDS ON ONLY OPERATOR OPTION OPTIONS OR
! ORDER OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER
PARSER PARTIAL PARTITION PASSING PASSWORD PLACING PLANS POSITION
PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY
--- 529,535 ----
NULLS_P NUMERIC
OBJECT_P OF OFF OFFSET OIDS ON ONLY OPERATOR OPTION OPTIONS OR
! ORDER OSCACHE OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER
PARSER PARTIAL PARTITION PASSING PASSWORD PLACING PLANS POSITION
PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY
*************** vacuum_option_elem:
*** 7801,7811 ****
;
AnalyzeStmt:
! analyze_keyword opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_ANALYZE;
if ($2)
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
--- 7801,7813 ----
;
AnalyzeStmt:
! analyze_keyword opt_oscache opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_ANALYZE;
if ($2)
+ n->options |= VACOPT_OSCACHE;
+ if ($3)
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
*************** AnalyzeStmt:
*** 7813,7828 ****
n->va_cols = NIL;
$$ = (Node *)n;
}
! | analyze_keyword opt_verbose qualified_name opt_name_list
{
VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_ANALYZE;
if ($2)
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
! n->relation = $3;
! n->va_cols = $4;
$$ = (Node *)n;
}
;
--- 7815,7832 ----
n->va_cols = NIL;
$$ = (Node *)n;
}
! | analyze_keyword opt_oscache opt_verbose qualified_name opt_name_list
{
VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_ANALYZE;
if ($2)
+ n->options |= VACOPT_OSCACHE;
+ if ($3)
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
! n->relation = $4;
! n->va_cols = $5;
$$ = (Node *)n;
}
;
*************** opt_freeze: FREEZE { $$ = TRUE;
*** 7845,7850 ****
--- 7849,7859 ----
| /*EMPTY*/ { $$ = FALSE; }
;
+ opt_oscache:
+ OSCACHE { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
+
opt_name_list:
'(' name_list ')' { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
*************** type_func_name_keyword:
*** 12158,12163 ****
--- 12167,12173 ----
| LIKE
| NATURAL
| NOTNULL
+ | OSCACHE
| OUTER_P
| OVER
| OVERLAPS
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
new file mode 100644
index b12348b..670dbdf
*** a/src/backend/storage/buffer/bufmgr.c
--- b/src/backend/storage/buffer/bufmgr.c
*************** RelationGetNumberOfBlocksInFork(Relation
*** 1928,1933 ****
--- 1928,1946 ----
return smgrnblocks(relation->rd_smgr, forkNum);
}
+ /*
+ * RelationGetRelationOSCacheInFork
+ * Determines the current percentage of pages in OS cache for the
+ * relation.
+ */
+ float4
+ RelationGetRelationOSCacheInFork(Relation relation, ForkNumber forkNum)
+ {
+ float4 percent = 0;
+
+ return percent;
+ }
+
/* ---------------------------------------------------------------------
* DropRelFileNodeBuffers
*
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
new file mode 100644
index 14937d4..bc191c2
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
*************** typedef enum VacuumOption
*** 2417,2423 ****
VACOPT_VERBOSE = 1 << 2, /* print progress info */
VACOPT_FREEZE = 1 << 3, /* FREEZE option */
VACOPT_FULL = 1 << 4, /* FULL (non-concurrent) vacuum */
! VACOPT_NOWAIT = 1 << 5
} VacuumOption;
typedef struct VacuumStmt
--- 2417,2424 ----
VACOPT_VERBOSE = 1 << 2, /* print progress info */
VACOPT_FREEZE = 1 << 3, /* FREEZE option */
VACOPT_FULL = 1 << 4, /* FULL (non-concurrent) vacuum */
! VACOPT_NOWAIT = 1 << 5,
! VACOPT_OSCACHE = 1 << 6 /* do OSCACHE stats analyze */
} VacuumOption;
typedef struct VacuumStmt
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
new file mode 100644
index 12c2faf..95a7e3d
*** a/src/include/parser/kwlist.h
--- b/src/include/parser/kwlist.h
*************** PG_KEYWORD("option", OPTION, UNRESERVED_
*** 264,269 ****
--- 264,270 ----
PG_KEYWORD("options", OPTIONS, UNRESERVED_KEYWORD)
PG_KEYWORD("or", OR, RESERVED_KEYWORD)
PG_KEYWORD("order", ORDER, RESERVED_KEYWORD)
+ PG_KEYWORD("oscache", OSCACHE, TYPE_FUNC_NAME_KEYWORD)
PG_KEYWORD("out", OUT_P, COL_NAME_KEYWORD)
PG_KEYWORD("outer", OUTER_P, TYPE_FUNC_NAME_KEYWORD)
PG_KEYWORD("over", OVER, TYPE_FUNC_NAME_KEYWORD)
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
new file mode 100644
index b8fc87e..7d22b5a
*** a/src/include/storage/bufmgr.h
--- b/src/include/storage/bufmgr.h
*************** extern void CheckPointBuffers(int flags)
*** 179,184 ****
--- 179,186 ----
extern BlockNumber BufferGetBlockNumber(Buffer buffer);
extern BlockNumber RelationGetNumberOfBlocksInFork(Relation relation,
ForkNumber forkNum);
+ extern float4 RelationGetRelationOSCacheInFork(Relation relation,
+ ForkNumber forkNum);
extern void FlushRelationBuffers(Relation rel);
extern void FlushDatabaseBuffers(Oid dbid);
extern void DropRelFileNodeBuffers(RelFileNodeBackend rnode,
--
1.7.5.3