diff -u -r -N bdb185/db.1.85/PORT/aix.3.2/include/db.h bdb186/db.1.86/PORT/aix.3.2/include/db.h --- bdb185/db.1.85/PORT/aix.3.2/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/aix.3.2/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/aix.3.2/include/mpool.h bdb186/db.1.86/PORT/aix.3.2/include/mpool.h --- bdb185/db.1.85/PORT/aix.3.2/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/aix.3.2/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/aix.3.2/sys/db.h bdb186/db.1.86/PORT/aix.3.2/sys/db.h --- bdb185/db.1.85/PORT/aix.3.2/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/aix.3.2/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/aix.3.2/sys/mpool.h bdb186/db.1.86/PORT/aix.3.2/sys/mpool.h --- bdb185/db.1.85/PORT/aix.3.2/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/aix.3.2/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/bsd.4.4/include/db.h bdb186/db.1.86/PORT/bsd.4.4/include/db.h --- bdb185/db.1.85/PORT/bsd.4.4/include/db.h 1994-06-16 15:08:53.000000000 -0700 +++ bdb186/db.1.86/PORT/bsd.4.4/include/db.h 1997-01-04 11:30:22.000000000 -0800 @@ -132,7 +132,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/bsd.4.4/include/mpool.h bdb186/db.1.86/PORT/bsd.4.4/include/mpool.h --- bdb185/db.1.85/PORT/bsd.4.4/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/bsd.4.4/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/bsd.4.4/sys/db.h bdb186/db.1.86/PORT/bsd.4.4/sys/db.h --- bdb185/db.1.85/PORT/bsd.4.4/sys/db.h 1994-06-16 15:08:53.000000000 -0700 +++ bdb186/db.1.86/PORT/bsd.4.4/sys/db.h 1997-01-04 11:30:22.000000000 -0800 @@ -132,7 +132,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/bsd.4.4/sys/mpool.h bdb186/db.1.86/PORT/bsd.4.4/sys/mpool.h --- bdb185/db.1.85/PORT/bsd.4.4/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/bsd.4.4/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/bsdi.1.0/include/db.h bdb186/db.1.86/PORT/bsdi.1.0/include/db.h --- bdb185/db.1.85/PORT/bsdi.1.0/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/bsdi.1.0/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/bsdi.1.0/include/mpool.h bdb186/db.1.86/PORT/bsdi.1.0/include/mpool.h --- bdb185/db.1.85/PORT/bsdi.1.0/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/bsdi.1.0/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/bsdi.1.0/sys/db.h bdb186/db.1.86/PORT/bsdi.1.0/sys/db.h --- bdb185/db.1.85/PORT/bsdi.1.0/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/bsdi.1.0/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/bsdi.1.0/sys/mpool.h bdb186/db.1.86/PORT/bsdi.1.0/sys/mpool.h --- bdb185/db.1.85/PORT/bsdi.1.0/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/bsdi.1.0/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/dgux.5.4/include/db.h bdb186/db.1.86/PORT/dgux.5.4/include/db.h --- bdb185/db.1.85/PORT/dgux.5.4/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/dgux.5.4/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/dgux.5.4/include/mpool.h bdb186/db.1.86/PORT/dgux.5.4/include/mpool.h --- bdb185/db.1.85/PORT/dgux.5.4/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/dgux.5.4/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/dgux.5.4/sys/db.h bdb186/db.1.86/PORT/dgux.5.4/sys/db.h --- bdb185/db.1.85/PORT/dgux.5.4/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/dgux.5.4/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/dgux.5.4/sys/mpool.h bdb186/db.1.86/PORT/dgux.5.4/sys/mpool.h --- bdb185/db.1.85/PORT/dgux.5.4/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/dgux.5.4/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/hpux.8.07/include/db.h bdb186/db.1.86/PORT/hpux.8.07/include/db.h --- bdb185/db.1.85/PORT/hpux.8.07/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/hpux.8.07/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/hpux.8.07/include/mpool.h bdb186/db.1.86/PORT/hpux.8.07/include/mpool.h --- bdb185/db.1.85/PORT/hpux.8.07/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/hpux.8.07/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/hpux.8.07/sys/db.h bdb186/db.1.86/PORT/hpux.8.07/sys/db.h --- bdb185/db.1.85/PORT/hpux.8.07/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/hpux.8.07/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/hpux.8.07/sys/mpool.h bdb186/db.1.86/PORT/hpux.8.07/sys/mpool.h --- bdb185/db.1.85/PORT/hpux.8.07/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/hpux.8.07/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/hpux.9.01/include/db.h bdb186/db.1.86/PORT/hpux.9.01/include/db.h --- bdb185/db.1.85/PORT/hpux.9.01/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/hpux.9.01/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/hpux.9.01/include/mpool.h bdb186/db.1.86/PORT/hpux.9.01/include/mpool.h --- bdb185/db.1.85/PORT/hpux.9.01/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/hpux.9.01/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/hpux.9.01/sys/db.h bdb186/db.1.86/PORT/hpux.9.01/sys/db.h --- bdb185/db.1.85/PORT/hpux.9.01/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/hpux.9.01/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/hpux.9.01/sys/mpool.h bdb186/db.1.86/PORT/hpux.9.01/sys/mpool.h --- bdb185/db.1.85/PORT/hpux.9.01/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/hpux.9.01/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/include/db.h bdb186/db.1.86/PORT/include/db.h --- bdb185/db.1.85/PORT/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/include/mpool.h bdb186/db.1.86/PORT/include/mpool.h --- bdb185/db.1.85/PORT/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/irix.4.05F/include/db.h bdb186/db.1.86/PORT/irix.4.05F/include/db.h --- bdb185/db.1.85/PORT/irix.4.05F/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/irix.4.05F/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/irix.4.05F/include/mpool.h bdb186/db.1.86/PORT/irix.4.05F/include/mpool.h --- bdb185/db.1.85/PORT/irix.4.05F/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/irix.4.05F/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/irix.4.05F/sys/db.h bdb186/db.1.86/PORT/irix.4.05F/sys/db.h --- bdb185/db.1.85/PORT/irix.4.05F/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/irix.4.05F/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/irix.4.05F/sys/mpool.h bdb186/db.1.86/PORT/irix.4.05F/sys/mpool.h --- bdb185/db.1.85/PORT/irix.4.05F/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/irix.4.05F/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/linux/include/db.h bdb186/db.1.86/PORT/linux/include/db.h --- bdb185/db.1.85/PORT/linux/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/linux/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/linux/include/mpool.h bdb186/db.1.86/PORT/linux/include/mpool.h --- bdb185/db.1.85/PORT/linux/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/linux/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/linux/sys/db.h bdb186/db.1.86/PORT/linux/sys/db.h --- bdb185/db.1.85/PORT/linux/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/linux/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/linux/sys/mpool.h bdb186/db.1.86/PORT/linux/sys/mpool.h --- bdb185/db.1.85/PORT/linux/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/linux/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/osf.1.0.2/include/db.h bdb186/db.1.86/PORT/osf.1.0.2/include/db.h --- bdb185/db.1.85/PORT/osf.1.0.2/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/osf.1.0.2/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/osf.1.0.2/include/mpool.h bdb186/db.1.86/PORT/osf.1.0.2/include/mpool.h --- bdb185/db.1.85/PORT/osf.1.0.2/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/osf.1.0.2/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/osf.1.0.2/sys/db.h bdb186/db.1.86/PORT/osf.1.0.2/sys/db.h --- bdb185/db.1.85/PORT/osf.1.0.2/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/osf.1.0.2/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/osf.1.0.2/sys/mpool.h bdb186/db.1.86/PORT/osf.1.0.2/sys/mpool.h --- bdb185/db.1.85/PORT/osf.1.0.2/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/osf.1.0.2/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/osf.1.3/include/db.h bdb186/db.1.86/PORT/osf.1.3/include/db.h --- bdb185/db.1.85/PORT/osf.1.3/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/osf.1.3/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/osf.1.3/include/mpool.h bdb186/db.1.86/PORT/osf.1.3/include/mpool.h --- bdb185/db.1.85/PORT/osf.1.3/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/osf.1.3/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/osf.1.3/sys/db.h bdb186/db.1.86/PORT/osf.1.3/sys/db.h --- bdb185/db.1.85/PORT/osf.1.3/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/osf.1.3/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/osf.1.3/sys/mpool.h bdb186/db.1.86/PORT/osf.1.3/sys/mpool.h --- bdb185/db.1.85/PORT/osf.1.3/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/osf.1.3/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/osf.2.0/include/db.h bdb186/db.1.86/PORT/osf.2.0/include/db.h --- bdb185/db.1.85/PORT/osf.2.0/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/osf.2.0/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/osf.2.0/include/mpool.h bdb186/db.1.86/PORT/osf.2.0/include/mpool.h --- bdb185/db.1.85/PORT/osf.2.0/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/osf.2.0/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/osf.2.0/sys/db.h bdb186/db.1.86/PORT/osf.2.0/sys/db.h --- bdb185/db.1.85/PORT/osf.2.0/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/osf.2.0/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/osf.2.0/sys/mpool.h bdb186/db.1.86/PORT/osf.2.0/sys/mpool.h --- bdb185/db.1.85/PORT/osf.2.0/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/osf.2.0/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/ptx.2.0/include/db.h bdb186/db.1.86/PORT/ptx.2.0/include/db.h --- bdb185/db.1.85/PORT/ptx.2.0/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/ptx.2.0/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/ptx.2.0/include/mpool.h bdb186/db.1.86/PORT/ptx.2.0/include/mpool.h --- bdb185/db.1.85/PORT/ptx.2.0/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/ptx.2.0/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/ptx.2.0/sys/db.h bdb186/db.1.86/PORT/ptx.2.0/sys/db.h --- bdb185/db.1.85/PORT/ptx.2.0/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/ptx.2.0/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/ptx.2.0/sys/mpool.h bdb186/db.1.86/PORT/ptx.2.0/sys/mpool.h --- bdb185/db.1.85/PORT/ptx.2.0/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/ptx.2.0/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/sinix.5.41/include/db.h bdb186/db.1.86/PORT/sinix.5.41/include/db.h --- bdb185/db.1.85/PORT/sinix.5.41/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/sinix.5.41/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/sinix.5.41/include/mpool.h bdb186/db.1.86/PORT/sinix.5.41/include/mpool.h --- bdb185/db.1.85/PORT/sinix.5.41/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/sinix.5.41/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/sinix.5.41/sys/db.h bdb186/db.1.86/PORT/sinix.5.41/sys/db.h --- bdb185/db.1.85/PORT/sinix.5.41/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/sinix.5.41/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/sinix.5.41/sys/mpool.h bdb186/db.1.86/PORT/sinix.5.41/sys/mpool.h --- bdb185/db.1.85/PORT/sinix.5.41/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/sinix.5.41/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/solaris.2.2/include/db.h bdb186/db.1.86/PORT/solaris.2.2/include/db.h --- bdb185/db.1.85/PORT/solaris.2.2/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/solaris.2.2/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/solaris.2.2/include/mpool.h bdb186/db.1.86/PORT/solaris.2.2/include/mpool.h --- bdb185/db.1.85/PORT/solaris.2.2/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/solaris.2.2/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/solaris.2.2/sys/db.h bdb186/db.1.86/PORT/solaris.2.2/sys/db.h --- bdb185/db.1.85/PORT/solaris.2.2/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/solaris.2.2/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/solaris.2.2/sys/mpool.h bdb186/db.1.86/PORT/solaris.2.2/sys/mpool.h --- bdb185/db.1.85/PORT/solaris.2.2/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/solaris.2.2/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/sunos.4.1.1/include/db.h bdb186/db.1.86/PORT/sunos.4.1.1/include/db.h --- bdb185/db.1.85/PORT/sunos.4.1.1/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.4.1.1/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/sunos.4.1.1/include/mpool.h bdb186/db.1.86/PORT/sunos.4.1.1/include/mpool.h --- bdb185/db.1.85/PORT/sunos.4.1.1/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.4.1.1/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/sunos.4.1.1/sys/db.h bdb186/db.1.86/PORT/sunos.4.1.1/sys/db.h --- bdb185/db.1.85/PORT/sunos.4.1.1/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.4.1.1/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/sunos.4.1.1/sys/mpool.h bdb186/db.1.86/PORT/sunos.4.1.1/sys/mpool.h --- bdb185/db.1.85/PORT/sunos.4.1.1/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.4.1.1/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/sunos.4.1.2/include/db.h bdb186/db.1.86/PORT/sunos.4.1.2/include/db.h --- bdb185/db.1.85/PORT/sunos.4.1.2/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.4.1.2/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/sunos.4.1.2/include/mpool.h bdb186/db.1.86/PORT/sunos.4.1.2/include/mpool.h --- bdb185/db.1.85/PORT/sunos.4.1.2/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.4.1.2/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/sunos.4.1.2/sys/db.h bdb186/db.1.86/PORT/sunos.4.1.2/sys/db.h --- bdb185/db.1.85/PORT/sunos.4.1.2/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.4.1.2/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/sunos.4.1.2/sys/mpool.h bdb186/db.1.86/PORT/sunos.4.1.2/sys/mpool.h --- bdb185/db.1.85/PORT/sunos.4.1.2/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.4.1.2/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/sunos.4.1.3/include/db.h bdb186/db.1.86/PORT/sunos.4.1.3/include/db.h --- bdb185/db.1.85/PORT/sunos.4.1.3/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.4.1.3/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/sunos.4.1.3/include/mpool.h bdb186/db.1.86/PORT/sunos.4.1.3/include/mpool.h --- bdb185/db.1.85/PORT/sunos.4.1.3/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.4.1.3/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/sunos.4.1.3/sys/db.h bdb186/db.1.86/PORT/sunos.4.1.3/sys/db.h --- bdb185/db.1.85/PORT/sunos.4.1.3/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.4.1.3/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/sunos.4.1.3/sys/mpool.h bdb186/db.1.86/PORT/sunos.4.1.3/sys/mpool.h --- bdb185/db.1.85/PORT/sunos.4.1.3/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.4.1.3/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/sunos.5.2/include/db.h bdb186/db.1.86/PORT/sunos.5.2/include/db.h --- bdb185/db.1.85/PORT/sunos.5.2/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.5.2/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/sunos.5.2/include/mpool.h bdb186/db.1.86/PORT/sunos.5.2/include/mpool.h --- bdb185/db.1.85/PORT/sunos.5.2/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.5.2/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/sunos.5.2/sys/db.h bdb186/db.1.86/PORT/sunos.5.2/sys/db.h --- bdb185/db.1.85/PORT/sunos.5.2/sys/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.5.2/sys/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/sunos.5.2/sys/mpool.h bdb186/db.1.86/PORT/sunos.5.2/sys/mpool.h --- bdb185/db.1.85/PORT/sunos.5.2/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/sunos.5.2/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/ultrix.4.2/include/db.h bdb186/db.1.86/PORT/ultrix.4.2/include/db.h --- bdb185/db.1.85/PORT/ultrix.4.2/include/db.h 1994-06-20 08:02:34.000000000 -0700 +++ bdb186/db.1.86/PORT/ultrix.4.2/include/db.h 1997-01-04 11:30:20.000000000 -0800 @@ -140,7 +140,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/ultrix.4.2/include/mpool.h bdb186/db.1.86/PORT/ultrix.4.2/include/mpool.h --- bdb185/db.1.85/PORT/ultrix.4.2/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/ultrix.4.2/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/ultrix.4.2/sys/db.h bdb186/db.1.86/PORT/ultrix.4.2/sys/db.h --- bdb185/db.1.85/PORT/ultrix.4.2/sys/db.h 1994-06-20 08:02:34.000000000 -0700 +++ bdb186/db.1.86/PORT/ultrix.4.2/sys/db.h 1997-01-04 11:30:20.000000000 -0800 @@ -140,7 +140,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/ultrix.4.2/sys/mpool.h bdb186/db.1.86/PORT/ultrix.4.2/sys/mpool.h --- bdb185/db.1.85/PORT/ultrix.4.2/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/ultrix.4.2/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/ultrix.4.3/include/db.h bdb186/db.1.86/PORT/ultrix.4.3/include/db.h --- bdb185/db.1.85/PORT/ultrix.4.3/include/db.h 1994-06-20 08:02:34.000000000 -0700 +++ bdb186/db.1.86/PORT/ultrix.4.3/include/db.h 1997-01-04 11:30:20.000000000 -0800 @@ -140,7 +140,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/ultrix.4.3/include/mpool.h bdb186/db.1.86/PORT/ultrix.4.3/include/mpool.h --- bdb185/db.1.85/PORT/ultrix.4.3/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/ultrix.4.3/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/PORT/ultrix.4.3/sys/db.h bdb186/db.1.86/PORT/ultrix.4.3/sys/db.h --- bdb185/db.1.85/PORT/ultrix.4.3/sys/db.h 1994-06-20 08:02:34.000000000 -0700 +++ bdb186/db.1.86/PORT/ultrix.4.3/sys/db.h 1997-01-04 11:30:20.000000000 -0800 @@ -140,7 +140,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/PORT/ultrix.4.3/sys/mpool.h bdb186/db.1.86/PORT/ultrix.4.3/sys/mpool.h --- bdb185/db.1.85/PORT/ultrix.4.3/sys/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/PORT/ultrix.4.3/sys/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/btree/bt_debug.c bdb186/db.1.86/btree/bt_debug.c --- bdb185/db.1.85/btree/bt_debug.c 1994-08-18 06:30:42.000000000 -0700 +++ bdb186/db.1.86/btree/bt_debug.c 1997-01-04 11:35:45.000000000 -0800 @@ -86,10 +86,9 @@ } #undef X - for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { + for (i = P_ROOT; + (h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i) __bt_dpage(h); - (void)mpool_put(t->bt_mp, h, 0); - } } /* @@ -141,10 +140,8 @@ PAGE *h; t = dbp->internal; - if ((h = mpool_get(t->bt_mp, pgno, 0)) != NULL) { + if ((h = mpool_get(t->bt_mp, pgno, MPOOL_IGNOREPIN)) != NULL) __bt_dpage(h); - (void)mpool_put(t->bt_mp, h, 0); - } } /* @@ -264,7 +261,8 @@ t = dbp->internal; pcont = pinternal = pleaf = 0; nkeys = ifree = lfree = 0; - for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { + for (i = P_ROOT; + (h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i) switch (h->flags & P_TYPE) { case P_BINTERNAL: case P_RINTERNAL: @@ -281,22 +279,18 @@ ++pcont; break; } - (void)mpool_put(t->bt_mp, h, 0); - } /* Count the levels of the tree. */ for (i = P_ROOT, levels = 0 ;; ++levels) { - h = mpool_get(t->bt_mp, i, 0); + h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN); if (h->flags & (P_BLEAF|P_RLEAF)) { if (levels == 0) levels = 1; - (void)mpool_put(t->bt_mp, h, 0); break; } i = F_ISSET(t, R_RECNO) ? GETRINTERNAL(h, 0)->pgno : GETBINTERNAL(h, 0)->pgno; - (void)mpool_put(t->bt_mp, h, 0); } (void)fprintf(stderr, "%d level%s with %ld keys", diff -u -r -N bdb185/db.1.85/btree/bt_open.c bdb186/db.1.86/btree/bt_open.c --- bdb185/db.1.85/btree/bt_open.c 1994-08-18 06:30:42.000000000 -0700 +++ bdb186/db.1.86/btree/bt_open.c 1997-01-04 11:53:31.000000000 -0800 @@ -35,7 +35,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_open.c 8.10 (Berkeley) 8/17/94"; +static char sccsid[] = "@(#)bt_open.c 8.11 (Berkeley) 11/2/95"; #endif /* LIBC_SCCS and not lint */ /* @@ -356,18 +356,25 @@ PAGE *meta, *root; pgno_t npg; - if ((meta = mpool_get(t->bt_mp, 0, 0)) != NULL) { - mpool_put(t->bt_mp, meta, 0); - return (RET_SUCCESS); + if ((root = mpool_get(t->bt_mp, 1, 0)) != NULL) { + if (root->lower == 0 && + root->pgno == 0 && + root->linp[0] == 0) { + mpool_delete(t->bt_mp, root); + errno = EINVAL; + } else { + mpool_put(t->bt_mp, root, 0); + return (RET_SUCCESS); + } } if (errno != EINVAL) /* It's OK to not exist. */ return (RET_ERROR); errno = 0; - if ((meta = mpool_new(t->bt_mp, &npg)) == NULL) + if ((meta = mpool_new(t->bt_mp, &npg, MPOOL_PAGE_NEXT)) == NULL) return (RET_ERROR); - if ((root = mpool_new(t->bt_mp, &npg)) == NULL) + if ((root = mpool_new(t->bt_mp, &npg, MPOOL_PAGE_NEXT)) == NULL) return (RET_ERROR); if (npg != P_ROOT) diff -u -r -N bdb185/db.1.85/btree/bt_page.c bdb186/db.1.86/btree/bt_page.c --- bdb185/db.1.85/btree/bt_page.c 1994-07-13 18:29:02.000000000 -0700 +++ bdb186/db.1.86/btree/bt_page.c 1997-01-04 11:38:51.000000000 -0800 @@ -94,5 +94,5 @@ t->bt_free = h->nextpg; return (h); } - return (mpool_new(t->bt_mp, npg)); + return (mpool_new(t->bt_mp, npg, MPOOL_PAGE_NEXT)); } diff -u -r -N bdb185/db.1.85/btree/bt_split.c bdb186/db.1.86/btree/bt_split.c --- bdb185/db.1.85/btree/bt_split.c 1994-07-26 11:22:02.000000000 -0700 +++ bdb186/db.1.86/btree/bt_split.c 1997-01-04 11:38:55.000000000 -0800 @@ -35,7 +35,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_split.c 8.9 (Berkeley) 7/26/94"; +static char sccsid[] = "@(#)bt_split.c 8.10 (Berkeley) 1/9/95"; #endif /* LIBC_SCCS and not lint */ #include @@ -673,7 +673,7 @@ * where we decide to try and copy too much onto the left page. * Make sure that doesn't happen. */ - if (skip <= off && used + nbytes >= full) { + if (skip <= off && used + nbytes >= full || nxt == top - 1) { --off; break; } diff -u -r -N bdb185/db.1.85/hash/README bdb186/db.1.86/hash/README --- bdb185/db.1.85/hash/README 1993-06-04 15:21:34.000000000 -0700 +++ bdb186/db.1.86/hash/README 1969-12-31 16:00:00.000000000 -0800 @@ -1,72 +0,0 @@ -# @(#)README 8.1 (Berkeley) 6/4/93 - -This package implements a superset of the hsearch and dbm/ndbm libraries. - -Test Programs: - All test programs which need key/data pairs expect them entered - with key and data on separate lines - - tcreat3.c - Takes - bucketsize (bsize), - fill factor (ffactor), and - initial number of elements (nelem). - Creates a hash table named hashtest containing the - keys/data pairs entered from standard in. - thash4.c - Takes - bucketsize (bsize), - fill factor (ffactor), - initial number of elements (nelem) - bytes of cache (ncached), and - file from which to read data (fname) - Creates a table from the key/data pairs on standard in and - then does a read of each key/data in fname - tdel.c - Takes - bucketsize (bsize), and - fill factor (ffactor). - file from which to read data (fname) - Reads each key/data pair from fname and deletes the - key from the hash table hashtest - tseq.c - Reads the key/data pairs in the file hashtest and writes them - to standard out. - tread2.c - Takes - butes of cache (ncached). - Reads key/data pairs from standard in and looks them up - in the file hashtest. - tverify.c - Reads key/data pairs from standard in, looks them up - in the file hashtest, and verifies that the data is - correct. - -NOTES: - -The file search.h is provided for using the hsearch compatible interface -on BSD systems. On System V derived systems, search.h should appear in -/usr/include. - -The man page ../man/db.3 explains the interface to the hashing system. -The file hash.ps is a postscript copy of a paper explaining -the history, implementation, and performance of the hash package. - -"bugs" or idiosyncracies - -If you have a lot of overflows, it is possible to run out of overflow -pages. Currently, this will cause a message to be printed on stderr. -Eventually, this will be indicated by a return error code. - -If you are using the ndbm interface and exit without flushing or closing the -file, you may lose updates since the package buffers all writes. Also, -the db interface only creates a single database file. To avoid overwriting -the user's original file, the suffix ".db" is appended to the file name -passed to dbm_open. Additionally, if your code "knows" about the historic -.dir and .pag files, it will break. - -There is a fundamental difference between this package and the old hsearch. -Hsearch requires the user to maintain the keys and data in the application's -allocated memory while hash takes care of all storage management. The down -side is that the byte strings passed in the ENTRY structure must be null -terminated (both the keys and the data). diff -u -r -N bdb185/db.1.85/hash/extern.h bdb186/db.1.86/hash/extern.h --- bdb185/db.1.85/hash/extern.h 1994-06-16 13:30:14.000000000 -0700 +++ bdb186/db.1.86/hash/extern.h 1997-01-04 11:25:41.000000000 -0800 @@ -30,36 +30,47 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)extern.h 8.4 (Berkeley) 6/16/94 + * @(#)extern.h 8.8 (Berkeley) 11/7/95 */ -BUFHEAD *__add_ovflpage __P((HTAB *, BUFHEAD *)); -int __addel __P((HTAB *, BUFHEAD *, const DBT *, const DBT *)); -int __big_delete __P((HTAB *, BUFHEAD *)); -int __big_insert __P((HTAB *, BUFHEAD *, const DBT *, const DBT *)); -int __big_keydata __P((HTAB *, BUFHEAD *, DBT *, DBT *, int)); -int __big_return __P((HTAB *, BUFHEAD *, int, DBT *, int)); -int __big_split __P((HTAB *, BUFHEAD *, BUFHEAD *, BUFHEAD *, - int, u_int32_t, SPLIT_RETURN *)); -int __buf_free __P((HTAB *, int, int)); -void __buf_init __P((HTAB *, int)); -u_int32_t __call_hash __P((HTAB *, char *, int)); -int __delpair __P((HTAB *, BUFHEAD *, int)); -int __expand_table __P((HTAB *)); -int __find_bigpair __P((HTAB *, BUFHEAD *, int, char *, int)); -u_int16_t __find_last_page __P((HTAB *, BUFHEAD **)); -void __free_ovflpage __P((HTAB *, BUFHEAD *)); -BUFHEAD *__get_buf __P((HTAB *, u_int32_t, BUFHEAD *, int)); -int __get_page __P((HTAB *, char *, u_int32_t, int, int, int)); -int __ibitmap __P((HTAB *, int, int, int)); -u_int32_t __log2 __P((u_int32_t)); -int __put_page __P((HTAB *, char *, u_int32_t, int, int)); -void __reclaim_buf __P((HTAB *, BUFHEAD *)); -int __split_page __P((HTAB *, u_int32_t, u_int32_t)); +PAGE16 *__add_bigpage __P((HTAB *, PAGE16 *, indx_t, const u_int8_t)); +PAGE16 *__add_ovflpage __P((HTAB *, PAGE16 *)); +int32_t __addel __P((HTAB *, ITEM_INFO *, + const DBT *, const DBT *, u_int32_t, const u_int8_t)); +u_int32_t __alloc_tmp __P((HTAB*)); +int32_t __big_delete __P((HTAB *, PAGE16 *, indx_t)); +int32_t __big_insert __P((HTAB *, PAGE16 *, const DBT *, const DBT *)); +int32_t __big_keydata __P((HTAB *, PAGE16 *, DBT *, DBT *, int32_t)); +int32_t __big_return __P((HTAB *, ITEM_INFO *, DBT *, int32_t)); +u_int32_t __call_hash __P((HTAB *, int8_t *, int32_t)); +CURSOR *__cursor_creat __P((const DB *)); +int32_t __delete_page __P((HTAB *, PAGE16 *, int32_t)); +int32_t __delpair __P((HTAB *, CURSOR *, ITEM_INFO *)); +int32_t __expand_table __P((HTAB *)); +int32_t __find_bigpair __P((HTAB *, CURSOR *, int8_t *, int32_t)); +void __free_ovflpage __P((HTAB *, PAGE16 *)); +int32_t __get_bigkey __P((HTAB *, PAGE16 *, indx_t, DBT *)); +PAGE16 *__get_buf __P((HTAB *, u_int32_t, int32_t)); +u_int32_t __get_item __P((HTAB *, CURSOR *, DBT *, DBT *, ITEM_INFO *)); +u_int32_t __get_item_done __P((HTAB *, CURSOR *)); +u_int32_t __get_item_first __P((HTAB *, CURSOR *, DBT *, DBT *, ITEM_INFO *)); +u_int32_t __get_item_next __P((HTAB *, CURSOR *, DBT *, DBT *, ITEM_INFO *)); +u_int32_t __get_item_reset __P((HTAB *, CURSOR *)); +PAGE16 *__get_page __P((HTAB *, u_int32_t, int32_t)); +int32_t __ibitmap __P((HTAB *, int32_t, int32_t, int32_t)); +u_int32_t __log2 __P((u_int32_t)); +int32_t __new_page __P((HTAB *, u_int32_t, int32_t)); +void __pgin_routine __P((void *, pgno_t, void *)); +void __pgout_routine __P((void *, pgno_t, void *)); +u_int32_t __put_buf __P((HTAB *, PAGE16 *, u_int32_t)); +int32_t __put_page __P((HTAB *, PAGE16 *, int32_t, int32_t)); +void __reclaim_tmp __P((HTAB *)); +int32_t __split_page __P((HTAB *, u_int32_t, u_int32_t)); /* Default hash routine. */ extern u_int32_t (*__default_hash) __P((const void *, size_t)); #ifdef HASH_STATISTICS -extern int hash_accesses, hash_collisions, hash_expansions, hash_overflows; +extern long hash_accesses, hash_bigpages, hash_collisions, hash_expansions; +extern long hash_overflow; #endif diff -u -r -N bdb185/db.1.85/hash/hash.c bdb186/db.1.86/hash/hash.c --- bdb185/db.1.85/hash/hash.c 1994-06-24 08:12:29.000000000 -0700 +++ bdb186/db.1.86/hash/hash.c 1997-01-04 11:25:41.000000000 -0800 @@ -35,7 +35,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash.c 8.9 (Berkeley) 6/16/94"; +static char sccsid[] = "@(#)hash.c 8.12 (Berkeley) 11/7/95"; #endif /* LIBC_SCCS and not lint */ #include @@ -56,27 +56,27 @@ #include "page.h" #include "extern.h" -static int alloc_segs __P((HTAB *, int)); -static int flush_meta __P((HTAB *)); -static int hash_access __P((HTAB *, ACTION, DBT *, DBT *)); -static int hash_close __P((DB *)); -static int hash_delete __P((const DB *, const DBT *, u_int32_t)); -static int hash_fd __P((const DB *)); -static int hash_get __P((const DB *, const DBT *, DBT *, u_int32_t)); -static int hash_put __P((const DB *, DBT *, const DBT *, u_int32_t)); -static void *hash_realloc __P((SEGMENT **, int, int)); -static int hash_seq __P((const DB *, DBT *, DBT *, u_int32_t)); -static int hash_sync __P((const DB *, u_int32_t)); -static int hdestroy __P((HTAB *)); +static int32_t flush_meta __P((HTAB *)); +static int32_t hash_access __P((HTAB *, ACTION, DBT *, DBT *)); +static int32_t hash_close __P((DB *)); +static int32_t hash_delete __P((const DB *, const DBT *, u_int32_t)); +static int32_t hash_fd __P((const DB *)); +static int32_t hash_get __P((const DB *, const DBT *, DBT *, u_int32_t)); +static int32_t hash_put __P((const DB *, DBT *, const DBT *, u_int32_t)); +static int32_t hash_seq __P((const DB *, DBT *, DBT *, u_int32_t)); +static int32_t hash_sync __P((const DB *, u_int32_t)); +static int32_t hdestroy __P((HTAB *)); +static int32_t cursor_get __P((const DB *, CURSOR *, DBT *, DBT *, \ + u_int32_t)); +static int32_t cursor_delete __P((const DB *, CURSOR *, u_int32_t)); static HTAB *init_hash __P((HTAB *, const char *, HASHINFO *)); -static int init_htab __P((HTAB *, int)); +static int32_t init_htab __P((HTAB *, int32_t)); #if BYTE_ORDER == LITTLE_ENDIAN -static void swap_header __P((HTAB *)); -static void swap_header_copy __P((HASHHDR *, HASHHDR *)); +static void swap_header __P((HTAB *)); +static void swap_header_copy __P((HASHHDR *, HASHHDR *)); #endif - -/* Fast arithmetic, relying on powers of 2, */ -#define MOD(x, y) ((x) & ((y) - 1)) +static u_int32_t hget_header __P((HTAB *, u_int32_t)); +static void hput_header __P((HTAB *)); #define RETURN_ERROR(ERR, LOC) { save_errno = ERR; goto LOC; } @@ -86,7 +86,8 @@ #define ABNORMAL (1) #ifdef HASH_STATISTICS -int hash_accesses, hash_collisions, hash_expansions, hash_overflows; +u_int32_t hash_accesses, hash_collisions, hash_expansions, hash_overflows, + hash_bigpages; #endif /************************** INTERFACE ROUTINES ***************************/ @@ -95,23 +96,33 @@ extern DB * __hash_open(file, flags, mode, info, dflags) const char *file; - int flags, mode, dflags; + int32_t flags, mode, dflags; const HASHINFO *info; /* Special directives for create */ { - HTAB *hashp; struct stat statbuf; DB *dbp; - int bpages, hdrsize, new_table, nsegs, save_errno; + DBT mpool_key; + HTAB *hashp; + int32_t bpages, csize, new_table, save_errno, specified_file; if ((flags & O_ACCMODE) == O_WRONLY) { errno = EINVAL; return (NULL); } - if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB)))) return (NULL); hashp->fp = -1; + /* set this now, before file goes away... */ + specified_file = (file != NULL); + if (!file) { + file = tmpnam(NULL); + /* store the file name so that we can unlink it later */ + hashp->fname = (char *)file; +#ifdef DEBUG + fprintf(stderr, "Using file name %s.\n", file); +#endif + } /* * Even if user wants write only, we need to be able to read * the actual file, so we need to open it read/write. But, the @@ -119,12 +130,13 @@ * we can check accesses. */ hashp->flags = flags; + hashp->save_file = specified_file && (hashp->flags & O_RDWR); new_table = 0; if (!file || (flags & O_TRUNC) || (stat(file, &statbuf) && (errno == ENOENT))) { if (errno == ENOENT) - errno = 0; /* Just in case someone looks at errno */ + errno = 0; /* In case someone looks at errno. */ new_table = 1; } if (file) { @@ -132,6 +144,8 @@ RETURN_ERROR(errno, error0); (void)fcntl(hashp->fp, F_SETFD, 1); } + + /* Process arguments to set up hash table header. */ if (new_table) { if (!(hashp = init_hash(hashp, file, (HASHINFO *)info))) RETURN_ERROR(errno, error1); @@ -142,61 +156,73 @@ else hashp->hash = __default_hash; - hdrsize = read(hashp->fp, &hashp->hdr, sizeof(HASHHDR)); -#if BYTE_ORDER == LITTLE_ENDIAN - swap_header(hashp); -#endif - if (hdrsize == -1) - RETURN_ERROR(errno, error1); - if (hdrsize != sizeof(HASHHDR)) + /* copy metadata from page into header */ + if (hget_header(hashp, + (info && info->bsize ? info->bsize : DEF_BUCKET_SIZE)) != + sizeof(HASHHDR)) RETURN_ERROR(EFTYPE, error1); + /* Verify file type, versions and hash function */ - if (hashp->MAGIC != HASHMAGIC) + if (hashp->hdr.magic != HASHMAGIC) RETURN_ERROR(EFTYPE, error1); #define OLDHASHVERSION 1 - if (hashp->VERSION != HASHVERSION && - hashp->VERSION != OLDHASHVERSION) + if (hashp->hdr.version != HASHVERSION && + hashp->hdr.version != OLDHASHVERSION) RETURN_ERROR(EFTYPE, error1); - if (hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY) + if (hashp->hash(CHARKEY, sizeof(CHARKEY)) + != hashp->hdr.h_charkey) RETURN_ERROR(EFTYPE, error1); /* * Figure out how many segments we need. Max_Bucket is the * maximum bucket number, so the number of buckets is * max_bucket + 1. */ - nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) / - hashp->SGSIZE; - hashp->nsegs = 0; - if (alloc_segs(hashp, nsegs)) - /* - * If alloc_segs fails, table will have been destroyed - * and errno will have been set. - */ - return (NULL); + /* Read in bitmaps */ - bpages = (hashp->SPARES[hashp->OVFL_POINT] + - (hashp->BSIZE << BYTE_SHIFT) - 1) >> - (hashp->BSHIFT + BYTE_SHIFT); + bpages = (hashp->hdr.spares[hashp->hdr.ovfl_point] + + (hashp->hdr.bsize << BYTE_SHIFT) - 1) >> + (hashp->hdr.bshift + BYTE_SHIFT); hashp->nmaps = bpages; (void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *)); } - /* Initialize Buffer Manager */ + /* start up mpool */ + mpool_key.data = (u_int8_t *)file; + mpool_key.size = strlen(file); + if (info && info->cachesize) - __buf_init(hashp, info->cachesize); + csize = info->cachesize / hashp->hdr.bsize; else - __buf_init(hashp, DEF_BUFSIZE); + csize = DEF_CACHESIZE / hashp->hdr.bsize; + hashp->mp = mpool_open(&mpool_key, hashp->fp, hashp->hdr.bsize, csize); + + if (!hashp->mp) + RETURN_ERROR(errno, error1); + mpool_filter(hashp->mp, __pgin_routine, __pgout_routine, hashp); + + /* + * For a new table, set up the bitmaps. + */ + if (new_table && + init_htab(hashp, info && info->nelem ? info->nelem : 1)) + goto error2; + + /* initialize the cursor queue */ + TAILQ_INIT(&hashp->curs_queue); + hashp->seq_cursor = NULL; + + + /* get a chunk of memory for our split buffer */ + hashp->split_buf = (PAGE16 *)malloc(hashp->hdr.bsize); + if (!hashp->split_buf) + goto error2; hashp->new_file = new_table; - hashp->save_file = file && (hashp->flags & O_RDWR); - hashp->cbucket = -1; - if (!(dbp = (DB *)malloc(sizeof(DB)))) { - save_errno = errno; - hdestroy(hashp); - errno = save_errno; - return (NULL); - } + + if (!(dbp = (DB *)malloc(sizeof(DB)))) + goto error2; + dbp->internal = hashp; dbp->close = hash_close; dbp->del = hash_delete; @@ -209,28 +235,31 @@ #ifdef DEBUG (void)fprintf(stderr, -"%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n", + "%s\n%s%lx\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n", "init_htab:", - "TABLE POINTER ", hashp, - "BUCKET SIZE ", hashp->BSIZE, - "BUCKET SHIFT ", hashp->BSHIFT, - "DIRECTORY SIZE ", hashp->DSIZE, - "SEGMENT SIZE ", hashp->SGSIZE, - "SEGMENT SHIFT ", hashp->SSHIFT, - "FILL FACTOR ", hashp->FFACTOR, - "MAX BUCKET ", hashp->MAX_BUCKET, - "OVFL POINT ", hashp->OVFL_POINT, - "LAST FREED ", hashp->LAST_FREED, - "HIGH MASK ", hashp->HIGH_MASK, - "LOW MASK ", hashp->LOW_MASK, - "NSEGS ", hashp->nsegs, - "NKEYS ", hashp->NKEYS); + "TABLE POINTER ", (void *)hashp, + "BUCKET SIZE ", hashp->hdr.bsize, + "BUCKET SHIFT ", hashp->hdr.bshift, + "FILL FACTOR ", hashp->hdr.ffactor, + "MAX BUCKET ", hashp->hdr.max_bucket, + "OVFL POINT ", hashp->hdr.ovfl_point, + "LAST FREED ", hashp->hdr.last_freed, + "HIGH MASK ", hashp->hdr.high_mask, + "LOW MASK ", hashp->hdr.low_mask, + "NKEYS ", hashp->hdr.nkeys); #endif #ifdef HASH_STATISTICS hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0; + hash_bigpages = 0; #endif return (dbp); +error2: + save_errno = errno; + hdestroy(hashp); + errno = save_errno; + return (NULL); + error1: if (hashp != NULL) (void)close(hashp->fp); @@ -241,12 +270,12 @@ return (NULL); } -static int +static int32_t hash_close(dbp) DB *dbp; { HTAB *hashp; - int retval; + int32_t retval; if (!dbp) return (ERROR); @@ -257,7 +286,7 @@ return (retval); } -static int +static int32_t hash_fd(dbp) const DB *dbp; { @@ -282,104 +311,161 @@ HASHINFO *info; { struct stat statbuf; - int nelem; + int32_t nelem; nelem = 1; - hashp->NKEYS = 0; - hashp->LORDER = BYTE_ORDER; - hashp->BSIZE = DEF_BUCKET_SIZE; - hashp->BSHIFT = DEF_BUCKET_SHIFT; - hashp->SGSIZE = DEF_SEGSIZE; - hashp->SSHIFT = DEF_SEGSIZE_SHIFT; - hashp->DSIZE = DEF_DIRSIZE; - hashp->FFACTOR = DEF_FFACTOR; + hashp->hdr.nkeys = 0; + hashp->hdr.lorder = BYTE_ORDER; + hashp->hdr.bsize = DEF_BUCKET_SIZE; + hashp->hdr.bshift = DEF_BUCKET_SHIFT; + hashp->hdr.ffactor = DEF_FFACTOR; hashp->hash = __default_hash; - memset(hashp->SPARES, 0, sizeof(hashp->SPARES)); - memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS)); + memset(hashp->hdr.spares, 0, sizeof(hashp->hdr.spares)); + memset(hashp->hdr.bitmaps, 0, sizeof(hashp->hdr.bitmaps)); /* Fix bucket size to be optimal for file system */ if (file != NULL) { if (stat(file, &statbuf)) return (NULL); - hashp->BSIZE = statbuf.st_blksize; - hashp->BSHIFT = __log2(hashp->BSIZE); + hashp->hdr.bsize = statbuf.st_blksize; + hashp->hdr.bshift = __log2(hashp->hdr.bsize); } - if (info) { if (info->bsize) { /* Round pagesize up to power of 2 */ - hashp->BSHIFT = __log2(info->bsize); - hashp->BSIZE = 1 << hashp->BSHIFT; - if (hashp->BSIZE > MAX_BSIZE) { + hashp->hdr.bshift = __log2(info->bsize); + hashp->hdr.bsize = 1 << hashp->hdr.bshift; + if (hashp->hdr.bsize > MAX_BSIZE) { errno = EINVAL; return (NULL); } } if (info->ffactor) - hashp->FFACTOR = info->ffactor; + hashp->hdr.ffactor = info->ffactor; if (info->hash) hashp->hash = info->hash; - if (info->nelem) - nelem = info->nelem; if (info->lorder) { - if (info->lorder != BIG_ENDIAN && - info->lorder != LITTLE_ENDIAN) { + if ((info->lorder != BIG_ENDIAN) && + (info->lorder != LITTLE_ENDIAN)) { errno = EINVAL; return (NULL); } - hashp->LORDER = info->lorder; + hashp->hdr.lorder = info->lorder; } } - /* init_htab should destroy the table and set errno if it fails */ - if (init_htab(hashp, nelem)) - return (NULL); - else - return (hashp); + return (hashp); } + /* - * This calls alloc_segs which may run out of memory. Alloc_segs will destroy - * the table and set errno, so we just pass the error information along. - * * Returns 0 on No Error */ -static int +static int32_t init_htab(hashp, nelem) HTAB *hashp; - int nelem; + int32_t nelem; { - register int nbuckets, nsegs; - int l2; + int32_t l2, nbuckets; + pgno_t i; /* * Divide number of elements by the fill factor and determine a * desired number of buckets. Allocate space for the next greater * power of two number of buckets. */ - nelem = (nelem - 1) / hashp->FFACTOR + 1; + nelem = (nelem - 1) / hashp->hdr.ffactor + 1; l2 = __log2(MAX(nelem, 2)); nbuckets = 1 << l2; - hashp->SPARES[l2] = l2 + 1; - hashp->SPARES[l2 + 1] = l2 + 1; - hashp->OVFL_POINT = l2; - hashp->LAST_FREED = 2; + hashp->hdr.spares[l2] = l2 + 1; + hashp->hdr.spares[l2 + 1] = l2 + 1; + hashp->hdr.ovfl_point = l2; + hashp->hdr.last_freed = 2; + + hashp->hdr.max_bucket = hashp->hdr.low_mask = nbuckets - 1; + hashp->hdr.high_mask = (nbuckets << 1) - 1; + + /* + * The number of header pages is the size of the header divided by + * the amount of freespace on header pages (the page size - the + * size of 1 integer where the length of the header info on that + * page is stored) plus another page if it didn't divide evenly. + */ + hashp->hdr.hdrpages = + (sizeof(HASHHDR) / (hashp->hdr.bsize - HEADER_OVERHEAD)) + + (((sizeof(HASHHDR) % (hashp->hdr.bsize - HEADER_OVERHEAD)) == 0) + ? 0 : 1); + + /* Create pages for these buckets */ + /* + for (i = 0; i <= hashp->hdr.max_bucket; i++) { + if (__new_page(hashp, (u_int32_t)i, A_BUCKET) != 0) + return (-1); + } + */ /* First bitmap page is at: splitpoint l2 page offset 1 */ if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0)) return (-1); - hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1; - hashp->HIGH_MASK = (nbuckets << 1) - 1; - hashp->HDRPAGES = ((MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >> - hashp->BSHIFT) + 1; - - nsegs = (nbuckets - 1) / hashp->SGSIZE + 1; - nsegs = 1 << __log2(nsegs); - - if (nsegs > hashp->DSIZE) - hashp->DSIZE = nsegs; - return (alloc_segs(hashp, nsegs)); + return (0); +} + +/* + * Functions to get/put hash header. We access the file directly. + */ +u_int32_t +hget_header(hashp, page_size) + HTAB *hashp; + u_int32_t page_size; +{ + u_int32_t num_copied, i; + u_int8_t *hdr_dest; + + num_copied = 0; + i = 0; + + hdr_dest = (u_int8_t *)&hashp->hdr; + + /* + * XXX + * This should not be printing to stderr on a "normal" error case. + */ + lseek(hashp->fp, 0, SEEK_SET); + num_copied = read(hashp->fp, hdr_dest, sizeof(HASHHDR)); + if (num_copied != sizeof(HASHHDR)) { + fprintf(stderr, "hash: could not retrieve header"); + return (0); + } +#if BYTE_ORDER == LITTLE_ENDIAN + swap_header(hashp); +#endif + return (num_copied); +} + +void +hput_header(hashp) + HTAB *hashp; +{ + HASHHDR *whdrp; +#if BYTE_ORDER == LITTLE_ENDIAN + HASHHDR whdr; +#endif + u_int32_t num_copied, i; + + num_copied = i = 0; + + whdrp = &hashp->hdr; +#if BYTE_ORDER == LITTLE_ENDIAN + whdrp = &whdr; + swap_header_copy(&hashp->hdr, whdrp); +#endif + + lseek(hashp->fp, 0, SEEK_SET); + num_copied = write(hashp->fp, whdrp, sizeof(HASHHDR)); + if (num_copied != sizeof(HASHHDR)) + (void)fprintf(stderr, "hash: could not write hash header"); + return; } /********************** DESTROY/CLOSE ROUTINES ************************/ @@ -388,51 +474,67 @@ * Flushes any changes to the file if necessary and destroys the hashp * structure, freeing all allocated space. */ -static int +static int32_t hdestroy(hashp) HTAB *hashp; { - int i, save_errno; + int32_t save_errno; save_errno = 0; #ifdef HASH_STATISTICS + { int i; (void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n", hash_accesses, hash_collisions); - (void)fprintf(stderr, "hdestroy: expansions %ld\n", - hash_expansions); - (void)fprintf(stderr, "hdestroy: overflows %ld\n", - hash_overflows); - (void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n", - hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs); + (void)fprintf(stderr, + "hdestroy: expansions %ld\n", hash_expansions); + (void)fprintf(stderr, + "hdestroy: overflows %ld\n", hash_overflows); + (void)fprintf(stderr, + "hdestroy: big key/data pages %ld\n", hash_bigpages); + (void)fprintf(stderr, + "keys %ld maxp %d\n", hashp->hdr.nkeys, hashp->hdr.max_bucket); for (i = 0; i < NCACHED; i++) (void)fprintf(stderr, - "spares[%d] = %d\n", i, hashp->SPARES[i]); -#endif - /* - * Call on buffer manager to free buffers, and if required, - * write them to disk. - */ - if (__buf_free(hashp, 1, hashp->save_file)) - save_errno = errno; - if (hashp->dir) { - free(*hashp->dir); /* Free initial segments */ - /* Free extra segments */ - while (hashp->exsegs--) - free(hashp->dir[--hashp->nsegs]); - free(hashp->dir); + "spares[%d] = %d\n", i, hashp->hdr.spares[i]); } +#endif + if (flush_meta(hashp) && !save_errno) save_errno = errno; - /* Free Bigmaps */ - for (i = 0; i < hashp->nmaps; i++) - if (hashp->mapp[i]) - free(hashp->mapp[i]); + + /* Free the split page, big key buf and big data buf */ + if (hashp->split_buf) + free(hashp->split_buf); + if (hashp->bigdata_buf) + free(hashp->bigdata_buf); + if (hashp->bigkey_buf) + free(hashp->bigkey_buf); + + /* shut down mpool */ + mpool_sync(hashp->mp); + mpool_close(hashp->mp); if (hashp->fp != -1) (void)close(hashp->fp); + /* + * *** This may cause problems if hashp->fname is set in any case + * other than the case that we are generating a temporary file name. + * Note that the new version of mpool should support temporary + * files within mpool itself. + */ + if (hashp->fname && !hashp->save_file) { +#ifdef DEBUG + fprintf(stderr, "Unlinking file %s.\n", hashp->fname); +#endif + /* we need to chmod the file to allow it to be deleted... */ + chmod(hashp->fname, 0700); + unlink(hashp->fname); + /* destroy the temporary name */ + tmpnam(NULL); + } free(hashp); if (save_errno) { @@ -441,6 +543,7 @@ } return (SUCCESS); } + /* * Write modified pages to disk * @@ -448,28 +551,20 @@ * 0 == OK * -1 ERROR */ -static int +static int32_t hash_sync(dbp, flags) const DB *dbp; u_int32_t flags; { HTAB *hashp; - if (flags != 0) { - errno = EINVAL; - return (ERROR); - } - - if (!dbp) - return (ERROR); - hashp = (HTAB *)dbp->internal; - if (!hashp->save_file) - return (0); - if (__buf_free(hashp, 0, 1) || flush_meta(hashp)) - return (ERROR); - hashp->new_file = 0; - return (0); + + /* + * XXX + * Check success/failure conditions. + */ + return (flush_meta(hashp) || mpool_sync(hashp->mp)); } /* @@ -477,42 +572,28 @@ * 0 == OK * -1 indicates that errno should be set */ -static int +static int32_t flush_meta(hashp) HTAB *hashp; { - HASHHDR *whdrp; -#if BYTE_ORDER == LITTLE_ENDIAN - HASHHDR whdr; -#endif - int fp, i, wsize; + int32_t i; if (!hashp->save_file) return (0); - hashp->MAGIC = HASHMAGIC; - hashp->VERSION = HASHVERSION; - hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY)); + hashp->hdr.magic = HASHMAGIC; + hashp->hdr.version = HASHVERSION; + hashp->hdr.h_charkey = hashp->hash(CHARKEY, sizeof(CHARKEY)); + + /* write out metadata */ + hput_header(hashp); - fp = hashp->fp; - whdrp = &hashp->hdr; -#if BYTE_ORDER == LITTLE_ENDIAN - whdrp = &whdr; - swap_header_copy(&hashp->hdr, whdrp); -#endif - if ((lseek(fp, (off_t)0, SEEK_SET) == -1) || - ((wsize = write(fp, whdrp, sizeof(HASHHDR))) == -1)) - return (-1); - else - if (wsize != sizeof(HASHHDR)) { - errno = EFTYPE; - hashp->errno = errno; - return (-1); - } for (i = 0; i < NCACHED; i++) - if (hashp->mapp[i]) - if (__put_page(hashp, (char *)hashp->mapp[i], - hashp->BITMAPS[i], 0, 1)) + if (hashp->mapp[i]) { + if (__put_page(hashp, + (PAGE16 *)hashp->mapp[i], A_BITMAP, 1)) return (-1); + hashp->mapp[i] = NULL; + } return (0); } @@ -525,7 +606,10 @@ * 1 to indicate an external ERROR (i.e. key not found, etc) * -1 to indicate an internal ERROR (i.e. out of memory, etc) */ -static int + +/* *** make sure this is true! */ + +static int32_t hash_get(dbp, key, data, flag) const DB *dbp; const DBT *key; @@ -542,7 +626,7 @@ return (hash_access(hashp, HASH_GET, (DBT *)key, data)); } -static int +static int32_t hash_put(dbp, key, data, flag) const DB *dbp; DBT *key; @@ -561,10 +645,10 @@ return (ERROR); } return (hash_access(hashp, flag == R_NOOVERWRITE ? - HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data)); + HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data)); } -static int +static int32_t hash_delete(dbp, key, flag) const DB *dbp; const DBT *key; @@ -573,7 +657,7 @@ HTAB *hashp; hashp = (HTAB *)dbp->internal; - if (flag && flag != R_CURSOR) { + if (flag) { hashp->errno = errno = EINVAL; return (ERROR); } @@ -581,222 +665,265 @@ hashp->errno = errno = EPERM; return (ERROR); } + return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL)); } /* * Assume that hashp has been set in wrapper routine. */ -static int +static int32_t hash_access(hashp, action, key, val) HTAB *hashp; ACTION action; DBT *key, *val; { - register BUFHEAD *rbufp; - BUFHEAD *bufp, *save_bufp; - register u_int16_t *bp; - register int n, ndx, off, size; - register char *kp; - u_int16_t pageno; + DBT page_key, page_val; + CURSOR cursor; + ITEM_INFO item_info; + u_int32_t bucket; + u_int32_t num_items; #ifdef HASH_STATISTICS hash_accesses++; #endif - off = hashp->BSIZE; - size = key->size; - kp = (char *)key->data; - rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0); - if (!rbufp) - return (ERROR); - save_bufp = rbufp; + num_items = 0; - /* Pin the bucket chain */ - rbufp->flags |= BUF_PIN; - for (bp = (u_int16_t *)rbufp->page, n = *bp++, ndx = 1; ndx < n;) - if (bp[1] >= REAL_KEY) { - /* Real key/data pair */ - if (size == off - *bp && - memcmp(kp, rbufp->page + *bp, size) == 0) + /* + * Set up item_info so that we're looking for space to add an item + * as we cycle through the pages looking for the key. + */ + if (action == HASH_PUT || action == HASH_PUTNEW) { + if (ISBIG(key->size + val->size, hashp)) + item_info.seek_size = PAIR_OVERHEAD; + else + item_info.seek_size = key->size + val->size; + } else + item_info.seek_size = 0; + item_info.seek_found_page = 0; + + bucket = __call_hash(hashp, (int8_t *)key->data, key->size); + + cursor.pagep = NULL; + __get_item_reset(hashp, &cursor); + + cursor.bucket = bucket; + while (1) { + __get_item_next(hashp, &cursor, &page_key, &page_val, &item_info); + if (item_info.status == ITEM_ERROR) + return (ABNORMAL); + if (item_info.status == ITEM_NO_MORE) + break; + num_items++; + if (item_info.key_off == BIGPAIR) { + /* + * !!! + * 0 is a valid index. + */ + if (__find_bigpair(hashp, &cursor, (int8_t *)key->data, + key->size) > 0) goto found; - off = bp[1]; + } else if (key->size == page_key.size && + !memcmp(key->data, page_key.data, key->size)) + goto found; + } #ifdef HASH_STATISTICS - hash_collisions++; + hash_collisions++; #endif - bp += 2; - ndx += 2; - } else if (bp[1] == OVFLPAGE) { - rbufp = __get_buf(hashp, *bp, rbufp, 0); - if (!rbufp) { - save_bufp->flags &= ~BUF_PIN; - return (ERROR); - } - /* FOR LOOP INIT */ - bp = (u_int16_t *)rbufp->page; - n = *bp++; - ndx = 1; - off = hashp->BSIZE; - } else if (bp[1] < REAL_KEY) { - if ((ndx = - __find_bigpair(hashp, rbufp, ndx, kp, size)) > 0) - goto found; - if (ndx == -2) { - bufp = rbufp; - if (!(pageno = - __find_last_page(hashp, &bufp))) { - ndx = 0; - rbufp = bufp; - break; /* FOR */ - } - rbufp = __get_buf(hashp, pageno, bufp, 0); - if (!rbufp) { - save_bufp->flags &= ~BUF_PIN; - return (ERROR); - } - /* FOR LOOP INIT */ - bp = (u_int16_t *)rbufp->page; - n = *bp++; - ndx = 1; - off = hashp->BSIZE; - } else { - save_bufp->flags &= ~BUF_PIN; - return (ERROR); - } - } + __get_item_done(hashp, &cursor); + + /* + * At this point, item_info will list either the last page in + * the chain, or the last page in the chain plus a pgno for where + * to find the first page in the chain with space for the + * item we wish to add. + */ /* Not found */ switch (action) { case HASH_PUT: case HASH_PUTNEW: - if (__addel(hashp, rbufp, key, val)) { - save_bufp->flags &= ~BUF_PIN; + if (__addel(hashp, &item_info, key, val, num_items, 0)) return (ERROR); - } else { - save_bufp->flags &= ~BUF_PIN; - return (SUCCESS); - } + break; case HASH_GET: case HASH_DELETE: default: - save_bufp->flags &= ~BUF_PIN; return (ABNORMAL); } -found: + if (item_info.caused_expand) + __expand_table(hashp); + return (SUCCESS); + +found: __get_item_done(hashp, &cursor); + switch (action) { case HASH_PUTNEW: - save_bufp->flags &= ~BUF_PIN; + /* mpool_put(hashp->mp, pagep, 0); */ return (ABNORMAL); case HASH_GET: - bp = (u_int16_t *)rbufp->page; - if (bp[ndx + 1] < REAL_KEY) { - if (__big_return(hashp, rbufp, ndx, val, 0)) + if (item_info.key_off == BIGPAIR) { + if (__big_return(hashp, &item_info, val, 0)) return (ERROR); } else { - val->data = (u_char *)rbufp->page + (int)bp[ndx + 1]; - val->size = bp[ndx] - bp[ndx + 1]; + val->data = page_val.data; + val->size = page_val.size; } + /* *** data may not be available! */ break; case HASH_PUT: - if ((__delpair(hashp, rbufp, ndx)) || - (__addel(hashp, rbufp, key, val))) { - save_bufp->flags &= ~BUF_PIN; + if (__delpair(hashp, &cursor, &item_info) || + __addel(hashp, &item_info, key, val, UNKNOWN, 0)) return (ERROR); - } + __get_item_done(hashp, &cursor); + if (item_info.caused_expand) + __expand_table(hashp); break; case HASH_DELETE: - if (__delpair(hashp, rbufp, ndx)) + if (__delpair(hashp, &cursor, &item_info)) return (ERROR); break; default: abort(); } - save_bufp->flags &= ~BUF_PIN; return (SUCCESS); } -static int -hash_seq(dbp, key, data, flag) +/* ****************** CURSORS ********************************** */ +CURSOR * +__cursor_creat(dbp) const DB *dbp; - DBT *key, *data; - u_int32_t flag; { - register u_int32_t bucket; - register BUFHEAD *bufp; + CURSOR *new_curs; HTAB *hashp; - u_int16_t *bp, ndx; + new_curs = (CURSOR *)malloc(sizeof(struct cursor_t)); + if (!new_curs) + return NULL; + new_curs->internal = + (struct item_info *)malloc(sizeof(struct item_info)); + if (!new_curs->internal) { + free(new_curs); + return NULL; + } + new_curs->get = cursor_get; + new_curs->delete = cursor_delete; + + new_curs->bucket = 0; + new_curs->pgno = INVALID_PGNO; + new_curs->ndx = 0; + new_curs->pgndx = 0; + new_curs->pagep = NULL; + + /* place onto queue of cursors */ hashp = (HTAB *)dbp->internal; - if (flag && flag != R_FIRST && flag != R_NEXT) { + TAILQ_INSERT_TAIL(&hashp->curs_queue, new_curs, queue); + + return new_curs; +} + +int32_t +cursor_get(dbp, cursorp, key, val, flags) + const DB *dbp; + CURSOR *cursorp; + DBT *key, *val; + u_int32_t flags; +{ + HTAB *hashp; + ITEM_INFO item_info; + + hashp = (HTAB *)dbp->internal; + + if (flags && flags != R_FIRST && flags != R_NEXT) { hashp->errno = errno = EINVAL; return (ERROR); } #ifdef HASH_STATISTICS hash_accesses++; #endif - if ((hashp->cbucket < 0) || (flag == R_FIRST)) { - hashp->cbucket = 0; - hashp->cndx = 1; - hashp->cpage = NULL; - } - - for (bp = NULL; !bp || !bp[0]; ) { - if (!(bufp = hashp->cpage)) { - for (bucket = hashp->cbucket; - bucket <= hashp->MAX_BUCKET; - bucket++, hashp->cndx = 1) { - bufp = __get_buf(hashp, bucket, NULL, 0); - if (!bufp) - return (ERROR); - hashp->cpage = bufp; - bp = (u_int16_t *)bufp->page; - if (bp[0]) - break; - } - hashp->cbucket = bucket; - if (hashp->cbucket > hashp->MAX_BUCKET) { - hashp->cbucket = -1; + + item_info.seek_size = 0; + + if (flags == R_FIRST) + __get_item_first(hashp, cursorp, key, val, &item_info); + else + __get_item_next(hashp, cursorp, key, val, &item_info); + + /* + * This needs to be changed around. As is, get_item_next advances + * the pointers on the page but this function actually advances + * bucket pointers. This works, since the only other place we + * use get_item_next is in hash_access which only deals with one + * bucket at a time. However, there is the problem that certain other + * functions (such as find_bigpair and delpair) depend on the + * pgndx member of the cursor. Right now, they are using pngdx - 1 + * since indices refer to the __next__ item that is to be fetched + * from the page. This is ugly, as you may have noticed, whoever + * you are. The best solution would be to depend on item_infos to + * deal with _current_ information, and have the cursors only + * deal with _next_ information. In that scheme, get_item_next + * would also advance buckets. Version 3... + */ + + + /* + * Must always enter this loop to do error handling and + * check for big key/data pair. + */ + while (1) { + if (item_info.status == ITEM_OK) { + if (item_info.key_off == BIGPAIR && + __big_keydata(hashp, cursorp->pagep, key, val, + item_info.pgndx)) return (ABNORMAL); - } - } else - bp = (u_int16_t *)hashp->cpage->page; -#ifdef DEBUG - assert(bp); - assert(bufp); -#endif - while (bp[hashp->cndx + 1] == OVFLPAGE) { - bufp = hashp->cpage = - __get_buf(hashp, bp[hashp->cndx], bufp, 0); - if (!bufp) - return (ERROR); - bp = (u_int16_t *)(bufp->page); - hashp->cndx = 1; - } - if (!bp[0]) { - hashp->cpage = NULL; - ++hashp->cbucket; - } + break; + } else if (item_info.status != ITEM_NO_MORE) + return (ABNORMAL); + + __put_page(hashp, cursorp->pagep, A_RAW, 0); + cursorp->ndx = cursorp->pgndx = 0; + cursorp->bucket++; + cursorp->pgno = INVALID_PGNO; + cursorp->pagep = NULL; + if (cursorp->bucket > hashp->hdr.max_bucket) + return (ABNORMAL); + __get_item_next(hashp, cursorp, key, val, &item_info); } - ndx = hashp->cndx; - if (bp[ndx + 1] < REAL_KEY) { - if (__big_keydata(hashp, bufp, key, data, 1)) - return (ERROR); - } else { - key->data = (u_char *)hashp->cpage->page + bp[ndx]; - key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx]; - data->data = (u_char *)hashp->cpage->page + bp[ndx + 1]; - data->size = bp[ndx] - bp[ndx + 1]; - ndx += 2; - if (ndx > bp[0]) { - hashp->cpage = NULL; - hashp->cbucket++; - hashp->cndx = 1; - } else - hashp->cndx = ndx; - } - return (SUCCESS); + + __get_item_done(hashp, cursorp); + return (0); +} + +int32_t +cursor_delete(dbp, cursor, flags) + const DB *dbp; + CURSOR *cursor; + u_int32_t flags; +{ + return (0); +} + +static int32_t +hash_seq(dbp, key, val, flag) + const DB *dbp; + DBT *key, *val; + u_int32_t flag; +{ + HTAB *hashp; + + /* + * Seq just uses the default cursor to go sequecing through the + * database. Note that the default cursor is the first in the list. + */ + + hashp = (HTAB *)dbp->internal; + if (!hashp->seq_cursor) + hashp->seq_cursor = __cursor_creat(dbp); + + return (hashp->seq_cursor->get(dbp, hashp->seq_cursor, key, val, flag)); } /********************************* UTILITIES ************************/ @@ -806,127 +933,61 @@ * 0 ==> OK * -1 ==> Error */ -extern int +int32_t __expand_table(hashp) HTAB *hashp; { u_int32_t old_bucket, new_bucket; - int dirsize, new_segnum, spare_ndx; + int32_t spare_ndx; #ifdef HASH_STATISTICS hash_expansions++; #endif - new_bucket = ++hashp->MAX_BUCKET; - old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK); + new_bucket = ++hashp->hdr.max_bucket; + old_bucket = (hashp->hdr.max_bucket & hashp->hdr.low_mask); - new_segnum = new_bucket >> hashp->SSHIFT; + /* Get a page for this new bucket */ + if (__new_page(hashp, new_bucket, A_BUCKET) != 0) + return (-1); - /* Check if we need a new segment */ - if (new_segnum >= hashp->nsegs) { - /* Check if we need to expand directory */ - if (new_segnum >= hashp->DSIZE) { - /* Reallocate directory */ - dirsize = hashp->DSIZE * sizeof(SEGMENT *); - if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1)) - return (-1); - hashp->DSIZE = dirsize << 1; - } - if ((hashp->dir[new_segnum] = - (SEGMENT)calloc(hashp->SGSIZE, sizeof(SEGMENT))) == NULL) - return (-1); - hashp->exsegs++; - hashp->nsegs++; - } /* - * If the split point is increasing (MAX_BUCKET's log base 2 - * * increases), we need to copy the current contents of the spare + * If the split point is increasing (hdr.max_bucket's log base 2 + * increases), we need to copy the current contents of the spare * split bucket to the next bucket. */ - spare_ndx = __log2(hashp->MAX_BUCKET + 1); - if (spare_ndx > hashp->OVFL_POINT) { - hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT]; - hashp->OVFL_POINT = spare_ndx; + spare_ndx = __log2(hashp->hdr.max_bucket + 1); + if (spare_ndx > hashp->hdr.ovfl_point) { + hashp->hdr.spares[spare_ndx] = hashp->hdr.spares[hashp->hdr.ovfl_point]; + hashp->hdr.ovfl_point = spare_ndx; } - - if (new_bucket > hashp->HIGH_MASK) { + if (new_bucket > hashp->hdr.high_mask) { /* Starting a new doubling */ - hashp->LOW_MASK = hashp->HIGH_MASK; - hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK; + hashp->hdr.low_mask = hashp->hdr.high_mask; + hashp->hdr.high_mask = new_bucket | hashp->hdr.low_mask; + } + if (BUCKET_TO_PAGE(new_bucket) > MAX_PAGES(hashp)) { + fprintf(stderr, "hash: Cannot allocate new bucket. Pages exhausted.\n"); + return (-1); } /* Relocate records to the new bucket */ return (__split_page(hashp, old_bucket, new_bucket)); } -/* - * If realloc guarantees that the pointer is not destroyed if the realloc - * fails, then this routine can go away. - */ -static void * -hash_realloc(p_ptr, oldsize, newsize) - SEGMENT **p_ptr; - int oldsize, newsize; -{ - register void *p; - - if (p = malloc(newsize)) { - memmove(p, *p_ptr, oldsize); - memset((char *)p + oldsize, 0, newsize - oldsize); - free(*p_ptr); - *p_ptr = p; - } - return (p); -} - -extern u_int32_t +u_int32_t __call_hash(hashp, k, len) HTAB *hashp; - char *k; - int len; + int8_t *k; + int32_t len; { - int n, bucket; + int32_t n, bucket; n = hashp->hash(k, len); - bucket = n & hashp->HIGH_MASK; - if (bucket > hashp->MAX_BUCKET) - bucket = bucket & hashp->LOW_MASK; + bucket = n & hashp->hdr.high_mask; + if (bucket > hashp->hdr.max_bucket) + bucket = bucket & hashp->hdr.low_mask; return (bucket); } -/* - * Allocate segment table. On error, destroy the table and set errno. - * - * Returns 0 on success - */ -static int -alloc_segs(hashp, nsegs) - HTAB *hashp; - int nsegs; -{ - register int i; - register SEGMENT store; - - int save_errno; - - if ((hashp->dir = - (SEGMENT *)calloc(hashp->DSIZE, sizeof(SEGMENT *))) == NULL) { - save_errno = errno; - (void)hdestroy(hashp); - errno = save_errno; - return (-1); - } - /* Allocate segments */ - if ((store = - (SEGMENT)calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) { - save_errno = errno; - (void)hdestroy(hashp); - errno = save_errno; - return (-1); - } - for (i = 0; i < nsegs; i++, hashp->nsegs++) - hashp->dir[i] = &store[i << hashp->SSHIFT]; - return (0); -} - #if BYTE_ORDER == LITTLE_ENDIAN /* * Hashp->hdr needs to be byteswapped. @@ -935,16 +996,13 @@ swap_header_copy(srcp, destp) HASHHDR *srcp, *destp; { - int i; + int32_t i; P_32_COPY(srcp->magic, destp->magic); P_32_COPY(srcp->version, destp->version); P_32_COPY(srcp->lorder, destp->lorder); P_32_COPY(srcp->bsize, destp->bsize); P_32_COPY(srcp->bshift, destp->bshift); - P_32_COPY(srcp->dsize, destp->dsize); - P_32_COPY(srcp->ssize, destp->ssize); - P_32_COPY(srcp->sshift, destp->sshift); P_32_COPY(srcp->ovfl_point, destp->ovfl_point); P_32_COPY(srcp->last_freed, destp->last_freed); P_32_COPY(srcp->max_bucket, destp->max_bucket); @@ -965,7 +1023,7 @@ HTAB *hashp; { HASHHDR *hdrp; - int i; + int32_t i; hdrp = &hashp->hdr; @@ -974,9 +1032,6 @@ M_32_SWAP(hdrp->lorder); M_32_SWAP(hdrp->bsize); M_32_SWAP(hdrp->bshift); - M_32_SWAP(hdrp->dsize); - M_32_SWAP(hdrp->ssize); - M_32_SWAP(hdrp->sshift); M_32_SWAP(hdrp->ovfl_point); M_32_SWAP(hdrp->last_freed); M_32_SWAP(hdrp->max_bucket); @@ -991,4 +1046,4 @@ M_16_SWAP(hdrp->bitmaps[i]); } } -#endif +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ diff -u -r -N bdb185/db.1.85/hash/hash.h bdb186/db.1.86/hash/hash.h --- bdb185/db.1.85/hash/hash.h 1994-06-24 08:12:29.000000000 -0700 +++ bdb186/db.1.86/hash/hash.h 1997-01-04 11:27:56.000000000 -0800 @@ -33,89 +33,78 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)hash.h 8.3 (Berkeley) 5/31/94 + * @(#)hash.h 8.4 (Berkeley) 11/2/95 */ +#include + +#include +#include "compat.h" + /* Operations */ typedef enum { HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT } ACTION; -/* Buffer Management structures */ -typedef struct _bufhead BUFHEAD; +/* cursor structure */ +typedef struct cursor_t { + TAILQ_ENTRY(cursor_t) queue; + int (*get) __P((const DB *, struct cursor_t *, DBT *, DBT *, \ + u_int32_t)); + int (*delete) __P((const DB *, struct cursor_t *, u_int32_t)); + pgno_t bucket; + pgno_t pgno; + indx_t ndx; + indx_t pgndx; + u_int16_t *pagep; + void *internal; +} CURSOR; -struct _bufhead { - BUFHEAD *prev; /* LRU links */ - BUFHEAD *next; /* LRU links */ - BUFHEAD *ovfl; /* Overflow page buffer header */ - u_int32_t addr; /* Address of this page */ - char *page; /* Actual page data */ - char flags; -#define BUF_MOD 0x0001 -#define BUF_DISK 0x0002 -#define BUF_BUCKET 0x0004 -#define BUF_PIN 0x0008 -}; #define IS_BUCKET(X) ((X) & BUF_BUCKET) - -typedef BUFHEAD **SEGMENT; +#define IS_VALID(X) (!((X) & BUF_INVALID)) /* Hash Table Information */ -typedef struct hashhdr { /* Disk resident portion */ - int magic; /* Magic NO for hash tables */ - int version; /* Version ID */ - u_int32_t lorder; /* Byte Order */ - int bsize; /* Bucket/Page Size */ - int bshift; /* Bucket shift */ - int dsize; /* Directory Size */ - int ssize; /* Segment Size */ - int sshift; /* Segment shift */ - int ovfl_point; /* Where overflow pages are being - * allocated */ - int last_freed; /* Last overflow page freed */ - int max_bucket; /* ID of Maximum bucket in use */ - int high_mask; /* Mask to modulo into entire table */ - int low_mask; /* Mask to modulo into lower half of - * table */ - int ffactor; /* Fill factor */ - int nkeys; /* Number of keys in hash table */ - int hdrpages; /* Size of table header */ - int h_charkey; /* value of hash(CHARKEY) */ -#define NCACHED 32 /* number of bit maps and spare - * points */ - int spares[NCACHED];/* spare pages for overflow */ - u_int16_t bitmaps[NCACHED]; /* address of overflow page - * bitmaps */ +typedef struct hashhdr { /* Disk resident portion */ + int32_t magic; /* Magic NO for hash tables */ + int32_t version; /* Version ID */ + int32_t lorder; /* Byte Order */ + int32_t bsize; /* Bucket/Page Size */ + int32_t bshift; /* Bucket shift */ + int32_t ovfl_point; /* Where overflow pages are being allocated */ + int32_t last_freed; /* Last overflow page freed */ + int32_t max_bucket; /* ID of Maximum bucket in use */ + int32_t high_mask; /* Mask to modulo into entire table */ + int32_t low_mask; /* Mask to modulo into lower half of table */ + int32_t ffactor; /* Fill factor */ + int32_t nkeys; /* Number of keys in hash table */ + int32_t hdrpages; /* Size of table header */ + int32_t h_charkey; /* value of hash(CHARKEY) */ +#define NCACHED 32 /* number of bit maps and spare points */ + int32_t spares[NCACHED];/* spare pages for overflow */ + u_int16_t bitmaps[NCACHED]; /* address of overflow page bitmaps */ } HASHHDR; -typedef struct htab { /* Memory resident data structure */ - HASHHDR hdr; /* Header */ - int nsegs; /* Number of allocated segments */ - int exsegs; /* Number of extra allocated - * segments */ - u_int32_t /* Hash function */ - (*hash)__P((const void *, size_t)); - int flags; /* Flag values */ - int fp; /* File pointer */ - char *tmp_buf; /* Temporary Buffer for BIG data */ - char *tmp_key; /* Temporary Buffer for BIG keys */ - BUFHEAD *cpage; /* Current page */ - int cbucket; /* Current bucket */ - int cndx; /* Index of next item on cpage */ - int errno; /* Error Number -- for DBM - * compatability */ - int new_file; /* Indicates if fd is backing store - * or no */ - int save_file; /* Indicates whether we need to flush - * file at - * exit */ - u_int32_t *mapp[NCACHED]; /* Pointers to page maps */ - int nmaps; /* Initial number of bitmaps */ - int nbufs; /* Number of buffers left to - * allocate */ - BUFHEAD bufhead; /* Header of buffer lru list */ - SEGMENT *dir; /* Hash Bucket directory */ +typedef struct htab { /* Memory resident data structure */ + TAILQ_HEAD(_cursor_queue, cursor_t) curs_queue; + HASHHDR hdr; /* Header */ + u_int32_t (*hash) __P((const void *, size_t)); /* Hash Function */ + int32_t flags; /* Flag values */ + int32_t fp; /* File pointer */ + char *fname; /* File path */ + char *bigdata_buf; /* Temporary Buffer for BIG data */ + int32_t bigdata_len; /* Length of bigdata_buf */ + char *bigkey_buf; /* Temporary Buffer for BIG keys */ + int32_t bigkey_len; /* Length of bigkey_buf */ + u_int16_t *split_buf; /* Temporary buffer for splits */ + CURSOR *seq_cursor; /* Cursor used for hash_seq */ + int32_t errno; /* Error Number -- for DBM compatability */ + int32_t new_file; /* Indicates if fd is backing store or no */ + int32_t save_file; /* Indicates whether we need to flush file at + * exit */ + u_int32_t *mapp[NCACHED];/* Pointers to page maps */ + int32_t nmaps; /* Initial number of bitmaps */ + MPOOL *mp; /* mpool for buffer management */ } HTAB; /* @@ -124,7 +113,7 @@ #define MAX_BSIZE 65536 /* 2^16 */ #define MIN_BUFFERS 6 #define MINHDRSIZE 512 -#define DEF_BUFSIZE 65536 /* 64 K */ +#define DEF_CACHESIZE 65536 #define DEF_BUCKET_SIZE 4096 #define DEF_BUCKET_SHIFT 12 /* log2(BUCKET) */ #define DEF_SEGSIZE 256 @@ -136,16 +125,16 @@ #define CHARKEY "%$sniglet^&" #define NUMKEY 1038583 #define BYTE_SHIFT 3 -#define INT_TO_BYTE 2 -#define INT_BYTE_SHIFT 5 +#define INT32_T_TO_BYTE 2 +#define INT32_T_BYTE_SHIFT 5 #define ALL_SET ((u_int32_t)0xFFFFFFFF) #define ALL_CLEAR 0 -#define PTROF(X) ((BUFHEAD *)((ptrdiff_t)(X)&~0x3)) -#define ISMOD(X) ((u_int32_t)(ptrdiff_t)(X)&0x1) -#define DOMOD(X) ((X) = (char *)((ptrdiff_t)(X)|0x1)) -#define ISDISK(X) ((u_int32_t)(ptrdiff_t)(X)&0x2) -#define DODISK(X) ((X) = (char *)((ptrdiff_t)(X)|0x2)) +#define PTROF(X) ((BUFHEAD *)((ptr_t)(X)&~0x3)) +#define ISMOD(X) ((ptr_t)(X)&0x1) +#define DOMOD(X) ((X) = (int8_t *)((ptr_t)(X)|0x1)) +#define ISDISK(X) ((ptr_t)(X)&0x2) +#define DODISK(X) ((X) = (int8_t *)((ptr_t)(X)|0x2)) #define BITS_PER_MAP 32 @@ -170,124 +159,56 @@ #define OADDR_OF(S,O) ((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O)) #define BUCKET_TO_PAGE(B) \ - (B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((B)+1)-1] : 0) + ((B) + hashp->hdr.hdrpages + ((B) \ + ? hashp->hdr.spares[__log2((B)+1)-1] : 0)) #define OADDR_TO_PAGE(B) \ - BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B)); + (BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B))) + +#define POW2(N) (1 << (N)) /* - * page.h contains a detailed description of the page format. - * - * Normally, keys and data are accessed from offset tables in the top of - * each page which point to the beginning of the key and data. There are - * four flag values which may be stored in these offset tables which indicate - * the following: - * - * - * OVFLPAGE Rather than a key data pair, this pair contains - * the address of an overflow page. The format of - * the pair is: - * OVERFLOW_PAGE_NUMBER OVFLPAGE - * - * PARTIAL_KEY This must be the first key/data pair on a page - * and implies that page contains only a partial key. - * That is, the key is too big to fit on a single page - * so it starts on this page and continues on the next. - * The format of the page is: - * KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE - * - * KEY_OFF -- offset of the beginning of the key - * PARTIAL_KEY -- 1 - * OVFL_PAGENO - page number of the next overflow page - * OVFLPAGE -- 0 - * - * FULL_KEY This must be the first key/data pair on the page. It - * is used in two cases. - * - * Case 1: - * There is a complete key on the page but no data - * (because it wouldn't fit). The next page contains - * the data. - * - * Page format it: - * KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE - * - * KEY_OFF -- offset of the beginning of the key - * FULL_KEY -- 2 - * OVFL_PAGENO - page number of the next overflow page - * OVFLPAGE -- 0 - * - * Case 2: - * This page contains no key, but part of a large - * data field, which is continued on the next page. - * - * Page format it: - * DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE - * - * KEY_OFF -- offset of the beginning of the data on - * this page - * FULL_KEY -- 2 - * OVFL_PAGENO - page number of the next overflow page - * OVFLPAGE -- 0 - * - * FULL_KEY_DATA - * This must be the first key/data pair on the page. - * There are two cases: - * - * Case 1: - * This page contains a key and the beginning of the - * data field, but the data field is continued on the - * next page. - * - * Page format is: - * KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF - * - * KEY_OFF -- offset of the beginning of the key - * FULL_KEY_DATA -- 3 - * OVFL_PAGENO - page number of the next overflow page - * DATA_OFF -- offset of the beginning of the data - * - * Case 2: - * This page contains the last page of a big data pair. - * There is no key, only the tail end of the data - * on this page. - * - * Page format is: - * DATA_OFF FULL_KEY_DATA - * - * DATA_OFF -- offset of the beginning of the data on - * this page - * FULL_KEY_DATA -- 3 - * OVFL_PAGENO - page number of the next overflow page - * OVFLPAGE -- 0 - * - * OVFL_PAGENO and OVFLPAGE are optional (they are - * not present if there is no next page). + * There is no portable way to figure out the maximum value of a file + * offset, so we put it here. */ +#ifdef OFF_T_MAX +#define DB_OFF_T_MAX OFF_T_MAX +#else +#ifdef LONG_MAX +#define DB_OFF_T_MAX LONG_MAX +#else +#define DB_OFF_T_MAX 0xffffffff +#endif +#endif + +#define MAX_PAGES(H) (DB_OFF_T_MAX / (H)->hdr.bsize) + +/* Shorthands for accessing structure */ +#define METADATA_PGNO 0 +#define SPLIT_PGNO 0xFFFF + +typedef struct item_info { + pgno_t pgno; + pgno_t bucket; + indx_t ndx; + indx_t pgndx; + u_int8_t status; + int32_t seek_size; + pgno_t seek_found_page; + indx_t key_off; + indx_t data_off; + u_int8_t caused_expand; +} ITEM_INFO; + + +#define ITEM_ERROR 0 +#define ITEM_OK 1 +#define ITEM_NO_MORE 2 + +#define ITEM_GET_FIRST 0 +#define ITEM_GET_NEXT 1 +#define ITEM_GET_RESET 2 +#define ITEM_GET_DONE 3 +#define ITEM_GET_N 4 -#define OVFLPAGE 0 -#define PARTIAL_KEY 1 -#define FULL_KEY 2 -#define FULL_KEY_DATA 3 -#define REAL_KEY 4 - -/* Short hands for accessing structure */ -#define BSIZE hdr.bsize -#define BSHIFT hdr.bshift -#define DSIZE hdr.dsize -#define SGSIZE hdr.ssize -#define SSHIFT hdr.sshift -#define LORDER hdr.lorder -#define OVFL_POINT hdr.ovfl_point -#define LAST_FREED hdr.last_freed -#define MAX_BUCKET hdr.max_bucket -#define FFACTOR hdr.ffactor -#define HIGH_MASK hdr.high_mask -#define LOW_MASK hdr.low_mask -#define NKEYS hdr.nkeys -#define HDRPAGES hdr.hdrpages -#define SPARES hdr.spares -#define BITMAPS hdr.bitmaps -#define VERSION hdr.version -#define MAGIC hdr.magic -#define NEXT_FREE hdr.next_free -#define H_CHARKEY hdr.h_charkey +#define UNKNOWN 0xffffffff /* for num_items */ +#define NO_EXPAND 0xfffffffe diff -u -r -N bdb185/db.1.85/hash/hash_bigkey.c bdb186/db.1.86/hash/hash_bigkey.c --- bdb185/db.1.85/hash/hash_bigkey.c 1994-06-24 08:12:30.000000000 -0700 +++ bdb186/db.1.86/hash/hash_bigkey.c 1997-01-04 11:25:41.000000000 -0800 @@ -35,7 +35,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94"; +static char sccsid[] = "@(#)hash_bigkey.c 8.5 (Berkeley) 11/2/95"; #endif /* LIBC_SCCS and not lint */ /* @@ -55,11 +55,8 @@ * collect_key * collect_data */ +#include -#include - -#include -#include #include #include @@ -72,596 +69,424 @@ #include "page.h" #include "extern.h" -static int collect_key __P((HTAB *, BUFHEAD *, int, DBT *, int)); -static int collect_data __P((HTAB *, BUFHEAD *, int, int)); +static int32_t collect_key __P((HTAB *, PAGE16 *, int32_t, pgno_t *)); +static int32_t collect_data __P((HTAB *, PAGE16 *, int32_t)); /* * Big_insert * - * You need to do an insert and the key/data pair is too big + * You need to do an insert and the key/data pair is greater than + * MINFILL * the bucket size * * Returns: - * 0 ==> OK - *-1 ==> ERROR + * 0 ==> OK + * -1 ==> ERROR */ -extern int -__big_insert(hashp, bufp, key, val) +int32_t +__big_insert(hashp, pagep, key, val) HTAB *hashp; - BUFHEAD *bufp; + PAGE16 *pagep; const DBT *key, *val; { - register u_int16_t *p; - int key_size, n, val_size; - u_int16_t space, move_bytes, off; - char *cp, *key_data, *val_data; - - cp = bufp->page; /* Character pointer of p. */ - p = (u_int16_t *)cp; + size_t key_size, val_size; + indx_t key_move_bytes, val_move_bytes; + int8_t *key_data, *val_data, base_page; - key_data = (char *)key->data; + key_data = (int8_t *)key->data; key_size = key->size; - val_data = (char *)val->data; + val_data = (int8_t *)val->data; val_size = val->size; - /* First move the Key */ - for (space = FREESPACE(p) - BIGOVERHEAD; key_size; - space = FREESPACE(p) - BIGOVERHEAD) { - move_bytes = MIN(space, key_size); - off = OFFSET(p) - move_bytes; - memmove(cp + off, key_data, move_bytes); - key_size -= move_bytes; - key_data += move_bytes; - n = p[0]; - p[++n] = off; - p[0] = ++n; - FREESPACE(p) = off - PAGE_META(n); - OFFSET(p) = off; - p[n] = PARTIAL_KEY; - bufp = __add_ovflpage(hashp, bufp); - if (!bufp) + NUM_ENT(pagep) = NUM_ENT(pagep) + 1; + + for (base_page = 1; key_size + val_size;) { + /* Add a page! */ + pagep = + __add_bigpage(hashp, pagep, NUM_ENT(pagep) - 1, base_page); + if (!pagep) return (-1); - n = p[0]; - if (!key_size) - if (FREESPACE(p)) { - move_bytes = MIN(FREESPACE(p), val_size); - off = OFFSET(p) - move_bytes; - p[n] = off; - memmove(cp + off, val_data, move_bytes); - val_data += move_bytes; - val_size -= move_bytes; - p[n - 2] = FULL_KEY_DATA; - FREESPACE(p) = FREESPACE(p) - move_bytes; - OFFSET(p) = off; - } else - p[n - 2] = FULL_KEY; - p = (u_int16_t *)bufp->page; - cp = bufp->page; - bufp->flags |= BUF_MOD; - } - /* Now move the data */ - for (space = FREESPACE(p) - BIGOVERHEAD; val_size; - space = FREESPACE(p) - BIGOVERHEAD) { - move_bytes = MIN(space, val_size); - /* - * Here's the hack to make sure that if the data ends on the - * same page as the key ends, FREESPACE is at least one. - */ - if (space == val_size && val_size == val->size) - move_bytes--; - off = OFFSET(p) - move_bytes; - memmove(cp + off, val_data, move_bytes); - val_size -= move_bytes; - val_data += move_bytes; - n = p[0]; - p[++n] = off; - p[0] = ++n; - FREESPACE(p) = off - PAGE_META(n); - OFFSET(p) = off; - if (val_size) { - p[n] = FULL_KEY; - bufp = __add_ovflpage(hashp, bufp); - if (!bufp) - return (-1); - cp = bufp->page; - p = (u_int16_t *)cp; - } else - p[n] = FULL_KEY_DATA; - bufp->flags |= BUF_MOD; + /* There's just going to be one entry on this page. */ + NUM_ENT(pagep) = 1; + + /* Move the key's data. */ + key_move_bytes = MIN(FREESPACE(pagep), key_size); + /* Mark the page as to how much key & data is on this page. */ + BIGKEYLEN(pagep) = key_move_bytes; + val_move_bytes = + MIN(FREESPACE(pagep) - key_move_bytes, val_size); + BIGDATALEN(pagep) = val_move_bytes; + + /* Note big pages build beginning --> end, not vice versa. */ + if (key_move_bytes) + memmove(BIGKEY(pagep), key_data, key_move_bytes); + if (val_move_bytes) + memmove(BIGDATA(pagep), val_data, val_move_bytes); + + key_size -= key_move_bytes; + key_data += key_move_bytes; + val_size -= val_move_bytes; + val_data += val_move_bytes; + + base_page = 0; } + __put_page(hashp, pagep, A_RAW, 1); return (0); } /* - * Called when bufp's page contains a partial key (index should be 1) - * - * All pages in the big key/data pair except bufp are freed. We cannot - * free bufp because the page pointing to it is lost and we can't get rid - * of its pointer. + * Called when we need to delete a big pair. * * Returns: - * 0 => OK - *-1 => ERROR + * 0 => OK + * -1 => ERROR */ -extern int -__big_delete(hashp, bufp) +int32_t +#ifdef __STDC__ +__big_delete(HTAB *hashp, PAGE16 *pagep, indx_t ndx) +#else +__big_delete(hashp, pagep, ndx) HTAB *hashp; - BUFHEAD *bufp; + PAGE16 *pagep; + u_int32_t ndx; /* Index of big pair on base page. */ +#endif { - register BUFHEAD *last_bfp, *rbufp; - u_int16_t *bp, pageno; - int key_done, n; - - rbufp = bufp; - last_bfp = NULL; - bp = (u_int16_t *)bufp->page; - pageno = 0; - key_done = 0; - - while (!key_done || (bp[2] != FULL_KEY_DATA)) { - if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) - key_done = 1; - - /* - * If there is freespace left on a FULL_KEY_DATA page, then - * the data is short and fits entirely on this page, and this - * is the last page. - */ - if (bp[2] == FULL_KEY_DATA && FREESPACE(bp)) - break; - pageno = bp[bp[0] - 1]; - rbufp->flags |= BUF_MOD; - rbufp = __get_buf(hashp, pageno, rbufp, 0); - if (last_bfp) - __free_ovflpage(hashp, last_bfp); - last_bfp = rbufp; - if (!rbufp) - return (-1); /* Error. */ - bp = (u_int16_t *)rbufp->page; - } + PAGE16 *last_pagep; + + /* Get first page with big key/data. */ + pagep = __get_page(hashp, OADDR_TO_PAGE(DATA_OFF(pagep, ndx)), A_RAW); + if (!pagep) + return (-1); /* - * If we get here then rbufp points to the last page of the big - * key/data pair. Bufp points to the first one -- it should now be - * empty pointing to the next page after this pair. Can't free it - * because we don't have the page pointing to it. + * Traverse through the pages, freeing the previous one (except + * the first) at each new page. */ + while (NEXT_PGNO(pagep) != INVALID_PGNO) { + last_pagep = pagep; + pagep = __get_page(hashp, NEXT_PGNO(pagep), A_RAW); + if (!pagep) + return (-1); + __delete_page(hashp, last_pagep, A_OVFL); + } - /* This is information from the last page of the pair. */ - n = bp[0]; - pageno = bp[n - 1]; - - /* Now, bp is the first page of the pair. */ - bp = (u_int16_t *)bufp->page; - if (n > 2) { - /* There is an overflow page. */ - bp[1] = pageno; - bp[2] = OVFLPAGE; - bufp->ovfl = rbufp->ovfl; - } else - /* This is the last page. */ - bufp->ovfl = NULL; - n -= 2; - bp[0] = n; - FREESPACE(bp) = hashp->BSIZE - PAGE_META(n); - OFFSET(bp) = hashp->BSIZE - 1; - - bufp->flags |= BUF_MOD; - if (rbufp) - __free_ovflpage(hashp, rbufp); - if (last_bfp != rbufp) - __free_ovflpage(hashp, last_bfp); - - hashp->NKEYS--; + /* Free the last page in the chain. */ + __delete_page(hashp, pagep, A_OVFL); return (0); } + /* + * Given a key, indicates whether the big key at cursorp matches the + * given key. + * * Returns: - * 0 = key not found - * -1 = get next overflow page - * -2 means key not found and this is big key/data - * -3 error + * 1 = Found! + * 0 = Key not found + * -1 error */ -extern int -__find_bigpair(hashp, bufp, ndx, key, size) +int32_t +__find_bigpair(hashp, cursorp, key, size) HTAB *hashp; - BUFHEAD *bufp; - int ndx; - char *key; - int size; + CURSOR *cursorp; + int8_t *key; + int32_t size; { - register u_int16_t *bp; - register char *p; - int ksize; + PAGE16 *pagep, *hold_pagep; + pgno_t next_pgno; + int32_t ksize; u_int16_t bytes; - char *kkey; + int8_t *kkey; - bp = (u_int16_t *)bufp->page; - p = bufp->page; ksize = size; kkey = key; + bytes = 0; - for (bytes = hashp->BSIZE - bp[ndx]; - bytes <= size && bp[ndx + 1] == PARTIAL_KEY; - bytes = hashp->BSIZE - bp[ndx]) { - if (memcmp(p + bp[ndx], kkey, bytes)) - return (-2); - kkey += bytes; - ksize -= bytes; - bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0); - if (!bufp) - return (-3); - p = bufp->page; - bp = (u_int16_t *)p; - ndx = 1; + hold_pagep = NULL; + /* Chances are, hashp->cpage is the base page. */ + if (cursorp->pagep) + pagep = hold_pagep = cursorp->pagep; + else { + pagep = __get_page(hashp, cursorp->pgno, A_RAW); + if (!pagep) + return (-1); } - if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) { + /* + * Now, get the first page with the big stuff on it. + * + * XXX + * KLUDGE: we know that cursor is looking at the _next_ item, so + * we have to look at pgndx - 1. + */ + next_pgno = OADDR_TO_PAGE(DATA_OFF(pagep, (cursorp->pgndx - 1))); + if (!hold_pagep) + __put_page(hashp, pagep, A_RAW, 0); + pagep = __get_page(hashp, next_pgno, A_RAW); + if (!pagep) + return (-1); + + /* While there are both keys to compare. */ + while ((ksize > 0) && (BIGKEYLEN(pagep))) { + if (ksize < KEY_OFF(pagep, 0) || + memcmp(BIGKEY(pagep), kkey, BIGKEYLEN(pagep))) { + __put_page(hashp, pagep, A_RAW, 0); + return (0); + } + kkey += BIGKEYLEN(pagep); + ksize -= BIGKEYLEN(pagep); + if (NEXT_PGNO(pagep) != INVALID_PGNO) { + next_pgno = NEXT_PGNO(pagep); + __put_page(hashp, pagep, A_RAW, 0); + pagep = __get_page(hashp, next_pgno, A_RAW); + if (!pagep) + return (-1); + } + } + __put_page(hashp, pagep, A_RAW, 0); +#ifdef DEBUG + assert(ksize >= 0); +#endif + if (ksize != 0) { #ifdef HASH_STATISTICS ++hash_collisions; #endif - return (-2); + return (0); } else - return (ndx); + return (1); } /* - * Given the buffer pointer of the first overflow page of a big pair, - * find the end of the big pair - * - * This will set bpp to the buffer header of the last page of the big pair. - * It will return the pageno of the overflow page following the last page - * of the pair; 0 if there isn't any (i.e. big pair is the last key in the - * bucket) + * Fill in the key and data for this big pair. */ -extern u_int16_t -__find_last_page(hashp, bpp) +int32_t +__big_keydata(hashp, pagep, key, val, ndx) HTAB *hashp; - BUFHEAD **bpp; + PAGE16 *pagep; + DBT *key, *val; + int32_t ndx; { - BUFHEAD *bufp; - u_int16_t *bp, pageno; - int n; - - bufp = *bpp; - bp = (u_int16_t *)bufp->page; - for (;;) { - n = bp[0]; - - /* - * This is the last page if: the tag is FULL_KEY_DATA and - * either only 2 entries OVFLPAGE marker is explicit there - * is freespace on the page. - */ - if (bp[2] == FULL_KEY_DATA && - ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp)))) - break; - - pageno = bp[n - 1]; - bufp = __get_buf(hashp, pageno, bufp, 0); - if (!bufp) - return (0); /* Need to indicate an error! */ - bp = (u_int16_t *)bufp->page; - } + ITEM_INFO ii; + PAGE16 *key_pagep; + pgno_t last_page; + + key_pagep = + __get_page(hashp, OADDR_TO_PAGE(DATA_OFF(pagep, ndx)), A_RAW); + if (!key_pagep) + return (-1); + key->size = collect_key(hashp, key_pagep, 0, &last_page); + key->data = hashp->bigkey_buf; + __put_page(hashp, key_pagep, A_RAW, 0); - *bpp = bufp; - if (bp[0] > 2) - return (bp[3]); - else - return (0); + if (key->size == -1) + return (-1); + + /* Create an item_info to direct __big_return to the beginning pgno. */ + ii.pgno = last_page; + return (__big_return(hashp, &ii, val, 1)); } /* - * Return the data for the key/data pair that begins on this page at this - * index (index should always be 1). + * Return the big key on page, ndx. */ -extern int -__big_return(hashp, bufp, ndx, val, set_current) +int32_t +#ifdef __STDC__ +__get_bigkey(HTAB *hashp, PAGE16 *pagep, indx_t ndx, DBT *key) +#else +__get_bigkey(hashp, pagep, ndx, key) HTAB *hashp; - BUFHEAD *bufp; - int ndx; - DBT *val; - int set_current; + PAGE16 *pagep; + u_int32_t ndx; + DBT *key; +#endif { - BUFHEAD *save_p; - u_int16_t *bp, len, off, save_addr; - char *tp; - - bp = (u_int16_t *)bufp->page; - while (bp[ndx + 1] == PARTIAL_KEY) { - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - ndx = 1; - } + PAGE16 *key_pagep; - if (bp[ndx + 1] == FULL_KEY) { - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - save_p = bufp; - save_addr = save_p->addr; - off = bp[1]; - len = 0; - } else - if (!FREESPACE(bp)) { - /* - * This is a hack. We can't distinguish between - * FULL_KEY_DATA that contains complete data or - * incomplete data, so we require that if the data - * is complete, there is at least 1 byte of free - * space left. - */ - off = bp[bp[0]]; - len = bp[1] - off; - save_p = bufp; - save_addr = bufp->addr; - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - } else { - /* The data is all on one page. */ - tp = (char *)bp; - off = bp[bp[0]]; - val->data = (u_char *)tp + off; - val->size = bp[1] - off; - if (set_current) { - if (bp[0] == 2) { /* No more buckets in - * chain */ - hashp->cpage = NULL; - hashp->cbucket++; - hashp->cndx = 1; - } else { - hashp->cpage = __get_buf(hashp, - bp[bp[0] - 1], bufp, 0); - if (!hashp->cpage) - return (-1); - hashp->cndx = 1; - if (!((u_int16_t *) - hashp->cpage->page)[0]) { - hashp->cbucket++; - hashp->cpage = NULL; - } - } - } - return (0); - } - - val->size = collect_data(hashp, bufp, (int)len, set_current); - if (val->size == -1) - return (-1); - if (save_p->addr != save_addr) { - /* We are pretty short on buffers. */ - errno = EINVAL; /* OUT OF BUFFERS */ + key_pagep = + __get_page(hashp, OADDR_TO_PAGE(DATA_OFF(pagep, ndx)), A_RAW); + if (!pagep) return (-1); - } - memmove(hashp->tmp_buf, (save_p->page) + off, len); - val->data = (u_char *)hashp->tmp_buf; + key->size = collect_key(hashp, key_pagep, 0, NULL); + key->data = hashp->bigkey_buf; + + __put_page(hashp, key_pagep, A_RAW, 0); + return (0); } + /* - * Count how big the total datasize is by recursing through the pages. Then - * allocate a buffer and copy the data as you recurse up. + * Return the big key and data indicated in item_info. */ -static int -collect_data(hashp, bufp, len, set) +int32_t +__big_return(hashp, item_info, val, on_bigkey_page) HTAB *hashp; - BUFHEAD *bufp; - int len, set; + ITEM_INFO *item_info; + DBT *val; + int32_t on_bigkey_page; { - register u_int16_t *bp; - register char *p; - BUFHEAD *xbp; - u_int16_t save_addr; - int mylen, totlen; - - p = bufp->page; - bp = (u_int16_t *)p; - mylen = hashp->BSIZE - bp[1]; - save_addr = bufp->addr; - - if (bp[2] == FULL_KEY_DATA) { /* End of Data */ - totlen = len + mylen; - if (hashp->tmp_buf) - free(hashp->tmp_buf); - if ((hashp->tmp_buf = (char *)malloc(totlen)) == NULL) + PAGE16 *pagep; + pgno_t next_pgno; + + if (!on_bigkey_page) { + /* Get first page with big pair on it. */ + pagep = __get_page(hashp, + OADDR_TO_PAGE(item_info->data_off), A_RAW); + if (!pagep) return (-1); - if (set) { - hashp->cndx = 1; - if (bp[0] == 2) { /* No more buckets in chain */ - hashp->cpage = NULL; - hashp->cbucket++; - } else { - hashp->cpage = - __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!hashp->cpage) - return (-1); - else if (!((u_int16_t *)hashp->cpage->page)[0]) { - hashp->cbucket++; - hashp->cpage = NULL; - } - } - } } else { - xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!xbp || ((totlen = - collect_data(hashp, xbp, len + mylen, set)) < 1)) + pagep = __get_page(hashp, item_info->pgno, A_RAW); + if (!pagep) return (-1); } - if (bufp->addr != save_addr) { - errno = EINVAL; /* Out of buffers. */ - return (-1); + + /* Traverse through the bigkey pages until a page with data is found. */ + while (!BIGDATALEN(pagep)) { + next_pgno = NEXT_PGNO(pagep); + __put_page(hashp, pagep, A_RAW, 0); + pagep = __get_page(hashp, next_pgno, A_RAW); + if (!pagep) + return (-1); } - memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], mylen); - return (totlen); -} -/* - * Fill in the key and data for this big pair. - */ -extern int -__big_keydata(hashp, bufp, key, val, set) - HTAB *hashp; - BUFHEAD *bufp; - DBT *key, *val; - int set; -{ - key->size = collect_key(hashp, bufp, 0, val, set); - if (key->size == -1) + val->size = collect_data(hashp, pagep, 0); + if (val->size < 1) return (-1); - key->data = (u_char *)hashp->tmp_key; + val->data = (void *)hashp->bigdata_buf; + + __put_page(hashp, pagep, A_RAW, 0); return (0); } /* - * Count how big the total key size is by recursing through the pages. Then - * collect the data, allocate a buffer and copy the key as you recurse up. + * Given a page with a big key on it, traverse through the pages counting data + * length, and collect all of the data on the way up. Store the key in + * hashp->bigkey_buf. last_page indicates to the calling function what the + * last page with key on it is; this will help if you later want to retrieve + * the data portion. + * + * Does the work for __get_bigkey. + * + * Return total length of data; -1 if error. */ -static int -collect_key(hashp, bufp, len, val, set) +static int32_t +collect_key(hashp, pagep, len, last_page) HTAB *hashp; - BUFHEAD *bufp; - int len; - DBT *val; - int set; + PAGE16 *pagep; + int32_t len; + pgno_t *last_page; { - BUFHEAD *xbp; - char *p; - int mylen, totlen; - u_int16_t *bp, save_addr; - - p = bufp->page; - bp = (u_int16_t *)p; - mylen = hashp->BSIZE - bp[1]; - - save_addr = bufp->addr; - totlen = len + mylen; - if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) { /* End of Key. */ - if (hashp->tmp_key != NULL) - free(hashp->tmp_key); - if ((hashp->tmp_key = (char *)malloc(totlen)) == NULL) - return (-1); - if (__big_return(hashp, bufp, 1, val, set)) - return (-1); - } else { - xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!xbp || ((totlen = - collect_key(hashp, xbp, totlen, val, set)) < 1)) - return (-1); + PAGE16 *next_pagep; + int32_t totlen, retval; + pgno_t next_pgno; +#ifdef DEBUG + pgno_t save_addr; +#endif + + totlen = len + BIGKEYLEN(pagep); + + /* If this is the last page with key. */ + if (BIGDATALEN(pagep)) { + if (totlen > hashp->bigkey_len) { + hashp->bigkey_buf = + (char *)realloc(hashp->bigkey_buf, totlen); + hashp->bigkey_len = totlen; + if (!hashp->bigkey_buf) { + hashp->bigkey_len = 0; + return (-1); + } + } + memcpy(hashp->bigkey_buf + len, + BIGKEY(pagep), BIGKEYLEN(pagep)); + if (last_page) + *last_page = ADDR(pagep); + return (totlen); } - if (bufp->addr != save_addr) { - errno = EINVAL; /* MIS -- OUT OF BUFFERS */ - return (-1); + + /* Key filled up all of last key page, so we've gone 1 too far. */ + if (BIGKEYLEN(pagep) == 0) { + if (hashp->bigkey_len < totlen) { + hashp->bigkey_buf = realloc(hashp->bigkey_buf, totlen); + hashp->bigkey_len = hashp->bigkey_buf ? totlen : 0; + } + return (hashp->bigkey_buf ? totlen : -1); } - memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], mylen); - return (totlen); + + /* Set pagep to the next page in the chain. */ + if (last_page) + *last_page = ADDR(pagep); + next_pgno = NEXT_PGNO(pagep); + next_pagep = __get_page(hashp, next_pgno, A_RAW); + if (!next_pagep) + return (-1); +#ifdef DEBUG + save_addr = ADDR(pagep); +#endif + retval = collect_key(hashp, next_pagep, totlen, last_page); + +#ifdef DEBUG + assert(save_addr == ADDR(pagep)); +#endif + memcpy(hashp->bigkey_buf + len, BIGKEY(pagep), BIGKEYLEN(pagep)); + __put_page(hashp, next_pagep, A_RAW, 0); + + return (retval); } /* - * Returns: - * 0 => OK - * -1 => error + * Given a page with big data on it, recur through the pages counting data + * length, and collect all of the data on the way up. Store the data in + * hashp->bigdata_buf. + * + * Does the work for __big_return. + * + * Return total length of data; -1 if error. */ -extern int -__big_split(hashp, op, np, big_keyp, addr, obucket, ret) +static int32_t +collect_data(hashp, pagep, len) HTAB *hashp; - BUFHEAD *op; /* Pointer to where to put keys that go in old bucket */ - BUFHEAD *np; /* Pointer to new bucket page */ - /* Pointer to first page containing the big key/data */ - BUFHEAD *big_keyp; - int addr; /* Address of big_keyp */ - u_int32_t obucket;/* Old Bucket */ - SPLIT_RETURN *ret; + PAGE16 *pagep; + int32_t len; { - register BUFHEAD *tmpp; - register u_int16_t *tp; - BUFHEAD *bp; - DBT key, val; - u_int32_t change; - u_int16_t free_space, n, off; + PAGE16 *next_pagep; + int32_t totlen, retval; + pgno_t next_pgno; +#ifdef DEBUG + pgno_t save_addr; +#endif - bp = big_keyp; + totlen = len + BIGDATALEN(pagep); - /* Now figure out where the big key/data goes */ - if (__big_keydata(hashp, big_keyp, &key, &val, 0)) - return (-1); - change = (__call_hash(hashp, key.data, key.size) != obucket); + /* If there is no next page. */ + if (NEXT_PGNO(pagep) == INVALID_PGNO) { + if (totlen > hashp->bigdata_len) { + hashp->bigdata_buf = + (char *)realloc(hashp->bigdata_buf, totlen); + hashp->bigdata_len = totlen; + if (!hashp->bigdata_buf) { + hashp->bigdata_len = 0; + return (-1); + } + } + memcpy(hashp->bigdata_buf + totlen - BIGDATALEN(pagep), + BIGDATA(pagep), BIGDATALEN(pagep)); + return (totlen); + } - if (ret->next_addr = __find_last_page(hashp, &big_keyp)) { - if (!(ret->nextp = - __get_buf(hashp, ret->next_addr, big_keyp, 0))) - return (-1);; - } else - ret->nextp = NULL; + /* Set pagep to the next page in the chain. */ + next_pgno = NEXT_PGNO(pagep); + next_pagep = __get_page(hashp, next_pgno, A_RAW); + if (!next_pagep) + return (-1); - /* Now make one of np/op point to the big key/data pair */ #ifdef DEBUG - assert(np->ovfl == NULL); -#endif - if (change) - tmpp = np; - else - tmpp = op; - - tmpp->flags |= BUF_MOD; -#ifdef DEBUG1 - (void)fprintf(stderr, - "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr, - (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0)); + save_addr = ADDR(pagep); #endif - tmpp->ovfl = bp; /* one of op/np point to big_keyp */ - tp = (u_int16_t *)tmpp->page; + retval = collect_data(hashp, next_pagep, totlen); #ifdef DEBUG - assert(FREESPACE(tp) >= OVFLSIZE); + assert(save_addr == ADDR(pagep)); #endif - n = tp[0]; - off = OFFSET(tp); - free_space = FREESPACE(tp); - tp[++n] = (u_int16_t)addr; - tp[++n] = OVFLPAGE; - tp[0] = n; - OFFSET(tp) = off; - FREESPACE(tp) = free_space - OVFLSIZE; - - /* - * Finally, set the new and old return values. BIG_KEYP contains a - * pointer to the last page of the big key_data pair. Make sure that - * big_keyp has no following page (2 elements) or create an empty - * following page. - */ + memcpy(hashp->bigdata_buf + totlen - BIGDATALEN(pagep), + BIGDATA(pagep), BIGDATALEN(pagep)); + __put_page(hashp, next_pagep, A_RAW, 0); - ret->newp = np; - ret->oldp = op; - - tp = (u_int16_t *)big_keyp->page; - big_keyp->flags |= BUF_MOD; - if (tp[0] > 2) { - /* - * There may be either one or two offsets on this page. If - * there is one, then the overflow page is linked on normally - * and tp[4] is OVFLPAGE. If there are two, tp[4] contains - * the second offset and needs to get stuffed in after the - * next overflow page is added. - */ - n = tp[4]; - free_space = FREESPACE(tp); - off = OFFSET(tp); - tp[0] -= 2; - FREESPACE(tp) = free_space + OVFLSIZE; - OFFSET(tp) = off; - tmpp = __add_ovflpage(hashp, big_keyp); - if (!tmpp) - return (-1); - tp[4] = n; - } else - tmpp = big_keyp; - - if (change) - ret->newp = tmpp; - else - ret->oldp = tmpp; - return (0); + return (retval); } diff -u -r -N bdb185/db.1.85/hash/hash_buf.c bdb186/db.1.86/hash/hash_buf.c --- bdb185/db.1.85/hash/hash_buf.c 1994-07-15 05:23:46.000000000 -0700 +++ bdb186/db.1.86/hash/hash_buf.c 1997-01-04 11:25:41.000000000 -0800 @@ -1,9 +1,9 @@ /*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. + * Copyright (c) 1995 + * The President and Fellows of Harvard University * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. + * This code is derived from software contributed to Harvard by + * Jeremy Rassen. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,321 +35,72 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94"; +static char sccsid[] = "@(#)hash_debug.c 8.4 (Berkeley) 11/7/95"; #endif /* LIBC_SCCS and not lint */ +#ifdef DEBUG /* - * PACKAGE: hash + * PACKAGE: hashing * * DESCRIPTION: - * Contains buffer management + * Debug routines. * * ROUTINES: + * * External - * __buf_init - * __get_buf - * __buf_free - * __reclaim_buf - * Internal - * newbuf + * __dump_bucket */ - -#include - -#include -#include #include -#include - -#ifdef DEBUG -#include -#endif #include #include "hash.h" #include "page.h" #include "extern.h" +#include "compat.h" -static BUFHEAD *newbuf __P((HTAB *, u_int32_t, BUFHEAD *)); - -/* Unlink B from its place in the lru */ -#define BUF_REMOVE(B) { \ - (B)->prev->next = (B)->next; \ - (B)->next->prev = (B)->prev; \ -} - -/* Insert B after P */ -#define BUF_INSERT(B, P) { \ - (B)->next = (P)->next; \ - (B)->prev = (P); \ - (P)->next = (B); \ - (B)->next->prev = (B); \ -} - -#define MRU hashp->bufhead.next -#define LRU hashp->bufhead.prev - -#define MRU_INSERT(B) BUF_INSERT((B), &hashp->bufhead) -#define LRU_INSERT(B) BUF_INSERT((B), LRU) - -/* - * We are looking for a buffer with address "addr". If prev_bp is NULL, then - * address is a bucket index. If prev_bp is not NULL, then it points to the - * page previous to an overflow page that we are trying to find. - * - * CAVEAT: The buffer header accessed via prev_bp's ovfl field may no longer - * be valid. Therefore, you must always verify that its address matches the - * address you are seeking. - */ -extern BUFHEAD * -__get_buf(hashp, addr, prev_bp, newpage) - HTAB *hashp; - u_int32_t addr; - BUFHEAD *prev_bp; - int newpage; /* If prev_bp set, indicates a new overflow page. */ -{ - register BUFHEAD *bp; - register u_int32_t is_disk_mask; - register int is_disk, segment_ndx; - SEGMENT segp; - - is_disk = 0; - is_disk_mask = 0; - if (prev_bp) { - bp = prev_bp->ovfl; - if (!bp || (bp->addr != addr)) - bp = NULL; - if (!newpage) - is_disk = BUF_DISK; - } else { - /* Grab buffer out of directory */ - segment_ndx = addr & (hashp->SGSIZE - 1); - - /* valid segment ensured by __call_hash() */ - segp = hashp->dir[addr >> hashp->SSHIFT]; -#ifdef DEBUG - assert(segp != NULL); -#endif - bp = PTROF(segp[segment_ndx]); - is_disk_mask = ISDISK(segp[segment_ndx]); - is_disk = is_disk_mask || !hashp->new_file; - } - - if (!bp) { - bp = newbuf(hashp, addr, prev_bp); - if (!bp || - __get_page(hashp, bp->page, addr, !prev_bp, is_disk, 0)) - return (NULL); - if (!prev_bp) - segp[segment_ndx] = - (BUFHEAD *)((ptrdiff_t)bp | is_disk_mask); - } else { - BUF_REMOVE(bp); - MRU_INSERT(bp); - } - return (bp); -} - -/* - * We need a buffer for this page. Either allocate one, or evict a resident - * one (if we have as many buffers as we're allowed) and put this one in. - * - * If newbuf finds an error (returning NULL), it also sets errno. - */ -static BUFHEAD * -newbuf(hashp, addr, prev_bp) +void +__dump_bucket(hashp, bucket) HTAB *hashp; - u_int32_t addr; - BUFHEAD *prev_bp; + u_int32_t bucket; { - register BUFHEAD *bp; /* The buffer we're going to use */ - register BUFHEAD *xbp; /* Temp pointer */ - register BUFHEAD *next_xbp; - SEGMENT segp; - int segment_ndx; - u_int16_t oaddr, *shortp; - - oaddr = 0; - bp = LRU; - /* - * If LRU buffer is pinned, the buffer pool is too small. We need to - * allocate more buffers. - */ - if (hashp->nbufs || (bp->flags & BUF_PIN)) { - /* Allocate a new one */ - if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL) - return (NULL); -#ifdef PURIFY - memset(bp, 0xff, sizeof(BUFHEAD)); -#endif - if ((bp->page = (char *)malloc(hashp->BSIZE)) == NULL) { - free(bp); - return (NULL); - } -#ifdef PURIFY - memset(bp->page, 0xff, hashp->BSIZE); -#endif - if (hashp->nbufs) - hashp->nbufs--; - } else { - /* Kick someone out */ - BUF_REMOVE(bp); - /* - * If this is an overflow page with addr 0, it's already been - * flushed back in an overflow chain and initialized. - */ - if ((bp->addr != 0) || (bp->flags & BUF_BUCKET)) { - /* - * Set oaddr before __put_page so that you get it - * before bytes are swapped. - */ - shortp = (u_int16_t *)bp->page; - if (shortp[0]) - oaddr = shortp[shortp[0] - 1]; - if ((bp->flags & BUF_MOD) && __put_page(hashp, bp->page, - bp->addr, (int)IS_BUCKET(bp->flags), 0)) - return (NULL); - /* - * Update the pointer to this page (i.e. invalidate it). - * - * If this is a new file (i.e. we created it at open - * time), make sure that we mark pages which have been - * written to disk so we retrieve them from disk later, - * rather than allocating new pages. - */ - if (IS_BUCKET(bp->flags)) { - segment_ndx = bp->addr & (hashp->SGSIZE - 1); - segp = hashp->dir[bp->addr >> hashp->SSHIFT]; -#ifdef DEBUG - assert(segp != NULL); -#endif - - if (hashp->new_file && - ((bp->flags & BUF_MOD) || - ISDISK(segp[segment_ndx]))) - segp[segment_ndx] = (BUFHEAD *)BUF_DISK; - else - segp[segment_ndx] = NULL; - } - /* - * Since overflow pages can only be access by means of - * their bucket, free overflow pages associated with - * this bucket. - */ - for (xbp = bp; xbp->ovfl;) { - next_xbp = xbp->ovfl; - xbp->ovfl = 0; - xbp = next_xbp; - - /* Check that ovfl pointer is up date. */ - if (IS_BUCKET(xbp->flags) || - (oaddr != xbp->addr)) - break; - - shortp = (u_int16_t *)xbp->page; - if (shortp[0]) - /* set before __put_page */ - oaddr = shortp[shortp[0] - 1]; - if ((xbp->flags & BUF_MOD) && __put_page(hashp, - xbp->page, xbp->addr, 0, 0)) - return (NULL); - xbp->addr = 0; - xbp->flags = 0; - BUF_REMOVE(xbp); - LRU_INSERT(xbp); + CURSOR cursor; + DBT key, val; + ITEM_INFO item_info; + int var; + char *cp; + + cursor.pagep = NULL; + item_info.seek_size = 0; + item_info.seek_found_page = 0; + + __get_item_reset(hashp, &cursor); + + cursor.bucket = bucket; + for (;;) { + __get_item_next(hashp, &cursor, &key, &val, &item_info); + if (item_info.status == ITEM_ERROR) { + (void)printf("get_item_next returned error\n"); + break; + } else if (item_info.status == ITEM_NO_MORE) + break; + + if (item_info.key_off == BIGPAIR) { + if (__big_keydata(hashp, cursor.pagep, &key, &val, + item_info.pgndx)) { + (void)printf("__big_keydata returned error\n"); + break; } } - } - - /* Now assign this buffer */ - bp->addr = addr; -#ifdef DEBUG1 - (void)fprintf(stderr, "NEWBUF1: %d->ovfl was %d is now %d\n", - bp->addr, (bp->ovfl ? bp->ovfl->addr : 0), 0); -#endif - bp->ovfl = NULL; - if (prev_bp) { - /* - * If prev_bp is set, this is an overflow page, hook it in to - * the buffer overflow links. - */ -#ifdef DEBUG1 - (void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n", - prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0), - (bp ? bp->addr : 0)); -#endif - prev_bp->ovfl = bp; - bp->flags = 0; - } else - bp->flags = BUF_BUCKET; - MRU_INSERT(bp); - return (bp); -} -extern void -__buf_init(hashp, nbytes) - HTAB *hashp; - int nbytes; -{ - BUFHEAD *bfp; - int npages; - - bfp = &(hashp->bufhead); - npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT; - npages = MAX(npages, MIN_BUFFERS); - - hashp->nbufs = npages; - bfp->next = bfp; - bfp->prev = bfp; - /* - * This space is calloc'd so these are already null. - * - * bfp->ovfl = NULL; - * bfp->flags = 0; - * bfp->page = NULL; - * bfp->addr = 0; - */ -} - -extern int -__buf_free(hashp, do_free, to_disk) - HTAB *hashp; - int do_free, to_disk; -{ - BUFHEAD *bp; - - /* Need to make sure that buffer manager has been initialized */ - if (!LRU) - return (0); - for (bp = LRU; bp != &hashp->bufhead;) { - /* Check that the buffer is valid */ - if (bp->addr || IS_BUCKET(bp->flags)) { - if (to_disk && (bp->flags & BUF_MOD) && - __put_page(hashp, bp->page, - bp->addr, IS_BUCKET(bp->flags), 0)) - return (-1); + if (key.size == sizeof(int)) { + memcpy(&var, key.data, sizeof(int)); + (void)printf("%d\n", var); + } else { + for (cp = (char *)key.data; key.size--; cp++) + (void)printf("%c", *cp); + (void)printf("\n"); } - /* Check if we are freeing stuff */ - if (do_free) { - if (bp->page) - free(bp->page); - BUF_REMOVE(bp); - free(bp); - bp = LRU; - } else - bp = bp->prev; } - return (0); -} - -extern void -__reclaim_buf(hashp, bp) - HTAB *hashp; - BUFHEAD *bp; -{ - bp->ovfl = 0; - bp->addr = 0; - bp->flags = 0; - BUF_REMOVE(bp); - LRU_INSERT(bp); + __get_item_done(hashp, &cursor); } +#endif /* DEBUG */ diff -u -r -N bdb185/db.1.85/hash/hash_func.c bdb186/db.1.86/hash/hash_func.c --- bdb185/db.1.85/hash/hash_func.c 1994-02-21 15:09:30.000000000 -0800 +++ bdb186/db.1.86/hash/hash_func.c 1997-01-04 11:25:41.000000000 -0800 @@ -35,7 +35,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_func.c 8.2 (Berkeley) 2/21/94"; +static char sccsid[] = "@(#)hash_func.c 8.4 (Berkeley) 11/7/95"; #endif /* LIBC_SCCS and not lint */ #include @@ -50,55 +50,53 @@ static u_int32_t hash3 __P((const void *, size_t)); static u_int32_t hash4 __P((const void *, size_t)); -/* Global default hash function */ +/* Default hash function. */ u_int32_t (*__default_hash) __P((const void *, size_t)) = hash4; /* - * HASH FUNCTIONS - * * Assume that we've already split the bucket to which this key hashes, * calculate that bucket, and check that in fact we did already split it. * - * This came from ejb's hsearch. + * EJB's original hsearch hash. */ - #define PRIME1 37 #define PRIME2 1048583 -static u_int32_t -hash1(keyarg, len) - const void *keyarg; - register size_t len; +u_int32_t +hash1(key, len) + const void *key; + size_t len; { - register const u_char *key; - register u_int32_t h; + u_int32_t h; + u_int8_t *k; + h = 0; + k = (u_int8_t *)key; /* Convert string to integer */ - for (key = keyarg, h = 0; len--;) - h = h * PRIME1 ^ (*key++ - ' '); + while (len--) + h = h * PRIME1 ^ (*k++ - ' '); h %= PRIME2; return (h); } /* - * Phong's linear congruential hash + * Phong Vo's linear congruential hash */ #define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c)) -static u_int32_t -hash2(keyarg, len) - const void *keyarg; +u_int32_t +hash2(key, len) + const void *key; size_t len; { - register const u_char *e, *key; - register u_int32_t h; - register u_char c; - - key = keyarg; - e = key + len; - for (h = 0; key != e;) { - c = *key++; - if (!c && key > e) + u_int32_t h; + u_int8_t *e, c, *k; + + k = (u_int8_t *)key; + e = k + len; + for (h = 0; k != e;) { + c = *k++; + if (!c && k > e) break; dcharhash(h, c); } @@ -112,101 +110,87 @@ * all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If * this routine is heavily used enough, it's worth the ugly coding. * - * OZ's original sdbm hash + * Ozan Yigit's original sdbm hash. */ -static u_int32_t -hash3(keyarg, len) - const void *keyarg; - register size_t len; +u_int32_t +hash3(key, len) + const void *key; + size_t len; { - register const u_char *key; - register size_t loop; - register u_int32_t h; + u_int32_t n, loop; + u_int8_t *k; -#define HASHC h = *key++ + 65599 * h +#define HASHC n = *k++ + 65599 * n - h = 0; - key = keyarg; + n = 0; + k = (u_int8_t *)key; if (len > 0) { loop = (len + 8 - 1) >> 3; switch (len & (8 - 1)) { case 0: - do { + do { /* All fall throughs */ HASHC; - /* FALLTHROUGH */ case 7: HASHC; - /* FALLTHROUGH */ case 6: HASHC; - /* FALLTHROUGH */ case 5: HASHC; - /* FALLTHROUGH */ case 4: HASHC; - /* FALLTHROUGH */ case 3: HASHC; - /* FALLTHROUGH */ case 2: HASHC; - /* FALLTHROUGH */ case 1: HASHC; } while (--loop); } + } - return (h); + return (n); } -/* Hash function from Chris Torek. */ -static u_int32_t -hash4(keyarg, len) - const void *keyarg; - register size_t len; +/* Chris Torek's hash function. */ +u_int32_t +hash4(key, len) + const void *key; + size_t len; { - register const u_char *key; - register size_t loop; - register u_int32_t h; + u_int32_t h, loop; + u_int8_t *k; -#define HASH4a h = (h << 5) - h + *key++; -#define HASH4b h = (h << 5) + h + *key++; +#define HASH4a h = (h << 5) - h + *k++; +#define HASH4b h = (h << 5) + h + *k++; #define HASH4 HASH4b h = 0; - key = keyarg; + k = (u_int8_t *)key; if (len > 0) { loop = (len + 8 - 1) >> 3; switch (len & (8 - 1)) { case 0: - do { + do { /* All fall throughs */ HASH4; - /* FALLTHROUGH */ case 7: HASH4; - /* FALLTHROUGH */ case 6: HASH4; - /* FALLTHROUGH */ case 5: HASH4; - /* FALLTHROUGH */ case 4: HASH4; - /* FALLTHROUGH */ case 3: HASH4; - /* FALLTHROUGH */ case 2: HASH4; - /* FALLTHROUGH */ case 1: HASH4; } while (--loop); } + } return (h); } diff -u -r -N bdb185/db.1.85/hash/hash_log2.c bdb186/db.1.86/hash/hash_log2.c --- bdb185/db.1.85/hash/hash_log2.c 1994-05-31 13:56:53.000000000 -0700 +++ bdb186/db.1.86/hash/hash_log2.c 1997-01-04 11:25:41.000000000 -0800 @@ -35,18 +35,16 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94"; +static char sccsid[] = "@(#)hash_log2.c 8.4 (Berkeley) 11/7/95"; #endif /* LIBC_SCCS and not lint */ -#include - #include u_int32_t __log2(num) u_int32_t num; { - register u_int32_t i, limit; + u_int32_t i, limit; limit = 1; for (i = 0; limit < num; limit = limit << 1, i++); diff -u -r -N bdb185/db.1.85/hash/hash_page.c bdb186/db.1.86/hash/hash_page.c --- bdb185/db.1.85/hash/hash_page.c 1994-08-16 05:42:04.000000000 -0700 +++ bdb186/db.1.86/hash/hash_page.c 1997-01-04 11:25:41.000000000 -0800 @@ -35,613 +35,1013 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94"; +static char sccsid[] = "@(#)hash_page.c 8.11 (Berkeley) 11/7/95"; #endif /* LIBC_SCCS and not lint */ /* * PACKAGE: hashing * * DESCRIPTION: - * Page manipulation for hashing package. + * Page manipulation for hashing package. * * ROUTINES: * * External - * __get_page - * __add_ovflpage + * __get_page + * __add_ovflpage * Internal - * overflow_page - * open_temp + * overflow_page + * open_temp */ #include -#include -#include -#include +#ifdef DEBUG +#include +#endif #include #include #include #include -#ifdef DEBUG -#include -#endif #include #include "hash.h" #include "page.h" #include "extern.h" +#include "compat.h" + +static void adjust_cursor __P((HTAB *, int32_t, pgno_t, pgno_t, int)); +static int32_t add_bigptr __P((HTAB *, ITEM_INFO *, indx_t)); +static u_int32_t *fetch_bitmap __P((HTAB *, int32_t)); +static u_int32_t first_free __P((u_int32_t)); +static indx_t next_realkey __P((PAGE16 *, indx_t)); +static u_int16_t overflow_page __P((HTAB *)); +static void page_init __P((HTAB *, PAGE16 *, pgno_t, u_int8_t)); +static indx_t prev_realkey __P((PAGE16 *, indx_t)); +static void putpair __P((PAGE8 *, const DBT *, const DBT *)); +static void swap_page_header_in __P((PAGE16 *)); +static void swap_page_header_out __P((PAGE16 *)); + +#ifdef DEBUG_SLOW +static void account_page(HTAB *, pgno_t, int); +#endif + +u_int32_t +__get_item(hashp, cursorp, key, val, item_info) + HTAB *hashp; + CURSOR *cursorp; + DBT *key, *val; + ITEM_INFO *item_info; +{ + pgno_t next_pgno; + int32_t i; -static u_int32_t *fetch_bitmap __P((HTAB *, int)); -static u_int32_t first_free __P((u_int32_t)); -static int open_temp __P((HTAB *)); -static u_int16_t overflow_page __P((HTAB *)); -static void putpair __P((char *, const DBT *, const DBT *)); -static void squeeze_key __P((u_int16_t *, const DBT *, const DBT *)); -static int ugly_split - __P((HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int)); - -#define PAGE_INIT(P) { \ - ((u_int16_t *)(P))[0] = 0; \ - ((u_int16_t *)(P))[1] = hashp->BSIZE - 3 * sizeof(u_int16_t); \ - ((u_int16_t *)(P))[2] = hashp->BSIZE; \ + /* Check if we need to get a page. */ + if (!cursorp->pagep) { + if (cursorp->pgno == INVALID_PGNO) { + cursorp->pagep = + __get_page(hashp, cursorp->bucket, A_BUCKET); + cursorp->pgno = ADDR(cursorp->pagep); + cursorp->ndx = 0; + cursorp->pgndx = 0; + } else + cursorp->pagep = + __get_page(hashp, cursorp->pgno, A_RAW); + if (!cursorp->pagep) { + item_info->status = ITEM_ERROR; + return (-1); + } + } + if (item_info->seek_size && + FREESPACE(cursorp->pagep) > item_info->seek_size) + item_info->seek_found_page = cursorp->pgno; + + if (cursorp->pgndx == NUM_ENT(cursorp->pagep)) { + /* Fetch next page. */ + if (NEXT_PGNO(cursorp->pagep) == INVALID_PGNO) { + item_info->status = ITEM_NO_MORE; + return (-1); + } + next_pgno = NEXT_PGNO(cursorp->pagep); + cursorp->pgndx = 0; + __put_page(hashp, cursorp->pagep, A_RAW, 0); + cursorp->pagep = __get_page(hashp, next_pgno, A_RAW); + if (!cursorp->pagep) { + item_info->status = ITEM_ERROR; + return (-1); + } + cursorp->pgno = next_pgno; + } + if (KEY_OFF(cursorp->pagep, cursorp->pgndx) != BIGPAIR) { + if ((i = prev_realkey(cursorp->pagep, cursorp->pgndx)) == + cursorp->pgndx) + key->size = hashp->hdr.bsize - + KEY_OFF(cursorp->pagep, cursorp->pgndx); + else + key->size = DATA_OFF(cursorp->pagep, i) - + KEY_OFF(cursorp->pagep, cursorp->pgndx); + } + + /* + * All of this information will be set incorrectly for big keys, but + * it will be ignored anyway. + */ + val->size = KEY_OFF(cursorp->pagep, cursorp->pgndx) - + DATA_OFF(cursorp->pagep, cursorp->pgndx); + key->data = KEY(cursorp->pagep, cursorp->pgndx); + val->data = DATA(cursorp->pagep, cursorp->pgndx); + item_info->pgno = cursorp->pgno; + item_info->bucket = cursorp->bucket; + item_info->ndx = cursorp->ndx; + item_info->pgndx = cursorp->pgndx; + item_info->key_off = KEY_OFF(cursorp->pagep, cursorp->pgndx); + item_info->data_off = DATA_OFF(cursorp->pagep, cursorp->pgndx); + item_info->status = ITEM_OK; + + return (0); +} + +u_int32_t +__get_item_reset(hashp, cursorp) + HTAB *hashp; + CURSOR *cursorp; +{ + if (cursorp->pagep) + __put_page(hashp, cursorp->pagep, A_RAW, 0); + cursorp->pagep = NULL; + cursorp->bucket = -1; + cursorp->ndx = 0; + cursorp->pgndx = 0; + cursorp->pgno = INVALID_PGNO; + return (0); +} + +u_int32_t +__get_item_done(hashp, cursorp) + HTAB *hashp; + CURSOR *cursorp; +{ + if (cursorp->pagep) + __put_page(hashp, cursorp->pagep, A_RAW, 0); + cursorp->pagep = NULL; + + /* + * We don't throw out the page number since we might want to + * continue getting on this page. + */ + return (0); +} + +u_int32_t +__get_item_first(hashp, cursorp, key, val, item_info) + HTAB *hashp; + CURSOR *cursorp; + DBT *key, *val; + ITEM_INFO *item_info; +{ + __get_item_reset(hashp, cursorp); + cursorp->bucket = 0; + return (__get_item_next(hashp, cursorp, key, val, item_info)); } /* - * This is called AFTER we have verified that there is room on the page for - * the pair (PAIRFITS has returned true) so we go right ahead and start moving - * stuff on. + * Returns a pointer to key/data pair on a page. In the case of bigkeys, + * just returns the page number and index of the bigkey pointer pair. + */ +u_int32_t +__get_item_next(hashp, cursorp, key, val, item_info) + HTAB *hashp; + CURSOR *cursorp; + DBT *key, *val; + ITEM_INFO *item_info; +{ + int stat; + + stat = __get_item(hashp, cursorp, key, val, item_info); + cursorp->ndx++; + cursorp->pgndx++; + return (stat); +} + +/* + * Put a non-big pair on a page. */ static void putpair(p, key, val) - char *p; + PAGE8 *p; const DBT *key, *val; { - register u_int16_t *bp, n, off; - - bp = (u_int16_t *)p; + u_int16_t *pagep, n, off; - /* Enter the key first. */ - n = bp[0]; + pagep = (PAGE16 *)p; - off = OFFSET(bp) - key->size; + /* Items on the page are 0-indexed. */ + n = NUM_ENT(pagep); + off = OFFSET(pagep) - key->size + 1; memmove(p + off, key->data, key->size); - bp[++n] = off; + KEY_OFF(pagep, n) = off; - /* Now the data. */ off -= val->size; memmove(p + off, val->data, val->size); - bp[++n] = off; + DATA_OFF(pagep, n) = off; /* Adjust page info. */ - bp[0] = n; - bp[n + 1] = off - ((n + 3) * sizeof(u_int16_t)); - bp[n + 2] = off; + NUM_ENT(pagep) = n + 1; + OFFSET(pagep) = off - 1; } /* - * Returns: - * 0 OK - * -1 error + * Returns the index of the next non-bigkey pair after n on the page. + * Returns -1 if there are no more non-big things on the page. */ -extern int -__delpair(hashp, bufp, ndx) - HTAB *hashp; - BUFHEAD *bufp; - register int ndx; +indx_t +#ifdef __STDC__ +next_realkey(PAGE16 * pagep, indx_t n) +#else +next_realkey(pagep, n) + PAGE16 *pagep; + u_int32_t n; +#endif { - register u_int16_t *bp, newoff; - register int n; - u_int16_t pairlen; - - bp = (u_int16_t *)bufp->page; - n = bp[0]; - - if (bp[ndx + 1] < REAL_KEY) - return (__big_delete(hashp, bufp)); - if (ndx != 1) - newoff = bp[ndx - 1]; - else - newoff = hashp->BSIZE; - pairlen = newoff - bp[ndx + 1]; + indx_t i; - if (ndx != (n - 1)) { - /* Hard Case -- need to shuffle keys */ - register int i; - register char *src = bufp->page + (int)OFFSET(bp); - register char *dst = src + (int)pairlen; - memmove(dst, src, bp[ndx + 1] - OFFSET(bp)); - - /* Now adjust the pointers */ - for (i = ndx + 2; i <= n; i += 2) { - if (bp[i + 1] == OVFLPAGE) { - bp[i - 2] = bp[i]; - bp[i - 1] = bp[i + 1]; - } else { - bp[i - 2] = bp[i] + pairlen; - bp[i - 1] = bp[i + 1] + pairlen; - } - } - } - /* Finally adjust the page data */ - bp[n] = OFFSET(bp) + pairlen; - bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(u_int16_t); - bp[0] = n - 2; - hashp->NKEYS--; + for (i = n + 1; i < NUM_ENT(pagep); i++) + if (KEY_OFF(pagep, i) != BIGPAIR) + return (i); + return (-1); +} - bufp->flags |= BUF_MOD; - return (0); +/* + * Returns the index of the previous non-bigkey pair after n on the page. + * Returns n if there are no previous non-big things on the page. + */ +static indx_t +#ifdef __STDC__ +prev_realkey(PAGE16 * pagep, indx_t n) +#else +prev_realkey(pagep, n) + PAGE16 *pagep; + u_int32_t n; +#endif +{ + int32_t i; + + /* Need a signed value to do the compare properly. */ + for (i = n - 1; i > -1; i--) + if (KEY_OFF(pagep, i) != BIGPAIR) + return (i); + return (n); } + /* * Returns: - * 0 ==> OK - * -1 ==> Error + * 0 OK + * -1 error */ -extern int -__split_page(hashp, obucket, nbucket) +extern int32_t +__delpair(hashp, cursorp, item_info) HTAB *hashp; - u_int32_t obucket, nbucket; + CURSOR *cursorp; + ITEM_INFO *item_info; { - register BUFHEAD *new_bufp, *old_bufp; - register u_int16_t *ino; - register char *np; - DBT key, val; - int n, ndx, retval; - u_int16_t copyto, diff, off, moved; - char *op; - - copyto = (u_int16_t)hashp->BSIZE; - off = (u_int16_t)hashp->BSIZE; - old_bufp = __get_buf(hashp, obucket, NULL, 0); - if (old_bufp == NULL) - return (-1); - new_bufp = __get_buf(hashp, nbucket, NULL, 0); - if (new_bufp == NULL) - return (-1); - - old_bufp->flags |= (BUF_MOD | BUF_PIN); - new_bufp->flags |= (BUF_MOD | BUF_PIN); + PAGE16 *pagep; + PAGE16 *empty_page; + pgno_t to_find, next_pgno, link_page; + indx_t ndx; + short check_ndx; + int16_t delta, len, next_key; + int32_t n; + u_int8_t *src, *dest; + pgno_t move_pgno; + int page_deleted; + + ndx = cursorp->pgndx; + if (!cursorp->pagep) { + pagep = __get_page(hashp, cursorp->pgno, A_RAW); + if (!pagep) + return (-1); + /* + * KLUGE: pgndx has gone one too far, because cursor points + * to the _next_ item. Use pgndx - 1. + */ + --ndx; + } else + pagep = cursorp->pagep; +#ifdef DEBUG + assert(ADDR(pagep) == cursorp->pgno); +#endif - ino = (u_int16_t *)(op = old_bufp->page); - np = new_bufp->page; + if (KEY_OFF(pagep, ndx) == BIGPAIR) { + delta = 0; + __big_delete(hashp, pagep, ndx); + } else { + /* + * Compute "delta", the amount we have to shift all of the + * offsets. To find the delta, we need to make sure that + * we aren't looking at the DATA_OFF of a big/keydata pair. + */ + for (check_ndx = (short)(ndx - 1); + check_ndx >= 0 && KEY_OFF(pagep, check_ndx) == BIGPAIR; + check_ndx--); + if (check_ndx < 0) + delta = hashp->hdr.bsize - DATA_OFF(pagep, ndx); + else + delta = + DATA_OFF(pagep, check_ndx) - DATA_OFF(pagep, ndx); - moved = 0; + /* + * The hard case: we want to remove something other than + * the last item on the page. We need to shift data and + * offsets down. + */ + if (ndx != NUM_ENT(pagep) - 1) { + /* + * Move the data: src is the address of the last data + * item on the page. + */ + src = (u_int8_t *)pagep + OFFSET(pagep) + 1; + /* + * Length is the distance between where to start + * deleting and end of the data on the page. + */ + len = DATA_OFF(pagep, ndx) - (OFFSET(pagep) + 1); + /* + * Dest is the location of the to-be-deleted item + * occupied - length. + */ + if (check_ndx < 0) + dest = + (u_int8_t *)pagep + hashp->hdr.bsize - len; + else + dest = (u_int8_t *)pagep + + DATA_OFF(pagep, (check_ndx)) - len; + memmove(dest, src, len); + } + } - for (n = 1, ndx = 1; n < ino[0]; n += 2) { - if (ino[n + 1] < REAL_KEY) { - retval = ugly_split(hashp, obucket, old_bufp, new_bufp, - (int)copyto, (int)moved); - old_bufp->flags &= ~BUF_PIN; - new_bufp->flags &= ~BUF_PIN; - return (retval); - - } - key.data = (u_char *)op + ino[n]; - key.size = off - ino[n]; - - if (__call_hash(hashp, key.data, key.size) == obucket) { - /* Don't switch page */ - diff = copyto - off; - if (diff) { - copyto = ino[n + 1] + diff; - memmove(op + copyto, op + ino[n + 1], - off - ino[n + 1]); - ino[ndx] = copyto + ino[n] - ino[n + 1]; - ino[ndx + 1] = copyto; - } else - copyto = ino[n + 1]; - ndx += 2; + /* Adjust the offsets. */ + for (n = ndx; n < NUM_ENT(pagep) - 1; n++) + if (KEY_OFF(pagep, (n + 1)) != BIGPAIR) { + next_key = next_realkey(pagep, n); +#ifdef DEBUG + assert(next_key != -1); +#endif + KEY_OFF(pagep, n) = KEY_OFF(pagep, (n + 1)) + delta; + DATA_OFF(pagep, n) = DATA_OFF(pagep, (n + 1)) + delta; } else { - /* Switch page */ - val.data = (u_char *)op + ino[n + 1]; - val.size = ino[n] - ino[n + 1]; - putpair(np, &key, &val); - moved += 2; + KEY_OFF(pagep, n) = KEY_OFF(pagep, (n + 1)); + DATA_OFF(pagep, n) = DATA_OFF(pagep, (n + 1)); } - off = ino[n + 1]; - } + /* Adjust page metadata. */ + OFFSET(pagep) = OFFSET(pagep) + delta; + NUM_ENT(pagep) = NUM_ENT(pagep) - 1; + + --hashp->hdr.nkeys; - /* Now clean up the page */ - ino[0] -= moved; - FREESPACE(ino) = copyto - sizeof(u_int16_t) * (ino[0] + 3); - OFFSET(ino) = copyto; + /* Is this page now an empty overflow page? If so, free it. */ + if (TYPE(pagep) == HASH_OVFLPAGE && NUM_ENT(pagep) == 0) { -#ifdef DEBUG3 - (void)fprintf(stderr, "split %d/%d\n", - ((u_int16_t *)np)[0] / 2, - ((u_int16_t *)op)[0] / 2); + page_deleted = 1; + /* + * We need to go back to the first page in the chain and + * look for this page so that we can update the previous + * page's NEXT_PGNO field. + */ + to_find = ADDR(pagep); + empty_page = pagep; + link_page = NEXT_PGNO(empty_page); + pagep = __get_page(hashp, item_info->bucket, A_BUCKET); + if (!pagep) + return (-1); + while (NEXT_PGNO(pagep) != to_find) { + next_pgno = NEXT_PGNO(pagep); +#ifdef DEBUG + assert(next_pgno != INVALID_PGNO); #endif - /* unpin both pages */ - old_bufp->flags &= ~BUF_PIN; - new_bufp->flags &= ~BUF_PIN; + __put_page(hashp, pagep, A_RAW, 0); + pagep = __get_page(hashp, next_pgno, A_RAW); + if (!pagep) + return (-1); + } + + /* + * At this point, pagep should point to the page before the + * page to be deleted. + */ + NEXT_PGNO(pagep) = link_page; + if (item_info->pgno == to_find) { + item_info->pgno = ADDR(pagep); + item_info->pgndx = NUM_ENT(pagep); + item_info->seek_found_page = ADDR(pagep); + } + __delete_page(hashp, empty_page, A_OVFL); + } else + page_deleted = 0; + __put_page(hashp, pagep, A_RAW, 1); + adjust_cursor(hashp, ndx, cursorp->pgno, link_page, page_deleted); + return (0); } -/* - * Called when we encounter an overflow or big key/data page during split - * handling. This is special cased since we have to begin checking whether - * the key/data pairs fit on their respective pages and because we may need - * overflow pages for both the old and new pages. - * - * The first page might be a page with regular key/data pairs in which case - * we have a regular overflow condition and just need to go on to the next - * page or it might be a big key/data pair in which case we need to fix the - * big key/data pair. - * - * Returns: - * 0 ==> success - * -1 ==> failure - */ -static int -ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved) +extern int32_t +__split_page(hashp, obucket, nbucket) HTAB *hashp; - u_int32_t obucket; /* Same as __split_page. */ - BUFHEAD *old_bufp, *new_bufp; - int copyto; /* First byte on page which contains key/data values. */ - int moved; /* Number of pairs moved to new page. */ -{ - register BUFHEAD *bufp; /* Buffer header for ino */ - register u_int16_t *ino; /* Page keys come off of */ - register u_int16_t *np; /* New page */ - register u_int16_t *op; /* Page keys go on to if they aren't moving */ - - BUFHEAD *last_bfp; /* Last buf header OVFL needing to be freed */ + u_int32_t obucket, nbucket; +{ DBT key, val; - SPLIT_RETURN ret; - u_int16_t n, off, ov_addr, scopyto; - char *cino; /* Character value of ino */ - - bufp = old_bufp; - ino = (u_int16_t *)old_bufp->page; - np = (u_int16_t *)new_bufp->page; - op = (u_int16_t *)old_bufp->page; - last_bfp = NULL; - scopyto = (u_int16_t)copyto; /* ANSI */ - - n = ino[0] - 1; - while (n < ino[0]) { - if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) { - if (__big_split(hashp, old_bufp, - new_bufp, bufp, bufp->addr, obucket, &ret)) - return (-1); - old_bufp = ret.oldp; - if (!old_bufp) - return (-1); - op = (u_int16_t *)old_bufp->page; - new_bufp = ret.newp; - if (!new_bufp) - return (-1); - np = (u_int16_t *)new_bufp->page; - bufp = ret.nextp; - if (!bufp) - return (0); - cino = (char *)bufp->page; - ino = (u_int16_t *)cino; - last_bfp = ret.nextp; - } else if (ino[n + 1] == OVFLPAGE) { - ov_addr = ino[n]; - /* - * Fix up the old page -- the extra 2 are the fields - * which contained the overflow information. - */ - ino[0] -= (moved + 2); - FREESPACE(ino) = - scopyto - sizeof(u_int16_t) * (ino[0] + 3); - OFFSET(ino) = scopyto; - - bufp = __get_buf(hashp, ov_addr, bufp, 0); - if (!bufp) - return (-1); - - ino = (u_int16_t *)bufp->page; - n = 1; - scopyto = hashp->BSIZE; - moved = 0; - - if (last_bfp) - __free_ovflpage(hashp, last_bfp); - last_bfp = bufp; - } - /* Move regular sized pairs of there are any */ - off = hashp->BSIZE; - for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) { - cino = (char *)ino; - key.data = (u_char *)cino + ino[n]; - key.size = off - ino[n]; - val.data = (u_char *)cino + ino[n + 1]; - val.size = ino[n] - ino[n + 1]; - off = ino[n + 1]; - - if (__call_hash(hashp, key.data, key.size) == obucket) { - /* Keep on old page */ - if (PAIRFITS(op, (&key), (&val))) - putpair((char *)op, &key, &val); - else { - old_bufp = - __add_ovflpage(hashp, old_bufp); - if (!old_bufp) - return (-1); - op = (u_int16_t *)old_bufp->page; - putpair((char *)op, &key, &val); - } - old_bufp->flags |= BUF_MOD; + ITEM_INFO old_ii, new_ii; + PAGE16 *old_pagep, *temp_pagep; + pgno_t next_pgno; + int32_t off; + u_int16_t n; + int8_t base_page; + + off = hashp->hdr.bsize; + old_pagep = __get_page(hashp, obucket, A_BUCKET); + + base_page = 1; + + temp_pagep = hashp->split_buf; + memcpy(temp_pagep, old_pagep, hashp->hdr.bsize); + + page_init(hashp, old_pagep, ADDR(old_pagep), HASH_PAGE); + __put_page(hashp, old_pagep, A_RAW, 1); + + old_ii.pgno = BUCKET_TO_PAGE(obucket); + new_ii.pgno = BUCKET_TO_PAGE(nbucket); + old_ii.bucket = obucket; + new_ii.bucket = nbucket; + old_ii.seek_found_page = new_ii.seek_found_page = 0; + + while (temp_pagep != 0) { + off = hashp->hdr.bsize; + for (n = 0; n < NUM_ENT(temp_pagep); n++) { + if (KEY_OFF(temp_pagep, n) == BIGPAIR) { + __get_bigkey(hashp, temp_pagep, n, &key); + if (__call_hash(hashp, + key.data, key.size) == obucket) + add_bigptr(hashp, &old_ii, + DATA_OFF(temp_pagep, n)); + else + add_bigptr(hashp, &new_ii, + DATA_OFF(temp_pagep, n)); } else { - /* Move to new page */ - if (PAIRFITS(np, (&key), (&val))) - putpair((char *)np, &key, &val); - else { - new_bufp = - __add_ovflpage(hashp, new_bufp); - if (!new_bufp) - return (-1); - np = (u_int16_t *)new_bufp->page; - putpair((char *)np, &key, &val); - } - new_bufp->flags |= BUF_MOD; + key.size = off - KEY_OFF(temp_pagep, n); + key.data = KEY(temp_pagep, n); + off = KEY_OFF(temp_pagep, n); + val.size = off - DATA_OFF(temp_pagep, n); + val.data = DATA(temp_pagep, n); + if (__call_hash(hashp, + key.data, key.size) == obucket) + __addel(hashp, &old_ii, &key, &val, + NO_EXPAND, 1); + else + __addel(hashp, &new_ii, &key, &val, + NO_EXPAND, 1); + off = DATA_OFF(temp_pagep, n); } } + next_pgno = NEXT_PGNO(temp_pagep); + + /* Clear temp_page; if it's an overflow page, free it. */ + if (!base_page) + __delete_page(hashp, temp_pagep, A_OVFL); + else + base_page = 0; + if (next_pgno != INVALID_PGNO) + temp_pagep = __get_page(hashp, next_pgno, A_RAW); + else + break; } - if (last_bfp) - __free_ovflpage(hashp, last_bfp); return (0); } /* - * Add the given pair to the page + * Add the given pair to the page. + * * * Returns: - * 0 ==> OK - * 1 ==> failure + * 0 ==> OK + * -1 ==> failure */ -extern int -__addel(hashp, bufp, key, val) +extern int32_t +#ifdef __STDC__ +__addel(HTAB *hashp, ITEM_INFO *item_info, const DBT *key, const DBT *val, + u_int32_t num_items, const u_int8_t expanding) +#else +__addel(hashp, item_info, key, val, num_items, expanding) HTAB *hashp; - BUFHEAD *bufp; + ITEM_INFO *item_info; const DBT *key, *val; + u_int32_t num_items; + const u_int32_t expanding; +#endif { - register u_int16_t *bp, *sop; - int do_expand; + PAGE16 *pagep; + int32_t do_expand; + pgno_t next_pgno; - bp = (u_int16_t *)bufp->page; do_expand = 0; - while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY)) - /* Exception case */ - if (bp[2] == FULL_KEY_DATA && bp[0] == 2) - /* This is the last page of a big key/data pair - and we need to add another page */ + + pagep = __get_page(hashp, + item_info->seek_found_page != 0 ? + item_info->seek_found_page : item_info->pgno, A_RAW); + if (!pagep) + return (-1); + + /* Advance to first page in chain with room for item. */ + while (NUM_ENT(pagep) && NEXT_PGNO(pagep) != INVALID_PGNO) { + /* + * This may not be the end of the chain, but the pair may fit + * anyway. + */ + if (ISBIG(PAIRSIZE(key, val), hashp) && BIGPAIRFITS(pagep)) break; - else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) { - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - } else - /* Try to squeeze key on this page */ - if (FREESPACE(bp) > PAIRSIZE(key, val)) { - squeeze_key(bp, key, val); - return (0); - } else { - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - } + if (PAIRFITS(pagep, key, val)) + break; + next_pgno = NEXT_PGNO(pagep); + __put_page(hashp, pagep, A_RAW, 0); + pagep = (PAGE16 *)__get_page(hashp, next_pgno, A_RAW); + if (!pagep) + return (-1); + } - if (PAIRFITS(bp, key, val)) - putpair(bufp->page, key, val); + if (ISBIG(PAIRSIZE(key, val), hashp)) { + if (__big_insert(hashp, pagep, key, val)) + return (-1); + } else if (PAIRFITS(pagep, key, val)) + putpair((PAGE8 *)pagep, key, val); else { do_expand = 1; - bufp = __add_ovflpage(hashp, bufp); - if (!bufp) + pagep = __add_ovflpage(hashp, pagep); + if (!pagep) return (-1); - sop = (u_int16_t *)bufp->page; - if (PAIRFITS(sop, key, val)) - putpair((char *)sop, key, val); - else - if (__big_insert(hashp, bufp, key, val)) - return (-1); + if (!PAIRFITS(pagep, key, val)) { + __put_page(hashp, pagep, A_RAW, 0); + return (-1); + } + putpair((PAGE8 *)pagep, key, val); } - bufp->flags |= BUF_MOD; + + /* + * For splits, we are going to update item_info's page number + * field, so that we can easily return to the same page the + * next time we come in here. For other operations, this shouldn't + * matter, since adds are the last thing that happens before we + * return to the user program. + */ + item_info->pgno = ADDR(pagep); + + if (!expanding) + hashp->hdr.nkeys++; + + /* Kludge: if this is a big page, then it's already been put. */ + if (!ISBIG(PAIRSIZE(key, val), hashp)) + __put_page(hashp, pagep, A_RAW, 1); + + if (expanding) + item_info->caused_expand = 0; + else + switch (num_items) { + case NO_EXPAND: + item_info->caused_expand = 0; + break; + case UNKNOWN: + item_info->caused_expand = + (hashp->hdr.nkeys / hashp->hdr.max_bucket) > + hashp->hdr.ffactor || + item_info->pgndx > hashp->hdr.ffactor; + break; + default: + item_info->caused_expand = + num_items > hashp->hdr.ffactor ? 1 : do_expand; + break; + } + return (0); +} + +/* + * Special __addel used in big splitting; this one just puts the pointer + * to an already-allocated big page in the appropriate bucket. + */ +int32_t +#ifdef __STDC__ +add_bigptr(HTAB * hashp, ITEM_INFO * item_info, indx_t big_pgno) +#else +add_bigptr(hashp, item_info, big_pgno) + HTAB *hashp; + ITEM_INFO *item_info; + u_int32_t big_pgno; +#endif +{ + PAGE16 *pagep; + pgno_t next_pgno; + + pagep = __get_page(hashp, item_info->bucket, A_BUCKET); + if (!pagep) + return (-1); + /* - * If the average number of keys per bucket exceeds the fill factor, - * expand the table. + * Note: in __addel(), we used item_info->pgno for the beginning of + * our search for space. Now, we use item_info->bucket, since we + * know that the space required by a big pair on the base page is + * quite small, and we may very well find that space early in the + * chain. */ - hashp->NKEYS++; - if (do_expand || - (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR)) - return (__expand_table(hashp)); + + /* Find first page in chain that has space for a big pair. */ + while (NUM_ENT(pagep) && (NEXT_PGNO(pagep) != INVALID_PGNO)) { + if (BIGPAIRFITS(pagep)) + break; + next_pgno = NEXT_PGNO(pagep); + __put_page(hashp, pagep, A_RAW, 0); + pagep = __get_page(hashp, next_pgno, A_RAW); + if (!pagep) + return (-1); + } + if (!BIGPAIRFITS(pagep)) { + pagep = __add_ovflpage(hashp, pagep); + if (!pagep) + return (-1); +#ifdef DEBUG + assert(BIGPAIRFITS(pagep)); +#endif + } + KEY_OFF(pagep, NUM_ENT(pagep)) = BIGPAIR; + DATA_OFF(pagep, NUM_ENT(pagep)) = big_pgno; + NUM_ENT(pagep) = NUM_ENT(pagep) + 1; + + __put_page(hashp, pagep, A_RAW, 1); + return (0); } /* * * Returns: - * pointer on success - * NULL on error + * pointer on success + * NULL on error */ -extern BUFHEAD * -__add_ovflpage(hashp, bufp) +extern PAGE16 * +__add_ovflpage(hashp, pagep) HTAB *hashp; - BUFHEAD *bufp; + PAGE16 *pagep; { - register u_int16_t *sp; - u_int16_t ndx, ovfl_num; -#ifdef DEBUG1 - int tmp1, tmp2; -#endif - sp = (u_int16_t *)bufp->page; + PAGE16 *new_pagep; + u_int16_t ovfl_num; - /* Check if we are dynamically determining the fill factor */ - if (hashp->FFACTOR == DEF_FFACTOR) { - hashp->FFACTOR = sp[0] >> 1; - if (hashp->FFACTOR < MIN_FFACTOR) - hashp->FFACTOR = MIN_FFACTOR; + /* Check if we are dynamically determining the fill factor. */ + if (hashp->hdr.ffactor == DEF_FFACTOR) { + hashp->hdr.ffactor = NUM_ENT(pagep) >> 1; + if (hashp->hdr.ffactor < MIN_FFACTOR) + hashp->hdr.ffactor = MIN_FFACTOR; } - bufp->flags |= BUF_MOD; ovfl_num = overflow_page(hashp); -#ifdef DEBUG1 - tmp1 = bufp->addr; - tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0; -#endif - if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1))) + + if (__new_page(hashp, (u_int32_t)ovfl_num, A_OVFL) != 0) return (NULL); - bufp->ovfl->flags |= BUF_MOD; -#ifdef DEBUG1 - (void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n", - tmp1, tmp2, bufp->ovfl->addr); -#endif - ndx = sp[0]; - /* - * Since a pair is allocated on a page only if there's room to add - * an overflow page, we know that the OVFL information will fit on - * the page. - */ - sp[ndx + 4] = OFFSET(sp); - sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE; - sp[ndx + 1] = ovfl_num; - sp[ndx + 2] = OVFLPAGE; - sp[0] = ndx + 2; + + if (!ovfl_num || !(new_pagep = __get_page(hashp, ovfl_num, A_OVFL))) + return (NULL); + + NEXT_PGNO(pagep) = (pgno_t)OADDR_TO_PAGE(ovfl_num); + TYPE(new_pagep) = HASH_OVFLPAGE; + + __put_page(hashp, pagep, A_RAW, 1); + #ifdef HASH_STATISTICS hash_overflows++; #endif - return (bufp->ovfl); + return (new_pagep); } /* + * * Returns: - * 0 indicates SUCCESS - * -1 indicates FAILURE + * pointer on success + * NULL on error */ -extern int -__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap) +extern PAGE16 * +#ifdef __STDC__ +__add_bigpage(HTAB * hashp, PAGE16 * pagep, indx_t ndx, const u_int8_t + is_basepage) +#else +__add_bigpage(hashp, pagep, ndx, is_basepage) HTAB *hashp; - char *p; - u_int32_t bucket; - int is_bucket, is_disk, is_bitmap; + PAGE16 *pagep; + u_int32_t ndx; + const u_int32_t is_basepage; +#endif { - register int fd, page, size; - int rsize; - u_int16_t *bp; + PAGE16 *new_pagep; + u_int16_t ovfl_num; - fd = hashp->fp; - size = hashp->BSIZE; + ovfl_num = overflow_page(hashp); - if ((fd == -1) || !is_disk) { - PAGE_INIT(p); - return (0); + if (__new_page(hashp, (u_int32_t)ovfl_num, A_OVFL) != 0) + return (NULL); + + if (!ovfl_num || !(new_pagep = __get_page(hashp, ovfl_num, A_OVFL))) + return (NULL); + + if (is_basepage) { + KEY_OFF(pagep, ndx) = BIGPAIR; + DATA_OFF(pagep, ndx) = (indx_t)ovfl_num; + } else + NEXT_PGNO(pagep) = ADDR(new_pagep); + + __put_page(hashp, pagep, A_RAW, 1); + + TYPE(new_pagep) = HASH_BIGPAGE; + +#ifdef HASH_STATISTICS + hash_bigpages++; +#endif + return (new_pagep); +} + +static void +#ifdef __STDC__ +page_init(HTAB * hashp, PAGE16 * pagep, pgno_t pgno, u_int8_t type) +#else +page_init(hashp, pagep, pgno, type) + HTAB *hashp; + PAGE16 *pagep; + pgno_t pgno; + u_int32_t type; +#endif +{ + NUM_ENT(pagep) = 0; + PREV_PGNO(pagep) = NEXT_PGNO(pagep) = INVALID_PGNO; + TYPE(pagep) = type; + OFFSET(pagep) = hashp->hdr.bsize - 1; + /* + * Note: since in the current version ADDR(pagep) == PREV_PGNO(pagep), + * make sure that ADDR(pagep) is set after resetting PREV_PGNO(pagep). + * We reset PREV_PGNO(pagep) just in case the macros are changed. + */ + ADDR(pagep) = pgno; + + return; +} + +int32_t +__new_page(hashp, addr, addr_type) + HTAB *hashp; + u_int32_t addr; + int32_t addr_type; +{ + pgno_t paddr; + PAGE16 *pagep; + + switch (addr_type) { /* Convert page number. */ + case A_BUCKET: + paddr = BUCKET_TO_PAGE(addr); + break; + case A_OVFL: + case A_BITMAP: + paddr = OADDR_TO_PAGE(addr); + break; + default: + paddr = addr; + break; } - if (is_bucket) - page = BUCKET_TO_PAGE(bucket); - else - page = OADDR_TO_PAGE(bucket); - if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) || - ((rsize = read(fd, p, size)) == -1)) + pagep = mpool_new(hashp->mp, &paddr, MPOOL_PAGE_REQUEST); + if (!pagep) return (-1); - bp = (u_int16_t *)p; - if (!rsize) - bp[0] = 0; /* We hit the EOF, so initialize a new page */ - else - if (rsize != size) { - errno = EFTYPE; - return (-1); - } - if (!is_bitmap && !bp[0]) { - PAGE_INIT(p); - } else - if (hashp->LORDER != BYTE_ORDER) { - register int i, max; +#if DEBUG_SLOW + account_page(hashp, paddr, 1); +#endif + + if (addr_type != A_BITMAP) + page_init(hashp, pagep, paddr, HASH_PAGE); + + __put_page(hashp, pagep, addr_type, 1); - if (is_bitmap) { - max = hashp->BSIZE >> 2; /* divide by 4 */ - for (i = 0; i < max; i++) - M_32_SWAP(((int *)p)[i]); - } else { - M_16_SWAP(bp[0]); - max = bp[0] + 2; - for (i = 1; i <= max; i++) - M_16_SWAP(bp[i]); - } - } return (0); } +int32_t +__delete_page(hashp, pagep, page_type) + HTAB *hashp; + PAGE16 *pagep; + int32_t page_type; +{ + if (page_type == A_OVFL) + __free_ovflpage(hashp, pagep); + return (mpool_delete(hashp->mp, pagep)); +} + +u_int8_t +is_bitmap_pgno(hashp, pgno) + HTAB *hashp; + pgno_t pgno; +{ + int32_t i; + + for (i = 0; i < hashp->nmaps; i++) + if (OADDR_TO_PAGE(hashp->hdr.bitmaps[i]) == pgno) + return (1); + return (0); +} + +void +__pgin_routine(pg_cookie, pgno, page) + void *pg_cookie; + pgno_t pgno; + void *page; +{ + HTAB *hashp; + PAGE16 *pagep; + int32_t max, i; + + pagep = (PAGE16 *)page; + hashp = (HTAB *)pg_cookie; + + /* + * There are the following cases for swapping: + * 0) New page that may be unitialized. + * 1) Bucket page or overflow page. Either swap + * the header or initialize the page. + * 2) Bitmap page. Swap the whole page! + * 3) Header pages. Not handled here; these are written directly + * to the file. + */ + + if (NUM_ENT(pagep) == 0 && NEXT_PGNO(pagep) == 0 && + !is_bitmap_pgno(hashp, pgno)) { + /* XXX check for !0 LSN */ + page_init(hashp, pagep, pgno, HASH_PAGE); + return; + } + + if (hashp->hdr.lorder == BYTE_ORDER) + return; + if (is_bitmap_pgno(hashp, pgno)) { + max = hashp->hdr.bsize >> 2; /* divide by 4 bytes */ + for (i = 0; i < max; i++) + M_32_SWAP(((int32_t *)pagep)[i]); + } else + swap_page_header_in(pagep); +} + +void +__pgout_routine(pg_cookie, pgno, page) + void *pg_cookie; + pgno_t pgno; + void *page; +{ + HTAB *hashp; + PAGE16 *pagep; + int32_t i, max; + + pagep = (PAGE16 *)page; + hashp = (HTAB *)pg_cookie; + + /* + * There are the following cases for swapping: + * 1) Bucket page or overflow page. Just swap the header. + * 2) Bitmap page. Swap the whole page! + * 3) Header pages. Not handled here; these are written directly + * to the file. + */ + + if (hashp->hdr.lorder == BYTE_ORDER) + return; + if (is_bitmap_pgno(hashp, pgno)) { + max = hashp->hdr.bsize >> 2; /* divide by 4 bytes */ + for (i = 0; i < max; i++) + M_32_SWAP(((int32_t *)pagep)[i]); + } else + swap_page_header_out(pagep); +} + /* - * Write page p to disk * * Returns: - * 0 ==> OK - * -1 ==>failure + * 0 ==> OK + * -1 ==>failure */ -extern int -__put_page(hashp, p, bucket, is_bucket, is_bitmap) +extern int32_t +__put_page(hashp, pagep, addr_type, is_dirty) HTAB *hashp; - char *p; - u_int32_t bucket; - int is_bucket, is_bitmap; + PAGE16 *pagep; + int32_t addr_type, is_dirty; { - register int fd, page, size; - int wsize; +#if DEBUG_SLOW + account_page(hashp, + ((BKT *)((char *)pagep - sizeof(BKT)))->pgno, -1); +#endif - size = hashp->BSIZE; - if ((hashp->fp == -1) && open_temp(hashp)) - return (-1); - fd = hashp->fp; + return (mpool_put(hashp->mp, pagep, (is_dirty ? MPOOL_DIRTY : 0))); +} - if (hashp->LORDER != BYTE_ORDER) { - register int i; - register int max; - - if (is_bitmap) { - max = hashp->BSIZE >> 2; /* divide by 4 */ - for (i = 0; i < max; i++) - M_32_SWAP(((int *)p)[i]); - } else { - max = ((u_int16_t *)p)[0] + 2; - for (i = 0; i <= max; i++) - M_16_SWAP(((u_int16_t *)p)[i]); - } +/* + * Returns: + * 0 indicates SUCCESS + * -1 indicates FAILURE + */ +extern PAGE16 * +__get_page(hashp, addr, addr_type) + HTAB *hashp; + u_int32_t addr; + int32_t addr_type; +{ + PAGE16 *pagep; + pgno_t paddr; + + switch (addr_type) { /* Convert page number. */ + case A_BUCKET: + paddr = BUCKET_TO_PAGE(addr); + break; + case A_OVFL: + case A_BITMAP: + paddr = OADDR_TO_PAGE(addr); + break; + default: + paddr = addr; + break; } - if (is_bucket) - page = BUCKET_TO_PAGE(bucket); - else - page = OADDR_TO_PAGE(bucket); - if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) || - ((wsize = write(fd, p, size)) == -1)) - /* Errno is set */ - return (-1); - if (wsize != size) { - errno = EFTYPE; - return (-1); + pagep = (PAGE16 *)mpool_get(hashp->mp, paddr, 0); + +#if DEBUG_SLOW + account_page(hashp, paddr, 1); +#endif +#ifdef DEBUG + assert(ADDR(pagep) == paddr || ADDR(pagep) == 0 || + addr_type == A_BITMAP || addr_type == A_HEADER); +#endif + + return (pagep); +} + +void +swap_page_header_in(pagep) + PAGE16 *pagep; +{ + u_int32_t i; + + /* can leave type and filler alone, since they're 1-byte quantities */ + + M_32_SWAP(PREV_PGNO(pagep)); + M_32_SWAP(NEXT_PGNO(pagep)); + M_16_SWAP(NUM_ENT(pagep)); + M_16_SWAP(OFFSET(pagep)); + + for (i = 0; i < NUM_ENT(pagep); i++) { + M_16_SWAP(KEY_OFF(pagep, i)); + M_16_SWAP(DATA_OFF(pagep, i)); } - return (0); } -#define BYTE_MASK ((1 << INT_BYTE_SHIFT) -1) +void +swap_page_header_out(pagep) + PAGE16 *pagep; +{ + u_int32_t i; + + for (i = 0; i < NUM_ENT(pagep); i++) { + M_16_SWAP(KEY_OFF(pagep, i)); + M_16_SWAP(DATA_OFF(pagep, i)) + } + + /* can leave type and filler alone, since they're 1-byte quantities */ + + M_32_SWAP(PREV_PGNO(pagep)); + M_32_SWAP(NEXT_PGNO(pagep)); + M_16_SWAP(NUM_ENT(pagep)); + M_16_SWAP(OFFSET(pagep)); +} + +#define BYTE_MASK ((1 << INT32_T_BYTE_SHIFT) -1) /* * Initialize a new bitmap page. Bitmap pages are left in memory * once they are read in. */ -extern int +extern int32_t __ibitmap(hashp, pnum, nbits, ndx) HTAB *hashp; - int pnum, nbits, ndx; + int32_t pnum, nbits, ndx; { u_int32_t *ip; - int clearbytes, clearints; + int32_t clearbytes, clearints; - if ((ip = (u_int32_t *)malloc(hashp->BSIZE)) == NULL) + /* make a new bitmap page */ + if (__new_page(hashp, pnum, A_BITMAP) != 0) + return (1); + if (!(ip = (u_int32_t *)__get_page(hashp, pnum, A_BITMAP))) return (1); hashp->nmaps++; - clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1; - clearbytes = clearints << INT_TO_BYTE; - (void)memset((char *)ip, 0, clearbytes); - (void)memset(((char *)ip) + clearbytes, 0xFF, - hashp->BSIZE - clearbytes); + clearints = ((nbits - 1) >> INT32_T_BYTE_SHIFT) + 1; + clearbytes = clearints << INT32_T_TO_BYTE; + (void)memset((int8_t *)ip, 0, clearbytes); + (void)memset((int8_t *)ip + clearbytes, + 0xFF, hashp->hdr.bsize - clearbytes); ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK); SETBIT(ip, 0); - hashp->BITMAPS[ndx] = (u_int16_t)pnum; + hashp->hdr.bitmaps[ndx] = (u_int16_t)pnum; hashp->mapp[ndx] = ip; return (0); } @@ -650,10 +1050,9 @@ first_free(map) u_int32_t map; { - register u_int32_t i, mask; + u_int32_t i, mask; - mask = 0x1; - for (i = 0; i < BITS_PER_MAP; i++) { + for (mask = 0x1, i = 0; i < BITS_PER_MAP; i++) { if (!(mask & map)) return (i); mask = mask << 1; @@ -665,33 +1064,38 @@ overflow_page(hashp) HTAB *hashp; { - register u_int32_t *freep; - register int max_free, offset, splitnum; + u_int32_t *freep; + int32_t bit, first_page, free_bit, free_page, i, in_use_bits, j; + int32_t max_free, offset, splitnum; u_int16_t addr; - int bit, first_page, free_bit, free_page, i, in_use_bits, j; #ifdef DEBUG2 - int tmp1, tmp2; + int32_t tmp1, tmp2; #endif - splitnum = hashp->OVFL_POINT; - max_free = hashp->SPARES[splitnum]; - free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT); - free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1); + splitnum = hashp->hdr.ovfl_point; + max_free = hashp->hdr.spares[splitnum]; - /* Look through all the free maps to find the first free block */ - first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT); - for ( i = first_page; i <= free_page; i++ ) { - if (!(freep = (u_int32_t *)hashp->mapp[i]) && - !(freep = fetch_bitmap(hashp, i))) + free_page = (max_free - 1) >> (hashp->hdr.bshift + BYTE_SHIFT); + free_bit = (max_free - 1) & ((hashp->hdr.bsize << BYTE_SHIFT) - 1); + + /* + * Look through all the free maps to find the first free block. + * The compiler under -Wall will complain that freep may be used + * before being set, however, this loop will ALWAYS get executed + * at least once, so freep is guaranteed to be set. + */ + first_page = hashp->hdr.last_freed >> (hashp->hdr.bshift + BYTE_SHIFT); + for (i = first_page; i <= free_page; i++) { + if (!(freep = fetch_bitmap(hashp, i))) return (0); if (i == free_page) in_use_bits = free_bit; else - in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1; - + in_use_bits = (hashp->hdr.bsize << BYTE_SHIFT) - 1; + if (i == first_page) { - bit = hashp->LAST_FREED & - ((hashp->BSIZE << BYTE_SHIFT) - 1); + bit = hashp->hdr.last_freed & + ((hashp->hdr.bsize << BYTE_SHIFT) - 1); j = bit / BITS_PER_MAP; bit = bit & ~(BITS_PER_MAP - 1); } else { @@ -704,25 +1108,25 @@ } /* No Free Page Found */ - hashp->LAST_FREED = hashp->SPARES[splitnum]; - hashp->SPARES[splitnum]++; - offset = hashp->SPARES[splitnum] - - (splitnum ? hashp->SPARES[splitnum - 1] : 0); + hashp->hdr.last_freed = hashp->hdr.spares[splitnum]; + hashp->hdr.spares[splitnum]++; + offset = hashp->hdr.spares[splitnum] - + (splitnum ? hashp->hdr.spares[splitnum - 1] : 0); #define OVMSG "HASH: Out of overflow pages. Increase page size\n" + if (offset > SPLITMASK) { if (++splitnum >= NCACHED) { (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); return (0); } - hashp->OVFL_POINT = splitnum; - hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1]; - hashp->SPARES[splitnum-1]--; + hashp->hdr.ovfl_point = splitnum; + hashp->hdr.spares[splitnum] = hashp->hdr.spares[splitnum - 1]; + hashp->hdr.spares[splitnum - 1]--; offset = 1; } - - /* Check if we need to allocate a new bitmap page */ - if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) { + /* Check if we need to allocate a new bitmap page. */ + if (free_bit == (hashp->hdr.bsize << BYTE_SHIFT) - 1) { free_page++; if (free_page >= NCACHED) { (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); @@ -733,29 +1137,30 @@ * allocated with 1 clear bit. Actually, you are going to * allocate 2 pages from this map. The first is going to be * the map page, the second is the overflow page we were - * looking for. The init_bitmap routine automatically, sets + * looking for. The __ibitmap routine automatically, sets * the first bit of itself to indicate that the bitmap itself * is in use. We would explicitly set the second bit, but - * don't have to if we tell init_bitmap not to leave it clear + * don't have to if we tell __ibitmap not to leave it clear * in the first place. */ if (__ibitmap(hashp, - (int)OADDR_OF(splitnum, offset), 1, free_page)) + (int32_t)OADDR_OF(splitnum, offset), 1, free_page)) return (0); - hashp->SPARES[splitnum]++; + hashp->hdr.spares[splitnum]++; #ifdef DEBUG2 free_bit = 2; #endif offset++; if (offset > SPLITMASK) { if (++splitnum >= NCACHED) { - (void)write(STDERR_FILENO, OVMSG, - sizeof(OVMSG) - 1); + (void)write(STDERR_FILENO, + OVMSG, sizeof(OVMSG) - 1); return (0); } - hashp->OVFL_POINT = splitnum; - hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1]; - hashp->SPARES[splitnum-1]--; + hashp->hdr.ovfl_point = splitnum; + hashp->hdr.spares[splitnum] = + hashp->hdr.spares[splitnum - 1]; + hashp->hdr.spares[splitnum - 1]--; offset = 0; } } else { @@ -773,6 +1178,11 @@ (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n", addr, free_bit, free_page); #endif + + if (OADDR_TO_PAGE(addr) > MAX_PAGES(hashp)) { + (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); + return (0); + } return (addr); found: @@ -784,16 +1194,16 @@ #endif /* * Bits are addressed starting with 0, but overflow pages are addressed - * beginning at 1. Bit is a bit addressnumber, so we need to increment + * beginning at 1. Bit is a bit address number, so we need to increment * it to convert it to a page number. */ - bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT)); - if (bit >= hashp->LAST_FREED) - hashp->LAST_FREED = bit - 1; + bit = 1 + bit + (i * (hashp->hdr.bsize << BYTE_SHIFT)); + if (bit >= hashp->hdr.last_freed) + hashp->hdr.last_freed = bit - 1; /* Calculate the split number for this page */ - for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++); - offset = (i ? bit - hashp->SPARES[i - 1] : bit); + for (i = 0; i < splitnum && (bit > hashp->hdr.spares[i]); i++); + offset = (i ? bit - hashp->hdr.spares[i - 1] : bit); if (offset >= SPLITMASK) return (0); /* Out of overflow pages */ addr = OADDR_OF(i, offset); @@ -802,37 +1212,100 @@ addr, tmp1, tmp2); #endif + if (OADDR_TO_PAGE(addr) > MAX_PAGES(hashp)) { + (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); + return (0); + } /* Allocate and return the overflow page */ return (addr); } +#ifdef DEBUG +int +bucket_to_page(hashp, n) + HTAB *hashp; + int n; +{ + int ret_val; + + ret_val = n + hashp->hdr.hdrpages; + if (n != 0) + ret_val += hashp->hdr.spares[__log2(n + 1) - 1]; + return (ret_val); +} + +int32_t +oaddr_to_page(hashp, n) + HTAB *hashp; + int n; +{ + int ret_val, temp; + + temp = (1 << SPLITNUM(n)) - 1; + ret_val = bucket_to_page(hashp, temp); + ret_val += (n & SPLITMASK); + + return (ret_val); +} +#endif /* DEBUG */ + +indx_t +page_to_oaddr(hashp, pgno) + HTAB *hashp; + pgno_t pgno; +{ + int32_t sp, ret_val; + + /* + * To convert page number to overflow address: + * + * 1. Find a starting split point -- use 0 since there are only + * 32 split points. + * 2. Find the split point s.t. 2^sp + hdr.spares[sp] < pgno and + * 2^(sp+1) = hdr.spares[sp+1] > pgno. The overflow address will + * be located at sp. + * 3. return... + */ + pgno -= hashp->hdr.hdrpages; + for (sp = 0; sp < NCACHED; sp++) + if (POW2(sp) + hashp->hdr.spares[sp] < pgno && + (POW2(sp + 1) + hashp->hdr.spares[sp + 1]) > pgno) + break; + + ret_val = OADDR_OF(sp + 1, + pgno - ((POW2(sp + 1) - 1) + hashp->hdr.spares[sp])); +#ifdef DEBUG + assert(OADDR_TO_PAGE(ret_val) == (pgno + hashp->hdr.hdrpages)); +#endif + return (ret_val); +} + /* * Mark this overflow page as free. */ extern void -__free_ovflpage(hashp, obufp) +__free_ovflpage(hashp, pagep) HTAB *hashp; - BUFHEAD *obufp; + PAGE16 *pagep; { - register u_int16_t addr; u_int32_t *freep; - int bit_address, free_page, free_bit; - u_int16_t ndx; + int32_t bit_address, free_page, free_bit; + u_int16_t addr, ndx; + + addr = page_to_oaddr(hashp, ADDR(pagep)); - addr = obufp->addr; -#ifdef DEBUG1 +#ifdef DEBUG2 (void)fprintf(stderr, "Freeing %d\n", addr); #endif - ndx = (((u_int16_t)addr) >> SPLITSHIFT); + ndx = ((u_int16_t)addr) >> SPLITSHIFT; bit_address = - (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1; - if (bit_address < hashp->LAST_FREED) - hashp->LAST_FREED = bit_address; - free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT)); - free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1); + (ndx ? hashp->hdr.spares[ndx - 1] : 0) + (addr & SPLITMASK) - 1; + if (bit_address < hashp->hdr.last_freed) + hashp->hdr.last_freed = bit_address; + free_page = (bit_address >> (hashp->hdr.bshift + BYTE_SHIFT)); + free_bit = bit_address & ((hashp->hdr.bsize << BYTE_SHIFT) - 1); - if (!(freep = hashp->mapp[free_page])) - freep = fetch_bitmap(hashp, free_page); + freep = fetch_bitmap(hashp, free_page); #ifdef DEBUG /* * This had better never happen. It means we tried to read a bitmap @@ -847,98 +1320,93 @@ (void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n", obufp->addr, free_bit, free_page); #endif - __reclaim_buf(hashp, obufp); } -/* - * Returns: - * 0 success - * -1 failure - */ -static int -open_temp(hashp) +static u_int32_t * +fetch_bitmap(hashp, ndx) HTAB *hashp; + int32_t ndx; { - sigset_t set, oset; - static char namestr[] = "_hashXXXXXX"; + if (ndx >= hashp->nmaps) + return (NULL); + if (!hashp->mapp[ndx]) + hashp->mapp[ndx] = (u_int32_t *)__get_page(hashp, + hashp->hdr.bitmaps[ndx], A_BITMAP); - /* Block signals; make sure file goes away at process exit. */ - (void)sigfillset(&set); - (void)sigprocmask(SIG_BLOCK, &set, &oset); - if ((hashp->fp = mkstemp(namestr)) != -1) { - (void)unlink(namestr); - (void)fcntl(hashp->fp, F_SETFD, 1); - } - (void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL); - return (hashp->fp != -1 ? 0 : -1); + return (hashp->mapp[ndx]); } -/* - * We have to know that the key will fit, but the last entry on the page is - * an overflow pair, so we need to shift things. - */ static void -squeeze_key(sp, key, val) - u_int16_t *sp; - const DBT *key, *val; +adjust_cursor(hashp, ndx, chg_pgno, nxt_pgno, page_deleted) + HTAB *hashp; + int32_t ndx; + pgno_t chg_pgno; + pgno_t nxt_pgno; + int page_deleted; { - register char *p; - u_int16_t free_space, n, off, pageno; + CURSOR *cp; - p = (char *)sp; - n = sp[0]; - free_space = FREESPACE(sp); - off = OFFSET(sp); - - pageno = sp[n - 1]; - off -= key->size; - sp[n - 1] = off; - memmove(p + off, key->data, key->size); - off -= val->size; - sp[n] = off; - memmove(p + off, val->data, val->size); - sp[0] = n + 2; - sp[n + 1] = pageno; - sp[n + 2] = OVFLPAGE; - FREESPACE(sp) = free_space - PAIRSIZE(key, val); - OFFSET(sp) = off; + for (cp = (CURSOR *)hashp->curs_queue.tqh_first; + cp != NULL; + cp = (CURSOR *)cp->queue.tqe_next) { + if (cp->pgno == chg_pgno && ndx < cp->pgndx) { + if (page_deleted) { + if (nxt_pgno == INVALID_PGNO) { + cp->bucket++; + cp->pgno = INVALID_PGNO; + } else { + cp->pgno = nxt_pgno; + cp->pgndx = 0; + } + if (cp->pagep) { + __put_page(hashp, cp->pagep, A_RAW, 0); + cp->pagep == NULL; + } + } else { + cp->pgndx--; + cp->ndx--; + } + } + } } -static u_int32_t * -fetch_bitmap(hashp, ndx) +#ifdef DEBUG_SLOW +static void +account_page(hashp, pgno, inout) HTAB *hashp; - int ndx; + pgno_t pgno; + int inout; { - if (ndx >= hashp->nmaps) - return (NULL); - if ((hashp->mapp[ndx] = (u_int32_t *)malloc(hashp->BSIZE)) == NULL) - return (NULL); - if (__get_page(hashp, - (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) { - free(hashp->mapp[ndx]); - return (NULL); + static struct { + pgno_t pgno; + int times; + } list[100]; + static int last; + int i, j; + + if (inout == -1) /* XXX: Kluge */ + inout = 0; + + /* Find page in list. */ + for (i = 0; i < last; i++) + if (list[i].pgno == pgno) + break; + /* Not found. */ + if (i == last) { + list[last].times = inout; + list[last].pgno = pgno; + last++; } - return (hashp->mapp[ndx]); -} - -#ifdef DEBUG4 -int -print_chain(addr) - int addr; -{ - BUFHEAD *bufp; - short *bp, oaddr; - - (void)fprintf(stderr, "%d ", addr); - bufp = __get_buf(hashp, addr, NULL, 0); - bp = (short *)bufp->page; - while (bp[0] && ((bp[bp[0]] == OVFLPAGE) || - ((bp[0] > 2) && bp[2] < REAL_KEY))) { - oaddr = bp[bp[0] - 1]; - (void)fprintf(stderr, "%d ", (int)oaddr); - bufp = __get_buf(hashp, (int)oaddr, bufp, 0); - bp = (short *)bufp->page; + list[i].times = inout; + if (list[i].times == 0) { + for (j = i; j < last; j++) + list[j] = list[j + 1]; + last--; } - (void)fprintf(stderr, "\n"); + for (i = 0; i < last; i++, list[i].times++) + if (list[i].times > 20 && !is_bitmap_pgno(hashp, list[i].pgno)) + (void)fprintf(stderr, + "Warning: pg %d has been out for %d times\n", + list[i].pgno, list[i].times); } -#endif +#endif /* DEBUG_SLOW */ diff -u -r -N bdb185/db.1.85/hash/hsearch.c bdb186/db.1.86/hash/hsearch.c --- bdb185/db.1.85/hash/hsearch.c 1994-07-21 11:02:29.000000000 -0700 +++ bdb186/db.1.86/hash/hsearch.c 1997-01-04 11:25:41.000000000 -0800 @@ -35,7 +35,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hsearch.c 8.4 (Berkeley) 7/21/94"; +static char sccsid[] = "@(#)hsearch.c 8.5 (Berkeley) 9/21/94"; #endif /* LIBC_SCCS and not lint */ #include @@ -62,7 +62,7 @@ info.hash = NULL; info.lorder = 0; dbp = (DB *)__hash_open(NULL, O_CREAT | O_RDWR, 0600, &info, 0); - return ((int)dbp); + return (dbp != NULL); } extern ENTRY * diff -u -r -N bdb185/db.1.85/hash/ndbm.c bdb186/db.1.86/hash/ndbm.c --- bdb185/db.1.85/hash/ndbm.c 1994-07-21 11:02:40.000000000 -0700 +++ bdb186/db.1.86/hash/ndbm.c 1997-01-04 11:25:41.000000000 -0800 @@ -35,16 +35,12 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94"; +static char sccsid[] = "@(#)dbm.c 8.6 (Berkeley) 11/7/95"; #endif /* LIBC_SCCS and not lint */ -/* - * This package provides a dbm compatible interface to the new hashing - * package described in db(3). - */ - #include +#include #include #include @@ -52,11 +48,107 @@ #include "hash.h" /* + * + * This package provides dbm and ndbm compatible interfaces to DB. + * First are the DBM routines, which call the NDBM routines, and + * the NDBM routines, which call the DB routines. + */ +static DBM *__cur_db; + +static void no_open_db __P((void)); + +int +dbminit(file) + char *file; +{ + if (__cur_db != NULL) + (void)dbm_close(__cur_db); + if ((__cur_db = dbm_open(file, O_RDWR, 0)) != NULL) + return (0); + if ((__cur_db = dbm_open(file, O_RDONLY, 0)) != NULL) + return (0); + return (-1); +} + +datum +fetch(key) + datum key; +{ + datum item; + + if (__cur_db == NULL) { + no_open_db(); + item.dptr = 0; + return (item); + } + return (dbm_fetch(__cur_db, key)); +} + +datum +firstkey() +{ + datum item; + + if (__cur_db == NULL) { + no_open_db(); + item.dptr = 0; + return (item); + } + return (dbm_firstkey(__cur_db)); +} + +datum +nextkey(key) + datum key; +{ + datum item; + + if (__cur_db == NULL) { + no_open_db(); + item.dptr = 0; + return (item); + } + return (dbm_nextkey(__cur_db)); +} + +int +delete(key) + datum key; +{ + if (__cur_db == NULL) { + no_open_db(); + return (-1); + } + if (dbm_rdonly(__cur_db)) + return (-1); + return (dbm_delete(__cur_db, key)); +} + +int +store(key, dat) + datum key, dat; +{ + if (__cur_db == NULL) { + no_open_db(); + return (-1); + } + if (dbm_rdonly(__cur_db)) + return (-1); + return (dbm_store(__cur_db, key, dat, DBM_REPLACE)); +} + +static void +no_open_db() +{ + (void)fprintf(stderr, "dbm: no open database.\n"); +} + +/* * Returns: * *DBM on success * NULL on failure */ -extern DBM * +DBM * dbm_open(file, flags, mode) const char *file; int flags, mode; @@ -75,7 +167,11 @@ return ((DBM *)__hash_open(path, flags, mode, &info, 0)); } -extern void +/* + * Returns: + * Nothing. + */ +void dbm_close(db) DBM *db; { @@ -87,7 +183,7 @@ * DATUM on success * NULL on failure */ -extern datum +datum dbm_fetch(db, key) DBM *db; datum key; @@ -108,7 +204,7 @@ * DATUM on success * NULL on failure */ -extern datum +datum dbm_firstkey(db) DBM *db; { @@ -126,7 +222,7 @@ * DATUM on success * NULL on failure */ -extern datum +datum dbm_nextkey(db) DBM *db; { @@ -138,12 +234,13 @@ retkey.dptr = NULL; return (retkey); } + /* * Returns: * 0 on success * <0 failure */ -extern int +int dbm_delete(db, key) DBM *db; datum key; @@ -163,7 +260,7 @@ * <0 failure * 1 if DBM_INSERT and entry exists */ -extern int +int dbm_store(db, key, content, flags) DBM *db; datum key, content; @@ -173,7 +270,7 @@ (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); } -extern int +int dbm_error(db) DBM *db; { @@ -183,7 +280,7 @@ return (hp->errno); } -extern int +int dbm_clearerr(db) DBM *db; { @@ -194,7 +291,7 @@ return (0); } -extern int +int dbm_dirfno(db) DBM *db; { diff -u -r -N bdb185/db.1.85/hash/page.h bdb186/db.1.86/hash/page.h --- bdb185/db.1.85/hash/page.h 1994-05-31 13:56:54.000000000 -0700 +++ bdb186/db.1.86/hash/page.h 1997-01-04 11:25:41.000000000 -0800 @@ -33,60 +33,146 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)page.h 8.2 (Berkeley) 5/31/94 + * @(#)page.h 8.4 (Berkeley) 11/7/95 */ +#define HI_MASK 0xFFFF0000 +#define LO_MASK (~HI_MASK) + +#define HI(N) ((u_int16_t)(((N) & HI_MASK) >> 16)) +#define LO(N) ((u_int16_t)((N) & LO_MASK)) + +/* Constants for big key page overhead information. */ +#define NUMSHORTS 0 +#define KEYLEN 1 +#define DATALEN 2 +#define NEXTPAGE 3 + /* - * Definitions for hashing page file format. + * Hash pages store meta-data beginning at the top of the page (offset 0) + * and key/data values beginning at the bottom of the page (offset pagesize). + * Fields are always accessed via macros so that we can change the page + * format without too much pain. The only changes that will require massive + * code changes are if we no longer store key/data offsets next to each + * other (since we use that fact to compute key lengths). In the accessor + * macros below, P means a pointer to the page, I means an index of the + * particular entry being accessed. + * + * Hash base page format + * BYTE ITEM NBYTES TYPE ACCESSOR MACRO + * ---- ------------------ ------ -------- -------------- + * 0 previous page number 4 pgno_t PREV_PGNO(P) + * 4 next page number 4 pgno_t NEXT_PGNO(P) + * 8 # pairs on page 2 indx_t NUM_ENT(P) + * 10 page type 1 u_int8_t TYPE(P) + * 11 padding 1 u_int8_t none + * 12 highest free byte 2 indx_t OFFSET(P) + * 14 key offset 0 2 indx_t KEY_OFF(P, I) + * 16 data offset 0 2 indx_t DATA_OFF(P, I) + * 18 key offset 1 2 indx_t KEY_OFF(P, I) + * 20 data offset 1 2 indx_t DATA_OFF(P, I) + * ...etc... */ +/* Indices (in bytes) of the beginning of each of these entries */ +#define I_PREV_PGNO 0 +#define I_NEXT_PGNO 4 +#define I_ENTRIES 8 +#define I_TYPE 10 +#define I_HF_OFFSET 12 + +/* Overhead is everything prior to the first key/data pair. */ +#define PAGE_OVERHEAD (I_HF_OFFSET + sizeof(indx_t)) + +/* To allocate a pair, we need room for one key offset and one data offset. */ +#define PAIR_OVERHEAD ((sizeof(indx_t) << 1)) + +/* Use this macro to extract a value of type T from page P at offset O. */ +#define REFERENCE(P, T, O) (((T *)((u_int8_t *)(P) + O))[0]) + /* - * routines dealing with a data page - * - * page format: - * +------------------------------+ - * p | n | keyoff | datoff | keyoff | - * +------------+--------+--------+ - * | datoff | free | ptr | --> | - * +--------+---------------------+ - * | F R E E A R E A | - * +--------------+---------------+ - * | <---- - - - | data | - * +--------+-----+----+----------+ - * | key | data | key | - * +--------+----------+----------+ - * - * Pointer to the free space is always: p[p[0] + 2] - * Amount of free space on the page is: p[p[0] + 1] + * Use these macros to access fields on a page; P is a PAGE16 *. + */ +#define NUM_ENT(P) (REFERENCE((P), indx_t, I_ENTRIES)) +#define PREV_PGNO(P) (REFERENCE((P), pgno_t, I_PREV_PGNO)) +#define NEXT_PGNO(P) (REFERENCE((P), pgno_t, I_NEXT_PGNO)) +#define TYPE(P) (REFERENCE((P), u_int8_t, I_TYPE)) +#define OFFSET(P) (REFERENCE((P), indx_t, I_HF_OFFSET)) +/* + * We need to store a page's own address on each page (unlike the Btree + * access method which needs the previous page). We use the PREV_PGNO + * field to store our own page number. */ +#define ADDR(P) (PREV_PGNO((P))) + +/* Extract key/data offsets and data for a given index. */ +#define DATA_OFF(P, N) \ + REFERENCE(P, indx_t, PAGE_OVERHEAD + N * PAIR_OVERHEAD + sizeof(indx_t)) +#define KEY_OFF(P, N) \ + REFERENCE(P, indx_t, PAGE_OVERHEAD + N * PAIR_OVERHEAD) + +#define KEY(P, N) (((PAGE8 *)(P)) + KEY_OFF((P), (N))) +#define DATA(P, N) (((PAGE8 *)(P)) + DATA_OFF((P), (N))) /* - * How many bytes required for this pair? - * 2 shorts in the table at the top of the page + room for the - * key and room for the data - * - * We prohibit entering a pair on a page unless there is also room to append - * an overflow page. The reason for this it that you can get in a situation - * where a single key/data pair fits on a page, but you can't append an - * overflow page and later you'd have to split the key/data and handle like - * a big pair. - * You might as well do this up front. - */ - -#define PAIRSIZE(K,D) (2*sizeof(u_int16_t) + (K)->size + (D)->size) -#define BIGOVERHEAD (4*sizeof(u_int16_t)) -#define KEYSIZE(K) (4*sizeof(u_int16_t) + (K)->size); -#define OVFLSIZE (2*sizeof(u_int16_t)) -#define FREESPACE(P) ((P)[(P)[0]+1]) -#define OFFSET(P) ((P)[(P)[0]+2]) -#define PAIRFITS(P,K,D) \ - (((P)[2] >= REAL_KEY) && \ - (PAIRSIZE((K),(D)) + OVFLSIZE) <= FREESPACE((P))) -#define PAGE_META(N) (((N)+3) * sizeof(u_int16_t)) - -typedef struct { - BUFHEAD *newp; - BUFHEAD *oldp; - BUFHEAD *nextp; - u_int16_t next_addr; -} SPLIT_RETURN; + * Macros used to compute various sizes on a page. + */ +#define PAIRSIZE(K, D) (PAIR_OVERHEAD + (K)->size + (D)->size) +#define BIGOVERHEAD (4 * sizeof(u_int16_t)) +#define KEYSIZE(K) (4 * sizeof(u_int16_t) + (K)->size); +#define OVFLSIZE (2 * sizeof(u_int16_t)) +#define BIGPAGEOVERHEAD (4 * sizeof(u_int16_t)) +#define BIGPAGEOFFSET 4 +#define BIGPAGESIZE(P) ((P)->BSIZE - BIGPAGEOVERHEAD) + +#define PAGE_META(N) (((N) + 3) * sizeof(u_int16_t)) +#define MINFILL 0.75 +#define ISBIG(N, P) (((N) > ((P)->hdr.bsize * MINFILL)) ? 1 : 0) + +#define ITEMSIZE(I) (sizeof(u_int16_t) + (I)->size) + +/* + * Big key/data pages use a different page format. They have a single + * key/data "pair" containing the length of the key and data instead + * of offsets. + */ +#define BIGKEYLEN(P) (KEY_OFF((P), 0)) +#define BIGDATALEN(P) (DATA_OFF((P), 0)) +#define BIGKEY(P) (((PAGE8 *)(P)) + PAGE_OVERHEAD + PAIR_OVERHEAD) +#define BIGDATA(P) \ + (((PAGE8 *)(P)) + PAGE_OVERHEAD + PAIR_OVERHEAD + KEY_OFF((P), 0)) + + +#define OVFLPAGE 0 +#define BIGPAIR 0 +#define INVALID_PGNO 0xFFFFFFFF + +typedef unsigned short PAGE16; +typedef unsigned char PAGE8; + +#define A_BUCKET 0 +#define A_OVFL 1 +#define A_BITMAP 2 +#define A_RAW 4 +#define A_HEADER 5 + +#define PAIRFITS(P,K,D) ((PAIRSIZE((K),(D))) <= FREESPACE((P))) +#define BIGPAIRFITS(P) ((FREESPACE((P)) >= PAIR_OVERHEAD)) +/* + * Since these are all unsigned, we need to guarantee that we never go + * negative. Offset values are 0-based and overheads are one based (i.e. + * one byte of overhead is 1, not 0), so we need to convert OFFSETs to + * 1-based counting before subtraction. + */ +#define FREESPACE(P) \ + ((OFFSET((P)) + 1 - PAGE_OVERHEAD - (NUM_ENT((P)) * PAIR_OVERHEAD))) + +/* + * Overhead on header pages is just one word -- the length of the + * header info stored on that page. + */ +#define HEADER_OVERHEAD 4 + +#define HASH_PAGE 2 +#define HASH_BIGPAGE 3 +#define HASH_OVFLPAGE 4 diff -u -r -N bdb185/db.1.85/include/db.h bdb186/db.1.86/include/db.h --- bdb185/db.1.85/include/db.h 1994-06-21 12:59:28.000000000 -0700 +++ bdb186/db.1.86/include/db.h 1997-01-04 11:39:53.000000000 -0800 @@ -146,7 +146,7 @@ } BTREEINFO; #define HASHMAGIC 0x061561 -#define HASHVERSION 2 +#define HASHVERSION 3 /* Structure used to pass parameters to the hashing routines. */ typedef struct { diff -u -r -N bdb185/db.1.85/include/mpool.h bdb186/db.1.86/include/mpool.h --- bdb185/db.1.85/include/mpool.h 1994-07-13 18:33:26.000000000 -0700 +++ bdb186/db.1.86/include/mpool.h 1996-06-11 06:06:35.000000000 -0700 @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 */ #include @@ -43,7 +43,7 @@ * pool is handed an opaque MPOOL cookie which stores all of this information. */ #define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) +#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE) /* The BKT structures are the elements of the queues. */ typedef struct _bkt { @@ -54,6 +54,7 @@ #define MPOOL_DIRTY 0x01 /* page needs to be written */ #define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ u_int8_t flags; /* flags */ } BKT; @@ -84,12 +85,19 @@ #endif } MPOOL; +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + __BEGIN_DECLS MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), void (*)(void *, pgno_t, void *), void *)); -void *mpool_new __P((MPOOL *, pgno_t *)); +void *mpool_new __P((MPOOL *, pgno_t *, u_int)); void *mpool_get __P((MPOOL *, pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); int mpool_put __P((MPOOL *, void *, u_int)); int mpool_sync __P((MPOOL *)); int mpool_close __P((MPOOL *)); diff -u -r -N bdb185/db.1.85/mpool/mpool.c bdb186/db.1.86/mpool/mpool.c --- bdb185/db.1.85/mpool/mpool.c 1994-07-26 12:19:35.000000000 -0700 +++ bdb186/db.1.86/mpool/mpool.c 1997-01-04 11:50:48.000000000 -0800 @@ -32,7 +32,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)mpool.c 8.5 (Berkeley) 7/26/94"; +static char sccsid[] = "@(#)mpool.c 8.7 (Berkeley) 11/2/95"; #endif /* LIBC_SCCS and not lint */ #include @@ -115,9 +115,10 @@ * Get a new page of memory. */ void * -mpool_new(mp, pgnoaddr) +mpool_new(mp, pgnoaddr, flags) MPOOL *mp; pgno_t *pgnoaddr; + u_int flags; { struct _hqh *head; BKT *bp; @@ -136,8 +137,13 @@ */ if ((bp = mpool_bkt(mp)) == NULL) return (NULL); - *pgnoaddr = bp->pgno = mp->npages++; - bp->flags = MPOOL_PINNED; + if (flags == MPOOL_PAGE_REQUEST) { + mp->npages++; + bp->pgno = *pgnoaddr; + } else + bp->pgno = *pgnoaddr = mp->npages++; + + bp->flags = MPOOL_PINNED | MPOOL_INUSE; head = &mp->hqh[HASHKEY(bp->pgno)]; CIRCLEQ_INSERT_HEAD(head, bp, hq); @@ -145,6 +151,33 @@ return (bp->page); } +int +mpool_delete(mp, page) + MPOOL *mp; + void *page; +{ + struct _hqh *head; + BKT *bp; + + bp = (BKT *)((char *)page - sizeof(BKT)); + +#ifdef DEBUG + if (!(bp->flags & MPOOL_PINNED)) { + (void)fprintf(stderr, + "mpool_delete: page %d not pinned\n", bp->pgno); + abort(); + } +#endif + + /* Remove from the hash and lru queues. */ + head = &mp->hqh[HASHKEY(bp->pgno)]; + CIRCLEQ_REMOVE(head, bp, hq); + CIRCLEQ_REMOVE(&mp->lqh, bp, q); + + free(bp); + return (RET_SUCCESS); +} + /* * mpool_get * Get a page. @@ -160,12 +193,6 @@ off_t off; int nr; - /* Check for attempt to retrieve a non-existent page. */ - if (pgno >= mp->npages) { - errno = EINVAL; - return (NULL); - } - #ifdef STATISTICS ++mp->pageget; #endif @@ -173,7 +200,7 @@ /* Check for a page that is cached. */ if ((bp = mpool_look(mp, pgno)) != NULL) { #ifdef DEBUG - if (bp->flags & MPOOL_PINNED) { + if (!(flags & MPOOL_IGNOREPIN) && bp->flags & MPOOL_PINNED) { (void)fprintf(stderr, "mpool_get: page %d already pinned\n", bp->pgno); abort(); @@ -205,15 +232,26 @@ off = mp->pagesize * pgno; if (lseek(mp->fd, off, SEEK_SET) != off) return (NULL); + if ((nr = read(mp->fd, bp->page, mp->pagesize)) != mp->pagesize) { - if (nr >= 0) - errno = EFTYPE; - return (NULL); + if (nr > 0) { + /* A partial read is definitely bad. */ + errno = EINVAL; + return (NULL); + } else { + /* + * A zero-length reads, means you need to create a + * new page. + */ + memset(bp->page, 0, mp->pagesize); + } } /* Set the page number, pin the page. */ bp->pgno = pgno; - bp->flags = MPOOL_PINNED; + if (!(flags & MPOOL_IGNOREPIN)) + bp->flags = MPOOL_PINNED; + bp->flags |= MPOOL_INUSE; /* * Add the page to the head of the hash chain and the tail @@ -254,7 +292,8 @@ } #endif bp->flags &= ~MPOOL_PINNED; - bp->flags |= flags & MPOOL_DIRTY; + if (flags & MPOOL_DIRTY) + bp->flags |= flags & MPOOL_DIRTY; return (RET_SUCCESS); } @@ -342,6 +381,7 @@ bp->page = spage; } #endif + bp->flags = 0; return (bp); } @@ -354,6 +394,7 @@ memset(bp, 0xff, sizeof(BKT) + mp->pagesize); #endif bp->page = (char *)bp + sizeof(BKT); + bp->flags = 0; ++mp->curcache; return (bp); } @@ -401,7 +442,8 @@ head = &mp->hqh[HASHKEY(pgno)]; for (bp = head->cqh_first; bp != (void *)head; bp = bp->hq.cqe_next) - if (bp->pgno == pgno) { + if ((bp->pgno == pgno) && + (bp->flags & MPOOL_INUSE == MPOOL_INUSE)) { #ifdef STATISTICS ++mp->cachehit; #endif