@@ -279,42 +279,23 @@ spcachekey_equal(SearchPathCacheKey a, SearchPathCacheKey b)
279279static nsphash_hash * SearchPathCache = NULL ;
280280
281281/*
282- * Create search path cache.
282+ * Create or reset search_path cache as necessary .
283283 */
284284static void
285285spcache_init (void )
286286{
287287 Assert (SearchPathCacheContext );
288288
289- if (SearchPathCache )
289+ if (SearchPathCache && searchPathCacheValid &&
290+ SearchPathCache -> members < SPCACHE_RESET_THRESHOLD )
290291 return ;
291292
293+ MemoryContextReset (SearchPathCacheContext );
292294 /* arbitrary initial starting size of 16 elements */
293295 SearchPathCache = nsphash_create (SearchPathCacheContext , 16 , NULL );
294296 searchPathCacheValid = true;
295297}
296298
297- /*
298- * Reset and reinitialize search path cache.
299- */
300- static void
301- spcache_reset (void )
302- {
303- Assert (SearchPathCacheContext );
304- Assert (SearchPathCache );
305-
306- MemoryContextReset (SearchPathCacheContext );
307- SearchPathCache = NULL ;
308-
309- spcache_init ();
310- }
311-
312- static uint32
313- spcache_members (void )
314- {
315- return SearchPathCache -> members ;
316- }
317-
318299/*
319300 * Look up or insert entry in search path cache.
320301 *
@@ -325,27 +306,25 @@ static SearchPathCacheEntry *
325306spcache_insert (const char * searchPath , Oid roleid )
326307{
327308 SearchPathCacheEntry * entry ;
328- bool found ;
329309 SearchPathCacheKey cachekey = {
330310 .searchPath = searchPath ,
331311 .roleid = roleid
332312 };
333313
334314 /*
335- * If a new entry is created, we must ensure that it's properly
336- * initialized. Set the cache invalid temporarily, so that if the
337- * MemoryContextStrdup() below raises an OOM, the cache will be reset on
338- * the next use, clearing the uninitialized entry.
315+ * searchPath is not saved in SearchPathCacheContext. First perform a
316+ * lookup, and copy searchPath only if we need to create a new entry.
339317 */
340- searchPathCacheValid = false;
341-
342- entry = nsphash_insert (SearchPathCache , cachekey , & found );
318+ entry = nsphash_lookup (SearchPathCache , cachekey );
343319
344- /* ensure that key is initialized and the rest is zeroed */
345- if (!found )
320+ if (!entry )
346321 {
347- entry -> key .searchPath = MemoryContextStrdup (SearchPathCacheContext , searchPath );
348- entry -> key .roleid = roleid ;
322+ bool found ;
323+
324+ cachekey .searchPath = MemoryContextStrdup (SearchPathCacheContext , searchPath );
325+ entry = nsphash_insert (SearchPathCache , cachekey , & found );
326+ Assert (!found );
327+
349328 entry -> oidlist = NIL ;
350329 entry -> finalPath = NIL ;
351330 entry -> firstNS = InvalidOid ;
@@ -354,7 +333,6 @@ spcache_insert(const char *searchPath, Oid roleid)
354333 /* do not touch entry->status, used by simplehash */
355334 }
356335
357- searchPathCacheValid = true;
358336 return entry ;
359337}
360338
@@ -4183,31 +4161,15 @@ finalNamespacePath(List *oidlist, Oid *firstNS)
41834161/*
41844162 * Retrieve search path information from the cache; or if not there, fill
41854163 * it. The returned entry is valid only until the next call to this function.
4186- *
4187- * We also determine if the newly-computed finalPath is the same as the
4188- * prevPath passed by the caller (i.e. a no-op or a real change?). It's more
4189- * efficient to check for a change in this function than the caller, because
4190- * we can avoid unnecessary temporary copies of the previous path.
41914164 */
41924165static const SearchPathCacheEntry *
4193- cachedNamespacePath (const char * searchPath , Oid roleid , List * prevPath ,
4194- bool * same )
4166+ cachedNamespacePath (const char * searchPath , Oid roleid )
41954167{
41964168 MemoryContext oldcxt ;
41974169 SearchPathCacheEntry * entry ;
4198- List * prevPathCopy = NIL ;
41994170
42004171 spcache_init ();
42014172
4202- /* invalidate cache if necessary */
4203- if (!searchPathCacheValid || spcache_members () >= SPCACHE_RESET_THRESHOLD )
4204- {
4205- /* prevPath will be destroyed; make temp copy for later comparison */
4206- prevPathCopy = list_copy (prevPath );
4207- prevPath = prevPathCopy ;
4208- spcache_reset ();
4209- }
4210-
42114173 entry = spcache_insert (searchPath , roleid );
42124174
42134175 /*
@@ -4232,38 +4194,22 @@ cachedNamespacePath(const char *searchPath, Oid roleid, List *prevPath,
42324194 if (entry -> finalPath == NIL || object_access_hook ||
42334195 entry -> forceRecompute )
42344196 {
4235- /*
4236- * Do not free the stale value of entry->finalPath until we've
4237- * performed the comparison, in case it's aliased by prevPath (which
4238- * can only happen when recomputing due to an object_access_hook).
4239- */
4240- List * finalPath ;
4197+ list_free (entry -> finalPath );
4198+ entry -> finalPath = NIL ;
42414199
42424200 oldcxt = MemoryContextSwitchTo (SearchPathCacheContext );
4243- finalPath = finalNamespacePath (entry -> oidlist ,
4244- & entry -> firstNS );
4201+ entry -> finalPath = finalNamespacePath (entry -> oidlist ,
4202+ & entry -> firstNS );
42454203 MemoryContextSwitchTo (oldcxt );
42464204
4247- * same = equal (prevPath , finalPath );
4248-
4249- list_free (entry -> finalPath );
4250- entry -> finalPath = finalPath ;
4251-
42524205 /*
4253- * If an object_access_hook set when finalPath is calculated, the
4206+ * If an object_access_hook is set when finalPath is calculated, the
42544207 * result may be affected by the hook. Force recomputation of
42554208 * finalPath the next time this cache entry is used, even if the
42564209 * object_access_hook is not set at that time.
42574210 */
42584211 entry -> forceRecompute = object_access_hook ? true : false;
42594212 }
4260- else
4261- {
4262- /* use cached version of finalPath */
4263- * same = equal (prevPath , entry -> finalPath );
4264- }
4265-
4266- list_free (prevPathCopy );
42674213
42684214 return entry ;
42694215}
@@ -4275,32 +4221,39 @@ static void
42754221recomputeNamespacePath (void )
42764222{
42774223 Oid roleid = GetUserId ();
4278- bool newPathEqual ;
42794224 bool pathChanged ;
42804225 const SearchPathCacheEntry * entry ;
42814226
42824227 /* Do nothing if path is already valid. */
42834228 if (baseSearchPathValid && namespaceUser == roleid )
42844229 return ;
42854230
4286- entry = cachedNamespacePath (namespace_search_path , roleid , baseSearchPath ,
4287- & newPathEqual );
4231+ entry = cachedNamespacePath (namespace_search_path , roleid );
42884232
42894233 if (baseCreationNamespace == entry -> firstNS &&
42904234 baseTempCreationPending == entry -> temp_missing &&
4291- newPathEqual )
4235+ equal ( entry -> finalPath , baseSearchPath ) )
42924236 {
42934237 pathChanged = false;
42944238 }
42954239 else
42964240 {
4241+ MemoryContext oldcxt ;
4242+ List * newpath ;
4243+
42974244 pathChanged = true;
4298- }
42994245
4300- /* Now safe to assign to state variables. */
4301- baseSearchPath = entry -> finalPath ;
4302- baseCreationNamespace = entry -> firstNS ;
4303- baseTempCreationPending = entry -> temp_missing ;
4246+ /* Must save OID list in permanent storage. */
4247+ oldcxt = MemoryContextSwitchTo (TopMemoryContext );
4248+ newpath = list_copy (entry -> finalPath );
4249+ MemoryContextSwitchTo (oldcxt );
4250+
4251+ /* Now safe to assign to state variables. */
4252+ list_free (baseSearchPath );
4253+ baseSearchPath = newpath ;
4254+ baseCreationNamespace = entry -> firstNS ;
4255+ baseTempCreationPending = entry -> temp_missing ;
4256+ }
43044257
43054258 /* Mark the path valid. */
43064259 baseSearchPathValid = true;
0 commit comments