本文整理汇总了C++中RelationOpenSmgr函数的典型用法代码示例。如果您正苦于以下问题:C++ RelationOpenSmgr函数的具体用法?C++ RelationOpenSmgr怎么用?C++ RelationOpenSmgr使用的例子?那么, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了RelationOpenSmgr函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: SetMatViewToPopulated
/*
* SetMatViewToPopulated
* Indicate that the materialized view has been populated by its query.
*
* NOTE: The heap starts out in a state that doesn't look scannable, and can
* only transition from there to scannable at the time a new heap is created.
*
* NOTE: caller must be holding an appropriate lock on the relation.
*/
void
SetMatViewToPopulated(Relation relation)
{
Page page;
Assert(relation->rd_rel->relkind == RELKIND_MATVIEW);
Assert(relation->rd_ispopulated == false);
page = (Page) palloc(BLCKSZ);
PageInit(page, BLCKSZ, 0);
if (RelationNeedsWAL(relation))
log_newpage(&(relation->rd_node), MAIN_FORKNUM, 0, page);
RelationOpenSmgr(relation);
PageSetChecksumInplace(page, 0);
smgrextend(relation->rd_smgr, MAIN_FORKNUM, 0, (char *) page, true);
pfree(page);
smgrimmedsync(relation->rd_smgr, MAIN_FORKNUM);
RelationCacheInvalidateEntry(relation->rd_id);
}
示例2: pg_truncate_visibility_map
/*
* Remove the visibility map fork for a relation. If there turn out to be
* any bugs in the visibility map code that require rebuilding the VM, this
* provides users with a way to do it that is cleaner than shutting down the
* server and removing files by hand.
*
* This is a cut-down version of RelationTruncate.
*/
Datum
pg_truncate_visibility_map(PG_FUNCTION_ARGS)
{
Oid relid = PG_GETARG_OID(0);
Relation rel;
rel = relation_open(relid, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION &&
rel->rd_rel->relkind != RELKIND_MATVIEW &&
rel->rd_rel->relkind != RELKIND_TOASTVALUE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table, materialized view, or TOAST table",
RelationGetRelationName(rel))));
RelationOpenSmgr(rel);
rel->rd_smgr->smgr_vm_nblocks = InvalidBlockNumber;
visibilitymap_truncate(rel, 0);
if (RelationNeedsWAL(rel))
{
xl_smgr_truncate xlrec;
xlrec.blkno = 0;
xlrec.rnode = rel->rd_node;
xlrec.flags = SMGR_TRUNCATE_VM;
XLogBeginInsert();
XLogRegisterData((char *) &xlrec, sizeof(xlrec));
XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE);
}
/*
* Release the lock right away, not at commit time.
*
* It would be a problem to release the lock prior to commit if this
* truncate operation sends any transactional invalidation messages. Other
* backends would potentially be able to lock the relation without
* processing them in the window of time between when we release the lock
* here and when we sent the messages at our eventual commit. However,
* we're currently only sending a non-transactional smgr invalidation,
* which will have been posted to shared memory immediately from within
* visibilitymap_truncate. Therefore, there should be no race here.
*
* The reason why it's desirable to release the lock early here is because
* of the possibility that someone will need to use this to blow away many
* visibility map forks at once. If we can't release the lock until
* commit time, the transaction doing this will accumulate
* AccessExclusiveLocks on all of those relations at the same time, which
* is undesirable. However, if this turns out to be unsafe we may have no
* choice...
*/
relation_close(rel, AccessExclusiveLock);
/* Nothing to return. */
PG_RETURN_VOID();
}
示例3: vm_extend
/*
* Ensure that the visibility map fork is at least vm_nblocks long, extending
* it if necessary with zeroed pages.
*/
static void
vm_extend(Relation rel, BlockNumber vm_nblocks)
{
BlockNumber vm_nblocks_now;
Page pg;
pg = (Page) palloc(BLCKSZ);
PageInit(pg, BLCKSZ, 0);
/*
* We use the relation extension lock to lock out other backends trying to
* extend the visibility map at the same time. It also locks out extension
* of the main fork, unnecessarily, but extending the visibility map
* happens seldom enough that it doesn't seem worthwhile to have a
* separate lock tag type for it.
*
* Note that another backend might have extended or created the relation
* by the time we get the lock.
*/
LockRelationForExtension(rel, ExclusiveLock);
/* Might have to re-open if a cache flush happened */
RelationOpenSmgr(rel);
/*
* Create the file first if it doesn't exist. If smgr_vm_nblocks is
* positive then it must exist, no need for an smgrexists call.
*/
if ((rel->rd_smgr->smgr_vm_nblocks == 0 ||
rel->rd_smgr->smgr_vm_nblocks == InvalidBlockNumber) &&
!smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM))
smgrcreate(rel->rd_smgr, VISIBILITYMAP_FORKNUM, false);
vm_nblocks_now = smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM);
/* Now extend the file */
while (vm_nblocks_now < vm_nblocks)
{
smgrextend(rel->rd_smgr, VISIBILITYMAP_FORKNUM, vm_nblocks_now,
(char *) pg, false);
vm_nblocks_now++;
}
/*
* Send a shared-inval message to force other backends to close any smgr
* references they may have for this rel, which we are about to change.
* This is a useful optimization because it means that backends don't have
* to keep checking for creation or extension of the file, which happens
* infrequently.
*/
CacheInvalidateSmgr(rel->rd_smgr->smgr_rnode);
/* Update local cache with the up-to-date size */
rel->rd_smgr->smgr_vm_nblocks = vm_nblocks_now;
UnlockRelationForExtension(rel, ExclusiveLock);
pfree(pg);
}
示例4: FreeSpaceMapTruncateRel
/*
* FreeSpaceMapTruncateRel - adjust for truncation of a relation.
*
* The caller must hold AccessExclusiveLock on the relation, to ensure that
* other backends receive the smgr invalidation event that this function sends
* before they access the FSM again.
*
* nblocks is the new___ size of the heap.
*/
void
FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
{
BlockNumber new_nfsmblocks;
FSMAddress first_removed_address;
uint16 first_removed_slot;
Buffer buf;
RelationOpenSmgr(rel);
/*
* If no FSM has been created yet for this relation, there's nothing to
* truncate.
*/
if (!smgrexists(rel->rd_smgr, FSM_FORKNUM))
return;
/* Get the location in the FSM of the first removed heap block */
first_removed_address = fsm_get_location(nblocks, &first_removed_slot);
/*
* Zero out the tail of the last remaining FSM page. If the slot
* representing the first removed heap block is at a page boundary, as the
* first slot on the FSM page that first_removed_address points to, we can
* just truncate that page altogether.
*/
if (first_removed_slot > 0)
{
buf = fsm_readbuf(rel, first_removed_address, false);
if (!BufferIsValid(buf))
return; /* nothing to do; the FSM was already smaller */
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
fsm_truncate_avail(BufferGetPage(buf), first_removed_slot);
MarkBufferDirtyHint(buf, false);
UnlockReleaseBuffer(buf);
new_nfsmblocks = fsm_logical_to_physical(first_removed_address) + 1;
}
else
{
new_nfsmblocks = fsm_logical_to_physical(first_removed_address);
if (smgrnblocks(rel->rd_smgr, FSM_FORKNUM) <= new_nfsmblocks)
return; /* nothing to do; the FSM was already smaller */
}
/* Truncate the unused FSM pages, and send smgr inval message */
smgrtruncate(rel->rd_smgr, FSM_FORKNUM, new_nfsmblocks);
/*
* We might as well update the local smgr_fsm_nblocks setting.
* smgrtruncate sent an smgr cache inval message, which will cause other
* backends to invalidate their copy of smgr_fsm_nblocks, and this one too
* at the next command boundary. But this ensures it isn't outright wrong
* until then.
*/
if (rel->rd_smgr)
rel->rd_smgr->smgr_fsm_nblocks = new_nfsmblocks;
}
示例5: _bt_blwritepage
/*
* emit a completed btree page, and release the working storage.
*/
static void
_bt_blwritepage(BTWriteState *wstate, Page page, BlockNumber blkno)
{
/* Ensure rd_smgr is open (could have been closed by relcache flush!) */
RelationOpenSmgr(wstate->index);
/* XLOG stuff */
if (wstate->btws_use_wal)
{
/* We use the heap NEWPAGE record type for this */
log_newpage(&wstate->index->rd_node, MAIN_FORKNUM, blkno, page);
}
else
{
/* Leave the page LSN zero if not WAL-logged, but set TLI anyway */
PageSetTLI(page, ThisTimeLineID);
}
/*
* If we have to write pages nonsequentially, fill in the space with
* zeroes until we come back and overwrite. This is not logically
* necessary on standard Unix filesystems (unwritten space will read as
* zeroes anyway), but it should help to avoid fragmentation. The dummy
* pages aren't WAL-logged though.
*/
while (blkno > wstate->btws_pages_written)
{
if (!wstate->btws_zeropage)
wstate->btws_zeropage = (Page) palloc0(BLCKSZ);
smgrextend(wstate->index->rd_smgr, MAIN_FORKNUM,
wstate->btws_pages_written++,
(char *) wstate->btws_zeropage,
true);
}
/*
* Now write the page. We say isTemp = true even if it's not a temp
* index, because there's no need for smgr to schedule an fsync for this
* write; we'll do it ourselves before ending the build.
*/
if (blkno == wstate->btws_pages_written)
{
/* extending the file... */
smgrextend(wstate->index->rd_smgr, MAIN_FORKNUM, blkno,
(char *) page, true);
wstate->btws_pages_written++;
}
else
{
/* overwriting a block we zero-filled before */
smgrwrite(wstate->index->rd_smgr, MAIN_FORKNUM, blkno,
(char *) page, true);
}
pfree(page);
}
示例6: end_heap_rewrite
/*
* End a rewrite.
*
* state and any other resources are freed.
*/
void
end_heap_rewrite(RewriteState state)
{
HASH_SEQ_STATUS seq_status;
UnresolvedTup unresolved;
/*
* Write any remaining tuples in the UnresolvedTups table. If we have any
* left, they should in fact be dead, but let's err on the safe side.
*/
hash_seq_init(&seq_status, state->rs_unresolved_tups);
while ((unresolved = hash_seq_search(&seq_status)) != NULL)
{
ItemPointerSetInvalid(&unresolved->tuple->t_data->t_ctid);
raw_heap_insert(state, unresolved->tuple);
}
/* Write the last page, if any */
if (state->rs_buffer_valid)
{
if (state->rs_use_wal)
log_newpage(&state->rs_new_rel->rd_node,
MAIN_FORKNUM,
state->rs_blockno,
state->rs_buffer,
true);
RelationOpenSmgr(state->rs_new_rel);
PageSetChecksumInplace(state->rs_buffer, state->rs_blockno);
smgrextend(state->rs_new_rel->rd_smgr, MAIN_FORKNUM, state->rs_blockno,
(char *) state->rs_buffer, true);
}
/*
* If the rel is WAL-logged, must fsync before commit. We use heap_sync
* to ensure that the toast table gets fsync'd too.
*
* It's obvious that we must do this when not WAL-logging. It's less
* obvious that we have to do it even if we did WAL-log the pages. The
* reason is the same as in tablecmds.c's copy_relation_data(): we're
* writing data that's not in shared buffers, and so a CHECKPOINT
* occurring during the rewriteheap operation won't have fsync'd data we
* wrote before the checkpoint.
*/
if (RelationNeedsWAL(state->rs_new_rel))
heap_sync(state->rs_new_rel);
/* Deleting the context frees everything */
MemoryContextDelete(state->rs_cxt);
}
示例7: fsm_extend
/*
* Ensure that the FSM fork is at least fsm_nblocks long, extending
* it if necessary with empty pages. And by empty, I mean pages filled
* with zeros, meaning there's no free space.
*/
static void
fsm_extend(Relation rel, BlockNumber fsm_nblocks)
{
BlockNumber fsm_nblocks_now;
Page pg;
pg = (Page) palloc(BLCKSZ);
PageInit(pg, BLCKSZ, 0);
/*
* We use the relation extension lock to lock out other backends trying to
* extend the FSM at the same time. It also locks out extension of the
* main fork, unnecessarily, but extending the FSM happens seldom enough
* that it doesn't seem worthwhile to have a separate lock tag type for
* it.
*
* Note that another backend might have extended or created the relation
* by the time we get the lock.
*/
LockRelationForExtension(rel, ExclusiveLock);
/* Might have to re-open if a cache flush happened */
RelationOpenSmgr(rel);
/*
* Create the FSM file first if it doesn't exist. If smgr_fsm_nblocks is
* positive then it must exist, no need for an smgrexists call.
*/
if ((rel->rd_smgr->smgr_fsm_nblocks == 0 ||
rel->rd_smgr->smgr_fsm_nblocks == InvalidBlockNumber) &&
!smgrexists(rel->rd_smgr, FSM_FORKNUM))
smgrcreate(rel->rd_smgr, FSM_FORKNUM, false);
fsm_nblocks_now = smgrnblocks(rel->rd_smgr, FSM_FORKNUM);
while (fsm_nblocks_now < fsm_nblocks)
{
PageSetChecksumInplace(pg, fsm_nblocks_now);
smgrextend(rel->rd_smgr, FSM_FORKNUM, fsm_nblocks_now,
(char *) pg, false);
fsm_nblocks_now++;
}
/* Update local cache with the up-to-date size */
rel->rd_smgr->smgr_fsm_nblocks = fsm_nblocks_now;
UnlockRelationForExtension(rel, ExclusiveLock);
pfree(pg);
}
示例8: fsm_allow_writes
/*
* For heaps, we prevent creation of the FSM unless the number of pages
* exceeds HEAP_FSM_CREATION_THRESHOLD. For tables that don't already have
* a FSM, this will save an inode and a few kB of space.
*
* XXX The API is a little awkward -- if the caller passes a valid nblocks
* value, it can avoid invoking a system call. If the caller passes
* InvalidBlockNumber and receives a false return value, it can get an
* up-to-date relation size from get_nblocks. This saves a few cycles in
* the caller, which would otherwise need to get the relation size by itself.
*/
static bool
fsm_allow_writes(Relation rel, BlockNumber heapblk,
BlockNumber nblocks, BlockNumber *get_nblocks)
{
bool skip_get_nblocks;
if (heapblk >= HEAP_FSM_CREATION_THRESHOLD)
return true;
/* Non-heap rels can always create a FSM. */
if (rel->rd_rel->relkind != RELKIND_RELATION &&
rel->rd_rel->relkind != RELKIND_TOASTVALUE)
return true;
/*
* If the caller knows nblocks, we can avoid a system call later. If it
* doesn't, maybe we have relpages from a previous VACUUM. Since the table
* may have extended since then, we still have to count the pages later if
* we can't return now.
*/
if (nblocks != InvalidBlockNumber)
{
if (nblocks > HEAP_FSM_CREATION_THRESHOLD)
return true;
else
skip_get_nblocks = true;
}
else
{
if (rel->rd_rel->relpages != InvalidBlockNumber &&
rel->rd_rel->relpages > HEAP_FSM_CREATION_THRESHOLD)
return true;
else
skip_get_nblocks = false;
}
RelationOpenSmgr(rel);
if (smgrexists(rel->rd_smgr, FSM_FORKNUM))
return true;
if (skip_get_nblocks)
return false;
/* last resort */
*get_nblocks = RelationGetNumberOfBlocks(rel);
if (*get_nblocks > HEAP_FSM_CREATION_THRESHOLD)
return true;
else
return false;
}
示例9: vm_readbuf
/*
* Read a visibility map page.
*
* If the page doesn't exist, InvalidBuffer is returned, or if 'extend' is
* true, the visibility map file is extended.
*/
static Buffer
vm_readbuf(Relation rel, BlockNumber blkno, bool extend)
{
Buffer buf;
/*
* We might not have opened the relation at the smgr level yet, or we
* might have been forced to close it by a sinval message. The code below
* won't necessarily notice relation extension immediately when extend =
* false, so we rely on sinval messages to ensure that our ideas about the
* size of the map aren't too far out of date.
*/
RelationOpenSmgr(rel);
/*
* If we haven't cached the size of the visibility map fork yet, check it
* first.
*/
if (rel->rd_smgr->smgr_vm_nblocks == InvalidBlockNumber)
{
if (smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM))
rel->rd_smgr->smgr_vm_nblocks = smgrnblocks(rel->rd_smgr,
VISIBILITYMAP_FORKNUM);
else
rel->rd_smgr->smgr_vm_nblocks = 0;
}
/* Handle requests beyond EOF */
if (blkno >= rel->rd_smgr->smgr_vm_nblocks)
{
if (extend)
vm_extend(rel, blkno + 1);
else
return InvalidBuffer;
}
/*
* Use ZERO_ON_ERROR mode, and initialize the page if necessary. It's
* always safe to clear bits, so it's better to clear corrupt pages than
* error out.
*/
buf = ReadBufferExtended(rel, VISIBILITYMAP_FORKNUM, blkno,
RBM_ZERO_ON_ERROR, NULL);
if (PageIsNew(BufferGetPage(buf)))
PageInit(BufferGetPage(buf), BLCKSZ, 0);
return buf;
}
示例10: _hash_alloc_buckets
/*
* _hash_alloc_buckets -- allocate a new splitpoint's worth of bucket pages
*
* This does not need to initialize the new bucket pages; we'll do that as
* each one is used by _hash_expandtable(). But we have to extend the logical
* EOF to the end of the splitpoint; this keeps smgr's idea of the EOF in
* sync with ours, so that we don't get complaints from smgr.
*
* We do this by writing a page of zeroes at the end of the splitpoint range.
* We expect that the filesystem will ensure that the intervening pages read
* as zeroes too. On many filesystems this "hole" will not be allocated
* immediately, which means that the index file may end up more fragmented
* than if we forced it all to be allocated now; but since we don't scan
* hash indexes sequentially anyway, that probably doesn't matter.
*
* XXX It's annoying that this code is executed with the metapage lock held.
* We need to interlock against _hash_addovflpage() adding a new overflow page
* concurrently, but it'd likely be better to use LockRelationForExtension
* for the purpose. OTOH, adding a splitpoint is a very infrequent operation,
* so it may not be worth worrying about.
*
* Returns TRUE if successful, or FALSE if allocation failed due to
* BlockNumber overflow.
*/
static bool
_hash_alloc_buckets(Relation rel, BlockNumber firstblock, uint32 nblocks)
{
BlockNumber lastblock;
char zerobuf[BLCKSZ];
Page page;
HashPageOpaque ovflopaque;
lastblock = firstblock + nblocks - 1;
/*
* Check for overflow in block number calculation; if so, we cannot extend
* the index anymore.
*/
if (lastblock < firstblock || lastblock == InvalidBlockNumber)
return false;
page = (Page) zerobuf;
/*
* Initialize the page. Just zeroing the page won't work; see
* _hash_freeovflpage for similar usage. We take care to make the special
* space valid for the benefit of tools such as pageinspect.
*/
_hash_pageinit(page, BLCKSZ);
ovflopaque = (HashPageOpaque) PageGetSpecialPointer(page);
ovflopaque->hasho_prevblkno = InvalidBlockNumber;
ovflopaque->hasho_nextblkno = InvalidBlockNumber;
ovflopaque->hasho_bucket = -1;
ovflopaque->hasho_flag = LH_UNUSED_PAGE;
ovflopaque->hasho_page_id = HASHO_PAGE_ID;
if (RelationNeedsWAL(rel))
log_newpage(&rel->rd_node,
MAIN_FORKNUM,
lastblock,
zerobuf,
true);
RelationOpenSmgr(rel);
smgrextend(rel->rd_smgr, MAIN_FORKNUM, lastblock, zerobuf, false);
return true;
}
示例11: fsm_readbuf
/*
* Read a FSM page.
*
* If the page doesn't exist, InvalidBuffer is returned, or if 'extend' is
* true, the FSM file is extended.
*/
static Buffer
fsm_readbuf(Relation rel, FSMAddress addr, bool extend)
{
BlockNumber blkno = fsm_logical_to_physical(addr);
Buffer buf;
RelationOpenSmgr(rel);
/*
* If we haven't cached the size of the FSM yet, check it first. Also
* recheck if the requested block seems to be past end, since our cached
* value might be stale. (We send smgr inval messages on truncation, but
* not on extension.)
*/
if (rel->rd_smgr->smgr_fsm_nblocks == InvalidBlockNumber ||
blkno >= rel->rd_smgr->smgr_fsm_nblocks)
{
if (smgrexists(rel->rd_smgr, FSM_FORKNUM))
rel->rd_smgr->smgr_fsm_nblocks = smgrnblocks(rel->rd_smgr,
FSM_FORKNUM);
else
rel->rd_smgr->smgr_fsm_nblocks = 0;
}
/* Handle requests beyond EOF */
if (blkno >= rel->rd_smgr->smgr_fsm_nblocks)
{
if (extend)
fsm_extend(rel, blkno + 1);
else
return InvalidBuffer;
}
/*
* Use ZERO_ON_ERROR mode, and initialize the page if necessary. The FSM
* information is not accurate anyway, so it's better to clear corrupt
* pages than error out. Since the FSM changes are not WAL-logged, the
* so-called torn page problem on crash can lead to pages with corrupt
* headers, for example.
*/
buf = ReadBufferExtended(rel, FSM_FORKNUM, blkno, RBM_ZERO_ON_ERROR, NULL);
if (PageIsNew(BufferGetPage(buf)))
PageInit(BufferGetPage(buf), BLCKSZ, 0);
return buf;
}
示例12: vm_readbuf
/*
* Read a visibility map page.
*
* If the page doesn't exist, InvalidBuffer is returned, or if 'extend' is
* true, the visibility map file is extended.
*/
static Buffer
vm_readbuf(Relation rel, BlockNumber blkno, bool extend)
{
Buffer buf;
RelationOpenSmgr(rel);
/*
* If we haven't cached the size of the visibility map fork yet, check it
* first. Also recheck if the requested block seems to be past end, since
* our cached value might be stale. (We send smgr inval messages on
* truncation, but not on extension.)
*/
if (rel->rd_smgr->smgr_vm_nblocks == InvalidBlockNumber ||
blkno >= rel->rd_smgr->smgr_vm_nblocks)
{
if (smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM))
rel->rd_smgr->smgr_vm_nblocks = smgrnblocks(rel->rd_smgr,
VISIBILITYMAP_FORKNUM);
else
rel->rd_smgr->smgr_vm_nblocks = 0;
}
/* Handle requests beyond EOF */
if (blkno >= rel->rd_smgr->smgr_vm_nblocks)
{
if (extend)
vm_extend(rel, blkno + 1);
else
return InvalidBuffer;
}
/*
* Use ZERO_ON_ERROR mode, and initialize the page if necessary. It's
* always safe to clear bits, so it's better to clear corrupt pages than
* error out.
*/
buf = ReadBufferExtended(rel, VISIBILITYMAP_FORKNUM, blkno,
RBM_ZERO_ON_ERROR, NULL);
if (PageIsNew(BufferGetPage(buf)))
PageInit(BufferGetPage(buf), BLCKSZ, 0);
return buf;
}
示例13: vm_readbuf
/*
* Read a visibility map page.
*
* If the page doesn't exist, InvalidBuffer is returned, or if 'extend' is
* true, the visibility map file is extended.
*/
static Buffer
vm_readbuf(Relation rel, BlockNumber blkno, bool extend)
{
Buffer buf;
RelationOpenSmgr(rel);
/*
* The current size of the visibility map fork is kept in relcache, to
* avoid reading beyond EOF. If we haven't cached the size of the map yet,
* do that first.
*/
if (rel->rd_vm_nblocks == InvalidBlockNumber)
{
if (smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM))
rel->rd_vm_nblocks = smgrnblocks(rel->rd_smgr,
VISIBILITYMAP_FORKNUM);
else
rel->rd_vm_nblocks = 0;
}
/* Handle requests beyond EOF */
if (blkno >= rel->rd_vm_nblocks)
{
if (extend)
vm_extend(rel, blkno + 1);
else
return InvalidBuffer;
}
/*
* Use ZERO_ON_ERROR mode, and initialize the page if necessary. It's
* always safe to clear bits, so it's better to clear corrupt pages than
* error out.
*/
buf = ReadBufferExtended(rel, VISIBILITYMAP_FORKNUM, blkno,
RBM_ZERO_ON_ERROR, NULL);
if (PageIsNew(BufferGetPage(buf)))
PageInit(BufferGetPage(buf), BLCKSZ, 0);
return buf;
}
示例14: _hash_alloc_buckets
/*
* _hash_alloc_buckets -- allocate a new splitpoint's worth of bucket pages
*
* This does not need to initialize the new bucket pages; we'll do that as
* each one is used by _hash_expandtable(). But we have to extend the logical
* EOF to the end of the splitpoint; this keeps smgr's idea of the EOF in
* sync with ours, so that we don't get complaints from smgr.
*
* We do this by writing a page of zeroes at the end of the splitpoint range.
* We expect that the filesystem will ensure that the intervening pages read
* as zeroes too. On many filesystems this "hole" will not be allocated
* immediately, which means that the index file may end up more fragmented
* than if we forced it all to be allocated now; but since we don't scan
* hash indexes sequentially anyway, that probably doesn't matter.
*
* XXX It's annoying that this code is executed with the metapage lock held.
* We need to interlock against _hash_getovflpage() adding a new overflow page
* concurrently, but it'd likely be better to use LockRelationForExtension
* for the purpose. OTOH, adding a splitpoint is a very infrequent operation,
* so it may not be worth worrying about.
*
* Returns TRUE if successful, or FALSE if allocation failed due to
* BlockNumber overflow.
*/
static bool
_hash_alloc_buckets(Relation rel, BlockNumber firstblock, uint32 nblocks)
{
BlockNumber lastblock;
char zerobuf[BLCKSZ];
lastblock = firstblock + nblocks - 1;
/*
* Check for overflow in block number calculation; if so, we cannot extend
* the index anymore.
*/
if (lastblock < firstblock || lastblock == InvalidBlockNumber)
return false;
MemSet(zerobuf, 0, sizeof(zerobuf));
RelationOpenSmgr(rel);
smgrextend(rel->rd_smgr, MAIN_FORKNUM, lastblock, zerobuf, false);
return true;
}
示例15: _hash_alloc_buckets
/*
* _hash_alloc_buckets -- allocate a new splitpoint's worth of bucket pages
*
* This does not need to initialize the new bucket pages; we'll do that as
* each one is used by _hash_expandtable(). But we have to extend the logical
* EOF to the end of the splitpoint; otherwise the first overflow page
* allocated beyond the splitpoint will represent a noncontiguous access,
* which can confuse md.c (and will probably be forbidden by future changes
* to md.c).
*
* We do this by writing a page of zeroes at the end of the splitpoint range.
* We expect that the filesystem will ensure that the intervening pages read
* as zeroes too. On many filesystems this "hole" will not be allocated
* immediately, which means that the index file may end up more fragmented
* than if we forced it all to be allocated now; but since we don't scan
* hash indexes sequentially anyway, that probably doesn't matter.
*
* XXX It's annoying that this code is executed with the metapage lock held.
* We need to interlock against _hash_getovflpage() adding a new overflow page
* concurrently, but it'd likely be better to use LockRelationForExtension
* for the purpose. OTOH, adding a splitpoint is a very infrequent operation,
* so it may not be worth worrying about.
*
* Returns TRUE if successful, or FALSE if allocation failed due to
* BlockNumber overflow.
*/
static bool
_hash_alloc_buckets(Relation rel, BlockNumber firstblock, uint32 nblocks)
{
BlockNumber lastblock;
BlockNumber endblock;
char zerobuf[BLCKSZ];
lastblock = firstblock + nblocks - 1;
/*
* Check for overflow in block number calculation; if so, we cannot
* extend the index anymore.
*/
if (lastblock < firstblock || lastblock == InvalidBlockNumber)
return false;
MemSet(zerobuf, 0, sizeof(zerobuf));
RelationOpenSmgr(rel);
/*
* XXX If the extension results in creation of new segment files,
* we have to make sure that each non-last file is correctly filled out to
* RELSEG_SIZE blocks. This ought to be done inside mdextend, but
* changing the smgr API seems best left for development cycle not late
* beta. Temporary fix for bug #2737.
*/
#ifndef LET_OS_MANAGE_FILESIZE
for (endblock = firstblock | (RELSEG_SIZE - 1);
endblock < lastblock;
endblock += RELSEG_SIZE)
smgrextend(rel->rd_smgr, endblock, zerobuf, rel->rd_istemp);
#endif
smgrextend(rel->rd_smgr, lastblock, zerobuf, rel->rd_istemp);
return true;
}