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/06 22:27:09 tgl Exp $
15+ * $PostgreSQL: pgsql/src/backend/utils/cache/spccache.c,v 1.3 2010/01/06 23: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{
5155 HASH_SEQ_STATUS status ;
52- TableSpace * spc ;
56+ TableSpaceCacheEntry * spc ;
5357
5458 hash_seq_init (& status , TableSpaceCacheHash );
55- while ((spc = (TableSpace * ) hash_seq_search (& status )) != NULL )
59+ while ((spc = (TableSpaceCacheEntry * ) hash_seq_search (& status )) != NULL )
5660 {
5761 if (spc -> opts )
5862 pfree (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. */
7781 MemSet (& ctl , 0 , sizeof (ctl ));
7882 ctl .keysize = sizeof (Oid );
79- ctl .entrysize = sizeof (TableSpace );
80- ctl .hash = tag_hash ;
83+ ctl .entrysize = sizeof (TableSpaceCacheEntry );
84+ ctl .hash = oid_hash ;
8185 TableSpaceCacheHash =
8286 hash_create ("TableSpace cache" , 16 , & ctl ,
8387 HASH_ELEM | HASH_FUNCTION );
@@ -94,17 +98,17 @@ InitializeTableSpaceCache(void)
9498
9599/*
96100 * get_tablespace
97- * Fetch TableSpace structure for a specified table OID.
101+ * Fetch TableSpaceCacheEntry 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 ;
105110 HeapTuple 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)
113117 if (spcid == InvalidOid )
114118 spcid = MyDatabaseTableSpace ;
115119
116- /* Find existing cache entry, or create a new one . */
120+ /* Find existing cache entry, if any . */
117121 if (!TableSpaceCacheHash )
118122 InitializeTableSpaceCache ();
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 )
122128 return 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 );
131139 if (!HeapTupleIsValid (tp ))
132- spc -> opts = NULL ;
140+ opts = NULL ;
133141 else
134142 {
135143 Datum datum ;
@@ -141,29 +149,40 @@ get_tablespace(Oid spcid)
141149 Anum_pg_tablespace_spcoptions ,
142150 & isNull );
143151 if (isNull )
144- spc -> opts = NULL ;
152+ opts = NULL ;
145153 else
146154 {
155+ /* XXX should NOT do the parsing work in CacheMemoryContext */
147156 octx = MemoryContextSwitchTo (CacheMemoryContext );
148- spc -> opts = (TableSpaceOpts * ) tablespace_reloptions (datum , false);
157+ opts = (TableSpaceOpts * ) tablespace_reloptions (datum , false);
149158 MemoryContextSwitchTo (octx );
150159 }
151160 ReleaseSysCache (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 ;
155173 return 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
168187 Assert (spc != NULL );
169188
0 commit comments