Skip to content

Commit 0a64b45

Browse files
committed
Fix handling of non-upgraded B-tree metapages
857f9c3 bumps B-tree metapage version while upgrade is performed "on the fly" when needed. However, some asserts fired when old version metapage was cached to rel->rd_amcache. Despite new metadata fields are never used from rel->rd_amcache, that needs to be fixed. This patch introduces metadata upgrade during its caching, which fills unavailable fields with their default values. contrib/pageinspect is also patched to handle non-upgraded metapages in the same way. Author: Alexander Korotkov
1 parent 01b88b4 commit 0a64b45

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

contrib/pageinspect/btreefuncs.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,8 +555,21 @@ bt_metap(PG_FUNCTION_ARGS)
555555
values[j++] = psprintf("%d", metad->btm_level);
556556
values[j++] = psprintf("%d", metad->btm_fastroot);
557557
values[j++] = psprintf("%d", metad->btm_fastlevel);
558-
values[j++] = psprintf("%u", metad->btm_oldest_btpo_xact);
559-
values[j++] = psprintf("%lf", metad->btm_last_cleanup_num_heap_tuples);
558+
559+
/*
560+
* Get values of extended metadata if available, use default values
561+
* otherwise.
562+
*/
563+
if (metad->btm_version == BTREE_VERSION)
564+
{
565+
values[j++] = psprintf("%u", metad->btm_oldest_btpo_xact);
566+
values[j++] = psprintf("%lf", metad->btm_last_cleanup_num_heap_tuples);
567+
}
568+
else
569+
{
570+
values[j++] = "0";
571+
values[j++] = "-1";
572+
}
560573

561574
tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc),
562575
values);

src/backend/access/nbtree/nbtpage.c

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "storage/predicate.h"
3434
#include "utils/snapmgr.h"
3535

36+
static void _bt_cachemetadata(Relation rel, BTMetaPageData *metad);
3637
static bool _bt_mark_page_halfdead(Relation rel, Buffer buf, BTStack stack);
3738
static bool _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf,
3839
bool *rightsib_empty);
@@ -105,6 +106,44 @@ _bt_upgrademetapage(Page page)
105106
((char *) metad + sizeof(BTMetaPageData)) - (char *) page;
106107
}
107108

109+
/*
110+
* Cache metadata from meta page to rel->rd_amcache.
111+
*/
112+
static void
113+
_bt_cachemetadata(Relation rel, BTMetaPageData *metad)
114+
{
115+
/* We assume rel->rd_amcache was already freed by caller */
116+
Assert(rel->rd_amcache == NULL);
117+
rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
118+
sizeof(BTMetaPageData));
119+
120+
/*
121+
* Meta page should be of supported version (should be already checked by
122+
* caller).
123+
*/
124+
Assert(metad->btm_version >= BTREE_MIN_VERSION &&
125+
metad->btm_version <= BTREE_VERSION);
126+
127+
if (metad->btm_version == BTREE_VERSION)
128+
{
129+
/* Last version of meta-data, no need to upgrade */
130+
memcpy(rel->rd_amcache, metad, sizeof(BTMetaPageData));
131+
}
132+
else
133+
{
134+
BTMetaPageData *cached_metad = (BTMetaPageData *) rel->rd_amcache;
135+
136+
/*
137+
* Upgrade meta-data: copy available information from meta-page and
138+
* fill new fields with default values.
139+
*/
140+
memcpy(rel->rd_amcache, metad, offsetof(BTMetaPageData, btm_oldest_btpo_xact));
141+
cached_metad->btm_version = BTREE_VERSION;
142+
cached_metad->btm_oldest_btpo_xact = InvalidTransactionId;
143+
cached_metad->btm_last_cleanup_num_heap_tuples = -1.0;
144+
}
145+
}
146+
108147
/*
109148
* _bt_update_meta_cleanup_info() -- Update cleanup-related information in
110149
* the metapage.
@@ -403,9 +442,7 @@ _bt_getroot(Relation rel, int access)
403442
/*
404443
* Cache the metapage data for next time
405444
*/
406-
rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
407-
sizeof(BTMetaPageData));
408-
memcpy(rel->rd_amcache, metad, sizeof(BTMetaPageData));
445+
_bt_cachemetadata(rel, metad);
409446

410447
/*
411448
* We are done with the metapage; arrange to release it via first
@@ -604,9 +641,7 @@ _bt_getrootheight(Relation rel)
604641
/*
605642
* Cache the metapage data for next time
606643
*/
607-
rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
608-
sizeof(BTMetaPageData));
609-
memcpy(rel->rd_amcache, metad, sizeof(BTMetaPageData));
644+
_bt_cachemetadata(rel, metad);
610645

611646
_bt_relbuf(rel, metabuf);
612647
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy