mirror of
https://github.com/postgres/postgres.git
synced 2025-07-11 10:01:57 +03:00
Postgres95 1.01 Distribution - Virgin Sources
This commit is contained in:
14
src/backend/access/heap/Makefile.inc
Normal file
14
src/backend/access/heap/Makefile.inc
Normal file
@ -0,0 +1,14 @@
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile.inc--
|
||||
# Makefile for access/heap
|
||||
#
|
||||
# Copyright (c) 1994, Regents of the University of California
|
||||
#
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/backend/access/heap/Attic/Makefile.inc,v 1.1.1.1 1996/07/09 06:21:11 scrappy Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
SUBSRCS+= heapam.c hio.c stats.c
|
1507
src/backend/access/heap/heapam.c
Normal file
1507
src/backend/access/heap/heapam.c
Normal file
File diff suppressed because it is too large
Load Diff
195
src/backend/access/heap/hio.c
Normal file
195
src/backend/access/heap/hio.c
Normal file
@ -0,0 +1,195 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* hio.c--
|
||||
* POSTGRES heap access method input/output code.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Id: hio.c,v 1.1.1.1 1996/07/09 06:21:11 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "c.h"
|
||||
|
||||
#include "access/heapam.h"
|
||||
#include "access/hio.h"
|
||||
#include "access/htup.h"
|
||||
|
||||
#include "storage/block.h"
|
||||
#include "storage/buf.h"
|
||||
#include "storage/bufmgr.h"
|
||||
#include "storage/bufpage.h"
|
||||
#include "storage/itemid.h"
|
||||
#include "storage/itemptr.h"
|
||||
#include "storage/off.h"
|
||||
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/elog.h"
|
||||
#include "utils/rel.h"
|
||||
|
||||
/*
|
||||
* amputunique - place tuple at tid
|
||||
* Currently on errors, calls elog. Perhaps should return -1?
|
||||
* Possible errors include the addition of a tuple to the page
|
||||
* between the time the linep is chosen and the page is L_UP'd.
|
||||
*
|
||||
* This should be coordinated with the B-tree code.
|
||||
* Probably needs to have an amdelunique to allow for
|
||||
* internal index records to be deleted and reordered as needed.
|
||||
* For the heap AM, this should never be needed.
|
||||
*/
|
||||
void
|
||||
RelationPutHeapTuple(Relation relation,
|
||||
BlockNumber blockIndex,
|
||||
HeapTuple tuple)
|
||||
{
|
||||
Buffer buffer;
|
||||
Page pageHeader;
|
||||
BlockNumber numberOfBlocks;
|
||||
OffsetNumber offnum;
|
||||
unsigned int len;
|
||||
ItemId itemId;
|
||||
Item item;
|
||||
|
||||
/* ----------------
|
||||
* increment access statistics
|
||||
* ----------------
|
||||
*/
|
||||
IncrHeapAccessStat(local_RelationPutHeapTuple);
|
||||
IncrHeapAccessStat(global_RelationPutHeapTuple);
|
||||
|
||||
Assert(RelationIsValid(relation));
|
||||
Assert(HeapTupleIsValid(tuple));
|
||||
|
||||
numberOfBlocks = RelationGetNumberOfBlocks(relation);
|
||||
Assert(blockIndex < numberOfBlocks);
|
||||
|
||||
buffer = ReadBuffer(relation, blockIndex);
|
||||
#ifndef NO_BUFFERISVALID
|
||||
if (!BufferIsValid(buffer)) {
|
||||
elog(WARN, "RelationPutHeapTuple: no buffer for %ld in %s",
|
||||
blockIndex, &relation->rd_rel->relname);
|
||||
}
|
||||
#endif
|
||||
|
||||
pageHeader = (Page)BufferGetPage(buffer);
|
||||
len = (unsigned)DOUBLEALIGN(tuple->t_len); /* be conservative */
|
||||
Assert((int)len <= PageGetFreeSpace(pageHeader));
|
||||
|
||||
offnum = PageAddItem((Page)pageHeader, (Item)tuple,
|
||||
tuple->t_len, InvalidOffsetNumber, LP_USED);
|
||||
|
||||
itemId = PageGetItemId((Page)pageHeader, offnum);
|
||||
item = PageGetItem((Page)pageHeader, itemId);
|
||||
|
||||
ItemPointerSet(&((HeapTuple)item)->t_ctid, blockIndex, offnum);
|
||||
|
||||
WriteBuffer(buffer);
|
||||
/* return an accurate tuple */
|
||||
ItemPointerSet(&tuple->t_ctid, blockIndex, offnum);
|
||||
}
|
||||
|
||||
/*
|
||||
* The heap_insert routines "know" that a buffer page is initialized to
|
||||
* zero when a BlockExtend operation is performed.
|
||||
*/
|
||||
|
||||
#define PageIsNew(page) ((page)->pd_upper == 0)
|
||||
|
||||
/*
|
||||
* This routine is another in the series of attempts to reduce the number
|
||||
* of I/O's and system calls executed in the various benchmarks. In
|
||||
* particular, this routine is used to append data to the end of a relation
|
||||
* file without excessive lseeks. This code should do no more than 2 semops
|
||||
* in the ideal case.
|
||||
*
|
||||
* Eventually, we should cache the number of blocks in a relation somewhere.
|
||||
* Until that time, this code will have to do an lseek to determine the number
|
||||
* of blocks in a relation.
|
||||
*
|
||||
* This code should ideally do at most 4 semops, 1 lseek, and possibly 1 write
|
||||
* to do an append; it's possible to eliminate 2 of the semops if we do direct
|
||||
* buffer stuff (!); the lseek and the write can go if we get
|
||||
* RelationGetNumberOfBlocks to be useful.
|
||||
*
|
||||
* NOTE: This code presumes that we have a write lock on the relation.
|
||||
*
|
||||
* Also note that this routine probably shouldn't have to exist, and does
|
||||
* screw up the call graph rather badly, but we are wasting so much time and
|
||||
* system resources being massively general that we are losing badly in our
|
||||
* performance benchmarks.
|
||||
*/
|
||||
void
|
||||
RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
|
||||
{
|
||||
Buffer buffer;
|
||||
Page pageHeader;
|
||||
BlockNumber lastblock;
|
||||
OffsetNumber offnum;
|
||||
unsigned int len;
|
||||
ItemId itemId;
|
||||
Item item;
|
||||
|
||||
Assert(RelationIsValid(relation));
|
||||
Assert(HeapTupleIsValid(tuple));
|
||||
|
||||
/*
|
||||
* XXX This does an lseek - VERY expensive - but at the moment it
|
||||
* is the only way to accurately determine how many blocks are in
|
||||
* a relation. A good optimization would be to get this to actually
|
||||
* work properly.
|
||||
*/
|
||||
|
||||
lastblock = RelationGetNumberOfBlocks(relation);
|
||||
|
||||
if (lastblock == 0)
|
||||
{
|
||||
buffer = ReadBuffer(relation, lastblock);
|
||||
pageHeader = (Page)BufferGetPage(buffer);
|
||||
if (PageIsNew((PageHeader) pageHeader))
|
||||
{
|
||||
buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
|
||||
pageHeader = (Page)BufferGetPage(buffer);
|
||||
PageInit(pageHeader, BufferGetPageSize(buffer), 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
buffer = ReadBuffer(relation, lastblock - 1);
|
||||
|
||||
pageHeader = (Page)BufferGetPage(buffer);
|
||||
len = (unsigned)DOUBLEALIGN(tuple->t_len); /* be conservative */
|
||||
|
||||
/*
|
||||
* Note that this is true if the above returned a bogus page, which
|
||||
* it will do for a completely empty relation.
|
||||
*/
|
||||
|
||||
if (len > PageGetFreeSpace(pageHeader))
|
||||
{
|
||||
buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
|
||||
pageHeader = (Page)BufferGetPage(buffer);
|
||||
PageInit(pageHeader, BufferGetPageSize(buffer), 0);
|
||||
|
||||
if (len > PageGetFreeSpace(pageHeader))
|
||||
elog(WARN, "Tuple is too big: size %d", len);
|
||||
}
|
||||
|
||||
offnum = PageAddItem((Page)pageHeader, (Item)tuple,
|
||||
tuple->t_len, InvalidOffsetNumber, LP_USED);
|
||||
|
||||
itemId = PageGetItemId((Page)pageHeader, offnum);
|
||||
item = PageGetItem((Page)pageHeader, itemId);
|
||||
|
||||
lastblock = BufferGetBlockNumber(buffer);
|
||||
|
||||
ItemPointerSet(&((HeapTuple)item)->t_ctid, lastblock, offnum);
|
||||
|
||||
/* return an accurate tuple */
|
||||
ItemPointerSet(&tuple->t_ctid, lastblock, offnum);
|
||||
|
||||
WriteBuffer(buffer);
|
||||
}
|
329
src/backend/access/heap/stats.c
Normal file
329
src/backend/access/heap/stats.c
Normal file
@ -0,0 +1,329 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* stats.c--
|
||||
* heap access method debugging statistic collection routines
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/heap/Attic/stats.c,v 1.1.1.1 1996/07/09 06:21:11 scrappy Exp $
|
||||
*
|
||||
* NOTES
|
||||
* initam should be moved someplace else.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/heapam.h"
|
||||
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/palloc.h"
|
||||
#include "utils/elog.h"
|
||||
#include "utils/mcxt.h"
|
||||
|
||||
/* ----------------
|
||||
* InitHeapAccessStatistics
|
||||
* ----------------
|
||||
*/
|
||||
HeapAccessStatistics heap_access_stats = (HeapAccessStatistics) NULL;
|
||||
|
||||
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_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_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
|
||||
* ----------------
|
||||
*/
|
||||
(void) MemoryContextSwitchTo(oldContext);
|
||||
|
||||
heap_access_stats = stats;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* 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_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);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* 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;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* 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_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");
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* PrintAndFreeHeapAccessStatistics
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
PrintAndFreeHeapAccessStatistics(HeapAccessStatistics stats)
|
||||
{
|
||||
PrintHeapAccessStatistics(stats);
|
||||
if (stats != NULL)
|
||||
pfree(stats);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* access method initialization
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
/* ----------------
|
||||
* initam should someday be moved someplace else.
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
initam()
|
||||
{
|
||||
/* ----------------
|
||||
* initialize heap statistics.
|
||||
* ----------------
|
||||
*/
|
||||
InitHeapAccessStatistics();
|
||||
}
|
Reference in New Issue
Block a user