diff options
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r-- | src/backend/utils/cache/Makefile | 4 | ||||
-rw-r--r-- | src/backend/utils/cache/spccache.c | 183 | ||||
-rw-r--r-- | src/backend/utils/cache/syscache.c | 15 |
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, |