diff options
Diffstat (limited to 'src/backend/access')
| -rw-r--r-- | src/backend/access/heap/Makefile | 4 | ||||
| -rw-r--r-- | src/backend/access/heap/heapam.c | 160 | ||||
| -rw-r--r-- | src/backend/access/heap/stats.c | 333 | ||||
| -rw-r--r-- | src/backend/access/index/indexam.c | 40 |
4 files changed, 99 insertions, 438 deletions
diff --git a/src/backend/access/heap/Makefile b/src/backend/access/heap/Makefile index 95575f8e32..352ced3392 100644 --- a/src/backend/access/heap/Makefile +++ b/src/backend/access/heap/Makefile @@ -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 diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index f73ca50285..bf7798a07d 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -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,116 +499,111 @@ 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 + * relation_close - close any relation + * + * If lockmode is not "NoLock", we first release the specified lock. * - * The caller must check for a NULL return value indicating - * that no such relation exists. - * No lock is obtained on the relation, either. + * Note that it is often sensible to hold a lock beyond relation_close; + * in that case, the lock is released automatically at xact end. * ---------------- */ -Relation -heap_open_nofail(Oid relationId) +void +relation_close(Relation relation, LOCKMODE lockmode) { - Relation r; + Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); /* * increment access statistics */ - IncrHeapAccessStat(local_open); - IncrHeapAccessStat(global_open); - - /* The relcache does all the real work... */ - r = RelationIdGetRelation(relationId); + IncrHeapAccessStat(local_close); + IncrHeapAccessStat(global_close); - /* 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 (lockmode != NoLock) + UnlockRelation(relation, lockmode); - return r; + /* The relcache does the real work... */ + RelationClose(relation); } + /* ---------------- - * heap_openr_nofail - open a heap relation by name, - * do not raise error on failure + * heap_open - open a heap relation by relation OID * - * The caller must check for a NULL return value indicating - * that no such relation exists. - * No lock is obtained on the relation, either. + * 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_openr_nofail(const char *relationName) +heap_open(Oid relationId, LOCKMODE lockmode) { Relation r; - /* - * increment access statistics - */ - IncrHeapAccessStat(local_openr); - IncrHeapAccessStat(global_openr); + r = relation_open(relationId, lockmode); - /* 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 (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)); - if (RelationIsValid(r)) - pgstat_initstats(&r->pgstat_info, r); + pgstat_initstats(&r->pgstat_info, r); return r; } /* ---------------- - * heap_close - close a heap relation + * heap_openr - open a heap relation by name * - * If lockmode is not "NoLock", we first release the specified lock. - * Note that it is often sensible to hold a lock beyond heap_close; - * in that case, the lock is released automatically at xact end. + * As above, but lookup by name instead of OID. * ---------------- */ -void -heap_close(Relation relation, LOCKMODE lockmode) +Relation +heap_openr(const char *relationName, LOCKMODE lockmode) { - Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); + Relation r; - /* - * increment access statistics - */ - IncrHeapAccessStat(local_close); - IncrHeapAccessStat(global_close); + r = relation_openr(relationName, lockmode); - if (lockmode != NoLock) - UnlockRelation(relation, 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)); - /* The relcache does the real work... */ - RelationClose(relation); + pgstat_initstats(&r->pgstat_info, r); + + return r; } @@ -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"); diff --git a/src/backend/access/heap/stats.c b/src/backend/access/heap/stats.c deleted file mode 100644 index 6f5dfbea14..0000000000 --- a/src/backend/access/heap/stats.c +++ /dev/null @@ -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(); -} diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index 8e1d5b8733..523349ebdb 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -8,12 +8,12 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.54 2001/10/25 05:49:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.55 2001/11/02 16:30:29 tgl Exp $ * * INTERFACE ROUTINES - * index_open - open an index relation by relationId - * index_openr - open a index relation by name - * index_close - close a index relation + * index_open - open an index relation by relation OID + * index_openr - open an index relation by name + * index_close - close an index relation * index_beginscan - start a scan of an index * index_rescan - restart a scan of an index * index_endscan - end a scan @@ -106,15 +106,17 @@ * index_ interface functions * ---------------------------------------------------------------- */ + /* ---------------- - * index_open - open an index relation by relationId - * - * presently the relcache routines do all the work we need - * to open/close index relations. However, callers of index_open - * expect it to succeed, so we need to check for a failure return. + * index_open - open an index relation by relation OID * * Note: we acquire no lock on the index. An AccessShareLock is * acquired by index_beginscan (and released by index_endscan). + * Generally, the caller should already hold some type of lock on + * the parent relation to ensure that the index doesn't disappear. + * + * This is a convenience routine adapted for indexscan use. + * Some callers may prefer to use relation_open directly. * ---------------- */ Relation @@ -122,13 +124,11 @@ index_open(Oid relationId) { Relation r; - r = RelationIdGetRelation(relationId); - - if (!RelationIsValid(r)) - elog(ERROR, "Index %u does not exist", relationId); + r = relation_open(relationId, NoLock); if (r->rd_rel->relkind != RELKIND_INDEX) - elog(ERROR, "%s is not an index relation", RelationGetRelationName(r)); + elog(ERROR, "%s is not an index relation", + RelationGetRelationName(r)); pgstat_initstats(&r->pgstat_info, r); @@ -136,23 +136,21 @@ index_open(Oid relationId) } /* ---------------- - * index_openr - open a index relation by name + * index_openr - open an index relation by name * * As above, but lookup by name instead of OID. * ---------------- */ Relation -index_openr(char *relationName) +index_openr(const char *relationName) { Relation r; - r = RelationNameGetRelation(relationName); - - if (!RelationIsValid(r)) - elog(ERROR, "Index '%s' does not exist", relationName); + r = relation_openr(relationName, NoLock); if (r->rd_rel->relkind != RELKIND_INDEX) - elog(ERROR, "%s is not an index relation", RelationGetRelationName(r)); + elog(ERROR, "%s is not an index relation", + RelationGetRelationName(r)); pgstat_initstats(&r->pgstat_info, r); |
