Improve cache invalidation handling. Eespecially

this would fix TODO
* elog() flushes cache, try invalidating just entries from
  current xact, perhaps using invalidation cache
This commit is contained in:
Hiroshi Inoue 2000-01-10 06:30:56 +00:00
parent 5770935965
commit 0f2e7948e2
5 changed files with 476 additions and 51 deletions

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.62 1999/12/21 00:06:40 wieck Exp $ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.63 2000/01/10 06:30:50 inoue Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -1262,7 +1262,7 @@ heap_insert(Relation relation, HeapTuple tup)
RelationPutHeapTupleAtEnd(relation, tup); RelationPutHeapTupleAtEnd(relation, tup);
if (IsSystemRelationName(RelationGetRelationName(relation))) if (IsSystemRelationName(RelationGetRelationName(relation)))
RelationInvalidateHeapTuple(relation, tup); RelationMark4RollbackHeapTuple(relation, tup);
return tup->t_data->t_oid; return tup->t_data->t_oid;
} }
@ -1473,6 +1473,8 @@ l2:
RelationPutHeapTupleAtEnd(relation, newtup); RelationPutHeapTupleAtEnd(relation, newtup);
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
} }
/* mark for rollback caches */
RelationMark4RollbackHeapTuple(relation, newtup);
/* /*
* New item in place, now record address of new tuple in t_ctid of old * New item in place, now record address of new tuple in t_ctid of old

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.57 2000/01/05 18:23:44 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.58 2000/01/10 06:30:50 inoue Exp $
* *
* NOTES * NOTES
* Transaction aborts can now occur two ways: * Transaction aborts can now occur two ways:
@ -165,6 +165,7 @@ static void AtAbort_Cache(void);
static void AtAbort_Locks(void); static void AtAbort_Locks(void);
static void AtAbort_Memory(void); static void AtAbort_Memory(void);
static void AtCommit_Cache(void); static void AtCommit_Cache(void);
static void AtCommit_LocalCache(void);
static void AtCommit_Locks(void); static void AtCommit_Locks(void);
static void AtCommit_Memory(void); static void AtCommit_Memory(void);
static void AtStart_Cache(void); static void AtStart_Cache(void);
@ -512,8 +513,11 @@ CommandCounterIncrement()
CurrentTransactionStateData.scanCommandId = CurrentTransactionStateData.commandId; CurrentTransactionStateData.scanCommandId = CurrentTransactionStateData.commandId;
/* make cache changes visible to me */ /*
AtCommit_Cache(); * make cache changes visible to me. AtCommit_LocalCache()
* instead of AtCommit_Cache() is called here.
*/
AtCommit_LocalCache();
AtStart_Cache(); AtStart_Cache();
} }
@ -663,15 +667,26 @@ static void
AtCommit_Cache() AtCommit_Cache()
{ {
/* ---------------- /* ----------------
* Make catalog changes visible to me for the next command. * Make catalog changes visible to all backend.
* Other backends will not process my invalidation messages until
* after I commit and free my locks--though they will do
* unnecessary work if I abort.
* ---------------- * ----------------
*/ */
RegisterInvalid(true); RegisterInvalid(true);
} }
/* --------------------------------
* AtCommit_LocalCache
* --------------------------------
*/
static void
AtCommit_LocalCache()
{
/* ----------------
* Make catalog changes visible to me for the next command.
* ----------------
*/
ImmediateLocalInvalidation(true);
}
/* -------------------------------- /* --------------------------------
* AtCommit_Locks * AtCommit_Locks
* -------------------------------- * --------------------------------

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.60 1999/11/16 04:13:56 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.61 2000/01/10 06:30:51 inoue Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -20,6 +20,7 @@
#include "catalog/catalog.h" #include "catalog/catalog.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "storage/smgr.h" #include "storage/smgr.h"
#include "utils/inval.h" /* ImmediateSharedRelationCacheInvalidate() */
#undef DIAGNOSTIC #undef DIAGNOSTIC
@ -203,6 +204,15 @@ mdunlink(Relation reln)
*/ */
if (reln->rd_unlinked && reln->rd_fd < 0) if (reln->rd_unlinked && reln->rd_fd < 0)
return SM_SUCCESS; return SM_SUCCESS;
/*
* This call isn't good for independency of md stuff,but
* mdunlink() unlinks the base file immediately and couldn't
* be rollbacked in case of abort. We must guarantee all
* backends' relation cache invalidation here.
* This would be unnecessary if unlinking is postponed
* till end of transaction.
*/
ImmediateSharedRelationCacheInvalidate(reln);
/* /*
* Force all segments of the relation to be opened, so that we * Force all segments of the relation to be opened, so that we
* won't miss deleting any of them. * won't miss deleting any of them.
@ -779,6 +789,7 @@ mdtruncate(Relation reln, int nblocks)
#ifndef LET_OS_MANAGE_FILESIZE #ifndef LET_OS_MANAGE_FILESIZE
MemoryContext oldcxt; MemoryContext oldcxt;
int priorblocks; int priorblocks;
bool invalregistered = false;
#endif #endif
/* NOTE: mdnblocks makes sure we have opened all existing segments, /* NOTE: mdnblocks makes sure we have opened all existing segments,
@ -810,6 +821,20 @@ mdtruncate(Relation reln, int nblocks)
* a big file... * a big file...
*/ */
FileTruncate(v->mdfd_vfd, 0); FileTruncate(v->mdfd_vfd, 0);
/*
* To call ImmediateSharedRelationCacheInvalidate() here
* isn't good for independency of md stuff,but smgrunlink()
* removes the base file immediately and couldn't be
* rollbacked in case of abort. We must guarantee
* all backends' relation cache invalidation here.
* This would be unnecessary if the truncation is postponed
* till end of transaction.
*/
if (!invalregistered)
{
ImmediateSharedRelationCacheInvalidate(reln);
invalregistered = true;
}
FileUnlink(v->mdfd_vfd); FileUnlink(v->mdfd_vfd);
v = v->mdfd_chain; v = v->mdfd_chain;
Assert(ov != &Md_fdvec[fd]); /* we never drop the 1st segment */ Assert(ov != &Md_fdvec[fd]); /* we never drop the 1st segment */

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.30 1999/11/21 01:58:22 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.31 2000/01/10 06:30:53 inoue Exp $
* *
* Note - this code is real crufty... * Note - this code is real crufty...
* *
@ -79,13 +79,39 @@ typedef InvalidationMessageData *InvalidationMessage;
* variables and macros * variables and macros
* ---------------- * ----------------
*/ */
static LocalInvalid Invalid = EmptyLocalInvalid; /* head of linked list */
/*
* ----------------
* Invalidation info was devided into three parts.
* 1) shared invalidation to be registerd for all backends
* 2) local invalidation for the transaction itself
* 3) rollback information for the transaction itself
* ----------------
*/
/*
* head of invalidation linked list for all backends
* eaten by AtCommit_Cache() in CommitTransaction()
*/
static LocalInvalid InvalidForall = EmptyLocalInvalid;
/*
* head of invalidation linked list for the backend itself
* eaten by AtCommit_LocalCache() in CommandCounterIncrement()
*/
static LocalInvalid InvalidLocal = EmptyLocalInvalid;
/*
* head of rollback linked list for the backend itself
* eaten by AtAbort_Cache() in AbortTransaction()
*/
static LocalInvalid RollbackStack = EmptyLocalInvalid;
static InvalidationEntry InvalidationEntryAllocate(uint16 size); static InvalidationEntry InvalidationEntryAllocate(uint16 size);
static void LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ()); static void LocalInvalidInvalidate(LocalInvalid invalid, void (*function) (), bool freemember);
static LocalInvalid LocalInvalidRegister(LocalInvalid invalid, static LocalInvalid LocalInvalidRegister(LocalInvalid invalid,
InvalidationEntry entry); InvalidationEntry entry);
static void DiscardInvalidStack(LocalInvalid *invalid);
static void InvalidationMessageRegisterSharedInvalid(InvalidationMessage message);
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
@ -130,11 +156,11 @@ LocalInvalidRegister(LocalInvalid invalid,
/* -------------------------------- /* --------------------------------
* LocalInvalidInvalidate * LocalInvalidInvalidate
* Processes, then frees all entries in a local cache * Processes, then frees all entries in a local cache
* invalidation list. * invalidation list unless freemember parameter is false.
* -------------------------------- * --------------------------------
*/ */
static void static void
LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ()) LocalInvalidInvalidate(LocalInvalid invalid, void (*function) (), bool freemember)
{ {
InvalidationEntryData *entryDataP; InvalidationEntryData *entryDataP;
@ -148,6 +174,8 @@ LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ())
invalid = (Pointer) entryDataP->nextP; invalid = (Pointer) entryDataP->nextP;
if (!freemember)
continue;
/* help catch errors */ /* help catch errors */
entryDataP->nextP = (InvalidationUserData *) NULL; entryDataP->nextP = (InvalidationUserData *) NULL;
@ -155,27 +183,57 @@ LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ())
} }
} }
static void
DiscardInvalidStack(LocalInvalid *invalid)
{
LocalInvalid locinv;
locinv = *invalid;
*invalid = EmptyLocalInvalid;
if (locinv)
LocalInvalidInvalidate(locinv, (void (*)()) NULL, true);
}
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* private support functions * private support functions
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
/* -------------------------------- /* --------------------------------
* CacheIdRegisterLocalInvalid * CacheIdRegister.......
* RelationIdRegister....
* -------------------------------- * --------------------------------
*/ */
#ifdef INVALIDDEBUG #ifdef INVALIDDEBUG
#define CacheIdRegisterSpecifiedLocalInvalid_DEBUG1 \
elog(DEBUG, "CacheIdRegisterSpecifiedLocalInvalid(%d, %d, [%d, %d])", \
cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \
ItemPointerGetOffsetNumber(pointer))
#define CacheIdRegisterLocalInvalid_DEBUG1 \ #define CacheIdRegisterLocalInvalid_DEBUG1 \
elog(DEBUG, "CacheIdRegisterLocalInvalid(%d, %d, [%d, %d])", \ elog(DEBUG, "CacheIdRegisterLocalInvalid(%d, %d, [%d, %d])", \
cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \ cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \
ItemPointerGetOffsetNumber(pointer)) ItemPointerGetOffsetNumber(pointer))
#define CacheIdRegisterLocalRollback_DEBUG1 \
elog(DEBUG, "CacheIdRegisterLocalRollback(%d, %d, [%d, %d])", \
cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \
ItemPointerGetOffsetNumber(pointer))
#define CacheIdImmediateRegisterSharedInvalid_DEBUG1 \
elog(DEBUG, "CacheIdImmediateRegisterSharedInvalid(%d, %d, [%d, %d])", \
cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \
ItemPointerGetOffsetNumber(pointer))
#else #else
#define CacheIdRegisterSpecifiedLocalInvalid_DEBUG1
#define CacheIdRegisterLocalInvalid_DEBUG1 #define CacheIdRegisterLocalInvalid_DEBUG1
#define CacheIdRegisterLocalRollback_DEBUG1
#define CacheIdImmediateRegisterSharedInvalid_DEBUG1
#endif /* INVALIDDEBUG */ #endif /* INVALIDDEBUG */
static void /* --------------------------------
CacheIdRegisterLocalInvalid(Index cacheId, * CacheIdRegisterSpecifiedLocalInvalid
Index hashIndex, * --------------------------------
ItemPointer pointer) */
static LocalInvalid
CacheIdRegisterSpecifiedLocalInvalid(LocalInvalid invalid,
Index cacheId, Index hashIndex, ItemPointer pointer)
{ {
InvalidationMessage message; InvalidationMessage message;
@ -183,7 +241,7 @@ CacheIdRegisterLocalInvalid(Index cacheId,
* debugging stuff * debugging stuff
* ---------------- * ----------------
*/ */
CacheIdRegisterLocalInvalid_DEBUG1; CacheIdRegisterSpecifiedLocalInvalid_DEBUG1;
/* ---------------- /* ----------------
* create a message describing the system catalog tuple * create a message describing the system catalog tuple
@ -203,15 +261,106 @@ CacheIdRegisterLocalInvalid(Index cacheId,
* Add message to linked list of unprocessed messages. * Add message to linked list of unprocessed messages.
* ---------------- * ----------------
*/ */
Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry) message); invalid = LocalInvalidRegister(invalid, (InvalidationEntry) message);
return invalid;
} }
/* -------------------------------- /* --------------------------------
* RelationIdRegisterLocalInvalid * CacheIdRegisterLocalInvalid
* -------------------------------- * --------------------------------
*/ */
static void static void
RelationIdRegisterLocalInvalid(Oid relationId, Oid objectId) CacheIdRegisterLocalInvalid(Index cacheId,
Index hashIndex,
ItemPointer pointer)
{
/* ----------------
* debugging stuff
* ----------------
*/
CacheIdRegisterLocalInvalid_DEBUG1;
/* ----------------
* Add message to InvalidForall linked list.
* ----------------
*/
InvalidForall = CacheIdRegisterSpecifiedLocalInvalid(InvalidForall,
cacheId, hashIndex, pointer);
/* ----------------
* Add message to InvalidLocal linked list.
* ----------------
*/
InvalidLocal = CacheIdRegisterSpecifiedLocalInvalid(InvalidLocal,
cacheId, hashIndex, pointer);
}
/* --------------------------------
* CacheIdRegisterLocalRollback
* --------------------------------
*/
static void
CacheIdRegisterLocalRollback(Index cacheId, Index hashIndex,
ItemPointer pointer)
{
/* ----------------
* debugging stuff
* ----------------
*/
CacheIdRegisterLocalRollback_DEBUG1;
/* ----------------
* Add message to RollbackStack linked list.
* ----------------
*/
RollbackStack = CacheIdRegisterSpecifiedLocalInvalid(
RollbackStack, cacheId, hashIndex, pointer);
}
/* --------------------------------
* CacheIdImmediateRegisterSharedInvalid
* --------------------------------
*/
static void
CacheIdImmediateRegisterSharedInvalid(Index cacheId, Index hashIndex,
ItemPointer pointer)
{
InvalidationMessage message;
/* ----------------
* debugging stuff
* ----------------
*/
CacheIdImmediateRegisterSharedInvalid_DEBUG1;
/* ----------------
* create a message describing the system catalog tuple
* we wish to invalidate.
* ----------------
*/
message = (InvalidationMessage)
InvalidationEntryAllocate(sizeof(InvalidationMessageData));
message->kind = 'c';
message->any.catalog.cacheId = cacheId;
message->any.catalog.hashIndex = hashIndex;
ItemPointerCopy(pointer, &message->any.catalog.pointerData);
/* ----------------
* Register a shared catalog cache invalidation.
* ----------------
*/
InvalidationMessageRegisterSharedInvalid(message);
free((Pointer) &((InvalidationUserData *) message)->dataP[-1]);
}
/* --------------------------------
* RelationIdRegisterSpecifiedLocalInvalid
* --------------------------------
*/
static LocalInvalid
RelationIdRegisterSpecifiedLocalInvalid(LocalInvalid invalid,
Oid relationId, Oid objectId)
{ {
InvalidationMessage message; InvalidationMessage message;
@ -220,7 +369,7 @@ RelationIdRegisterLocalInvalid(Oid relationId, Oid objectId)
* ---------------- * ----------------
*/ */
#ifdef INVALIDDEBUG #ifdef INVALIDDEBUG
elog(DEBUG, "RelationRegisterLocalInvalid(%u, %u)", relationId, elog(DEBUG, "RelationRegisterSpecifiedLocalInvalid(%u, %u)", relationId,
objectId); objectId);
#endif /* defined(INVALIDDEBUG) */ #endif /* defined(INVALIDDEBUG) */
@ -240,7 +389,101 @@ RelationIdRegisterLocalInvalid(Oid relationId, Oid objectId)
* Add message to linked list of unprocessed messages. * Add message to linked list of unprocessed messages.
* ---------------- * ----------------
*/ */
Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry) message); invalid = LocalInvalidRegister(invalid, (InvalidationEntry) message);
return invalid;
}
/* --------------------------------
* RelationIdRegisterLocalInvalid
* --------------------------------
*/
static void
RelationIdRegisterLocalInvalid(Oid relationId, Oid objectId)
{
/* ----------------
* debugging stuff
* ----------------
*/
#ifdef INVALIDDEBUG
elog(DEBUG, "RelationRegisterLocalInvalid(%u, %u)", relationId,
objectId);
#endif /* defined(INVALIDDEBUG) */
/* ----------------
* Add message to InvalidForall linked list.
* ----------------
*/
InvalidForall = RelationIdRegisterSpecifiedLocalInvalid(InvalidForall,
relationId, objectId);
/* ----------------
* Add message to InvalidLocal linked list.
* ----------------
*/
InvalidLocal = RelationIdRegisterSpecifiedLocalInvalid(InvalidLocal,
relationId, objectId);
}
/* --------------------------------
* RelationIdRegisterLocalRollback
* --------------------------------
*/
static void
RelationIdRegisterLocalRollback(Oid relationId, Oid objectId)
{
/* ----------------
* debugging stuff
* ----------------
*/
#ifdef INVALIDDEBUG
elog(DEBUG, "RelationRegisterLocalRollback(%u, %u)", relationId,
objectId);
#endif /* defined(INVALIDDEBUG) */
/* ----------------
* Add message to RollbackStack linked list.
* ----------------
*/
RollbackStack = RelationIdRegisterSpecifiedLocalInvalid(
RollbackStack, relationId, objectId);
}
/* --------------------------------
* RelationIdImmediateRegisterSharedInvalid
* --------------------------------
*/
static void
RelationIdImmediateRegisterSharedInvalid(Oid relationId, Oid objectId)
{
InvalidationMessage message;
/* ----------------
* debugging stuff
* ----------------
*/
#ifdef INVALIDDEBUG
elog(DEBUG, "RelationImmediateRegisterSharedInvalid(%u, %u)", relationId,
objectId);
#endif /* defined(INVALIDDEBUG) */
/* ----------------
* create a message describing the relation descriptor
* we wish to invalidate.
* ----------------
*/
message = (InvalidationMessage)
InvalidationEntryAllocate(sizeof(InvalidationMessageData));
message->kind = 'r';
message->any.relation.relationId = relationId;
message->any.relation.objectId = objectId;
/* ----------------
* Register a shared catalog cache invalidation.
* ----------------
*/
InvalidationMessageRegisterSharedInvalid(message);
free((Pointer) &((InvalidationUserData *) message)->dataP[-1]);
} }
/* -------------------------------- /* --------------------------------
@ -397,7 +640,7 @@ InvalidationMessageCacheInvalidate(InvalidationMessage message)
case 'c': /* cached system catalog tuple */ case 'c': /* cached system catalog tuple */
InvalidationMessageCacheInvalidate_DEBUG1; InvalidationMessageCacheInvalidate_DEBUG1;
CatalogCacheIdInvalidate(message->any.catalog.cacheId, CacheIdInvalidate(message->any.catalog.cacheId,
message->any.catalog.hashIndex, message->any.catalog.hashIndex,
&message->any.catalog.pointerData); &message->any.catalog.pointerData);
break; break;
@ -405,7 +648,9 @@ InvalidationMessageCacheInvalidate(InvalidationMessage message)
case 'r': /* cached relation descriptor */ case 'r': /* cached relation descriptor */
InvalidationMessageCacheInvalidate_DEBUG2; InvalidationMessageCacheInvalidate_DEBUG2;
/* XXX ignore this--is this correct ??? */ CacheIdInvalidate(message->any.relation.relationId,
message->any.relation.objectId,
(ItemPointer) NULL);
break; break;
default: default:
@ -500,38 +745,93 @@ RegisterInvalid(bool send)
* Process and free the current list of inval messages. * Process and free the current list of inval messages.
* ---------------- * ----------------
*/ */
invalid = Invalid;
Invalid = EmptyLocalInvalid; /* anything added now is part of a new list */
DiscardInvalidStack(&InvalidLocal);
if (send) if (send)
LocalInvalidInvalidate(invalid, {
InvalidationMessageRegisterSharedInvalid); DiscardInvalidStack(&RollbackStack);
invalid = InvalidForall;
InvalidForall = EmptyLocalInvalid; /* clear InvalidForall */
LocalInvalidInvalidate(invalid, InvalidationMessageRegisterSharedInvalid, true);
}
else else
LocalInvalidInvalidate(invalid, {
InvalidationMessageCacheInvalidate); DiscardInvalidStack(&InvalidForall);
invalid = RollbackStack;
RollbackStack = EmptyLocalInvalid; /* clear RollbackStack */
LocalInvalidInvalidate(invalid, InvalidationMessageCacheInvalidate, true);
}
} }
/* /*
* RelationIdInvalidateHeapTuple * ImmediateLocalInvalidation
* Causes the given tuple in a relation to be invalidated. * Causes invalidation immediately for the next command of the transaction.
* *
* Note: * Note:
* This should be called in time of CommandCounterIncrement().
*/
void
ImmediateLocalInvalidation(bool send)
{
LocalInvalid invalid;
/* ----------------
* debugging stuff
* ----------------
*/
#ifdef INVALIDDEBUG
elog(DEBUG, "ImmediateLocalInvalidation(%d) called", send);
#endif /* defined(INVALIDDEBUG) */
/* ----------------
* Process and free the local list of inval messages.
* ----------------
*/
if (send)
{
invalid = InvalidLocal;
InvalidLocal = EmptyLocalInvalid; /* clear InvalidLocal */
LocalInvalidInvalidate(invalid, InvalidationMessageCacheInvalidate, true);
}
else
{
/*
* This may be used for rollback to a savepoint.
* Don't clear InvalidForall and RollbackStack here.
*/
DiscardInvalidStack(&InvalidLocal);
invalid = RollbackStack;
LocalInvalidInvalidate(invalid, InvalidationMessageCacheInvalidate, false);
}
}
/*
* InvokeHeapTupleInvalidation
* Invoke functions for the tuple which register invalidation
* of catalog/relation cache.
* Note:
* Assumes object id is valid. * Assumes object id is valid.
* Assumes tuple is valid. * Assumes tuple is valid.
*/ */
#ifdef INVALIDDEBUG #ifdef INVALIDDEBUG
#define RelationInvalidateHeapTuple_DEBUG1 \ #define InvokeHeapTupleInvalidation_DEBUG1 \
elog(DEBUG, "RelationInvalidateHeapTuple(%s, [%d,%d])", \ elog(DEBUG, "%s(%s, [%d,%d])", \
funcname,\
RelationGetPhysicalRelationName(relation), \ RelationGetPhysicalRelationName(relation), \
ItemPointerGetBlockNumber(&tuple->t_ctid), \ ItemPointerGetBlockNumber(&tuple->t_self), \
ItemPointerGetOffsetNumber(&tuple->t_ctid)) ItemPointerGetOffsetNumber(&tuple->t_self))
#else #else
#define RelationInvalidateHeapTuple_DEBUG1 #define InvokeHeapTupleInvalidation_DEBUG1
#endif /* defined(INVALIDDEBUG) */ #endif /* defined(INVALIDDEBUG) */
void static void
RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple) InvokeHeapTupleInvalidation(Relation relation, HeapTuple tuple,
void (*CacheIdRegisterFunc)(),
void (*RelationIdRegisterFunc)(),
const char *funcname)
{ {
/* ---------------- /* ----------------
* sanity checks * sanity checks
@ -553,13 +853,88 @@ RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple)
* debugging stuff * debugging stuff
* ---------------- * ----------------
*/ */
RelationInvalidateHeapTuple_DEBUG1; InvokeHeapTupleInvalidation_DEBUG1;
RelationInvalidateCatalogCacheTuple(relation, RelationInvalidateCatalogCacheTuple(relation, tuple,
tuple, CacheIdRegisterFunc);
CacheIdRegisterLocalInvalid);
RelationInvalidateRelationCache(relation, RelationInvalidateRelationCache(relation, tuple,
tuple, RelationIdRegisterFunc);
RelationIdRegisterLocalInvalid); }
/*
* RelationInvalidateHeapTuple
* Causes the given tuple in a relation to be invalidated.
*/
void
RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple)
{
InvokeHeapTupleInvalidation(relation, tuple,
CacheIdRegisterLocalInvalid,
RelationIdRegisterLocalInvalid,
"RelationInvalidateHeapTuple");
}
/*
* RelationMark4RollbackHeapTuple
* keep the given tuple in a relation to be invalidated
* in case of abort.
*/
void
RelationMark4RollbackHeapTuple(Relation relation, HeapTuple tuple)
{
InvokeHeapTupleInvalidation(relation, tuple,
CacheIdRegisterLocalRollback,
RelationIdRegisterLocalRollback,
"RelationMark4RollbackHeapTuple");
}
/*
* ImmediateInvalidateSharedHeapTuple
* Different from RelationInvalidateHeapTuple()
* this function queues shared invalidation info immediately.
*/
void
ImmediateInvalidateSharedHeapTuple(Relation relation, HeapTuple tuple)
{
InvokeHeapTupleInvalidation(relation, tuple,
CacheIdImmediateRegisterSharedInvalid,
RelationIdImmediateRegisterSharedInvalid,
"ImmediateInvalidateSharedHeapTuple");
}
/*
* ImmediateSharedRelationCacheInvalidate
* Register shared relation cache invalidation immediately
*
* This is needed for smgrunlink()/smgrtruncate().
* Those functions unlink/truncate the base file immediately
* and couldn't be rollbacked in case of abort/crash.
* So relation cache invalidation must be registerd immediately.
* Note:
* Assumes Relation is valid.
*/
void
ImmediateSharedRelationCacheInvalidate(Relation relation)
{
/* ----------------
* sanity checks
* ----------------
*/
Assert(RelationIsValid(relation));
if (IsBootstrapProcessingMode())
return;
/* ----------------
* debugging stuff
* ----------------
*/
#ifdef INVALIDDEBUG
elog(DEBUG, "ImmediateSharedRelationCacheInvalidate(%s)", \
RelationGetPhysicalRelationName(relation));
#endif /* defined(INVALIDDEBUG) */
RelationIdImmediateRegisterSharedInvalid(
RelOid_pg_class, RelationGetRelid(relation));
} }

View File

@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: inval.h,v 1.14 1999/11/21 01:58:20 tgl Exp $ * $Id: inval.h,v 1.15 2000/01/10 06:30:56 inoue Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -19,6 +19,14 @@ extern void DiscardInvalid(void);
extern void RegisterInvalid(bool send); extern void RegisterInvalid(bool send);
extern void ImmediateLocalInvalidation(bool send);
extern void RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple); extern void RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple);
extern void RelationMark4RollbackHeapTuple(Relation relation, HeapTuple tuple);
extern void ImmediateInvalidateSharedHeapTuple(Relation relation, HeapTuple tuple);
extern void ImmediateSharedRelationCacheInvalidate(Relation relation);
#endif /* INVAL_H */ #endif /* INVAL_H */