mirror of
https://github.com/postgres/postgres.git
synced 2025-07-23 03:21:12 +03:00
Fix problem reported by Alex Korn: if a relation has been dropped and
recreated since the start of our transaction, our first reference to it errored out because we'd try to reuse our old relcache entry for it. Do this by accepting SI inval messages just before relcache search in heap_openr, so that dead relcache entries will be flushed before we search. Also, break heap_open/openr into two pairs of routines, relation_open(r) and heap_open(r). The relation_open routines make no tests on relkind and so can be used to open anything that has a pg_class entry. The heap_open routines are wrappers that add a relkind test to preserve their established behavior. Use the relation_open routines in several places that had various kluge solutions for opening rels that might be either heap or index rels. Also, remove the old 'heap stats' code that's been superseded by Jan's stats collector, and clean up some inconsistencies in error reporting between the different types of ALTER TABLE.
This commit is contained in:
@ -4,7 +4,7 @@
|
||||
# Makefile for access/heap
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/backend/access/heap/Makefile,v 1.11 2000/08/31 16:09:33 petere Exp $
|
||||
# $Header: /cvsroot/pgsql/src/backend/access/heap/Makefile,v 1.12 2001/11/02 16:30:29 tgl Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -12,7 +12,7 @@ subdir = src/backend/access/heap
|
||||
top_builddir = ../../../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = heapam.o hio.o stats.o tuptoaster.o
|
||||
OBJS = heapam.o hio.o tuptoaster.o
|
||||
|
||||
all: SUBSYS.o
|
||||
|
||||
|
@ -8,14 +8,16 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.126 2001/10/25 05:49:21 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.127 2001/11/02 16:30:29 tgl Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
* heap_open - open a heap relation by relationId
|
||||
* relation_open - open any relation by relation OID
|
||||
* relation_openr - open any relation by name
|
||||
* relation_close - close any relation
|
||||
* heap_open - open a heap relation by relation OID
|
||||
* heap_openr - open a heap relation by name
|
||||
* heap_open[r]_nofail - same, but return NULL on failure instead of elog
|
||||
* heap_close - close a heap relation
|
||||
* heap_close - (now just a macro for relation_close)
|
||||
* heap_beginscan - begin relation scan
|
||||
* heap_rescan - restart a relation scan
|
||||
* heap_endscan - end relation scan
|
||||
@ -440,15 +442,21 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
|
||||
*/
|
||||
|
||||
/* ----------------
|
||||
* heap_open - open a heap relation by relationId
|
||||
* relation_open - open any relation by relation OID
|
||||
*
|
||||
* If lockmode is not "NoLock", the specified kind of lock is
|
||||
* obtained on the relation.
|
||||
* obtained on the relation. (Generally, NoLock should only be
|
||||
* used if the caller knows it has some appropriate lock on the
|
||||
* relation already.)
|
||||
*
|
||||
* An error is raised if the relation does not exist.
|
||||
*
|
||||
* NB: a "relation" is anything with a pg_class entry. The caller is
|
||||
* expected to check whether the relkind is something it can handle.
|
||||
* ----------------
|
||||
*/
|
||||
Relation
|
||||
heap_open(Oid relationId, LOCKMODE lockmode)
|
||||
relation_open(Oid relationId, LOCKMODE lockmode)
|
||||
{
|
||||
Relation r;
|
||||
|
||||
@ -466,10 +474,6 @@ heap_open(Oid relationId, LOCKMODE lockmode)
|
||||
if (!RelationIsValid(r))
|
||||
elog(ERROR, "Relation %u does not exist", relationId);
|
||||
|
||||
/* Under no circumstances will we return an index as a relation. */
|
||||
if (r->rd_rel->relkind == RELKIND_INDEX)
|
||||
elog(ERROR, "%s is an index relation", RelationGetRelationName(r));
|
||||
|
||||
if (lockmode != NoLock)
|
||||
LockRelation(r, lockmode);
|
||||
|
||||
@ -477,15 +481,13 @@ heap_open(Oid relationId, LOCKMODE lockmode)
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* heap_openr - open a heap relation by name
|
||||
* relation_openr - open any relation by name
|
||||
*
|
||||
* If lockmode is not "NoLock", the specified kind of lock is
|
||||
* obtained on the relation.
|
||||
* An error is raised if the relation does not exist.
|
||||
* As above, but lookup by name instead of OID.
|
||||
* ----------------
|
||||
*/
|
||||
Relation
|
||||
heap_openr(const char *relationName, LOCKMODE lockmode)
|
||||
relation_openr(const char *relationName, LOCKMODE lockmode)
|
||||
{
|
||||
Relation r;
|
||||
|
||||
@ -497,102 +499,44 @@ heap_openr(const char *relationName, LOCKMODE lockmode)
|
||||
IncrHeapAccessStat(local_openr);
|
||||
IncrHeapAccessStat(global_openr);
|
||||
|
||||
/*
|
||||
* Check for shared-cache-inval messages before trying to open the
|
||||
* relation. This is needed to cover the case where the name identifies
|
||||
* a rel that has been dropped and recreated since the start of our
|
||||
* transaction: if we don't flush the old relcache entry then we'll
|
||||
* latch onto that entry and suffer an error when we do LockRelation.
|
||||
* Note that relation_open does not need to do this, since a relation's
|
||||
* OID never changes.
|
||||
*
|
||||
* We skip this if asked for NoLock, on the assumption that the caller
|
||||
* has already ensured some appropriate lock is held.
|
||||
*/
|
||||
if (lockmode != NoLock)
|
||||
AcceptInvalidationMessages();
|
||||
|
||||
/* The relcache does all the real work... */
|
||||
r = RelationNameGetRelation(relationName);
|
||||
|
||||
if (!RelationIsValid(r))
|
||||
elog(ERROR, "Relation '%s' does not exist", relationName);
|
||||
|
||||
/* Under no circumstances will we return an index as a relation. */
|
||||
if (r->rd_rel->relkind == RELKIND_INDEX)
|
||||
elog(ERROR, "%s is an index relation", RelationGetRelationName(r));
|
||||
elog(ERROR, "Relation \"%s\" does not exist", relationName);
|
||||
|
||||
if (lockmode != NoLock)
|
||||
LockRelation(r, lockmode);
|
||||
|
||||
pgstat_initstats(&r->pgstat_info, r);
|
||||
|
||||
pgstat_initstats(&r->pgstat_info, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* heap_open_nofail - open a heap relation by relationId,
|
||||
* do not raise error on failure
|
||||
*
|
||||
* The caller must check for a NULL return value indicating
|
||||
* that no such relation exists.
|
||||
* No lock is obtained on the relation, either.
|
||||
* ----------------
|
||||
*/
|
||||
Relation
|
||||
heap_open_nofail(Oid relationId)
|
||||
{
|
||||
Relation r;
|
||||
|
||||
/*
|
||||
* increment access statistics
|
||||
*/
|
||||
IncrHeapAccessStat(local_open);
|
||||
IncrHeapAccessStat(global_open);
|
||||
|
||||
/* The relcache does all the real work... */
|
||||
r = RelationIdGetRelation(relationId);
|
||||
|
||||
/* Under no circumstances will we return an index as a relation. */
|
||||
if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX)
|
||||
elog(ERROR, "%s is an index relation", RelationGetRelationName(r));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* heap_openr_nofail - open a heap relation by name,
|
||||
* do not raise error on failure
|
||||
*
|
||||
* The caller must check for a NULL return value indicating
|
||||
* that no such relation exists.
|
||||
* No lock is obtained on the relation, either.
|
||||
* ----------------
|
||||
*/
|
||||
Relation
|
||||
heap_openr_nofail(const char *relationName)
|
||||
{
|
||||
Relation r;
|
||||
|
||||
/*
|
||||
* increment access statistics
|
||||
*/
|
||||
IncrHeapAccessStat(local_openr);
|
||||
IncrHeapAccessStat(global_openr);
|
||||
|
||||
/* The relcache does all the real work... */
|
||||
r = RelationNameGetRelation(relationName);
|
||||
|
||||
/* Under no circumstances will we return an index as a relation. */
|
||||
if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX)
|
||||
elog(ERROR, "%s is an index relation", RelationGetRelationName(r));
|
||||
|
||||
if (RelationIsValid(r))
|
||||
pgstat_initstats(&r->pgstat_info, r);
|
||||
|
||||
if (RelationIsValid(r))
|
||||
pgstat_initstats(&r->pgstat_info, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* heap_close - close a heap relation
|
||||
* relation_close - close any relation
|
||||
*
|
||||
* If lockmode is not "NoLock", we first release the specified lock.
|
||||
* Note that it is often sensible to hold a lock beyond heap_close;
|
||||
*
|
||||
* Note that it is often sensible to hold a lock beyond relation_close;
|
||||
* in that case, the lock is released automatically at xact end.
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
heap_close(Relation relation, LOCKMODE lockmode)
|
||||
relation_close(Relation relation, LOCKMODE lockmode)
|
||||
{
|
||||
Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
|
||||
|
||||
@ -610,6 +554,59 @@ heap_close(Relation relation, LOCKMODE lockmode)
|
||||
}
|
||||
|
||||
|
||||
/* ----------------
|
||||
* heap_open - open a heap relation by relation OID
|
||||
*
|
||||
* This is essentially relation_open plus check that the relation
|
||||
* is not an index or special relation. (The caller should also check
|
||||
* that it's not a view before assuming it has storage.)
|
||||
* ----------------
|
||||
*/
|
||||
Relation
|
||||
heap_open(Oid relationId, LOCKMODE lockmode)
|
||||
{
|
||||
Relation r;
|
||||
|
||||
r = relation_open(relationId, lockmode);
|
||||
|
||||
if (r->rd_rel->relkind == RELKIND_INDEX)
|
||||
elog(ERROR, "%s is an index relation",
|
||||
RelationGetRelationName(r));
|
||||
else if (r->rd_rel->relkind == RELKIND_SPECIAL)
|
||||
elog(ERROR, "%s is a special relation",
|
||||
RelationGetRelationName(r));
|
||||
|
||||
pgstat_initstats(&r->pgstat_info, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* heap_openr - open a heap relation by name
|
||||
*
|
||||
* As above, but lookup by name instead of OID.
|
||||
* ----------------
|
||||
*/
|
||||
Relation
|
||||
heap_openr(const char *relationName, LOCKMODE lockmode)
|
||||
{
|
||||
Relation r;
|
||||
|
||||
r = relation_openr(relationName, lockmode);
|
||||
|
||||
if (r->rd_rel->relkind == RELKIND_INDEX)
|
||||
elog(ERROR, "%s is an index relation",
|
||||
RelationGetRelationName(r));
|
||||
else if (r->rd_rel->relkind == RELKIND_SPECIAL)
|
||||
elog(ERROR, "%s is a special relation",
|
||||
RelationGetRelationName(r));
|
||||
|
||||
pgstat_initstats(&r->pgstat_info, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------
|
||||
* heap_beginscan - begin relation scan
|
||||
* ----------------
|
||||
@ -2332,8 +2329,7 @@ newsame:;
|
||||
}
|
||||
|
||||
/* undo */
|
||||
if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied
|
||||
* ?! */
|
||||
if (XLByteLT(PageGetLSN(page), lsn)) /* changes not applied?! */
|
||||
elog(STOP, "heap_update_undo: bad new tuple page LSN");
|
||||
|
||||
elog(STOP, "heap_update_undo: unimplemented");
|
||||
|
@ -1,333 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* stats.c
|
||||
* heap access method debugging statistic collection routines
|
||||
*
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/heap/Attic/stats.c,v 1.25 2001/10/25 05:49:21 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* initam should be moved someplace else.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/heapam.h"
|
||||
|
||||
|
||||
static void InitHeapAccessStatistics(void);
|
||||
|
||||
/* ----------------
|
||||
* InitHeapAccessStatistics
|
||||
* ----------------
|
||||
*/
|
||||
HeapAccessStatistics heap_access_stats = (HeapAccessStatistics) NULL;
|
||||
|
||||
static void
|
||||
InitHeapAccessStatistics()
|
||||
{
|
||||
MemoryContext oldContext;
|
||||
HeapAccessStatistics stats;
|
||||
|
||||
/*
|
||||
* make sure we don't initialize things twice
|
||||
*/
|
||||
if (heap_access_stats != NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* allocate statistics structure from the top memory context
|
||||
*/
|
||||
oldContext = MemoryContextSwitchTo(TopMemoryContext);
|
||||
|
||||
stats = (HeapAccessStatistics)
|
||||
palloc(sizeof(HeapAccessStatisticsData));
|
||||
|
||||
/*
|
||||
* initialize fields to default values
|
||||
*/
|
||||
stats->global_open = 0;
|
||||
stats->global_openr = 0;
|
||||
stats->global_close = 0;
|
||||
stats->global_beginscan = 0;
|
||||
stats->global_rescan = 0;
|
||||
stats->global_endscan = 0;
|
||||
stats->global_getnext = 0;
|
||||
stats->global_fetch = 0;
|
||||
stats->global_insert = 0;
|
||||
stats->global_delete = 0;
|
||||
stats->global_replace = 0;
|
||||
stats->global_mark4update = 0;
|
||||
stats->global_markpos = 0;
|
||||
stats->global_restrpos = 0;
|
||||
stats->global_BufferGetRelation = 0;
|
||||
stats->global_RelationIdGetRelation = 0;
|
||||
stats->global_RelationIdGetRelation_Buf = 0;
|
||||
stats->global_getreldesc = 0;
|
||||
stats->global_heapgettup = 0;
|
||||
stats->global_RelationPutHeapTuple = 0;
|
||||
stats->global_RelationPutLongHeapTuple = 0;
|
||||
|
||||
stats->local_open = 0;
|
||||
stats->local_openr = 0;
|
||||
stats->local_close = 0;
|
||||
stats->local_beginscan = 0;
|
||||
stats->local_rescan = 0;
|
||||
stats->local_endscan = 0;
|
||||
stats->local_getnext = 0;
|
||||
stats->local_fetch = 0;
|
||||
stats->local_insert = 0;
|
||||
stats->local_delete = 0;
|
||||
stats->local_replace = 0;
|
||||
stats->local_mark4update = 0;
|
||||
stats->local_markpos = 0;
|
||||
stats->local_restrpos = 0;
|
||||
stats->local_BufferGetRelation = 0;
|
||||
stats->local_RelationIdGetRelation = 0;
|
||||
stats->local_RelationIdGetRelation_Buf = 0;
|
||||
stats->local_getreldesc = 0;
|
||||
stats->local_heapgettup = 0;
|
||||
stats->local_RelationPutHeapTuple = 0;
|
||||
stats->local_RelationPutLongHeapTuple = 0;
|
||||
stats->local_RelationNameGetRelation = 0;
|
||||
stats->global_RelationNameGetRelation = 0;
|
||||
|
||||
/*
|
||||
* record init times
|
||||
*/
|
||||
time(&stats->init_global_timestamp);
|
||||
time(&stats->local_reset_timestamp);
|
||||
time(&stats->last_request_timestamp);
|
||||
|
||||
/*
|
||||
* return to old memory context
|
||||
*/
|
||||
MemoryContextSwitchTo(oldContext);
|
||||
|
||||
heap_access_stats = stats;
|
||||
}
|
||||
|
||||
#ifdef NOT_USED
|
||||
/* ----------------
|
||||
* ResetHeapAccessStatistics
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
ResetHeapAccessStatistics()
|
||||
{
|
||||
HeapAccessStatistics stats;
|
||||
|
||||
/*
|
||||
* do nothing if stats aren't initialized
|
||||
*/
|
||||
if (heap_access_stats == NULL)
|
||||
return;
|
||||
|
||||
stats = heap_access_stats;
|
||||
|
||||
/*
|
||||
* reset local counts
|
||||
*/
|
||||
stats->local_open = 0;
|
||||
stats->local_openr = 0;
|
||||
stats->local_close = 0;
|
||||
stats->local_beginscan = 0;
|
||||
stats->local_rescan = 0;
|
||||
stats->local_endscan = 0;
|
||||
stats->local_getnext = 0;
|
||||
stats->local_fetch = 0;
|
||||
stats->local_insert = 0;
|
||||
stats->local_delete = 0;
|
||||
stats->local_replace = 0;
|
||||
stats->local_mark4update = 0;
|
||||
stats->local_markpos = 0;
|
||||
stats->local_restrpos = 0;
|
||||
stats->local_BufferGetRelation = 0;
|
||||
stats->local_RelationIdGetRelation = 0;
|
||||
stats->local_RelationIdGetRelation_Buf = 0;
|
||||
stats->local_getreldesc = 0;
|
||||
stats->local_heapgettup = 0;
|
||||
stats->local_RelationPutHeapTuple = 0;
|
||||
stats->local_RelationPutLongHeapTuple = 0;
|
||||
|
||||
/*
|
||||
* reset local timestamps
|
||||
*/
|
||||
time(&stats->local_reset_timestamp);
|
||||
time(&stats->last_request_timestamp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NOT_USED
|
||||
/* ----------------
|
||||
* GetHeapAccessStatistics
|
||||
* ----------------
|
||||
*/
|
||||
HeapAccessStatistics
|
||||
GetHeapAccessStatistics()
|
||||
{
|
||||
HeapAccessStatistics stats;
|
||||
|
||||
/*
|
||||
* return nothing if stats aren't initialized
|
||||
*/
|
||||
if (heap_access_stats == NULL)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* record the current request time
|
||||
*/
|
||||
time(&heap_access_stats->last_request_timestamp);
|
||||
|
||||
/*
|
||||
* allocate a copy of the stats and return it to the caller.
|
||||
*/
|
||||
stats = (HeapAccessStatistics)
|
||||
palloc(sizeof(HeapAccessStatisticsData));
|
||||
|
||||
memmove(stats,
|
||||
heap_access_stats,
|
||||
sizeof(HeapAccessStatisticsData));
|
||||
|
||||
return stats;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NOT_USED
|
||||
/* ----------------
|
||||
* PrintHeapAccessStatistics
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
PrintHeapAccessStatistics(HeapAccessStatistics stats)
|
||||
{
|
||||
/*
|
||||
* return nothing if stats aren't valid
|
||||
*/
|
||||
if (stats == NULL)
|
||||
return;
|
||||
|
||||
printf("======== heap am statistics ========\n");
|
||||
printf("init_global_timestamp: %s",
|
||||
ctime(&(stats->init_global_timestamp)));
|
||||
|
||||
printf("local_reset_timestamp: %s",
|
||||
ctime(&(stats->local_reset_timestamp)));
|
||||
|
||||
printf("last_request_timestamp: %s",
|
||||
ctime(&(stats->last_request_timestamp)));
|
||||
|
||||
printf("local/global_open: %6d/%6d\n",
|
||||
stats->local_open, stats->global_open);
|
||||
|
||||
printf("local/global_openr: %6d/%6d\n",
|
||||
stats->local_openr, stats->global_openr);
|
||||
|
||||
printf("local/global_close: %6d/%6d\n",
|
||||
stats->local_close, stats->global_close);
|
||||
|
||||
printf("local/global_beginscan: %6d/%6d\n",
|
||||
stats->local_beginscan, stats->global_beginscan);
|
||||
|
||||
printf("local/global_rescan: %6d/%6d\n",
|
||||
stats->local_rescan, stats->global_rescan);
|
||||
|
||||
printf("local/global_endscan: %6d/%6d\n",
|
||||
stats->local_endscan, stats->global_endscan);
|
||||
|
||||
printf("local/global_getnext: %6d/%6d\n",
|
||||
stats->local_getnext, stats->global_getnext);
|
||||
|
||||
printf("local/global_fetch: %6d/%6d\n",
|
||||
stats->local_fetch, stats->global_fetch);
|
||||
|
||||
printf("local/global_insert: %6d/%6d\n",
|
||||
stats->local_insert, stats->global_insert);
|
||||
|
||||
printf("local/global_delete: %6d/%6d\n",
|
||||
stats->local_delete, stats->global_delete);
|
||||
|
||||
printf("local/global_replace: %6d/%6d\n",
|
||||
stats->local_replace, stats->global_replace);
|
||||
|
||||
printf("local/global_mark4update: %6d/%6d\n",
|
||||
stats->local_mark4update, stats->global_mark4update);
|
||||
|
||||
printf("local/global_markpos: %6d/%6d\n",
|
||||
stats->local_markpos, stats->global_markpos);
|
||||
|
||||
printf("local/global_restrpos: %6d/%6d\n",
|
||||
stats->local_restrpos, stats->global_restrpos);
|
||||
|
||||
printf("================\n");
|
||||
|
||||
printf("local/global_BufferGetRelation: %6d/%6d\n",
|
||||
stats->local_BufferGetRelation,
|
||||
stats->global_BufferGetRelation);
|
||||
|
||||
printf("local/global_RelationIdGetRelation: %6d/%6d\n",
|
||||
stats->local_RelationIdGetRelation,
|
||||
stats->global_RelationIdGetRelation);
|
||||
|
||||
printf("local/global_RelationIdGetRelation_Buf: %6d/%6d\n",
|
||||
stats->local_RelationIdGetRelation_Buf,
|
||||
stats->global_RelationIdGetRelation_Buf);
|
||||
|
||||
printf("local/global_getreldesc: %6d/%6d\n",
|
||||
stats->local_getreldesc, stats->global_getreldesc);
|
||||
|
||||
printf("local/global_heapgettup: %6d/%6d\n",
|
||||
stats->local_heapgettup, stats->global_heapgettup);
|
||||
|
||||
printf("local/global_RelationPutHeapTuple: %6d/%6d\n",
|
||||
stats->local_RelationPutHeapTuple,
|
||||
stats->global_RelationPutHeapTuple);
|
||||
|
||||
printf("local/global_RelationPutLongHeapTuple: %6d/%6d\n",
|
||||
stats->local_RelationPutLongHeapTuple,
|
||||
stats->global_RelationPutLongHeapTuple);
|
||||
|
||||
printf("===================================\n");
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NOT_USED
|
||||
/* ----------------
|
||||
* PrintAndFreeHeapAccessStatistics
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
PrintAndFreeHeapAccessStatistics(HeapAccessStatistics stats)
|
||||
{
|
||||
PrintHeapAccessStatistics(stats);
|
||||
if (stats != NULL)
|
||||
pfree(stats);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* access method initialization
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
/* ----------------
|
||||
* initam should someday be moved someplace else.
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
initam(void)
|
||||
{
|
||||
/*
|
||||
* initialize heap statistics.
|
||||
*/
|
||||
InitHeapAccessStatistics();
|
||||
}
|
Reference in New Issue
Block a user