scan->rs_strategy = NULL; /* set in initscan */
scan->rs_allow_strat = allow_strat;
scan->rs_allow_sync = allow_sync;
- scan->rs_lowpage = RelationHasMetapage(relation) ? METAPAGE_BLKNO + 1 : 0;
+ scan->rs_lowpage = RelationFirstNonMetapage(relation);
/*
* we can use page-at-a-time mode if it's an MVCC-safe snapshot
#include "access/heapam.h"
#include "access/hio.h"
+#include "access/metapage.h"
#include "access/visibilitymap.h"
#include "storage/bufmgr.h"
#include "storage/freespace.h"
{
BlockNumber nblocks = RelationGetNumberOfBlocks(relation);
- if (nblocks > 0)
+ if (nblocks > RelationFirstNonMetapage(relation))
targetBlock = nblocks - 1;
}
}
while (targetBlock != InvalidBlockNumber)
{
+ /* Make sure we don't insert into the metapage. */
+ Assert(targetBlock != METAPAGE_BLKNO || !RelationHasMetapage(relation));
+
/*
* Read and exclusive-lock the target block, as well as the other
* block if one was given, taking suitable care with lock ordering and
*/
#include "postgres.h"
+#include "access/metapage.h"
#include "access/sysattr.h"
#include "access/transam.h"
#include "access/xact.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
+#include "storage/bufmgr.h"
#include "storage/predicate.h"
#include "storage/smgr.h"
#include "utils/acl.h"
{
RelationOpenSmgr(rel);
RelationCreateStorage(rel->rd_node, relpersistence);
+ heap_create_storage(rel);
}
return rel;
if (oncommit != ONCOMMIT_NOOP)
register_on_commit_action(relid, oncommit);
- if (relpersistence == RELPERSISTENCE_UNLOGGED)
- {
- Assert(relkind == RELKIND_RELATION || relkind == RELKIND_TOASTVALUE);
- heap_create_init_fork(new_rel_desc);
- }
-
/*
* ok, the relation has been cataloged, so close our relations and return
* the OID of the newly created relation.
}
/*
- * Set up an init fork for an unlogged table so that it can be correctly
- * reinitialized on restart. Since we're going to do an immediate sync, we
- * only need to xlog this if archiving or streaming is enabled. And the
- * immediate sync is required, because otherwise there's no guarantee that
- * this will hit the disk before the next checkpoint moves the redo pointer.
+ * Create storage for a new heap relation.
+ *
+ * This creates the physical file and inserts the metapage. If the relation
+ * is unlogged, we do the same for the init fork as well.
*/
void
-heap_create_init_fork(Relation rel)
+heap_create_storage(Relation rel)
{
- RelationOpenSmgr(rel);
- smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
- if (XLogIsNeeded())
- log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM);
- smgrimmedsync(rel->rd_smgr, INIT_FORKNUM);
+ Buffer metabuffer;
+ Page metapage;
+
+ /* Write metapage. */
+ metabuffer = ReadBufferExtended(rel, MAIN_FORKNUM, P_NEW, RBM_ZERO, NULL);
+ metapage = BufferGetPage(metabuffer);
+ Assert(BufferGetBlockNumber(metabuffer) == METAPAGE_BLKNO);
+ LockBuffer(metabuffer, BUFFER_LOCK_EXCLUSIVE);
+ START_CRIT_SECTION();
+ PageInit(metapage, BLCKSZ, 0);
+ MetapageInit(rel, metapage);
+ MarkBufferDirty(metabuffer);
+ if (RelationNeedsWAL(rel))
+ log_newpage_buffer(metabuffer);
+ END_CRIT_SECTION();
+ UnlockReleaseBuffer(metabuffer);
+
+ /*
+ * If this relation is unlogged, set up an init fork so that it can be
+ * correctly reinitialized on restart.
+ */
+ if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
+ {
+ smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
+ metabuffer = ReadBufferExtended(rel, INIT_FORKNUM, P_NEW, RBM_ZERO,
+ NULL);
+ Assert(BufferGetBlockNumber(metabuffer) == METAPAGE_BLKNO);
+ LockBuffer(metabuffer, BUFFER_LOCK_EXCLUSIVE);
+ START_CRIT_SECTION();
+ PageInit(metapage, BLCKSZ, 0);
+ MetapageInit(rel, metapage);
+ MarkBufferDirty(metabuffer);
+ log_newpage_buffer(metabuffer);
+ END_CRIT_SECTION();
+ UnlockReleaseBuffer(metabuffer);
+ }
}
/*
*/
#include "postgres.h"
+#include "access/metapage.h"
#include "access/transam.h"
#include "access/xlogutils.h"
#include "catalog/dependency.h"
/* Initialize first page of relation with special magic number */
buf = ReadBuffer(rel, P_NEW);
- Assert(BufferGetBlockNumber(buf) == 0);
+ Assert(BufferGetBlockNumber(buf) == RelationFirstNonMetapage(rel));
page = BufferGetPage(buf);
sm->magic = SEQ_MAGIC;
/* hack: ensure heap_insert will insert on the just-created page */
- RelationSetTargetBlock(rel, 0);
+ RelationSetTargetBlock(rel, BufferGetBlockNumber(buf));
/* Now insert sequence tuple */
simple_heap_insert(rel, tuple);
sequence_magic *sm;
Form_pg_sequence seq;
- *buf = ReadBuffer(rel, 0);
+ *buf = ReadBuffer(rel, RelationFirstNonMetapage(rel));
LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE);
page = BufferGetPage(*buf);
* deletion at commit.
*/
RelationSetNewRelfilenode(rel, RecentXmin);
- if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
- heap_create_init_fork(rel);
+ heap_create_storage(rel);
heap_relid = RelationGetRelid(rel);
toast_relid = rel->rd_rel->reltoastrelid;
{
rel = relation_open(toast_relid, AccessExclusiveLock);
RelationSetNewRelfilenode(rel, RecentXmin);
- if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
- heap_create_init_fork(rel);
+ heap_create_storage(rel);
heap_close(rel, NoLock);
}
#include "access/genam.h"
#include "access/heapam.h"
+#include "access/metapage.h"
#include "access/transam.h"
#include "access/visibilitymap.h"
#include "catalog/storage.h"
Relation *Irel, int nindexes, bool scan_all)
{
BlockNumber nblocks,
- blkno;
+ blkno,
+ startblock;
HeapTupleData tuple;
char *relname;
BlockNumber empty_pages,
lazy_space_alloc(vacrelstats, nblocks);
+ startblock = RelationFirstNonMetapage(onerel);
+
/*
* We want to skip pages that don't require vacuuming according to the
* visibility map, but only when we can skip at least SKIP_PAGES_THRESHOLD
* them. If we make the reverse mistake and vacuum a page unnecessarily,
* it'll just be a no-op.
*/
- for (next_not_all_visible_block = 0;
+ for (next_not_all_visible_block = startblock;
next_not_all_visible_block < nblocks;
next_not_all_visible_block++)
{
else
skipping_all_visible_blocks = false;
- for (blkno = 0; blkno < nblocks; blkno++)
+ for (blkno = startblock; blkno < nblocks; blkno++)
{
Buffer buf;
Page page;
#include "postgres.h"
#include "access/htup.h"
+#include "access/metapage.h"
#include "access/xlogutils.h"
#include "miscadmin.h"
#include "storage/freespace.h"
FSMAddress addr;
uint16 slot;
+ /* No free space in the metablock! */
+ Assert(heapBlk != METAPAGE_BLKNO || !RelationHasMetapage(rel));
+
/* Get the location of the FSM byte representing the heap block */
addr = fsm_get_location(heapBlk, &slot);
RelationInitPhysicalAddr(rel);
- /* XXX: Not for heaps yet. */
- if (relkind == RELKIND_INDEX)
- RelationBuildMetadata(rel);
+ RelationBuildMetadata(rel);
/*
* Okay to insert into the relcache hash tables.
*/
#define RelationHasMetapage(relation) \
(RelationGetMetadata((relation))->rmp_version != 0)
+#define RelationFirstNonMetapage(relation) \
+ (RelationHasMetapage((relation)) ? 1 : 0)
#endif /* METAPAGE_H */
bool use_user_acl,
bool allow_system_table_mods);
-extern void heap_create_init_fork(Relation rel);
+extern void heap_create_storage(Relation rel);
extern void heap_drop_with_catalog(Oid relid);