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 + -
显示快捷键?