Minor tweaking of index special-space definitions so that the various
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 9 Apr 2007 22:04:08 +0000 (22:04 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 9 Apr 2007 22:04:08 +0000 (22:04 +0000)
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.

src/backend/access/gist/gistutil.c
src/backend/access/hash/hashovfl.c
src/backend/access/hash/hashpage.c
src/backend/access/nbtree/nbtutils.c
src/include/access/gin.h
src/include/access/gist.h
src/include/access/hash.h
src/include/access/nbtree.h
src/include/catalog/catversion.h

index 0c10fc49cc771cae8b6eb3249b0e0d7a88631d66..c09e9249ea3b1e39233864a77a7dc6669eee47f9 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *                     $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.21 2007/01/05 22:19:22 momjian Exp $
+ *                     $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.22 2007/04/09 22:03:57 tgl Exp $
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
@@ -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;
 }
 
 /*
index abd9972ced641072e40c93e29f512bba4fafdbd3..2a844f40d42f71dbf0cf3fa28ecf7789d20f8ff5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.54 2007/01/05 22:19:22 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.55 2007/04/09 22:03:57 tgl Exp $
  *
  * NOTES
  *       Overflow pages look like ordinary relation pages.
@@ -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);
index 97eb3c379ee62e98ebfebbcd597f0ed8bedca021..c368bcd05d2db6a906f2179f54d5db59efd247ba 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.64 2007/01/29 23:22:59 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.65 2007/04/09 22:03:57 tgl Exp $
  *
  * NOTES
  *       Postgres hash pages look like ordinary relation pages.  The opaque
@@ -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
index b5e7686303e82fc41b5e3cc5c2f487b649ed03f0..33c0ee00823c1c612b45fe5fa42cbcd8f97fb9d0 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.84 2007/04/06 22:33:42 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.85 2007/04/09 22:04:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -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++)
index 80f237499681cdca6c4cbb7592784550992f353f..4e4259363dd8b7d42c440744f210337a7a5abbfe 100644 (file)
@@ -3,7 +3,7 @@
  *       header file for postgres inverted index access method implementation.
  *
  *     Copyright (c) 2006, PostgreSQL Global Development Group
- *     $PostgreSQL: pgsql/src/include/access/gin.h,v 1.10 2007/01/31 15:09:45 teodor Exp $
+ *     $PostgreSQL: pgsql/src/include/access/gin.h,v 1.11 2007/04/09 22:04:04 tgl Exp $
  *--------------------------------------------------------------------------
  */
 
 #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))
index 52d3a2fe1a0cc411839e691cdf1712fedc0f30a7..eab6a01bfd5e1d46b2cf0b4781cf349707bc2e88 100644 (file)
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/gist.h,v 1.57 2007/01/05 22:19:50 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/gist.h,v 1.58 2007/04/09 22:04:05 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 /*
  * 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',
index 7ba8fbfc2f292d34f9e99e470e5f860f19346c3b..114a684dbc557a96223bf00c4caebca8cc71a07f 100644 (file)
@@ -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/access/hash.h,v 1.77 2007/04/02 03:49:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.78 2007/04/09 22:04:05 tgl Exp $
  *
  * NOTES
  *             modeled after Margo Seltzer's hash implementation for unix.
@@ -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.
index ff78cf1f71a582f1e42953dd019971233e03a11c..53e10c80e8dc6885755b2be3484207584c571fef 100644 (file)
@@ -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/access/nbtree.h,v 1.111 2007/02/08 05:05:53 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.112 2007/04/09 22:04:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -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.
index f18415a4fd7ac2feb954e38a0abdd6472471fe41..7b2c9661010b3ef041d169730416d2fe6122617e 100644 (file)
@@ -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.401 2007/04/06 22:33:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.402 2007/04/09 22:04:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200704061
+#define CATALOG_VERSION_NO     200704091
 
 #endif