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
* $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
@ -1262,7 +1262,7 @@ heap_insert(Relation relation, HeapTuple tup)
RelationPutHeapTupleAtEnd(relation, tup);
if (IsSystemRelationName(RelationGetRelationName(relation)))
RelationInvalidateHeapTuple(relation, tup);
RelationMark4RollbackHeapTuple(relation, tup);
return tup->t_data->t_oid;
}
@ -1473,6 +1473,8 @@ l2:
RelationPutHeapTupleAtEnd(relation, newtup);
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

View File

@ -7,7 +7,7 @@
*
*
* 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
* Transaction aborts can now occur two ways:
@ -165,6 +165,7 @@ static void AtAbort_Cache(void);
static void AtAbort_Locks(void);
static void AtAbort_Memory(void);
static void AtCommit_Cache(void);
static void AtCommit_LocalCache(void);
static void AtCommit_Locks(void);
static void AtCommit_Memory(void);
static void AtStart_Cache(void);
@ -512,8 +513,11 @@ CommandCounterIncrement()
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();
}
@ -663,15 +667,26 @@ static void
AtCommit_Cache()
{
/* ----------------
* Make catalog changes visible to me for the next command.
* 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.
* Make catalog changes visible to all backend.
* ----------------
*/
RegisterInvalid(true);
}
/* --------------------------------
* AtCommit_LocalCache
* --------------------------------
*/
static void
AtCommit_LocalCache()
{
/* ----------------
* Make catalog changes visible to me for the next command.
* ----------------
*/
ImmediateLocalInvalidation(true);
}
/* --------------------------------
* AtCommit_Locks
* --------------------------------

View File

@ -7,7 +7,7 @@
*
*
* 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 "miscadmin.h"
#include "storage/smgr.h"
#include "utils/inval.h" /* ImmediateSharedRelationCacheInvalidate() */
#undef DIAGNOSTIC
@ -203,6 +204,15 @@ mdunlink(Relation reln)
*/
if (reln->rd_unlinked && reln->rd_fd < 0)
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
* won't miss deleting any of them.
@ -779,6 +789,7 @@ mdtruncate(Relation reln, int nblocks)
#ifndef LET_OS_MANAGE_FILESIZE
MemoryContext oldcxt;
int priorblocks;
bool invalregistered = false;
#endif
/* NOTE: mdnblocks makes sure we have opened all existing segments,
@ -810,6 +821,20 @@ mdtruncate(Relation reln, int nblocks)
* a big file...
*/
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);
v = v->mdfd_chain;
Assert(ov != &Md_fdvec[fd]); /* we never drop the 1st segment */

View File

@ -7,7 +7,7 @@
*
*
* 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...
*
@ -79,13 +79,39 @@ typedef InvalidationMessageData *InvalidationMessage;
* 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 void LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ());
static void LocalInvalidInvalidate(LocalInvalid invalid, void (*function) (), bool freemember);
static LocalInvalid LocalInvalidRegister(LocalInvalid invalid,
InvalidationEntry entry);
static void DiscardInvalidStack(LocalInvalid *invalid);
static void InvalidationMessageRegisterSharedInvalid(InvalidationMessage message);
/* ----------------------------------------------------------------
@ -130,11 +156,11 @@ LocalInvalidRegister(LocalInvalid invalid,
/* --------------------------------
* LocalInvalidInvalidate
* Processes, then frees all entries in a local cache
* invalidation list.
* invalidation list unless freemember parameter is false.
* --------------------------------
*/
static void
LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ())
LocalInvalidInvalidate(LocalInvalid invalid, void (*function) (), bool freemember)
{
InvalidationEntryData *entryDataP;
@ -148,6 +174,8 @@ LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ())
invalid = (Pointer) entryDataP->nextP;
if (!freemember)
continue;
/* help catch errors */
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
* ----------------------------------------------------------------
*/
/* --------------------------------
* CacheIdRegisterLocalInvalid
* CacheIdRegister.......
* RelationIdRegister....
* --------------------------------
*/
#ifdef INVALIDDEBUG
#define CacheIdRegisterSpecifiedLocalInvalid_DEBUG1 \
elog(DEBUG, "CacheIdRegisterSpecifiedLocalInvalid(%d, %d, [%d, %d])", \
cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \
ItemPointerGetOffsetNumber(pointer))
#define CacheIdRegisterLocalInvalid_DEBUG1 \
elog(DEBUG, "CacheIdRegisterLocalInvalid(%d, %d, [%d, %d])", \
cacheId, hashIndex, ItemPointerGetBlockNumber(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
#define CacheIdRegisterSpecifiedLocalInvalid_DEBUG1
#define CacheIdRegisterLocalInvalid_DEBUG1
#define CacheIdRegisterLocalRollback_DEBUG1
#define CacheIdImmediateRegisterSharedInvalid_DEBUG1
#endif /* INVALIDDEBUG */
static void
CacheIdRegisterLocalInvalid(Index cacheId,
Index hashIndex,
ItemPointer pointer)
/* --------------------------------
* CacheIdRegisterSpecifiedLocalInvalid
* --------------------------------
*/
static LocalInvalid
CacheIdRegisterSpecifiedLocalInvalid(LocalInvalid invalid,
Index cacheId, Index hashIndex, ItemPointer pointer)
{
InvalidationMessage message;
@ -183,7 +241,7 @@ CacheIdRegisterLocalInvalid(Index cacheId,
* debugging stuff
* ----------------
*/
CacheIdRegisterLocalInvalid_DEBUG1;
CacheIdRegisterSpecifiedLocalInvalid_DEBUG1;
/* ----------------
* create a message describing the system catalog tuple
@ -203,15 +261,106 @@ CacheIdRegisterLocalInvalid(Index cacheId,
* Add message to linked list of unprocessed messages.
* ----------------
*/
Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry) message);
invalid = LocalInvalidRegister(invalid, (InvalidationEntry) message);
return invalid;
}
/* --------------------------------
* RelationIdRegisterLocalInvalid
* CacheIdRegisterLocalInvalid
* --------------------------------
*/
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;
@ -220,7 +369,7 @@ RelationIdRegisterLocalInvalid(Oid relationId, Oid objectId)
* ----------------
*/
#ifdef INVALIDDEBUG
elog(DEBUG, "RelationRegisterLocalInvalid(%u, %u)", relationId,
elog(DEBUG, "RelationRegisterSpecifiedLocalInvalid(%u, %u)", relationId,
objectId);
#endif /* defined(INVALIDDEBUG) */
@ -240,7 +389,101 @@ RelationIdRegisterLocalInvalid(Oid relationId, Oid objectId)
* 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 */
InvalidationMessageCacheInvalidate_DEBUG1;
CatalogCacheIdInvalidate(message->any.catalog.cacheId,
CacheIdInvalidate(message->any.catalog.cacheId,
message->any.catalog.hashIndex,
&message->any.catalog.pointerData);
break;
@ -405,7 +648,9 @@ InvalidationMessageCacheInvalidate(InvalidationMessage message)
case 'r': /* cached relation descriptor */
InvalidationMessageCacheInvalidate_DEBUG2;
/* XXX ignore this--is this correct ??? */
CacheIdInvalidate(message->any.relation.relationId,
message->any.relation.objectId,
(ItemPointer) NULL);
break;
default:
@ -500,38 +745,93 @@ RegisterInvalid(bool send)
* 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)
LocalInvalidInvalidate(invalid,
InvalidationMessageRegisterSharedInvalid);
{
DiscardInvalidStack(&RollbackStack);
invalid = InvalidForall;
InvalidForall = EmptyLocalInvalid; /* clear InvalidForall */
LocalInvalidInvalidate(invalid, InvalidationMessageRegisterSharedInvalid, true);
}
else
LocalInvalidInvalidate(invalid,
InvalidationMessageCacheInvalidate);
{
DiscardInvalidStack(&InvalidForall);
invalid = RollbackStack;
RollbackStack = EmptyLocalInvalid; /* clear RollbackStack */
LocalInvalidInvalidate(invalid, InvalidationMessageCacheInvalidate, true);
}
}
/*
* RelationIdInvalidateHeapTuple
* Causes the given tuple in a relation to be invalidated.
* ImmediateLocalInvalidation
* Causes invalidation immediately for the next command of the transaction.
*
* 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 tuple is valid.
*/
#ifdef INVALIDDEBUG
#define RelationInvalidateHeapTuple_DEBUG1 \
elog(DEBUG, "RelationInvalidateHeapTuple(%s, [%d,%d])", \
#define InvokeHeapTupleInvalidation_DEBUG1 \
elog(DEBUG, "%s(%s, [%d,%d])", \
funcname,\
RelationGetPhysicalRelationName(relation), \
ItemPointerGetBlockNumber(&tuple->t_ctid), \
ItemPointerGetOffsetNumber(&tuple->t_ctid))
ItemPointerGetBlockNumber(&tuple->t_self), \
ItemPointerGetOffsetNumber(&tuple->t_self))
#else
#define RelationInvalidateHeapTuple_DEBUG1
#define InvokeHeapTupleInvalidation_DEBUG1
#endif /* defined(INVALIDDEBUG) */
void
RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple)
static void
InvokeHeapTupleInvalidation(Relation relation, HeapTuple tuple,
void (*CacheIdRegisterFunc)(),
void (*RelationIdRegisterFunc)(),
const char *funcname)
{
/* ----------------
* sanity checks
@ -553,13 +853,88 @@ RelationInvalidateHeapTuple(Relation relation, HeapTuple tuple)
* debugging stuff
* ----------------
*/
RelationInvalidateHeapTuple_DEBUG1;
InvokeHeapTupleInvalidation_DEBUG1;
RelationInvalidateCatalogCacheTuple(relation,
tuple,
CacheIdRegisterLocalInvalid);
RelationInvalidateCatalogCacheTuple(relation, tuple,
CacheIdRegisterFunc);
RelationInvalidateRelationCache(relation,
tuple,
RelationIdRegisterLocalInvalid);
RelationInvalidateRelationCache(relation, tuple,
RelationIdRegisterFunc);
}
/*
* 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
*
* $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 ImmediateLocalInvalidation(bool send);
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 */