@@ -279,42 +279,23 @@ spcachekey_equal(SearchPathCacheKey a, SearchPathCacheKey b)
279
279
static nsphash_hash * SearchPathCache = NULL ;
280
280
281
281
/*
282
- * Create search path cache.
282
+ * Create or reset search_path cache as necessary .
283
283
*/
284
284
static void
285
285
spcache_init (void )
286
286
{
287
287
Assert (SearchPathCacheContext );
288
288
289
- if (SearchPathCache )
289
+ if (SearchPathCache && searchPathCacheValid &&
290
+ SearchPathCache -> members < SPCACHE_RESET_THRESHOLD )
290
291
return ;
291
292
293
+ MemoryContextReset (SearchPathCacheContext );
292
294
/* arbitrary initial starting size of 16 elements */
293
295
SearchPathCache = nsphash_create (SearchPathCacheContext , 16 , NULL );
294
296
searchPathCacheValid = true;
295
297
}
296
298
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
-
318
299
/*
319
300
* Look up or insert entry in search path cache.
320
301
*
@@ -325,27 +306,25 @@ static SearchPathCacheEntry *
325
306
spcache_insert (const char * searchPath , Oid roleid )
326
307
{
327
308
SearchPathCacheEntry * entry ;
328
- bool found ;
329
309
SearchPathCacheKey cachekey = {
330
310
.searchPath = searchPath ,
331
311
.roleid = roleid
332
312
};
333
313
334
314
/*
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.
339
317
*/
340
- searchPathCacheValid = false;
341
-
342
- entry = nsphash_insert (SearchPathCache , cachekey , & found );
318
+ entry = nsphash_lookup (SearchPathCache , cachekey );
343
319
344
- /* ensure that key is initialized and the rest is zeroed */
345
- if (!found )
320
+ if (!entry )
346
321
{
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
+
349
328
entry -> oidlist = NIL ;
350
329
entry -> finalPath = NIL ;
351
330
entry -> firstNS = InvalidOid ;
@@ -354,7 +333,6 @@ spcache_insert(const char *searchPath, Oid roleid)
354
333
/* do not touch entry->status, used by simplehash */
355
334
}
356
335
357
- searchPathCacheValid = true;
358
336
return entry ;
359
337
}
360
338
@@ -4183,31 +4161,15 @@ finalNamespacePath(List *oidlist, Oid *firstNS)
4183
4161
/*
4184
4162
* Retrieve search path information from the cache; or if not there, fill
4185
4163
* 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.
4191
4164
*/
4192
4165
static const SearchPathCacheEntry *
4193
- cachedNamespacePath (const char * searchPath , Oid roleid , List * prevPath ,
4194
- bool * same )
4166
+ cachedNamespacePath (const char * searchPath , Oid roleid )
4195
4167
{
4196
4168
MemoryContext oldcxt ;
4197
4169
SearchPathCacheEntry * entry ;
4198
- List * prevPathCopy = NIL ;
4199
4170
4200
4171
spcache_init ();
4201
4172
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
-
4211
4173
entry = spcache_insert (searchPath , roleid );
4212
4174
4213
4175
/*
@@ -4232,38 +4194,22 @@ cachedNamespacePath(const char *searchPath, Oid roleid, List *prevPath,
4232
4194
if (entry -> finalPath == NIL || object_access_hook ||
4233
4195
entry -> forceRecompute )
4234
4196
{
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 ;
4241
4199
4242
4200
oldcxt = MemoryContextSwitchTo (SearchPathCacheContext );
4243
- finalPath = finalNamespacePath (entry -> oidlist ,
4244
- & entry -> firstNS );
4201
+ entry -> finalPath = finalNamespacePath (entry -> oidlist ,
4202
+ & entry -> firstNS );
4245
4203
MemoryContextSwitchTo (oldcxt );
4246
4204
4247
- * same = equal (prevPath , finalPath );
4248
-
4249
- list_free (entry -> finalPath );
4250
- entry -> finalPath = finalPath ;
4251
-
4252
4205
/*
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
4254
4207
* result may be affected by the hook. Force recomputation of
4255
4208
* finalPath the next time this cache entry is used, even if the
4256
4209
* object_access_hook is not set at that time.
4257
4210
*/
4258
4211
entry -> forceRecompute = object_access_hook ? true : false;
4259
4212
}
4260
- else
4261
- {
4262
- /* use cached version of finalPath */
4263
- * same = equal (prevPath , entry -> finalPath );
4264
- }
4265
-
4266
- list_free (prevPathCopy );
4267
4213
4268
4214
return entry ;
4269
4215
}
@@ -4275,32 +4221,39 @@ static void
4275
4221
recomputeNamespacePath (void )
4276
4222
{
4277
4223
Oid roleid = GetUserId ();
4278
- bool newPathEqual ;
4279
4224
bool pathChanged ;
4280
4225
const SearchPathCacheEntry * entry ;
4281
4226
4282
4227
/* Do nothing if path is already valid. */
4283
4228
if (baseSearchPathValid && namespaceUser == roleid )
4284
4229
return ;
4285
4230
4286
- entry = cachedNamespacePath (namespace_search_path , roleid , baseSearchPath ,
4287
- & newPathEqual );
4231
+ entry = cachedNamespacePath (namespace_search_path , roleid );
4288
4232
4289
4233
if (baseCreationNamespace == entry -> firstNS &&
4290
4234
baseTempCreationPending == entry -> temp_missing &&
4291
- newPathEqual )
4235
+ equal ( entry -> finalPath , baseSearchPath ) )
4292
4236
{
4293
4237
pathChanged = false;
4294
4238
}
4295
4239
else
4296
4240
{
4241
+ MemoryContext oldcxt ;
4242
+ List * newpath ;
4243
+
4297
4244
pathChanged = true;
4298
- }
4299
4245
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
+ }
4304
4257
4305
4258
/* Mark the path valid. */
4306
4259
baseSearchPathValid = true;
0 commit comments