#include "storage/predicate.h"
#include "utils/snapmgr.h"
-static void _bt_cachemetadata(Relation rel, BTMetaPageData *input);
static BTMetaPageData *_bt_getmeta(Relation rel, Buffer metabuf);
static bool _bt_mark_page_halfdead(Relation rel, Buffer buf, BTStack stack);
static bool _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf,
((char *) metad + sizeof(BTMetaPageData)) - (char *) page;
}
-/*
- * Cache metadata from input meta page to rel->rd_amcache.
- */
-static void
-_bt_cachemetadata(Relation rel, BTMetaPageData *input)
-{
- BTMetaPageData *cached_metad;
-
- /* We assume rel->rd_amcache was already freed by caller */
- Assert(rel->rd_amcache == NULL);
- rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
- sizeof(BTMetaPageData));
-
- /* Meta page should be of supported version */
- Assert(input->btm_version >= BTREE_MIN_VERSION &&
- input->btm_version <= BTREE_VERSION);
-
- cached_metad = (BTMetaPageData *) rel->rd_amcache;
- if (input->btm_version >= BTREE_NOVAC_VERSION)
- {
- /* Version with compatible meta-data, no need to upgrade */
- memcpy(cached_metad, input, sizeof(BTMetaPageData));
- }
- else
- {
- /*
- * Upgrade meta-data: copy available information from meta-page and
- * fill new fields with default values.
- *
- * Note that we cannot upgrade to version 4+ without a REINDEX, since
- * extensive on-disk changes are required.
- */
- memcpy(cached_metad, input, offsetof(BTMetaPageData, btm_oldest_btpo_xact));
- cached_metad->btm_version = BTREE_NOVAC_VERSION;
- cached_metad->btm_oldest_btpo_xact = InvalidTransactionId;
- cached_metad->btm_last_cleanup_num_heap_tuples = -1.0;
- }
-}
-
/*
* Get metadata from share-locked buffer containing metapage, while performing
- * standard sanity checks. Sanity checks here must match _bt_getroot().
+ * standard sanity checks.
+ *
+ * Callers that cache data returned here in local cache should note that an
+ * on-the-fly upgrade using _bt_upgrademetapage() can change the version field
+ * and BTREE_NOVAC_VERSION specific fields without invalidating local cache.
*/
static BTMetaPageData *
_bt_getmeta(Relation rel, Buffer metabuf)
_bt_getroot(Relation rel, int access)
{
Buffer metabuf;
- Page metapg;
- BTPageOpaque metaopaque;
Buffer rootbuf;
Page rootpage;
BTPageOpaque rootopaque;
}
metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_READ);
- metapg = BufferGetPage(metabuf);
- metaopaque = (BTPageOpaque) PageGetSpecialPointer(metapg);
- metad = BTPageGetMeta(metapg);
-
- /* sanity-check the metapage */
- if (!P_ISMETA(metaopaque) ||
- metad->btm_magic != BTREE_MAGIC)
- ereport(ERROR,
- (errcode(ERRCODE_INDEX_CORRUPTED),
- errmsg("index \"%s\" is not a btree",
- RelationGetRelationName(rel))));
-
- if (metad->btm_version < BTREE_MIN_VERSION ||
- metad->btm_version > BTREE_VERSION)
- ereport(ERROR,
- (errcode(ERRCODE_INDEX_CORRUPTED),
- errmsg("version mismatch in index \"%s\": file version %d, "
- "current version %d, minimal supported version %d",
- RelationGetRelationName(rel),
- metad->btm_version, BTREE_VERSION, BTREE_MIN_VERSION)));
+ metad = _bt_getmeta(rel, metabuf);
/* if no root page initialized yet, do it */
if (metad->btm_root == P_NONE)
{
+ Page metapg;
+
/* If access = BT_READ, caller doesn't want us to create root yet */
if (access == BT_READ)
{
rootopaque->btpo_flags = (BTP_LEAF | BTP_ROOT);
rootopaque->btpo.level = 0;
rootopaque->btpo_cycleid = 0;
+ /* Get raw page pointer for metapage */
+ metapg = BufferGetPage(metabuf);
/* NO ELOG(ERROR) till meta is updated */
START_CRIT_SECTION();
LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK);
LockBuffer(rootbuf, BT_READ);
- /* okay, metadata is correct, release lock on it */
+ /* okay, metadata is correct, release lock on it without caching */
_bt_relbuf(rel, metabuf);
}
else
/*
* Cache the metapage data for next time
*/
- _bt_cachemetadata(rel, metad);
+ rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
+ sizeof(BTMetaPageData));
+ memcpy(rel->rd_amcache, metad, sizeof(BTMetaPageData));
/*
* We are done with the metapage; arrange to release it via first
/*
* Cache the metapage data for next time
*/
- _bt_cachemetadata(rel, metad);
- /* We shouldn't have cached it if any of these fail */
- Assert(metad->btm_magic == BTREE_MAGIC);
- Assert(metad->btm_version >= BTREE_NOVAC_VERSION);
- Assert(metad->btm_fastroot != P_NONE);
+ rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
+ sizeof(BTMetaPageData));
+ memcpy(rel->rd_amcache, metad, sizeof(BTMetaPageData));
_bt_relbuf(rel, metabuf);
}
/* Get cached page */
metad = (BTMetaPageData *) rel->rd_amcache;
+ /* We shouldn't have cached it if any of these fail */
+ Assert(metad->btm_magic == BTREE_MAGIC);
+ Assert(metad->btm_version >= BTREE_MIN_VERSION);
+ Assert(metad->btm_version <= BTREE_VERSION);
+ Assert(metad->btm_fastroot != P_NONE);
return metad->btm_fastlevel;
}
/*
* Cache the metapage data for next time
+ *
+ * An on-the-fly version upgrade performed by _bt_upgrademetapage()
+ * can change the nbtree version for an index without invalidating any
+ * local cache. This is okay because it can only happen when moving
+ * from version 2 to version 3, both of which are !heapkeyspace
+ * versions.
*/
- _bt_cachemetadata(rel, metad);
- /* We shouldn't have cached it if any of these fail */
- Assert(metad->btm_magic == BTREE_MAGIC);
- Assert(metad->btm_version >= BTREE_NOVAC_VERSION);
- Assert(metad->btm_fastroot != P_NONE);
+ rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
+ sizeof(BTMetaPageData));
+ memcpy(rel->rd_amcache, metad, sizeof(BTMetaPageData));
_bt_relbuf(rel, metabuf);
}
/* Get cached page */
metad = (BTMetaPageData *) rel->rd_amcache;
+ /* We shouldn't have cached it if any of these fail */
+ Assert(metad->btm_magic == BTREE_MAGIC);
+ Assert(metad->btm_version >= BTREE_MIN_VERSION);
+ Assert(metad->btm_version <= BTREE_VERSION);
+ Assert(metad->btm_fastroot != P_NONE);
return metad->btm_version > BTREE_NOVAC_VERSION;
}