📄 db_page.h
字号:
/* * Initialize a page. * * !!! * Don't modify the page's LSN, code depends on it being unchanged after a * P_INIT call. */#define P_INIT(pg, pg_size, n, pg_prev, pg_next, btl, pg_type) do { \ PGNO(pg) = n; \ PREV_PGNO(pg) = pg_prev; \ NEXT_PGNO(pg) = pg_next; \ NUM_ENT(pg) = 0; \ HOFFSET(pg) = pg_size; \ LEVEL(pg) = btl; \ TYPE(pg) = pg_type; \} while (0)/* Page header length (offset to first index). */#define P_OVERHEAD(dbp) P_TO_UINT16(P_INP(dbp, 0))/* First free byte. */#define LOFFSET(dbp, pg) \ (P_OVERHEAD(dbp) + NUM_ENT(pg) * sizeof(db_indx_t))/* Free space on a regular page. */#define P_FREESPACE(dbp, pg) (HOFFSET(pg) - LOFFSET(dbp, pg))/* Get a pointer to the bytes at a specific index. */#define P_ENTRY(dbp, pg, indx) ((u_int8_t *)pg + P_INP(dbp, pg)[indx])/************************************************************************ OVERFLOW PAGE LAYOUT ************************************************************************//* * Overflow items are referenced by HOFFPAGE and BOVERFLOW structures, which * store a page number (the first page of the overflow item) and a length * (the total length of the overflow item). The overflow item consists of * some number of overflow pages, linked by the next_pgno field of the page. * A next_pgno field of PGNO_INVALID flags the end of the overflow item. * * Overflow page overloads: * The amount of overflow data stored on each page is stored in the * hf_offset field. * * The implementation reference counts overflow items as it's possible * for them to be promoted onto btree internal pages. The reference * count is stored in the entries field. */#define OV_LEN(p) (((PAGE *)p)->hf_offset)#define OV_REF(p) (((PAGE *)p)->entries)/* Maximum number of bytes that you can put on an overflow page. */#define P_MAXSPACE(dbp, psize) ((psize) - P_OVERHEAD(dbp))/* Free space on an overflow page. */#define P_OVFLSPACE(dbp, psize, pg) (P_MAXSPACE(dbp, psize) - HOFFSET(pg))/************************************************************************ HASH PAGE LAYOUT ************************************************************************//* Each index references a group of bytes on the page. */#define H_KEYDATA 1 /* Key/data item. */#define H_DUPLICATE 2 /* Duplicate key/data item. */#define H_OFFPAGE 3 /* Overflow key/data item. */#define H_OFFDUP 4 /* Overflow page of duplicates. *//* * !!! * Items on hash pages are (potentially) unaligned, so we can never cast the * (page + offset) pointer to an HKEYDATA, HOFFPAGE or HOFFDUP structure, as * we do with B+tree on-page structures. Because we frequently want the type * field, it requires no alignment, and it's in the same location in all three * structures, there's a pair of macros. */#define HPAGE_PTYPE(p) (*(u_int8_t *)p)#define HPAGE_TYPE(dbp, pg, indx) (*P_ENTRY(dbp, pg, indx))/* * The first and second types are H_KEYDATA and H_DUPLICATE, represented * by the HKEYDATA structure: * * +-----------------------------------+ * | type | key/data ... | * +-----------------------------------+ * * For duplicates, the data field encodes duplicate elements in the data * field: * * +---------------------------------------------------------------+ * | type | len1 | element1 | len1 | len2 | element2 | len2 | * +---------------------------------------------------------------+ * * Thus, by keeping track of the offset in the element, we can do both * backward and forward traversal. */typedef struct _hkeydata { u_int8_t type; /* 00: Page type. */ u_int8_t data[1]; /* Variable length key/data item. */} HKEYDATA;#define HKEYDATA_DATA(p) (((u_int8_t *)p) + SSZA(HKEYDATA, data))/* * The length of any HKEYDATA item. Note that indx is an element index, * not a PAIR index. */#define LEN_HITEM(dbp, pg, pgsize, indx) \ (((indx) == 0 ? pgsize : \ (P_INP(dbp, pg)[indx - 1])) - (P_INP(dbp, pg)[indx]))#define LEN_HKEYDATA(dbp, pg, psize, indx) \ (db_indx_t)(LEN_HITEM(dbp, pg, psize, indx) - HKEYDATA_SIZE(0))/* * Page space required to add a new HKEYDATA item to the page, with and * without the index value. */#define HKEYDATA_SIZE(len) \ ((len) + SSZA(HKEYDATA, data))#define HKEYDATA_PSIZE(len) \ (HKEYDATA_SIZE(len) + sizeof(db_indx_t))/* Put a HKEYDATA item at the location referenced by a page entry. */#define PUT_HKEYDATA(pe, kd, len, type) { \ ((HKEYDATA *)pe)->type = type; \ memcpy((u_int8_t *)pe + sizeof(u_int8_t), kd, len); \}/* * Macros the describe the page layout in terms of key-data pairs. */#define H_NUMPAIRS(pg) (NUM_ENT(pg) / 2)#define H_KEYINDEX(indx) (indx)#define H_DATAINDEX(indx) ((indx) + 1)#define H_PAIRKEY(dbp, pg, indx) P_ENTRY(dbp, pg, H_KEYINDEX(indx))#define H_PAIRDATA(dbp, pg, indx) P_ENTRY(dbp, pg, H_DATAINDEX(indx))#define H_PAIRSIZE(dbp, pg, psize, indx) \ (LEN_HITEM(dbp, pg, psize, H_KEYINDEX(indx)) + \ LEN_HITEM(dbp, pg, psize, H_DATAINDEX(indx)))#define LEN_HDATA(dbp, p, psize, indx) \ LEN_HKEYDATA(dbp, p, psize, H_DATAINDEX(indx))#define LEN_HKEY(dbp, p, psize, indx) \ LEN_HKEYDATA(dbp, p, psize, H_KEYINDEX(indx))/* * The third type is the H_OFFPAGE, represented by the HOFFPAGE structure: */typedef struct _hoffpage { u_int8_t type; /* 00: Page type and delete flag. */ u_int8_t unused[3]; /* 01-03: Padding, unused. */ db_pgno_t pgno; /* 04-07: Offpage page number. */ u_int32_t tlen; /* 08-11: Total length of item. */} HOFFPAGE;#define HOFFPAGE_PGNO(p) (((u_int8_t *)p) + SSZ(HOFFPAGE, pgno))#define HOFFPAGE_TLEN(p) (((u_int8_t *)p) + SSZ(HOFFPAGE, tlen))/* * Page space required to add a new HOFFPAGE item to the page, with and * without the index value. */#define HOFFPAGE_SIZE (sizeof(HOFFPAGE))#define HOFFPAGE_PSIZE (HOFFPAGE_SIZE + sizeof(db_indx_t))/* * The fourth type is H_OFFDUP represented by the HOFFDUP structure: */typedef struct _hoffdup { u_int8_t type; /* 00: Page type and delete flag. */ u_int8_t unused[3]; /* 01-03: Padding, unused. */ db_pgno_t pgno; /* 04-07: Offpage page number. */} HOFFDUP;#define HOFFDUP_PGNO(p) (((u_int8_t *)p) + SSZ(HOFFDUP, pgno))/* * Page space required to add a new HOFFDUP item to the page, with and * without the index value. */#define HOFFDUP_SIZE (sizeof(HOFFDUP))/************************************************************************ BTREE PAGE LAYOUT ************************************************************************//* Each index references a group of bytes on the page. */#define B_KEYDATA 1 /* Key/data item. */#define B_DUPLICATE 2 /* Duplicate key/data item. */#define B_OVERFLOW 3 /* Overflow key/data item. *//* * We have to store a deleted entry flag in the page. The reason is complex, * but the simple version is that we can't delete on-page items referenced by * a cursor -- the return order of subsequent insertions might be wrong. The * delete flag is an overload of the top bit of the type byte. */#define B_DELETE (0x80)#define B_DCLR(t) (t) &= ~B_DELETE#define B_DSET(t) (t) |= B_DELETE#define B_DISSET(t) ((t) & B_DELETE)#define B_TYPE(t) ((t) & ~B_DELETE)#define B_TSET(t, type, deleted) { \ (t) = (type); \ if (deleted) \ B_DSET(t); \}/* * The first type is B_KEYDATA, represented by the BKEYDATA structure: */typedef struct _bkeydata { db_indx_t len; /* 00-01: Key/data item length. */ u_int8_t type; /* 02: Page type AND DELETE FLAG. */ u_int8_t data[1]; /* Variable length key/data item. */} BKEYDATA;/* Get a BKEYDATA item for a specific index. */#define GET_BKEYDATA(dbp, pg, indx) \ ((BKEYDATA *)P_ENTRY(dbp, pg, indx))/* * Page space required to add a new BKEYDATA item to the page, with and * without the index value. */#define BKEYDATA_SIZE(len) \ ALIGN((len) + SSZA(BKEYDATA, data), sizeof(u_int32_t))#define BKEYDATA_PSIZE(len) \ (BKEYDATA_SIZE(len) + sizeof(db_indx_t))/* * The second and third types are B_DUPLICATE and B_OVERFLOW, represented * by the BOVERFLOW structure. */typedef struct _boverflow { db_indx_t unused1; /* 00-01: Padding, unused. */ u_int8_t type; /* 02: Page type AND DELETE FLAG. */ u_int8_t unused2; /* 03: Padding, unused. */ db_pgno_t pgno; /* 04-07: Next page number. */ u_int32_t tlen; /* 08-11: Total length of item. */} BOVERFLOW;/* Get a BOVERFLOW item for a specific index. */#define GET_BOVERFLOW(dbp, pg, indx) \ ((BOVERFLOW *)P_ENTRY(dbp, pg, indx))/* * Page space required to add a new BOVERFLOW item to the page, with and * without the index value. The (u_int16_t) cast avoids warnings: ALIGN * casts to db_align_t, the cast converts it to a small integral type so * we don't get complaints when we assign the final result to an integral * type smaller than db_align_t. */#define BOVERFLOW_SIZE \ ((u_int16_t)ALIGN(sizeof(BOVERFLOW), sizeof(u_int32_t)))#define BOVERFLOW_PSIZE \ (BOVERFLOW_SIZE + sizeof(db_indx_t))/* * Btree leaf and hash page layouts group indices in sets of two, one for the * key and one for the data. Everything else does it in sets of one to save * space. Use the following macros so that it's real obvious what's going on. */#define O_INDX 1#define P_INDX 2/************************************************************************ BTREE INTERNAL PAGE LAYOUT ************************************************************************//* * Btree internal entry. */typedef struct _binternal { db_indx_t len; /* 00-01: Key/data item length. */ u_int8_t type; /* 02: Page type AND DELETE FLAG. */ u_int8_t unused; /* 03: Padding, unused. */ db_pgno_t pgno; /* 04-07: Page number of referenced page. */ db_recno_t nrecs; /* 08-11: Subtree record count. */ u_int8_t data[1]; /* Variable length key item. */} BINTERNAL;/* Get a BINTERNAL item for a specific index. */#define GET_BINTERNAL(dbp, pg, indx) \ ((BINTERNAL *)P_ENTRY(dbp, pg, indx))/* * Page space required to add a new BINTERNAL item to the page, with and * without the index value. */#define BINTERNAL_SIZE(len) \ ALIGN((len) + SSZA(BINTERNAL, data), sizeof(u_int32_t))#define BINTERNAL_PSIZE(len) \ (BINTERNAL_SIZE(len) + sizeof(db_indx_t))/************************************************************************ RECNO INTERNAL PAGE LAYOUT ************************************************************************//* * The recno internal entry. */typedef struct _rinternal { db_pgno_t pgno; /* 00-03: Page number of referenced page. */ db_recno_t nrecs; /* 04-07: Subtree record count. */} RINTERNAL;/* Get a RINTERNAL item for a specific index. */#define GET_RINTERNAL(dbp, pg, indx) \ ((RINTERNAL *)P_ENTRY(dbp, pg, indx))/* * Page space required to add a new RINTERNAL item to the page, with and * without the index value. */#define RINTERNAL_SIZE \ ALIGN(sizeof(RINTERNAL), sizeof(u_int32_t))#define RINTERNAL_PSIZE \ (RINTERNAL_SIZE + sizeof(db_indx_t))#if defined(__cplusplus)}#endif#endif /* !_DB_PAGE_H_ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -