summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2007-04-09 22:04:08 +0000
committerTom Lane2007-04-09 22:04:08 +0000
commit5dcf7d8c357482ab118c704d464a3dff27a1fd55 (patch)
tree89b58ed5ba3fd55e505905cfcf2d7494385bbaa3
parent25f3eb514b4f39c902161277e2dfd2a924deb860 (diff)
Minor tweaking of index special-space definitions so that the various
index types can be reliably distinguished by examining the special space on an index page. Per my earlier proposal, plus the realization that there's no need for btree's vacuum cycle ID to cycle through every possible 16-bit value. Restricting its range a little costs nearly nothing and eliminates the possibility of collisions. Memo to self: remember to make bitmap indexes play along with this scheme, assuming that patch ever gets accepted.
-rw-r--r--src/backend/access/gist/gistutil.c5
-rw-r--r--src/backend/access/hash/hashovfl.c4
-rw-r--r--src/backend/access/hash/hashpage.c6
-rw-r--r--src/backend/access/nbtree/nbtutils.c12
-rw-r--r--src/include/access/gin.h41
-rw-r--r--src/include/access/gist.h23
-rw-r--r--src/include/access/hash.h18
-rw-r--r--src/include/access/nbtree.h13
-rw-r--r--src/include/catalog/catversion.h2
9 files changed, 69 insertions, 55 deletions
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index 307be16d5d..e658d05928 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -559,10 +559,11 @@ GISTInitBuffer(Buffer b, uint32 f)
PageInit(page, pageSize, sizeof(GISTPageOpaqueData));
opaque = GistPageGetOpaque(page);
- opaque->flags = f;
- opaque->rightlink = InvalidBlockNumber;
/* page was already zeroed by PageInit, so this is not needed: */
/* memset(&(opaque->nsn), 0, sizeof(GistNSN)); */
+ opaque->rightlink = InvalidBlockNumber;
+ opaque->flags = f;
+ opaque->gist_page_id = GIST_PAGE_ID;
}
/*
diff --git a/src/backend/access/hash/hashovfl.c b/src/backend/access/hash/hashovfl.c
index a987ffbc3f..f37ce3c093 100644
--- a/src/backend/access/hash/hashovfl.c
+++ b/src/backend/access/hash/hashovfl.c
@@ -141,7 +141,7 @@ _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf)
ovflopaque->hasho_nextblkno = InvalidBlockNumber;
ovflopaque->hasho_bucket = pageopaque->hasho_bucket;
ovflopaque->hasho_flag = LH_OVERFLOW_PAGE;
- ovflopaque->hasho_filler = HASHO_FILL;
+ ovflopaque->hasho_page_id = HASHO_PAGE_ID;
MarkBufferDirty(ovflbuf);
@@ -529,7 +529,7 @@ _hash_initbitmap(Relation rel, HashMetaPage metap, BlockNumber blkno)
op->hasho_nextblkno = InvalidBlockNumber;
op->hasho_bucket = -1;
op->hasho_flag = LH_BITMAP_PAGE;
- op->hasho_filler = HASHO_FILL;
+ op->hasho_page_id = HASHO_PAGE_ID;
/* set all of the bits to 1 */
freep = HashPageGetBitmap(pg);
diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c
index cc181d3095..baae1f08de 100644
--- a/src/backend/access/hash/hashpage.c
+++ b/src/backend/access/hash/hashpage.c
@@ -252,7 +252,7 @@ _hash_metapinit(Relation rel)
pageopaque->hasho_nextblkno = InvalidBlockNumber;
pageopaque->hasho_bucket = -1;
pageopaque->hasho_flag = LH_META_PAGE;
- pageopaque->hasho_filler = HASHO_FILL;
+ pageopaque->hasho_page_id = HASHO_PAGE_ID;
metap = (HashMetaPage) pg;
@@ -310,7 +310,7 @@ _hash_metapinit(Relation rel)
pageopaque->hasho_nextblkno = InvalidBlockNumber;
pageopaque->hasho_bucket = i;
pageopaque->hasho_flag = LH_BUCKET_PAGE;
- pageopaque->hasho_filler = HASHO_FILL;
+ pageopaque->hasho_page_id = HASHO_PAGE_ID;
_hash_wrtbuf(rel, buf);
}
@@ -654,7 +654,7 @@ _hash_splitbucket(Relation rel,
nopaque->hasho_nextblkno = InvalidBlockNumber;
nopaque->hasho_bucket = nbucket;
nopaque->hasho_flag = LH_BUCKET_PAGE;
- nopaque->hasho_filler = HASHO_FILL;
+ nopaque->hasho_page_id = HASHO_PAGE_ID;
/*
* Partition the tuples in the old bucket between the old bucket and the
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index d57b63908a..d6c1ee501c 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -1263,11 +1263,13 @@ _bt_start_vacuum(Relation rel)
LWLockAcquire(BtreeVacuumLock, LW_EXCLUSIVE);
- /* Assign the next cycle ID, being careful to avoid zero */
- do
- {
- result = ++(btvacinfo->cycle_ctr);
- } while (result == 0);
+ /*
+ * Assign the next cycle ID, being careful to avoid zero as well as
+ * the reserved high values.
+ */
+ result = ++(btvacinfo->cycle_ctr);
+ if (result == 0 || result > MAX_BT_CYCLE_ID)
+ result = btvacinfo->cycle_ctr = 1;
/* Let's just make sure there's no entry already for this index */
for (i = 0; i < btvacinfo->num_vacuums; i++)
diff --git a/src/include/access/gin.h b/src/include/access/gin.h
index 3ba4d88114..b1ff1cf57c 100644
--- a/src/include/access/gin.h
+++ b/src/include/access/gin.h
@@ -31,41 +31,27 @@
#define GIN_CONSISTENT_PROC 4
#define GINNProcs 4
-typedef XLogRecPtr GinNSN;
-
/*
* Page opaque data in a inverted index page.
+ *
+ * Note: GIN does not include a page ID word as do the other index types.
+ * This is OK because the opaque data is only 8 bytes and so can be reliably
+ * distinguished by size. Revisit this if the size ever increases.
*/
typedef struct GinPageOpaqueData
{
- uint16 flags;
+ BlockNumber rightlink; /* next page if any */
OffsetNumber maxoff; /* number entries on GIN_DATA page: number of
* heap ItemPointer on GIN_DATA|GIN_LEAF page
* and number of records on GIN_DATA &
* ~GIN_LEAF page */
- BlockNumber rightlink;
+ uint16 flags; /* see bit definitions below */
} GinPageOpaqueData;
typedef GinPageOpaqueData *GinPageOpaque;
#define GIN_ROOT_BLKNO (0)
-typedef struct
-{
- BlockIdData child_blkno; /* use it instead of BlockNumber to save space
- * on page */
- ItemPointerData key;
-} PostingItem;
-
-#define PostingItemGetBlockNumber(pointer) \
- BlockIdGetBlockNumber(&(pointer)->child_blkno)
-
-#define PostingItemSetBlockNumber(pointer, blockNumber) \
- BlockIdSet(&((pointer)->child_blkno), (blockNumber))
-
-/*
- * Page opaque data in a inverted index page.
- */
#define GIN_DATA (1 << 0)
#define GIN_LEAF (1 << 1)
#define GIN_DELETED (1 << 2)
@@ -98,8 +84,21 @@ typedef struct
#define GinItemPointerGetOffsetNumber(pointer) \
((pointer)->ip_posid)
+typedef struct
+{
+ BlockIdData child_blkno; /* use it instead of BlockNumber to save space
+ * on page */
+ ItemPointerData key;
+} PostingItem;
+
+#define PostingItemGetBlockNumber(pointer) \
+ BlockIdGetBlockNumber(&(pointer)->child_blkno)
+
+#define PostingItemSetBlockNumber(pointer, blockNumber) \
+ BlockIdSet(&((pointer)->child_blkno), (blockNumber))
+
/*
- * Support work on IndexTuuple on leaf pages
+ * Support work on IndexTuple on leaf pages
*/
#define GinGetNPosting(itup) GinItemPointerGetOffsetNumber(&(itup)->t_tid)
#define GinSetNPosting(itup,n) ItemPointerSetOffsetNumber(&(itup)->t_tid,(n))
diff --git a/src/include/access/gist.h b/src/include/access/gist.h
index 9d794ef094..f648056b90 100644
--- a/src/include/access/gist.h
+++ b/src/include/access/gist.h
@@ -56,26 +56,31 @@
/*
* Page opaque data in a GiST index page.
*/
-#define F_LEAF (1 << 0)
-#define F_DELETED (1 << 1)
+#define F_LEAF (1 << 0)
+#define F_DELETED (1 << 1)
#define F_TUPLES_DELETED (1 << 2)
typedef XLogRecPtr GistNSN;
typedef struct GISTPageOpaqueData
{
- uint32 flags; /* 29 bits are unused for now */
- BlockNumber rightlink;
-
- /*
- * the only meaning - change this value if page split.
- */
- GistNSN nsn;
+ GistNSN nsn; /* this value must change on page split */
+ BlockNumber rightlink; /* next page if any */
+ uint16 flags; /* see bit definitions above */
+ uint16 gist_page_id; /* for identification of GiST indexes */
} GISTPageOpaqueData;
typedef GISTPageOpaqueData *GISTPageOpaque;
/*
+ * The page ID is for the convenience of pg_filedump and similar utilities,
+ * which otherwise would have a hard time telling pages of different index
+ * types apart. It should be the last 2 bytes on the page. This is more or
+ * less "free" due to alignment considerations.
+ */
+#define GIST_PAGE_ID 0xFF81
+
+/*
* This is the Split Vector to be returned by the PickSplit method.
* PickSplit should check spl_(r|l)datum_exists. If it is 'true',
* that corresponding spl_(r|l)datum already defined and
diff --git a/src/include/access/hash.h b/src/include/access/hash.h
index 8dc65a92d1..99716912fc 100644
--- a/src/include/access/hash.h
+++ b/src/include/access/hash.h
@@ -56,20 +56,18 @@ typedef struct HashPageOpaqueData
BlockNumber hasho_nextblkno; /* next ovfl blkno */
Bucket hasho_bucket; /* bucket number this pg belongs to */
uint16 hasho_flag; /* page type code, see above */
- uint16 hasho_filler; /* available for future use */
-
- /*
- * We presently set hasho_filler to HASHO_FILL (0x1234); this is for the
- * convenience of pg_filedump, which otherwise would have a hard time
- * telling HashPageOpaqueData from BTPageOpaqueData. If we ever need that
- * space for some other purpose, pg_filedump will have to find another
- * way.
- */
+ uint16 hasho_page_id; /* for identification of hash indexes */
} HashPageOpaqueData;
typedef HashPageOpaqueData *HashPageOpaque;
-#define HASHO_FILL 0x1234
+/*
+ * The page ID is for the convenience of pg_filedump and similar utilities,
+ * which otherwise would have a hard time telling pages of different index
+ * types apart. It should be the last 2 bytes on the page. This is more or
+ * less "free" due to alignment considerations.
+ */
+#define HASHO_PAGE_ID 0xFF80
/*
* HashScanOpaqueData is private state for a hash index scan.
diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h
index d3f836cd5a..77b1c3682a 100644
--- a/src/include/access/nbtree.h
+++ b/src/include/access/nbtree.h
@@ -40,8 +40,8 @@ typedef uint16 BTCycleId;
* stored into both halves of the split page. (If VACUUM is not running,
* both pages receive zero cycleids.) This allows VACUUM to detect whether
* a page was split since it started, with a small probability of false match
- * if the page was last split some exact multiple of 65536 VACUUMs ago.
- * Also, during a split, the BTP_SPLIT_END flag is cleared in the left
+ * if the page was last split some exact multiple of MAX_BT_CYCLE_ID VACUUMs
+ * ago. Also, during a split, the BTP_SPLIT_END flag is cleared in the left
* (original) page, and set in the right page, but only if the next page
* to its right has a different cycleid.
*
@@ -73,6 +73,15 @@ typedef BTPageOpaqueData *BTPageOpaque;
#define BTP_SPLIT_END (1 << 5) /* rightmost page of split group */
#define BTP_HAS_GARBAGE (1 << 6) /* page has LP_DELETEd tuples */
+/*
+ * The max allowed value of a cycle ID is a bit less than 64K. This is
+ * for convenience of pg_filedump and similar utilities: we want to use
+ * the last 2 bytes of special space as an index type indicator, and
+ * restricting cycle ID lets btree use that space for vacuum cycle IDs
+ * while still allowing index type to be identified.
+ */
+#define MAX_BT_CYCLE_ID 0xFF7F
+
/*
* The Meta page is always the first page in the btree index.
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index f956d96ba2..de707035e9 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200704061
+#define CATALOG_VERSION_NO 200704091
#endif