Commit 4af34211 authored by Tom Lane's avatar Tom Lane

Get rid of rd_nblocks field in relcache entries. Turns out this was

costing us lots more to maintain than it was worth.  On shared tables
it was of exactly zero benefit because we couldn't trust it to be
up to date.  On temp tables it sometimes saved an lseek, but not often
enough to be worth getting excited about.  And the real problem was that
we forced an lseek on every relcache flush in order to update the field.
So all in all it seems best to lose the complexity.
parent 1fe11fad
/* /*
* $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.14 2004/04/01 21:28:43 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.15 2004/05/08 19:09:24 tgl Exp $
* *
* Copyright (c) 2001,2002 Tatsuo Ishii * Copyright (c) 2001,2002 Tatsuo Ishii
* *
...@@ -127,9 +127,10 @@ pgstattuple_real(Relation rel) ...@@ -127,9 +127,10 @@ pgstattuple_real(Relation rel)
*/ */
attinmeta = TupleDescGetAttInMetadata(tupdesc); attinmeta = TupleDescGetAttInMetadata(tupdesc);
nblocks = RelationGetNumberOfBlocks(rel);
scan = heap_beginscan(rel, SnapshotAny, 0, NULL); scan = heap_beginscan(rel, SnapshotAny, 0, NULL);
nblocks = scan->rs_nblocks; /* # blocks to be scanned */
/* scan the relation */ /* scan the relation */
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.165 2004/04/21 18:24:23 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.166 2004/05/08 19:09:24 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -73,12 +73,13 @@ static void ...@@ -73,12 +73,13 @@ static void
initscan(HeapScanDesc scan, ScanKey key) initscan(HeapScanDesc scan, ScanKey key)
{ {
/* /*
* Make sure we have up-to-date idea of number of blocks in relation. * Determine the number of blocks we have to scan.
*
* It is sufficient to do this once at scan start, since any tuples * It is sufficient to do this once at scan start, since any tuples
* added while the scan is in progress will be invisible to my * added while the scan is in progress will be invisible to my
* transaction anyway... * transaction anyway...
*/ */
scan->rs_rd->rd_nblocks = RelationGetNumberOfBlocks(scan->rs_rd); scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_rd);
scan->rs_ctup.t_datamcxt = NULL; scan->rs_ctup.t_datamcxt = NULL;
scan->rs_ctup.t_data = NULL; scan->rs_ctup.t_data = NULL;
...@@ -113,12 +114,12 @@ heapgettup(Relation relation, ...@@ -113,12 +114,12 @@ heapgettup(Relation relation,
Buffer *buffer, Buffer *buffer,
Snapshot snapshot, Snapshot snapshot,
int nkeys, int nkeys,
ScanKey key) ScanKey key,
BlockNumber pages)
{ {
ItemId lpp; ItemId lpp;
Page dp; Page dp;
BlockNumber page; BlockNumber page;
BlockNumber pages;
int lines; int lines;
OffsetNumber lineoff; OffsetNumber lineoff;
int linesleft; int linesleft;
...@@ -159,7 +160,7 @@ heapgettup(Relation relation, ...@@ -159,7 +160,7 @@ heapgettup(Relation relation,
/* /*
* return null immediately if relation is empty * return null immediately if relation is empty
*/ */
if ((pages = relation->rd_nblocks) == 0) if (pages == 0)
{ {
if (BufferIsValid(*buffer)) if (BufferIsValid(*buffer))
ReleaseBuffer(*buffer); ReleaseBuffer(*buffer);
...@@ -832,7 +833,8 @@ heap_getnext(HeapScanDesc scan, ScanDirection direction) ...@@ -832,7 +833,8 @@ heap_getnext(HeapScanDesc scan, ScanDirection direction)
&(scan->rs_cbuf), &(scan->rs_cbuf),
scan->rs_snapshot, scan->rs_snapshot,
scan->rs_nkeys, scan->rs_nkeys,
scan->rs_key); scan->rs_key,
scan->rs_nblocks);
if (scan->rs_ctup.t_data == NULL && !BufferIsValid(scan->rs_cbuf)) if (scan->rs_ctup.t_data == NULL && !BufferIsValid(scan->rs_cbuf))
{ {
...@@ -1992,7 +1994,8 @@ heap_restrpos(HeapScanDesc scan) ...@@ -1992,7 +1994,8 @@ heap_restrpos(HeapScanDesc scan)
&(scan->rs_cbuf), &(scan->rs_cbuf),
scan->rs_snapshot, scan->rs_snapshot,
0, 0,
NULL); NULL,
scan->rs_nblocks);
} }
} }
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.114 2004/04/21 18:24:26 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.115 2004/05/08 19:09:24 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -802,12 +802,7 @@ btvacuumcleanup(PG_FUNCTION_ARGS) ...@@ -802,12 +802,7 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
/* /*
* Do the physical truncation. * Do the physical truncation.
*/ */
if (rel->rd_smgr == NULL) RelationTruncate(rel, new_pages);
rel->rd_smgr = smgropen(rel->rd_node);
new_pages = smgrtruncate(rel->rd_smgr, new_pages);
rel->rd_nblocks = new_pages; /* update relcache
* immediately */
rel->rd_targblock = InvalidBlockNumber;
num_pages = new_pages; num_pages = new_pages;
} }
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.263 2004/05/05 04:48:45 tgl Exp $ * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.264 2004/05/08 19:09:24 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -1979,12 +1979,8 @@ RelationTruncateIndexes(Oid heapId) ...@@ -1979,12 +1979,8 @@ RelationTruncateIndexes(Oid heapId)
*/ */
DropRelationBuffers(currentIndex); DropRelationBuffers(currentIndex);
/* Now truncate the actual data and set blocks to zero */ /* Now truncate the actual data */
if (currentIndex->rd_smgr == NULL) RelationTruncate(currentIndex, 0);
currentIndex->rd_smgr = smgropen(currentIndex->rd_node);
smgrtruncate(currentIndex->rd_smgr, 0);
currentIndex->rd_nblocks = 0;
currentIndex->rd_targblock = InvalidBlockNumber;
/* Initialize the index and rebuild */ /* Initialize the index and rebuild */
index_build(heapRelation, currentIndex, indexInfo); index_build(heapRelation, currentIndex, indexInfo);
...@@ -2028,12 +2024,8 @@ heap_truncate(Oid rid) ...@@ -2028,12 +2024,8 @@ heap_truncate(Oid rid)
*/ */
DropRelationBuffers(rel); DropRelationBuffers(rel);
/* Now truncate the actual data and set blocks to zero */ /* Now truncate the actual data */
if (rel->rd_smgr == NULL) RelationTruncate(rel, 0);
rel->rd_smgr = smgropen(rel->rd_node);
smgrtruncate(rel->rd_smgr, 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);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.230 2004/05/08 00:34:49 tgl Exp $ * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.231 2004/05/08 19:09:24 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -1702,12 +1702,8 @@ reindex_index(Oid indexId) ...@@ -1702,12 +1702,8 @@ reindex_index(Oid indexId)
*/ */
DropRelationBuffers(iRel); DropRelationBuffers(iRel);
/* Now truncate the actual data and set blocks to zero */ /* Now truncate the actual data */
if (iRel->rd_smgr == NULL) RelationTruncate(iRel, 0);
iRel->rd_smgr = smgropen(iRel->rd_node);
smgrtruncate(iRel->rd_smgr, 0);
iRel->rd_nblocks = 0;
iRel->rd_targblock = InvalidBlockNumber;
} }
else else
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.70 2004/02/15 21:01:39 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.71 2004/05/08 19:09:24 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -388,7 +388,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -388,7 +388,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
/* /*
* If we are running a standalone ANALYZE, update pages/tuples stats * If we are running a standalone ANALYZE, update pages/tuples stats
* in pg_class. We have the accurate page count from heap_beginscan, * in pg_class. We know the accurate page count from the smgr,
* but only an approximate number of tuples; therefore, if we are part * but only an approximate number of tuples; therefore, if we are part
* of VACUUM ANALYZE do *not* overwrite the accurate count already * of VACUUM ANALYZE do *not* overwrite the accurate count already
* inserted by VACUUM. The same consideration applies to indexes. * inserted by VACUUM. The same consideration applies to indexes.
...@@ -396,7 +396,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -396,7 +396,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
if (!vacstmt->vacuum) if (!vacstmt->vacuum)
{ {
vac_update_relstats(RelationGetRelid(onerel), vac_update_relstats(RelationGetRelid(onerel),
onerel->rd_nblocks, RelationGetNumberOfBlocks(onerel),
totalrows, totalrows,
hasindex); hasindex);
for (ind = 0; ind < nindexes; ind++) for (ind = 0; ind < nindexes; ind++)
...@@ -657,6 +657,7 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows, ...@@ -657,6 +657,7 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
{ {
int numrows = 0; int numrows = 0;
HeapScanDesc scan; HeapScanDesc scan;
BlockNumber totalblocks;
HeapTuple tuple; HeapTuple tuple;
ItemPointer lasttuple; ItemPointer lasttuple;
BlockNumber lastblock, BlockNumber lastblock,
...@@ -673,6 +674,7 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows, ...@@ -673,6 +674,7 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
* Do a simple linear scan until we reach the target number of rows. * Do a simple linear scan until we reach the target number of rows.
*/ */
scan = heap_beginscan(onerel, SnapshotNow, 0, NULL); scan = heap_beginscan(onerel, SnapshotNow, 0, NULL);
totalblocks = scan->rs_nblocks; /* grab current relation size */
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{ {
rows[numrows++] = heap_copytuple(tuple); rows[numrows++] = heap_copytuple(tuple);
...@@ -693,7 +695,7 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows, ...@@ -693,7 +695,7 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
ereport(elevel, ereport(elevel,
(errmsg("\"%s\": %u pages, %d rows sampled, %.0f estimated total rows", (errmsg("\"%s\": %u pages, %d rows sampled, %.0f estimated total rows",
RelationGetRelationName(onerel), RelationGetRelationName(onerel),
onerel->rd_nblocks, numrows, *totalrows))); totalblocks, numrows, *totalrows)));
return numrows; return numrows;
} }
...@@ -772,10 +774,9 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows, ...@@ -772,10 +774,9 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
pageloop:; pageloop:;
/* /*
* Have we fallen off the end of the relation? (We rely on * Have we fallen off the end of the relation?
* heap_beginscan to have updated rd_nblocks.)
*/ */
if (targblock >= onerel->rd_nblocks) if (targblock >= totalblocks)
break; break;
/* /*
...@@ -841,7 +842,7 @@ pageloop:; ...@@ -841,7 +842,7 @@ pageloop:;
/* /*
* Estimate total number of valid rows in relation. * Estimate total number of valid rows in relation.
*/ */
*totalrows = floor((double) onerel->rd_nblocks * tuplesperpage + 0.5); *totalrows = floor((double) totalblocks * tuplesperpage + 0.5);
/* /*
* Emit some interesting relation info * Emit some interesting relation info
...@@ -849,7 +850,7 @@ pageloop:; ...@@ -849,7 +850,7 @@ pageloop:;
ereport(elevel, ereport(elevel,
(errmsg("\"%s\": %u pages, %d rows sampled, %.0f estimated total rows", (errmsg("\"%s\": %u pages, %d rows sampled, %.0f estimated total rows",
RelationGetRelationName(onerel), RelationGetRelationName(onerel),
onerel->rd_nblocks, numrows, *totalrows))); totalblocks, numrows, *totalrows)));
return numrows; return numrows;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.109 2004/04/06 16:39:30 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.110 2004/05/08 19:09:24 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -822,10 +822,6 @@ read_info(SeqTable elm, Relation rel, Buffer *buf) ...@@ -822,10 +822,6 @@ read_info(SeqTable elm, Relation rel, Buffer *buf)
sequence_magic *sm; sequence_magic *sm;
Form_pg_sequence seq; Form_pg_sequence seq;
if (rel->rd_nblocks > 1)
elog(ERROR, "invalid number of blocks in sequence \"%s\"",
RelationGetRelationName(rel));
*buf = ReadBuffer(rel, 0); *buf = ReadBuffer(rel, 0);
if (!BufferIsValid(*buf)) if (!BufferIsValid(*buf))
elog(ERROR, "ReadBuffer failed"); elog(ERROR, "ReadBuffer failed");
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.274 2004/02/12 05:39:55 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.275 2004/05/08 19:09:24 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2522,11 +2522,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, ...@@ -2522,11 +2522,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
/* truncate relation, if needed */ /* truncate relation, if needed */
if (blkno < nblocks) if (blkno < nblocks)
{ {
if (onerel->rd_smgr == NULL) RelationTruncate(onerel, blkno);
onerel->rd_smgr = smgropen(onerel->rd_node);
blkno = smgrtruncate(onerel->rd_smgr, blkno);
onerel->rd_nblocks = blkno; /* update relcache immediately */
onerel->rd_targblock = InvalidBlockNumber;
vacrelstats->rel_pages = blkno; /* set new number of blocks */ vacrelstats->rel_pages = blkno; /* set new number of blocks */
} }
...@@ -2594,11 +2590,7 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages) ...@@ -2594,11 +2590,7 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
(errmsg("\"%s\": truncated %u to %u pages", (errmsg("\"%s\": truncated %u to %u pages",
RelationGetRelationName(onerel), RelationGetRelationName(onerel),
vacrelstats->rel_pages, relblocks))); vacrelstats->rel_pages, relblocks)));
if (onerel->rd_smgr == NULL) RelationTruncate(onerel, relblocks);
onerel->rd_smgr = smgropen(onerel->rd_node);
relblocks = smgrtruncate(onerel->rd_smgr, relblocks);
onerel->rd_nblocks = relblocks; /* update relcache immediately */
onerel->rd_targblock = InvalidBlockNumber;
vacrelstats->rel_pages = relblocks; /* set new number of vacrelstats->rel_pages = relblocks; /* set new number of
* blocks */ * blocks */
} }
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.39 2004/04/25 23:50:54 neilc Exp $ * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.40 2004/05/08 19:09:25 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -738,11 +738,7 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats) ...@@ -738,11 +738,7 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats)
/* /*
* Do the physical truncation. * Do the physical truncation.
*/ */
if (onerel->rd_smgr == NULL) RelationTruncate(onerel, new_rel_pages);
onerel->rd_smgr = smgropen(onerel->rd_node);
new_rel_pages = smgrtruncate(onerel->rd_smgr, new_rel_pages);
onerel->rd_nblocks = new_rel_pages; /* update relcache immediately */
onerel->rd_targblock = InvalidBlockNumber;
vacrelstats->rel_pages = new_rel_pages; /* save new number of vacrelstats->rel_pages = new_rel_pages; /* save new number of
* blocks */ * blocks */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.164 2004/04/25 23:50:54 neilc Exp $ * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.165 2004/05/08 19:09:25 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -98,8 +98,6 @@ static void write_buffer(Buffer buffer, bool unpin); ...@@ -98,8 +98,6 @@ static void write_buffer(Buffer buffer, bool unpin);
* *
* Assume when this function is called, that reln has been * Assume when this function is called, that reln has been
* opened already. * opened already.
*
* Note: a side effect of a P_NEW call is to update reln->rd_nblocks.
*/ */
Buffer Buffer
ReadBuffer(Relation reln, BlockNumber blockNum) ReadBuffer(Relation reln, BlockNumber blockNum)
...@@ -129,14 +127,14 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum, ...@@ -129,14 +127,14 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
if (reln->rd_smgr == NULL) if (reln->rd_smgr == NULL)
reln->rd_smgr = smgropen(reln->rd_node); reln->rd_smgr = smgropen(reln->rd_node);
/* Substitute proper block number if caller asked for P_NEW */
if (isExtend)
blockNum = smgrnblocks(reln->rd_smgr);
if (isLocalBuf) if (isLocalBuf)
{ {
ReadLocalBufferCount++; ReadLocalBufferCount++;
pgstat_count_buffer_read(&reln->pgstat_info, reln); pgstat_count_buffer_read(&reln->pgstat_info, reln);
/* Substitute proper block number if caller asked for P_NEW */
if (isExtend)
blockNum = reln->rd_nblocks;
bufHdr = LocalBufferAlloc(reln, blockNum, &found); bufHdr = LocalBufferAlloc(reln, blockNum, &found);
if (found) if (found)
LocalBufferHitCount++; LocalBufferHitCount++;
...@@ -145,13 +143,6 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum, ...@@ -145,13 +143,6 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
{ {
ReadBufferCount++; ReadBufferCount++;
pgstat_count_buffer_read(&reln->pgstat_info, reln); pgstat_count_buffer_read(&reln->pgstat_info, reln);
/* Substitute proper block number if caller asked for P_NEW */
if (isExtend)
{
/* must be sure we have accurate file length! */
blockNum = reln->rd_nblocks = smgrnblocks(reln->rd_smgr);
}
/* /*
* lookup the buffer. IO_IN_PROGRESS is set if the requested * lookup the buffer. IO_IN_PROGRESS is set if the requested
* block is not currently in memory. * block is not currently in memory.
...@@ -196,8 +187,6 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum, ...@@ -196,8 +187,6 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
/* new buffers are zero-filled */ /* new buffers are zero-filled */
MemSet((char *) MAKE_PTR(bufHdr->data), 0, BLCKSZ); MemSet((char *) MAKE_PTR(bufHdr->data), 0, BLCKSZ);
smgrextend(reln->rd_smgr, blockNum, (char *) MAKE_PTR(bufHdr->data)); smgrextend(reln->rd_smgr, blockNum, (char *) MAKE_PTR(bufHdr->data));
/* After successful extend, increment relation length */
reln->rd_nblocks++;
} }
else else
{ {
...@@ -1085,55 +1074,36 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln) ...@@ -1085,55 +1074,36 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln)
/* /*
* RelationGetNumberOfBlocks * RelationGetNumberOfBlocks
* Determines the current number of pages in the relation. * Determines the current number of pages in the relation.
* Side effect: relation->rd_nblocks is updated.
*/ */
BlockNumber BlockNumber
RelationGetNumberOfBlocks(Relation relation) RelationGetNumberOfBlocks(Relation relation)
{ {
/* /* Open it at the smgr level if not already done */
* relation->rd_nblocks should be accurate already if the relation is if (relation->rd_smgr == NULL)
* new or temp, because no one else should be modifying it. Otherwise relation->rd_smgr = smgropen(relation->rd_node);
* we need to ask the smgr for the current physical file length.
*
* Don't call smgr on a view or a composite type, either.
*/
if (relation->rd_rel->relkind == RELKIND_VIEW ||
relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
relation->rd_nblocks = 0;
else if (!relation->rd_isnew && !relation->rd_istemp)
{
/* Open it at the smgr level if not already done */
if (relation->rd_smgr == NULL)
relation->rd_smgr = smgropen(relation->rd_node);
relation->rd_nblocks = smgrnblocks(relation->rd_smgr);
}
return relation->rd_nblocks; return smgrnblocks(relation->rd_smgr);
} }
/* /*
* RelationUpdateNumberOfBlocks * RelationTruncate
* Forcibly update relation->rd_nblocks. * Physically truncate a relation to the specified number of blocks.
* *
* If the relcache drops an entry for a temp relation, it must call this * Caller should already have done something to flush any buffered pages
* routine after recreating the relcache entry, so that rd_nblocks is * that are to be dropped.
* re-sync'd with reality. See RelationGetNumberOfBlocks.
*/ */
void void
RelationUpdateNumberOfBlocks(Relation relation) RelationTruncate(Relation rel, BlockNumber nblocks)
{ {
if (relation->rd_rel->relkind == RELKIND_VIEW || /* Open it at the smgr level if not already done */
relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE) if (rel->rd_smgr == NULL)
relation->rd_nblocks = 0; rel->rd_smgr = smgropen(rel->rd_node);
else
{
/* Open it at the smgr level if not already done */
if (relation->rd_smgr == NULL)
relation->rd_smgr = smgropen(relation->rd_node);
relation->rd_nblocks = smgrnblocks(relation->rd_smgr); /* Make sure rd_targblock isn't pointing somewhere past end */
} rel->rd_targblock = InvalidBlockNumber;
/* Do the real work */
smgrtruncate(rel->rd_smgr, nblocks);
} }
/* --------------------------------------------------------------------- /* ---------------------------------------------------------------------
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.201 2004/04/01 21:28:45 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.202 2004/05/08 19:09:25 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -889,17 +889,6 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo, ...@@ -889,17 +889,6 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
RelationCacheInsert(relation); RelationCacheInsert(relation);
MemoryContextSwitchTo(oldcxt); MemoryContextSwitchTo(oldcxt);
/*
* If it's a temp rel, RelationGetNumberOfBlocks will assume that
* rd_nblocks is correct. Must forcibly update the block count when
* creating the relcache entry. But if we are doing a rebuild, don't
* do this yet; leave it to RelationClearRelation to do at the end.
* (Otherwise, an elog in RelationUpdateNumberOfBlocks would leave us
* with inconsistent relcache state.)
*/
if (relation->rd_istemp && oldrelation == NULL)
RelationUpdateNumberOfBlocks(relation);
return relation; return relation;
} }
...@@ -1583,9 +1572,7 @@ RelationReloadClassinfo(Relation relation) ...@@ -1583,9 +1572,7 @@ RelationReloadClassinfo(Relation relation)
memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE); memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
relation->rd_node.relNode = relp->relfilenode; relation->rd_node.relNode = relp->relfilenode;
heap_freetuple(pg_class_tuple); heap_freetuple(pg_class_tuple);
/* Must adjust number of blocks after we know the new relfilenode */
relation->rd_targblock = InvalidBlockNumber; relation->rd_targblock = InvalidBlockNumber;
RelationUpdateNumberOfBlocks(relation);
/* Okay, now it's valid again */ /* Okay, now it's valid again */
relation->rd_isnailed = 1; relation->rd_isnailed = 1;
} }
...@@ -1620,29 +1607,26 @@ RelationClearRelation(Relation relation, bool rebuild) ...@@ -1620,29 +1607,26 @@ RelationClearRelation(Relation relation, bool rebuild)
/* /*
* Never, never ever blow away a nailed-in system relation, because * Never, never ever blow away a nailed-in system relation, because
* we'd be unable to recover. However, we must update rd_nblocks and * we'd be unable to recover. However, we must reset rd_targblock, in
* reset rd_targblock, in case we got called because of a relation * case we got called because of a relation cache flush that was triggered
* cache flush that was triggered by VACUUM. If it's a nailed index, * by VACUUM.
* then we need to re-read the pg_class row to see if its relfilenode *
* changed. We can't necessarily do that here, because we might be in * If it's a nailed index, then we need to re-read the pg_class row to see
* a failed transaction. We assume it's okay to do it if there are open * if its relfilenode changed. We can't necessarily do that here, because
* references to the relcache entry (cf notes for AtEOXact_RelationCache). * we might be in a failed transaction. We assume it's okay to do it if
* Otherwise just mark the entry as possibly invalid, and it'll be fixed * there are open references to the relcache entry (cf notes for
* when next opened. * AtEOXact_RelationCache). Otherwise just mark the entry as possibly
* invalid, and it'll be fixed when next opened.
*/ */
if (relation->rd_isnailed) if (relation->rd_isnailed)
{ {
relation->rd_targblock = InvalidBlockNumber;
if (relation->rd_rel->relkind == RELKIND_INDEX) if (relation->rd_rel->relkind == RELKIND_INDEX)
{ {
relation->rd_isnailed = 2; /* needs to be revalidated */ relation->rd_isnailed = 2; /* needs to be revalidated */
if (relation->rd_refcnt > 1) if (relation->rd_refcnt > 1)
RelationReloadClassinfo(relation); RelationReloadClassinfo(relation);
} }
else
{
relation->rd_targblock = InvalidBlockNumber;
RelationUpdateNumberOfBlocks(relation);
}
return; return;
} }
...@@ -1746,15 +1730,6 @@ RelationClearRelation(Relation relation, bool rebuild) ...@@ -1746,15 +1730,6 @@ RelationClearRelation(Relation relation, bool rebuild)
if (old_rulescxt) if (old_rulescxt)
MemoryContextDelete(old_rulescxt); MemoryContextDelete(old_rulescxt);
} }
/*
* Update rd_nblocks. This is kind of expensive, but I think we
* must do it in case relation has been truncated... we definitely
* must do it if the rel is new or temp, since
* RelationGetNumberOfBlocks will subsequently assume that the
* block count is correct.
*/
RelationUpdateNumberOfBlocks(relation);
} }
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.34 2003/11/29 22:40:55 pgsql Exp $ * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.35 2004/05/08 19:09:25 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -25,6 +25,7 @@ typedef struct HeapScanDescData ...@@ -25,6 +25,7 @@ typedef struct HeapScanDescData
Snapshot rs_snapshot; /* snapshot to see */ Snapshot rs_snapshot; /* snapshot to see */
int rs_nkeys; /* number of scan keys */ int rs_nkeys; /* number of scan keys */
ScanKey rs_key; /* array of scan key descriptors */ ScanKey rs_key; /* array of scan key descriptors */
BlockNumber rs_nblocks; /* number of blocks to scan */
/* scan current state */ /* scan current state */
HeapTupleData rs_ctup; /* current tuple in scan, if any */ HeapTupleData rs_ctup; /* current tuple in scan, if any */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/storage/bufmgr.h,v 1.78 2004/04/25 23:50:58 neilc Exp $ * $PostgreSQL: pgsql/src/include/storage/bufmgr.h,v 1.79 2004/05/08 19:09:25 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -156,7 +156,7 @@ extern void AtEOXact_Buffers(bool isCommit); ...@@ -156,7 +156,7 @@ extern void AtEOXact_Buffers(bool isCommit);
extern void FlushBufferPool(void); extern void FlushBufferPool(void);
extern BlockNumber BufferGetBlockNumber(Buffer buffer); extern BlockNumber BufferGetBlockNumber(Buffer buffer);
extern BlockNumber RelationGetNumberOfBlocks(Relation relation); extern BlockNumber RelationGetNumberOfBlocks(Relation relation);
extern void RelationUpdateNumberOfBlocks(Relation relation); extern void RelationTruncate(Relation rel, BlockNumber nblocks);
extern int FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock); extern int FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock);
extern void DropRelationBuffers(Relation rel); extern void DropRelationBuffers(Relation rel);
extern void DropRelFileNodeBuffers(RelFileNode rnode, bool istemp); extern void DropRelFileNodeBuffers(RelFileNode rnode, bool istemp);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.73 2004/02/10 01:55:27 tgl Exp $ * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.74 2004/05/08 19:09:25 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -107,7 +107,6 @@ typedef struct RelationData ...@@ -107,7 +107,6 @@ typedef struct RelationData
RelFileNode rd_node; /* relation physical identifier */ RelFileNode rd_node; /* relation physical identifier */
/* use "struct" here to avoid needing to include smgr.h: */ /* use "struct" here to avoid needing to include smgr.h: */
struct SMgrRelationData *rd_smgr; /* cached file handle, or NULL */ struct SMgrRelationData *rd_smgr; /* cached file handle, or NULL */
BlockNumber rd_nblocks; /* number of blocks in rel */
BlockNumber rd_targblock; /* current insertion target block, or BlockNumber rd_targblock; /* current insertion target block, or
* InvalidBlockNumber */ * InvalidBlockNumber */
int rd_refcnt; /* reference count */ int rd_refcnt; /* reference count */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment