inval.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 736 行 · 第 1/2 页

C
736
字号
 *					  private support functions * ---------------------------------------------------------------- *//* * RegisterCatcacheInvalidation * * Register an invalidation event for a catcache tuple entry. */static voidRegisterCatcacheInvalidation(int cacheId,							 uint32 hashValue,							 ItemPointer tuplePtr,							 Oid dbId){	AddCatcacheInvalidationMessage(&CurrentCmdInvalidMsgs,								   cacheId, hashValue, tuplePtr, dbId);}/* * RegisterRelcacheInvalidation * * As above, but register a relcache invalidation event. */static voidRegisterRelcacheInvalidation(Oid dbId, Oid relId){	AddRelcacheInvalidationMessage(&CurrentCmdInvalidMsgs,								   dbId, relId);	/*	 * If the relation being invalidated is one of those cached in the	 * relcache init file, mark that we need to zap that file at commit.	 */	if (RelationIdIsInInitFile(relId))		RelcacheInitFileInval = true;}/* * LocalExecuteInvalidationMessage * * Process a single invalidation message (which could be either type). * Only the local caches are flushed; this does not transmit the message * to other backends. */static voidLocalExecuteInvalidationMessage(SharedInvalidationMessage *msg){	int			i;	if (msg->id >= 0)	{		if (msg->cc.dbId == MyDatabaseId || msg->cc.dbId == 0)		{			CatalogCacheIdInvalidate(msg->cc.id,									 msg->cc.hashValue,									 &msg->cc.tuplePtr);			for (i = 0; i < cache_callback_count; i++)			{				struct CACHECALLBACK *ccitem = cache_callback_list + i;				if (ccitem->id == msg->cc.id)					(*ccitem->function) (ccitem->arg, InvalidOid);			}		}	}	else if (msg->id == SHAREDINVALRELCACHE_ID)	{		if (msg->rc.dbId == MyDatabaseId || msg->rc.dbId == 0)		{			RelationIdInvalidateRelationCacheByRelationId(msg->rc.relId);			for (i = 0; i < cache_callback_count; i++)			{				struct CACHECALLBACK *ccitem = cache_callback_list + i;				if (ccitem->id == SHAREDINVALRELCACHE_ID)					(*ccitem->function) (ccitem->arg, msg->rc.relId);			}		}	}	else		elog(FATAL, "unrecognized SI message id: %d", msg->id);}/* *		InvalidateSystemCaches * *		This blows away all tuples in the system catalog caches and *		all the cached relation descriptors (and closes their files too). *		Relation descriptors that have positive refcounts are then rebuilt. * *		We call this when we see a shared-inval-queue overflow signal, *		since that tells us we've lost some shared-inval messages and hence *		don't know what needs to be invalidated. */static voidInvalidateSystemCaches(void){	int			i;	ResetCatalogCaches();	RelationCacheInvalidate();	for (i = 0; i < cache_callback_count; i++)	{		struct CACHECALLBACK *ccitem = cache_callback_list + i;		(*ccitem->function) (ccitem->arg, InvalidOid);	}}/* * PrepareForTupleInvalidation *		Detect whether invalidation of this tuple implies invalidation *		of catalog/relation cache entries; if so, register inval events. */static voidPrepareForTupleInvalidation(Relation relation, HeapTuple tuple,							void (*CacheIdRegisterFunc) (int, uint32,													   ItemPointer, Oid),							void (*RelationIdRegisterFunc) (Oid, Oid)){	Oid			tupleRelId;	Oid			relationId;	if (IsBootstrapProcessingMode())		return;	/*	 * We only need to worry about invalidation for tuples that are in	 * system relations; user-relation tuples are never in catcaches and	 * can't affect the relcache either.	 */	if (!IsSystemRelation(relation))		return;	/*	 * TOAST tuples can likewise be ignored here. Note that TOAST tables	 * are considered system relations so they are not filtered by the	 * above test.	 */	if (IsToastRelation(relation))		return;	/*	 * First let the catcache do its thing	 */	PrepareToInvalidateCacheTuple(relation, tuple,								  CacheIdRegisterFunc);	/*	 * Now, is this tuple one of the primary definers of a relcache entry?	 */	tupleRelId = RelationGetRelid(relation);	if (tupleRelId == RelOid_pg_class)		relationId = HeapTupleGetOid(tuple);	else if (tupleRelId == RelOid_pg_attribute)		relationId = ((Form_pg_attribute) GETSTRUCT(tuple))->attrelid;	else		return;	/*	 * Yes.  We need to register a relcache invalidation event for the	 * relation identified by relationId.	 *	 * KLUGE ALERT: we always send the relcache event with MyDatabaseId, even	 * if the rel in question is shared.  This essentially means that only	 * backends in this same database will react to the relcache flush	 * request.  This is in fact appropriate, since only those backends	 * could see our pg_class or pg_attribute change anyway.  It looks a	 * bit ugly though.	 */	(*RelationIdRegisterFunc) (MyDatabaseId, relationId);}/* ---------------------------------------------------------------- *					  public functions * ---------------------------------------------------------------- *//* * AcceptInvalidationMessages *		Read and process invalidation messages from the shared invalidation *		message queue. * * Note: *		This should be called as the first step in processing a transaction. */voidAcceptInvalidationMessages(void){	ReceiveSharedInvalidMessages(LocalExecuteInvalidationMessage,								 InvalidateSystemCaches);}/* * AtEOXactInvalidationMessages *		Process queued-up invalidation messages at end of transaction. * * If isCommit, we must send out the messages in our PriorCmdInvalidMsgs list * to the shared invalidation message queue.  Note that these will be read * not only by other backends, but also by our own backend at the next * transaction start (via AcceptInvalidationMessages).	This means that * we can skip immediate local processing of anything that's still in * CurrentCmdInvalidMsgs, and just send that list out too. * * If not isCommit, we are aborting, and must locally process the messages * in PriorCmdInvalidMsgs.	No messages need be sent to other backends, * since they'll not have seen our changed tuples anyway.  We can forget * about CurrentCmdInvalidMsgs too, since those changes haven't touched * the caches yet. * * In any case, reset the various lists to empty.  We need not physically * free memory here, since TopTransactionContext is about to be emptied * anyway. * * Note: *		This should be called as the last step in processing a transaction. */voidAtEOXactInvalidationMessages(bool isCommit){	if (isCommit)	{		/*		 * Relcache init file invalidation requires processing both before		 * and after we send the SI messages.  However, we need not do		 * anything unless we committed.		 */		if (RelcacheInitFileInval)			RelationCacheInitFileInvalidate(true);		AppendInvalidationMessages(&PriorCmdInvalidMsgs,								   &CurrentCmdInvalidMsgs);		ProcessInvalidationMessages(&PriorCmdInvalidMsgs,									SendSharedInvalidMessage);		if (RelcacheInitFileInval)			RelationCacheInitFileInvalidate(false);	}	else	{		ProcessInvalidationMessages(&PriorCmdInvalidMsgs,									LocalExecuteInvalidationMessage);	}	RelcacheInitFileInval = false;	DiscardInvalidationMessages(&PriorCmdInvalidMsgs, false);	DiscardInvalidationMessages(&CurrentCmdInvalidMsgs, false);}/* * CommandEndInvalidationMessages *		Process queued-up invalidation messages at end of one command *		in a transaction. * * Here, we send no messages to the shared queue, since we don't know yet if * we will commit.	We do need to locally process the CurrentCmdInvalidMsgs * list, so as to flush our caches of any entries we have outdated in the * current command.  We then move the current-cmd list over to become part * of the prior-cmds list. * * The isCommit = false case is not currently used, but may someday be * needed to support rollback to a savepoint within a transaction. * * Note: *		This should be called during CommandCounterIncrement(), *		after we have advanced the command ID. */voidCommandEndInvalidationMessages(bool isCommit){	if (isCommit)	{		ProcessInvalidationMessages(&CurrentCmdInvalidMsgs,									LocalExecuteInvalidationMessage);		AppendInvalidationMessages(&PriorCmdInvalidMsgs,								   &CurrentCmdInvalidMsgs);	}	else	{		/* XXX what needs to be done here? */	}}/* * CacheInvalidateHeapTuple *		Register the given tuple for invalidation at end of command *		(ie, current command is outdating this tuple). */voidCacheInvalidateHeapTuple(Relation relation, HeapTuple tuple){	PrepareForTupleInvalidation(relation, tuple,								RegisterCatcacheInvalidation,								RegisterRelcacheInvalidation);}/* * CacheInvalidateRelcache *		Register invalidation of the specified relation's relcache entry *		at end of command. * * This is used in places that need to force relcache rebuild but aren't * changing any of the tuples recognized as contributors to the relcache * entry by PrepareForTupleInvalidation.  (An example is dropping an index.) */voidCacheInvalidateRelcache(Oid relationId){	/* See KLUGE ALERT in PrepareForTupleInvalidation */	RegisterRelcacheInvalidation(MyDatabaseId, relationId);}/* * CacheRegisterSyscacheCallback *		Register the specified function to be called for all future *		invalidation events in the specified cache. * * NOTE: currently, the OID argument to the callback routine is not * provided for syscache callbacks; the routine doesn't really get any * useful info as to exactly what changed.	It should treat every call * as a "cache flush" request. */voidCacheRegisterSyscacheCallback(int cacheid,							  CacheCallbackFunction func,							  Datum arg){	if (cache_callback_count >= MAX_CACHE_CALLBACKS)		elog(FATAL, "out of cache_callback_list slots");	cache_callback_list[cache_callback_count].id = cacheid;	cache_callback_list[cache_callback_count].function = func;	cache_callback_list[cache_callback_count].arg = arg;	++cache_callback_count;}/* * CacheRegisterRelcacheCallback *		Register the specified function to be called for all future *		relcache invalidation events.  The OID of the relation being *		invalidated will be passed to the function. * * NOTE: InvalidOid will be passed if a cache reset request is received. * In this case the called routines should flush all cached state. */voidCacheRegisterRelcacheCallback(CacheCallbackFunction func,							  Datum arg){	if (cache_callback_count >= MAX_CACHE_CALLBACKS)		elog(FATAL, "out of cache_callback_list slots");	cache_callback_list[cache_callback_count].id = SHAREDINVALRELCACHE_ID;	cache_callback_list[cache_callback_count].function = func;	cache_callback_list[cache_callback_count].arg = arg;	++cache_callback_count;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?