Install infrastructure for shared-memory free space map. Doesn't actually

do anything yet, but it has the necessary connections to initialization
and so forth.  Make some gestures towards allowing number of blocks in
a relation to be BlockNumber, ie, unsigned int, rather than signed int.
(I doubt I got all the places that are sloppy about it, yet.)  On the
way, replace the hardwired NLOCKS_PER_XACT fudge factor with a GUC
variable.
This commit is contained in:
Tom Lane 2001-06-27 23:31:40 +00:00
parent b559382134
commit e0c9301c87
26 changed files with 572 additions and 316 deletions

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.69 2001/06/23 00:03:10 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.70 2001/06/27 23:31:37 tgl Exp $
--> -->
<Chapter Id="runtime"> <Chapter Id="runtime">
@ -1131,6 +1131,42 @@ dynamic_library_path = '/usr/local/lib:/home/my_project/lib:$libdir:$libdir/cont
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>MAX_FSM_RELATIONS (<type>integer</type>)</term>
<listitem>
<para>
Sets the maximum number of relations (tables) for which free space
will be tracked in the shared free-space map.
The default is 100. This option can only be set at server start.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>MAX_FSM_PAGES (<type>integer</type>)</term>
<listitem>
<para>
Sets the maximum number of disk pages for which free space
will be tracked in the shared free-space map.
The default is 10000. This option can only be set at server start.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>MAX_LOCKS_PER_XACT (<type>integer</type>)</term>
<listitem>
<para>
The shared lock table is sized on the assumption that at most
max_locks_per_xact * max_connections distinct objects will need
to be locked at any one time. The default, 64, has historically
proven sufficient, but you might need to raise this value if you
have clients that touch many different tables in a single transaction.
This option can only be set at server start.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term>PORT (<type>integer</type>)</term> <term>PORT (<type>integer</type>)</term>
<listitem> <listitem>

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.30 2001/03/07 21:20:26 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.31 2001/06/27 23:31:37 tgl Exp $
* *
* NOTES * NOTES
* Postgres hash pages look like ordinary relation pages. The opaque * Postgres hash pages look like ordinary relation pages. The opaque
@ -70,18 +70,15 @@ _hash_metapinit(Relation rel)
int nbuckets; int nbuckets;
uint32 nelem; /* number elements */ uint32 nelem; /* number elements */
uint32 lg2nelem; /* _hash_log2(nelem) */ uint32 lg2nelem; /* _hash_log2(nelem) */
uint32 nblocks;
uint16 i; uint16 i;
/* can't be sharing this with anyone, now... */ /* can't be sharing this with anyone, now... */
if (USELOCKING) if (USELOCKING)
LockRelation(rel, AccessExclusiveLock); LockRelation(rel, AccessExclusiveLock);
if ((nblocks = RelationGetNumberOfBlocks(rel)) != 0) if (RelationGetNumberOfBlocks(rel) != 0)
{
elog(ERROR, "Cannot initialize non-empty hash table %s", elog(ERROR, "Cannot initialize non-empty hash table %s",
RelationGetRelationName(rel)); RelationGetRelationName(rel));
}
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE); metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE);
pg = BufferGetPage(metabuf); pg = BufferGetPage(metabuf);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.119 2001/06/22 19:16:20 wieck Exp $ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.120 2001/06/27 23:31:38 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -121,8 +121,8 @@ heapgettup(Relation relation,
{ {
ItemId lpp; ItemId lpp;
Page dp; Page dp;
int page; BlockNumber page;
int pages; BlockNumber pages;
int lines; int lines;
OffsetNumber lineoff; OffsetNumber lineoff;
int linesleft; int linesleft;
@ -172,7 +172,7 @@ heapgettup(Relation relation,
/* /*
* return null immediately if relation is empty * return null immediately if relation is empty
*/ */
if (!(pages = relation->rd_nblocks)) if ((pages = relation->rd_nblocks) == 0)
{ {
if (BufferIsValid(*buffer)) if (BufferIsValid(*buffer))
ReleaseBuffer(*buffer); ReleaseBuffer(*buffer);
@ -233,15 +233,8 @@ heapgettup(Relation relation,
{ {
page = ItemPointerGetBlockNumber(tid); /* current page */ page = ItemPointerGetBlockNumber(tid); /* current page */
} }
if (page < 0)
{ Assert(page < pages);
if (BufferIsValid(*buffer))
ReleaseBuffer(*buffer);
*buffer = InvalidBuffer;
tuple->t_datamcxt = NULL;
tuple->t_data = NULL;
return;
}
*buffer = ReleaseAndReadBuffer(*buffer, *buffer = ReleaseAndReadBuffer(*buffer,
relation, relation,
@ -283,15 +276,7 @@ heapgettup(Relation relation,
OffsetNumberNext(ItemPointerGetOffsetNumber(tid)); OffsetNumberNext(ItemPointerGetOffsetNumber(tid));
} }
if (page >= pages) Assert(page < pages);
{
if (BufferIsValid(*buffer))
ReleaseBuffer(*buffer);
*buffer = InvalidBuffer;
tuple->t_datamcxt = NULL;
tuple->t_data = NULL;
return;
}
*buffer = ReleaseAndReadBuffer(*buffer, *buffer = ReleaseAndReadBuffer(*buffer,
relation, relation,
@ -369,12 +354,11 @@ heapgettup(Relation relation,
* and it's time to move to the next. * and it's time to move to the next.
*/ */
LockBuffer(*buffer, BUFFER_LOCK_UNLOCK); LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
page = (dir < 0) ? (page - 1) : (page + 1);
/* /*
* return NULL if we've exhausted all the pages * return NULL if we've exhausted all the pages
*/ */
if (page < 0 || page >= pages) if ((dir < 0) ? (page == 0) : (page+1 >= pages))
{ {
if (BufferIsValid(*buffer)) if (BufferIsValid(*buffer))
ReleaseBuffer(*buffer); ReleaseBuffer(*buffer);
@ -384,6 +368,10 @@ heapgettup(Relation relation,
return; return;
} }
page = (dir < 0) ? (page - 1) : (page + 1);
Assert(page < pages);
*buffer = ReleaseAndReadBuffer(*buffer, *buffer = ReleaseAndReadBuffer(*buffer,
relation, relation,
page, page,

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Id: hio.c,v 1.39 2001/05/16 22:35:12 tgl Exp $ * $Id: hio.c,v 1.40 2001/06/27 23:31:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -147,7 +147,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
*/ */
relation->rd_nblocks = RelationGetNumberOfBlocks(relation); relation->rd_nblocks = RelationGetNumberOfBlocks(relation);
if ((BlockNumber) relation->rd_nblocks > oldnblocks) if (relation->rd_nblocks > oldnblocks)
{ {
/* /*
* Someone else has indeed extended the relation recently. * Someone else has indeed extended the relation recently.

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.51 2001/03/22 03:59:14 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.52 2001/06/27 23:31:38 tgl Exp $
* *
* NOTES * NOTES
* Postgres btree pages look like ordinary relation pages. The opaque * Postgres btree pages look like ordinary relation pages. The opaque
@ -55,7 +55,6 @@ _bt_metapinit(Relation rel)
{ {
Buffer buf; Buffer buf;
Page pg; Page pg;
int nblocks;
BTMetaPageData metad; BTMetaPageData metad;
BTPageOpaque op; BTPageOpaque op;
@ -63,11 +62,9 @@ _bt_metapinit(Relation rel)
if (USELOCKING) if (USELOCKING)
LockRelation(rel, AccessExclusiveLock); LockRelation(rel, AccessExclusiveLock);
if ((nblocks = RelationGetNumberOfBlocks(rel)) != 0) if (RelationGetNumberOfBlocks(rel) != 0)
{
elog(ERROR, "Cannot initialize non-empty btree %s", elog(ERROR, "Cannot initialize non-empty btree %s",
RelationGetRelationName(rel)); RelationGetRelationName(rel));
}
buf = ReadBuffer(rel, P_NEW); buf = ReadBuffer(rel, P_NEW);
pg = BufferGetPage(buf); pg = BufferGetPage(buf);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.168 2001/06/18 16:13:21 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.169 2001/06/27 23:31:38 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -1089,6 +1089,7 @@ RelationTruncateIndexes(Oid heapId)
/* Now truncate the actual data and set blocks to zero */ /* Now truncate the actual data and set blocks to zero */
smgrtruncate(DEFAULT_SMGR, currentIndex, 0); smgrtruncate(DEFAULT_SMGR, currentIndex, 0);
currentIndex->rd_nblocks = 0; currentIndex->rd_nblocks = 0;
currentIndex->rd_targblock = InvalidBlockNumber;
/* Initialize the index and rebuild */ /* Initialize the index and rebuild */
InitIndexStrategy(indexInfo->ii_NumIndexAttrs, InitIndexStrategy(indexInfo->ii_NumIndexAttrs,
@ -1143,9 +1144,9 @@ heap_truncate(char *relname)
DropRelationBuffers(rel); DropRelationBuffers(rel);
/* Now truncate the actual data and set blocks to zero */ /* Now truncate the actual data and set blocks to zero */
smgrtruncate(DEFAULT_SMGR, rel, 0); smgrtruncate(DEFAULT_SMGR, rel, 0);
rel->rd_nblocks = 0; rel->rd_nblocks = 0;
rel->rd_targblock = InvalidBlockNumber;
/* If this relation has indexes, truncate the indexes too */ /* If this relation has indexes, truncate the indexes too */
RelationTruncateIndexes(rid); RelationTruncateIndexes(rid);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.154 2001/06/12 05:55:49 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.155 2001/06/27 23:31:38 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -1456,7 +1456,7 @@ UpdateStats(Oid relid, double reltuples)
Relation pg_class; Relation pg_class;
HeapTuple tuple; HeapTuple tuple;
HeapTuple newtup; HeapTuple newtup;
long relpages; BlockNumber relpages;
int i; int i;
Form_pg_class rd_rel; Form_pg_class rd_rel;
Relation idescs[Num_pg_class_indices]; Relation idescs[Num_pg_class_indices];
@ -1558,7 +1558,7 @@ UpdateStats(Oid relid, double reltuples)
reltuples = 1000; reltuples = 1000;
} }
else else
reltuples = relpages * NTUPLES_PER_PAGE(whichRel->rd_rel->relnatts); reltuples = (double) relpages * NTUPLES_PER_PAGE(whichRel->rd_rel->relnatts);
} }
/* /*
@ -1566,7 +1566,7 @@ UpdateStats(Oid relid, double reltuples)
* place with the new values so that the cache contains the latest * place with the new values so that the cache contains the latest
* copy. * copy.
*/ */
whichRel->rd_rel->relpages = relpages; whichRel->rd_rel->relpages = (int32) relpages;
whichRel->rd_rel->reltuples = reltuples; whichRel->rd_rel->reltuples = reltuples;
/* /*
@ -1581,7 +1581,7 @@ UpdateStats(Oid relid, double reltuples)
*/ */
rd_rel = (Form_pg_class) GETSTRUCT(tuple); rd_rel = (Form_pg_class) GETSTRUCT(tuple);
LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_EXCLUSIVE); LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_EXCLUSIVE);
rd_rel->relpages = relpages; rd_rel->relpages = (int32) relpages;
rd_rel->reltuples = reltuples; rd_rel->reltuples = reltuples;
LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_UNLOCK); LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
WriteNoReleaseBuffer(pg_class_scan->rs_cbuf); WriteNoReleaseBuffer(pg_class_scan->rs_cbuf);
@ -1600,7 +1600,7 @@ UpdateStats(Oid relid, double reltuples)
} }
replace[Anum_pg_class_relpages - 1] = 'r'; replace[Anum_pg_class_relpages - 1] = 'r';
values[Anum_pg_class_relpages - 1] = Int32GetDatum(relpages); values[Anum_pg_class_relpages - 1] = Int32GetDatum((int32) relpages);
replace[Anum_pg_class_reltuples - 1] = 'r'; replace[Anum_pg_class_reltuples - 1] = 'r';
values[Anum_pg_class_reltuples - 1] = Float4GetDatum((float4) reltuples); values[Anum_pg_class_reltuples - 1] = Float4GetDatum((float4) reltuples);
newtup = heap_modifytuple(tuple, pg_class, values, nulls, replace); newtup = heap_modifytuple(tuple, pg_class, values, nulls, replace);
@ -1962,6 +1962,7 @@ reindex_index(Oid indexId, bool force, bool inplace)
/* Now truncate the actual data and set blocks to zero */ /* Now truncate the actual data and set blocks to zero */
smgrtruncate(DEFAULT_SMGR, iRel, 0); smgrtruncate(DEFAULT_SMGR, iRel, 0);
iRel->rd_nblocks = 0; iRel->rd_nblocks = 0;
iRel->rd_targblock = InvalidBlockNumber;
} }
/* Initialize the index and rebuild */ /* Initialize the index and rebuild */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.197 2001/06/22 19:16:21 wieck Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.198 2001/06/27 23:31:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -107,8 +107,8 @@ typedef VTupleMoveData *VTupleMove;
typedef struct VRelStats typedef struct VRelStats
{ {
Oid relid; Oid relid;
long num_pages; BlockNumber rel_pages;
long num_tuples; double rel_tuples;
Size min_tlen; Size min_tlen;
Size max_tlen; Size max_tlen;
bool hasindex; bool hasindex;
@ -143,8 +143,8 @@ static void vacuum_heap(VRelStats *vacrelstats, Relation onerel,
VacPageList vacpagelist); VacPageList vacpagelist);
static void vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage); static void vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage);
static void vacuum_index(VacPageList vacpagelist, Relation indrel, static void vacuum_index(VacPageList vacpagelist, Relation indrel,
long num_tuples, int keep_tuples); double num_tuples, int keep_tuples);
static void scan_index(Relation indrel, long num_tuples); static void scan_index(Relation indrel, double num_tuples);
static VacPage tid_reaped(ItemPointer itemptr, VacPageList vacpagelist); static VacPage tid_reaped(ItemPointer itemptr, VacPageList vacpagelist);
static void reap_page(VacPageList vacpagelist, VacPage vacpage); static void reap_page(VacPageList vacpagelist, VacPage vacpage);
static void vpage_insert(VacPageList vacpagelist, VacPage vpnew); static void vpage_insert(VacPageList vacpagelist, VacPage vpnew);
@ -487,8 +487,8 @@ vacuum_rel(Oid relid)
*/ */
vacrelstats = (VRelStats *) palloc(sizeof(VRelStats)); vacrelstats = (VRelStats *) palloc(sizeof(VRelStats));
vacrelstats->relid = relid; vacrelstats->relid = relid;
vacrelstats->num_pages = 0; vacrelstats->rel_pages = 0;
vacrelstats->num_tuples = 0; vacrelstats->rel_tuples = 0;
vacrelstats->hasindex = false; vacrelstats->hasindex = false;
GetXmaxRecent(&XmaxRecent); GetXmaxRecent(&XmaxRecent);
@ -535,13 +535,13 @@ vacuum_rel(Oid relid)
{ {
for (i = 0; i < nindices; i++) for (i = 0; i < nindices; i++)
vacuum_index(&vacuum_pages, Irel[i], vacuum_index(&vacuum_pages, Irel[i],
vacrelstats->num_tuples, 0); vacrelstats->rel_tuples, 0);
} }
else else
{ {
/* just scan indices to update statistic */ /* just scan indices to update statistic */
for (i = 0; i < nindices; i++) for (i = 0; i < nindices; i++)
scan_index(Irel[i], vacrelstats->num_tuples); scan_index(Irel[i], vacrelstats->rel_tuples);
} }
} }
@ -562,14 +562,13 @@ vacuum_rel(Oid relid)
} }
else else
{ {
/* /*
* Flush dirty pages out to disk. We must do this even if we * Flush dirty pages out to disk. We must do this even if we
* didn't do anything else, because we want to ensure that all * didn't do anything else, because we want to ensure that all
* tuples have correct on-row commit status on disk (see * tuples have correct on-row commit status on disk (see
* bufmgr.c's comments for FlushRelationBuffers()). * bufmgr.c's comments for FlushRelationBuffers()).
*/ */
i = FlushRelationBuffers(onerel, vacrelstats->num_pages); i = FlushRelationBuffers(onerel, vacrelstats->rel_pages);
if (i < 0) if (i < 0)
elog(ERROR, "VACUUM (vacuum_rel): FlushRelationBuffers returned %d", elog(ERROR, "VACUUM (vacuum_rel): FlushRelationBuffers returned %d",
i); i);
@ -584,8 +583,8 @@ vacuum_rel(Oid relid)
heap_close(onerel, NoLock); heap_close(onerel, NoLock);
/* update statistics in pg_class */ /* update statistics in pg_class */
vac_update_relstats(vacrelstats->relid, vacrelstats->num_pages, vac_update_relstats(vacrelstats->relid, vacrelstats->rel_pages,
vacrelstats->num_tuples, vacrelstats->hasindex); vacrelstats->rel_tuples, vacrelstats->hasindex);
/* /*
* Complete the transaction and free all temporary memory used. * Complete the transaction and free all temporary memory used.
@ -637,7 +636,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
char *relname; char *relname;
VacPage vacpage, VacPage vacpage,
vp; vp;
long num_tuples; double num_tuples;
uint32 tups_vacuumed, uint32 tups_vacuumed,
nkeep, nkeep,
nunused, nunused,
@ -662,8 +661,9 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
relname = RelationGetRelationName(onerel); relname = RelationGetRelationName(onerel);
elog(MESSAGE_LEVEL, "--Relation %s--", relname); elog(MESSAGE_LEVEL, "--Relation %s--", relname);
tups_vacuumed = num_tuples = nkeep = nunused = ncrash = empty_pages = tups_vacuumed = nkeep = nunused = ncrash = empty_pages =
new_pages = changed_pages = empty_end_pages = 0; new_pages = changed_pages = empty_end_pages = 0;
num_tuples = 0;
free_size = usable_free_size = 0; free_size = usable_free_size = 0;
nblocks = RelationGetNumberOfBlocks(onerel); nblocks = RelationGetNumberOfBlocks(onerel);
@ -922,7 +922,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
} }
else else
{ {
num_tuples++; num_tuples += 1;
notup = false; notup = false;
if (tuple.t_len < min_tlen) if (tuple.t_len < min_tlen)
min_tlen = tuple.t_len; min_tlen = tuple.t_len;
@ -966,8 +966,8 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
pfree(vacpage); pfree(vacpage);
/* save stats in the rel list for use later */ /* save stats in the rel list for use later */
vacrelstats->num_tuples = num_tuples; vacrelstats->rel_tuples = num_tuples;
vacrelstats->num_pages = nblocks; vacrelstats->rel_pages = nblocks;
if (num_tuples == 0) if (num_tuples == 0)
min_tlen = max_tlen = 0; min_tlen = max_tlen = 0;
vacrelstats->min_tlen = min_tlen; vacrelstats->min_tlen = min_tlen;
@ -1014,7 +1014,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
} }
elog(MESSAGE_LEVEL, "Pages %u: Changed %u, reaped %u, Empty %u, New %u; \ elog(MESSAGE_LEVEL, "Pages %u: Changed %u, reaped %u, Empty %u, New %u; \
Tup %lu: Vac %u, Keep/VTL %u/%u, Crash %u, UnUsed %u, MinLen %lu, MaxLen %lu; \ Tup %.0f: Vac %u, Keep/VTL %u/%u, Crash %u, UnUsed %u, MinLen %lu, MaxLen %lu; \
Re-using: Free/Avail. Space %lu/%lu; EndEmpty/Avail. Pages %u/%u. %s", Re-using: Free/Avail. Space %lu/%lu; EndEmpty/Avail. Pages %u/%u. %s",
nblocks, changed_pages, vacuum_pages->num_pages, empty_pages, nblocks, changed_pages, vacuum_pages->num_pages, empty_pages,
new_pages, num_tuples, tups_vacuumed, new_pages, num_tuples, tups_vacuumed,
@ -1048,6 +1048,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
cur_buffer; cur_buffer;
int nblocks, int nblocks,
blkno; blkno;
BlockNumber last_move_dest_block = 0,
last_vacuum_block;
Page page, Page page,
ToPage = NULL; ToPage = NULL;
OffsetNumber offnum, OffsetNumber offnum,
@ -1069,9 +1071,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
vacpage, vacpage,
*curpage; *curpage;
int cur_item = 0; int cur_item = 0;
int last_move_dest_block = -1, int i;
last_vacuum_block,
i = 0;
Size tuple_len; Size tuple_len;
int num_moved, int num_moved,
num_fraged_pages, num_fraged_pages,
@ -1117,7 +1117,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
* NB: this code depends on the vacuum_pages and fraged_pages lists being * NB: this code depends on the vacuum_pages and fraged_pages lists being
* in order, and on fraged_pages being a subset of vacuum_pages. * in order, and on fraged_pages being a subset of vacuum_pages.
*/ */
nblocks = vacrelstats->num_pages; nblocks = vacrelstats->rel_pages;
for (blkno = nblocks - vacuum_pages->empty_end_pages - 1; for (blkno = nblocks - vacuum_pages->empty_end_pages - 1;
blkno > last_move_dest_block; blkno > last_move_dest_block;
blkno--) blkno--)
@ -1152,11 +1152,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
else else
{ {
last_vacuum_page = NULL; last_vacuum_page = NULL;
last_vacuum_block = -1; last_vacuum_block = InvalidBlockNumber;
} }
if (num_fraged_pages > 0 && if (num_fraged_pages > 0 &&
fraged_pages->pagedesc[num_fraged_pages - 1]->blkno == fraged_pages->pagedesc[num_fraged_pages - 1]->blkno == blkno)
(BlockNumber) blkno)
{ {
/* page is in fraged_pages too; remove it */ /* page is in fraged_pages too; remove it */
--num_fraged_pages; --num_fraged_pages;
@ -1577,7 +1576,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
} }
END_CRIT_SECTION(); END_CRIT_SECTION();
if (((int) destvacpage->blkno) > last_move_dest_block) if (destvacpage->blkno > last_move_dest_block)
last_move_dest_block = destvacpage->blkno; last_move_dest_block = destvacpage->blkno;
/* /*
@ -1710,9 +1709,9 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
InvalidOffsetNumber, LP_USED); InvalidOffsetNumber, LP_USED);
if (newoff == InvalidOffsetNumber) if (newoff == InvalidOffsetNumber)
{ {
elog(STOP, "\ elog(STOP, "failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)",
failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)", (unsigned long) tuple_len,
(unsigned long) tuple_len, cur_page->blkno, (unsigned long) cur_page->free, cur_page->blkno, (unsigned long) cur_page->free,
cur_page->offsets_used, cur_page->offsets_free); cur_page->offsets_used, cur_page->offsets_free);
} }
newitemid = PageGetItemId(ToPage, newoff); newitemid = PageGetItemId(ToPage, newoff);
@ -1746,7 +1745,7 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
cur_page->offsets_used++; cur_page->offsets_used++;
num_moved++; num_moved++;
cur_page->free = ((PageHeader) ToPage)->pd_upper - ((PageHeader) ToPage)->pd_lower; cur_page->free = ((PageHeader) ToPage)->pd_upper - ((PageHeader) ToPage)->pd_lower;
if (((int) cur_page->blkno) > last_move_dest_block) if (cur_page->blkno > last_move_dest_block)
last_move_dest_block = cur_page->blkno; last_move_dest_block = cur_page->blkno;
vacpage->offsets[vacpage->offsets_free++] = offnum; vacpage->offsets[vacpage->offsets_free++] = offnum;
@ -1882,7 +1881,7 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
checked_moved = 0; checked_moved = 0;
for (i = 0, curpage = vacuum_pages->pagedesc; i < vacuumed_pages; i++, curpage++) for (i = 0, curpage = vacuum_pages->pagedesc; i < vacuumed_pages; i++, curpage++)
{ {
Assert((*curpage)->blkno < (BlockNumber) blkno); Assert((*curpage)->blkno < blkno);
buf = ReadBuffer(onerel, (*curpage)->blkno); buf = ReadBuffer(onerel, (*curpage)->blkno);
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
page = BufferGetPage(buf); page = BufferGetPage(buf);
@ -1959,11 +1958,11 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
Assert(keep_tuples >= 0); Assert(keep_tuples >= 0);
for (i = 0; i < nindices; i++) for (i = 0; i < nindices; i++)
vacuum_index(&Nvacpagelist, Irel[i], vacuum_index(&Nvacpagelist, Irel[i],
vacrelstats->num_tuples, keep_tuples); vacrelstats->rel_tuples, keep_tuples);
} }
/* clean moved tuples from last page in Nvacpagelist list */ /* clean moved tuples from last page in Nvacpagelist list */
if (vacpage->blkno == (BlockNumber) (blkno - 1) && if (vacpage->blkno == (blkno - 1) &&
vacpage->offsets_free > 0) vacpage->offsets_free > 0)
{ {
OffsetNumber unbuf[BLCKSZ/sizeof(OffsetNumber)]; OffsetNumber unbuf[BLCKSZ/sizeof(OffsetNumber)];
@ -2037,8 +2036,7 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
if (blkno < nblocks) if (blkno < nblocks)
{ {
blkno = smgrtruncate(DEFAULT_SMGR, onerel, blkno); blkno = smgrtruncate(DEFAULT_SMGR, onerel, blkno);
Assert(blkno >= 0); vacrelstats->rel_pages = blkno; /* set new number of blocks */
vacrelstats->num_pages = blkno; /* set new number of blocks */
} }
if (Irel != (Relation *) NULL) /* pfree index' allocations */ if (Irel != (Relation *) NULL) /* pfree index' allocations */
@ -2063,7 +2061,8 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
{ {
Buffer buf; Buffer buf;
VacPage *vacpage; VacPage *vacpage;
long nblocks; BlockNumber relblocks;
int nblocks;
int i; int i;
nblocks = vacuum_pages->num_pages; nblocks = vacuum_pages->num_pages;
@ -2087,10 +2086,10 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
* tuples have correct on-row commit status on disk (see bufmgr.c's * tuples have correct on-row commit status on disk (see bufmgr.c's
* comments for FlushRelationBuffers()). * comments for FlushRelationBuffers()).
*/ */
Assert(vacrelstats->num_pages >= vacuum_pages->empty_end_pages); Assert(vacrelstats->rel_pages >= (BlockNumber) vacuum_pages->empty_end_pages);
nblocks = vacrelstats->num_pages - vacuum_pages->empty_end_pages; relblocks = vacrelstats->rel_pages - vacuum_pages->empty_end_pages;
i = FlushRelationBuffers(onerel, nblocks); i = FlushRelationBuffers(onerel, relblocks);
if (i < 0) if (i < 0)
elog(ERROR, "VACUUM (vacuum_heap): FlushRelationBuffers returned %d", elog(ERROR, "VACUUM (vacuum_heap): FlushRelationBuffers returned %d",
i); i);
@ -2098,12 +2097,11 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
/* truncate relation if there are some empty end-pages */ /* truncate relation if there are some empty end-pages */
if (vacuum_pages->empty_end_pages > 0) if (vacuum_pages->empty_end_pages > 0)
{ {
elog(MESSAGE_LEVEL, "Rel %s: Pages: %lu --> %lu.", elog(MESSAGE_LEVEL, "Rel %s: Pages: %u --> %u.",
RelationGetRelationName(onerel), RelationGetRelationName(onerel),
vacrelstats->num_pages, nblocks); vacrelstats->rel_pages, relblocks);
nblocks = smgrtruncate(DEFAULT_SMGR, onerel, nblocks); relblocks = smgrtruncate(DEFAULT_SMGR, onerel, relblocks);
Assert(nblocks >= 0); vacrelstats->rel_pages = relblocks; /* set new number of
vacrelstats->num_pages = nblocks; /* set new number of
* blocks */ * blocks */
} }
} }
@ -2148,12 +2146,12 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
* *
*/ */
static void static void
scan_index(Relation indrel, long num_tuples) scan_index(Relation indrel, double num_tuples)
{ {
RetrieveIndexResult res; RetrieveIndexResult res;
IndexScanDesc iscan; IndexScanDesc iscan;
long nitups; BlockNumber nipages;
int nipages; double nitups;
VacRUsage ru0; VacRUsage ru0;
init_rusage(&ru0); init_rusage(&ru0);
@ -2165,7 +2163,7 @@ scan_index(Relation indrel, long num_tuples)
while ((res = index_getnext(iscan, ForwardScanDirection)) while ((res = index_getnext(iscan, ForwardScanDirection))
!= (RetrieveIndexResult) NULL) != (RetrieveIndexResult) NULL)
{ {
nitups++; nitups += 1;
pfree(res); pfree(res);
} }
@ -2175,12 +2173,12 @@ scan_index(Relation indrel, long num_tuples)
nipages = RelationGetNumberOfBlocks(indrel); nipages = RelationGetNumberOfBlocks(indrel);
vac_update_relstats(RelationGetRelid(indrel), nipages, nitups, false); vac_update_relstats(RelationGetRelid(indrel), nipages, nitups, false);
elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %lu. %s", elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %.0f. %s",
RelationGetRelationName(indrel), nipages, nitups, RelationGetRelationName(indrel), nipages, nitups,
show_rusage(&ru0)); show_rusage(&ru0));
if (nitups != num_tuples) if (nitups != num_tuples)
elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%lu) IS NOT THE SAME AS HEAP' (%lu).\ elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\
\n\tRecreate the index.", \n\tRecreate the index.",
RelationGetRelationName(indrel), nitups, num_tuples); RelationGetRelationName(indrel), nitups, num_tuples);
@ -2200,14 +2198,14 @@ scan_index(Relation indrel, long num_tuples)
*/ */
static void static void
vacuum_index(VacPageList vacpagelist, Relation indrel, vacuum_index(VacPageList vacpagelist, Relation indrel,
long num_tuples, int keep_tuples) double num_tuples, int keep_tuples)
{ {
RetrieveIndexResult res; RetrieveIndexResult res;
IndexScanDesc iscan; IndexScanDesc iscan;
ItemPointer heapptr; ItemPointer heapptr;
int tups_vacuumed; int tups_vacuumed;
long num_index_tuples; BlockNumber num_pages;
int num_pages; double num_index_tuples;
VacPage vp; VacPage vp;
VacRUsage ru0; VacRUsage ru0;
@ -2242,7 +2240,7 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
index_delete(indrel, &res->index_iptr); index_delete(indrel, &res->index_iptr);
} }
else else
num_index_tuples++; num_index_tuples += 1;
pfree(res); pfree(res);
} }
@ -2254,13 +2252,13 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
vac_update_relstats(RelationGetRelid(indrel), vac_update_relstats(RelationGetRelid(indrel),
num_pages, num_index_tuples, false); num_pages, num_index_tuples, false);
elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %lu: Deleted %u. %s", elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %.0f: Deleted %u. %s",
RelationGetRelationName(indrel), num_pages, RelationGetRelationName(indrel), num_pages,
num_index_tuples - keep_tuples, tups_vacuumed, num_index_tuples - keep_tuples, tups_vacuumed,
show_rusage(&ru0)); show_rusage(&ru0));
if (num_index_tuples != num_tuples + keep_tuples) if (num_index_tuples != num_tuples + keep_tuples)
elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%lu) IS NOT THE SAME AS HEAP' (%lu).\ elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\
\n\tRecreate the index.", \n\tRecreate the index.",
RelationGetRelationName(indrel), num_index_tuples, num_tuples); RelationGetRelationName(indrel), num_index_tuples, num_tuples);
@ -2333,7 +2331,7 @@ tid_reaped(ItemPointer itemptr, VacPageList vacpagelist)
* these are. * these are.
*/ */
void void
vac_update_relstats(Oid relid, long num_pages, double num_tuples, vac_update_relstats(Oid relid, BlockNumber num_pages, double num_tuples,
bool hasindex) bool hasindex)
{ {
Relation rd; Relation rd;
@ -2361,8 +2359,8 @@ vac_update_relstats(Oid relid, long num_pages, double num_tuples,
/* overwrite the existing statistics in the tuple */ /* overwrite the existing statistics in the tuple */
pgcform = (Form_pg_class) GETSTRUCT(&rtup); pgcform = (Form_pg_class) GETSTRUCT(&rtup);
pgcform->relpages = (int32) num_pages;
pgcform->reltuples = num_tuples; pgcform->reltuples = num_tuples;
pgcform->relpages = num_pages;
pgcform->relhasindex = hasindex; pgcform->relhasindex = hasindex;
/* invalidate the tuple in the cache and write the buffer */ /* invalidate the tuple in the cache and write the buffer */

View File

@ -1,14 +1,14 @@
# #
# Makefile for the storage manager subsystem # Makefile for the storage manager subsystem
# #
# $Header: /cvsroot/pgsql/src/backend/storage/Makefile,v 1.8 2000/08/31 16:10:30 petere Exp $ # $Header: /cvsroot/pgsql/src/backend/storage/Makefile,v 1.9 2001/06/27 23:31:39 tgl Exp $
# #
subdir = src/backend/storage subdir = src/backend/storage
top_builddir = ../../.. top_builddir = ../../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
SUBDIRS := buffer file ipc large_object lmgr page smgr SUBDIRS := buffer file freespace ipc large_object lmgr page smgr
SUBDIROBJS := $(SUBDIRS:%=%/SUBSYS.o) SUBDIROBJS := $(SUBDIRS:%=%/SUBSYS.o)
all: SUBSYS.o all: SUBSYS.o

View File

@ -0,0 +1,30 @@
#-------------------------------------------------------------------------
#
# Makefile--
# Makefile for storage/freespace
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/storage/freespace/Makefile,v 1.1 2001/06/27 23:31:39 tgl Exp $
#
#-------------------------------------------------------------------------
subdir = src/backend/storage/freespace
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
OBJS = freespace.o
all: SUBSYS.o
SUBSYS.o: $(OBJS)
$(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS)
depend dep:
$(CC) -MM $(CFLAGS) *.c >depend
clean:
rm -f SUBSYS.o $(OBJS)
ifeq (depend,$(wildcard depend))
include depend
endif

View File

@ -0,0 +1,183 @@
/*-------------------------------------------------------------------------
*
* freespace.c
* POSTGRES free space map for quickly finding free space in relations
*
*
* 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/storage/freespace/freespace.c,v 1.1 2001/06/27 23:31:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "storage/freespace.h"
#include "storage/itemid.h"
#include "storage/shmem.h"
/*
* Shared free-space-map objects
*
* Note: we handle pointers to these items as pointers, not as SHMEM_OFFSETs.
* This assumes that all processes accessing the map will have the shared
* memory segment mapped at the same place in their address space.
*/
typedef struct FSMHeader FSMHeader;
typedef struct FSMRelation FSMRelation;
typedef struct FSMChunk FSMChunk;
/* Header for whole map */
struct FSMHeader
{
HTAB *relationHash; /* hashtable of FSMRelation entries */
FSMRelation *relationList; /* FSMRelations in order by recency of use */
int numRelations; /* number of FSMRelations now in use */
FSMChunk *freeChunks; /* linked list of currently-free chunks */
};
/*
* Per-relation struct --- this is an entry in the shared hash table.
* The hash key is the RelFileNode value (hence, we look at the physical
* relation ID, not the logical ID, which is appropriate).
*/
struct FSMRelation
{
RelFileNode key; /* hash key (must be first) */
FSMRelation *nextRel; /* next rel in order by recency of use */
FSMRelation *priorRel; /* prior rel in order by recency of use */
FSMChunk *relChunks; /* linked list of page info chunks */
};
#define SHMEM_FSMHASH_KEYSIZE sizeof(RelFileNode)
#define SHMEM_FSMHASH_DATASIZE (sizeof(FSMRelation) - SHMEM_FSMHASH_KEYSIZE)
#define CHUNKPAGES 32 /* each chunk can store this many pages */
struct FSMChunk
{
FSMChunk *next; /* linked-list link */
int numPages; /* number of pages described here */
BlockNumber pages[CHUNKPAGES]; /* page numbers within relation */
ItemLength bytes[CHUNKPAGES]; /* free space available on each page */
};
SPINLOCK FreeSpaceLock; /* in Shmem or created in
* CreateSpinlocks() */
int MaxFSMRelations; /* these are set by guc.c */
int MaxFSMPages;
static FSMHeader *FreeSpaceMap; /* points to FSMHeader in shared memory */
/*
* InitFreeSpaceMap -- Initialize the freespace module.
*
* This must be called once during shared memory initialization.
* It builds the empty free space map table. FreeSpaceLock must also be
* initialized at some point, but is not touched here --- we assume there is
* no need for locking, since only the calling process can be accessing shared
* memory as yet. FreeSpaceShmemSize() was called previously while computing
* the space needed for shared memory.
*/
void
InitFreeSpaceMap(void)
{
HASHCTL info;
FSMChunk *chunks,
*prevchunk;
int nchunks;
/* Create table header */
FreeSpaceMap = (FSMHeader *) ShmemAlloc(sizeof(FSMHeader));
if (FreeSpaceMap == NULL)
elog(FATAL, "Insufficient shared memory for free space map");
MemSet(FreeSpaceMap, 0, sizeof(FSMHeader));
/* Create hashtable for FSMRelations */
info.keysize = SHMEM_FSMHASH_KEYSIZE;
info.datasize = SHMEM_FSMHASH_DATASIZE;
info.hash = tag_hash;
FreeSpaceMap->relationHash = ShmemInitHash("Free Space Map Hash",
MaxFSMRelations / 10,
MaxFSMRelations,
&info,
(HASH_ELEM | HASH_FUNCTION));
if (!FreeSpaceMap->relationHash)
elog(FATAL, "Insufficient shared memory for free space map");
/* Allocate FSMChunks and fill up the free-chunks list */
nchunks = (MaxFSMPages - 1) / CHUNKPAGES + 1;
chunks = (FSMChunk *) ShmemAlloc(nchunks * sizeof(FSMChunk));
if (chunks == NULL)
elog(FATAL, "Insufficient shared memory for free space map");
prevchunk = NULL;
while (nchunks-- > 0)
{
chunks->next = prevchunk;
prevchunk = chunks;
chunks++;
}
FreeSpaceMap->freeChunks = prevchunk;
}
int
FreeSpaceShmemSize(void)
{
int size;
int nchunks;
/*
* There is no point in allowing less than one "chunk" per relation,
* so force MaxFSMPages to be at least CHUNKPAGES * MaxFSMRelations.
*/
Assert(MaxFSMRelations > 0);
if (MaxFSMPages < CHUNKPAGES * MaxFSMRelations)
MaxFSMPages = CHUNKPAGES * MaxFSMRelations;
/* table header */
size = MAXALIGN(sizeof(FSMHeader));
/* hash table, including the FSMRelation objects */
size += hash_estimate_size(MaxFSMRelations,
SHMEM_FSMHASH_KEYSIZE,
SHMEM_FSMHASH_DATASIZE);
/* FSMChunk objects */
nchunks = (MaxFSMPages - 1) / CHUNKPAGES + 1;
size += MAXALIGN(nchunks * sizeof(FSMChunk));
return size;
}
void
FreeSpaceMapForgetRel(RelFileNode *rel)
{
}
#ifdef FREESPACE_DEBUG
/*
* Dump contents of freespace map for debugging.
*
* We assume caller holds the FreeSpaceLock, or is otherwise unconcerned
* about other processes.
*/
void
DumpFreeSpace(void)
{
}
#endif /* FREESPACE_DEBUG */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.40 2001/03/22 03:59:45 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.41 2001/06/27 23:31:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -19,6 +19,7 @@
#include "miscadmin.h" #include "miscadmin.h"
#include "access/xlog.h" #include "access/xlog.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "storage/freespace.h"
#include "storage/lmgr.h" #include "storage/lmgr.h"
#include "storage/proc.h" #include "storage/proc.h"
#include "storage/sinval.h" #include "storage/sinval.h"
@ -47,8 +48,12 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int maxBackends)
* moderately-accurate estimates for the big hogs, plus 100K for the * moderately-accurate estimates for the big hogs, plus 100K for the
* stuff that's too small to bother with estimating. * stuff that's too small to bother with estimating.
*/ */
size = BufferShmemSize() + LockShmemSize(maxBackends) + size = BufferShmemSize();
XLOGShmemSize() + SLockShmemSize() + SInvalShmemSize(maxBackends); size += LockShmemSize(maxBackends);
size += XLOGShmemSize();
size += SLockShmemSize();
size += SInvalShmemSize(maxBackends);
size += FreeSpaceShmemSize();
#ifdef STABLE_MEMORY_STORAGE #ifdef STABLE_MEMORY_STORAGE
size += MMShmemSize(); size += MMShmemSize();
#endif #endif
@ -96,4 +101,9 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int maxBackends)
* Set up shared-inval messaging * Set up shared-inval messaging
*/ */
CreateSharedInvalidationState(maxBackends); CreateSharedInvalidationState(maxBackends);
/*
* Set up free-space map
*/
InitFreeSpaceMap();
} }

View File

@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.32 2001/03/22 03:59:45 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.33 2001/06/27 23:31:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -31,19 +31,18 @@
/* Probably should move these to an appropriate header file */ /* Probably should move these to an appropriate header file */
extern SPINLOCK ShmemLock;
extern SPINLOCK ShmemIndexLock;
extern SPINLOCK BufMgrLock; extern SPINLOCK BufMgrLock;
extern SPINLOCK LockMgrLock;
extern SPINLOCK ProcStructLock;
extern SPINLOCK SInvalLock;
extern SPINLOCK OidGenLockId; extern SPINLOCK OidGenLockId;
extern SPINLOCK XidGenLockId; extern SPINLOCK XidGenLockId;
extern SPINLOCK ControlFileLockId; extern SPINLOCK ControlFileLockId;
extern SPINLOCK ShmemLock;
extern SPINLOCK ShmemIndexLock;
extern SPINLOCK LockMgrLock;
extern SPINLOCK SInvalLock;
extern SPINLOCK ProcStructLock;
extern SPINLOCK FreeSpaceLock;
#ifdef STABLE_MEMORY_STORAGE #ifdef STABLE_MEMORY_STORAGE
extern SPINLOCK MMCacheLock; extern SPINLOCK MMCacheLock;
#endif #endif
@ -57,16 +56,16 @@ extern SPINLOCK MMCacheLock;
static void static void
InitSpinLockIDs(void) InitSpinLockIDs(void)
{ {
ShmemLock = (SPINLOCK) SHMEMLOCKID;
ShmemIndexLock = (SPINLOCK) SHMEMINDEXLOCKID;
BufMgrLock = (SPINLOCK) BUFMGRLOCKID; BufMgrLock = (SPINLOCK) BUFMGRLOCKID;
LockMgrLock = (SPINLOCK) LOCKMGRLOCKID;
ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID;
SInvalLock = (SPINLOCK) SINVALLOCKID;
OidGenLockId = (SPINLOCK) OIDGENLOCKID; OidGenLockId = (SPINLOCK) OIDGENLOCKID;
XidGenLockId = (SPINLOCK) XIDGENLOCKID; XidGenLockId = (SPINLOCK) XIDGENLOCKID;
ControlFileLockId = (SPINLOCK) CNTLFILELOCKID; ControlFileLockId = (SPINLOCK) CNTLFILELOCKID;
ShmemLock = (SPINLOCK) SHMEMLOCKID;
ShmemIndexLock = (SPINLOCK) SHMEMINDEXLOCKID;
LockMgrLock = (SPINLOCK) LOCKMGRLOCKID;
SInvalLock = (SPINLOCK) SINVALLOCKID;
ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID;
FreeSpaceLock = (SPINLOCK) FREESPACELOCKID;
#ifdef STABLE_MEMORY_STORAGE #ifdef STABLE_MEMORY_STORAGE
MMCacheLock = (SPINLOCK) MMCACHELOCKID; MMCacheLock = (SPINLOCK) MMCACHELOCKID;
#endif #endif

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.89 2001/06/22 00:04:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.90 2001/06/27 23:31:39 tgl Exp $
* *
* NOTES * NOTES
* Outside modules can create a lock table and acquire/release * Outside modules can create a lock table and acquire/release
@ -40,6 +40,13 @@
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/ps_status.h" #include "utils/ps_status.h"
/* This configuration variable is used to set the lock table size */
int max_locks_per_xact; /* set by guc.c */
#define NLOCKENTS(maxBackends) (max_locks_per_xact * (maxBackends))
static int WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode, static int WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode,
LOCK *lock, HOLDER *holder); LOCK *lock, HOLDER *holder);
static void LockCountMyLocks(SHMEM_OFFSET lockOffset, PROC *proc, static void LockCountMyLocks(SHMEM_OFFSET lockOffset, PROC *proc,
@ -1388,6 +1395,7 @@ int
LockShmemSize(int maxBackends) LockShmemSize(int maxBackends)
{ {
int size = 0; int size = 0;
long max_table_size = NLOCKENTS(maxBackends);
size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */ size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */
size += maxBackends * MAXALIGN(sizeof(PROC)); /* each MyProc */ size += maxBackends * MAXALIGN(sizeof(PROC)); /* each MyProc */
@ -1395,12 +1403,12 @@ LockShmemSize(int maxBackends)
* lockMethodTable->ctl */ * lockMethodTable->ctl */
/* lockHash table */ /* lockHash table */
size += hash_estimate_size(NLOCKENTS(maxBackends), size += hash_estimate_size(max_table_size,
SHMEM_LOCKTAB_KEYSIZE, SHMEM_LOCKTAB_KEYSIZE,
SHMEM_LOCKTAB_DATASIZE); SHMEM_LOCKTAB_DATASIZE);
/* holderHash table */ /* holderHash table */
size += hash_estimate_size(NLOCKENTS(maxBackends), size += hash_estimate_size(max_table_size,
SHMEM_HOLDERTAB_KEYSIZE, SHMEM_HOLDERTAB_KEYSIZE,
SHMEM_HOLDERTAB_DATASIZE); SHMEM_HOLDERTAB_DATASIZE);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.85 2001/06/06 17:07:46 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.86 2001/06/27 23:31:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -72,10 +72,10 @@ static MemoryContext MdCxt; /* context for all my allocations */
/* routines declared here */ /* routines declared here */
static void mdclose_fd(int fd); static void mdclose_fd(int fd);
static int _mdfd_getrelnfd(Relation reln); static int _mdfd_getrelnfd(Relation reln);
static MdfdVec *_mdfd_openseg(Relation reln, int segno, int oflags); static MdfdVec *_mdfd_openseg(Relation reln, BlockNumber segno, int oflags);
static MdfdVec *_mdfd_getseg(Relation reln, int blkno); static MdfdVec *_mdfd_getseg(Relation reln, BlockNumber blkno);
static int _mdfd_blind_getseg(RelFileNode rnode, int blkno); static int _mdfd_blind_getseg(RelFileNode rnode, BlockNumber blkno);
static int _fdvec_alloc(void); static int _fdvec_alloc(void);
static void _fdvec_free(int); static void _fdvec_free(int);
@ -93,7 +93,7 @@ static BlockNumber _mdnblocks(File file, Size blcksz);
* Returns SM_SUCCESS or SM_FAIL with errno set as appropriate. * Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
*/ */
int int
mdinit() mdinit(void)
{ {
int i; int i;
@ -194,11 +194,11 @@ mdunlink(RelFileNode rnode)
if (status == SM_SUCCESS) if (status == SM_SUCCESS)
{ {
char *segpath = (char *) palloc(strlen(path) + 12); char *segpath = (char *) palloc(strlen(path) + 12);
int segno; BlockNumber segno;
for (segno = 1;; segno++) for (segno = 1;; segno++)
{ {
sprintf(segpath, "%s.%d", path, segno); sprintf(segpath, "%s.%u", path, segno);
if (unlink(segpath) < 0) if (unlink(segpath) < 0)
{ {
/* ENOENT is expected after the last segment... */ /* ENOENT is expected after the last segment... */
@ -246,7 +246,7 @@ mdextend(Relation reln, BlockNumber blocknum, char *buffer)
v = _mdfd_getseg(reln, blocknum); v = _mdfd_getseg(reln, blocknum);
#ifndef LET_OS_MANAGE_FILESIZE #ifndef LET_OS_MANAGE_FILESIZE
seekpos = (long) (BLCKSZ * (blocknum % RELSEG_SIZE)); seekpos = (long) (BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)));
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
if (seekpos >= BLCKSZ * RELSEG_SIZE) if (seekpos >= BLCKSZ * RELSEG_SIZE)
elog(FATAL, "seekpos too big!"); elog(FATAL, "seekpos too big!");
@ -283,7 +283,7 @@ mdextend(Relation reln, BlockNumber blocknum, char *buffer)
#ifndef LET_OS_MANAGE_FILESIZE #ifndef LET_OS_MANAGE_FILESIZE
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
if (_mdnblocks(v->mdfd_vfd, BLCKSZ) > RELSEG_SIZE) if (_mdnblocks(v->mdfd_vfd, BLCKSZ) > ((BlockNumber) RELSEG_SIZE))
elog(FATAL, "segment too big!"); elog(FATAL, "segment too big!");
#endif #endif
#endif #endif
@ -338,7 +338,7 @@ mdopen(Relation reln)
Md_fdvec[vfd].mdfd_chain = (MdfdVec *) NULL; Md_fdvec[vfd].mdfd_chain = (MdfdVec *) NULL;
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
if (_mdnblocks(fd, BLCKSZ) > RELSEG_SIZE) if (_mdnblocks(fd, BLCKSZ) > ((BlockNumber) RELSEG_SIZE))
elog(FATAL, "segment too big on relopen!"); elog(FATAL, "segment too big on relopen!");
#endif #endif
#endif #endif
@ -438,7 +438,7 @@ mdread(Relation reln, BlockNumber blocknum, char *buffer)
v = _mdfd_getseg(reln, blocknum); v = _mdfd_getseg(reln, blocknum);
#ifndef LET_OS_MANAGE_FILESIZE #ifndef LET_OS_MANAGE_FILESIZE
seekpos = (long) (BLCKSZ * (blocknum % RELSEG_SIZE)); seekpos = (long) (BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)));
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
if (seekpos >= BLCKSZ * RELSEG_SIZE) if (seekpos >= BLCKSZ * RELSEG_SIZE)
@ -482,7 +482,7 @@ mdwrite(Relation reln, BlockNumber blocknum, char *buffer)
v = _mdfd_getseg(reln, blocknum); v = _mdfd_getseg(reln, blocknum);
#ifndef LET_OS_MANAGE_FILESIZE #ifndef LET_OS_MANAGE_FILESIZE
seekpos = (long) (BLCKSZ * (blocknum % RELSEG_SIZE)); seekpos = (long) (BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)));
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
if (seekpos >= BLCKSZ * RELSEG_SIZE) if (seekpos >= BLCKSZ * RELSEG_SIZE)
elog(FATAL, "seekpos too big!"); elog(FATAL, "seekpos too big!");
@ -516,7 +516,7 @@ mdflush(Relation reln, BlockNumber blocknum, char *buffer)
v = _mdfd_getseg(reln, blocknum); v = _mdfd_getseg(reln, blocknum);
#ifndef LET_OS_MANAGE_FILESIZE #ifndef LET_OS_MANAGE_FILESIZE
seekpos = (long) (BLCKSZ * (blocknum % RELSEG_SIZE)); seekpos = (long) (BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)));
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
if (seekpos >= BLCKSZ * RELSEG_SIZE) if (seekpos >= BLCKSZ * RELSEG_SIZE)
elog(FATAL, "seekpos too big!"); elog(FATAL, "seekpos too big!");
@ -561,7 +561,7 @@ mdblindwrt(RelFileNode rnode,
return SM_FAIL; return SM_FAIL;
#ifndef LET_OS_MANAGE_FILESIZE #ifndef LET_OS_MANAGE_FILESIZE
seekpos = (long) (BLCKSZ * (blkno % RELSEG_SIZE)); seekpos = (long) (BLCKSZ * (blkno % ((BlockNumber) RELSEG_SIZE)));
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
if (seekpos >= BLCKSZ * RELSEG_SIZE) if (seekpos >= BLCKSZ * RELSEG_SIZE)
elog(FATAL, "seekpos too big!"); elog(FATAL, "seekpos too big!");
@ -659,16 +659,14 @@ mdblindmarkdirty(RelFileNode rnode,
* *
* Returns # of blocks, elog's on error. * Returns # of blocks, elog's on error.
*/ */
int BlockNumber
mdnblocks(Relation reln) mdnblocks(Relation reln)
{ {
int fd; int fd;
MdfdVec *v; MdfdVec *v;
#ifndef LET_OS_MANAGE_FILESIZE #ifndef LET_OS_MANAGE_FILESIZE
int nblocks; BlockNumber nblocks;
int segno; BlockNumber segno;
#endif #endif
fd = _mdfd_getrelnfd(reln); fd = _mdfd_getrelnfd(reln);
@ -679,10 +677,10 @@ mdnblocks(Relation reln)
for (;;) for (;;)
{ {
nblocks = _mdnblocks(v->mdfd_vfd, BLCKSZ); nblocks = _mdnblocks(v->mdfd_vfd, BLCKSZ);
if (nblocks > RELSEG_SIZE) if (nblocks > ((BlockNumber) RELSEG_SIZE))
elog(FATAL, "segment too big in mdnblocks!"); elog(FATAL, "segment too big in mdnblocks!");
if (nblocks < RELSEG_SIZE) if (nblocks < ((BlockNumber) RELSEG_SIZE))
return (segno * RELSEG_SIZE) + nblocks; return (segno * ((BlockNumber) RELSEG_SIZE)) + nblocks;
/* /*
* If segment is exactly RELSEG_SIZE, advance to next one. * If segment is exactly RELSEG_SIZE, advance to next one.
*/ */
@ -713,18 +711,16 @@ mdnblocks(Relation reln)
/* /*
* mdtruncate() -- Truncate relation to specified number of blocks. * mdtruncate() -- Truncate relation to specified number of blocks.
* *
* Returns # of blocks or -1 on error. * Returns # of blocks or InvalidBlockNumber on error.
*/ */
int BlockNumber
mdtruncate(Relation reln, int nblocks) mdtruncate(Relation reln, BlockNumber nblocks)
{ {
int curnblk;
int fd; int fd;
MdfdVec *v; MdfdVec *v;
BlockNumber curnblk;
#ifndef LET_OS_MANAGE_FILESIZE #ifndef LET_OS_MANAGE_FILESIZE
int priorblocks; BlockNumber priorblocks;
#endif #endif
/* /*
@ -732,8 +728,8 @@ mdtruncate(Relation reln, int nblocks)
* that truncate/delete loop will get them all! * that truncate/delete loop will get them all!
*/ */
curnblk = mdnblocks(reln); curnblk = mdnblocks(reln);
if (nblocks < 0 || nblocks > curnblk) if (nblocks > curnblk)
return -1; /* bogus request */ return InvalidBlockNumber; /* bogus request */
if (nblocks == curnblk) if (nblocks == curnblk)
return nblocks; /* no work */ return nblocks; /* no work */
@ -748,7 +744,6 @@ mdtruncate(Relation reln, int nblocks)
if (priorblocks > nblocks) if (priorblocks > nblocks)
{ {
/* /*
* This segment is no longer wanted at all (and has already * This segment is no longer wanted at all (and has already
* been unlinked from the mdfd_chain). We truncate the file * been unlinked from the mdfd_chain). We truncate the file
@ -763,27 +758,25 @@ mdtruncate(Relation reln, int nblocks)
* segment */ * segment */
pfree(ov); pfree(ov);
} }
else if (priorblocks + RELSEG_SIZE > nblocks) else if (priorblocks + ((BlockNumber) RELSEG_SIZE) > nblocks)
{ {
/* /*
* This is the last segment we want to keep. Truncate the file * This is the last segment we want to keep. Truncate the file
* to the right length, and clear chain link that points to * to the right length, and clear chain link that points to
* any remaining segments (which we shall zap). NOTE: if * any remaining segments (which we shall zap). NOTE: if
* nblocks is exactly a multiple K of RELSEG_SIZE, we will * nblocks is exactly a multiple K of RELSEG_SIZE, we will
* truncate the K+1st segment to 0 length but keep it. This is * truncate the K+1st segment to 0 length but keep it. This is
* mainly so that the right thing happens if nblocks=0. * mainly so that the right thing happens if nblocks==0.
*/ */
int lastsegblocks = nblocks - priorblocks; BlockNumber lastsegblocks = nblocks - priorblocks;
if (FileTruncate(v->mdfd_vfd, lastsegblocks * BLCKSZ) < 0) if (FileTruncate(v->mdfd_vfd, lastsegblocks * BLCKSZ) < 0)
return -1; return InvalidBlockNumber;
v = v->mdfd_chain; v = v->mdfd_chain;
ov->mdfd_chain = (MdfdVec *) NULL; ov->mdfd_chain = (MdfdVec *) NULL;
} }
else else
{ {
/* /*
* We still need this segment and 0 or more blocks beyond it, * We still need this segment and 0 or more blocks beyond it,
* so nothing to do here. * so nothing to do here.
@ -794,7 +787,7 @@ mdtruncate(Relation reln, int nblocks)
} }
#else #else
if (FileTruncate(v->mdfd_vfd, nblocks * BLCKSZ) < 0) if (FileTruncate(v->mdfd_vfd, nblocks * BLCKSZ) < 0)
return -1; return InvalidBlockNumber;
#endif #endif
return nblocks; return nblocks;
@ -940,7 +933,7 @@ _fdvec_free(int fdvec)
} }
static MdfdVec * static MdfdVec *
_mdfd_openseg(Relation reln, int segno, int oflags) _mdfd_openseg(Relation reln, BlockNumber segno, int oflags)
{ {
MdfdVec *v; MdfdVec *v;
int fd; int fd;
@ -953,7 +946,7 @@ _mdfd_openseg(Relation reln, int segno, int oflags)
if (segno > 0) if (segno > 0)
{ {
fullpath = (char *) palloc(strlen(path) + 12); fullpath = (char *) palloc(strlen(path) + 12);
sprintf(fullpath, "%s.%d", path, segno); sprintf(fullpath, "%s.%u", path, segno);
pfree(path); pfree(path);
} }
else else
@ -977,7 +970,7 @@ _mdfd_openseg(Relation reln, int segno, int oflags)
v->mdfd_chain = (MdfdVec *) NULL; v->mdfd_chain = (MdfdVec *) NULL;
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
if (_mdnblocks(fd, BLCKSZ) > RELSEG_SIZE) if (_mdnblocks(fd, BLCKSZ) > ((BlockNumber) RELSEG_SIZE))
elog(FATAL, "segment too big on openseg!"); elog(FATAL, "segment too big on openseg!");
#endif #endif
#endif #endif
@ -1007,17 +1000,19 @@ _mdfd_getrelnfd(Relation reln)
/* Find the segment of the relation holding the specified block */ /* Find the segment of the relation holding the specified block */
static MdfdVec * static MdfdVec *
_mdfd_getseg(Relation reln, int blkno) _mdfd_getseg(Relation reln, BlockNumber blkno)
{ {
MdfdVec *v; MdfdVec *v;
int segno;
int fd; int fd;
int i; #ifndef LET_OS_MANAGE_FILESIZE
BlockNumber segno;
BlockNumber i;
#endif
fd = _mdfd_getrelnfd(reln); fd = _mdfd_getrelnfd(reln);
#ifndef LET_OS_MANAGE_FILESIZE #ifndef LET_OS_MANAGE_FILESIZE
for (v = &Md_fdvec[fd], segno = blkno / RELSEG_SIZE, i = 1; for (v = &Md_fdvec[fd], segno = blkno / ((BlockNumber) RELSEG_SIZE), i = 1;
segno > 0; segno > 0;
i++, segno--) i++, segno--)
{ {
@ -1038,7 +1033,7 @@ _mdfd_getseg(Relation reln, int blkno)
v->mdfd_chain = _mdfd_openseg(reln, i, (segno == 1) ? O_CREAT : 0); v->mdfd_chain = _mdfd_openseg(reln, i, (segno == 1) ? O_CREAT : 0);
if (v->mdfd_chain == (MdfdVec *) NULL) if (v->mdfd_chain == (MdfdVec *) NULL)
elog(ERROR, "cannot open segment %d of relation %s (target block %d): %m", elog(ERROR, "cannot open segment %u of relation %s (target block %u): %m",
i, RelationGetRelationName(reln), blkno); i, RelationGetRelationName(reln), blkno);
} }
v = v->mdfd_chain; v = v->mdfd_chain;
@ -1064,26 +1059,24 @@ _mdfd_getseg(Relation reln, int blkno)
*/ */
static int static int
_mdfd_blind_getseg(RelFileNode rnode, int blkno) _mdfd_blind_getseg(RelFileNode rnode, BlockNumber blkno)
{ {
char *path; char *path;
int fd; int fd;
#ifndef LET_OS_MANAGE_FILESIZE #ifndef LET_OS_MANAGE_FILESIZE
int segno; BlockNumber segno;
#endif #endif
path = relpath(rnode); path = relpath(rnode);
#ifndef LET_OS_MANAGE_FILESIZE #ifndef LET_OS_MANAGE_FILESIZE
/* append the '.segno', if needed */ /* append the '.segno', if needed */
segno = blkno / RELSEG_SIZE; segno = blkno / ((BlockNumber) RELSEG_SIZE);
if (segno > 0) if (segno > 0)
{ {
char *segpath = (char *) palloc(strlen(path) + 12); char *segpath = (char *) palloc(strlen(path) + 12);
sprintf(segpath, "%s.%d", path, segno); sprintf(segpath, "%s.%u", path, segno);
pfree(path); pfree(path);
path = segpath; path = segpath;
} }

View File

@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.23 2001/05/10 20:38:49 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.24 2001/06/27 23:31:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -489,15 +489,15 @@ mmblindwrt(char *dbstr,
/* /*
* mmnblocks() -- Get the number of blocks stored in a relation. * mmnblocks() -- Get the number of blocks stored in a relation.
* *
* Returns # of blocks or -1 on error. * Returns # of blocks or InvalidBlockNumber on error.
*/ */
int BlockNumber
mmnblocks(Relation reln) mmnblocks(Relation reln)
{ {
MMRelTag rtag; MMRelTag rtag;
MMRelHashEntry *rentry; MMRelHashEntry *rentry;
bool found; bool found;
int nblocks; BlockNumber nblocks;
if (reln->rd_rel->relisshared) if (reln->rd_rel->relisshared)
rtag.mmrt_dbid = (Oid) 0; rtag.mmrt_dbid = (Oid) 0;
@ -520,7 +520,7 @@ mmnblocks(Relation reln)
if (found) if (found)
nblocks = rentry->mmrhe_nblocks; nblocks = rentry->mmrhe_nblocks;
else else
nblocks = -1; nblocks = InvalidBlockNumber;
SpinRelease(MMCacheLock); SpinRelease(MMCacheLock);

View File

@ -11,13 +11,14 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/smgr.c,v 1.49 2001/05/10 20:38:49 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/smgr/smgr.c,v 1.50 2001/06/27 23:31:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "storage/freespace.h"
#include "storage/smgr.h" #include "storage/smgr.h"
#include "utils/memutils.h" #include "utils/memutils.h"
@ -44,8 +45,8 @@ typedef struct f_smgr
char *buffer, bool dofsync); char *buffer, bool dofsync);
int (*smgr_markdirty) (Relation reln, BlockNumber blkno); int (*smgr_markdirty) (Relation reln, BlockNumber blkno);
int (*smgr_blindmarkdirty) (RelFileNode, BlockNumber blkno); int (*smgr_blindmarkdirty) (RelFileNode, BlockNumber blkno);
int (*smgr_nblocks) (Relation reln); BlockNumber (*smgr_nblocks) (Relation reln);
int (*smgr_truncate) (Relation reln, int nblocks); BlockNumber (*smgr_truncate) (Relation reln, BlockNumber nblocks);
int (*smgr_commit) (void); /* may be NULL */ int (*smgr_commit) (void); /* may be NULL */
int (*smgr_abort) (void); /* may be NULL */ int (*smgr_abort) (void); /* may be NULL */
int (*smgr_sync) (void); int (*smgr_sync) (void);
@ -433,16 +434,10 @@ smgrblindmarkdirty(int16 which,
* Returns the number of blocks on success, aborts the current * Returns the number of blocks on success, aborts the current
* transaction on failure. * transaction on failure.
*/ */
int BlockNumber
smgrnblocks(int16 which, Relation reln) smgrnblocks(int16 which, Relation reln)
{ {
int nblocks; return (*(smgrsw[which].smgr_nblocks)) (reln);
if ((nblocks = (*(smgrsw[which].smgr_nblocks)) (reln)) < 0)
elog(ERROR, "cannot count blocks for %s: %m",
RelationGetRelationName(reln));
return nblocks;
} }
/* /*
@ -452,16 +447,24 @@ smgrnblocks(int16 which, Relation reln)
* Returns the number of blocks on success, aborts the current * Returns the number of blocks on success, aborts the current
* transaction on failure. * transaction on failure.
*/ */
int BlockNumber
smgrtruncate(int16 which, Relation reln, int nblocks) smgrtruncate(int16 which, Relation reln, BlockNumber nblocks)
{ {
int newblks; BlockNumber newblks;
newblks = nblocks; newblks = nblocks;
if (smgrsw[which].smgr_truncate) if (smgrsw[which].smgr_truncate)
{ {
if ((newblks = (*(smgrsw[which].smgr_truncate)) (reln, nblocks)) < 0) /*
elog(ERROR, "cannot truncate %s to %d blocks: %m", * Tell the free space map to forget this relation, so that it
* stops caching info about the deleted blocks. XXX perhaps
* tell it to forget only info about blocks beyond nblocks?
*/
FreeSpaceMapForgetRel(&reln->rd_node);
newblks = (*(smgrsw[which].smgr_truncate)) (reln, nblocks);
if (newblks == InvalidBlockNumber)
elog(ERROR, "cannot truncate %s to %u blocks: %m",
RelationGetRelationName(reln), nblocks); RelationGetRelationName(reln), nblocks);
} }
@ -481,7 +484,6 @@ smgrDoPendingDeletes(bool isCommit)
pendingDeletes = pending->next; pendingDeletes = pending->next;
if (pending->atCommit == isCommit) if (pending->atCommit == isCommit)
{ {
/* /*
* Get rid of any leftover buffers for the rel (shouldn't be * Get rid of any leftover buffers for the rel (shouldn't be
* any in the commit case, but there can be in the abort * any in the commit case, but there can be in the abort
@ -489,6 +491,13 @@ smgrDoPendingDeletes(bool isCommit)
*/ */
DropRelFileNodeBuffers(pending->relnode); DropRelFileNodeBuffers(pending->relnode);
/*
* Tell the free space map to forget this relation. It won't
* be accessed any more anyway, but we may as well recycle the
* map space quickly.
*/
FreeSpaceMapForgetRel(&pending->relnode);
/* /*
* And delete the physical files. * And delete the physical files.
* *

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.139 2001/06/22 19:16:23 wieck Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.140 2001/06/27 23:31:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -25,7 +25,6 @@
* NOTES * NOTES
* The following code contains many undocumented hacks. Please be * The following code contains many undocumented hacks. Please be
* careful.... * careful....
*
*/ */
#include "postgres.h" #include "postgres.h"
@ -63,7 +62,6 @@
/* /*
* hardcoded tuple descriptors. see lib/backend/catalog/pg_attribute.h * hardcoded tuple descriptors. see lib/backend/catalog/pg_attribute.h
*
*/ */
static FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class}; static FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class};
static FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute}; static FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute};
@ -76,7 +74,6 @@ static FormData_pg_attribute Desc_pg_log[Natts_pg_log] = {Schema_pg_log};
* *
* Relations are looked up two ways, by name and by id, * Relations are looked up two ways, by name and by id,
* thus there are two hash tables for referencing them. * thus there are two hash tables for referencing them.
*
*/ */
static HTAB *RelationNameCache; static HTAB *RelationNameCache;
static HTAB *RelationIdCache; static HTAB *RelationIdCache;
@ -105,7 +102,6 @@ static bool criticalRelcachesBuilt = false;
/* /*
* RelationBuildDescInfo exists so code can be shared * RelationBuildDescInfo exists so code can be shared
* between RelationIdGetRelation() and RelationNameGetRelation() * between RelationIdGetRelation() and RelationNameGetRelation()
*
*/ */
typedef struct RelationBuildDescInfo typedef struct RelationBuildDescInfo
{ {
@ -139,7 +135,6 @@ typedef struct relnodecacheent
/* /*
* macros to manipulate name cache and id cache * macros to manipulate name cache and id cache
*
*/ */
#define RelationCacheInsert(RELATION) \ #define RelationCacheInsert(RELATION) \
do { \ do { \
@ -285,7 +280,6 @@ static List *insert_ordered_oid(List *list, Oid datum);
/* /*
* RelationIdGetRelation() and RelationNameGetRelation() * RelationIdGetRelation() and RelationNameGetRelation()
* support functions * support functions
*
*/ */
@ -298,7 +292,6 @@ static List *insert_ordered_oid(List *list, Oid datum);
* *
* NB: the returned tuple has been copied into palloc'd storage * NB: the returned tuple has been copied into palloc'd storage
* and must eventually be freed with heap_freetuple. * and must eventually be freed with heap_freetuple.
*
*/ */
static HeapTuple static HeapTuple
ScanPgRelation(RelationBuildDescInfo buildinfo) ScanPgRelation(RelationBuildDescInfo buildinfo)
@ -327,7 +320,6 @@ scan_pg_rel_seq(RelationBuildDescInfo buildinfo)
/* /*
* form a scan key * form a scan key
*
*/ */
switch (buildinfo.infotype) switch (buildinfo.infotype)
{ {
@ -352,7 +344,6 @@ scan_pg_rel_seq(RelationBuildDescInfo buildinfo)
/* /*
* open pg_class and fetch a tuple * open pg_class and fetch a tuple
*
*/ */
pg_class_desc = heap_openr(RelationRelationName, AccessShareLock); pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
pg_class_scan = heap_beginscan(pg_class_desc, 0, SnapshotNow, 1, &key); pg_class_scan = heap_beginscan(pg_class_desc, 0, SnapshotNow, 1, &key);
@ -360,7 +351,6 @@ scan_pg_rel_seq(RelationBuildDescInfo buildinfo)
/* /*
* get set to return tuple * get set to return tuple
*
*/ */
if (!HeapTupleIsValid(pg_class_tuple)) if (!HeapTupleIsValid(pg_class_tuple))
return_tuple = pg_class_tuple; return_tuple = pg_class_tuple;
@ -372,7 +362,6 @@ scan_pg_rel_seq(RelationBuildDescInfo buildinfo)
* returned here without having the corresponding buffer pinned. * returned here without having the corresponding buffer pinned.
* so when the buffer gets replaced, all hell breaks loose. this * so when the buffer gets replaced, all hell breaks loose. this
* bug is discovered and killed by wei on 9/27/91. * bug is discovered and killed by wei on 9/27/91.
*
*/ */
return_tuple = heap_copytuple(pg_class_tuple); return_tuple = heap_copytuple(pg_class_tuple);
} }
@ -435,7 +424,6 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
* If 'relation' is NULL, allocate a new RelationData object. * If 'relation' is NULL, allocate a new RelationData object.
* If not, reuse the given object (that path is taken only when * If not, reuse the given object (that path is taken only when
* we have to rebuild a relcache entry during RelationClearRelation). * we have to rebuild a relcache entry during RelationClearRelation).
*
*/ */
static Relation static Relation
AllocateRelationDesc(Relation relation, Form_pg_class relp) AllocateRelationDesc(Relation relation, Form_pg_class relp)
@ -448,16 +436,15 @@ AllocateRelationDesc(Relation relation, Form_pg_class relp)
/* /*
* allocate space for new relation descriptor, if needed * allocate space for new relation descriptor, if needed
*
*/ */
if (relation == NULL) if (relation == NULL)
relation = (Relation) palloc(sizeof(RelationData)); relation = (Relation) palloc(sizeof(RelationData));
/* /*
* clear all fields of reldesc * clear all fields of reldesc
*
*/ */
MemSet((char *) relation, 0, sizeof(RelationData)); MemSet((char *) relation, 0, sizeof(RelationData));
relation->rd_targblock = InvalidBlockNumber;
/* make sure relation is marked as having no open file yet */ /* make sure relation is marked as having no open file yet */
relation->rd_fd = -1; relation->rd_fd = -1;
@ -471,7 +458,6 @@ AllocateRelationDesc(Relation relation, Form_pg_class relp)
* wouldn't know if the value is valid ... bottom line is that relacl * wouldn't know if the value is valid ... bottom line is that relacl
* *cannot* be retrieved from the relcache. Get it from the syscache * *cannot* be retrieved from the relcache. Get it from the syscache
* if you need it. * if you need it.
*
*/ */
relationForm = (Form_pg_class) palloc(CLASS_TUPLE_SIZE); relationForm = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
@ -493,7 +479,6 @@ AllocateRelationDesc(Relation relation, Form_pg_class relp)
* *
* Form the relation's tuple descriptor from information in * Form the relation's tuple descriptor from information in
* the pg_attribute, pg_attrdef & pg_relcheck system cataloges. * the pg_attribute, pg_attrdef & pg_relcheck system cataloges.
*
*/ */
static void static void
RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
@ -574,7 +559,6 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
/* /*
* form a scan key * form a scan key
*
*/ */
ScanKeyEntryInitialize(&key, 0, ScanKeyEntryInitialize(&key, 0,
Anum_pg_attribute_attrelid, Anum_pg_attribute_attrelid,
@ -583,14 +567,12 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
/* /*
* open pg_attribute and begin a scan * open pg_attribute and begin a scan
*
*/ */
pg_attribute_desc = heap_openr(AttributeRelationName, AccessShareLock); pg_attribute_desc = heap_openr(AttributeRelationName, AccessShareLock);
pg_attribute_scan = heap_beginscan(pg_attribute_desc, 0, SnapshotNow, 1, &key); pg_attribute_scan = heap_beginscan(pg_attribute_desc, 0, SnapshotNow, 1, &key);
/* /*
* add attribute data to relation->rd_att * add attribute data to relation->rd_att
*
*/ */
need = relation->rd_rel->relnatts; need = relation->rd_rel->relnatts;
@ -639,7 +621,6 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
/* /*
* end the scan and close the attribute relation * end the scan and close the attribute relation
*
*/ */
heap_endscan(pg_attribute_scan); heap_endscan(pg_attribute_scan);
heap_close(pg_attribute_desc, AccessShareLock); heap_close(pg_attribute_desc, AccessShareLock);
@ -648,7 +629,6 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
* The attcacheoff values we read from pg_attribute should all be -1 * The attcacheoff values we read from pg_attribute should all be -1
* ("unknown"). Verify this if assert checking is on. They will be * ("unknown"). Verify this if assert checking is on. They will be
* computed when and if needed during tuple access. * computed when and if needed during tuple access.
*
*/ */
#ifdef USE_ASSERT_CHECKING #ifdef USE_ASSERT_CHECKING
{ {
@ -664,7 +644,6 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
* attribute: it must be zero. This eliminates the need for special * attribute: it must be zero. This eliminates the need for special
* cases for attnum=1 that used to exist in fastgetattr() and * cases for attnum=1 that used to exist in fastgetattr() and
* index_getattr(). * index_getattr().
*
*/ */
relation->rd_att->attrs[0]->attcacheoff = 0; relation->rd_att->attrs[0]->attcacheoff = 0;
@ -758,7 +737,6 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
* The attcacheoff values we read from pg_attribute should all be -1 * The attcacheoff values we read from pg_attribute should all be -1
* ("unknown"). Verify this if assert checking is on. They will be * ("unknown"). Verify this if assert checking is on. They will be
* computed when and if needed during tuple access. * computed when and if needed during tuple access.
*
*/ */
#ifdef USE_ASSERT_CHECKING #ifdef USE_ASSERT_CHECKING
for (i = 0; i < relation->rd_rel->relnatts; i++) for (i = 0; i < relation->rd_rel->relnatts; i++)
@ -770,7 +748,6 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
* attribute: it must be zero. This eliminates the need for special * attribute: it must be zero. This eliminates the need for special
* cases for attnum=1 that used to exist in fastgetattr() and * cases for attnum=1 that used to exist in fastgetattr() and
* index_getattr(). * index_getattr().
*
*/ */
relation->rd_att->attrs[0]->attcacheoff = 0; relation->rd_att->attrs[0]->attcacheoff = 0;
@ -791,7 +768,6 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
* entry, because that keeps the update logic in RelationClearRelation() * entry, because that keeps the update logic in RelationClearRelation()
* manageable. The other subsidiary data structures are simple enough * manageable. The other subsidiary data structures are simple enough
* to be easy to free explicitly, anyway. * to be easy to free explicitly, anyway.
*
*/ */
static void static void
RelationBuildRuleLock(Relation relation) RelationBuildRuleLock(Relation relation)
@ -814,7 +790,7 @@ RelationBuildRuleLock(Relation relation)
*/ */
rulescxt = AllocSetContextCreate(CacheMemoryContext, rulescxt = AllocSetContextCreate(CacheMemoryContext,
RelationGetRelationName(relation), RelationGetRelationName(relation),
0, /* minsize */ 0, /* minsize */
1024, /* initsize */ 1024, /* initsize */
1024); /* maxsize */ 1024); /* maxsize */
relation->rd_rulescxt = rulescxt; relation->rd_rulescxt = rulescxt;
@ -822,7 +798,6 @@ RelationBuildRuleLock(Relation relation)
/* /*
* form an array to hold the rewrite rules (the array is extended if * form an array to hold the rewrite rules (the array is extended if
* necessary) * necessary)
*
*/ */
maxlocks = 4; maxlocks = 4;
rules = (RewriteRule **) rules = (RewriteRule **)
@ -831,7 +806,6 @@ RelationBuildRuleLock(Relation relation)
/* /*
* form a scan key * form a scan key
*
*/ */
ScanKeyEntryInitialize(&key, 0, ScanKeyEntryInitialize(&key, 0,
Anum_pg_rewrite_ev_class, Anum_pg_rewrite_ev_class,
@ -840,7 +814,6 @@ RelationBuildRuleLock(Relation relation)
/* /*
* open pg_rewrite and begin a scan * open pg_rewrite and begin a scan
*
*/ */
pg_rewrite_desc = heap_openr(RewriteRelationName, AccessShareLock); pg_rewrite_desc = heap_openr(RewriteRelationName, AccessShareLock);
pg_rewrite_scan = heap_beginscan(pg_rewrite_desc, 0, SnapshotNow, 1, &key); pg_rewrite_scan = heap_beginscan(pg_rewrite_desc, 0, SnapshotNow, 1, &key);
@ -908,14 +881,12 @@ RelationBuildRuleLock(Relation relation)
/* /*
* end the scan and close the attribute relation * end the scan and close the attribute relation
*
*/ */
heap_endscan(pg_rewrite_scan); heap_endscan(pg_rewrite_scan);
heap_close(pg_rewrite_desc, AccessShareLock); heap_close(pg_rewrite_desc, AccessShareLock);
/* /*
* form a RuleLock and insert into relation * form a RuleLock and insert into relation
*
*/ */
rulelock = (RuleLock *) MemoryContextAlloc(rulescxt, sizeof(RuleLock)); rulelock = (RuleLock *) MemoryContextAlloc(rulescxt, sizeof(RuleLock));
rulelock->numLocks = numlocks; rulelock->numLocks = numlocks;
@ -930,7 +901,6 @@ RelationBuildRuleLock(Relation relation)
* Determine whether two RuleLocks are equivalent * Determine whether two RuleLocks are equivalent
* *
* Probably this should be in the rules code someplace... * Probably this should be in the rules code someplace...
*
*/ */
static bool static bool
equalRuleLocks(RuleLock *rlock1, RuleLock *rlock2) equalRuleLocks(RuleLock *rlock1, RuleLock *rlock2)
@ -994,9 +964,9 @@ equalRuleLocks(RuleLock *rlock1, RuleLock *rlock2)
* fields: * fields:
* *
* File rd_fd; open file descriptor * File rd_fd; open file descriptor
* int rd_nblocks; number of blocks in rel * BlockNumber rd_nblocks; number of blocks in rel
* it will be set in ambeginscan() * it will be set in ambeginscan()
* uint16 rd_refcnt; reference count * int rd_refcnt; reference count
* Form_pg_am rd_am; AM tuple * Form_pg_am rd_am; AM tuple
* Form_pg_class rd_rel; RELATION tuple * Form_pg_class rd_rel; RELATION tuple
* Oid rd_id; relation's object id * Oid rd_id; relation's object id
@ -1022,20 +992,17 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
/* /*
* find the tuple in pg_class corresponding to the given relation id * find the tuple in pg_class corresponding to the given relation id
*
*/ */
pg_class_tuple = ScanPgRelation(buildinfo); pg_class_tuple = ScanPgRelation(buildinfo);
/* /*
* if no such tuple exists, return NULL * if no such tuple exists, return NULL
*
*/ */
if (!HeapTupleIsValid(pg_class_tuple)) if (!HeapTupleIsValid(pg_class_tuple))
return NULL; return NULL;
/* /*
* get information from the pg_class_tuple * get information from the pg_class_tuple
*
*/ */
relid = pg_class_tuple->t_data->t_oid; relid = pg_class_tuple->t_data->t_oid;
relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
@ -1043,37 +1010,31 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
/* /*
* allocate storage for the relation descriptor, and copy * allocate storage for the relation descriptor, and copy
* pg_class_tuple to relation->rd_rel. * pg_class_tuple to relation->rd_rel.
*
*/ */
relation = AllocateRelationDesc(oldrelation, relp); relation = AllocateRelationDesc(oldrelation, relp);
/* /*
* now we can free the memory allocated for pg_class_tuple * now we can free the memory allocated for pg_class_tuple
*
*/ */
heap_freetuple(pg_class_tuple); heap_freetuple(pg_class_tuple);
/* /*
* initialize the relation's relation id (relation->rd_id) * initialize the relation's relation id (relation->rd_id)
*
*/ */
RelationGetRelid(relation) = relid; RelationGetRelid(relation) = relid;
/* /*
* initialize relation->rd_refcnt * initialize relation->rd_refcnt
*
*/ */
RelationSetReferenceCount(relation, 1); RelationSetReferenceCount(relation, 1);
/* /*
* normal relations are not nailed into the cache * normal relations are not nailed into the cache
*
*/ */
relation->rd_isnailed = false; relation->rd_isnailed = false;
/* /*
* initialize the access method information (relation->rd_am) * initialize the access method information (relation->rd_am)
*
*/ */
relam = relation->rd_rel->relam; relam = relation->rd_rel->relam;
if (OidIsValid(relam)) if (OidIsValid(relam))
@ -1082,13 +1043,11 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
/* /*
* initialize the tuple descriptor (relation->rd_att). * initialize the tuple descriptor (relation->rd_att).
*
*/ */
RelationBuildTupleDesc(buildinfo, relation); RelationBuildTupleDesc(buildinfo, relation);
/* /*
* Fetch rules and triggers that affect this relation * Fetch rules and triggers that affect this relation
*
*/ */
if (relation->rd_rel->relhasrules) if (relation->rd_rel->relhasrules)
RelationBuildRuleLock(relation); RelationBuildRuleLock(relation);
@ -1105,14 +1064,12 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
/* /*
* initialize index strategy and support information for this relation * initialize index strategy and support information for this relation
*
*/ */
if (OidIsValid(relam)) if (OidIsValid(relam))
IndexedAccessMethodInitialize(relation); IndexedAccessMethodInitialize(relation);
/* /*
* initialize the relation lock manager information * initialize the relation lock manager information
*
*/ */
RelationInitLockInfo(relation); /* see lmgr.c */ RelationInitLockInfo(relation); /* see lmgr.c */
@ -1144,7 +1101,6 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
/* /*
* insert newly created relation into proper relcaches, restore memory * insert newly created relation into proper relcaches, restore memory
* context and return the new reldesc. * context and return the new reldesc.
*
*/ */
oldcxt = MemoryContextSwitchTo(CacheMemoryContext); oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
RelationCacheInsert(relation); RelationCacheInsert(relation);
@ -1214,11 +1170,14 @@ formrdesc(char *relationName,
* allocate new relation desc * allocate new relation desc
*/ */
relation = (Relation) palloc(sizeof(RelationData)); relation = (Relation) palloc(sizeof(RelationData));
MemSet((char *) relation, 0, sizeof(RelationData));
/* /*
* don't open the unix file yet.. * clear all fields of reldesc
*/ */
MemSet((char *) relation, 0, sizeof(RelationData));
relation->rd_targblock = InvalidBlockNumber;
/* make sure relation is marked as having no open file yet */
relation->rd_fd = -1; relation->rd_fd = -1;
/* /*
@ -1329,7 +1288,6 @@ fixrdesc(char *relationName)
/* /*
* find the tuple in pg_class corresponding to the given relation name * find the tuple in pg_class corresponding to the given relation name
*
*/ */
buildinfo.infotype = INFO_RELNAME; buildinfo.infotype = INFO_RELNAME;
buildinfo.i.info_name = relationName; buildinfo.i.info_name = relationName;
@ -1343,7 +1301,6 @@ fixrdesc(char *relationName)
/* /*
* find the pre-made relcache entry (better be there!) * find the pre-made relcache entry (better be there!)
*
*/ */
relation = RelationNameCacheGetRelation(relationName); relation = RelationNameCacheGetRelation(relationName);
if (!RelationIsValid(relation)) if (!RelationIsValid(relation))
@ -1353,7 +1310,6 @@ fixrdesc(char *relationName)
/* /*
* and copy pg_class_tuple to relation->rd_rel. (See notes in * and copy pg_class_tuple to relation->rd_rel. (See notes in
* AllocateRelationDesc()) * AllocateRelationDesc())
*
*/ */
Assert(relation->rd_rel != NULL); Assert(relation->rd_rel != NULL);
memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE); memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
@ -1378,7 +1334,6 @@ fixrdesc(char *relationName)
* NB: relation ref count is incremented if successful. * NB: relation ref count is incremented if successful.
* Caller should eventually decrement count. (Usually, * Caller should eventually decrement count. (Usually,
* that happens by calling RelationClose().) * that happens by calling RelationClose().)
*
*/ */
Relation Relation
RelationIdCacheGetRelation(Oid relationId) RelationIdCacheGetRelation(Oid relationId)
@ -1403,7 +1358,6 @@ RelationIdCacheGetRelation(Oid relationId)
* RelationNameCacheGetRelation * RelationNameCacheGetRelation
* *
* As above, but lookup by name. * As above, but lookup by name.
*
*/ */
static Relation static Relation
RelationNameCacheGetRelation(const char *relationName) RelationNameCacheGetRelation(const char *relationName)
@ -1457,7 +1411,6 @@ RelationNodeCacheGetRelation(RelFileNode rnode)
* NB: relation ref count is incremented, or set to 1 if new entry. * NB: relation ref count is incremented, or set to 1 if new entry.
* Caller should eventually decrement count. (Usually, * Caller should eventually decrement count. (Usually,
* that happens by calling RelationClose().) * that happens by calling RelationClose().)
*
*/ */
Relation Relation
RelationIdGetRelation(Oid relationId) RelationIdGetRelation(Oid relationId)
@ -1467,14 +1420,12 @@ RelationIdGetRelation(Oid relationId)
/* /*
* increment access statistics * increment access statistics
*
*/ */
IncrHeapAccessStat(local_RelationIdGetRelation); IncrHeapAccessStat(local_RelationIdGetRelation);
IncrHeapAccessStat(global_RelationIdGetRelation); IncrHeapAccessStat(global_RelationIdGetRelation);
/* /*
* first try and get a reldesc from the cache * first try and get a reldesc from the cache
*
*/ */
rd = RelationIdCacheGetRelation(relationId); rd = RelationIdCacheGetRelation(relationId);
if (RelationIsValid(rd)) if (RelationIsValid(rd))
@ -1483,7 +1434,6 @@ RelationIdGetRelation(Oid relationId)
/* /*
* no reldesc in the cache, so have RelationBuildDesc() build one and * no reldesc in the cache, so have RelationBuildDesc() build one and
* add it. * add it.
*
*/ */
buildinfo.infotype = INFO_RELID; buildinfo.infotype = INFO_RELID;
buildinfo.i.info_id = relationId; buildinfo.i.info_id = relationId;
@ -1496,7 +1446,6 @@ RelationIdGetRelation(Oid relationId)
* RelationNameGetRelation * RelationNameGetRelation
* *
* As above, but lookup by name. * As above, but lookup by name.
*
*/ */
Relation Relation
RelationNameGetRelation(const char *relationName) RelationNameGetRelation(const char *relationName)
@ -1507,7 +1456,6 @@ RelationNameGetRelation(const char *relationName)
/* /*
* increment access statistics * increment access statistics
*
*/ */
IncrHeapAccessStat(local_RelationNameGetRelation); IncrHeapAccessStat(local_RelationNameGetRelation);
IncrHeapAccessStat(global_RelationNameGetRelation); IncrHeapAccessStat(global_RelationNameGetRelation);
@ -1515,7 +1463,6 @@ RelationNameGetRelation(const char *relationName)
/* /*
* if caller is looking for a temp relation, substitute its real name; * if caller is looking for a temp relation, substitute its real name;
* we only index temp rels by their real names. * we only index temp rels by their real names.
*
*/ */
temprelname = get_temp_rel_by_username(relationName); temprelname = get_temp_rel_by_username(relationName);
if (temprelname != NULL) if (temprelname != NULL)
@ -1523,7 +1470,6 @@ RelationNameGetRelation(const char *relationName)
/* /*
* first try and get a reldesc from the cache * first try and get a reldesc from the cache
*
*/ */
rd = RelationNameCacheGetRelation(relationName); rd = RelationNameCacheGetRelation(relationName);
if (RelationIsValid(rd)) if (RelationIsValid(rd))
@ -1532,7 +1478,6 @@ RelationNameGetRelation(const char *relationName)
/* /*
* no reldesc in the cache, so have RelationBuildDesc() build one and * no reldesc in the cache, so have RelationBuildDesc() build one and
* add it. * add it.
*
*/ */
buildinfo.infotype = INFO_RELNAME; buildinfo.infotype = INFO_RELNAME;
buildinfo.i.info_name = (char *) relationName; buildinfo.i.info_name = (char *) relationName;
@ -1556,7 +1501,6 @@ RelationNameGetRelation(const char *relationName)
* with aset.c's CLOBBER_FREED_MEMORY option, this provides a good test * with aset.c's CLOBBER_FREED_MEMORY option, this provides a good test
* to catch references to already-released relcache entries. It slows * to catch references to already-released relcache entries. It slows
* things down quite a bit, however. * things down quite a bit, however.
*
*/ */
void void
RelationClose(Relation relation) RelationClose(Relation relation)
@ -1577,7 +1521,6 @@ RelationClose(Relation relation)
* This function is especially for nailed relations. * This function is especially for nailed relations.
* relhasindex/relfilenode could be changed even for * relhasindex/relfilenode could be changed even for
* nailed relations. * nailed relations.
*
*/ */
static void static void
RelationReloadClassinfo(Relation relation) RelationReloadClassinfo(Relation relation)
@ -1616,7 +1559,6 @@ RelationReloadClassinfo(Relation relation)
* usually used when we are notified of a change to an open relation * usually used when we are notified of a change to an open relation
* (one with refcount > 0). However, this routine just does whichever * (one with refcount > 0). However, this routine just does whichever
* it's told to do; callers must determine which they want. * it's told to do; callers must determine which they want.
*
*/ */
static void static void
RelationClearRelation(Relation relation, bool rebuildIt) RelationClearRelation(Relation relation, bool rebuildIt)
@ -1631,7 +1573,10 @@ RelationClearRelation(Relation relation, bool rebuildIt)
* a vacuum truncation. * a vacuum truncation.
*/ */
if (relation->rd_fd >= 0) if (relation->rd_fd >= 0)
{
smgrclose(DEFAULT_SMGR, relation); smgrclose(DEFAULT_SMGR, relation);
relation->rd_fd = -1;
}
/* /*
* Never, never ever blow away a nailed-in system relation, because * Never, never ever blow away a nailed-in system relation, because
@ -1702,13 +1647,13 @@ RelationClearRelation(Relation relation, bool rebuildIt)
* we save/restore rd_nblocks (in case it is a local relation) * we save/restore rd_nblocks (in case it is a local relation)
* *and* call RelationGetNumberOfBlocks (in case it isn't). * *and* call RelationGetNumberOfBlocks (in case it isn't).
*/ */
uint16 old_refcnt = relation->rd_refcnt; int old_refcnt = relation->rd_refcnt;
bool old_myxactonly = relation->rd_myxactonly; bool old_myxactonly = relation->rd_myxactonly;
TupleDesc old_att = relation->rd_att; TupleDesc old_att = relation->rd_att;
RuleLock *old_rules = relation->rd_rules; RuleLock *old_rules = relation->rd_rules;
MemoryContext old_rulescxt = relation->rd_rulescxt; MemoryContext old_rulescxt = relation->rd_rulescxt;
TriggerDesc *old_trigdesc = relation->trigdesc; TriggerDesc *old_trigdesc = relation->trigdesc;
int old_nblocks = relation->rd_nblocks; BlockNumber old_nblocks = relation->rd_nblocks;
RelationBuildDescInfo buildinfo; RelationBuildDescInfo buildinfo;
buildinfo.infotype = INFO_RELID; buildinfo.infotype = INFO_RELID;
@ -1767,7 +1712,6 @@ RelationClearRelation(Relation relation, bool rebuildIt)
* RelationFlushRelation * RelationFlushRelation
* *
* Rebuild the relation if it is open (refcount > 0), else blow it away. * Rebuild the relation if it is open (refcount > 0), else blow it away.
*
*/ */
static void static void
RelationFlushRelation(Relation relation) RelationFlushRelation(Relation relation)
@ -1801,7 +1745,6 @@ RelationFlushRelation(Relation relation)
* RelationClearRelation + if the relation is myxactonly then * RelationClearRelation + if the relation is myxactonly then
* remove the relation descriptor from the newly created * remove the relation descriptor from the newly created
* relation list. * relation list.
*
*/ */
void void
RelationForgetRelation(Oid rid) RelationForgetRelation(Oid rid)
@ -1851,7 +1794,6 @@ RelationForgetRelation(Oid rid)
* safer to process them, so that our *own* SI update messages will * safer to process them, so that our *own* SI update messages will
* have the same effects during CommandCounterIncrement for both * have the same effects during CommandCounterIncrement for both
* local and nonlocal relations. * local and nonlocal relations.
*
*/ */
void void
RelationIdInvalidateRelationCacheByRelationId(Oid relationId) RelationIdInvalidateRelationCacheByRelationId(Oid relationId)
@ -1989,7 +1931,6 @@ RelationCacheAbortWalker(Relation *relationPtr, Datum dummy)
* RelationRegisterRelation - * RelationRegisterRelation -
* register the Relation descriptor of a newly created relation * register the Relation descriptor of a newly created relation
* with the relation descriptor Cache. * with the relation descriptor Cache.
*
*/ */
void void
RelationRegisterRelation(Relation relation) RelationRegisterRelation(Relation relation)
@ -2048,7 +1989,6 @@ RelationPurgeLocalRelation(bool xactCommitted)
* RelationCacheInitialize * RelationCacheInitialize
* *
* This initializes the relation descriptor cache. * This initializes the relation descriptor cache.
*
*/ */
#define INITRELCACHESIZE 400 #define INITRELCACHESIZE 400
@ -2061,7 +2001,6 @@ RelationCacheInitialize(void)
/* /*
* switch to cache memory context * switch to cache memory context
*
*/ */
if (!CacheMemoryContext) if (!CacheMemoryContext)
CreateCacheMemoryContext(); CreateCacheMemoryContext();
@ -2070,7 +2009,6 @@ RelationCacheInitialize(void)
/* /*
* create global caches * create global caches
*
*/ */
MemSet(&ctl, 0, (int) sizeof(ctl)); MemSet(&ctl, 0, (int) sizeof(ctl));
ctl.keysize = sizeof(NameData); ctl.keysize = sizeof(NameData);
@ -2093,7 +2031,6 @@ RelationCacheInitialize(void)
* be in the cache. * be in the cache.
* *
* NB: see also the list in RelationCacheInitializePhase2(). * NB: see also the list in RelationCacheInitializePhase2().
*
*/ */
formrdesc(RelationRelationName, Natts_pg_class, Desc_pg_class); formrdesc(RelationRelationName, Natts_pg_class, Desc_pg_class);
formrdesc(AttributeRelationName, Natts_pg_attribute, Desc_pg_attribute); formrdesc(AttributeRelationName, Natts_pg_attribute, Desc_pg_attribute);
@ -2115,7 +2052,6 @@ RelationCacheInitialize(void)
* *
* This completes initialization of the relcache after catcache * This completes initialization of the relcache after catcache
* is functional and we are able to actually load data from pg_class. * is functional and we are able to actually load data from pg_class.
*
*/ */
void void
RelationCacheInitializePhase2(void) RelationCacheInitializePhase2(void)
@ -2658,7 +2594,8 @@ init_irels(void)
return; return;
} }
/* the file descriptor is not yet opened */ /* reset transient fields */
ird->rd_targblock = InvalidBlockNumber;
ird->rd_fd = -1; ird->rd_fd = -1;
ird->rd_node.tblNode = MyDatabaseId; ird->rd_node.tblNode = MyDatabaseId;

View File

@ -4,7 +4,7 @@
* Support for grand unified configuration scheme, including SET * Support for grand unified configuration scheme, including SET
* command, configuration file, and command line options. * command, configuration file, and command line options.
* *
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.42 2001/06/23 22:23:49 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.43 2001/06/27 23:31:39 tgl Exp $
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
@ -31,6 +31,8 @@
#include "optimizer/paths.h" #include "optimizer/paths.h"
#include "optimizer/planmain.h" #include "optimizer/planmain.h"
#include "parser/parse_expr.h" #include "parser/parse_expr.h"
#include "storage/freespace.h"
#include "storage/lock.h"
#include "storage/proc.h" #include "storage/proc.h"
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
#include "utils/datetime.h" #include "utils/datetime.h"
@ -270,11 +272,16 @@ static struct config_int
*/ */
{"max_connections", PGC_POSTMASTER, &MaxBackends, {"max_connections", PGC_POSTMASTER, &MaxBackends,
DEF_MAXBACKENDS, 1, MAXBACKENDS, NULL, NULL}, DEF_MAXBACKENDS, 1, MAXBACKENDS, NULL, NULL},
{"shared_buffers", PGC_POSTMASTER, &NBuffers, {"shared_buffers", PGC_POSTMASTER, &NBuffers,
DEF_NBUFFERS, 16, INT_MAX, NULL, NULL}, DEF_NBUFFERS, 16, INT_MAX, NULL, NULL},
{"port", PGC_POSTMASTER, &PostPortNumber, {"port", PGC_POSTMASTER, &PostPortNumber,
DEF_PGPORT, 1, 65535, NULL, NULL}, DEF_PGPORT, 1, 65535, NULL, NULL},
{"unix_socket_permissions", PGC_POSTMASTER, &Unix_socket_permissions,
0777, 0000, 0777, NULL, NULL},
{"sort_mem", PGC_USERSET, &SortMem, {"sort_mem", PGC_USERSET, &SortMem,
512, 4*BLCKSZ/1024, INT_MAX, NULL, NULL}, 512, 4*BLCKSZ/1024, INT_MAX, NULL, NULL},
@ -290,8 +297,13 @@ static struct config_int
{"max_expr_depth", PGC_USERSET, &max_expr_depth, {"max_expr_depth", PGC_USERSET, &max_expr_depth,
DEFAULT_MAX_EXPR_DEPTH, 10, INT_MAX, NULL, NULL}, DEFAULT_MAX_EXPR_DEPTH, 10, INT_MAX, NULL, NULL},
{"unix_socket_permissions", PGC_POSTMASTER, &Unix_socket_permissions, {"max_fsm_relations", PGC_POSTMASTER, &MaxFSMRelations,
0777, 0000, 0777, NULL, NULL}, 100, 10, INT_MAX, NULL, NULL},
{"max_fsm_pages", PGC_POSTMASTER, &MaxFSMPages,
10000, 1000, INT_MAX, NULL, NULL},
{"max_locks_per_xact", PGC_POSTMASTER, &max_locks_per_xact,
64, 10, INT_MAX, NULL, NULL},
{"checkpoint_segments", PGC_SIGHUP, &CheckPointSegments, {"checkpoint_segments", PGC_SIGHUP, &CheckPointSegments,
3, 1, INT_MAX, NULL, NULL}, 3, 1, INT_MAX, NULL, NULL},

View File

@ -44,11 +44,19 @@
#krb_server_keyfile = '' #krb_server_keyfile = ''
#
# Shared Memory Size
#
#shared_buffers = 64 # 2*max_connections, min 16
#max_fsm_relations = 100 # min 10
#max_fsm_pages = 10000 # min 1000
#max_locks_per_xact = 64 # min 10
#wal_buffers = 8 # min 4
# #
# Performance # Performance
# #
#sort_mem = 512 #sort_mem = 512
#shared_buffers = 64 # 2*max_connections, min 16
#fsync = true #fsync = true
@ -78,7 +86,7 @@
# GEQO Optimizer Parameters # GEQO Optimizer Parameters
# #
#geqo_threshold = 11 #geqo_threshold = 11
#geqo_pool_size = 0 #default based in tables, range 128-1024 #geqo_pool_size = 0 #default based on #tables in query, range 128-1024
#geqo_effort = 1 #geqo_effort = 1
#geqo_generations = 0 #geqo_generations = 0
#geqo_random_seed = -1 # auto-compute seed #geqo_random_seed = -1 # auto-compute seed
@ -87,7 +95,6 @@
# #
# Write-ahead log (WAL) # Write-ahead log (WAL)
# #
#wal_buffers = 8 # min 4
#wal_files = 0 # range 0-64 #wal_files = 0 # range 0-64
#wal_sync_method = fsync # fsync or fdatasync or open_sync or open_datasync #wal_sync_method = fsync # fsync or fdatasync or open_sync or open_datasync
# Note: default wal_sync_method varies across platforms # Note: default wal_sync_method varies across platforms

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: vacuum.h,v 1.35 2001/05/07 00:43:25 tgl Exp $ * $Id: vacuum.h,v 1.36 2001/06/27 23:31:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -15,11 +15,14 @@
#define VACUUM_H #define VACUUM_H
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "storage/block.h"
/* in commands/vacuum.c */ /* in commands/vacuum.c */
extern void vacuum(VacuumStmt *vacstmt); extern void vacuum(VacuumStmt *vacstmt);
extern void vac_update_relstats(Oid relid, long num_pages, double num_tuples, extern void vac_update_relstats(Oid relid,
BlockNumber num_pages,
double num_tuples,
bool hasindex); bool hasindex);
/* in commands/analyze.c */ /* in commands/analyze.c */
extern void analyze_rel(Oid relid, VacuumStmt *vacstmt); extern void analyze_rel(Oid relid, VacuumStmt *vacstmt);

View File

@ -0,0 +1,53 @@
/*-------------------------------------------------------------------------
*
* freespace.h
* POSTGRES free space map for quickly finding free space in relations
*
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: freespace.h,v 1.1 2001/06/27 23:31:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef FREESPACE_H_
#define FREESPACE_H_
#include "storage/block.h"
#include "storage/relfilenode.h"
#include "storage/spin.h"
extern SPINLOCK FreeSpaceLock;
extern int MaxFSMRelations;
extern int MaxFSMPages;
/*
* function prototypes
*/
extern void InitFreeSpaceMap(void);
extern int FreeSpaceShmemSize(void);
extern BlockNumber GetPageWithFreeSpace(RelFileNode *rel, Size spaceNeeded);
extern void RecordFreeSpace(RelFileNode *rel, BlockNumber page,
Size spaceAvail);
extern BlockNumber RecordAndGetPageWithFreeSpace(RelFileNode *rel,
BlockNumber oldPage,
Size oldSpaceAvail,
Size spaceNeeded);
extern void MultiRecordFreeSpace(RelFileNode *rel,
BlockNumber minPage,
BlockNumber maxPage,
int nPages,
BlockNumber *pages,
Size *spaceAvail);
extern void FreeSpaceMapForgetRel(RelFileNode *rel);
#ifdef FREESPACE_DEBUG
extern void DumpFreeSpace(void);
#endif
#endif /* FREESPACE_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: ipc.h,v 1.49 2001/03/22 04:01:05 momjian Exp $ * $Id: ipc.h,v 1.50 2001/06/27 23:31:39 tgl Exp $
* *
* Some files that would normally need to include only sys/ipc.h must * Some files that would normally need to include only sys/ipc.h must
* instead include this file because on Ultrix, sys/ipc.h is not designed * instead include this file because on Ultrix, sys/ipc.h is not designed
@ -74,6 +74,7 @@ typedef enum _LockId_
LOCKMGRLOCKID, LOCKMGRLOCKID,
SINVALLOCKID, SINVALLOCKID,
PROCSTRUCTLOCKID, PROCSTRUCTLOCKID,
FREESPACELOCKID,
#ifdef STABLE_MEMORY_STORAGE #ifdef STABLE_MEMORY_STORAGE
MMCACHELOCKID, MMCACHELOCKID,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: lock.h,v 1.49 2001/06/22 00:04:59 tgl Exp $ * $Id: lock.h,v 1.50 2001/06/27 23:31:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -32,6 +32,8 @@ typedef struct proc PROC;
extern SPINLOCK LockMgrLock; extern SPINLOCK LockMgrLock;
extern int max_locks_per_xact;
#ifdef LOCK_DEBUG #ifdef LOCK_DEBUG
extern int Trace_lock_oidmin; extern int Trace_lock_oidmin;
extern bool Trace_locks; extern bool Trace_locks;
@ -41,19 +43,6 @@ extern bool Debug_deadlocks;
#endif /* LOCK_DEBUG */ #endif /* LOCK_DEBUG */
/* ----------------------
* The following defines are used to estimate how much shared
* memory the lock manager is going to require.
* See LockShmemSize() in lock.c.
*
* NLOCKS_PER_XACT - The number of unique objects locked in a transaction
* (this should be configurable!)
* NLOCKENTS - The maximum number of lock entries in the lock table.
* ----------------------
*/
#define NLOCKS_PER_XACT 64
#define NLOCKENTS(maxBackends) (NLOCKS_PER_XACT*(maxBackends))
typedef int LOCKMASK; typedef int LOCKMASK;
typedef int LOCKMODE; typedef int LOCKMODE;

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: smgr.h,v 1.29 2001/05/10 20:38:49 tgl Exp $ * $Id: smgr.h,v 1.30 2001/06/27 23:31:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -43,8 +43,9 @@ extern int smgrblindwrt(int16 which, RelFileNode rnode,
extern int smgrblindmarkdirty(int16 which, RelFileNode rnode, extern int smgrblindmarkdirty(int16 which, RelFileNode rnode,
BlockNumber blkno); BlockNumber blkno);
extern int smgrmarkdirty(int16 which, Relation reln, BlockNumber blkno); extern int smgrmarkdirty(int16 which, Relation reln, BlockNumber blkno);
extern int smgrnblocks(int16 which, Relation reln); extern BlockNumber smgrnblocks(int16 which, Relation reln);
extern int smgrtruncate(int16 which, Relation reln, int nblocks); extern BlockNumber smgrtruncate(int16 which, Relation reln,
BlockNumber nblocks);
extern int smgrDoPendingDeletes(bool isCommit); extern int smgrDoPendingDeletes(bool isCommit);
extern int smgrcommit(void); extern int smgrcommit(void);
extern int smgrabort(void); extern int smgrabort(void);
@ -71,8 +72,8 @@ extern int mdmarkdirty(Relation reln, BlockNumber blkno);
extern int mdblindwrt(RelFileNode rnode, BlockNumber blkno, extern int mdblindwrt(RelFileNode rnode, BlockNumber blkno,
char *buffer, bool dofsync); char *buffer, bool dofsync);
extern int mdblindmarkdirty(RelFileNode rnode, BlockNumber blkno); extern int mdblindmarkdirty(RelFileNode rnode, BlockNumber blkno);
extern int mdnblocks(Relation reln); extern BlockNumber mdnblocks(Relation reln);
extern int mdtruncate(Relation reln, int nblocks); extern BlockNumber mdtruncate(Relation reln, BlockNumber nblocks);
extern int mdcommit(void); extern int mdcommit(void);
extern int mdabort(void); extern int mdabort(void);
extern int mdsync(void); extern int mdsync(void);
@ -95,8 +96,8 @@ extern int mmblindwrt(char *dbname, char *relname, Oid dbid, Oid relid,
extern int mmmarkdirty(Relation reln, BlockNumber blkno); extern int mmmarkdirty(Relation reln, BlockNumber blkno);
extern int mmblindmarkdirty(char *dbname, char *relname, Oid dbid, Oid relid, extern int mmblindmarkdirty(char *dbname, char *relname, Oid dbid, Oid relid,
BlockNumber blkno); BlockNumber blkno);
extern int mmnblocks(Relation reln); extern BlockNumber mmnblocks(Relation reln);
extern int mmtruncate(Relation reln, int nblocks); extern BlockNumber mmtruncate(Relation reln, BlockNumber nblocks);
extern int mmcommit(void); extern int mmcommit(void);
extern int mmabort(void); extern int mmabort(void);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: rel.h,v 1.50 2001/06/22 19:16:24 wieck Exp $ * $Id: rel.h,v 1.51 2001/06/27 23:31:40 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -19,8 +19,9 @@
#include "catalog/pg_am.h" #include "catalog/pg_am.h"
#include "catalog/pg_class.h" #include "catalog/pg_class.h"
#include "rewrite/prs2lock.h" #include "rewrite/prs2lock.h"
#include "storage/relfilenode.h" #include "storage/block.h"
#include "storage/fd.h" #include "storage/fd.h"
#include "storage/relfilenode.h"
/* added to prevent circular dependency. bjm 1999/11/15 */ /* added to prevent circular dependency. bjm 1999/11/15 */
extern char *get_temp_rel_by_physicalname(const char *relname); extern char *get_temp_rel_by_physicalname(const char *relname);
@ -105,9 +106,11 @@ typedef struct PgStat_Info
typedef struct RelationData typedef struct RelationData
{ {
File rd_fd; /* open file descriptor, or -1 if none */ File rd_fd; /* open file descriptor, or -1 if none */
RelFileNode rd_node; /* relation file node */ RelFileNode rd_node; /* file node (physical identifier) */
int rd_nblocks; /* number of blocks in rel */ BlockNumber rd_nblocks; /* number of blocks in rel */
uint16 rd_refcnt; /* reference count */ BlockNumber rd_targblock; /* current insertion target block,
* or InvalidBlockNumber */
int rd_refcnt; /* reference count */
bool rd_myxactonly; /* rel uses the local buffer mgr */ bool rd_myxactonly; /* rel uses the local buffer mgr */
bool rd_isnailed; /* rel is nailed in cache */ bool rd_isnailed; /* rel is nailed in cache */
bool rd_indexfound; /* true if rd_indexlist is valid */ bool rd_indexfound; /* true if rd_indexlist is valid */