1*7f2fe78bSCy Schubert /*- 2*7f2fe78bSCy Schubert * Copyright (c) 1990, 1993, 1994 3*7f2fe78bSCy Schubert * The Regents of the University of California. All rights reserved. 4*7f2fe78bSCy Schubert * 5*7f2fe78bSCy Schubert * This code is derived from software contributed to Berkeley by 6*7f2fe78bSCy Schubert * Margo Seltzer. 7*7f2fe78bSCy Schubert * 8*7f2fe78bSCy Schubert * Redistribution and use in source and binary forms, with or without 9*7f2fe78bSCy Schubert * modification, are permitted provided that the following conditions 10*7f2fe78bSCy Schubert * are met: 11*7f2fe78bSCy Schubert * 1. Redistributions of source code must retain the above copyright 12*7f2fe78bSCy Schubert * notice, this list of conditions and the following disclaimer. 13*7f2fe78bSCy Schubert * 2. Redistributions in binary form must reproduce the above copyright 14*7f2fe78bSCy Schubert * notice, this list of conditions and the following disclaimer in the 15*7f2fe78bSCy Schubert * documentation and/or other materials provided with the distribution. 16*7f2fe78bSCy Schubert * 3. All advertising materials mentioning features or use of this software 17*7f2fe78bSCy Schubert * must display the following acknowledgement: 18*7f2fe78bSCy Schubert * This product includes software developed by the University of 19*7f2fe78bSCy Schubert * California, Berkeley and its contributors. 20*7f2fe78bSCy Schubert * 4. Neither the name of the University nor the names of its contributors 21*7f2fe78bSCy Schubert * may be used to endorse or promote products derived from this software 22*7f2fe78bSCy Schubert * without specific prior written permission. 23*7f2fe78bSCy Schubert * 24*7f2fe78bSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25*7f2fe78bSCy Schubert * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26*7f2fe78bSCy Schubert * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27*7f2fe78bSCy Schubert * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28*7f2fe78bSCy Schubert * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29*7f2fe78bSCy Schubert * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30*7f2fe78bSCy Schubert * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31*7f2fe78bSCy Schubert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32*7f2fe78bSCy Schubert * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33*7f2fe78bSCy Schubert * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34*7f2fe78bSCy Schubert * SUCH DAMAGE. 35*7f2fe78bSCy Schubert * 36*7f2fe78bSCy Schubert * @(#)page.h 8.4 (Berkeley) 11/7/95 37*7f2fe78bSCy Schubert */ 38*7f2fe78bSCy Schubert 39*7f2fe78bSCy Schubert #define HI_MASK 0xFFFF0000 40*7f2fe78bSCy Schubert #define LO_MASK (~HI_MASK) 41*7f2fe78bSCy Schubert 42*7f2fe78bSCy Schubert #define HI(N) ((u_int16_t)(((N) & HI_MASK) >> 16)) 43*7f2fe78bSCy Schubert #define LO(N) ((u_int16_t)((N) & LO_MASK)) 44*7f2fe78bSCy Schubert 45*7f2fe78bSCy Schubert /* Constants for big key page overhead information. */ 46*7f2fe78bSCy Schubert #define NUMSHORTS 0 47*7f2fe78bSCy Schubert #define KEYLEN 1 48*7f2fe78bSCy Schubert #define DATALEN 2 49*7f2fe78bSCy Schubert #define NEXTPAGE 3 50*7f2fe78bSCy Schubert 51*7f2fe78bSCy Schubert /* 52*7f2fe78bSCy Schubert * Hash pages store meta-data beginning at the top of the page (offset 0) 53*7f2fe78bSCy Schubert * and key/data values beginning at the bottom of the page (offset pagesize). 54*7f2fe78bSCy Schubert * Fields are always accessed via macros so that we can change the page 55*7f2fe78bSCy Schubert * format without too much pain. The only changes that will require massive 56*7f2fe78bSCy Schubert * code changes are if we no longer store key/data offsets next to each 57*7f2fe78bSCy Schubert * other (since we use that fact to compute key lengths). In the accessor 58*7f2fe78bSCy Schubert * macros below, P means a pointer to the page, I means an index of the 59*7f2fe78bSCy Schubert * particular entry being accessed. 60*7f2fe78bSCy Schubert * 61*7f2fe78bSCy Schubert * Hash base page format 62*7f2fe78bSCy Schubert * BYTE ITEM NBYTES TYPE ACCESSOR MACRO 63*7f2fe78bSCy Schubert * ---- ------------------ ------ -------- -------------- 64*7f2fe78bSCy Schubert * 0 previous page number 4 db_pgno_t PREV_PGNO(P) 65*7f2fe78bSCy Schubert * 4 next page number 4 db_pgno_t NEXT_PGNO(P) 66*7f2fe78bSCy Schubert * 8 # pairs on page 2 indx_t NUM_ENT(P) 67*7f2fe78bSCy Schubert * 10 page type 1 u_int8_t TYPE(P) 68*7f2fe78bSCy Schubert * 11 padding 1 u_int8_t none 69*7f2fe78bSCy Schubert * 12 highest free byte 2 indx_t OFFSET(P) 70*7f2fe78bSCy Schubert * 14 key offset 0 2 indx_t KEY_OFF(P, I) 71*7f2fe78bSCy Schubert * 16 data offset 0 2 indx_t DATA_OFF(P, I) 72*7f2fe78bSCy Schubert * 18 key offset 1 2 indx_t KEY_OFF(P, I) 73*7f2fe78bSCy Schubert * 20 data offset 1 2 indx_t DATA_OFF(P, I) 74*7f2fe78bSCy Schubert * ...etc... 75*7f2fe78bSCy Schubert */ 76*7f2fe78bSCy Schubert 77*7f2fe78bSCy Schubert /* Indices (in bytes) of the beginning of each of these entries */ 78*7f2fe78bSCy Schubert #define I_PREV_PGNO 0 79*7f2fe78bSCy Schubert #define I_NEXT_PGNO 4 80*7f2fe78bSCy Schubert #define I_ENTRIES 8 81*7f2fe78bSCy Schubert #define I_TYPE 10 82*7f2fe78bSCy Schubert #define I_HF_OFFSET 12 83*7f2fe78bSCy Schubert 84*7f2fe78bSCy Schubert /* Overhead is everything prior to the first key/data pair. */ 85*7f2fe78bSCy Schubert #define PAGE_OVERHEAD (I_HF_OFFSET + sizeof(indx_t)) 86*7f2fe78bSCy Schubert 87*7f2fe78bSCy Schubert /* To allocate a pair, we need room for one key offset and one data offset. */ 88*7f2fe78bSCy Schubert #define PAIR_OVERHEAD ((sizeof(indx_t) << 1)) 89*7f2fe78bSCy Schubert 90*7f2fe78bSCy Schubert /* Use this macro to extract a value of type T from page P at offset O. */ 91*7f2fe78bSCy Schubert #define REFERENCE(P, T, O) (((T *)(void *)((u_int8_t *)(void *)(P) + O))[0]) 92*7f2fe78bSCy Schubert 93*7f2fe78bSCy Schubert /* 94*7f2fe78bSCy Schubert * Use these macros to access fields on a page; P is a PAGE16 *. 95*7f2fe78bSCy Schubert */ 96*7f2fe78bSCy Schubert #define NUM_ENT(P) (REFERENCE((P), indx_t, I_ENTRIES)) 97*7f2fe78bSCy Schubert #define PREV_PGNO(P) (REFERENCE((P), db_pgno_t, I_PREV_PGNO)) 98*7f2fe78bSCy Schubert #define NEXT_PGNO(P) (REFERENCE((P), db_pgno_t, I_NEXT_PGNO)) 99*7f2fe78bSCy Schubert #define TYPE(P) (REFERENCE((P), u_int8_t, I_TYPE)) 100*7f2fe78bSCy Schubert #define OFFSET(P) (REFERENCE((P), indx_t, I_HF_OFFSET)) 101*7f2fe78bSCy Schubert /* 102*7f2fe78bSCy Schubert * We need to store a page's own address on each page (unlike the Btree 103*7f2fe78bSCy Schubert * access method which needs the previous page). We use the PREV_PGNO 104*7f2fe78bSCy Schubert * field to store our own page number. 105*7f2fe78bSCy Schubert */ 106*7f2fe78bSCy Schubert #define ADDR(P) (PREV_PGNO((P))) 107*7f2fe78bSCy Schubert 108*7f2fe78bSCy Schubert /* Extract key/data offsets and data for a given index. */ 109*7f2fe78bSCy Schubert #define DATA_OFF(P, N) \ 110*7f2fe78bSCy Schubert REFERENCE(P, indx_t, PAGE_OVERHEAD + N * PAIR_OVERHEAD + sizeof(indx_t)) 111*7f2fe78bSCy Schubert #define KEY_OFF(P, N) \ 112*7f2fe78bSCy Schubert REFERENCE(P, indx_t, PAGE_OVERHEAD + N * PAIR_OVERHEAD) 113*7f2fe78bSCy Schubert 114*7f2fe78bSCy Schubert #define KEY(P, N) (((PAGE8 *)(P)) + KEY_OFF((P), (N))) 115*7f2fe78bSCy Schubert #define DATA(P, N) (((PAGE8 *)(P)) + DATA_OFF((P), (N))) 116*7f2fe78bSCy Schubert 117*7f2fe78bSCy Schubert /* 118*7f2fe78bSCy Schubert * Macros used to compute various sizes on a page. 119*7f2fe78bSCy Schubert */ 120*7f2fe78bSCy Schubert #define PAIRSIZE(K, D) (PAIR_OVERHEAD + (K)->size + (D)->size) 121*7f2fe78bSCy Schubert #define BIGOVERHEAD (4 * sizeof(u_int16_t)) 122*7f2fe78bSCy Schubert #define KEYSIZE(K) (4 * sizeof(u_int16_t) + (K)->size); 123*7f2fe78bSCy Schubert #define OVFLSIZE (2 * sizeof(u_int16_t)) 124*7f2fe78bSCy Schubert #define BIGPAGEOVERHEAD (4 * sizeof(u_int16_t)) 125*7f2fe78bSCy Schubert #define BIGPAGEOFFSET 4 126*7f2fe78bSCy Schubert #define BIGPAGESIZE(P) ((P)->BSIZE - BIGPAGEOVERHEAD) 127*7f2fe78bSCy Schubert 128*7f2fe78bSCy Schubert #define PAGE_META(N) (((N) + 3) * sizeof(u_int16_t)) 129*7f2fe78bSCy Schubert #define MINFILL 0.75 130*7f2fe78bSCy Schubert #define ISBIG(N, P) (((N) > ((P)->hdr.bsize * MINFILL)) ? 1 : 0) 131*7f2fe78bSCy Schubert 132*7f2fe78bSCy Schubert #define ITEMSIZE(I) (sizeof(u_int16_t) + (I)->size) 133*7f2fe78bSCy Schubert 134*7f2fe78bSCy Schubert /* 135*7f2fe78bSCy Schubert * Big key/data pages use a different page format. They have a single 136*7f2fe78bSCy Schubert * key/data "pair" containing the length of the key and data instead 137*7f2fe78bSCy Schubert * of offsets. 138*7f2fe78bSCy Schubert */ 139*7f2fe78bSCy Schubert #define BIGKEYLEN(P) (KEY_OFF((P), 0)) 140*7f2fe78bSCy Schubert #define BIGDATALEN(P) (DATA_OFF((P), 0)) 141*7f2fe78bSCy Schubert #define BIGKEY(P) (((PAGE8 *)(P)) + PAGE_OVERHEAD + PAIR_OVERHEAD) 142*7f2fe78bSCy Schubert #define BIGDATA(P) \ 143*7f2fe78bSCy Schubert (((PAGE8 *)(P)) + PAGE_OVERHEAD + PAIR_OVERHEAD + KEY_OFF((P), 0)) 144*7f2fe78bSCy Schubert 145*7f2fe78bSCy Schubert 146*7f2fe78bSCy Schubert #define OVFLPAGE 0 147*7f2fe78bSCy Schubert #define BIGPAIR 0 148*7f2fe78bSCy Schubert #define INVALID_PGNO 0xFFFFFFFF 149*7f2fe78bSCy Schubert 150*7f2fe78bSCy Schubert typedef unsigned short PAGE16; 151*7f2fe78bSCy Schubert typedef unsigned char PAGE8; 152*7f2fe78bSCy Schubert 153*7f2fe78bSCy Schubert #define A_BUCKET 0 154*7f2fe78bSCy Schubert #define A_OVFL 1 155*7f2fe78bSCy Schubert #define A_BITMAP 2 156*7f2fe78bSCy Schubert #define A_RAW 4 157*7f2fe78bSCy Schubert #define A_HEADER 5 158*7f2fe78bSCy Schubert 159*7f2fe78bSCy Schubert #define PAIRFITS(P,K,D) ((PAIRSIZE((K),(D))) <= FREESPACE((P))) 160*7f2fe78bSCy Schubert #define BIGPAIRFITS(P) ((FREESPACE((P)) >= PAIR_OVERHEAD)) 161*7f2fe78bSCy Schubert /* 162*7f2fe78bSCy Schubert * Since these are all unsigned, we need to guarantee that we never go 163*7f2fe78bSCy Schubert * negative. Offset values are 0-based and overheads are one based (i.e. 164*7f2fe78bSCy Schubert * one byte of overhead is 1, not 0), so we need to convert OFFSETs to 165*7f2fe78bSCy Schubert * 1-based counting before subtraction. 166*7f2fe78bSCy Schubert */ 167*7f2fe78bSCy Schubert #define FREESPACE(P) \ 168*7f2fe78bSCy Schubert ((OFFSET((P)) + 1 - PAGE_OVERHEAD - (NUM_ENT((P)) * PAIR_OVERHEAD))) 169*7f2fe78bSCy Schubert 170*7f2fe78bSCy Schubert /* 171*7f2fe78bSCy Schubert * Overhead on header pages is just one word -- the length of the 172*7f2fe78bSCy Schubert * header info stored on that page. 173*7f2fe78bSCy Schubert */ 174*7f2fe78bSCy Schubert #define HEADER_OVERHEAD 4 175*7f2fe78bSCy Schubert 176*7f2fe78bSCy Schubert #define HASH_PAGE 2 177*7f2fe78bSCy Schubert #define HASH_BIGPAGE 3 178*7f2fe78bSCy Schubert #define HASH_OVFLPAGE 4 179