aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r--src/backend/utils/cache/Makefile4
-rw-r--r--src/backend/utils/cache/spccache.c183
-rw-r--r--src/backend/utils/cache/syscache.c15
3 files changed, 199 insertions, 3 deletions
diff --git a/src/backend/utils/cache/Makefile b/src/backend/utils/cache/Makefile
index 1766c0315f8..1a3d2cc482e 100644
--- a/src/backend/utils/cache/Makefile
+++ b/src/backend/utils/cache/Makefile
@@ -4,7 +4,7 @@
# Makefile for utils/cache
#
# IDENTIFICATION
-# $PostgreSQL: pgsql/src/backend/utils/cache/Makefile,v 1.23 2008/02/19 10:30:08 petere Exp $
+# $PostgreSQL: pgsql/src/backend/utils/cache/Makefile,v 1.24 2010/01/05 21:53:59 rhaas Exp $
#
#-------------------------------------------------------------------------
@@ -13,6 +13,6 @@ top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
OBJS = catcache.o inval.o plancache.o relcache.o \
- syscache.o lsyscache.o typcache.o ts_cache.o
+ spccache.o syscache.o lsyscache.o typcache.o ts_cache.o
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/utils/cache/spccache.c b/src/backend/utils/cache/spccache.c
new file mode 100644
index 00000000000..00629c09f06
--- /dev/null
+++ b/src/backend/utils/cache/spccache.c
@@ -0,0 +1,183 @@
+/*-------------------------------------------------------------------------
+ *
+ * spccache.c
+ * Tablespace cache management.
+ *
+ * We cache the parsed version of spcoptions for each tablespace to avoid
+ * needing to reparse on every lookup. Right now, there doesn't appear to
+ * be a measurable performance gain from doing this, but that might change
+ * in the future as we add more options.
+ *
+ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * $PostgreSQL: pgsql/src/backend/utils/cache/spccache.c,v 1.1 2010/01/05 21:53:59 rhaas Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+#include "access/reloptions.h"
+#include "catalog/pg_tablespace.h"
+#include "commands/tablespace.h"
+#include "miscadmin.h"
+#include "optimizer/cost.h"
+#include "utils/catcache.h"
+#include "utils/hsearch.h"
+#include "utils/inval.h"
+#include "utils/spccache.h"
+#include "utils/syscache.h"
+
+static HTAB *TableSpaceCacheHash = NULL;
+
+typedef struct {
+ Oid oid;
+ TableSpaceOpts *opts;
+} TableSpace;
+
+/*
+ * InvalidateTableSpaceCacheCallback
+ * Flush all cache entries when pg_tablespace is updated.
+ *
+ * When pg_tablespace is updated, we must flush the cache entry at least
+ * for that tablespace. Currently, we just flush them all. This is quick
+ * and easy and doesn't cost much, since there shouldn't be terribly many
+ * tablespaces, nor do we expect them to be frequently modified.
+ */
+static void
+InvalidateTableSpaceCacheCallback(Datum arg, int cacheid, ItemPointer tuplePtr)
+{
+ HASH_SEQ_STATUS status;
+ TableSpace *spc;
+
+ hash_seq_init(&status, TableSpaceCacheHash);
+ while ((spc = (TableSpace *) hash_seq_search(&status)) != NULL)
+ {
+ if (hash_search(TableSpaceCacheHash, (void *) &spc->oid, HASH_REMOVE,
+ NULL) == NULL)
+ elog(ERROR, "hash table corrupted");
+ if (spc->opts)
+ pfree(spc->opts);
+ }
+}
+
+/*
+ * InitializeTableSpaceCache
+ * Initiate the tablespace cache.
+ */
+static void
+InitializeTableSpaceCache(void)
+{
+ HASHCTL ctl;
+
+ /* Initialize the hash table. */
+ MemSet(&ctl, 0, sizeof(ctl));
+ ctl.keysize = sizeof(Oid);
+ ctl.entrysize = sizeof(TableSpace);
+ ctl.hash = tag_hash;
+ TableSpaceCacheHash =
+ hash_create("TableSpace cache", 16, &ctl,
+ HASH_ELEM | HASH_FUNCTION);
+
+ /* Make sure we've initialized CacheMemoryContext. */
+ if (!CacheMemoryContext)
+ CreateCacheMemoryContext();
+
+ /* Watch for invalidation events. */
+ CacheRegisterSyscacheCallback(TABLESPACEOID,
+ InvalidateTableSpaceCacheCallback,
+ (Datum) 0);
+}
+
+/*
+ * get_tablespace
+ * Fetch TableSpace structure for a specified table OID.
+ *
+ * Pointers returned by this function should not be stored, since a cache
+ * flush will invalidate them.
+ */
+static TableSpace *
+get_tablespace(Oid spcid)
+{
+ HeapTuple tp;
+ TableSpace *spc;
+ bool found;
+
+ /*
+ * Since spcid is always from a pg_class tuple, InvalidOid implies the
+ * default.
+ */
+ if (spcid == InvalidOid)
+ spcid = MyDatabaseTableSpace;
+
+ /* Find existing cache entry, or create a new one. */
+ if (!TableSpaceCacheHash)
+ InitializeTableSpaceCache();
+ spc = (TableSpace *) hash_search(TableSpaceCacheHash, (void *) &spcid,
+ HASH_ENTER, &found);
+ if (found)
+ return spc;
+
+ /*
+ * Not found in TableSpace cache. Check catcache. If we don't find a
+ * valid HeapTuple, it must mean someone has managed to request tablespace
+ * details for a non-existent tablespace. We'll just treat that case as if
+ * no options were specified.
+ */
+ tp = SearchSysCache(TABLESPACEOID, ObjectIdGetDatum(spcid), 0, 0, 0);
+ if (!HeapTupleIsValid(tp))
+ spc->opts = NULL;
+ else
+ {
+ Datum datum;
+ bool isNull;
+ MemoryContext octx;
+
+ datum = SysCacheGetAttr(TABLESPACEOID,
+ tp,
+ Anum_pg_tablespace_spcoptions,
+ &isNull);
+ if (isNull)
+ spc->opts = NULL;
+ else
+ {
+ octx = MemoryContextSwitchTo(CacheMemoryContext);
+ spc->opts = (TableSpaceOpts *) tablespace_reloptions(datum, false);
+ MemoryContextSwitchTo(octx);
+ }
+ ReleaseSysCache(tp);
+ }
+
+ /* Update new TableSpace cache entry with results of option parsing. */
+ return spc;
+}
+
+/*
+ * get_tablespace_page_costs
+ * Return random and sequential page costs for a given tablespace.
+ */
+void
+get_tablespace_page_costs(Oid spcid, double *spc_random_page_cost,
+ double *spc_seq_page_cost)
+{
+ TableSpace *spc = get_tablespace(spcid);
+
+ Assert(spc != NULL);
+
+ if (spc_random_page_cost)
+ {
+ if (!spc->opts || spc->opts->random_page_cost < 0)
+ *spc_random_page_cost = random_page_cost;
+ else
+ *spc_random_page_cost = spc->opts->random_page_cost;
+ }
+
+ if (spc_seq_page_cost)
+ {
+ if (!spc->opts || spc->opts->seq_page_cost < 0)
+ *spc_seq_page_cost = seq_page_cost;
+ else
+ *spc_seq_page_cost = spc->opts->seq_page_cost;
+ }
+}
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index bd747abc80c..f35712732b2 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.123 2010/01/02 16:57:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.124 2010/01/05 21:53:59 rhaas Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
@@ -43,6 +43,7 @@
#include "catalog/pg_proc.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_statistic.h"
+#include "catalog/pg_tablespace.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_config_map.h"
#include "catalog/pg_ts_dict.h"
@@ -609,6 +610,18 @@ static const struct cachedesc cacheinfo[] = {
},
1024
},
+ {TableSpaceRelationId, /* TABLESPACEOID */
+ TablespaceOidIndexId,
+ 0,
+ 1,
+ {
+ ObjectIdAttributeNumber,
+ 0,
+ 0,
+ 0,
+ },
+ 16
+ },
{TSConfigMapRelationId, /* TSCONFIGMAP */
TSConfigMapIndexId,
0,