summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/page/bufpage.c37
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/storage/bufpage.h41
3 files changed, 66 insertions, 16 deletions
diff --git a/src/backend/storage/page/bufpage.c b/src/backend/storage/page/bufpage.c
index 8299f550d6e..b246b0afeb8 100644
--- a/src/backend/storage/page/bufpage.c
+++ b/src/backend/storage/page/bufpage.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/page/bufpage.c,v 1.71 2007/02/21 20:02:17 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/page/bufpage.c,v 1.72 2007/03/02 00:48:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -39,6 +39,7 @@ PageInit(Page page, Size pageSize, Size specialSize)
/* 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;
@@ -73,6 +74,7 @@ PageHeaderIsValid(PageHeader page)
/* Check normal case */
if (PageGetPageSize(page) == BLCKSZ &&
PageGetPageLayoutVersion(page) == PG_PAGE_LAYOUT_VERSION &&
+ (page->pd_flags & ~PD_VALID_FLAG_BITS) == 0 &&
page->pd_lower >= SizeOfPageHeaderData &&
page->pd_lower <= page->pd_upper &&
page->pd_upper <= page->pd_special &&
@@ -165,14 +167,27 @@ PageAddItem(Page page,
else
{
/* offsetNumber was not passed in, so find a free slot */
- /* look for "recyclable" (unused & deallocated) ItemId */
- for (offsetNumber = 1; offsetNumber < limit; offsetNumber++)
+ /* if no free slot, we'll put it at limit (1st open slot) */
+ if (PageHasFreeLinePointers(phdr))
+ {
+ /* look for "recyclable" (unused & deallocated) ItemId */
+ for (offsetNumber = 1; offsetNumber < limit; offsetNumber++)
+ {
+ itemId = PageGetItemId(phdr, offsetNumber);
+ if (!ItemIdIsUsed(itemId) && ItemIdGetLength(itemId) == 0)
+ break;
+ }
+ if (offsetNumber >= limit)
+ {
+ /* the hint is wrong, so reset it */
+ PageClearHasFreeLinePointers(phdr);
+ }
+ }
+ else
{
- itemId = PageGetItemId(phdr, offsetNumber);
- if (!ItemIdIsUsed(itemId) && ItemIdGetLength(itemId) == 0)
- break;
+ /* don't bother searching if hint says there's no free slot */
+ offsetNumber = limit;
}
- /* if no free slot, we'll put it at limit (1st open slot) */
}
if (offsetNumber > limit)
@@ -413,13 +428,19 @@ PageRepairFragmentation(Page page, OffsetNumber *unused)
pfree(itemidbase);
}
+ /* Set hint bit for PageAddItem */
+ if (nused < nline)
+ PageSetHasFreeLinePointers(page);
+ else
+ PageClearHasFreeLinePointers(page);
+
return (nline - nused);
}
/*
* PageGetFreeSpace
* Returns the size of the free (allocatable) space on a page,
- * deducted by the space needed for a new line pointer.
+ * reduced by the space needed for a new line pointer.
*/
Size
PageGetFreeSpace(Page page)
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 8c53a2df2ac..51263557f9e 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.388 2007/02/20 17:32:17 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.389 2007/03/02 00:48:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200702202
+#define CATALOG_VERSION_NO 200703011
#endif
diff --git a/src/include/storage/bufpage.h b/src/include/storage/bufpage.h
index 44ab48c9b8f..d38544e3f05 100644
--- a/src/include/storage/bufpage.h
+++ b/src/include/storage/bufpage.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/bufpage.h,v 1.71 2007/02/21 20:02:17 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/bufpage.h,v 1.72 2007/03/02 00:48:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -90,6 +90,7 @@ typedef uint16 LocationIndex;
*
* pd_lsn - identifies xlog record for last change to this page.
* pd_tli - ditto.
+ * pd_flags - flag bits.
* pd_lower - offset to start of free space.
* pd_upper - offset to end of free space.
* pd_special - offset to start of special space.
@@ -98,8 +99,9 @@ typedef uint16 LocationIndex;
* The LSN is used by the buffer manager to enforce the basic rule of WAL:
* "thou shalt write xlog before data". A dirty buffer cannot be dumped
* to disk until xlog has been flushed at least as far as the page's LSN.
- * We also store the TLI for identification purposes (it is not clear that
- * this is actually necessary, but it seems like a good idea).
+ * We also store the 16 least significant bits of the TLI for identification
+ * purposes (it is not clear that this is actually necessary, but it seems
+ * like a good idea).
*
* The page version number and page size are packed together into a single
* uint16 field. This is for historical reasons: before PostgreSQL 7.3,
@@ -119,7 +121,9 @@ typedef struct PageHeaderData
/* XXX LSN is member of *any* block, not only page-organized ones */
XLogRecPtr pd_lsn; /* LSN: next byte after last byte of xlog
* record for last change to this page */
- TimeLineID pd_tli; /* TLI of last change */
+ uint16 pd_tli; /* least significant bits of the TimeLineID
+ * containing the LSN */
+ uint16 pd_flags; /* flag bits, see below */
LocationIndex pd_lower; /* offset to start of free space */
LocationIndex pd_upper; /* offset to end of free space */
LocationIndex pd_special; /* offset to start of special space */
@@ -130,11 +134,24 @@ typedef struct PageHeaderData
typedef PageHeaderData *PageHeader;
/*
+ * pd_flags contains the following flag bits. Undefined bits are initialized
+ * to zero and may be used in the future.
+ *
+ * PD_HAS_FREE_LINES is set if there are any not-LP_USED line pointers before
+ * pd_lower. This should be considered a hint rather than the truth, since
+ * changes to it are not WAL-logged.
+ */
+#define PD_HAS_FREE_LINES 0x0001 /* are there any unused line pointers? */
+
+#define PD_VALID_FLAG_BITS 0x0001 /* OR of all valid pd_flags bits */
+
+/*
* Page layout version number 0 is for pre-7.3 Postgres releases.
* Releases 7.3 and 7.4 use 1, denoting a new HeapTupleHeader layout.
* Release 8.0 uses 2; it changed the HeapTupleHeader layout again.
* Release 8.1 uses 3; it redefined HeapTupleHeader infomask bits.
- * Release 8.3 uses 4; it changed the HeapTupleHeader layout again.
+ * Release 8.3 uses 4; it changed the HeapTupleHeader layout again, and
+ * added the pd_flags field (by stealing some bits from pd_tli).
*/
#define PG_PAGE_LAYOUT_VERSION 4
@@ -299,15 +316,27 @@ typedef PageHeaderData *PageHeader;
((((PageHeader) (page))->pd_lower - SizeOfPageHeaderData) \
/ sizeof(ItemIdData)))
+/*
+ * Additional macros for access to page headers
+ */
#define PageGetLSN(page) \
(((PageHeader) (page))->pd_lsn)
#define PageSetLSN(page, lsn) \
(((PageHeader) (page))->pd_lsn = (lsn))
+/* NOTE: only the 16 least significant bits are stored */
#define PageGetTLI(page) \
(((PageHeader) (page))->pd_tli)
#define PageSetTLI(page, tli) \
- (((PageHeader) (page))->pd_tli = (tli))
+ (((PageHeader) (page))->pd_tli = (uint16) (tli))
+
+#define PageHasFreeLinePointers(page) \
+ (((PageHeader) (page))->pd_flags & PD_HAS_FREE_LINES)
+#define PageSetHasFreeLinePointers(page) \
+ (((PageHeader) (page))->pd_flags |= PD_HAS_FREE_LINES)
+#define PageClearHasFreeLinePointers(page) \
+ (((PageHeader) (page))->pd_flags &= ~PD_HAS_FREE_LINES)
+
/* ----------------------------------------------------------------
* extern declarations