diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/cache/inval.c | 39 | ||||
-rw-r--r-- | src/backend/utils/cache/syscache.c | 5 | ||||
-rw-r--r-- | src/include/utils/syscache.h | 2 |
3 files changed, 40 insertions, 6 deletions
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c index 72c8e9e0c48..a1e6ea2a356 100644 --- a/src/backend/utils/cache/inval.c +++ b/src/backend/utils/cache/inval.c @@ -177,7 +177,12 @@ static int maxSharedInvalidMessagesArray; /* * Dynamically-registered callback functions. Current implementation - * assumes there won't be very many of these at once; could improve if needed. + * assumes there won't be enough of these to justify a dynamically resizable + * array; it'd be easy to improve that if needed. + * + * To avoid searching in CallSyscacheCallbacks, all callbacks for a given + * syscache are linked into a list pointed to by syscache_callback_links[id]. + * The link values are syscache_callback_list[] index plus 1, or 0 for none. */ #define MAX_SYSCACHE_CALLBACKS 64 @@ -186,10 +191,13 @@ static int maxSharedInvalidMessagesArray; static struct SYSCACHECALLBACK { int16 id; /* cache number */ + int16 link; /* next callback index+1 for same cache */ SyscacheCallbackFunction function; Datum arg; } syscache_callback_list[MAX_SYSCACHE_CALLBACKS]; +static int16 syscache_callback_links[SysCacheSize]; + static int syscache_callback_count = 0; static struct RELCACHECALLBACK @@ -1383,10 +1391,28 @@ CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg) { + if (cacheid < 0 || cacheid >= SysCacheSize) + elog(FATAL, "invalid cache ID: %d", cacheid); if (syscache_callback_count >= MAX_SYSCACHE_CALLBACKS) elog(FATAL, "out of syscache_callback_list slots"); + if (syscache_callback_links[cacheid] == 0) + { + /* first callback for this cache */ + syscache_callback_links[cacheid] = syscache_callback_count + 1; + } + else + { + /* add to end of chain, so that older callbacks are called first */ + int i = syscache_callback_links[cacheid] - 1; + + while (syscache_callback_list[i].link > 0) + i = syscache_callback_list[i].link - 1; + syscache_callback_list[i].link = syscache_callback_count + 1; + } + syscache_callback_list[syscache_callback_count].id = cacheid; + syscache_callback_list[syscache_callback_count].link = 0; syscache_callback_list[syscache_callback_count].function = func; syscache_callback_list[syscache_callback_count].arg = arg; @@ -1426,11 +1452,16 @@ CallSyscacheCallbacks(int cacheid, uint32 hashvalue) { int i; - for (i = 0; i < syscache_callback_count; i++) + if (cacheid < 0 || cacheid >= SysCacheSize) + elog(ERROR, "invalid cache ID: %d", cacheid); + + i = syscache_callback_links[cacheid] - 1; + while (i >= 0) { struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i; - if (ccitem->id == cacheid) - (*ccitem->function) (ccitem->arg, cacheid, hashvalue); + Assert(ccitem->id == cacheid); + (*ccitem->function) (ccitem->arg, cacheid, hashvalue); + i = ccitem->link - 1; } } diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 066ce728775..f0a16e309c0 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -971,8 +971,6 @@ static const struct cachedesc cacheinfo[] = { } }; -#define SysCacheSize ((int) lengthof(cacheinfo)) - static CatCache *SysCache[SysCacheSize]; static bool CacheInitialized = false; @@ -1003,6 +1001,9 @@ InitCatalogCache(void) int i, j; + StaticAssertStmt(SysCacheSize == (int) lengthof(cacheinfo), + "SysCacheSize does not match syscache.c's array"); + Assert(!CacheInitialized); SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0; diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h index 73991dde4f9..e20284d0615 100644 --- a/src/include/utils/syscache.h +++ b/src/include/utils/syscache.h @@ -108,6 +108,8 @@ enum SysCacheIdentifier TYPEOID, USERMAPPINGOID, USERMAPPINGUSERSERVER + +#define SysCacheSize (USERMAPPINGUSERSERVER + 1) }; extern void InitCatalogCache(void); |