/* Like PageInit() in the backend */ static void page_init(Page page) { PageHeader p = (PageHeader) page; /* Make sure all fields of page are zero, as well as unused space */ MemSet(p, 0, BLCKSZ); /* p->pd_flags = 0; done by above MemSet */ p->pd_lower = SizeOfPageHeaderData; p->pd_upper = BLCKSZ; p->pd_special = BLCKSZ; /* no special area on heap pages */ PageSetPageSizeAndVersion(page, BLCKSZ, TARGET_PAGE_VERSION); /* p->pd_prune_xid = InvalidTransactionId; done by above MemSet */ }
/* * PageInit * Initializes the contents of a page. */ void PageInit(Page page, Size pageSize, Size specialSize) { PageHeader p = (PageHeader) page; specialSize = MAXALIGN(specialSize); Assert(pageSize == BLCKSZ); Assert(pageSize > specialSize + SizeOfPageHeaderData); /* Make sure all fields of page are zero, as well as unused space */ MemSet(p, 0, pageSize); /* p->pd_flags = 0; done by above MemSet */ p->pd_lower = SizeOfPageHeaderData; p->pd_upper = pageSize - specialSize; p->pd_special = pageSize - specialSize; PageSetPageSizeAndVersion(page, pageSize, PG_PAGE_LAYOUT_VERSION); }
static const char * convert_gpdb4_heap_page(char *page) { VERSION4_PageHeaderData *oldhdr; PageHeader newhdr; OffsetNumber off; OffsetNumber maxoff; if (PageGetPageSize(page) != BLCKSZ) return "invalid block size on page"; /* Can only convert from GPDB4 format */ if (PageGetPageLayoutVersion(page) != 4) return "invalid page version"; oldhdr = (VERSION4_PageHeaderData *) page; /* Other checks that PageHeaderIsValid() normally performs */ if (!((oldhdr->pd_flags & ~PD_VALID_FLAG_BITS) == 0 && oldhdr->pd_lower >= SizeOfPageHeaderData && oldhdr->pd_lower <= oldhdr->pd_upper && oldhdr->pd_upper <= oldhdr->pd_special && oldhdr->pd_special <= BLCKSZ && oldhdr->pd_special == MAXALIGN(oldhdr->pd_special))) return "invalid header"; /* * Ok, it's a valid heap page, from GPDB4. We know how to convert that! */ /* 1. pd_prune_xid was added to page header */ /* 2. Line pointer flags were changed */ /* 3. HEAP_COMPRESSED flag was removed */ /* 4. On-disk representation of numerics was changed */ /* * Also, money datatype was widened from 32 to 64 bits. (pg_upgrade * should've refused the upgrade) */ /* * First, check if there is enough space on the page, after we expand the header. */ oldhdr = (VERSION4_PageHeaderData *) page; newhdr = (PageHeader) page; /* * If there isn't enough space on this page for the new header field, relocate a tuple */ make_room(page); /* * There is space. Move the line pointers. We also convert the line pointer flags * while we're at it. Begin from end to beginning, so that we don't overwrite items * we haven't processed yet. */ maxoff = (oldhdr->pd_lower - VERSION4_SizeOfPageHeaderData) / sizeof(ItemIdData); /* PageGetMaxOffsetNumber */ for (off = maxoff; off >= 1; off--) { ItemIdData iid = oldhdr->pd_linp[off - 1]; /* PageGetItemId */ if (iid.lp_flags == VERSION4_LP_UNUSED) iid.lp_flags = LP_UNUSED; else if (iid.lp_flags == VERSION4_LP_USED) iid.lp_flags = LP_NORMAL; else { /* LP_DELETE and LP_USED were never used on heap pages. */ return "unexpected LP_DELETE or LP_DEAD line pointer on old-format heap page"; } newhdr->pd_linp[off - 1] = iid; } newhdr->pd_lower = (char *) &newhdr->pd_linp[maxoff] - (char *) page; /* Initialize the field that was added after version 4 format */ newhdr->pd_prune_xid = 0; /* * Ok, the page header and line pointers are in the new format now. Mangle * the tuples themselves */ for (off = 1; off <= maxoff; off++) { ItemId iid = PageGetItemId(page, off); /* we can use PageGetItemId now */ HeapTupleHeader htup; if (!ItemIdIsNormal(iid)) continue; htup = (HeapTupleHeader) PageGetItem(page, iid); convert_heaptuple(htup); } /* * Finally, change the version number. */ PageSetPageSizeAndVersion(page, BLCKSZ, TARGET_PAGE_VERSION); return NULL; }