ts_cache.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 643 行 · 第 1/2 页
C
643 行
Datum opt; bool isnull; MemoryContext oldcontext; /* * Init method runs in dictionary's private memory context, and we * make sure the options are stored there too */ oldcontext = MemoryContextSwitchTo(entry->dictCtx); opt = SysCacheGetAttr(TSDICTOID, tpdict, Anum_pg_ts_dict_dictinitoption, &isnull); if (isnull) dictoptions = NIL; else dictoptions = deserialize_deflist(opt); entry->dictData = DatumGetPointer(OidFunctionCall1(template->tmplinit, PointerGetDatum(dictoptions))); MemoryContextSwitchTo(oldcontext); } ReleaseSysCache(tptmpl); ReleaseSysCache(tpdict); fmgr_info_cxt(entry->lexizeOid, &entry->lexize, entry->dictCtx); entry->isvalid = true; } lastUsedDictionary = entry; return entry;}/* * Initialize config cache and prepare callbacks. This is split out of * lookup_ts_config_cache because we need to activate the callback before * caching TSCurrentConfigCache, too. */static voidinit_ts_config_cache(void){ HASHCTL ctl; if (!CacheMemoryContext) CreateCacheMemoryContext(); MemSet(&ctl, 0, sizeof(ctl)); ctl.keysize = sizeof(Oid); ctl.entrysize = sizeof(TSConfigCacheEntry); ctl.hash = oid_hash; TSConfigCacheHash = hash_create("Tsearch configuration cache", 16, &ctl, HASH_ELEM | HASH_FUNCTION); /* Flush cache on pg_ts_config and pg_ts_config_map changes */ CacheRegisterSyscacheCallback(TSCONFIGOID, InvalidateTSCacheCallBack, PointerGetDatum(TSConfigCacheHash)); CacheRegisterSyscacheCallback(TSCONFIGMAP, InvalidateTSCacheCallBack, PointerGetDatum(TSConfigCacheHash));}/* * Fetch configuration cache entry */TSConfigCacheEntry *lookup_ts_config_cache(Oid cfgId){ TSConfigCacheEntry *entry; if (TSConfigCacheHash == NULL) { /* First time through: initialize the hash table */ init_ts_config_cache(); } /* Check single-entry cache */ if (lastUsedConfig && lastUsedConfig->cfgId == cfgId && lastUsedConfig->isvalid) return lastUsedConfig; /* Try to look up an existing entry */ entry = (TSConfigCacheEntry *) hash_search(TSConfigCacheHash, (void *) &cfgId, HASH_FIND, NULL); if (entry == NULL || !entry->isvalid) { /* * If we didn't find one, we want to make one. But first look up the * object to be sure the OID is real. */ HeapTuple tp; Form_pg_ts_config cfg; Relation maprel; Relation mapidx; ScanKeyData mapskey; IndexScanDesc mapscan; HeapTuple maptup; ListDictionary maplists[MAXTOKENTYPE + 1]; Oid mapdicts[MAXDICTSPERTT]; int maxtokentype; int ndicts; int i; tp = SearchSysCache(TSCONFIGOID, ObjectIdGetDatum(cfgId), 0, 0, 0); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for text search configuration %u", cfgId); cfg = (Form_pg_ts_config) GETSTRUCT(tp); /* * Sanity checks */ if (!OidIsValid(cfg->cfgparser)) elog(ERROR, "text search configuration %u has no parser", cfgId); if (entry == NULL) { bool found; /* Now make the cache entry */ entry = (TSConfigCacheEntry *) hash_search(TSConfigCacheHash, (void *) &cfgId, HASH_ENTER, &found); Assert(!found); /* it wasn't there a moment ago */ } else { /* Cleanup old contents */ if (entry->map) { for (i = 0; i < entry->lenmap; i++) if (entry->map[i].dictIds) pfree(entry->map[i].dictIds); pfree(entry->map); } } MemSet(entry, 0, sizeof(TSConfigCacheEntry)); entry->cfgId = cfgId; entry->prsId = cfg->cfgparser; ReleaseSysCache(tp); /* * Scan pg_ts_config_map to gather dictionary list for each token type * * Because the index is on (mapcfg, maptokentype, mapseqno), we will * see the entries in maptokentype order, and in mapseqno order for * each token type, even though we didn't explicitly ask for that. */ MemSet(maplists, 0, sizeof(maplists)); maxtokentype = 0; ndicts = 0; ScanKeyInit(&mapskey, Anum_pg_ts_config_map_mapcfg, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(cfgId)); maprel = heap_open(TSConfigMapRelationId, AccessShareLock); mapidx = index_open(TSConfigMapIndexId, AccessShareLock); mapscan = index_beginscan(maprel, mapidx, SnapshotNow, 1, &mapskey); while ((maptup = index_getnext(mapscan, ForwardScanDirection)) != NULL) { Form_pg_ts_config_map cfgmap = (Form_pg_ts_config_map) GETSTRUCT(maptup); int toktype = cfgmap->maptokentype; if (toktype <= 0 || toktype > MAXTOKENTYPE) elog(ERROR, "maptokentype value %d is out of range", toktype); if (toktype < maxtokentype) elog(ERROR, "maptokentype entries are out of order"); if (toktype > maxtokentype) { /* starting a new token type, but first save the prior data */ if (ndicts > 0) { maplists[maxtokentype].len = ndicts; maplists[maxtokentype].dictIds = (Oid *) MemoryContextAlloc(CacheMemoryContext, sizeof(Oid) * ndicts); memcpy(maplists[maxtokentype].dictIds, mapdicts, sizeof(Oid) * ndicts); } maxtokentype = toktype; mapdicts[0] = cfgmap->mapdict; ndicts = 1; } else { /* continuing data for current token type */ if (ndicts >= MAXDICTSPERTT) elog(ERROR, "too many pg_ts_config_map entries for one token type"); mapdicts[ndicts++] = cfgmap->mapdict; } } index_endscan(mapscan); index_close(mapidx, AccessShareLock); heap_close(maprel, AccessShareLock); if (ndicts > 0) { /* save the last token type's dictionaries */ maplists[maxtokentype].len = ndicts; maplists[maxtokentype].dictIds = (Oid *) MemoryContextAlloc(CacheMemoryContext, sizeof(Oid) * ndicts); memcpy(maplists[maxtokentype].dictIds, mapdicts, sizeof(Oid) * ndicts); /* and save the overall map */ entry->lenmap = maxtokentype + 1; entry->map = (ListDictionary *) MemoryContextAlloc(CacheMemoryContext, sizeof(ListDictionary) * entry->lenmap); memcpy(entry->map, maplists, sizeof(ListDictionary) * entry->lenmap); } entry->isvalid = true; } lastUsedConfig = entry; return entry;}/*--------------------------------------------------- * GUC variable "default_text_search_config" *--------------------------------------------------- */OidgetTSCurrentConfig(bool emitError){ /* if we have a cached value, return it */ if (OidIsValid(TSCurrentConfigCache)) return TSCurrentConfigCache; /* fail if GUC hasn't been set up yet */ if (TSCurrentConfig == NULL || *TSCurrentConfig == '\0') { if (emitError) elog(ERROR, "text search configuration isn't set"); else return InvalidOid; } if (TSConfigCacheHash == NULL) { /* First time through: initialize the tsconfig inval callback */ init_ts_config_cache(); } /* Look up the config */ TSCurrentConfigCache = TSConfigGetCfgid(stringToQualifiedNameList(TSCurrentConfig), !emitError); return TSCurrentConfigCache;}const char *assignTSCurrentConfig(const char *newval, bool doit, GucSource source){ /* * If we aren't inside a transaction, we cannot do database access so * cannot verify the config name. Must accept it on faith. */ if (IsTransactionState()) { Oid cfgId; HeapTuple tuple; Form_pg_ts_config cfg; char *buf; cfgId = TSConfigGetCfgid(stringToQualifiedNameList(newval), true); if (!OidIsValid(cfgId)) return NULL; /* * Modify the actually stored value to be fully qualified, to ensure * later changes of search_path don't affect it. */ tuple = SearchSysCache(TSCONFIGOID, ObjectIdGetDatum(cfgId), 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for text search configuration %u", cfgId); cfg = (Form_pg_ts_config) GETSTRUCT(tuple); buf = quote_qualified_identifier(get_namespace_name(cfg->cfgnamespace), NameStr(cfg->cfgname)); ReleaseSysCache(tuple); /* GUC wants it malloc'd not palloc'd */ newval = strdup(buf); pfree(buf); if (doit && newval) TSCurrentConfigCache = cfgId; } else { if (doit) TSCurrentConfigCache = InvalidOid; } return newval;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?