1212 * Portions Copyright (c) 1994, Regents of the University of California
1313 *
1414 * IDENTIFICATION
15- * $PostgreSQL: pgsql/src/backend/utils/cache/spccache.c,v 1.2 2010/01/0622:27:09 tgl Exp $
15+ * $PostgreSQL: pgsql/src/backend/utils/cache/spccache.c,v 1.3 2010/01/0623:00:02 tgl Exp $
1616 *
1717 *-------------------------------------------------------------------------
1818 */
19-
2019#include "postgres.h"
20+
2121#include "access/reloptions.h"
2222#include "catalog/pg_tablespace.h"
2323#include "commands/tablespace.h"
2929#include "utils/spccache.h"
3030#include "utils/syscache.h"
3131
32+
33+ /* Hash table for information about each tablespace */
3234static HTAB * TableSpaceCacheHash = NULL ;
3335
34- typedef struct {
35- Oid oid ;
36- TableSpaceOpts * opts ;
37- }TableSpace ;
36+ typedef struct
37+ {
38+ Oid oid ;/* lookup key - must be first */
39+ TableSpaceOpts * opts ;/* options, or NULL if none */
40+ }TableSpaceCacheEntry ;
41+
3842
3943/*
4044 * InvalidateTableSpaceCacheCallback
@@ -49,10 +53,10 @@ static void
4953InvalidateTableSpaceCacheCallback (Datum arg ,int cacheid ,ItemPointer tuplePtr )
5054{
5155HASH_SEQ_STATUS status ;
52- TableSpace * spc ;
56+ TableSpaceCacheEntry * spc ;
5357
5458hash_seq_init (& status ,TableSpaceCacheHash );
55- while ((spc = (TableSpace * )hash_seq_search (& status ))!= NULL )
59+ while ((spc = (TableSpaceCacheEntry * )hash_seq_search (& status ))!= NULL )
5660{
5761if (spc -> opts )
5862pfree (spc -> opts );
@@ -66,7 +70,7 @@ InvalidateTableSpaceCacheCallback(Datum arg, int cacheid, ItemPointer tuplePtr)
6670
6771/*
6872 * InitializeTableSpaceCache
69- *Initiate the tablespace cache.
73+ *Initialize the tablespace cache.
7074 */
7175static void
7276InitializeTableSpaceCache (void )
@@ -76,8 +80,8 @@ InitializeTableSpaceCache(void)
7680/* Initialize the hash table. */
7781MemSet (& ctl ,0 ,sizeof (ctl ));
7882ctl .keysize = sizeof (Oid );
79- ctl .entrysize = sizeof (TableSpace );
80- ctl .hash = tag_hash ;
83+ ctl .entrysize = sizeof (TableSpaceCacheEntry );
84+ ctl .hash = oid_hash ;
8185TableSpaceCacheHash =
8286hash_create ("TableSpace cache" ,16 ,& ctl ,
8387HASH_ELEM |HASH_FUNCTION );
@@ -94,17 +98,17 @@ InitializeTableSpaceCache(void)
9498
9599/*
96100 * get_tablespace
97- *FetchTableSpace structure for a specified table OID.
101+ *FetchTableSpaceCacheEntry structure for a specified table OID.
98102 *
99103 * Pointers returned by this function should not be stored, since a cache
100104 * flush will invalidate them.
101105 */
102- static TableSpace *
106+ static TableSpaceCacheEntry *
103107get_tablespace (Oid spcid )
104108{
109+ TableSpaceCacheEntry * spc ;
105110HeapTuple tp ;
106- TableSpace * spc ;
107- bool found ;
111+ TableSpaceOpts * opts ;
108112
109113/*
110114 * Since spcid is always from a pg_class tuple, InvalidOid implies the
@@ -113,12 +117,14 @@ get_tablespace(Oid spcid)
113117if (spcid == InvalidOid )
114118spcid = MyDatabaseTableSpace ;
115119
116- /* Find existing cache entry,or create a new one . */
120+ /* Find existing cache entry,if any . */
117121if (!TableSpaceCacheHash )
118122InitializeTableSpaceCache ();
119- spc = (TableSpace * )hash_search (TableSpaceCacheHash , (void * )& spcid ,
120- HASH_ENTER ,& found );
121- if (found )
123+ spc = (TableSpaceCacheEntry * )hash_search (TableSpaceCacheHash ,
124+ (void * )& spcid ,
125+ HASH_FIND ,
126+ NULL );
127+ if (spc )
122128return spc ;
123129
124130/*
@@ -127,9 +133,11 @@ get_tablespace(Oid spcid)
127133 * details for a non-existent tablespace. We'll just treat that case as if
128134 * no options were specified.
129135 */
130- tp = SearchSysCache (TABLESPACEOID ,ObjectIdGetDatum (spcid ),0 ,0 ,0 );
136+ tp = SearchSysCache (TABLESPACEOID ,
137+ ObjectIdGetDatum (spcid ),
138+ 0 ,0 ,0 );
131139if (!HeapTupleIsValid (tp ))
132- spc -> opts = NULL ;
140+ opts = NULL ;
133141else
134142{
135143Datum datum ;
@@ -141,29 +149,40 @@ get_tablespace(Oid spcid)
141149Anum_pg_tablespace_spcoptions ,
142150& isNull );
143151if (isNull )
144- spc -> opts = NULL ;
152+ opts = NULL ;
145153else
146154{
155+ /* XXX should NOT do the parsing work in CacheMemoryContext */
147156octx = MemoryContextSwitchTo (CacheMemoryContext );
148- spc -> opts = (TableSpaceOpts * )tablespace_reloptions (datum , false);
157+ opts = (TableSpaceOpts * )tablespace_reloptions (datum , false);
149158MemoryContextSwitchTo (octx );
150159}
151160ReleaseSysCache (tp );
152161}
153162
154- /* Update new TableSpace cache entry with results of option parsing. */
163+ /*
164+ * Now create the cache entry. It's important to do this only after
165+ * reading the pg_tablespace entry, since doing so could cause a cache
166+ * flush.
167+ */
168+ spc = (TableSpaceCacheEntry * )hash_search (TableSpaceCacheHash ,
169+ (void * )& spcid ,
170+ HASH_ENTER ,
171+ NULL );
172+ spc -> opts = opts ;
155173return spc ;
156174}
157175
158176/*
159177 * get_tablespace_page_costs
160- *Return random and sequential page costs for a given tablespace.
178+ *Return random and/or sequential page costs for a given tablespace.
161179 */
162180void
163- get_tablespace_page_costs (Oid spcid ,double * spc_random_page_cost ,
164- double * spc_seq_page_cost )
181+ get_tablespace_page_costs (Oid spcid ,
182+ double * spc_random_page_cost ,
183+ double * spc_seq_page_cost )
165184{
166- TableSpace * spc = get_tablespace (spcid );
185+ TableSpaceCacheEntry * spc = get_tablespace (spcid );
167186
168187Assert (spc != NULL );
169188