зеркало из https://github.com/mozilla/gecko-dev.git
Removing mozilla/db due to incompatible license.
This commit is contained in:
Родитель
c444378873
Коммит
c3543c147a
|
@ -1,177 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Mike Olson.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)bt_close.c 10.32 (Sleepycat) 5/6/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "btree.h"
|
||||
|
||||
static void __bam_upstat __P((DB *dbp));
|
||||
|
||||
/*
|
||||
* __bam_close --
|
||||
* Close a btree.
|
||||
*
|
||||
* PUBLIC: int __bam_close __P((DB *));
|
||||
*/
|
||||
int
|
||||
__bam_close(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
BTREE *t;
|
||||
|
||||
DEBUG_LWRITE(dbp, NULL, "bam_close", NULL, NULL, 0);
|
||||
|
||||
t = dbp->internal;
|
||||
|
||||
/* Update tree statistics. */
|
||||
__bam_upstat(dbp);
|
||||
|
||||
/* Free any allocated memory. */
|
||||
if (t->bt_rkey.data)
|
||||
FREE(t->bt_rkey.data, t->bt_rkey.size);
|
||||
if (t->bt_rdata.data)
|
||||
FREE(t->bt_rdata.data, t->bt_rdata.ulen);
|
||||
if (t->bt_sp != t->bt_stack)
|
||||
FREE(t->bt_sp, (t->bt_esp - t->bt_sp) * sizeof(EPG));
|
||||
|
||||
FREE(t, sizeof(BTREE));
|
||||
dbp->internal = NULL;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_sync --
|
||||
* Sync the btree to disk.
|
||||
*
|
||||
* PUBLIC: int __bam_sync __P((DB *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__bam_sync(argdbp, flags)
|
||||
DB *argdbp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB *dbp;
|
||||
int ret;
|
||||
|
||||
DEBUG_LWRITE(argdbp, NULL, "bam_sync", NULL, NULL, flags);
|
||||
|
||||
/* Check for invalid flags. */
|
||||
if ((ret = __db_syncchk(argdbp, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* If it wasn't possible to modify the file, we're done. */
|
||||
if (F_ISSET(argdbp, DB_AM_INMEM | DB_AM_RDONLY))
|
||||
return (0);
|
||||
|
||||
GETHANDLE(argdbp, NULL, &dbp, ret);
|
||||
|
||||
/* Flush any dirty pages from the cache to the backing file. */
|
||||
if ((ret = memp_fsync(dbp->mpf)) == DB_INCOMPLETE)
|
||||
ret = 0;
|
||||
|
||||
PUTHANDLE(dbp);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_upstat --
|
||||
* Update tree statistics.
|
||||
*/
|
||||
static void
|
||||
__bam_upstat(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
BTREE *t;
|
||||
BTMETA *meta;
|
||||
DB_LOCK metalock;
|
||||
db_pgno_t pgno;
|
||||
u_int32_t flags;
|
||||
|
||||
/*
|
||||
* We use a no-op log call to log the update of the statistics onto the
|
||||
* metadata page. The Db->close call isn't transaction protected to
|
||||
* start with, and I'm not sure what undoing a statistics update means,
|
||||
* anyway.
|
||||
*/
|
||||
if (F_ISSET(dbp, DB_AM_INMEM | DB_AM_RDONLY))
|
||||
return;
|
||||
|
||||
flags = 0;
|
||||
pgno = PGNO_METADATA;
|
||||
|
||||
/* Lock and retrieve the page. */
|
||||
if (__bam_lget(dbp, 0, pgno, DB_LOCK_WRITE, &metalock) != 0)
|
||||
return;
|
||||
if (__bam_pget(dbp, (PAGE **)&meta, &pgno, 0) == 0) {
|
||||
/* Log the change. */
|
||||
if (DB_LOGGING(dbp) &&
|
||||
__db_noop_log(dbp->dbenv->lg_info, dbp->txn, &LSN(meta), 0,
|
||||
dbp->log_fileid, PGNO_METADATA, &LSN(meta)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Update the statistics. */
|
||||
t = dbp->internal;
|
||||
__bam_add_mstat(&t->lstat, &meta->stat);
|
||||
|
||||
flags = DB_MPOOL_DIRTY;
|
||||
}
|
||||
|
||||
err: (void)memp_fput(dbp->mpf, (PAGE *)meta, flags);
|
||||
(void)__BT_LPUT(dbp, metalock);
|
||||
}
|
|
@ -1,212 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Mike Olson.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)bt_compare.c 10.9 (Sleepycat) 5/6/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "btree.h"
|
||||
|
||||
/*
|
||||
* __bam_cmp --
|
||||
* Compare a key to a given record.
|
||||
*
|
||||
* PUBLIC: int __bam_cmp __P((DB *, const DBT *, EPG *));
|
||||
*/
|
||||
int
|
||||
__bam_cmp(dbp, k1, e)
|
||||
DB *dbp;
|
||||
const DBT *k1;
|
||||
EPG *e;
|
||||
{
|
||||
BINTERNAL *bi;
|
||||
BKEYDATA *bk;
|
||||
BOVERFLOW *bo;
|
||||
BTREE *t;
|
||||
DBT k2;
|
||||
PAGE *h;
|
||||
|
||||
t = dbp->internal;
|
||||
|
||||
/*
|
||||
* Returns:
|
||||
* < 0 if k1 is < record
|
||||
* = 0 if k1 is = record
|
||||
* > 0 if k1 is > record
|
||||
*
|
||||
* The left-most key on internal pages, at any level of the tree, is
|
||||
* guaranteed, by the following code, to be less than any user key.
|
||||
* This saves us from having to update the leftmost key on an internal
|
||||
* page when the user inserts a new key in the tree smaller than
|
||||
* anything we've yet seen.
|
||||
*/
|
||||
h = e->page;
|
||||
if (e->indx == 0 &&
|
||||
h->prev_pgno == PGNO_INVALID && TYPE(h) != P_LBTREE)
|
||||
return (1);
|
||||
|
||||
bo = NULL;
|
||||
if (TYPE(h) == P_LBTREE) {
|
||||
bk = GET_BKEYDATA(h, e->indx);
|
||||
if (B_TYPE(bk->type) == B_OVERFLOW)
|
||||
bo = (BOVERFLOW *)bk;
|
||||
else {
|
||||
k2.data = bk->data;
|
||||
k2.size = bk->len;
|
||||
}
|
||||
} else {
|
||||
bi = GET_BINTERNAL(h, e->indx);
|
||||
if (B_TYPE(bi->type) == B_OVERFLOW)
|
||||
bo = (BOVERFLOW *)(bi->data);
|
||||
else {
|
||||
k2.data = bi->data;
|
||||
k2.size = bi->len;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* We ignore system errors; the only recoverable one is ENOMEM, and we
|
||||
* don't want to require that comparison routines handle random errors.
|
||||
* We don't want to return a valid comparison, either, so we stop.
|
||||
*/
|
||||
if (bo != NULL) {
|
||||
/*
|
||||
* If using the default comparison routine, use __db_moff(),
|
||||
* which compares the overflow key a page at a time.
|
||||
*/
|
||||
if (t->bt_compare == __bam_defcmp)
|
||||
return (__db_moff(dbp, k1, bo->pgno));
|
||||
|
||||
/*
|
||||
* Otherwise, we need a contiguous record so we can hand it
|
||||
* to the user's routine.
|
||||
*/
|
||||
memset(&k2, 0, sizeof(k2));
|
||||
if (__db_goff(dbp, &k2, bo->tlen,
|
||||
bo->pgno, &t->bt_rdata.data, &t->bt_rdata.ulen) != 0) {
|
||||
(void)__db_panic(dbp);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Note, we have not cleared the k2 DBT in this path. This should
|
||||
* be okay, because the user's comparison routine had better not be
|
||||
* looking at any fields other than the data/size. We don't clear
|
||||
* it because we go through this path a lot and it's expensive.
|
||||
*/
|
||||
return ((*t->bt_compare)(k1, &k2));
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_defcmp --
|
||||
* Default comparison routine.
|
||||
*
|
||||
* PUBLIC: int __bam_defcmp __P((const DBT *, const DBT *));
|
||||
*/
|
||||
int
|
||||
__bam_defcmp(a, b)
|
||||
const DBT *a, *b;
|
||||
{
|
||||
size_t len;
|
||||
u_int8_t *p1, *p2;
|
||||
|
||||
/*
|
||||
* Returns:
|
||||
* < 0 if a is < b
|
||||
* = 0 if a is = b
|
||||
* > 0 if a is > b
|
||||
*
|
||||
* XXX
|
||||
* If a size_t doesn't fit into a long, or if the difference between
|
||||
* any two characters doesn't fit into an int, this routine can lose.
|
||||
* What we need is a signed integral type that's guaranteed to be at
|
||||
* least as large as a size_t, and there is no such thing.
|
||||
*/
|
||||
len = a->size > b->size ? b->size : a->size;
|
||||
for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2)
|
||||
if (*p1 != *p2)
|
||||
return ((long)*p1 - (long)*p2);
|
||||
return ((long)a->size - (long)b->size);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_defpfx --
|
||||
* Default prefix routine.
|
||||
*
|
||||
* PUBLIC: size_t __bam_defpfx __P((const DBT *, const DBT *));
|
||||
*/
|
||||
size_t
|
||||
__bam_defpfx(a, b)
|
||||
const DBT *a, *b;
|
||||
{
|
||||
size_t cnt, len;
|
||||
u_int8_t *p1, *p2;
|
||||
|
||||
cnt = 1;
|
||||
len = a->size > b->size ? b->size : a->size;
|
||||
for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt)
|
||||
if (*p1 != *p2)
|
||||
return (cnt);
|
||||
|
||||
/*
|
||||
* We know that a->size must be <= b->size, or they wouldn't be
|
||||
* in this order.
|
||||
*/
|
||||
return (a->size < b->size ? a->size + 1 : a->size);
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)bt_conv.c 10.6 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "db_swap.h"
|
||||
#include "btree.h"
|
||||
|
||||
/*
|
||||
* __bam_pgin --
|
||||
* Convert host-specific page layout from the host-independent format
|
||||
* stored on disk.
|
||||
*
|
||||
* PUBLIC: int __bam_pgin __P((db_pgno_t, void *, DBT *));
|
||||
*/
|
||||
int
|
||||
__bam_pgin(pg, pp, cookie)
|
||||
db_pgno_t pg;
|
||||
void *pp;
|
||||
DBT *cookie;
|
||||
{
|
||||
DB_PGINFO *pginfo;
|
||||
|
||||
pginfo = (DB_PGINFO *)cookie->data;
|
||||
if (!pginfo->needswap)
|
||||
return (0);
|
||||
return (pg == PGNO_METADATA ?
|
||||
__bam_mswap(pp) : __db_pgin(pg, pginfo->db_pagesize, pp));
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_pgout --
|
||||
* Convert host-specific page layout to the host-independent format
|
||||
* stored on disk.
|
||||
*
|
||||
* PUBLIC: int __bam_pgout __P((db_pgno_t, void *, DBT *));
|
||||
*/
|
||||
int
|
||||
__bam_pgout(pg, pp, cookie)
|
||||
db_pgno_t pg;
|
||||
void *pp;
|
||||
DBT *cookie;
|
||||
{
|
||||
DB_PGINFO *pginfo;
|
||||
|
||||
pginfo = (DB_PGINFO *)cookie->data;
|
||||
if (!pginfo->needswap)
|
||||
return (0);
|
||||
return (pg == PGNO_METADATA ?
|
||||
__bam_mswap(pp) : __db_pgout(pg, pginfo->db_pagesize, pp));
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_mswap --
|
||||
* Swap the bytes on the btree metadata page.
|
||||
*
|
||||
* PUBLIC: int __bam_mswap __P((PAGE *));
|
||||
*/
|
||||
int
|
||||
__bam_mswap(pg)
|
||||
PAGE *pg;
|
||||
{
|
||||
u_int8_t *p;
|
||||
|
||||
p = (u_int8_t *)pg;
|
||||
|
||||
/* Swap the meta-data information. */
|
||||
SWAP32(p); /* lsn.file */
|
||||
SWAP32(p); /* lsn.offset */
|
||||
SWAP32(p); /* pgno */
|
||||
SWAP32(p); /* magic */
|
||||
SWAP32(p); /* version */
|
||||
SWAP32(p); /* pagesize */
|
||||
SWAP32(p); /* maxkey */
|
||||
SWAP32(p); /* minkey */
|
||||
SWAP32(p); /* free */
|
||||
SWAP32(p); /* flags */
|
||||
|
||||
/* Swap the statistics. */
|
||||
p = (u_int8_t *)&((BTMETA *)pg)->stat;
|
||||
SWAP32(p); /* bt_freed */
|
||||
SWAP32(p); /* bt_pfxsaved */
|
||||
SWAP32(p); /* bt_split */
|
||||
SWAP32(p); /* bt_rootsplit */
|
||||
SWAP32(p); /* bt_fastsplit */
|
||||
SWAP32(p); /* bt_added */
|
||||
SWAP32(p); /* bt_deleted */
|
||||
SWAP32(p); /* bt_get */
|
||||
SWAP32(p); /* bt_cache_hit */
|
||||
SWAP32(p); /* bt_cache_miss */
|
||||
|
||||
return (0);
|
||||
}
|
1752
db/btree/bt_cursor.c
1752
db/btree/bt_cursor.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,647 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Mike Olson.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)bt_delete.c 10.31 (Sleepycat) 5/6/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "btree.h"
|
||||
|
||||
static int __bam_dpages __P((DB *, BTREE *));
|
||||
|
||||
/*
|
||||
* __bam_delete --
|
||||
* Delete the items referenced by a key.
|
||||
*
|
||||
* PUBLIC: int __bam_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__bam_delete(argdbp, txn, key, flags)
|
||||
DB *argdbp;
|
||||
DB_TXN *txn;
|
||||
DBT *key;
|
||||
u_int32_t flags;
|
||||
{
|
||||
BTREE *t;
|
||||
DB *dbp;
|
||||
PAGE *h;
|
||||
db_indx_t cnt, i, indx;
|
||||
int dpage, exact, ret, stack;
|
||||
|
||||
DEBUG_LWRITE(argdbp, txn, "bam_delete", key, NULL, flags);
|
||||
|
||||
stack = 0;
|
||||
|
||||
/* Check for invalid flags. */
|
||||
if ((ret = __db_delchk(argdbp,
|
||||
key, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0)
|
||||
return (ret);
|
||||
|
||||
GETHANDLE(argdbp, txn, &dbp, ret);
|
||||
t = dbp->internal;
|
||||
|
||||
/* Search the tree for the key; delete only deletes exact matches. */
|
||||
if ((ret = __bam_search(dbp, key, S_DELETE, 1, NULL, &exact)) != 0)
|
||||
goto err;
|
||||
stack = 1;
|
||||
h = t->bt_csp->page;
|
||||
indx = t->bt_csp->indx;
|
||||
|
||||
/* Delete the key/data pair, including any on-or-off page duplicates. */
|
||||
for (cnt = 1, i = indx;; ++cnt)
|
||||
if ((i += P_INDX) >= NUM_ENT(h) || h->inp[i] != h->inp[indx])
|
||||
break;
|
||||
for (; cnt > 0; --cnt, ++t->lstat.bt_deleted)
|
||||
if (__bam_ca_delete(dbp, h->pgno, indx, NULL, 1) == 0) {
|
||||
/*
|
||||
* XXX
|
||||
* Delete the key item first, otherwise the duplicate
|
||||
* checks in __bam_ditem() won't work!
|
||||
*/
|
||||
if ((ret = __bam_ditem(dbp, h, indx)) != 0)
|
||||
goto err;
|
||||
if ((ret = __bam_ditem(dbp, h, indx)) != 0)
|
||||
goto err;
|
||||
} else {
|
||||
B_DSET(GET_BKEYDATA(h, indx + O_INDX)->type);
|
||||
indx += P_INDX;
|
||||
}
|
||||
|
||||
/* If we're using record numbers, update internal page record counts. */
|
||||
if (F_ISSET(dbp, DB_BT_RECNUM) && (ret = __bam_adjust(dbp, t, -1)) != 0)
|
||||
goto err;
|
||||
|
||||
/* If the page is now empty, delete it. */
|
||||
dpage = NUM_ENT(h) == 0 && h->pgno != PGNO_ROOT;
|
||||
|
||||
__bam_stkrel(dbp);
|
||||
stack = 0;
|
||||
|
||||
ret = dpage ? __bam_dpage(dbp, key) : 0;
|
||||
|
||||
err: if (stack)
|
||||
__bam_stkrel(dbp);
|
||||
PUTHANDLE(dbp);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __ram_delete --
|
||||
* Delete the items referenced by a key.
|
||||
*
|
||||
* PUBLIC: int __ram_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__ram_delete(argdbp, txn, key, flags)
|
||||
DB *argdbp;
|
||||
DB_TXN *txn;
|
||||
DBT *key;
|
||||
u_int32_t flags;
|
||||
{
|
||||
BKEYDATA bk;
|
||||
BTREE *t;
|
||||
DB *dbp;
|
||||
DBT hdr, data;
|
||||
PAGE *h;
|
||||
db_indx_t indx;
|
||||
db_recno_t recno;
|
||||
int exact, ret, stack;
|
||||
|
||||
stack = 0;
|
||||
|
||||
/* Check for invalid flags. */
|
||||
if ((ret = __db_delchk(argdbp,
|
||||
key, flags, F_ISSET(argdbp, DB_AM_RDONLY))) != 0)
|
||||
return (ret);
|
||||
|
||||
GETHANDLE(argdbp, txn, &dbp, ret);
|
||||
t = dbp->internal;
|
||||
|
||||
/* Check the user's record number and fill in as necessary. */
|
||||
if ((ret = __ram_getno(argdbp, key, &recno, 0)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Search the tree for the key; delete only deletes exact matches. */
|
||||
if ((ret = __bam_rsearch(dbp, &recno, S_DELETE, 1, &exact)) != 0)
|
||||
goto err;
|
||||
if (!exact) {
|
||||
ret = DB_NOTFOUND;
|
||||
goto err;
|
||||
}
|
||||
|
||||
h = t->bt_csp->page;
|
||||
indx = t->bt_csp->indx;
|
||||
stack = 1;
|
||||
|
||||
/* If the record has already been deleted, we couldn't have found it. */
|
||||
if (B_DISSET(GET_BKEYDATA(h, indx)->type)) {
|
||||
ret = DB_KEYEMPTY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're not renumbering records, replace the record with a marker
|
||||
* and return.
|
||||
*/
|
||||
if (!F_ISSET(dbp, DB_RE_RENUMBER)) {
|
||||
if ((ret = __bam_ditem(dbp, h, indx)) != 0)
|
||||
goto err;
|
||||
|
||||
B_TSET(bk.type, B_KEYDATA, 1);
|
||||
bk.len = 0;
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.data = &bk;
|
||||
hdr.size = SSZA(BKEYDATA, data);
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.data = (char *)"";
|
||||
data.size = 0;
|
||||
if ((ret = __db_pitem(dbp,
|
||||
h, indx, BKEYDATA_SIZE(0), &hdr, &data)) != 0)
|
||||
goto err;
|
||||
|
||||
++t->lstat.bt_deleted;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Delete the item. */
|
||||
if ((ret = __bam_ditem(dbp, h, indx)) != 0)
|
||||
goto err;
|
||||
|
||||
++t->lstat.bt_deleted;
|
||||
if (t->bt_recno != NULL)
|
||||
F_SET(t->bt_recno, RECNO_MODIFIED);
|
||||
|
||||
/* Adjust the counts. */
|
||||
__bam_adjust(dbp, t, -1);
|
||||
|
||||
/* Adjust the cursors. */
|
||||
__ram_ca(dbp, recno, CA_DELETE);
|
||||
|
||||
/*
|
||||
* If the page is now empty, delete it -- we have the whole tree
|
||||
* locked, so there are no preparations to make. Else, release
|
||||
* the pages.
|
||||
*/
|
||||
if (NUM_ENT(h) == 0 && h->pgno != PGNO_ROOT) {
|
||||
stack = 0;
|
||||
ret = __bam_dpages(dbp, t);
|
||||
}
|
||||
|
||||
done:
|
||||
err: if (stack)
|
||||
__bam_stkrel(dbp);
|
||||
|
||||
PUTHANDLE(dbp);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_ditem --
|
||||
* Delete one or more entries from a page.
|
||||
*
|
||||
* PUBLIC: int __bam_ditem __P((DB *, PAGE *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__bam_ditem(dbp, h, indx)
|
||||
DB *dbp;
|
||||
PAGE *h;
|
||||
u_int32_t indx;
|
||||
{
|
||||
BINTERNAL *bi;
|
||||
BKEYDATA *bk;
|
||||
BOVERFLOW *bo;
|
||||
u_int32_t nbytes;
|
||||
int ret;
|
||||
|
||||
switch (TYPE(h)) {
|
||||
case P_IBTREE:
|
||||
bi = GET_BINTERNAL(h, indx);
|
||||
switch (B_TYPE(bi->type)) {
|
||||
case B_DUPLICATE:
|
||||
case B_OVERFLOW:
|
||||
nbytes = BINTERNAL_SIZE(bi->len);
|
||||
bo = (BOVERFLOW *)bi->data;
|
||||
goto offpage;
|
||||
case B_KEYDATA:
|
||||
nbytes = BINTERNAL_SIZE(bi->len);
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbp, h->pgno));
|
||||
}
|
||||
break;
|
||||
case P_IRECNO:
|
||||
nbytes = RINTERNAL_SIZE;
|
||||
break;
|
||||
case P_LBTREE:
|
||||
/*
|
||||
* If it's a duplicate key, discard the index and don't touch
|
||||
* the actual page item.
|
||||
*
|
||||
* XXX
|
||||
* This works because no data item can have an index matching
|
||||
* any other index so even if the data item is in a key "slot",
|
||||
* it won't match any other index.
|
||||
*/
|
||||
if ((indx % 2) == 0) {
|
||||
/*
|
||||
* Check for a duplicate after us on the page. NOTE:
|
||||
* we have to delete the key item before deleting the
|
||||
* data item, otherwise the "indx + P_INDX" calculation
|
||||
* won't work!
|
||||
*/
|
||||
if (indx + P_INDX < (u_int32_t)NUM_ENT(h) &&
|
||||
h->inp[indx] == h->inp[indx + P_INDX])
|
||||
return (__bam_adjindx(dbp,
|
||||
h, indx, indx + O_INDX, 0));
|
||||
/*
|
||||
* Check for a duplicate before us on the page. It
|
||||
* doesn't matter if we delete the key item before or
|
||||
* after the data item for the purposes of this one.
|
||||
*/
|
||||
if (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX])
|
||||
return (__bam_adjindx(dbp,
|
||||
h, indx, indx - P_INDX, 0));
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case P_LRECNO:
|
||||
bk = GET_BKEYDATA(h, indx);
|
||||
switch (B_TYPE(bk->type)) {
|
||||
case B_DUPLICATE:
|
||||
case B_OVERFLOW:
|
||||
nbytes = BOVERFLOW_SIZE;
|
||||
bo = GET_BOVERFLOW(h, indx);
|
||||
|
||||
offpage: /* Delete duplicate/offpage chains. */
|
||||
if (B_TYPE(bo->type) == B_DUPLICATE) {
|
||||
if ((ret =
|
||||
__db_ddup(dbp, bo->pgno, __bam_free)) != 0)
|
||||
return (ret);
|
||||
} else
|
||||
if ((ret =
|
||||
__db_doff(dbp, bo->pgno, __bam_free)) != 0)
|
||||
return (ret);
|
||||
break;
|
||||
case B_KEYDATA:
|
||||
nbytes = BKEYDATA_SIZE(bk->len);
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbp, h->pgno));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbp, h->pgno));
|
||||
}
|
||||
|
||||
/* Delete the item. */
|
||||
if ((ret = __db_ditem(dbp, h, indx, nbytes)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Mark the page dirty. */
|
||||
return (memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY));
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_adjindx --
|
||||
* Adjust an index on the page.
|
||||
*
|
||||
* PUBLIC: int __bam_adjindx __P((DB *, PAGE *, u_int32_t, u_int32_t, int));
|
||||
*/
|
||||
int
|
||||
__bam_adjindx(dbp, h, indx, indx_copy, is_insert)
|
||||
DB *dbp;
|
||||
PAGE *h;
|
||||
u_int32_t indx, indx_copy;
|
||||
int is_insert;
|
||||
{
|
||||
db_indx_t copy;
|
||||
int ret;
|
||||
|
||||
/* Log the change. */
|
||||
if (DB_LOGGING(dbp) &&
|
||||
(ret = __bam_adj_log(dbp->dbenv->lg_info, dbp->txn, &LSN(h),
|
||||
0, dbp->log_fileid, PGNO(h), &LSN(h), indx, indx_copy,
|
||||
(u_int32_t)is_insert)) != 0)
|
||||
return (ret);
|
||||
|
||||
if (is_insert) {
|
||||
copy = h->inp[indx_copy];
|
||||
if (indx != NUM_ENT(h))
|
||||
memmove(&h->inp[indx + O_INDX], &h->inp[indx],
|
||||
sizeof(db_indx_t) * (NUM_ENT(h) - indx));
|
||||
h->inp[indx] = copy;
|
||||
++NUM_ENT(h);
|
||||
} else {
|
||||
--NUM_ENT(h);
|
||||
if (indx != NUM_ENT(h))
|
||||
memmove(&h->inp[indx], &h->inp[indx + O_INDX],
|
||||
sizeof(db_indx_t) * (NUM_ENT(h) - indx));
|
||||
}
|
||||
|
||||
/* Mark the page dirty. */
|
||||
ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY);
|
||||
|
||||
/* Adjust the cursors. */
|
||||
__bam_ca_di(dbp, h->pgno, indx, is_insert ? 1 : -1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_dpage --
|
||||
* Delete a page from the tree.
|
||||
*
|
||||
* PUBLIC: int __bam_dpage __P((DB *, const DBT *));
|
||||
*/
|
||||
int
|
||||
__bam_dpage(dbp, key)
|
||||
DB *dbp;
|
||||
const DBT *key;
|
||||
{
|
||||
BTREE *t;
|
||||
DB_LOCK lock;
|
||||
PAGE *h;
|
||||
db_pgno_t pgno;
|
||||
int level; /* !!!: has to hold number of tree levels. */
|
||||
int exact, ret;
|
||||
|
||||
ret = 0;
|
||||
t = dbp->internal;
|
||||
|
||||
/*
|
||||
* The locking protocol is that we acquire locks by walking down the
|
||||
* tree, to avoid the obvious deadlocks.
|
||||
*
|
||||
* Call __bam_search to reacquire the empty leaf page, but this time
|
||||
* get both the leaf page and it's parent, locked. Walk back up the
|
||||
* tree, until we have the top pair of pages that we want to delete.
|
||||
* Once we have the top page that we want to delete locked, lock the
|
||||
* underlying pages and check to make sure they're still empty. If
|
||||
* they are, delete them.
|
||||
*/
|
||||
for (level = LEAFLEVEL;; ++level) {
|
||||
/* Acquire a page and its parent, locked. */
|
||||
if ((ret =
|
||||
__bam_search(dbp, key, S_WRPAIR, level, NULL, &exact)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* If we reach the root or the page isn't going to be empty
|
||||
* when we delete one record, quit.
|
||||
*/
|
||||
h = t->bt_csp[-1].page;
|
||||
if (h->pgno == PGNO_ROOT || NUM_ENT(h) != 1)
|
||||
break;
|
||||
|
||||
/* Release the two locked pages. */
|
||||
(void)memp_fput(dbp->mpf, t->bt_csp[-1].page, 0);
|
||||
(void)__BT_TLPUT(dbp, t->bt_csp[-1].lock);
|
||||
(void)memp_fput(dbp->mpf, t->bt_csp[0].page, 0);
|
||||
(void)__BT_TLPUT(dbp, t->bt_csp[0].lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Leave the stack pointer one after the last entry, we may be about
|
||||
* to push more items on the stack.
|
||||
*/
|
||||
++t->bt_csp;
|
||||
|
||||
/*
|
||||
* t->bt_csp[-2].page is the top page, which we're not going to delete,
|
||||
* and t->bt_csp[-1].page is the first page we are going to delete.
|
||||
*
|
||||
* Walk down the chain, acquiring the rest of the pages until we've
|
||||
* retrieved the leaf page. If we find any pages that aren't going
|
||||
* to be emptied by the delete, someone else added something while we
|
||||
* were walking the tree, and we discontinue the delete.
|
||||
*/
|
||||
for (h = t->bt_csp[-1].page;;) {
|
||||
if (ISLEAF(h)) {
|
||||
if (NUM_ENT(h) != 0)
|
||||
goto release;
|
||||
break;
|
||||
} else
|
||||
if (NUM_ENT(h) != 1)
|
||||
goto release;
|
||||
|
||||
/*
|
||||
* Get the next page, write lock it and push it onto the stack.
|
||||
* We know it's index 0, because it can only have one element.
|
||||
*/
|
||||
pgno = TYPE(h) == P_IBTREE ?
|
||||
GET_BINTERNAL(h, 0)->pgno : GET_RINTERNAL(h, 0)->pgno;
|
||||
|
||||
if ((ret = __bam_lget(dbp, 0, pgno, DB_LOCK_WRITE, &lock)) != 0)
|
||||
goto release;
|
||||
if ((ret = __bam_pget(dbp, &h, &pgno, 0)) != 0)
|
||||
goto release;
|
||||
BT_STK_PUSH(t, h, 0, lock, ret);
|
||||
if (ret != 0)
|
||||
goto release;
|
||||
}
|
||||
|
||||
BT_STK_POP(t);
|
||||
return (__bam_dpages(dbp, t));
|
||||
|
||||
release:
|
||||
/* Discard any locked pages and return. */
|
||||
BT_STK_POP(t);
|
||||
__bam_stkrel(dbp);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_dpages --
|
||||
* Delete a set of locked pages.
|
||||
*/
|
||||
static int
|
||||
__bam_dpages(dbp, t)
|
||||
DB *dbp;
|
||||
BTREE *t;
|
||||
{
|
||||
DBT a, b;
|
||||
DB_LOCK lock;
|
||||
EPG *epg;
|
||||
PAGE *h;
|
||||
db_pgno_t pgno;
|
||||
db_recno_t rcnt;
|
||||
int ret;
|
||||
|
||||
COMPQUIET(rcnt, 0);
|
||||
|
||||
epg = t->bt_sp;
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* There is an interesting deadlock situation here. We have to relink
|
||||
* the leaf page chain around the leaf page being deleted. Consider
|
||||
* a cursor walking through the leaf pages, that has the previous page
|
||||
* read-locked and is waiting on a lock for the page we're deleting.
|
||||
* It will deadlock here. This is a problem, because if our process is
|
||||
* selected to resolve the deadlock, we'll leave an empty leaf page
|
||||
* that we can never again access by walking down the tree. So, before
|
||||
* we unlink the subtree, we relink the leaf page chain.
|
||||
*/
|
||||
if ((ret = __db_relink(dbp, t->bt_csp->page, NULL, 1)) != 0)
|
||||
goto release;
|
||||
|
||||
/*
|
||||
* We have the entire stack of deletable pages locked. Start from the
|
||||
* top of the tree and move to the bottom, as it's better to release
|
||||
* the inner pages as soon as possible.
|
||||
*/
|
||||
if ((ret = __bam_ditem(dbp, epg->page, epg->indx)) != 0)
|
||||
goto release;
|
||||
|
||||
/*
|
||||
* If we just deleted the last or next-to-last item from the root page,
|
||||
* the tree can collapse a level. Write lock the last page referenced
|
||||
* by the root page and copy it over the root page. If we can't get a
|
||||
* write lock, that's okay, the tree just remains a level deeper than
|
||||
* we'd like.
|
||||
*/
|
||||
h = epg->page;
|
||||
if (h->pgno == PGNO_ROOT && NUM_ENT(h) <= 1) {
|
||||
pgno = TYPE(epg->page) == P_IBTREE ?
|
||||
GET_BINTERNAL(epg->page, 0)->pgno :
|
||||
GET_RINTERNAL(epg->page, 0)->pgno;
|
||||
if ((ret = __bam_lget(dbp, 0, pgno, DB_LOCK_WRITE, &lock)) != 0)
|
||||
goto release;
|
||||
if ((ret = __bam_pget(dbp, &h, &pgno, 0)) != 0)
|
||||
goto release;
|
||||
|
||||
/* Log the change. */
|
||||
if (DB_LOGGING(dbp)) {
|
||||
memset(&a, 0, sizeof(a));
|
||||
a.data = h;
|
||||
a.size = dbp->pgsize;
|
||||
memset(&b, 0, sizeof(b));
|
||||
b.data = P_ENTRY(epg->page, 0);
|
||||
b.size = BINTERNAL_SIZE(((BINTERNAL *)b.data)->len);
|
||||
__bam_rsplit_log(dbp->dbenv->lg_info, dbp->txn,
|
||||
&h->lsn, 0, dbp->log_fileid, h->pgno, &a,
|
||||
RE_NREC(epg->page), &b, &epg->page->lsn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the switch.
|
||||
*
|
||||
* One fixup -- if the tree has record numbers and we're not
|
||||
* converting to a leaf page, we have to preserve the total
|
||||
* record count.
|
||||
*/
|
||||
if (TYPE(h) == P_IRECNO ||
|
||||
(TYPE(h) == P_IBTREE && F_ISSET(dbp, DB_BT_RECNUM)))
|
||||
rcnt = RE_NREC(epg->page);
|
||||
memcpy(epg->page, h, dbp->pgsize);
|
||||
epg->page->pgno = PGNO_ROOT;
|
||||
if (TYPE(h) == P_IRECNO ||
|
||||
(TYPE(h) == P_IBTREE && F_ISSET(dbp, DB_BT_RECNUM)))
|
||||
RE_NREC_SET(epg->page, rcnt);
|
||||
(void)memp_fset(dbp->mpf, epg->page, DB_MPOOL_DIRTY);
|
||||
|
||||
/*
|
||||
* Free the page copied onto the root page and discard its
|
||||
* lock. (The call to __bam_free() discards our reference
|
||||
* to the page.)
|
||||
*
|
||||
* It's possible that the reverse split we're doing involves
|
||||
* pages from the stack of pages we're deleting. Don't free
|
||||
* the page twice.
|
||||
*/
|
||||
if (h->pgno == (epg + 1)->page->pgno)
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
else {
|
||||
(void)__bam_free(dbp, h);
|
||||
++t->lstat.bt_freed;
|
||||
}
|
||||
(void)__BT_TLPUT(dbp, lock);
|
||||
|
||||
/* Adjust the cursors. */
|
||||
__bam_ca_move(dbp, h->pgno, PGNO_ROOT);
|
||||
}
|
||||
|
||||
/* Release the top page in the subtree. */
|
||||
(void)memp_fput(dbp->mpf, epg->page, 0);
|
||||
(void)__BT_TLPUT(dbp, epg->lock);
|
||||
|
||||
/*
|
||||
* Free the rest of the pages.
|
||||
*
|
||||
* XXX
|
||||
* Don't bother checking for errors. We've unlinked the subtree from
|
||||
* the tree, and there's no possibility of recovery.
|
||||
*/
|
||||
while (++epg <= t->bt_csp) {
|
||||
/*
|
||||
* XXX
|
||||
* Why do we need to do this? Isn't the page already empty?
|
||||
*/
|
||||
if (NUM_ENT(epg->page) != 0)
|
||||
(void)__bam_ditem(dbp, epg->page, epg->indx);
|
||||
|
||||
(void)__bam_free(dbp, epg->page);
|
||||
(void)__BT_TLPUT(dbp, epg->lock);
|
||||
++t->lstat.bt_freed;
|
||||
}
|
||||
return (0);
|
||||
|
||||
release:
|
||||
/* Discard any remaining pages and return. */
|
||||
for (; epg <= t->bt_csp; ++epg) {
|
||||
(void)memp_fput(dbp->mpf, epg->page, 0);
|
||||
(void)__BT_TLPUT(dbp, epg->lock);
|
||||
}
|
||||
return (ret);
|
||||
}
|
|
@ -1,348 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Mike Olson.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)bt_open.c 10.27 (Sleepycat) 5/6/98";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Implementation of btree access method for 4.4BSD.
|
||||
*
|
||||
* The design here was originally based on that of the btree access method
|
||||
* used in the Postgres database system at UC Berkeley. This implementation
|
||||
* is wholly independent of the Postgres code.
|
||||
*/
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "btree.h"
|
||||
|
||||
static int __bam_keyalloc __P((BTREE *));
|
||||
static int __bam_setmeta __P((DB *, BTREE *));
|
||||
|
||||
/*
|
||||
* __bam_open --
|
||||
* Open a btree.
|
||||
*
|
||||
* PUBLIC: int __bam_open __P((DB *, DBTYPE, DB_INFO *));
|
||||
*/
|
||||
int
|
||||
__bam_open(dbp, type, dbinfo)
|
||||
DB *dbp;
|
||||
DBTYPE type;
|
||||
DB_INFO *dbinfo;
|
||||
{
|
||||
BTREE *t;
|
||||
int ret;
|
||||
|
||||
/* Allocate the btree internal structure. */
|
||||
if ((t = (BTREE *)__db_calloc(1, sizeof(BTREE))) == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
t->bt_sp = t->bt_csp = t->bt_stack;
|
||||
t->bt_esp = t->bt_stack + sizeof(t->bt_stack) / sizeof(t->bt_stack[0]);
|
||||
|
||||
if ((type == DB_RECNO || F_ISSET(dbp, DB_BT_RECNUM)) &&
|
||||
(ret = __bam_keyalloc(t)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Intention is to make sure all of the user's selections are okay
|
||||
* here and then use them without checking.
|
||||
*/
|
||||
if (dbinfo != NULL) {
|
||||
/* Minimum number of keys per page. */
|
||||
if (dbinfo->bt_minkey == 0)
|
||||
t->bt_minkey = DEFMINKEYPAGE;
|
||||
else {
|
||||
if (dbinfo->bt_minkey < 2)
|
||||
goto einval;
|
||||
t->bt_minkey = dbinfo->bt_minkey;
|
||||
}
|
||||
|
||||
/* Maximum number of keys per page. */
|
||||
if (dbinfo->bt_maxkey == 0)
|
||||
t->bt_maxkey = 0;
|
||||
else {
|
||||
if (dbinfo->bt_maxkey < 1)
|
||||
goto einval;
|
||||
t->bt_maxkey = dbinfo->bt_maxkey;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no comparison, use default comparison. If no comparison
|
||||
* and no prefix, use default prefix. (We can't default the
|
||||
* prefix if the user supplies a comparison routine; shortening
|
||||
* the keys may break their comparison algorithm.)
|
||||
*/
|
||||
t->bt_compare = dbinfo->bt_compare == NULL ?
|
||||
__bam_defcmp : dbinfo->bt_compare;
|
||||
t->bt_prefix = dbinfo->bt_prefix == NULL ?
|
||||
(dbinfo->bt_compare == NULL ?
|
||||
__bam_defpfx : NULL) : dbinfo->bt_prefix;
|
||||
} else {
|
||||
t->bt_minkey = DEFMINKEYPAGE;
|
||||
t->bt_compare = __bam_defcmp;
|
||||
t->bt_prefix = __bam_defpfx;
|
||||
}
|
||||
|
||||
/* Initialize the remaining fields of the DB. */
|
||||
dbp->type = type;
|
||||
dbp->internal = t;
|
||||
dbp->cursor = __bam_cursor;
|
||||
dbp->del = __bam_delete;
|
||||
dbp->get = __bam_get;
|
||||
dbp->put = __bam_put;
|
||||
dbp->stat = __bam_stat;
|
||||
dbp->sync = __bam_sync;
|
||||
|
||||
/*
|
||||
* The btree data structure requires that at least two key/data pairs
|
||||
* can fit on a page, but other than that there's no fixed requirement.
|
||||
* Translate the minimum number of items into the bytes a key/data pair
|
||||
* can use before being placed on an overflow page. We calculate for
|
||||
* the worst possible alignment by assuming every item requires the
|
||||
* maximum alignment for padding.
|
||||
*
|
||||
* Recno uses the btree bt_ovflsize value -- it's close enough.
|
||||
*/
|
||||
t->bt_ovflsize = (dbp->pgsize - P_OVERHEAD) / (t->bt_minkey * P_INDX)
|
||||
- (BKEYDATA_PSIZE(0) + ALIGN(1, 4));
|
||||
|
||||
/* Create a root page if new tree. */
|
||||
if ((ret = __bam_setmeta(dbp, t)) != 0)
|
||||
goto err;
|
||||
|
||||
return (0);
|
||||
|
||||
einval: ret = EINVAL;
|
||||
|
||||
err: if (t != NULL) {
|
||||
/* If we allocated room for key/data return, discard it. */
|
||||
if (t->bt_rkey.data != NULL)
|
||||
__db_free(t->bt_rkey.data);
|
||||
|
||||
FREE(t, sizeof(BTREE));
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_bdup --
|
||||
* Create a BTREE handle for a threaded DB handle.
|
||||
*
|
||||
* PUBLIC: int __bam_bdup __P((DB *, DB *));
|
||||
*/
|
||||
int
|
||||
__bam_bdup(orig, new)
|
||||
DB *orig, *new;
|
||||
{
|
||||
BTREE *t, *ot;
|
||||
int ret;
|
||||
|
||||
ot = orig->internal;
|
||||
|
||||
if ((t = (BTREE *)__db_calloc(1, sizeof(*t))) == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* Ignore the cursor queue, only the first DB has attached cursors.
|
||||
*/
|
||||
|
||||
t->bt_sp = t->bt_csp = t->bt_stack;
|
||||
t->bt_esp = t->bt_stack + sizeof(t->bt_stack) / sizeof(t->bt_stack[0]);
|
||||
|
||||
if ((orig->type == DB_RECNO || F_ISSET(orig, DB_BT_RECNUM)) &&
|
||||
(ret = __bam_keyalloc(t)) != 0) {
|
||||
FREE(t, sizeof(*t));
|
||||
return (ret);
|
||||
}
|
||||
|
||||
t->bt_maxkey = ot->bt_maxkey;
|
||||
t->bt_minkey = ot->bt_minkey;
|
||||
t->bt_compare = ot->bt_compare;
|
||||
t->bt_prefix = ot->bt_prefix;
|
||||
t->bt_ovflsize = ot->bt_ovflsize;
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* The entire RECNO structure is shared. If it breaks, the application
|
||||
* was misusing it to start with.
|
||||
*/
|
||||
t->bt_recno = ot->bt_recno;
|
||||
|
||||
new->internal = t;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_keyalloc --
|
||||
* Allocate return memory for recno keys.
|
||||
*/
|
||||
static int
|
||||
__bam_keyalloc(t)
|
||||
BTREE *t;
|
||||
{
|
||||
/*
|
||||
* Recno keys are always the same size, and we don't want to have
|
||||
* to check for space on each return. Allocate it now.
|
||||
*/
|
||||
if ((t->bt_rkey.data = (void *)__db_malloc(sizeof(db_recno_t))) == NULL)
|
||||
return (ENOMEM);
|
||||
t->bt_rkey.ulen = sizeof(db_recno_t);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_setmeta --
|
||||
* Check (and optionally create) a tree.
|
||||
*/
|
||||
static int
|
||||
__bam_setmeta(dbp, t)
|
||||
DB *dbp;
|
||||
BTREE *t;
|
||||
{
|
||||
BTMETA *meta;
|
||||
PAGE *root;
|
||||
DB_LOCK metalock, rootlock;
|
||||
db_pgno_t pgno;
|
||||
int ret;
|
||||
|
||||
/* Get, and optionally create the metadata page. */
|
||||
pgno = PGNO_METADATA;
|
||||
if ((ret =
|
||||
__bam_lget(dbp, 0, PGNO_METADATA, DB_LOCK_WRITE, &metalock)) != 0)
|
||||
return (ret);
|
||||
if ((ret =
|
||||
__bam_pget(dbp, (PAGE **)&meta, &pgno, DB_MPOOL_CREATE)) != 0) {
|
||||
(void)__BT_LPUT(dbp, metalock);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the magic number is correct, we're not creating the tree.
|
||||
* Correct any fields that may not be right. Note, all of the
|
||||
* local flags were set by db_open(3).
|
||||
*/
|
||||
if (meta->magic != 0) {
|
||||
t->bt_maxkey = meta->maxkey;
|
||||
t->bt_minkey = meta->minkey;
|
||||
|
||||
(void)memp_fput(dbp->mpf, (PAGE *)meta, 0);
|
||||
(void)__BT_LPUT(dbp, metalock);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Initialize the tree structure metadata information. */
|
||||
memset(meta, 0, sizeof(BTMETA));
|
||||
ZERO_LSN(meta->lsn);
|
||||
meta->pgno = PGNO_METADATA;
|
||||
meta->magic = DB_BTREEMAGIC;
|
||||
meta->version = DB_BTREEVERSION;
|
||||
meta->pagesize = dbp->pgsize;
|
||||
meta->maxkey = t->bt_maxkey;
|
||||
meta->minkey = t->bt_minkey;
|
||||
meta->free = PGNO_INVALID;
|
||||
if (dbp->type == DB_RECNO)
|
||||
F_SET(meta, BTM_RECNO);
|
||||
if (F_ISSET(dbp, DB_AM_DUP))
|
||||
F_SET(meta, BTM_DUP);
|
||||
if (F_ISSET(dbp, DB_RE_FIXEDLEN))
|
||||
F_SET(meta, BTM_FIXEDLEN);
|
||||
if (F_ISSET(dbp, DB_BT_RECNUM))
|
||||
F_SET(meta, BTM_RECNUM);
|
||||
if (F_ISSET(dbp, DB_RE_RENUMBER))
|
||||
F_SET(meta, BTM_RENUMBER);
|
||||
memcpy(meta->uid, dbp->lock.fileid, DB_FILE_ID_LEN);
|
||||
|
||||
/* Create and initialize a root page. */
|
||||
pgno = PGNO_ROOT;
|
||||
if ((ret =
|
||||
__bam_lget(dbp, 0, PGNO_ROOT, DB_LOCK_WRITE, &rootlock)) != 0)
|
||||
return (ret);
|
||||
if ((ret = __bam_pget(dbp, &root, &pgno, DB_MPOOL_CREATE)) != 0) {
|
||||
(void)__BT_LPUT(dbp, rootlock);
|
||||
return (ret);
|
||||
}
|
||||
P_INIT(root, dbp->pgsize, PGNO_ROOT, PGNO_INVALID,
|
||||
PGNO_INVALID, 1, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE);
|
||||
ZERO_LSN(root->lsn);
|
||||
|
||||
/* Release the metadata and root pages. */
|
||||
if ((ret = memp_fput(dbp->mpf, (PAGE *)meta, DB_MPOOL_DIRTY)) != 0)
|
||||
return (ret);
|
||||
if ((ret = memp_fput(dbp->mpf, root, DB_MPOOL_DIRTY)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* Flush the metadata and root pages to disk -- since the user can't
|
||||
* transaction protect open, the pages have to exist during recovery.
|
||||
*
|
||||
* XXX
|
||||
* It's not useful to return not-yet-flushed here -- convert it to
|
||||
* an error.
|
||||
*/
|
||||
if ((ret = memp_fsync(dbp->mpf)) == DB_INCOMPLETE)
|
||||
ret = EINVAL;
|
||||
|
||||
/* Release the locks. */
|
||||
(void)__BT_LPUT(dbp, metalock);
|
||||
(void)__BT_LPUT(dbp, rootlock);
|
||||
|
||||
return (ret);
|
||||
}
|
|
@ -1,316 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Mike Olson.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)bt_page.c 10.12 (Sleepycat) 5/6/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "btree.h"
|
||||
|
||||
/*
|
||||
* __bam_new --
|
||||
* Get a new page, preferably from the freelist.
|
||||
*
|
||||
* PUBLIC: int __bam_new __P((DB *, u_int32_t, PAGE **));
|
||||
*/
|
||||
int
|
||||
__bam_new(dbp, type, pagepp)
|
||||
DB *dbp;
|
||||
u_int32_t type;
|
||||
PAGE **pagepp;
|
||||
{
|
||||
BTMETA *meta;
|
||||
DB_LOCK metalock;
|
||||
PAGE *h;
|
||||
db_pgno_t pgno;
|
||||
int ret;
|
||||
|
||||
meta = NULL;
|
||||
h = NULL;
|
||||
metalock = LOCK_INVALID;
|
||||
|
||||
pgno = PGNO_METADATA;
|
||||
if ((ret = __bam_lget(dbp, 0, pgno, DB_LOCK_WRITE, &metalock)) != 0)
|
||||
goto err;
|
||||
if ((ret = __bam_pget(dbp, (PAGE **)&meta, &pgno, 0)) != 0)
|
||||
goto err;
|
||||
|
||||
if (meta->free == PGNO_INVALID) {
|
||||
if ((ret = __bam_pget(dbp, &h, &pgno, DB_MPOOL_NEW)) != 0)
|
||||
goto err;
|
||||
ZERO_LSN(h->lsn);
|
||||
h->pgno = pgno;
|
||||
} else {
|
||||
pgno = meta->free;
|
||||
if ((ret = __bam_pget(dbp, &h, &pgno, 0)) != 0)
|
||||
goto err;
|
||||
meta->free = h->next_pgno;
|
||||
}
|
||||
|
||||
/* Log the change. */
|
||||
if (DB_LOGGING(dbp)) {
|
||||
if ((ret = __bam_pg_alloc_log(dbp->dbenv->lg_info, dbp->txn,
|
||||
&meta->lsn, 0, dbp->log_fileid, &meta->lsn, &h->lsn,
|
||||
h->pgno, (u_int32_t)type, meta->free)) != 0)
|
||||
goto err;
|
||||
LSN(h) = LSN(meta);
|
||||
}
|
||||
|
||||
(void)memp_fput(dbp->mpf, (PAGE *)meta, DB_MPOOL_DIRTY);
|
||||
(void)__BT_TLPUT(dbp, metalock);
|
||||
|
||||
P_INIT(h, dbp->pgsize, h->pgno, PGNO_INVALID, PGNO_INVALID, 0, type);
|
||||
*pagepp = h;
|
||||
return (0);
|
||||
|
||||
err: if (h != NULL)
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
if (meta != NULL)
|
||||
(void)memp_fput(dbp->mpf, meta, 0);
|
||||
if (metalock != LOCK_INVALID)
|
||||
(void)__BT_TLPUT(dbp, metalock);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_free --
|
||||
* Add a page to the head of the freelist.
|
||||
*
|
||||
* PUBLIC: int __bam_free __P((DB *, PAGE *));
|
||||
*/
|
||||
int
|
||||
__bam_free(dbp, h)
|
||||
DB *dbp;
|
||||
PAGE *h;
|
||||
{
|
||||
BTMETA *meta;
|
||||
DBT ldbt;
|
||||
DB_LOCK metalock;
|
||||
db_pgno_t pgno;
|
||||
u_int32_t dirty_flag;
|
||||
int ret, t_ret;
|
||||
|
||||
/*
|
||||
* Retrieve the metadata page and insert the page at the head of
|
||||
* the free list. If either the lock get or page get routines
|
||||
* fail, then we need to put the page with which we were called
|
||||
* back because our caller assumes we take care of it.
|
||||
*/
|
||||
dirty_flag = 0;
|
||||
pgno = PGNO_METADATA;
|
||||
if ((ret = __bam_lget(dbp, 0, pgno, DB_LOCK_WRITE, &metalock)) != 0)
|
||||
goto err;
|
||||
if ((ret = __bam_pget(dbp, (PAGE **)&meta, &pgno, 0)) != 0) {
|
||||
(void)__BT_TLPUT(dbp, metalock);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Log the change. */
|
||||
if (DB_LOGGING(dbp)) {
|
||||
memset(&ldbt, 0, sizeof(ldbt));
|
||||
ldbt.data = h;
|
||||
ldbt.size = P_OVERHEAD;
|
||||
if ((ret = __bam_pg_free_log(dbp->dbenv->lg_info,
|
||||
dbp->txn, &meta->lsn, 0, dbp->log_fileid, h->pgno,
|
||||
&meta->lsn, &ldbt, meta->free)) != 0) {
|
||||
(void)memp_fput(dbp->mpf, (PAGE *)meta, 0);
|
||||
(void)__BT_TLPUT(dbp, metalock);
|
||||
return (ret);
|
||||
}
|
||||
LSN(h) = LSN(meta);
|
||||
}
|
||||
|
||||
/*
|
||||
* The page should have nothing interesting on it, re-initialize it,
|
||||
* leaving only the page number and the LSN.
|
||||
*/
|
||||
#ifdef DIAGNOSTIC
|
||||
{ db_pgno_t __pgno; DB_LSN __lsn;
|
||||
__pgno = h->pgno;
|
||||
__lsn = h->lsn;
|
||||
memset(h, 0xff, dbp->pgsize);
|
||||
h->pgno = __pgno;
|
||||
h->lsn = __lsn;
|
||||
}
|
||||
#endif
|
||||
P_INIT(h, dbp->pgsize, h->pgno, PGNO_INVALID, meta->free, 0, P_INVALID);
|
||||
|
||||
/* Link the page on the metadata free list. */
|
||||
meta->free = h->pgno;
|
||||
|
||||
/* Discard the metadata page. */
|
||||
ret = memp_fput(dbp->mpf, (PAGE *)meta, DB_MPOOL_DIRTY);
|
||||
if ((t_ret = __BT_TLPUT(dbp, metalock)) != 0)
|
||||
ret = t_ret;
|
||||
|
||||
/* Discard the caller's page reference. */
|
||||
dirty_flag = DB_MPOOL_DIRTY;
|
||||
err: if ((t_ret = memp_fput(dbp->mpf, h, dirty_flag)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* We have to unlock the caller's page in the caller!
|
||||
*/
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* __bam_lt --
|
||||
* Print out the list of currently held locks.
|
||||
*
|
||||
* PUBLIC: int __bam_lt __P((DB *));
|
||||
*/
|
||||
int
|
||||
__bam_lt(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
DB_LOCKREQ req;
|
||||
|
||||
if (F_ISSET(dbp, DB_AM_LOCKING)) {
|
||||
req.op = DB_LOCK_DUMP;
|
||||
lock_vec(dbp->dbenv->lk_info, dbp->locker, 0, &req, 1, NULL);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* __bam_lget --
|
||||
* The standard lock get call.
|
||||
*
|
||||
* PUBLIC: int __bam_lget __P((DB *, int, db_pgno_t, db_lockmode_t, DB_LOCK *));
|
||||
*/
|
||||
int
|
||||
__bam_lget(dbp, do_couple, pgno, mode, lockp)
|
||||
DB *dbp;
|
||||
int do_couple;
|
||||
db_pgno_t pgno;
|
||||
db_lockmode_t mode;
|
||||
DB_LOCK *lockp;
|
||||
{
|
||||
DB_LOCKREQ couple[2];
|
||||
u_int32_t locker;
|
||||
int ret;
|
||||
|
||||
if (!F_ISSET(dbp, DB_AM_LOCKING)) {
|
||||
*lockp = LOCK_INVALID;
|
||||
return (0);
|
||||
}
|
||||
|
||||
locker = dbp->txn == NULL ? dbp->locker : dbp->txn->txnid;
|
||||
dbp->lock.pgno = pgno;
|
||||
|
||||
/*
|
||||
* If the object not currently locked, acquire the lock and return,
|
||||
* otherwise, lock couple. If we fail and it's not a system error,
|
||||
* convert to EAGAIN.
|
||||
*/
|
||||
if (do_couple) {
|
||||
couple[0].op = DB_LOCK_GET;
|
||||
couple[0].obj = &dbp->lock_dbt;
|
||||
couple[0].mode = mode;
|
||||
couple[1].op = DB_LOCK_PUT;
|
||||
couple[1].lock = *lockp;
|
||||
|
||||
ret = lock_vec(dbp->dbenv->lk_info, locker, 0, couple, 2, NULL);
|
||||
if (ret != 0) {
|
||||
/* If we fail, discard the lock we held. */
|
||||
__bam_lput(dbp, *lockp);
|
||||
|
||||
return (ret < 0 ? EAGAIN : ret);
|
||||
}
|
||||
*lockp = couple[0].lock;
|
||||
} else {
|
||||
ret = lock_get(dbp->dbenv->lk_info,
|
||||
locker, 0, &dbp->lock_dbt, mode, lockp);
|
||||
return (ret < 0 ? EAGAIN : ret);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_lput --
|
||||
* The standard lock put call.
|
||||
*
|
||||
* PUBLIC: int __bam_lput __P((DB *, DB_LOCK));
|
||||
*/
|
||||
int
|
||||
__bam_lput(dbp, lock)
|
||||
DB *dbp;
|
||||
DB_LOCK lock;
|
||||
{
|
||||
return (__BT_LPUT(dbp, lock));
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_pget --
|
||||
* The standard page get call.
|
||||
*
|
||||
* PUBLIC: int __bam_pget __P((DB *, PAGE **, db_pgno_t *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__bam_pget(dbp, hp, pgnop, mpool_flags)
|
||||
DB *dbp;
|
||||
PAGE **hp;
|
||||
db_pgno_t *pgnop;
|
||||
u_int32_t mpool_flags;
|
||||
{
|
||||
return (memp_fget((dbp)->mpf,
|
||||
pgnop, mpool_flags, hp) == 0 ? 0 : __db_pgerr(dbp, *pgnop));
|
||||
}
|
1160
db/btree/bt_put.c
1160
db/btree/bt_put.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,910 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)bt_rec.c 10.21 (Sleepycat) 4/28/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "shqueue.h"
|
||||
#include "hash.h"
|
||||
#include "btree.h"
|
||||
#include "log.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
/*
|
||||
* __bam_pg_alloc_recover --
|
||||
* Recovery function for pg_alloc.
|
||||
*
|
||||
* PUBLIC: int __bam_pg_alloc_recover
|
||||
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__bam_pg_alloc_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__bam_pg_alloc_args *argp;
|
||||
BTMETA *meta;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
DB *file_dbp, *mdbp;
|
||||
db_pgno_t pgno;
|
||||
int cmp_n, cmp_p, modified, ret;
|
||||
|
||||
REC_PRINT(__bam_pg_alloc_print);
|
||||
REC_INTRO(__bam_pg_alloc_read);
|
||||
|
||||
/*
|
||||
* Fix up the allocated page. If we're redoing the operation, we have
|
||||
* to get the page (creating it if it doesn't exist), and update its
|
||||
* LSN. If we're undoing the operation, we have to reset the page's
|
||||
* LSN and put it on the free list.
|
||||
*
|
||||
* Fix up the metadata page. If we're redoing the operation, we have
|
||||
* to get the metadata page and update its LSN and its free pointer.
|
||||
* If we're undoing the operation and the page was ever created, we put
|
||||
* it on the freelist.
|
||||
*/
|
||||
pgno = PGNO_METADATA;
|
||||
if ((ret = memp_fget(mpf, &pgno, 0, &meta)) != 0) {
|
||||
/* The metadata page must always exist. */
|
||||
(void)__db_pgerr(file_dbp, pgno);
|
||||
goto out;
|
||||
}
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
|
||||
/*
|
||||
* We specify creation and check for it later, because this
|
||||
* operation was supposed to create the page, and even in
|
||||
* the undo case it's going to get linked onto the freelist
|
||||
* which we're also fixing up.
|
||||
*/
|
||||
(void)__db_pgerr(file_dbp, argp->pgno);
|
||||
(void)memp_fput(mpf, meta, 0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Fix up the allocated page. */
|
||||
modified = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->page_lsn);
|
||||
if (cmp_p == 0 && redo) {
|
||||
/* Need to redo update described. */
|
||||
P_INIT(pagep, file_dbp->pgsize,
|
||||
argp->pgno, PGNO_INVALID, PGNO_INVALID, 0, argp->ptype);
|
||||
|
||||
pagep->lsn = *lsnp;
|
||||
modified = 1;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
/* Need to undo update described. */
|
||||
P_INIT(pagep, file_dbp->pgsize,
|
||||
argp->pgno, PGNO_INVALID, meta->free, 0, P_INVALID);
|
||||
|
||||
pagep->lsn = argp->page_lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) {
|
||||
(void)__db_panic(file_dbp);
|
||||
(void)memp_fput(mpf, meta, 0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Fix up the metadata page. */
|
||||
modified = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(meta));
|
||||
cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
|
||||
if (cmp_p == 0 && redo) {
|
||||
/* Need to redo update described. */
|
||||
meta->lsn = *lsnp;
|
||||
meta->free = argp->next;
|
||||
modified = 1;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
/* Need to undo update described. */
|
||||
meta->lsn = argp->meta_lsn;
|
||||
meta->free = argp->pgno;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0) {
|
||||
(void)__db_panic(file_dbp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
*lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_pg_free_recover --
|
||||
* Recovery function for pg_free.
|
||||
*
|
||||
* PUBLIC: int __bam_pg_free_recover
|
||||
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__bam_pg_free_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__bam_pg_free_args *argp;
|
||||
BTMETA *meta;
|
||||
DB *file_dbp, *mdbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
db_pgno_t pgno;
|
||||
int cmp_n, cmp_p, modified, ret;
|
||||
|
||||
REC_PRINT(__bam_pg_free_print);
|
||||
REC_INTRO(__bam_pg_free_read);
|
||||
|
||||
/*
|
||||
* Fix up the freed page. If we're redoing the operation we get the
|
||||
* page and explicitly discard its contents, then update its LSN. If
|
||||
* we're undoing the operation, we get the page and restore its header.
|
||||
*/
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
/*
|
||||
* We don't automatically create the page. The only way the
|
||||
* page might not exist is if the alloc never happened, and
|
||||
* the only way the alloc might never have happened is if we
|
||||
* are undoing, in which case there's no reason to create the
|
||||
* page.
|
||||
*/
|
||||
if (!redo)
|
||||
goto done;
|
||||
(void)__db_pgerr(file_dbp, argp->pgno);
|
||||
goto out;
|
||||
}
|
||||
modified = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &LSN(argp->header.data));
|
||||
if (cmp_p == 0 && redo) {
|
||||
/* Need to redo update described. */
|
||||
P_INIT(pagep, file_dbp->pgsize,
|
||||
pagep->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
|
||||
pagep->lsn = *lsnp;
|
||||
|
||||
modified = 1;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
/* Need to undo update described. */
|
||||
memcpy(pagep, argp->header.data, argp->header.size);
|
||||
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) {
|
||||
(void)__db_panic(file_dbp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix up the metadata page. If we're redoing or undoing the operation
|
||||
* we get the page and update its LSN and free pointer.
|
||||
*/
|
||||
pgno = PGNO_METADATA;
|
||||
if ((ret = memp_fget(mpf, &pgno, 0, &meta)) != 0) {
|
||||
/* The metadata page must always exist. */
|
||||
(void)__db_pgerr(file_dbp, pgno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
modified = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(meta));
|
||||
cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
|
||||
if (cmp_p == 0 && redo) {
|
||||
/* Need to redo update described. */
|
||||
meta->free = argp->pgno;
|
||||
|
||||
meta->lsn = *lsnp;
|
||||
modified = 1;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
/* Need to undo update described. */
|
||||
meta->free = argp->next;
|
||||
|
||||
meta->lsn = argp->meta_lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0) {
|
||||
(void)__db_panic(file_dbp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_split_recover --
|
||||
* Recovery function for split.
|
||||
*
|
||||
* PUBLIC: int __bam_split_recover
|
||||
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__bam_split_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__bam_split_args *argp;
|
||||
DB *file_dbp, *mdbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *_lp, *lp, *np, *pp, *_rp, *rp, *sp;
|
||||
db_pgno_t pgno;
|
||||
int l_update, p_update, r_update, ret, rootsplit, t_ret;
|
||||
|
||||
REC_PRINT(__bam_split_print);
|
||||
|
||||
mpf = NULL;
|
||||
_lp = lp = np = pp = _rp = rp = NULL;
|
||||
|
||||
REC_INTRO(__bam_split_read);
|
||||
|
||||
/*
|
||||
* There are two kinds of splits that we have to recover from. The
|
||||
* first is a root-page split, where the root page is split from a
|
||||
* leaf page into an internal page and two new leaf pages are created.
|
||||
* The second is where a page is split into two pages, and a new key
|
||||
* is inserted into the parent page.
|
||||
*/
|
||||
sp = argp->pg.data;
|
||||
pgno = PGNO(sp);
|
||||
rootsplit = pgno == PGNO_ROOT;
|
||||
if (memp_fget(mpf, &argp->left, 0, &lp) != 0)
|
||||
lp = NULL;
|
||||
if (memp_fget(mpf, &argp->right, 0, &rp) != 0)
|
||||
rp = NULL;
|
||||
|
||||
if (redo) {
|
||||
l_update = r_update = p_update = 0;
|
||||
/*
|
||||
* Decide if we need to resplit the page.
|
||||
*
|
||||
* If this is a root split, then the root has to exist, it's
|
||||
* the page we're splitting and it gets modified. If this is
|
||||
* not a root split, then the left page has to exist, for the
|
||||
* same reason.
|
||||
*/
|
||||
if (rootsplit) {
|
||||
if ((ret = memp_fget(mpf, &pgno, 0, &pp)) != 0) {
|
||||
(void)__db_pgerr(file_dbp, pgno);
|
||||
pp = NULL;
|
||||
goto out;
|
||||
}
|
||||
p_update =
|
||||
log_compare(&LSN(pp), &LSN(argp->pg.data)) == 0;
|
||||
} else
|
||||
if (lp == NULL) {
|
||||
(void)__db_pgerr(file_dbp, argp->left);
|
||||
goto out;
|
||||
}
|
||||
if (lp == NULL || log_compare(&LSN(lp), &argp->llsn) == 0)
|
||||
l_update = 1;
|
||||
if (rp == NULL || log_compare(&LSN(rp), &argp->rlsn) == 0)
|
||||
r_update = 1;
|
||||
if (!p_update && !l_update && !r_update)
|
||||
goto done;
|
||||
|
||||
/* Allocate and initialize new left/right child pages. */
|
||||
if ((_lp = (PAGE *)__db_malloc(file_dbp->pgsize)) == NULL ||
|
||||
(_rp = (PAGE *)__db_malloc(file_dbp->pgsize)) == NULL) {
|
||||
ret = ENOMEM;
|
||||
__db_err(file_dbp->dbenv, "%s", strerror(ret));
|
||||
goto out;
|
||||
}
|
||||
if (rootsplit) {
|
||||
P_INIT(_lp, file_dbp->pgsize, argp->left,
|
||||
PGNO_INVALID,
|
||||
ISINTERNAL(sp) ? PGNO_INVALID : argp->right,
|
||||
LEVEL(sp), TYPE(sp));
|
||||
P_INIT(_rp, file_dbp->pgsize, argp->right,
|
||||
ISINTERNAL(sp) ? PGNO_INVALID : argp->left,
|
||||
PGNO_INVALID, LEVEL(sp), TYPE(sp));
|
||||
} else {
|
||||
P_INIT(_lp, file_dbp->pgsize, PGNO(sp),
|
||||
ISINTERNAL(sp) ? PGNO_INVALID : PREV_PGNO(sp),
|
||||
ISINTERNAL(sp) ? PGNO_INVALID : argp->right,
|
||||
LEVEL(sp), TYPE(sp));
|
||||
P_INIT(_rp, file_dbp->pgsize, argp->right,
|
||||
ISINTERNAL(sp) ? PGNO_INVALID : sp->pgno,
|
||||
ISINTERNAL(sp) ? PGNO_INVALID : NEXT_PGNO(sp),
|
||||
LEVEL(sp), TYPE(sp));
|
||||
}
|
||||
|
||||
/* Split the page. */
|
||||
if ((ret = __bam_copy(file_dbp, sp, _lp, 0, argp->indx)) != 0 ||
|
||||
(ret = __bam_copy(file_dbp, sp, _rp, argp->indx,
|
||||
NUM_ENT(sp))) != 0)
|
||||
goto out;
|
||||
|
||||
/* If the left child is wrong, update it. */
|
||||
if (lp == NULL && (ret =
|
||||
memp_fget(mpf, &argp->left, DB_MPOOL_CREATE, &lp)) != 0) {
|
||||
(void)__db_pgerr(file_dbp, argp->left);
|
||||
lp = NULL;
|
||||
goto out;
|
||||
}
|
||||
if (l_update) {
|
||||
memcpy(lp, _lp, file_dbp->pgsize);
|
||||
lp->lsn = *lsnp;
|
||||
if ((ret = memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto fatal;
|
||||
lp = NULL;
|
||||
}
|
||||
|
||||
/* If the right child is wrong, update it. */
|
||||
if (rp == NULL && (ret = memp_fget(mpf,
|
||||
&argp->right, DB_MPOOL_CREATE, &rp)) != 0) {
|
||||
(void)__db_pgerr(file_dbp, argp->right);
|
||||
rp = NULL;
|
||||
goto out;
|
||||
}
|
||||
if (r_update) {
|
||||
memcpy(rp, _rp, file_dbp->pgsize);
|
||||
rp->lsn = *lsnp;
|
||||
if ((ret = memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto fatal;
|
||||
rp = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the parent page is wrong, update it. This is of interest
|
||||
* only if it was a root split, since root splits create parent
|
||||
* pages. All other splits modify a parent page, but those are
|
||||
* separately logged and recovered.
|
||||
*/
|
||||
if (rootsplit && p_update) {
|
||||
if (file_dbp->type == DB_BTREE)
|
||||
P_INIT(pp, file_dbp->pgsize,
|
||||
PGNO_ROOT, PGNO_INVALID, PGNO_INVALID,
|
||||
_lp->level + 1, P_IBTREE);
|
||||
else
|
||||
P_INIT(pp, file_dbp->pgsize,
|
||||
PGNO_ROOT, PGNO_INVALID, PGNO_INVALID,
|
||||
_lp->level + 1, P_IRECNO);
|
||||
RE_NREC_SET(pp,
|
||||
file_dbp->type == DB_RECNO ||
|
||||
F_ISSET(file_dbp, DB_BT_RECNUM) ?
|
||||
__bam_total(_lp) + __bam_total(_rp) : 0);
|
||||
pp->lsn = *lsnp;
|
||||
if ((ret = memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto fatal;
|
||||
pp = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, redo the next-page link if necessary. This is of
|
||||
* interest only if it wasn't a root split -- inserting a new
|
||||
* page in the tree requires that any following page have its
|
||||
* previous-page pointer updated to our new page. The next
|
||||
* page must exist because we're redoing the operation.
|
||||
*/
|
||||
if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) {
|
||||
if ((ret = memp_fget(mpf, &argp->npgno, 0, &np)) != 0) {
|
||||
(void)__db_pgerr(file_dbp, argp->npgno);
|
||||
np = NULL;
|
||||
goto out;
|
||||
}
|
||||
if (log_compare(&LSN(np), &argp->nlsn) == 0) {
|
||||
PREV_PGNO(np) = argp->right;
|
||||
np->lsn = *lsnp;
|
||||
if ((ret = memp_fput(mpf,
|
||||
np, DB_MPOOL_DIRTY)) != 0)
|
||||
goto fatal;
|
||||
np = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If the split page is wrong, replace its contents with the
|
||||
* logged page contents. If the page doesn't exist, it means
|
||||
* that the create of the page never happened, nor did any of
|
||||
* the adds onto the page that caused the split, and there's
|
||||
* really no undo-ing to be done.
|
||||
*/
|
||||
if ((ret = memp_fget(mpf, &pgno, 0, &pp)) != 0) {
|
||||
pp = NULL;
|
||||
goto lrundo;
|
||||
}
|
||||
if (log_compare(lsnp, &LSN(pp)) == 0) {
|
||||
memcpy(pp, argp->pg.data, argp->pg.size);
|
||||
if ((ret = memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto fatal;
|
||||
pp = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's a root split and the left child ever existed, update
|
||||
* its LSN. (If it's not a root split, we've updated the left
|
||||
* page already -- it's the same as the split page.) If the
|
||||
* right child ever existed, root split or not, update its LSN.
|
||||
* The undo of the page allocation(s) will restore them to the
|
||||
* free list.
|
||||
*/
|
||||
lrundo: if ((rootsplit && lp != NULL) || rp != NULL) {
|
||||
if (rootsplit && lp != NULL &&
|
||||
log_compare(lsnp, &LSN(lp)) == 0) {
|
||||
lp->lsn = argp->llsn;
|
||||
if ((ret =
|
||||
memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto fatal;
|
||||
lp = NULL;
|
||||
}
|
||||
if (rp != NULL &&
|
||||
log_compare(lsnp, &LSN(rp)) == 0) {
|
||||
rp->lsn = argp->rlsn;
|
||||
if ((ret =
|
||||
memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto fatal;
|
||||
rp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, undo the next-page link if necessary. This is of
|
||||
* interest only if it wasn't a root split -- inserting a new
|
||||
* page in the tree requires that any following page have its
|
||||
* previous-page pointer updated to our new page. Since it's
|
||||
* possible that the next-page never existed, we ignore it as
|
||||
* if there's nothing to undo.
|
||||
*/
|
||||
if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) {
|
||||
if ((ret = memp_fget(mpf, &argp->npgno, 0, &np)) != 0) {
|
||||
np = NULL;
|
||||
goto done;
|
||||
}
|
||||
if (log_compare(lsnp, &LSN(np)) == 0) {
|
||||
PREV_PGNO(np) = argp->left;
|
||||
np->lsn = argp->nlsn;
|
||||
if (memp_fput(mpf, np, DB_MPOOL_DIRTY))
|
||||
goto fatal;
|
||||
np = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
if (0) {
|
||||
fatal: (void)__db_panic(file_dbp);
|
||||
}
|
||||
out: /* Free any pages that weren't dirtied. */
|
||||
if (pp != NULL && (t_ret = memp_fput(mpf, pp, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if (lp != NULL && (t_ret = memp_fput(mpf, lp, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if (np != NULL && (t_ret = memp_fput(mpf, np, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if (rp != NULL && (t_ret = memp_fput(mpf, rp, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/* Free any allocated space. */
|
||||
if (_lp != NULL)
|
||||
__db_free(_lp);
|
||||
if (_rp != NULL)
|
||||
__db_free(_rp);
|
||||
|
||||
REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_rsplit_recover --
|
||||
* Recovery function for a reverse split.
|
||||
*
|
||||
* PUBLIC: int __bam_rsplit_recover
|
||||
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__bam_rsplit_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__bam_rsplit_args *argp;
|
||||
DB *file_dbp, *mdbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
db_pgno_t pgno;
|
||||
int cmp_n, cmp_p, modified, ret;
|
||||
|
||||
REC_PRINT(__bam_rsplit_print);
|
||||
REC_INTRO(__bam_rsplit_read);
|
||||
|
||||
/* Fix the root page. */
|
||||
pgno = PGNO_ROOT;
|
||||
if ((ret = memp_fget(mpf, &pgno, 0, &pagep)) != 0) {
|
||||
/* The root page must always exist. */
|
||||
__db_pgerr(file_dbp, pgno);
|
||||
goto out;
|
||||
}
|
||||
modified = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->rootlsn);
|
||||
if (cmp_p == 0 && redo) {
|
||||
/* Need to redo update described. */
|
||||
memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size);
|
||||
pagep->pgno = PGNO_ROOT;
|
||||
pagep->lsn = *lsnp;
|
||||
modified = 1;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
/* Need to undo update described. */
|
||||
P_INIT(pagep, file_dbp->pgsize, PGNO_ROOT,
|
||||
argp->nrec, PGNO_INVALID, pagep->level + 1,
|
||||
file_dbp->type == DB_BTREE ? P_IBTREE : P_IRECNO);
|
||||
if ((ret = __db_pitem(file_dbp, pagep, 0,
|
||||
argp->rootent.size, &argp->rootent, NULL)) != 0)
|
||||
goto out;
|
||||
pagep->lsn = argp->rootlsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) {
|
||||
(void)__db_panic(file_dbp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix the page copied over the root page. It's possible that the
|
||||
* page never made it to disk, so if we're undo-ing and the page
|
||||
* doesn't exist, it's okay and there's nothing further to do.
|
||||
*/
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (!redo)
|
||||
goto done;
|
||||
(void)__db_pgerr(file_dbp, argp->pgno);
|
||||
goto out;
|
||||
}
|
||||
modified = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &LSN(argp->pgdbt.data));
|
||||
if (cmp_p == 0 && redo) {
|
||||
/* Need to redo update described. */
|
||||
pagep->lsn = *lsnp;
|
||||
modified = 1;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
/* Need to undo update described. */
|
||||
memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size);
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) {
|
||||
(void)__db_panic(file_dbp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_adj_recover --
|
||||
* Recovery function for adj.
|
||||
*
|
||||
* PUBLIC: int __bam_adj_recover
|
||||
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__bam_adj_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__bam_adj_args *argp;
|
||||
DB *file_dbp, *mdbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
int cmp_n, cmp_p, modified, ret;
|
||||
|
||||
REC_PRINT(__bam_adj_print);
|
||||
REC_INTRO(__bam_adj_read);
|
||||
|
||||
/* Get the page; if it never existed and we're undoing, we're done. */
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (!redo)
|
||||
goto done;
|
||||
(void)__db_pgerr(file_dbp, argp->pgno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
modified = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
|
||||
if (cmp_p == 0 && redo) {
|
||||
/* Need to redo update described. */
|
||||
if ((ret = __bam_adjindx(file_dbp,
|
||||
pagep, argp->indx, argp->indx_copy, argp->is_insert)) != 0)
|
||||
goto err;
|
||||
|
||||
LSN(pagep) = *lsnp;
|
||||
modified = 1;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
/* Need to undo update described. */
|
||||
if ((ret = __bam_adjindx(file_dbp,
|
||||
pagep, argp->indx, argp->indx_copy, !argp->is_insert)) != 0)
|
||||
goto err;
|
||||
|
||||
LSN(pagep) = argp->lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
|
||||
done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
if (0) {
|
||||
err: (void)memp_fput(mpf, pagep, 0);
|
||||
}
|
||||
out: REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_cadjust_recover --
|
||||
* Recovery function for the adjust of a count change in an internal
|
||||
* page.
|
||||
*
|
||||
* PUBLIC: int __bam_cadjust_recover
|
||||
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__bam_cadjust_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__bam_cadjust_args *argp;
|
||||
DB *file_dbp, *mdbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
int cmp_n, cmp_p, modified, ret;
|
||||
|
||||
REC_PRINT(__bam_cadjust_print);
|
||||
REC_INTRO(__bam_cadjust_read);
|
||||
|
||||
/* Get the page; if it never existed and we're undoing, we're done. */
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (!redo)
|
||||
goto done;
|
||||
(void)__db_pgerr(file_dbp, argp->pgno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
modified = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
|
||||
if (cmp_p == 0 && redo) {
|
||||
/* Need to redo update described. */
|
||||
if (file_dbp->type == DB_BTREE &&
|
||||
F_ISSET(file_dbp, DB_BT_RECNUM)) {
|
||||
GET_BINTERNAL(pagep, argp->indx)->nrecs += argp->adjust;
|
||||
if (argp->total && PGNO(pagep) == PGNO_ROOT)
|
||||
RE_NREC_ADJ(pagep, argp->adjust);
|
||||
}
|
||||
if (file_dbp->type == DB_RECNO) {
|
||||
GET_RINTERNAL(pagep, argp->indx)->nrecs += argp->adjust;
|
||||
if (argp->total && PGNO(pagep) == PGNO_ROOT)
|
||||
RE_NREC_ADJ(pagep, argp->adjust);
|
||||
}
|
||||
|
||||
LSN(pagep) = *lsnp;
|
||||
modified = 1;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
/* Need to undo update described. */
|
||||
if (file_dbp->type == DB_BTREE &&
|
||||
F_ISSET(file_dbp, DB_BT_RECNUM)) {
|
||||
GET_BINTERNAL(pagep, argp->indx)->nrecs -= argp->adjust;
|
||||
if (argp->total && PGNO(pagep) == PGNO_ROOT)
|
||||
RE_NREC_ADJ(pagep, argp->adjust);
|
||||
}
|
||||
if (file_dbp->type == DB_RECNO) {
|
||||
GET_RINTERNAL(pagep, argp->indx)->nrecs -= argp->adjust;
|
||||
if (argp->total && PGNO(pagep) == PGNO_ROOT)
|
||||
RE_NREC_ADJ(pagep, -(argp->adjust));
|
||||
}
|
||||
LSN(pagep) = argp->lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
|
||||
done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_cdel_recover --
|
||||
* Recovery function for the intent-to-delete of a cursor record.
|
||||
*
|
||||
* PUBLIC: int __bam_cdel_recover
|
||||
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__bam_cdel_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__bam_cdel_args *argp;
|
||||
DB *file_dbp, *mdbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
int cmp_n, cmp_p, modified, ret;
|
||||
|
||||
REC_PRINT(__bam_cdel_print);
|
||||
REC_INTRO(__bam_cdel_read);
|
||||
|
||||
/* Get the page; if it never existed and we're undoing, we're done. */
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (!redo)
|
||||
goto done;
|
||||
(void)__db_pgerr(file_dbp, argp->pgno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
modified = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
|
||||
if (cmp_p == 0 && redo) {
|
||||
/* Need to redo update described. */
|
||||
B_DSET(GET_BKEYDATA(pagep, argp->indx + O_INDX)->type);
|
||||
|
||||
LSN(pagep) = *lsnp;
|
||||
modified = 1;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
/* Need to undo update described. */
|
||||
B_DCLR(GET_BKEYDATA(pagep, argp->indx + O_INDX)->type);
|
||||
|
||||
LSN(pagep) = argp->lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
|
||||
done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_repl_recover --
|
||||
* Recovery function for page item replacement.
|
||||
*
|
||||
* PUBLIC: int __bam_repl_recover
|
||||
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__bam_repl_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__bam_repl_args *argp;
|
||||
BKEYDATA *bk;
|
||||
DB *file_dbp, *mdbp;
|
||||
DBT dbt;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
int cmp_n, cmp_p, modified, ret;
|
||||
u_int8_t *p;
|
||||
|
||||
REC_PRINT(__bam_repl_print);
|
||||
REC_INTRO(__bam_repl_read);
|
||||
|
||||
/* Get the page; if it never existed and we're undoing, we're done. */
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (!redo)
|
||||
goto done;
|
||||
(void)__db_pgerr(file_dbp, argp->pgno);
|
||||
goto out;
|
||||
}
|
||||
bk = GET_BKEYDATA(pagep, argp->indx);
|
||||
|
||||
modified = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
|
||||
if (cmp_p == 0 && redo) {
|
||||
/*
|
||||
* Need to redo update described.
|
||||
*
|
||||
* Re-build the replacement item.
|
||||
*/
|
||||
memset(&dbt, 0, sizeof(dbt));
|
||||
dbt.size = argp->prefix + argp->suffix + argp->repl.size;
|
||||
if ((dbt.data = __db_malloc(dbt.size)) == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
p = dbt.data;
|
||||
memcpy(p, bk->data, argp->prefix);
|
||||
p += argp->prefix;
|
||||
memcpy(p, argp->repl.data, argp->repl.size);
|
||||
p += argp->repl.size;
|
||||
memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix);
|
||||
|
||||
ret = __bam_ritem(file_dbp, pagep, argp->indx, &dbt);
|
||||
__db_free(dbt.data);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
LSN(pagep) = *lsnp;
|
||||
modified = 1;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
/*
|
||||
* Need to undo update described.
|
||||
*
|
||||
* Re-build the original item.
|
||||
*/
|
||||
memset(&dbt, 0, sizeof(dbt));
|
||||
dbt.size = argp->prefix + argp->suffix + argp->orig.size;
|
||||
if ((dbt.data = __db_malloc(dbt.size)) == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
p = dbt.data;
|
||||
memcpy(p, bk->data, argp->prefix);
|
||||
p += argp->prefix;
|
||||
memcpy(p, argp->orig.data, argp->orig.size);
|
||||
p += argp->orig.size;
|
||||
memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix);
|
||||
|
||||
ret = __bam_ritem(file_dbp, pagep, argp->indx, &dbt);
|
||||
__db_free(dbt.data);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
/* Reset the deleted flag, if necessary. */
|
||||
if (argp->isdeleted)
|
||||
B_DSET(GET_BKEYDATA(pagep, argp->indx)->type);
|
||||
|
||||
LSN(pagep) = argp->lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
|
||||
done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
if (0) {
|
||||
err: (void)memp_fput(mpf, pagep, 0);
|
||||
}
|
||||
out: REC_CLOSE;
|
||||
}
|
1263
db/btree/bt_recno.c
1263
db/btree/bt_recno.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,383 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)bt_rsearch.c 10.15 (Sleepycat) 5/6/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "btree.h"
|
||||
|
||||
/*
|
||||
* __bam_rsearch --
|
||||
* Search a btree for a record number.
|
||||
*
|
||||
* PUBLIC: int __bam_rsearch __P((DB *, db_recno_t *, u_int32_t, int, int *));
|
||||
*/
|
||||
int
|
||||
__bam_rsearch(dbp, recnop, flags, stop, exactp)
|
||||
DB *dbp;
|
||||
db_recno_t *recnop;
|
||||
u_int32_t flags;
|
||||
int stop, *exactp;
|
||||
{
|
||||
BINTERNAL *bi;
|
||||
BTREE *t;
|
||||
DB_LOCK lock;
|
||||
PAGE *h;
|
||||
RINTERNAL *ri;
|
||||
db_indx_t indx, top;
|
||||
db_pgno_t pg;
|
||||
db_recno_t i, recno, total;
|
||||
int isappend, ret, stack;
|
||||
|
||||
t = dbp->internal;
|
||||
|
||||
/*
|
||||
* We test for groups of flags, S_APPEND is the only one that can be
|
||||
* OR'd into the set. Clear it now so that the tests for equality
|
||||
* will work.
|
||||
*/
|
||||
if ((isappend = LF_ISSET(S_APPEND)) != 0)
|
||||
LF_CLR(S_APPEND);
|
||||
|
||||
/*
|
||||
* There are several ways we search a btree tree. The flags argument
|
||||
* specifies if we're acquiring read or write locks and if we are
|
||||
* locking pairs of pages. See btree.h for more details.
|
||||
*
|
||||
* If write-locking pages, we need to know whether or not to acquire a
|
||||
* write lock on a page before getting it. This depends on how deep it
|
||||
* is in tree, which we don't know until we acquire the root page. So,
|
||||
* if we need to lock the root page we may have to upgrade it later,
|
||||
* because we won't get the correct lock initially.
|
||||
*
|
||||
* Retrieve the root page.
|
||||
*/
|
||||
pg = PGNO_ROOT;
|
||||
if ((ret = __bam_lget(dbp, 0, PGNO_ROOT,
|
||||
flags == S_INSERT || flags == S_DELETE ?
|
||||
DB_LOCK_WRITE : DB_LOCK_READ, &lock)) != 0)
|
||||
return (ret);
|
||||
if ((ret = __bam_pget(dbp, &h, &pg, 0)) != 0) {
|
||||
(void)__BT_LPUT(dbp, lock);
|
||||
return (ret);
|
||||
}
|
||||
total = RE_NREC(h);
|
||||
|
||||
/*
|
||||
* If appending to the tree, set the record number now -- we have the
|
||||
* root page locked.
|
||||
*
|
||||
* Delete only deletes exact matches, read only returns exact matches.
|
||||
* Note, this is different from __bam_search(), which returns non-exact
|
||||
* matches for read.
|
||||
*
|
||||
* The record may not exist. We can only return the correct location
|
||||
* for the record immediately after the last record in the tree, so do
|
||||
* a fast check now.
|
||||
*/
|
||||
if (isappend) {
|
||||
*exactp = 0;
|
||||
*recnop = recno = total + 1;
|
||||
} else {
|
||||
recno = *recnop;
|
||||
if (recno <= total)
|
||||
*exactp = 1;
|
||||
else {
|
||||
*exactp = 0;
|
||||
if (!PAST_END_OK(flags) || recno > total + 1) {
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
(void)__BT_LPUT(dbp, lock);
|
||||
return (DB_NOTFOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Decide if we're building a stack based on the operation. */
|
||||
BT_STK_CLR(t);
|
||||
stack = flags == S_DELETE || flags == S_INSERT;
|
||||
|
||||
/*
|
||||
* Decide if we need to save this page; if we do, write lock it, and
|
||||
* start to build a stack.
|
||||
*/
|
||||
if (LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) {
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
if ((ret = __bam_lget(dbp, 1, pg, DB_LOCK_WRITE, &lock)) != 0)
|
||||
return (ret);
|
||||
if ((ret = __bam_pget(dbp, &h, &pg, 0)) != 0) {
|
||||
(void)__BT_LPUT(dbp, lock);
|
||||
return (ret);
|
||||
}
|
||||
stack = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* Record numbers in the tree are 0-based, but the recno is
|
||||
* 1-based. All of the calculations below have to take this
|
||||
* into account.
|
||||
*/
|
||||
for (total = 0;;) {
|
||||
switch (TYPE(h)) {
|
||||
case P_LBTREE:
|
||||
recno -= total;
|
||||
|
||||
/*
|
||||
* There may be logically deleted records on the page,
|
||||
* walk the page correcting for them. The record may
|
||||
* not exist if there are enough deleted records in the
|
||||
* page.
|
||||
*/
|
||||
if (recno <= NUM_ENT(h))
|
||||
for (i = recno - 1;; --i) {
|
||||
if (B_DISSET(GET_BKEYDATA(h,
|
||||
i * P_INDX + O_INDX)->type))
|
||||
++recno;
|
||||
if (i == 0)
|
||||
break;
|
||||
}
|
||||
if (recno > NUM_ENT(h)) {
|
||||
*exactp = 0;
|
||||
if (!PAST_END_OK(flags) ||
|
||||
recno > (db_recno_t)(NUM_ENT(h) + 1)) {
|
||||
ret = DB_NOTFOUND;
|
||||
goto err;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Correct from 1-based to 0-based for a page offset. */
|
||||
--recno;
|
||||
BT_STK_ENTER(t, h, recno * P_INDX, lock, ret);
|
||||
return (ret);
|
||||
case P_IBTREE:
|
||||
for (indx = 0, top = NUM_ENT(h);;) {
|
||||
bi = GET_BINTERNAL(h, indx);
|
||||
if (++indx == top || total + bi->nrecs >= recno)
|
||||
break;
|
||||
total += bi->nrecs;
|
||||
}
|
||||
pg = bi->pgno;
|
||||
break;
|
||||
case P_LRECNO:
|
||||
recno -= total;
|
||||
|
||||
/* Correct from 1-based to 0-based for a page offset. */
|
||||
--recno;
|
||||
BT_STK_ENTER(t, h, recno, lock, ret);
|
||||
return (ret);
|
||||
case P_IRECNO:
|
||||
for (indx = 0, top = NUM_ENT(h);;) {
|
||||
ri = GET_RINTERNAL(h, indx);
|
||||
if (++indx == top || total + ri->nrecs >= recno)
|
||||
break;
|
||||
total += ri->nrecs;
|
||||
}
|
||||
pg = ri->pgno;
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbp, h->pgno));
|
||||
}
|
||||
--indx;
|
||||
|
||||
if (stack) {
|
||||
/* Return if this is the lowest page wanted. */
|
||||
if (LF_ISSET(S_PARENT) && stop == h->level) {
|
||||
BT_STK_ENTER(t, h, indx, lock, ret);
|
||||
return (ret);
|
||||
}
|
||||
BT_STK_PUSH(t, h, indx, lock, ret);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if ((ret = __bam_lget(dbp, 0, pg,
|
||||
LF_ISSET(S_WRITE) ? DB_LOCK_WRITE : DB_LOCK_READ,
|
||||
&lock)) != 0)
|
||||
goto err;
|
||||
} else {
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
|
||||
/*
|
||||
* Decide if we want to return a pointer to the next
|
||||
* page in the stack. If we do, write lock it and
|
||||
* never unlock it.
|
||||
*/
|
||||
if (LF_ISSET(S_PARENT) &&
|
||||
(u_int8_t)(stop + 1) >= (u_int8_t)(h->level - 1))
|
||||
stack = 1;
|
||||
|
||||
if ((ret = __bam_lget(dbp, 1, pg,
|
||||
LF_ISSET(S_WRITE) ? DB_LOCK_WRITE : DB_LOCK_READ,
|
||||
&lock)) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((ret = __bam_pget(dbp, &h, &pg, 0)) != 0)
|
||||
goto err;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
|
||||
err: BT_STK_POP(t);
|
||||
__bam_stkrel(dbp);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_adjust --
|
||||
* Adjust the tree after adding or deleting a record.
|
||||
*
|
||||
* PUBLIC: int __bam_adjust __P((DB *, BTREE *, int32_t));
|
||||
*/
|
||||
int
|
||||
__bam_adjust(dbp, t, adjust)
|
||||
DB *dbp;
|
||||
BTREE *t;
|
||||
int32_t adjust;
|
||||
{
|
||||
EPG *epg;
|
||||
PAGE *h;
|
||||
int ret;
|
||||
|
||||
/* Update the record counts for the tree. */
|
||||
for (epg = t->bt_sp; epg <= t->bt_csp; ++epg) {
|
||||
h = epg->page;
|
||||
if (TYPE(h) == P_IBTREE || TYPE(h) == P_IRECNO) {
|
||||
if (DB_LOGGING(dbp) &&
|
||||
(ret = __bam_cadjust_log(dbp->dbenv->lg_info,
|
||||
dbp->txn, &LSN(h), 0, dbp->log_fileid,
|
||||
PGNO(h), &LSN(h), (u_int32_t)epg->indx,
|
||||
adjust, 1)) != 0)
|
||||
return (ret);
|
||||
|
||||
if (TYPE(h) == P_IBTREE)
|
||||
GET_BINTERNAL(h, epg->indx)->nrecs += adjust;
|
||||
else
|
||||
GET_RINTERNAL(h, epg->indx)->nrecs += adjust;
|
||||
|
||||
if (PGNO(h) == PGNO_ROOT)
|
||||
RE_NREC_ADJ(h, adjust);
|
||||
|
||||
if ((ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0)
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_nrecs --
|
||||
* Return the number of records in the tree.
|
||||
*
|
||||
* PUBLIC: int __bam_nrecs __P((DB *, db_recno_t *));
|
||||
*/
|
||||
int
|
||||
__bam_nrecs(dbp, rep)
|
||||
DB *dbp;
|
||||
db_recno_t *rep;
|
||||
{
|
||||
DB_LOCK lock;
|
||||
PAGE *h;
|
||||
db_pgno_t pgno;
|
||||
int ret;
|
||||
|
||||
pgno = PGNO_ROOT;
|
||||
if ((ret = __bam_lget(dbp, 0, pgno, DB_LOCK_READ, &lock)) != 0)
|
||||
return (ret);
|
||||
if ((ret = __bam_pget(dbp, &h, &pgno, 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
*rep = RE_NREC(h);
|
||||
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
(void)__BT_TLPUT(dbp, lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_total --
|
||||
* Return the number of records below a page.
|
||||
*
|
||||
* PUBLIC: db_recno_t __bam_total __P((PAGE *));
|
||||
*/
|
||||
db_recno_t
|
||||
__bam_total(h)
|
||||
PAGE *h;
|
||||
{
|
||||
db_recno_t nrecs;
|
||||
db_indx_t indx, top;
|
||||
|
||||
nrecs = 0;
|
||||
top = NUM_ENT(h);
|
||||
|
||||
switch (TYPE(h)) {
|
||||
case P_LBTREE:
|
||||
/* Check for logically deleted records. */
|
||||
for (indx = 0; indx < top; indx += P_INDX)
|
||||
if (!B_DISSET(GET_BKEYDATA(h, indx + O_INDX)->type))
|
||||
++nrecs;
|
||||
break;
|
||||
case P_IBTREE:
|
||||
for (indx = 0; indx < top; indx += O_INDX)
|
||||
nrecs += GET_BINTERNAL(h, indx)->nrecs;
|
||||
break;
|
||||
case P_LRECNO:
|
||||
nrecs = NUM_ENT(h);
|
||||
break;
|
||||
case P_IRECNO:
|
||||
for (indx = 0; indx < top; indx += O_INDX)
|
||||
nrecs += GET_RINTERNAL(h, indx)->nrecs;
|
||||
break;
|
||||
}
|
||||
|
||||
return (nrecs);
|
||||
}
|
|
@ -1,351 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Mike Olson.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)bt_search.c 10.15 (Sleepycat) 5/6/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "btree.h"
|
||||
|
||||
/*
|
||||
* __bam_search --
|
||||
* Search a btree for a key.
|
||||
*
|
||||
* PUBLIC: int __bam_search __P((DB *,
|
||||
* PUBLIC: const DBT *, u_int32_t, int, db_recno_t *, int *));
|
||||
*/
|
||||
int
|
||||
__bam_search(dbp, key, flags, stop, recnop, exactp)
|
||||
DB *dbp;
|
||||
const DBT *key;
|
||||
u_int32_t flags;
|
||||
int stop, *exactp;
|
||||
db_recno_t *recnop;
|
||||
{
|
||||
BTREE *t;
|
||||
DB_LOCK lock;
|
||||
EPG cur;
|
||||
PAGE *h;
|
||||
db_indx_t base, i, indx, lim;
|
||||
db_pgno_t pg;
|
||||
db_recno_t recno;
|
||||
int cmp, jump, ret, stack;
|
||||
|
||||
t = dbp->internal;
|
||||
recno = 0;
|
||||
|
||||
BT_STK_CLR(t);
|
||||
|
||||
/*
|
||||
* There are several ways we search a btree tree. The flags argument
|
||||
* specifies if we're acquiring read or write locks, if we position
|
||||
* to the first or last item in a set of duplicates, if we return
|
||||
* deleted items, and if we are locking pairs of pages. See btree.h
|
||||
* for more details. In addition, if we're doing record numbers, we
|
||||
* have to lock the entire tree regardless.
|
||||
*
|
||||
* If write-locking pages, we need to know whether or not to acquire a
|
||||
* write lock on a page before getting it. This depends on how deep it
|
||||
* is in tree, which we don't know until we acquire the root page. So,
|
||||
* if we need to lock the root page we may have to upgrade it later,
|
||||
* because we won't get the correct lock initially.
|
||||
*
|
||||
* Retrieve the root page.
|
||||
*/
|
||||
pg = PGNO_ROOT;
|
||||
stack = F_ISSET(dbp, DB_BT_RECNUM) && LF_ISSET(S_STACK);
|
||||
if ((ret = __bam_lget(dbp,
|
||||
0, pg, stack ? DB_LOCK_WRITE : DB_LOCK_READ, &lock)) != 0)
|
||||
return (ret);
|
||||
if ((ret = __bam_pget(dbp, &h, &pg, 0)) != 0) {
|
||||
(void)__BT_LPUT(dbp, lock);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decide if we need to save this page; if we do, write lock it.
|
||||
* We deliberately don't lock-couple on this call. If the tree
|
||||
* is tiny, i.e., one page, and two threads are busily updating
|
||||
* the root page, we're almost guaranteed deadlocks galore, as
|
||||
* each one gets a read lock and then blocks the other's attempt
|
||||
* for a write lock.
|
||||
*/
|
||||
if (!stack &&
|
||||
((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) ||
|
||||
(LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
(void)__BT_LPUT(dbp, lock);
|
||||
if ((ret = __bam_lget(dbp, 0, pg, DB_LOCK_WRITE, &lock)) != 0)
|
||||
return (ret);
|
||||
if ((ret = __bam_pget(dbp, &h, &pg, 0)) != 0) {
|
||||
(void)__BT_LPUT(dbp, lock);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
stack = 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* Do a binary search on the current page. If we're searching
|
||||
* a leaf page, we have to manipulate the indices in groups of
|
||||
* two. If we're searching an internal page, they're an index
|
||||
* per page item. If we find an exact match on a leaf page,
|
||||
* we're done.
|
||||
*/
|
||||
cur.page = h;
|
||||
jump = TYPE(h) == P_LBTREE ? P_INDX : O_INDX;
|
||||
for (base = 0,
|
||||
lim = NUM_ENT(h) / (db_indx_t)jump; lim != 0; lim >>= 1) {
|
||||
cur.indx = indx = base + ((lim >> 1) * jump);
|
||||
if ((cmp = __bam_cmp(dbp, key, &cur)) == 0) {
|
||||
if (TYPE(h) == P_LBTREE)
|
||||
goto match;
|
||||
goto next;
|
||||
}
|
||||
if (cmp > 0) {
|
||||
base = indx + jump;
|
||||
--lim;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* No match found. Base is the smallest index greater than
|
||||
* key and may be zero or a last + O_INDX index.
|
||||
*
|
||||
* If it's a leaf page, return base as the "found" value.
|
||||
* Delete only deletes exact matches.
|
||||
*/
|
||||
if (TYPE(h) == P_LBTREE) {
|
||||
*exactp = 0;
|
||||
|
||||
if (LF_ISSET(S_EXACT))
|
||||
goto notfound;
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* Possibly returning a deleted record -- DB_SET_RANGE,
|
||||
* DB_KEYFIRST and DB_KEYLAST don't require an exact
|
||||
* match, and we don't want to walk multiple pages here
|
||||
* to find an undeleted record. This is handled in the
|
||||
* __bam_c_search() routine.
|
||||
*/
|
||||
BT_STK_ENTER(t, h, base, lock, ret);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's not a leaf page, record the internal page (which is
|
||||
* a parent page for the key). Decrement the base by 1 if it's
|
||||
* non-zero so that if a split later occurs, the inserted page
|
||||
* will be to the right of the saved page.
|
||||
*/
|
||||
indx = base > 0 ? base - O_INDX : base;
|
||||
|
||||
/*
|
||||
* If we're trying to calculate the record number, sum up
|
||||
* all the record numbers on this page up to the indx point.
|
||||
*/
|
||||
if (recnop != NULL)
|
||||
for (i = 0; i < indx; ++i)
|
||||
recno += GET_BINTERNAL(h, i)->nrecs;
|
||||
|
||||
next: pg = GET_BINTERNAL(h, indx)->pgno;
|
||||
if (stack) {
|
||||
/* Return if this is the lowest page wanted. */
|
||||
if (LF_ISSET(S_PARENT) && stop == h->level) {
|
||||
BT_STK_ENTER(t, h, indx, lock, ret);
|
||||
return (ret);
|
||||
}
|
||||
BT_STK_PUSH(t, h, indx, lock, ret);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
if ((ret =
|
||||
__bam_lget(dbp, 0, pg, DB_LOCK_WRITE, &lock)) != 0)
|
||||
goto err;
|
||||
} else {
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
|
||||
/*
|
||||
* Decide if we want to return a pointer to the next
|
||||
* page in the stack. If we do, write lock it and
|
||||
* never unlock it.
|
||||
*/
|
||||
if ((LF_ISSET(S_PARENT) &&
|
||||
(u_int8_t)(stop + 1) >= (u_int8_t)(h->level - 1)) ||
|
||||
(h->level - 1) == LEAFLEVEL)
|
||||
stack = 1;
|
||||
|
||||
if ((ret =
|
||||
__bam_lget(dbp, 1, pg, stack && LF_ISSET(S_WRITE) ?
|
||||
DB_LOCK_WRITE : DB_LOCK_READ, &lock)) != 0)
|
||||
goto err;
|
||||
}
|
||||
if ((ret = __bam_pget(dbp, &h, &pg, 0)) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
match: *exactp = 1;
|
||||
|
||||
/*
|
||||
* If we're trying to calculate the record number, add in the
|
||||
* offset on this page and correct for the fact that records
|
||||
* in the tree are 0-based.
|
||||
*/
|
||||
if (recnop != NULL)
|
||||
*recnop = recno + (indx / P_INDX) + 1;
|
||||
|
||||
/*
|
||||
* If we got here, we know that we have a btree leaf page.
|
||||
*
|
||||
* If there are duplicates, go to the first/last one. This is
|
||||
* safe because we know that we're not going to leave the page,
|
||||
* all duplicate sets that are not on overflow pages exist on a
|
||||
* single leaf page.
|
||||
*/
|
||||
if (LF_ISSET(S_DUPLAST))
|
||||
while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
|
||||
h->inp[indx] == h->inp[indx + P_INDX])
|
||||
indx += P_INDX;
|
||||
else
|
||||
while (indx > 0 &&
|
||||
h->inp[indx] == h->inp[indx - P_INDX])
|
||||
indx -= P_INDX;
|
||||
|
||||
/*
|
||||
* Now check if we are allowed to return deleted items; if not
|
||||
* find the next (or previous) non-deleted item.
|
||||
*/
|
||||
if (LF_ISSET(S_DELNO)) {
|
||||
if (LF_ISSET(S_DUPLAST))
|
||||
while (B_DISSET(GET_BKEYDATA(h, indx + O_INDX)->type) &&
|
||||
indx > 0 &&
|
||||
h->inp[indx] == h->inp[indx - P_INDX])
|
||||
indx -= P_INDX;
|
||||
else
|
||||
while (B_DISSET(GET_BKEYDATA(h, indx + O_INDX)->type) &&
|
||||
indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
|
||||
h->inp[indx] == h->inp[indx + P_INDX])
|
||||
indx += P_INDX;
|
||||
|
||||
if (B_DISSET(GET_BKEYDATA(h, indx + O_INDX)->type))
|
||||
goto notfound;
|
||||
}
|
||||
|
||||
BT_STK_ENTER(t, h, indx, lock, ret);
|
||||
return (ret);
|
||||
|
||||
notfound:
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
(void)__BT_LPUT(dbp, lock);
|
||||
ret = DB_NOTFOUND;
|
||||
|
||||
err: if (t->bt_csp > t->bt_sp) {
|
||||
BT_STK_POP(t);
|
||||
__bam_stkrel(dbp);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_stkrel --
|
||||
* Release all pages currently held in the stack.
|
||||
*
|
||||
* PUBLIC: int __bam_stkrel __P((DB *));
|
||||
*/
|
||||
int
|
||||
__bam_stkrel(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
BTREE *t;
|
||||
EPG *epg;
|
||||
|
||||
t = dbp->internal;
|
||||
for (epg = t->bt_sp; epg <= t->bt_csp; ++epg) {
|
||||
(void)memp_fput(dbp->mpf, epg->page, 0);
|
||||
(void)__BT_TLPUT(dbp, epg->lock);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_stkgrow --
|
||||
* Grow the stack.
|
||||
*
|
||||
* PUBLIC: int __bam_stkgrow __P((BTREE *));
|
||||
*/
|
||||
int
|
||||
__bam_stkgrow(t)
|
||||
BTREE *t;
|
||||
{
|
||||
EPG *p;
|
||||
size_t entries;
|
||||
|
||||
entries = t->bt_esp - t->bt_sp;
|
||||
|
||||
if ((p = (EPG *)__db_calloc(entries * 2, sizeof(EPG))) == NULL)
|
||||
return (ENOMEM);
|
||||
memcpy(p, t->bt_sp, entries * sizeof(EPG));
|
||||
if (t->bt_sp != t->bt_stack)
|
||||
FREE(t->bt_sp, entries * sizeof(EPG));
|
||||
t->bt_sp = p;
|
||||
t->bt_csp = p + entries;
|
||||
t->bt_esp = p + entries * 2;
|
||||
return (0);
|
||||
}
|
|
@ -1,950 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)bt_split.c 10.23 (Sleepycat) 5/23/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "btree.h"
|
||||
|
||||
static int __bam_page __P((DB *, EPG *, EPG *));
|
||||
static int __bam_pinsert __P((DB *, EPG *, PAGE *, PAGE *));
|
||||
static int __bam_psplit __P((DB *, EPG *, PAGE *, PAGE *, int));
|
||||
static int __bam_root __P((DB *, EPG *));
|
||||
|
||||
/*
|
||||
* __bam_split --
|
||||
* Split a page.
|
||||
*
|
||||
* PUBLIC: int __bam_split __P((DB *, void *));
|
||||
*/
|
||||
int
|
||||
__bam_split(dbp, arg)
|
||||
DB *dbp;
|
||||
void *arg;
|
||||
{
|
||||
BTREE *t;
|
||||
enum { UP, DOWN } dir;
|
||||
int exact, level, ret;
|
||||
|
||||
t = dbp->internal;
|
||||
|
||||
/*
|
||||
* The locking protocol we use to avoid deadlock to acquire locks by
|
||||
* walking down the tree, but we do it as lazily as possible, locking
|
||||
* the root only as a last resort. We expect all stack pages to have
|
||||
* been discarded before we're called; we discard all short-term locks.
|
||||
*
|
||||
* When __bam_split is first called, we know that a leaf page was too
|
||||
* full for an insert. We don't know what leaf page it was, but we
|
||||
* have the key/recno that caused the problem. We call XX_search to
|
||||
* reacquire the leaf page, but this time get both the leaf page and
|
||||
* its parent, locked. We then split the leaf page and see if the new
|
||||
* internal key will fit into the parent page. If it will, we're done.
|
||||
*
|
||||
* If it won't, we discard our current locks and repeat the process,
|
||||
* only this time acquiring the parent page and its parent, locked.
|
||||
* This process repeats until we succeed in the split, splitting the
|
||||
* root page as the final resort. The entire process then repeats,
|
||||
* as necessary, until we split a leaf page.
|
||||
*
|
||||
* XXX
|
||||
* A traditional method of speeding this up is to maintain a stack of
|
||||
* the pages traversed in the original search. You can detect if the
|
||||
* stack is correct by storing the page's LSN when it was searched and
|
||||
* comparing that LSN with the current one when it's locked during the
|
||||
* split. This would be an easy change for this code, but I have no
|
||||
* numbers that indicate it's worthwhile.
|
||||
*/
|
||||
for (dir = UP, level = LEAFLEVEL;; dir == UP ? ++level : --level) {
|
||||
/*
|
||||
* Acquire a page and its parent, locked.
|
||||
*/
|
||||
if ((ret = (dbp->type == DB_BTREE ?
|
||||
__bam_search(dbp, arg, S_WRPAIR, level, NULL, &exact) :
|
||||
__bam_rsearch(dbp,
|
||||
(db_recno_t *)arg, S_WRPAIR, level, &exact))) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Split the page. */
|
||||
ret = t->bt_csp[0].page->pgno == PGNO_ROOT ?
|
||||
__bam_root(dbp, &t->bt_csp[0]) :
|
||||
__bam_page(dbp, &t->bt_csp[-1], &t->bt_csp[0]);
|
||||
|
||||
switch (ret) {
|
||||
case 0:
|
||||
/* Once we've split the leaf page, we're done. */
|
||||
if (level == LEAFLEVEL)
|
||||
return (0);
|
||||
|
||||
/* Switch directions. */
|
||||
if (dir == UP)
|
||||
dir = DOWN;
|
||||
break;
|
||||
case DB_NEEDSPLIT:
|
||||
/*
|
||||
* It's possible to fail to split repeatedly, as other
|
||||
* threads may be modifying the tree, or the page usage
|
||||
* is sufficiently bad that we don't get enough space
|
||||
* the first time.
|
||||
*/
|
||||
if (dir == DOWN)
|
||||
dir = UP;
|
||||
break;
|
||||
default:
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_root --
|
||||
* Split the root page of a btree.
|
||||
*/
|
||||
static int
|
||||
__bam_root(dbp, cp)
|
||||
DB *dbp;
|
||||
EPG *cp;
|
||||
{
|
||||
BTREE *t;
|
||||
PAGE *lp, *rp;
|
||||
int ret;
|
||||
|
||||
t = dbp->internal;
|
||||
|
||||
/* Yeah, right. */
|
||||
if (cp->page->level >= MAXBTREELEVEL) {
|
||||
ret = ENOSPC;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Create new left and right pages for the split. */
|
||||
lp = rp = NULL;
|
||||
if ((ret = __bam_new(dbp, TYPE(cp->page), &lp)) != 0 ||
|
||||
(ret = __bam_new(dbp, TYPE(cp->page), &rp)) != 0)
|
||||
goto err;
|
||||
P_INIT(lp, dbp->pgsize, lp->pgno,
|
||||
PGNO_INVALID, ISINTERNAL(cp->page) ? PGNO_INVALID : rp->pgno,
|
||||
cp->page->level, TYPE(cp->page));
|
||||
P_INIT(rp, dbp->pgsize, rp->pgno,
|
||||
ISINTERNAL(cp->page) ? PGNO_INVALID : lp->pgno, PGNO_INVALID,
|
||||
cp->page->level, TYPE(cp->page));
|
||||
|
||||
/* Split the page. */
|
||||
if ((ret = __bam_psplit(dbp, cp, lp, rp, 1)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Log the change. */
|
||||
if (DB_LOGGING(dbp)) {
|
||||
DBT __a;
|
||||
DB_LSN __lsn;
|
||||
memset(&__a, 0, sizeof(__a));
|
||||
__a.data = cp->page;
|
||||
__a.size = dbp->pgsize;
|
||||
ZERO_LSN(__lsn);
|
||||
if ((ret = __bam_split_log(dbp->dbenv->lg_info, dbp->txn,
|
||||
&LSN(cp->page), 0, dbp->log_fileid, PGNO(lp), &LSN(lp),
|
||||
PGNO(rp), &LSN(rp), (u_int32_t)NUM_ENT(lp), 0, &__lsn,
|
||||
&__a)) != 0)
|
||||
goto err;
|
||||
LSN(lp) = LSN(rp) = LSN(cp->page);
|
||||
}
|
||||
|
||||
/* Clean up the new root page. */
|
||||
if ((ret = (dbp->type == DB_RECNO ?
|
||||
__ram_root(dbp, cp->page, lp, rp) :
|
||||
__bam_broot(dbp, cp->page, lp, rp))) != 0)
|
||||
goto err;
|
||||
|
||||
/* Success -- write the real pages back to the store. */
|
||||
(void)memp_fput(dbp->mpf, cp->page, DB_MPOOL_DIRTY);
|
||||
(void)__BT_TLPUT(dbp, cp->lock);
|
||||
(void)memp_fput(dbp->mpf, lp, DB_MPOOL_DIRTY);
|
||||
(void)memp_fput(dbp->mpf, rp, DB_MPOOL_DIRTY);
|
||||
|
||||
++t->lstat.bt_split;
|
||||
++t->lstat.bt_rootsplit;
|
||||
return (0);
|
||||
|
||||
err: if (lp != NULL)
|
||||
(void)__bam_free(dbp, lp);
|
||||
if (rp != NULL)
|
||||
(void)__bam_free(dbp, rp);
|
||||
(void)memp_fput(dbp->mpf, cp->page, 0);
|
||||
(void)__BT_TLPUT(dbp, cp->lock);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_page --
|
||||
* Split the non-root page of a btree.
|
||||
*/
|
||||
static int
|
||||
__bam_page(dbp, pp, cp)
|
||||
DB *dbp;
|
||||
EPG *pp, *cp;
|
||||
{
|
||||
DB_LOCK tplock;
|
||||
PAGE *lp, *rp, *tp;
|
||||
int ret;
|
||||
|
||||
lp = rp = tp = NULL;
|
||||
ret = -1;
|
||||
|
||||
/* Create new right page for the split. */
|
||||
if ((ret = __bam_new(dbp, TYPE(cp->page), &rp)) != 0)
|
||||
goto err;
|
||||
P_INIT(rp, dbp->pgsize, rp->pgno,
|
||||
ISINTERNAL(cp->page) ? PGNO_INVALID : cp->page->pgno,
|
||||
ISINTERNAL(cp->page) ? PGNO_INVALID : cp->page->next_pgno,
|
||||
cp->page->level, TYPE(cp->page));
|
||||
|
||||
/* Create new left page for the split. */
|
||||
if ((lp = (PAGE *)__db_malloc(dbp->pgsize)) == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
#ifdef DIAGNOSTIC
|
||||
memset(lp, 0xff, dbp->pgsize);
|
||||
#endif
|
||||
P_INIT(lp, dbp->pgsize, cp->page->pgno,
|
||||
ISINTERNAL(cp->page) ? PGNO_INVALID : cp->page->prev_pgno,
|
||||
ISINTERNAL(cp->page) ? PGNO_INVALID : rp->pgno,
|
||||
cp->page->level, TYPE(cp->page));
|
||||
ZERO_LSN(lp->lsn);
|
||||
|
||||
/*
|
||||
* Split right.
|
||||
*
|
||||
* Only the indices are sorted on the page, i.e., the key/data pairs
|
||||
* aren't, so it's simpler to copy the data from the split page onto
|
||||
* two new pages instead of copying half the data to the right page
|
||||
* and compacting the left page in place. Since the left page can't
|
||||
* change, we swap the original and the allocated left page after the
|
||||
* split.
|
||||
*/
|
||||
if ((ret = __bam_psplit(dbp, cp, lp, rp, 0)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Fix up the previous pointer of any leaf page following the split
|
||||
* page.
|
||||
*
|
||||
* !!!
|
||||
* There are interesting deadlock situations here as we write-lock a
|
||||
* page that's not in our direct ancestry. Consider a cursor walking
|
||||
* through the leaf pages, that has the previous page read-locked and
|
||||
* is waiting on a lock for the page we just split. It will deadlock
|
||||
* here. If this is a problem, we can fail in the split; it's not a
|
||||
* problem as the split will succeed after the cursor passes through
|
||||
* the page we're splitting.
|
||||
*/
|
||||
if (TYPE(cp->page) == P_LBTREE && rp->next_pgno != PGNO_INVALID) {
|
||||
if ((ret = __bam_lget(dbp,
|
||||
0, rp->next_pgno, DB_LOCK_WRITE, &tplock)) != 0)
|
||||
goto err;
|
||||
if ((ret = __bam_pget(dbp, &tp, &rp->next_pgno, 0)) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Insert the new pages into the parent page. */
|
||||
if ((ret = __bam_pinsert(dbp, pp, lp, rp)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Log the change. */
|
||||
if (DB_LOGGING(dbp)) {
|
||||
DBT __a;
|
||||
DB_LSN __lsn;
|
||||
memset(&__a, 0, sizeof(__a));
|
||||
__a.data = cp->page;
|
||||
__a.size = dbp->pgsize;
|
||||
if (tp == NULL)
|
||||
ZERO_LSN(__lsn);
|
||||
if ((ret = __bam_split_log(dbp->dbenv->lg_info, dbp->txn,
|
||||
&cp->page->lsn, 0, dbp->log_fileid, PGNO(cp->page),
|
||||
&LSN(cp->page), PGNO(rp), &LSN(rp), (u_int32_t)NUM_ENT(lp),
|
||||
tp == NULL ? 0 : PGNO(tp),
|
||||
tp == NULL ? &__lsn : &LSN(tp), &__a)) != 0)
|
||||
goto err;
|
||||
|
||||
LSN(lp) = LSN(rp) = LSN(cp->page);
|
||||
if (tp != NULL)
|
||||
LSN(tp) = LSN(cp->page);
|
||||
}
|
||||
|
||||
/* Copy the allocated page into place. */
|
||||
memcpy(cp->page, lp, LOFFSET(lp));
|
||||
memcpy((u_int8_t *)cp->page + HOFFSET(lp),
|
||||
(u_int8_t *)lp + HOFFSET(lp), dbp->pgsize - HOFFSET(lp));
|
||||
FREE(lp, dbp->pgsize);
|
||||
lp = NULL;
|
||||
|
||||
/* Finish the next-page link. */
|
||||
if (tp != NULL)
|
||||
tp->prev_pgno = rp->pgno;
|
||||
|
||||
/* Success -- write the real pages back to the store. */
|
||||
(void)memp_fput(dbp->mpf, pp->page, DB_MPOOL_DIRTY);
|
||||
(void)__BT_TLPUT(dbp, pp->lock);
|
||||
(void)memp_fput(dbp->mpf, cp->page, DB_MPOOL_DIRTY);
|
||||
(void)__BT_TLPUT(dbp, cp->lock);
|
||||
(void)memp_fput(dbp->mpf, rp, DB_MPOOL_DIRTY);
|
||||
if (tp != NULL) {
|
||||
(void)memp_fput(dbp->mpf, tp, DB_MPOOL_DIRTY);
|
||||
(void)__BT_TLPUT(dbp, tplock);
|
||||
}
|
||||
return (0);
|
||||
|
||||
err: if (lp != NULL)
|
||||
FREE(lp, dbp->pgsize);
|
||||
if (rp != NULL)
|
||||
(void)__bam_free(dbp, rp);
|
||||
if (tp != NULL) {
|
||||
(void)memp_fput(dbp->mpf, tp, 0);
|
||||
(void)__BT_TLPUT(dbp, tplock);
|
||||
}
|
||||
(void)memp_fput(dbp->mpf, pp->page, 0);
|
||||
(void)__BT_TLPUT(dbp, pp->lock);
|
||||
(void)memp_fput(dbp->mpf, cp->page, 0);
|
||||
(void)__BT_TLPUT(dbp, cp->lock);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_broot --
|
||||
* Fix up the btree root page after it has been split.
|
||||
*
|
||||
* PUBLIC: int __bam_broot __P((DB *, PAGE *, PAGE *, PAGE *));
|
||||
*/
|
||||
int
|
||||
__bam_broot(dbp, rootp, lp, rp)
|
||||
DB *dbp;
|
||||
PAGE *rootp, *lp, *rp;
|
||||
{
|
||||
BINTERNAL bi, *child_bi;
|
||||
BKEYDATA *child_bk;
|
||||
DBT hdr, data;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If the root page was a leaf page, change it into an internal page.
|
||||
* We copy the key we split on (but not the key's data, in the case of
|
||||
* a leaf page) to the new root page.
|
||||
*/
|
||||
P_INIT(rootp, dbp->pgsize,
|
||||
PGNO_ROOT, PGNO_INVALID, PGNO_INVALID, lp->level + 1, P_IBTREE);
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
|
||||
/*
|
||||
* The btree comparison code guarantees that the left-most key on any
|
||||
* level of the tree is never used, so it doesn't need to be filled in.
|
||||
*/
|
||||
memset(&bi, 0, sizeof(bi));
|
||||
bi.len = 0;
|
||||
B_TSET(bi.type, B_KEYDATA, 0);
|
||||
bi.pgno = lp->pgno;
|
||||
if (F_ISSET(dbp, DB_BT_RECNUM)) {
|
||||
bi.nrecs = __bam_total(lp);
|
||||
RE_NREC_SET(rootp, bi.nrecs);
|
||||
}
|
||||
hdr.data = &bi;
|
||||
hdr.size = SSZA(BINTERNAL, data);
|
||||
if ((ret =
|
||||
__db_pitem(dbp, rootp, 0, BINTERNAL_SIZE(0), &hdr, NULL)) != 0)
|
||||
return (ret);
|
||||
|
||||
switch (TYPE(rp)) {
|
||||
case P_IBTREE:
|
||||
/* Copy the first key of the child page onto the root page. */
|
||||
child_bi = GET_BINTERNAL(rp, 0);
|
||||
|
||||
bi.len = child_bi->len;
|
||||
B_TSET(bi.type, child_bi->type, 0);
|
||||
bi.pgno = rp->pgno;
|
||||
if (F_ISSET(dbp, DB_BT_RECNUM)) {
|
||||
bi.nrecs = __bam_total(rp);
|
||||
RE_NREC_ADJ(rootp, bi.nrecs);
|
||||
}
|
||||
hdr.data = &bi;
|
||||
hdr.size = SSZA(BINTERNAL, data);
|
||||
data.data = child_bi->data;
|
||||
data.size = child_bi->len;
|
||||
if ((ret = __db_pitem(dbp, rootp, 1,
|
||||
BINTERNAL_SIZE(child_bi->len), &hdr, &data)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Increment the overflow ref count. */
|
||||
if (B_TYPE(child_bi->type) == B_OVERFLOW)
|
||||
if ((ret = __db_ovref(dbp,
|
||||
((BOVERFLOW *)(child_bi->data))->pgno, 1)) != 0)
|
||||
return (ret);
|
||||
break;
|
||||
case P_LBTREE:
|
||||
/* Copy the first key of the child page onto the root page. */
|
||||
child_bk = GET_BKEYDATA(rp, 0);
|
||||
switch (B_TYPE(child_bk->type)) {
|
||||
case B_KEYDATA:
|
||||
bi.len = child_bk->len;
|
||||
B_TSET(bi.type, child_bk->type, 0);
|
||||
bi.pgno = rp->pgno;
|
||||
if (F_ISSET(dbp, DB_BT_RECNUM)) {
|
||||
bi.nrecs = __bam_total(rp);
|
||||
RE_NREC_ADJ(rootp, bi.nrecs);
|
||||
}
|
||||
hdr.data = &bi;
|
||||
hdr.size = SSZA(BINTERNAL, data);
|
||||
data.data = child_bk->data;
|
||||
data.size = child_bk->len;
|
||||
if ((ret = __db_pitem(dbp, rootp, 1,
|
||||
BINTERNAL_SIZE(child_bk->len), &hdr, &data)) != 0)
|
||||
return (ret);
|
||||
break;
|
||||
case B_DUPLICATE:
|
||||
case B_OVERFLOW:
|
||||
bi.len = BOVERFLOW_SIZE;
|
||||
B_TSET(bi.type, child_bk->type, 0);
|
||||
bi.pgno = rp->pgno;
|
||||
if (F_ISSET(dbp, DB_BT_RECNUM)) {
|
||||
bi.nrecs = __bam_total(rp);
|
||||
RE_NREC_ADJ(rootp, bi.nrecs);
|
||||
}
|
||||
hdr.data = &bi;
|
||||
hdr.size = SSZA(BINTERNAL, data);
|
||||
data.data = child_bk;
|
||||
data.size = BOVERFLOW_SIZE;
|
||||
if ((ret = __db_pitem(dbp, rootp, 1,
|
||||
BINTERNAL_SIZE(BOVERFLOW_SIZE), &hdr, &data)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Increment the overflow ref count. */
|
||||
if (B_TYPE(child_bk->type) == B_OVERFLOW)
|
||||
if ((ret = __db_ovref(dbp,
|
||||
((BOVERFLOW *)child_bk)->pgno, 1)) != 0)
|
||||
return (ret);
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbp, rp->pgno));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbp, rp->pgno));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __ram_root --
|
||||
* Fix up the recno root page after it has been split.
|
||||
*
|
||||
* PUBLIC: int __ram_root __P((DB *, PAGE *, PAGE *, PAGE *));
|
||||
*/
|
||||
int
|
||||
__ram_root(dbp, rootp, lp, rp)
|
||||
DB *dbp;
|
||||
PAGE *rootp, *lp, *rp;
|
||||
{
|
||||
DBT hdr;
|
||||
RINTERNAL ri;
|
||||
int ret;
|
||||
|
||||
/* Initialize the page. */
|
||||
P_INIT(rootp, dbp->pgsize,
|
||||
PGNO_ROOT, PGNO_INVALID, PGNO_INVALID, lp->level + 1, P_IRECNO);
|
||||
|
||||
/* Initialize the header. */
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.data = &ri;
|
||||
hdr.size = RINTERNAL_SIZE;
|
||||
|
||||
/* Insert the left and right keys, set the header information. */
|
||||
ri.pgno = lp->pgno;
|
||||
ri.nrecs = __bam_total(lp);
|
||||
if ((ret = __db_pitem(dbp, rootp, 0, RINTERNAL_SIZE, &hdr, NULL)) != 0)
|
||||
return (ret);
|
||||
RE_NREC_SET(rootp, ri.nrecs);
|
||||
ri.pgno = rp->pgno;
|
||||
ri.nrecs = __bam_total(rp);
|
||||
if ((ret = __db_pitem(dbp, rootp, 1, RINTERNAL_SIZE, &hdr, NULL)) != 0)
|
||||
return (ret);
|
||||
RE_NREC_ADJ(rootp, ri.nrecs);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_pinsert --
|
||||
* Insert a new key into a parent page, completing the split.
|
||||
*/
|
||||
static int
|
||||
__bam_pinsert(dbp, parent, lchild, rchild)
|
||||
DB *dbp;
|
||||
EPG *parent;
|
||||
PAGE *lchild, *rchild;
|
||||
{
|
||||
BINTERNAL bi, *child_bi;
|
||||
BKEYDATA *child_bk, *tmp_bk;
|
||||
BTREE *t;
|
||||
DBT a, b, hdr, data;
|
||||
PAGE *ppage;
|
||||
RINTERNAL ri;
|
||||
db_indx_t off;
|
||||
db_recno_t nrecs;
|
||||
u_int32_t n, nbytes, nksize;
|
||||
int ret;
|
||||
|
||||
t = dbp->internal;
|
||||
ppage = parent->page;
|
||||
|
||||
/* If handling record numbers, count records split to the right page. */
|
||||
nrecs = dbp->type == DB_RECNO || F_ISSET(dbp, DB_BT_RECNUM) ?
|
||||
__bam_total(rchild) : 0;
|
||||
|
||||
/*
|
||||
* Now we insert the new page's first key into the parent page, which
|
||||
* completes the split. The parent points to a PAGE and a page index
|
||||
* offset, where the new key goes ONE AFTER the index, because we split
|
||||
* to the right.
|
||||
*
|
||||
* XXX
|
||||
* Some btree algorithms replace the key for the old page as well as
|
||||
* the new page. We don't, as there's no reason to believe that the
|
||||
* first key on the old page is any better than the key we have, and,
|
||||
* in the case of a key being placed at index 0 causing the split, the
|
||||
* key is unavailable.
|
||||
*/
|
||||
off = parent->indx + O_INDX;
|
||||
|
||||
/*
|
||||
* Calculate the space needed on the parent page.
|
||||
*
|
||||
* Prefix trees: space hack used when inserting into BINTERNAL pages.
|
||||
* Retain only what's needed to distinguish between the new entry and
|
||||
* the LAST entry on the page to its left. If the keys compare equal,
|
||||
* retain the entire key. We ignore overflow keys, and the entire key
|
||||
* must be retained for the next-to-leftmost key on the leftmost page
|
||||
* of each level, or the search will fail. Applicable ONLY to internal
|
||||
* pages that have leaf pages as children. Further reduction of the
|
||||
* key between pairs of internal pages loses too much information.
|
||||
*/
|
||||
switch (TYPE(rchild)) {
|
||||
case P_IBTREE:
|
||||
child_bi = GET_BINTERNAL(rchild, 0);
|
||||
nbytes = BINTERNAL_PSIZE(child_bi->len);
|
||||
|
||||
if (P_FREESPACE(ppage) < nbytes)
|
||||
return (DB_NEEDSPLIT);
|
||||
|
||||
/* Add a new record for the right page. */
|
||||
memset(&bi, 0, sizeof(bi));
|
||||
bi.len = child_bi->len;
|
||||
B_TSET(bi.type, child_bi->type, 0);
|
||||
bi.pgno = rchild->pgno;
|
||||
bi.nrecs = nrecs;
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.data = &bi;
|
||||
hdr.size = SSZA(BINTERNAL, data);
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.data = child_bi->data;
|
||||
data.size = child_bi->len;
|
||||
if ((ret = __db_pitem(dbp, ppage, off,
|
||||
BINTERNAL_SIZE(child_bi->len), &hdr, &data)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Increment the overflow ref count. */
|
||||
if (B_TYPE(child_bi->type) == B_OVERFLOW)
|
||||
if ((ret = __db_ovref(dbp,
|
||||
((BOVERFLOW *)(child_bi->data))->pgno, 1)) != 0)
|
||||
return (ret);
|
||||
break;
|
||||
case P_LBTREE:
|
||||
child_bk = GET_BKEYDATA(rchild, 0);
|
||||
switch (B_TYPE(child_bk->type)) {
|
||||
case B_KEYDATA:
|
||||
nbytes = BINTERNAL_PSIZE(child_bk->len);
|
||||
nksize = child_bk->len;
|
||||
if (t->bt_prefix == NULL)
|
||||
goto noprefix;
|
||||
if (ppage->prev_pgno == PGNO_INVALID && off <= 1)
|
||||
goto noprefix;
|
||||
tmp_bk = GET_BKEYDATA(lchild, NUM_ENT(lchild) - P_INDX);
|
||||
if (B_TYPE(tmp_bk->type) != B_KEYDATA)
|
||||
goto noprefix;
|
||||
memset(&a, 0, sizeof(a));
|
||||
a.size = tmp_bk->len;
|
||||
a.data = tmp_bk->data;
|
||||
memset(&b, 0, sizeof(b));
|
||||
b.size = child_bk->len;
|
||||
b.data = child_bk->data;
|
||||
nksize = t->bt_prefix(&a, &b);
|
||||
if ((n = BINTERNAL_PSIZE(nksize)) < nbytes) {
|
||||
t->lstat.bt_pfxsaved += nbytes - n;
|
||||
nbytes = n;
|
||||
} else
|
||||
noprefix: nksize = child_bk->len;
|
||||
|
||||
if (P_FREESPACE(ppage) < nbytes)
|
||||
return (DB_NEEDSPLIT);
|
||||
|
||||
memset(&bi, 0, sizeof(bi));
|
||||
bi.len = nksize;
|
||||
B_TSET(bi.type, child_bk->type, 0);
|
||||
bi.pgno = rchild->pgno;
|
||||
bi.nrecs = nrecs;
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.data = &bi;
|
||||
hdr.size = SSZA(BINTERNAL, data);
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.data = child_bk->data;
|
||||
data.size = nksize;
|
||||
if ((ret = __db_pitem(dbp, ppage, off,
|
||||
BINTERNAL_SIZE(nksize), &hdr, &data)) != 0)
|
||||
return (ret);
|
||||
break;
|
||||
case B_DUPLICATE:
|
||||
case B_OVERFLOW:
|
||||
nbytes = BINTERNAL_PSIZE(BOVERFLOW_SIZE);
|
||||
|
||||
if (P_FREESPACE(ppage) < nbytes)
|
||||
return (DB_NEEDSPLIT);
|
||||
|
||||
memset(&bi, 0, sizeof(bi));
|
||||
bi.len = BOVERFLOW_SIZE;
|
||||
B_TSET(bi.type, child_bk->type, 0);
|
||||
bi.pgno = rchild->pgno;
|
||||
bi.nrecs = nrecs;
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.data = &bi;
|
||||
hdr.size = SSZA(BINTERNAL, data);
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.data = child_bk;
|
||||
data.size = BOVERFLOW_SIZE;
|
||||
if ((ret = __db_pitem(dbp, ppage, off,
|
||||
BINTERNAL_SIZE(BOVERFLOW_SIZE), &hdr, &data)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Increment the overflow ref count. */
|
||||
if (B_TYPE(child_bk->type) == B_OVERFLOW)
|
||||
if ((ret = __db_ovref(dbp,
|
||||
((BOVERFLOW *)child_bk)->pgno, 1)) != 0)
|
||||
return (ret);
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbp, rchild->pgno));
|
||||
}
|
||||
break;
|
||||
case P_IRECNO:
|
||||
case P_LRECNO:
|
||||
nbytes = RINTERNAL_PSIZE;
|
||||
|
||||
if (P_FREESPACE(ppage) < nbytes)
|
||||
return (DB_NEEDSPLIT);
|
||||
|
||||
/* Add a new record for the right page. */
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.data = &ri;
|
||||
hdr.size = RINTERNAL_SIZE;
|
||||
ri.pgno = rchild->pgno;
|
||||
ri.nrecs = nrecs;
|
||||
if ((ret = __db_pitem(dbp,
|
||||
ppage, off, RINTERNAL_SIZE, &hdr, NULL)) != 0)
|
||||
return (ret);
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbp, rchild->pgno));
|
||||
}
|
||||
|
||||
/* Adjust the parent page's left page record count. */
|
||||
if (dbp->type == DB_RECNO || F_ISSET(dbp, DB_BT_RECNUM)) {
|
||||
/* Log the change. */
|
||||
if (DB_LOGGING(dbp) &&
|
||||
(ret = __bam_cadjust_log(dbp->dbenv->lg_info,
|
||||
dbp->txn, &LSN(ppage), 0, dbp->log_fileid,
|
||||
PGNO(ppage), &LSN(ppage), (u_int32_t)parent->indx,
|
||||
-(int32_t)nrecs, (int32_t)0)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Update the left page count. */
|
||||
if (dbp->type == DB_RECNO)
|
||||
GET_RINTERNAL(ppage, parent->indx)->nrecs -= nrecs;
|
||||
else
|
||||
GET_BINTERNAL(ppage, parent->indx)->nrecs -= nrecs;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_psplit --
|
||||
* Do the real work of splitting the page.
|
||||
*/
|
||||
static int
|
||||
__bam_psplit(dbp, cp, lp, rp, cleft)
|
||||
DB *dbp;
|
||||
EPG *cp;
|
||||
PAGE *lp, *rp;
|
||||
int cleft;
|
||||
{
|
||||
BTREE *t;
|
||||
PAGE *pp;
|
||||
db_indx_t half, nbytes, off, splitp, top;
|
||||
int adjust, cnt, isbigkey, ret;
|
||||
|
||||
t = dbp->internal;
|
||||
pp = cp->page;
|
||||
adjust = TYPE(pp) == P_LBTREE ? P_INDX : O_INDX;
|
||||
|
||||
/*
|
||||
* If we're splitting the first (last) page on a level because we're
|
||||
* inserting (appending) a key to it, it's likely that the data is
|
||||
* sorted. Moving a single item to the new page is less work and can
|
||||
* push the fill factor higher than normal. If we're wrong it's not
|
||||
* a big deal, we'll just do the split the right way next time.
|
||||
*/
|
||||
off = 0;
|
||||
if (NEXT_PGNO(pp) == PGNO_INVALID &&
|
||||
((ISINTERNAL(pp) && cp->indx == NUM_ENT(cp->page) - 1) ||
|
||||
(!ISINTERNAL(pp) && cp->indx == NUM_ENT(cp->page))))
|
||||
off = NUM_ENT(cp->page) - adjust;
|
||||
else if (PREV_PGNO(pp) == PGNO_INVALID && cp->indx == 0)
|
||||
off = adjust;
|
||||
|
||||
++t->lstat.bt_split;
|
||||
if (off != 0) {
|
||||
++t->lstat.bt_fastsplit;
|
||||
goto sort;
|
||||
}
|
||||
|
||||
/*
|
||||
* Split the data to the left and right pages. Try not to split on
|
||||
* an overflow key. (Overflow keys on internal pages will slow down
|
||||
* searches.) Refuse to split in the middle of a set of duplicates.
|
||||
*
|
||||
* First, find the optimum place to split.
|
||||
*
|
||||
* It's possible to try and split past the last record on the page if
|
||||
* there's a very large record at the end of the page. Make sure this
|
||||
* doesn't happen by bounding the check at the next-to-last entry on
|
||||
* the page.
|
||||
*
|
||||
* Note, we try and split half the data present on the page. This is
|
||||
* because another process may have already split the page and left
|
||||
* it half empty. We don't try and skip the split -- we don't know
|
||||
* how much space we're going to need on the page, and we may need up
|
||||
* to half the page for a big item, so there's no easy test to decide
|
||||
* if we need to split or not. Besides, if two threads are inserting
|
||||
* data into the same place in the database, we're probably going to
|
||||
* need more space soon anyway.
|
||||
*/
|
||||
top = NUM_ENT(pp) - adjust;
|
||||
half = (dbp->pgsize - HOFFSET(pp)) / 2;
|
||||
for (nbytes = 0, off = 0; off < top && nbytes < half; ++off)
|
||||
switch (TYPE(pp)) {
|
||||
case P_IBTREE:
|
||||
if (B_TYPE(GET_BINTERNAL(pp, off)->type) == B_KEYDATA)
|
||||
nbytes +=
|
||||
BINTERNAL_SIZE(GET_BINTERNAL(pp, off)->len);
|
||||
else
|
||||
nbytes += BINTERNAL_SIZE(BOVERFLOW_SIZE);
|
||||
break;
|
||||
case P_LBTREE:
|
||||
if (B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA)
|
||||
nbytes +=
|
||||
BKEYDATA_SIZE(GET_BKEYDATA(pp, off)->len);
|
||||
else
|
||||
nbytes += BOVERFLOW_SIZE;
|
||||
|
||||
++off;
|
||||
if (B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA)
|
||||
nbytes +=
|
||||
BKEYDATA_SIZE(GET_BKEYDATA(pp, off)->len);
|
||||
else
|
||||
nbytes += BOVERFLOW_SIZE;
|
||||
break;
|
||||
case P_IRECNO:
|
||||
nbytes += RINTERNAL_SIZE;
|
||||
break;
|
||||
case P_LRECNO:
|
||||
nbytes += BKEYDATA_SIZE(GET_BKEYDATA(pp, off)->len);
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbp, pp->pgno));
|
||||
}
|
||||
sort: splitp = off;
|
||||
|
||||
/*
|
||||
* Splitp is either at or just past the optimum split point. If
|
||||
* it's a big key, try and find something close by that's not.
|
||||
*/
|
||||
if (TYPE(pp) == P_IBTREE)
|
||||
isbigkey = B_TYPE(GET_BINTERNAL(pp, off)->type) != B_KEYDATA;
|
||||
else if (TYPE(pp) == P_LBTREE)
|
||||
isbigkey = B_TYPE(GET_BKEYDATA(pp, off)->type) != B_KEYDATA;
|
||||
else
|
||||
isbigkey = 0;
|
||||
if (isbigkey)
|
||||
for (cnt = 1; cnt <= 3; ++cnt) {
|
||||
off = splitp + cnt * adjust;
|
||||
if (off < (db_indx_t)NUM_ENT(pp) &&
|
||||
((TYPE(pp) == P_IBTREE &&
|
||||
B_TYPE(GET_BINTERNAL(pp,off)->type) == B_KEYDATA) ||
|
||||
B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA)) {
|
||||
splitp = off;
|
||||
break;
|
||||
}
|
||||
if (splitp <= (db_indx_t)(cnt * adjust))
|
||||
continue;
|
||||
off = splitp - cnt * adjust;
|
||||
if (TYPE(pp) == P_IBTREE ?
|
||||
B_TYPE(GET_BINTERNAL(pp, off)->type) == B_KEYDATA :
|
||||
B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA) {
|
||||
splitp = off;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We can't split in the middle a set of duplicates. We know that
|
||||
* no duplicate set can take up more than about 25% of the page,
|
||||
* because that's the point where we push it off onto a duplicate
|
||||
* page set. So, this loop can't be unbounded.
|
||||
*/
|
||||
if (F_ISSET(dbp, DB_AM_DUP) && TYPE(pp) == P_LBTREE &&
|
||||
pp->inp[splitp] == pp->inp[splitp - adjust])
|
||||
for (cnt = 1;; ++cnt) {
|
||||
off = splitp + cnt * adjust;
|
||||
if (off < NUM_ENT(pp) &&
|
||||
pp->inp[splitp] != pp->inp[off]) {
|
||||
splitp = off;
|
||||
break;
|
||||
}
|
||||
if (splitp <= (db_indx_t)(cnt * adjust))
|
||||
continue;
|
||||
off = splitp - cnt * adjust;
|
||||
if (pp->inp[splitp] != pp->inp[off]) {
|
||||
splitp = off + adjust;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* We're going to split at splitp. */
|
||||
if ((ret = __bam_copy(dbp, pp, lp, 0, splitp)) != 0)
|
||||
return (ret);
|
||||
if ((ret = __bam_copy(dbp, pp, rp, splitp, NUM_ENT(pp))) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Adjust the cursors. */
|
||||
__bam_ca_split(dbp, pp->pgno, lp->pgno, rp->pgno, splitp, cleft);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_copy --
|
||||
* Copy a set of records from one page to another.
|
||||
*
|
||||
* PUBLIC: int __bam_copy __P((DB *, PAGE *, PAGE *, u_int32_t, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__bam_copy(dbp, pp, cp, nxt, stop)
|
||||
DB *dbp;
|
||||
PAGE *pp, *cp;
|
||||
u_int32_t nxt, stop;
|
||||
{
|
||||
db_indx_t nbytes, off;
|
||||
|
||||
/*
|
||||
* Copy the rest of the data to the right page. Nxt is the next
|
||||
* offset placed on the target page.
|
||||
*/
|
||||
for (off = 0; nxt < stop; ++nxt, ++NUM_ENT(cp), ++off) {
|
||||
switch (TYPE(pp)) {
|
||||
case P_IBTREE:
|
||||
if (B_TYPE(GET_BINTERNAL(pp, nxt)->type) == B_KEYDATA)
|
||||
nbytes =
|
||||
BINTERNAL_SIZE(GET_BINTERNAL(pp, nxt)->len);
|
||||
else
|
||||
nbytes = BINTERNAL_SIZE(BOVERFLOW_SIZE);
|
||||
break;
|
||||
case P_LBTREE:
|
||||
/*
|
||||
* If we're on a key and it's a duplicate, just copy
|
||||
* the offset.
|
||||
*/
|
||||
if (off != 0 && (nxt % P_INDX) == 0 &&
|
||||
pp->inp[nxt] == pp->inp[nxt - P_INDX]) {
|
||||
cp->inp[off] = cp->inp[off - P_INDX];
|
||||
continue;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case P_LRECNO:
|
||||
if (B_TYPE(GET_BKEYDATA(pp, nxt)->type) == B_KEYDATA)
|
||||
nbytes =
|
||||
BKEYDATA_SIZE(GET_BKEYDATA(pp, nxt)->len);
|
||||
else
|
||||
nbytes = BOVERFLOW_SIZE;
|
||||
break;
|
||||
case P_IRECNO:
|
||||
nbytes = RINTERNAL_SIZE;
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbp, pp->pgno));
|
||||
}
|
||||
cp->inp[off] = HOFFSET(cp) -= nbytes;
|
||||
memcpy(P_ENTRY(cp, off), P_ENTRY(pp, nxt), nbytes);
|
||||
}
|
||||
return (0);
|
||||
}
|
|
@ -1,254 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)bt_stat.c 10.17 (Sleepycat) 4/26/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "btree.h"
|
||||
|
||||
static void __bam_add_rstat __P((DB_BTREE_LSTAT *, DB_BTREE_STAT *));
|
||||
|
||||
/*
|
||||
* __bam_stat --
|
||||
* Gather/print the btree statistics
|
||||
*
|
||||
* PUBLIC: int __bam_stat __P((DB *, void *, void *(*)(size_t), u_int32_t));
|
||||
*/
|
||||
int
|
||||
__bam_stat(argdbp, spp, db_malloc, flags)
|
||||
DB *argdbp;
|
||||
void *spp;
|
||||
void *(*db_malloc) __P((size_t));
|
||||
u_int32_t flags;
|
||||
{
|
||||
BTMETA *meta;
|
||||
BTREE *t;
|
||||
DB *dbp;
|
||||
DB_BTREE_STAT *sp;
|
||||
DB_LOCK lock;
|
||||
PAGE *h;
|
||||
db_pgno_t lastpgno, pgno;
|
||||
int ret;
|
||||
|
||||
DEBUG_LWRITE(argdbp, NULL, "bam_stat", NULL, NULL, flags);
|
||||
|
||||
/* Check for invalid flags. */
|
||||
if ((ret = __db_statchk(argdbp, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
if (spp == NULL)
|
||||
return (0);
|
||||
|
||||
GETHANDLE(argdbp, NULL, &dbp, ret);
|
||||
t = dbp->internal;
|
||||
|
||||
/* Allocate and clear the structure. */
|
||||
if ((sp = db_malloc == NULL ?
|
||||
(DB_BTREE_STAT *)__db_malloc(sizeof(*sp)) :
|
||||
(DB_BTREE_STAT *)db_malloc(sizeof(*sp))) == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
memset(sp, 0, sizeof(*sp));
|
||||
|
||||
/* If the app just wants the record count, make it fast. */
|
||||
if (LF_ISSET(DB_RECORDCOUNT)) {
|
||||
pgno = PGNO_ROOT;
|
||||
if ((ret = __bam_lget(dbp, 0, pgno, DB_LOCK_READ, &lock)) != 0)
|
||||
goto err;
|
||||
if ((ret = __bam_pget(dbp, (PAGE **)&h, &pgno, 0)) != 0)
|
||||
goto err;
|
||||
|
||||
sp->bt_nrecs = RE_NREC(h);
|
||||
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
(void)__BT_LPUT(dbp, lock);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Get the meta-data page. */
|
||||
pgno = PGNO_METADATA;
|
||||
if ((ret = __bam_lget(dbp, 0, pgno, DB_LOCK_READ, &lock)) != 0)
|
||||
goto err;
|
||||
if ((ret = __bam_pget(dbp, (PAGE **)&meta, &pgno, 0)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Translate the metadata flags. */
|
||||
if (F_ISSET(meta, BTM_DUP))
|
||||
sp->bt_flags |= DB_DUP;
|
||||
if (F_ISSET(meta, BTM_FIXEDLEN))
|
||||
sp->bt_flags |= DB_FIXEDLEN;
|
||||
if (F_ISSET(meta, BTM_RECNUM))
|
||||
sp->bt_flags |= DB_RECNUM;
|
||||
if (F_ISSET(meta, BTM_RENUMBER))
|
||||
sp->bt_flags |= DB_RENUMBER;
|
||||
|
||||
/* Get the remaining metadata fields. */
|
||||
sp->bt_minkey = meta->minkey;
|
||||
sp->bt_maxkey = meta->maxkey;
|
||||
sp->bt_re_len = meta->re_len;
|
||||
sp->bt_re_pad = meta->re_pad;
|
||||
sp->bt_magic = meta->magic;
|
||||
sp->bt_version = meta->version;
|
||||
|
||||
/* Get the page size from the DB. */
|
||||
sp->bt_pagesize = dbp->pgsize;
|
||||
|
||||
/* Initialize counters with the meta-data page information. */
|
||||
__bam_add_rstat(&meta->stat, sp);
|
||||
|
||||
/*
|
||||
* Add in the local information from this handle.
|
||||
*
|
||||
* !!!
|
||||
* This is a bit odd, but it gets us closer to the truth.
|
||||
*/
|
||||
__bam_add_rstat(&t->lstat, sp);
|
||||
|
||||
/* Walk the free list, counting pages. */
|
||||
for (sp->bt_free = 0, pgno = meta->free; pgno != PGNO_INVALID;) {
|
||||
++sp->bt_free;
|
||||
|
||||
if ((ret = __bam_pget(dbp, &h, &pgno, 0)) != 0) {
|
||||
(void)memp_fput(dbp->mpf, meta, 0);
|
||||
(void)__BT_TLPUT(dbp, lock);
|
||||
goto err;
|
||||
}
|
||||
pgno = h->next_pgno;
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
}
|
||||
|
||||
/* Discard the meta-data page. */
|
||||
(void)memp_fput(dbp->mpf, meta, 0);
|
||||
(void)__BT_TLPUT(dbp, lock);
|
||||
|
||||
/* Determine the last page of the database. */
|
||||
if ((ret = memp_fget(dbp->mpf, &lastpgno, DB_MPOOL_LAST, &h)) != 0)
|
||||
goto err;
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
|
||||
/* Get the root page. */
|
||||
pgno = PGNO_ROOT;
|
||||
if ((ret = __bam_lget(dbp, 0, PGNO_ROOT, DB_LOCK_READ, &lock)) != 0)
|
||||
goto err;
|
||||
if ((ret = __bam_pget(dbp, &h, &pgno, 0)) != 0) {
|
||||
(void)__BT_LPUT(dbp, lock);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get the levels from the root page. */
|
||||
sp->bt_levels = h->level;
|
||||
|
||||
/* Walk the page list, counting things. */
|
||||
for (;;) {
|
||||
switch (TYPE(h)) {
|
||||
case P_INVALID:
|
||||
break;
|
||||
case P_IBTREE:
|
||||
case P_IRECNO:
|
||||
++sp->bt_int_pg;
|
||||
sp->bt_int_pgfree += HOFFSET(h) - LOFFSET(h);
|
||||
break;
|
||||
case P_LBTREE:
|
||||
++sp->bt_leaf_pg;
|
||||
sp->bt_leaf_pgfree += HOFFSET(h) - LOFFSET(h);
|
||||
sp->bt_nrecs += NUM_ENT(h) / P_INDX;
|
||||
break;
|
||||
case P_LRECNO:
|
||||
++sp->bt_leaf_pg;
|
||||
sp->bt_leaf_pgfree += HOFFSET(h) - LOFFSET(h);
|
||||
sp->bt_nrecs += NUM_ENT(h);
|
||||
break;
|
||||
case P_DUPLICATE:
|
||||
++sp->bt_dup_pg;
|
||||
/* XXX MARGO: sp->bt_dup_pgfree; */
|
||||
break;
|
||||
case P_OVERFLOW:
|
||||
++sp->bt_over_pg;
|
||||
/* XXX MARGO: sp->bt_over_pgfree; */
|
||||
break;
|
||||
default:
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
(void)__BT_LPUT(dbp, lock);
|
||||
return (__db_pgfmt(dbp, pgno));
|
||||
}
|
||||
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
(void)__BT_LPUT(dbp, lock);
|
||||
|
||||
if (++pgno > lastpgno)
|
||||
break;
|
||||
if (__bam_lget(dbp, 0, pgno, DB_LOCK_READ, &lock))
|
||||
break;
|
||||
if (memp_fget(dbp->mpf, &pgno, 0, &h) != 0) {
|
||||
(void)__BT_LPUT(dbp, lock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done: *(DB_BTREE_STAT **)spp = sp;
|
||||
ret = 0;
|
||||
|
||||
err: PUTHANDLE(dbp);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_add_mstat --
|
||||
* Add the local statistics to the meta-data page statistics.
|
||||
*
|
||||
* PUBLIC: void __bam_add_mstat __P((DB_BTREE_LSTAT *, DB_BTREE_LSTAT *));
|
||||
*/
|
||||
void
|
||||
__bam_add_mstat(from, to)
|
||||
DB_BTREE_LSTAT *from;
|
||||
DB_BTREE_LSTAT *to;
|
||||
{
|
||||
to->bt_freed += from->bt_freed;
|
||||
to->bt_pfxsaved += from->bt_pfxsaved;
|
||||
to->bt_split += from->bt_split;
|
||||
to->bt_rootsplit += from->bt_rootsplit;
|
||||
to->bt_fastsplit += from->bt_fastsplit;
|
||||
to->bt_added += from->bt_added;
|
||||
to->bt_deleted += from->bt_deleted;
|
||||
to->bt_get += from->bt_get;
|
||||
to->bt_cache_hit += from->bt_cache_hit;
|
||||
to->bt_cache_miss += from->bt_cache_miss;
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_add_rstat --
|
||||
* Add the local statistics to the returned statistics.
|
||||
*/
|
||||
static void
|
||||
__bam_add_rstat(from, to)
|
||||
DB_BTREE_LSTAT *from;
|
||||
DB_BTREE_STAT *to;
|
||||
{
|
||||
to->bt_freed += from->bt_freed;
|
||||
to->bt_pfxsaved += from->bt_pfxsaved;
|
||||
to->bt_split += from->bt_split;
|
||||
to->bt_rootsplit += from->bt_rootsplit;
|
||||
to->bt_fastsplit += from->bt_fastsplit;
|
||||
to->bt_added += from->bt_added;
|
||||
to->bt_deleted += from->bt_deleted;
|
||||
to->bt_get += from->bt_get;
|
||||
to->bt_cache_hit += from->bt_cache_hit;
|
||||
to->bt_cache_miss += from->bt_cache_miss;
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* @(#)btree.src 10.8 (Sleepycat) 4/10/98
|
||||
*/
|
||||
|
||||
PREFIX bam
|
||||
|
||||
/*
|
||||
* BTREE-pg_alloc: used to record allocating a new page.
|
||||
*
|
||||
* meta_lsn: the meta-data page's original lsn.
|
||||
* page_lsn: the allocated page's original lsn.
|
||||
* pgno: the page allocated.
|
||||
* next: the next page on the free list.
|
||||
*/
|
||||
BEGIN pg_alloc
|
||||
ARG fileid u_int32_t lu
|
||||
POINTER meta_lsn DB_LSN * lu
|
||||
POINTER page_lsn DB_LSN * lu
|
||||
ARG pgno db_pgno_t lu
|
||||
ARG ptype u_int32_t lu
|
||||
ARG next db_pgno_t lu
|
||||
END
|
||||
|
||||
/*
|
||||
* BTREE-pg_free: used to record freeing a page.
|
||||
*
|
||||
* pgno: the page being freed.
|
||||
* meta_lsn: the meta-data page's original lsn.
|
||||
* header: the header from the free'd page.
|
||||
* next: the previous next pointer on the metadata page.
|
||||
*/
|
||||
BEGIN pg_free
|
||||
ARG fileid u_int32_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER meta_lsn DB_LSN * lu
|
||||
DBT header DBT s
|
||||
ARG next db_pgno_t lu
|
||||
END
|
||||
|
||||
/*
|
||||
* BTREE-split: used to log a page split.
|
||||
*
|
||||
* left: the page number for the low-order contents.
|
||||
* llsn: the left page's original LSN.
|
||||
* right: the page number for the high-order contents.
|
||||
* rlsn: the right page's original LSN.
|
||||
* indx: the number of entries that went to the left page.
|
||||
* npgno: the next page number
|
||||
* nlsn: the next page's original LSN (or 0 if no next page).
|
||||
* pg: the split page's contents before the split.
|
||||
*/
|
||||
BEGIN split
|
||||
ARG fileid u_int32_t lu
|
||||
ARG left db_pgno_t lu
|
||||
POINTER llsn DB_LSN * lu
|
||||
ARG right db_pgno_t lu
|
||||
POINTER rlsn DB_LSN * lu
|
||||
ARG indx u_int32_t lu
|
||||
ARG npgno db_pgno_t lu
|
||||
POINTER nlsn DB_LSN * lu
|
||||
DBT pg DBT s
|
||||
END
|
||||
|
||||
/*
|
||||
* BTREE-rsplit: used to log a reverse-split
|
||||
*
|
||||
* pgno: the page number of the page copied over the root.
|
||||
* pgdbt: the page being copied on the root page.
|
||||
* nrec: the tree's record count.
|
||||
* rootent: last entry on the root page.
|
||||
* rootlsn: the root page's original lsn.
|
||||
*/
|
||||
BEGIN rsplit
|
||||
ARG fileid u_int32_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
DBT pgdbt DBT s
|
||||
ARG nrec db_pgno_t lu
|
||||
DBT rootent DBT s
|
||||
POINTER rootlsn DB_LSN * lu
|
||||
END
|
||||
|
||||
/*
|
||||
* BTREE-adj: used to log the adjustment of an index.
|
||||
*
|
||||
* pgno: the page modified.
|
||||
* lsn: the page's original lsn.
|
||||
* indx: the index adjusted.
|
||||
* indx_copy: the index to copy if inserting.
|
||||
* is_insert: 0 if a delete, 1 if an insert.
|
||||
*/
|
||||
BEGIN adj
|
||||
ARG fileid u_int32_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER lsn DB_LSN * lu
|
||||
ARG indx u_int32_t lu
|
||||
ARG indx_copy u_int32_t lu
|
||||
ARG is_insert u_int32_t lu
|
||||
END
|
||||
|
||||
/*
|
||||
* BTREE-cadjust: used to adjust the count change in an internal page.
|
||||
*
|
||||
* pgno: the page modified.
|
||||
* lsn: the page's original lsn.
|
||||
* indx: the index to be adjusted.
|
||||
* adjust: the signed adjustment.
|
||||
* total: if the total tree entries count should be adjusted
|
||||
*/
|
||||
BEGIN cadjust
|
||||
ARG fileid u_int32_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER lsn DB_LSN * lu
|
||||
ARG indx u_int32_t lu
|
||||
ARG adjust int32_t ld
|
||||
ARG total int32_t ld
|
||||
END
|
||||
|
||||
/*
|
||||
* BTREE-cdel: used to log the intent-to-delete of a cursor record.
|
||||
*
|
||||
* pgno: the page modified.
|
||||
* lsn: the page's original lsn.
|
||||
* indx: the index to be deleted.
|
||||
*/
|
||||
BEGIN cdel
|
||||
ARG fileid u_int32_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER lsn DB_LSN * lu
|
||||
ARG indx u_int32_t lu
|
||||
END
|
||||
|
||||
/*
|
||||
* BTREE-repl: used to log the replacement of an item.
|
||||
*
|
||||
* pgno: the page modified.
|
||||
* lsn: the page's original lsn.
|
||||
* orig: the original data.
|
||||
* new: the replacement data.
|
||||
* duplicate: the prefix of the replacement that matches the original.
|
||||
*/
|
||||
BEGIN repl
|
||||
ARG fileid u_int32_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER lsn DB_LSN * lu
|
||||
ARG indx u_int32_t lu
|
||||
ARG isdeleted u_int32_t lu
|
||||
DBT orig DBT s
|
||||
DBT repl DBT s
|
||||
ARG prefix u_int32_t lu
|
||||
ARG suffix u_int32_t lu
|
||||
END
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,242 +0,0 @@
|
|||
# @(#)README 8.24 (Sleepycat) 6/2/98
|
||||
|
||||
This is a directory for building UNIX versions of DB.
|
||||
|
||||
To build the default configuration of DB, simply enter the two commands:
|
||||
|
||||
../dist/configure
|
||||
make
|
||||
|
||||
in this directory. This will build the DB library. To install the DB
|
||||
library, enter:
|
||||
|
||||
make install
|
||||
|
||||
See below for specific information on what files are installed and in what
|
||||
directories, and how to configure installation on a per-system basis.
|
||||
|
||||
If you want to rebuild DB, enter:
|
||||
|
||||
make clean
|
||||
make
|
||||
|
||||
If you change your mind about how DB is configured, you must start from
|
||||
scratch by entering:
|
||||
|
||||
make distclean
|
||||
../dist/configure
|
||||
make
|
||||
|
||||
To build multiple UNIX versions of DB in the same source tree, create a
|
||||
new directory at the same level as build.unix, and then configure and build.
|
||||
|
||||
mkdir build.bsdos3.0
|
||||
cd build.bsdos3.0
|
||||
../dist/configure
|
||||
make
|
||||
|
||||
If you have trouble with any of these commands, please send email to the
|
||||
addresses found in the ../README file. In that email, please provide a
|
||||
complete copy of the commands that you entered and their output.
|
||||
|
||||
=-=-=-=-=-=-=
|
||||
DB'S OPTIONS TO THE CONFIGURE PROGRAM
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
There are many options that you can enter to the configuration program,
|
||||
only a few of which are DB specific. To see a complete list of the
|
||||
options, enter "../dist/configure --help".
|
||||
|
||||
The DB specific options are as follows:
|
||||
|
||||
--enable-cxx:
|
||||
If you want to include C++ interfaces in the library, enter:
|
||||
|
||||
--enable-cxx
|
||||
|
||||
as an argument to configure.
|
||||
|
||||
--enable-debug:
|
||||
If you want to build DB with -g as a compiler flag and with DEBUG
|
||||
#defined during compilation, enter:
|
||||
|
||||
--enable-debug
|
||||
|
||||
as an argument to configure. This will create DB with debugging
|
||||
symbols, as well as load various routines that can be called from
|
||||
a debugger to display pages, cursor queues and so forth. This
|
||||
flag should probably not be defined when configuring to build
|
||||
production binaries, although there shouldn't be any significant
|
||||
performance degradation.
|
||||
|
||||
--enable-diagnostic:
|
||||
If you want to build DB with debugging run-time sanity checks and
|
||||
with DIAGNOSTIC #defined during compilation, enter:
|
||||
|
||||
--enable-diagnostic
|
||||
|
||||
as an argument to configure. This will cause a number of special
|
||||
checks to be performed when DB is running. This flag should NOT
|
||||
be defined when configuring to build production binaries, as you
|
||||
will lose a significant amount of performance.
|
||||
|
||||
--enable-compat185
|
||||
If you want to compile or load DB 1.85 applications against the
|
||||
DB 2.0 library, enter:
|
||||
|
||||
--enable-compat185
|
||||
|
||||
as an argument to configure. This will include DB 1.85 API
|
||||
compatibility code in the library.
|
||||
|
||||
--enable-dump185:
|
||||
If you need to convert DB 1.85 (or earlier) databases to DB 2.0
|
||||
databases, enter:
|
||||
|
||||
--enable-dump185
|
||||
|
||||
as an argument to configure. This will build the dump_185(1)
|
||||
utility. This utility will dump DB 1.85 databases in a format
|
||||
readable by the db_load(1) utility. For more information, see
|
||||
db_dump(1) and db_load(1).
|
||||
|
||||
The system libraries with which you are loading the dump_185(1)
|
||||
utility MUST already contain the DB 1.85 library routines for this
|
||||
to work, as the DB distribution does not include them. If you
|
||||
are using a non-standard library for the DB 1.85 library routines,
|
||||
you will have to change the Makefile that configure creates to
|
||||
load dump_185 with that library.
|
||||
|
||||
--enable-test:
|
||||
If you want to build the Tcl test suite, enter:
|
||||
|
||||
--enable-test
|
||||
|
||||
as an argument to configure. Note, the Tcl test suite will only
|
||||
build if the Tcl libraries and include files are found.
|
||||
|
||||
--disable-bigfile:
|
||||
Some systems, notably versions of AIX, HP/UX and Solaris, require
|
||||
special compile-time options in order to create files larger than
|
||||
2^32 bytes. These options are automatically enabled when DB is
|
||||
compiled. For this reason, binaries built on current versions of
|
||||
these systems may not run on earlier versions of the system, as
|
||||
the library and system calls necessary for large files are not
|
||||
available. To disable building with these compile-time options,
|
||||
enter:
|
||||
|
||||
--disable-bigfile
|
||||
|
||||
as an argument to configure.
|
||||
|
||||
=-=-=-=-=-=-=
|
||||
RUNNING THE DB TEST SUITE
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
The DB test suite is built if you specify --enable-test as an argument to
|
||||
configure and the Tcl libraries are found on your system. (The libraries
|
||||
that DB needs to build the test suite are -ltcl and -lm.) For more
|
||||
information on running DB's test suite and debugging the DB package, see
|
||||
the file file ../test/README.
|
||||
|
||||
=-=-=-=-=-=-=
|
||||
CHANGING COMPILERS, LIBRARIES OR COMPILER AND LOADER OPTIONS
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
You can specify a compiler and/or compile and load time flags by using
|
||||
environment variables during configuration. For example, if you want
|
||||
to use a specific compiler, specify the CC environment variable before
|
||||
running configure:
|
||||
|
||||
env CC=gcc ../dist/configure
|
||||
|
||||
Using anything other than the native compiler will almost certainly
|
||||
mean that you'll want to check the compile and load line flags, too.
|
||||
|
||||
To specify debugging and optimization options for the C compiler,
|
||||
use the CFLAGS environment variable:
|
||||
|
||||
env CFLAGS=-O2 ../dist/configure
|
||||
|
||||
To specify header file search directories and other miscellaneous options
|
||||
for the C preprocessor and compiler, use the CPPFLAGS environment variable:
|
||||
|
||||
env CPPFLAGS=-I/usr/contrib/include ../dist/configure
|
||||
|
||||
To specify debugging and optimization options for the C++ compiler,
|
||||
use the CXXFLAGS environment variable:
|
||||
|
||||
env CXXFLAGS=-Woverloaded-virtual ../dist/configure
|
||||
|
||||
To specify miscellaneous options for the linker, use the LDFLAGS
|
||||
environment variable:
|
||||
|
||||
env LDFLAGS="-N32" ../dist/configure
|
||||
|
||||
If the Tcl or any other include files or libraries are in non-standard
|
||||
places on your system, you will need to specify the directory path where
|
||||
they can be found.
|
||||
|
||||
If you want to specify additional libraries and library directories, set
|
||||
the LIBS environment variable before running configure. For example:
|
||||
|
||||
env LIBS="-L/a/b -L/e/f -lposix" ../dist/configure
|
||||
|
||||
would specify two additional directories to search for libraries, /a/b
|
||||
and /e/f, and one additional library to load, "posix".
|
||||
|
||||
Make sure that you prepend -L to any library directory names and that you
|
||||
prepend -I to any include file directory names! Also, make sure that you
|
||||
quote the arguments as shown above, i.e. with single or double quotes
|
||||
around the values you're specifying for LIBS, if they contain blank or
|
||||
tab characters.
|
||||
|
||||
The env command is available on most systems, and simply sets one or more
|
||||
environment variables before running a command. If the env command is
|
||||
not available to you, you can set the environment variables in your shell
|
||||
before running configure. For example, in sh or ksh, you could do:
|
||||
|
||||
LIBS="-L/a/b -L/e/f -ldb" ../dist/configure
|
||||
|
||||
and in csh or tcsh, you could do:
|
||||
|
||||
setenv LIBS "-L/a/b -L/e/f -ldb"
|
||||
../dist/configure
|
||||
|
||||
See your shell's manual page for further information.
|
||||
|
||||
=-=-=-=-=-=-=
|
||||
INSTALLING DB
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
DB installs the following files into the following locations, with the
|
||||
following default values:
|
||||
|
||||
Variables: Default value:
|
||||
prefix /usr/local
|
||||
exec_prefix $(prefix)
|
||||
includedir $(prefix)/include
|
||||
bindir $(prefix)/bin
|
||||
libdir $(prefix)/lib
|
||||
mandir $(prefix)/man
|
||||
|
||||
File(s): Default location
|
||||
----------------------------------------
|
||||
db.h, db_185.h $(includedir)
|
||||
libdb.a $(libdir)
|
||||
utilities $(bindir)
|
||||
formatted man pages $(mandir)/cat1/
|
||||
formatted man pages $(mandir)/cat3/
|
||||
|
||||
Unformatted man pages are not installed by default.
|
||||
|
||||
To move the entire installation tree somewhere besides /usr/local, change
|
||||
the value "prefix". To move the binaries to a different place, change
|
||||
the value of "bindir". Similarly, to move the man pages to a different
|
||||
location, change the value of "mandir". These values can be changed as
|
||||
part of configuration:
|
||||
|
||||
../dist/configure --prefix=/usr/contrib
|
||||
|
||||
or when doing the install itself:
|
||||
|
||||
make prefix=/usr/contrib install
|
||||
|
||||
Note, the installation process will attempt to create any directories
|
||||
that are not already in place on the system.
|
|
@ -1,241 +0,0 @@
|
|||
/*
|
||||
* @(#)config.h 10.6 (Sleepycat) 5/2/98
|
||||
*
|
||||
* Generated by hand.
|
||||
*/
|
||||
|
||||
/* Define to empty if the keyword does not work. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define if your struct stat has st_blksize. */
|
||||
/* #undef HAVE_ST_BLKSIZE */
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#define mode_t int
|
||||
|
||||
/* Define to `long' if <sys/types.h> doesn't define. */
|
||||
/* #undef off_t */
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#define pid_t long
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> doesn't define. */
|
||||
/* #undef size_t */
|
||||
|
||||
/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
|
||||
/* #undef STAT_MACROS_BROKEN */
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define if your processor stores words with the most significant
|
||||
byte first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
/* #undef WORDS_BIGENDIAN */
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
typedef int ssize_t;
|
||||
|
||||
/* Define if you want a debugging version. */
|
||||
/* #undef DEBUG */
|
||||
#if defined(_DEBUG)
|
||||
#if !defined(DEBUG)
|
||||
#define DEBUG 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define if you want a version with run-time diagnostic checking. */
|
||||
/* #undef DIAGNOSTIC */
|
||||
|
||||
/* Define if you have sigfillset (and sigprocmask). */
|
||||
/* #undef HAVE_SIGFILLSET */
|
||||
|
||||
/* Define if building on AIX, HP, Solaris to get big-file environment. */
|
||||
/* #undef HAVE_FILE_OFFSET_BITS */
|
||||
#ifdef HAVE_FILE_OFFSET_BITS
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
|
||||
/* Define if you have spinlocks. */
|
||||
#define HAVE_SPINLOCKS 1
|
||||
|
||||
/* Define if you want to use mc68020/gcc assembly spinlocks. */
|
||||
/* #undef HAVE_ASSEM_MC68020_GCC */
|
||||
|
||||
/* Define if you want to use parisc/gcc assembly spinlocks. */
|
||||
/* #undef HAVE_ASSEM_PARISC_GCC */
|
||||
|
||||
/* Define if you want to use sco/cc assembly spinlocks. */
|
||||
/* #undef HAVE_ASSEM_SCO_CC */
|
||||
|
||||
/* Define if you want to use sparc/gcc assembly spinlocks. */
|
||||
/* #undef HAVE_ASSEM_SPARC_GCC */
|
||||
|
||||
/* Define if you want to use uts4/cc assembly spinlocks. */
|
||||
/* #undef HAVE_ASSEM_UTS4_CC */
|
||||
|
||||
/* Define if you want to use x86/gcc assembly spinlocks. */
|
||||
/* #undef HAVE_ASSEM_X86_GCC */
|
||||
|
||||
/* Define if you have the AIX _check_lock spinlocks. */
|
||||
/* #undef HAVE_FUNC_AIX */
|
||||
|
||||
/* Define if you have the OSF1 or HPPA msemaphore spinlocks. */
|
||||
/* #undef HAVE_FUNC_MSEM */
|
||||
|
||||
/* Define if you have the SGI abilock_t spinlocks. */
|
||||
/* #undef HAVE_FUNC_SGI */
|
||||
|
||||
/* Define if you have the ReliantUNIX spinlock_t spinlocks. */
|
||||
/* #undef HAVE_FUNC_RELIANT */
|
||||
|
||||
/* Define if you have the Solaris mutex_t spinlocks. */
|
||||
/* #undef HAVE_FUNC_SOLARIS */
|
||||
|
||||
/* Define if your sprintf returns a pointer, not a length. */
|
||||
/* #undef SPRINTF_RET_CHARPNT */
|
||||
|
||||
/* Define if you have the directio function. */
|
||||
/* #undef HAVE_DIRECTIO */
|
||||
|
||||
/* Define if you have the getcwd function. */
|
||||
#define HAVE_GETCWD
|
||||
|
||||
/* Define if you have the getopt function. */
|
||||
/* #undef HAVE_GETOPT */
|
||||
extern int getopt(int, char * const *, const char *);
|
||||
|
||||
/* Define if you have the getuid function. */
|
||||
/* #undef HAVE_GETUID */
|
||||
|
||||
/* Define if you have the memcmp function. */
|
||||
#define HAVE_MEMCMP 1
|
||||
|
||||
/* Define if you have the memcpy function. */
|
||||
#define HAVE_MEMCPY 1
|
||||
|
||||
/* Define if you have the memmove function. */
|
||||
#define HAVE_MEMMOVE 1
|
||||
|
||||
/* Define if you have the mmap function. */
|
||||
/* #undef HAVE_MMAP */
|
||||
|
||||
/* Define if you have the raise function. */
|
||||
#define HAVE_RAISE 1
|
||||
|
||||
/* Define if you have the select function. */
|
||||
/* #undef HAVE_SELECT */
|
||||
|
||||
/* Define if you have the shmget function. */
|
||||
/* #undef HAVE_SHMGET */
|
||||
|
||||
/* Define if you have the snprintf function. */
|
||||
#define HAVE_SNPRINTF 1
|
||||
|
||||
/* Define if you have the strerror function. */
|
||||
#define HAVE_STRERROR 1
|
||||
|
||||
/* Define if you have the strsep function. */
|
||||
/* #undef HAVE_STRSEP */
|
||||
|
||||
/* Define if you have the sysconf function. */
|
||||
/* #undef HAVE_SYSCONF */
|
||||
|
||||
/* Define if you have the vsnprintf function. */
|
||||
#define HAVE_VSNPRINTF 1
|
||||
|
||||
/* Define if you have the <dirent.h> header file. */
|
||||
/* #undef HAVE_DIRENT_H */
|
||||
|
||||
/* Define if you have the <ndir.h> header file. */
|
||||
/* #undef HAVE_NDIR_H */
|
||||
|
||||
/* Define if you have the <sys/dir.h> header file. */
|
||||
/* #undef HAVE_SYS_DIR_H */
|
||||
|
||||
/* Define if you have the <sys/ndir.h> header file. */
|
||||
/* #undef HAVE_SYS_NDIR_H */
|
||||
|
||||
/* Define if you have the <sys/select.h> header file. */
|
||||
/* #undef HAVE_SYS_SELECT_H */
|
||||
|
||||
/* Define if you have the <sys/time.h> header file. */
|
||||
/* #undef HAVE_SYS_TIME_H */
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* The following is not part of the automatic configuration setup,
|
||||
* but provides the information necessary to build DB.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <limits.h>
|
||||
#include <memory.h>
|
||||
#include <process.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <direct.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <dos.h>
|
||||
#include <i86.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#include <iostream.h>
|
||||
#endif
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include "queue.h"
|
||||
#include "shqueue.h"
|
||||
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
|
||||
#define NO_SYSTEM_INCLUDES
|
||||
|
||||
/*
|
||||
* Arrange to use the far versions of these functions by default.
|
||||
*/
|
||||
#define memcmp _fmemcmp
|
||||
#define memcpy _fmemcpy
|
||||
#define memmove _fmemmove
|
||||
#define strdup _fstrdup
|
||||
|
||||
/*
|
||||
* Callbacks need to be so tagged.
|
||||
*/
|
||||
#define DB_CALLBACK __cdecl __loadds
|
||||
|
||||
/*
|
||||
* The maximum region on Win16 is 64K.
|
||||
*/
|
||||
#define DB_REGIONSIZE_MAX (64 * 1024)
|
||||
|
||||
/*
|
||||
* include/lock.h:
|
||||
* The maximum region size on Win16 is 64K.
|
||||
*/
|
||||
#define DB_LOCK_DEFAULT_N 400
|
||||
|
||||
/*
|
||||
* include/mp.h:
|
||||
* The maximum region size on Win16 is 64K.
|
||||
*/
|
||||
#define DB_CACHESIZE_DEF DB_REGIONSIZE_MAX
|
||||
|
||||
/*
|
||||
* include/log.h:
|
||||
* File names can only have 3 characters after the dot.
|
||||
*/
|
||||
#define MAXLFNAME 999 /* Maximum log file name. */
|
||||
#define LFNAME "log.%03d" /* Log file name template. */
|
||||
|
||||
#define WIN16
|
|
@ -1,997 +0,0 @@
|
|||
/* DO NOT EDIT: automatically built by dist/distrib. */
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* @(#)db.h.src 10.131 (Sleepycat) 6/2/98
|
||||
*/
|
||||
|
||||
#ifndef _DB_H_
|
||||
#define _DB_H_
|
||||
|
||||
#ifndef __NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* MacOS: ensure that Metrowerks C makes enumeration types int sized.
|
||||
*/
|
||||
#ifdef __MWERKS__
|
||||
#pragma enumsalwaysint on
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Handle function prototypes and the keyword "const". This steps on name
|
||||
* space that DB doesn't control, but all of the other solutions are worse.
|
||||
*
|
||||
* XXX
|
||||
* While Microsoft's compiler is ANSI C compliant, it doesn't have _STDC_
|
||||
* defined by default, you specify a command line flag or #pragma to turn
|
||||
* it on. Don't do that, however, because some of Microsoft's own header
|
||||
* files won't compile.
|
||||
*/
|
||||
#undef __P
|
||||
#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER)
|
||||
#define __P(protos) protos /* ANSI C prototypes */
|
||||
#else
|
||||
#define const
|
||||
#define __P(protos) () /* K&R C preprocessor */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* DB needs basic information about specifically sized types. If they're
|
||||
* not provided by the system, typedef them here.
|
||||
*
|
||||
* We protect them against multiple inclusion using __BIT_TYPES_DEFINED__,
|
||||
* as does BIND and Kerberos, since we don't know for sure what #include
|
||||
* files the user is using.
|
||||
*
|
||||
* !!!
|
||||
* We also provide the standard u_int, u_long etc., if they're not provided
|
||||
* by the system.
|
||||
*/
|
||||
#ifndef __BIT_TYPES_DEFINED__
|
||||
#define __BIT_TYPES_DEFINED__
|
||||
typedef unsigned char u_int8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short u_int16_t;
|
||||
typedef long int32_t;
|
||||
typedef unsigned long u_int32_t;
|
||||
#endif
|
||||
|
||||
#if !defined(_WINSOCKAPI_)
|
||||
typedef unsigned char u_char;
|
||||
typedef unsigned short u_short;
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned long u_long;
|
||||
#endif
|
||||
|
||||
#define DB_VERSION_MAJOR 2
|
||||
#define DB_VERSION_MINOR 4
|
||||
#define DB_VERSION_PATCH 14
|
||||
#define DB_VERSION_STRING "Sleepycat Software: DB 2.4.14: (6/2/98)"
|
||||
|
||||
typedef u_int32_t db_pgno_t; /* Page number type. */
|
||||
typedef u_int16_t db_indx_t; /* Page offset type. */
|
||||
#define DB_MAX_PAGES 0xffffffff /* >= # of pages in a file */
|
||||
|
||||
typedef u_int32_t db_recno_t; /* Record number type. */
|
||||
typedef size_t DB_LOCK; /* Object returned by lock manager. */
|
||||
#define DB_MAX_RECORDS 0xffffffff /* >= # of records in a tree */
|
||||
|
||||
#define DB_FILE_ID_LEN 20 /* DB file ID length. */
|
||||
|
||||
/* Forward structure declarations, so applications get type checking. */
|
||||
struct __db; typedef struct __db DB;
|
||||
#ifdef DB_DBM_HSEARCH
|
||||
typedef struct __db DBM;
|
||||
#endif
|
||||
struct __db_bt_stat; typedef struct __db_bt_stat DB_BTREE_STAT;
|
||||
struct __db_dbt; typedef struct __db_dbt DBT;
|
||||
struct __db_env; typedef struct __db_env DB_ENV;
|
||||
struct __db_info; typedef struct __db_info DB_INFO;
|
||||
struct __db_lock_stat; typedef struct __db_lock_stat DB_LOCK_STAT;
|
||||
struct __db_lockregion; typedef struct __db_lockregion DB_LOCKREGION;
|
||||
struct __db_lockreq; typedef struct __db_lockreq DB_LOCKREQ;
|
||||
struct __db_locktab; typedef struct __db_locktab DB_LOCKTAB;
|
||||
struct __db_log; typedef struct __db_log DB_LOG;
|
||||
struct __db_log_stat; typedef struct __db_log_stat DB_LOG_STAT;
|
||||
struct __db_lsn; typedef struct __db_lsn DB_LSN;
|
||||
struct __db_mpool; typedef struct __db_mpool DB_MPOOL;
|
||||
struct __db_mpool_finfo;typedef struct __db_mpool_finfo DB_MPOOL_FINFO;
|
||||
struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
|
||||
struct __db_mpool_stat; typedef struct __db_mpool_stat DB_MPOOL_STAT;
|
||||
struct __db_mpoolfile; typedef struct __db_mpoolfile DB_MPOOLFILE;
|
||||
struct __db_txn; typedef struct __db_txn DB_TXN;
|
||||
struct __db_txn_active; typedef struct __db_txn_active DB_TXN_ACTIVE;
|
||||
struct __db_txn_stat; typedef struct __db_txn_stat DB_TXN_STAT;
|
||||
struct __db_txnmgr; typedef struct __db_txnmgr DB_TXNMGR;
|
||||
struct __db_txnregion; typedef struct __db_txnregion DB_TXNREGION;
|
||||
struct __dbc; typedef struct __dbc DBC;
|
||||
|
||||
/* Key/data structure -- a Data-Base Thang. */
|
||||
struct __db_dbt {
|
||||
void *data; /* key/data */
|
||||
u_int32_t size; /* key/data length */
|
||||
u_int32_t ulen; /* RO: length of user buffer. */
|
||||
u_int32_t dlen; /* RO: get/put record length. */
|
||||
u_int32_t doff; /* RO: get/put record offset. */
|
||||
|
||||
#define DB_DBT_INTERNAL 0x01 /* Perform any mallocs using regular
|
||||
malloc, not the user's malloc. */
|
||||
#define DB_DBT_MALLOC 0x02 /* Return in allocated memory. */
|
||||
#define DB_DBT_PARTIAL 0x04 /* Partial put/get. */
|
||||
#define DB_DBT_USERMEM 0x08 /* Return in user's memory. */
|
||||
u_int32_t flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* DB internal configuration.
|
||||
*
|
||||
* There are a set of functions that the application can replace with its
|
||||
* own versions, and some other knobs which can be turned at run-time.
|
||||
*/
|
||||
#define DB_FUNC_CALLOC 1 /* DELETED: ANSI C calloc. */
|
||||
#define DB_FUNC_CLOSE 2 /* POSIX 1003.1 close. */
|
||||
#define DB_FUNC_DIRFREE 3 /* DB: free directory list. */
|
||||
#define DB_FUNC_DIRLIST 4 /* DB: create directory list. */
|
||||
#define DB_FUNC_EXISTS 5 /* DB: return if file exists. */
|
||||
#define DB_FUNC_FREE 6 /* ANSI C free. */
|
||||
#define DB_FUNC_FSYNC 7 /* POSIX 1003.1 fsync. */
|
||||
#define DB_FUNC_IOINFO 8 /* DB: return file I/O information. */
|
||||
#define DB_FUNC_MALLOC 9 /* ANSI C malloc. */
|
||||
#define DB_FUNC_MAP 10 /* DB: map file into shared memory. */
|
||||
#define DB_FUNC_OPEN 11 /* POSIX 1003.1 open. */
|
||||
#define DB_FUNC_READ 12 /* POSIX 1003.1 read. */
|
||||
#define DB_FUNC_REALLOC 13 /* ANSI C realloc. */
|
||||
#define DB_FUNC_SEEK 14 /* POSIX 1003.1 lseek. */
|
||||
#define DB_FUNC_SLEEP 15 /* DB: sleep secs/usecs. */
|
||||
#define DB_FUNC_STRDUP 16 /* DELETED: DB: strdup(3). */
|
||||
#define DB_FUNC_UNLINK 17 /* POSIX 1003.1 unlink. */
|
||||
#define DB_FUNC_UNMAP 18 /* DB: unmap shared memory file. */
|
||||
#define DB_FUNC_WRITE 19 /* POSIX 1003.1 write. */
|
||||
#define DB_FUNC_YIELD 20 /* DB: yield thread to scheduler. */
|
||||
#define DB_TSL_SPINS 21 /* DB: initialize spin count. */
|
||||
#define DB_FUNC_RUNLINK 22 /* DB: remove a shared region. */
|
||||
#define DB_REGION_ANON 23 /* DB: anonymous, unnamed regions. */
|
||||
#define DB_REGION_INIT 24 /* DB: page-fault regions in create. */
|
||||
#define DB_REGION_NAME 25 /* DB: anonymous, named regions. */
|
||||
#define DB_MUTEXLOCKS 26 /* DB: turn off all mutex locks. */
|
||||
#define DB_PAGEYIELD 27 /* DB: yield the CPU on pool get. */
|
||||
|
||||
/*
|
||||
* Database configuration and initialization.
|
||||
*/
|
||||
/*
|
||||
* Flags understood by both db_open(3) and db_appinit(3).
|
||||
*/
|
||||
#define DB_CREATE 0x000001 /* O_CREAT: create file as necessary. */
|
||||
#define DB_NOMMAP 0x000002 /* Don't mmap underlying file. */
|
||||
#define DB_THREAD 0x000004 /* Free-thread DB package handles. */
|
||||
|
||||
/*
|
||||
* Flags understood by db_appinit(3).
|
||||
*/
|
||||
/* 0x000007 COMMON MASK. */
|
||||
#define DB_INIT_LOCK 0x000008 /* Initialize locking. */
|
||||
#define DB_INIT_LOG 0x000010 /* Initialize logging. */
|
||||
#define DB_INIT_MPOOL 0x000020 /* Initialize mpool. */
|
||||
#define DB_INIT_TXN 0x000040 /* Initialize transactions. */
|
||||
#define DB_MPOOL_PRIVATE 0x000080 /* Mpool: private memory pool. */
|
||||
#define __UNUSED_100 0x000100
|
||||
#define DB_RECOVER 0x000200 /* Run normal recovery. */
|
||||
#define DB_RECOVER_FATAL 0x000400 /* Run catastrophic recovery. */
|
||||
#define DB_TXN_NOSYNC 0x000800 /* Do not sync log on commit. */
|
||||
#define DB_USE_ENVIRON 0x001000 /* Use the environment. */
|
||||
#define DB_USE_ENVIRON_ROOT 0x002000 /* Use the environment if root. */
|
||||
|
||||
/* CURRENTLY UNUSED LOCK FLAGS. */
|
||||
#define DB_TXN_LOCK_2PL 0x000000 /* Two-phase locking. */
|
||||
#define DB_TXN_LOCK_OPTIMIST 0x000000 /* Optimistic locking. */
|
||||
#define DB_TXN_LOCK_MASK 0x000000 /* Lock flags mask. */
|
||||
|
||||
/* CURRENTLY UNUSED LOG FLAGS. */
|
||||
#define DB_TXN_LOG_REDO 0x000000 /* Redo-only logging. */
|
||||
#define DB_TXN_LOG_UNDO 0x000000 /* Undo-only logging. */
|
||||
#define DB_TXN_LOG_UNDOREDO 0x000000 /* Undo/redo write-ahead logging. */
|
||||
#define DB_TXN_LOG_MASK 0x000000 /* Log flags mask. */
|
||||
|
||||
/*
|
||||
* Flags understood by db_open(3).
|
||||
*
|
||||
* DB_EXCL and DB_TEMPORARY are internal only, and are not documented.
|
||||
* DB_SEQUENTIAL is currently internal, but may be exported some day.
|
||||
*/
|
||||
/* 0x000007 COMMON MASK. */
|
||||
/* 0x003fff ALREADY USED. */
|
||||
#define __UNUSED_4000 0x004000
|
||||
#define DB_EXCL 0x008000 /* O_EXCL: exclusive open. */
|
||||
#define DB_RDONLY 0x010000 /* O_RDONLY: read-only. */
|
||||
#define DB_SEQUENTIAL 0x020000 /* Indicate sequential access. */
|
||||
#define DB_TEMPORARY 0x040000 /* Remove on last close. */
|
||||
#define DB_TRUNCATE 0x080000 /* O_TRUNCATE: replace existing DB. */
|
||||
|
||||
/*
|
||||
* Deadlock detector modes; used in the DBENV structure to configure the
|
||||
* locking subsystem.
|
||||
*/
|
||||
#define DB_LOCK_NORUN 0x0
|
||||
#define DB_LOCK_DEFAULT 0x1 /* Default policy. */
|
||||
#define DB_LOCK_OLDEST 0x2 /* Abort oldest transaction. */
|
||||
#define DB_LOCK_RANDOM 0x3 /* Abort random transaction. */
|
||||
#define DB_LOCK_YOUNGEST 0x4 /* Abort youngest transaction. */
|
||||
|
||||
struct __db_env {
|
||||
int db_lorder; /* Byte order. */
|
||||
|
||||
/* Error message callback. */
|
||||
void (DB_CALLBACK *db_errcall) __P((const char *, char *));
|
||||
FILE *db_errfile; /* Error message file stream. */
|
||||
const char *db_errpfx; /* Error message prefix. */
|
||||
int db_verbose; /* Generate debugging messages. */
|
||||
|
||||
/* User paths. */
|
||||
char *db_home; /* Database home. */
|
||||
char *db_log_dir; /* Database log file directory. */
|
||||
char *db_tmp_dir; /* Database tmp file directory. */
|
||||
|
||||
char **db_data_dir; /* Database data file directories. */
|
||||
int data_cnt; /* Database data file slots. */
|
||||
int data_next; /* Next Database data file slot. */
|
||||
|
||||
/* Locking. */
|
||||
DB_LOCKTAB *lk_info; /* Return from lock_open(). */
|
||||
u_int8_t *lk_conflicts; /* Two dimensional conflict matrix. */
|
||||
u_int32_t lk_modes; /* Number of lock modes in table. */
|
||||
u_int32_t lk_max; /* Maximum number of locks. */
|
||||
u_int32_t lk_detect; /* Deadlock detect on all conflicts. */
|
||||
|
||||
/* Logging. */
|
||||
DB_LOG *lg_info; /* Return from log_open(). */
|
||||
u_int32_t lg_max; /* Maximum file size. */
|
||||
|
||||
/* Memory pool. */
|
||||
DB_MPOOL *mp_info; /* Return from memp_open(). */
|
||||
size_t mp_mmapsize; /* Maximum file size for mmap. */
|
||||
size_t mp_size; /* Bytes in the mpool cache. */
|
||||
|
||||
/* Transactions. */
|
||||
DB_TXNMGR *tx_info; /* Return from txn_open(). */
|
||||
u_int32_t tx_max; /* Maximum number of transactions. */
|
||||
int (DB_CALLBACK *tx_recover) /* Dispatch function for recovery. */
|
||||
__P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
|
||||
#define DB_ENV_APPINIT 0x01 /* Paths initialized by db_appinit(). */
|
||||
#define DB_ENV_STANDALONE 0x02 /* Test: freestanding environment. */
|
||||
#define DB_ENV_THREAD 0x04 /* DB_ENV is multi-threaded. */
|
||||
u_int32_t flags; /* Flags. */
|
||||
};
|
||||
|
||||
/*******************************************************
|
||||
* Access methods.
|
||||
*******************************************************/
|
||||
/*
|
||||
* XXX
|
||||
* Changes here must be reflected in java/src/com/sleepycat/db/Db.java.
|
||||
*/
|
||||
typedef enum {
|
||||
DB_BTREE=1, /* B+tree. */
|
||||
DB_HASH, /* Extended Linear Hashing. */
|
||||
DB_RECNO, /* Fixed and variable-length records. */
|
||||
DB_UNKNOWN /* Figure it out on open. */
|
||||
} DBTYPE;
|
||||
|
||||
#define DB_BTREEVERSION 6 /* Current btree version. */
|
||||
#define DB_BTREEOLDVER 6 /* Oldest btree version supported. */
|
||||
#define DB_BTREEMAGIC 0x053162
|
||||
|
||||
#define DB_HASHVERSION 5 /* Current hash version. */
|
||||
#define DB_HASHOLDVER 4 /* Oldest hash version supported. */
|
||||
#define DB_HASHMAGIC 0x061561
|
||||
|
||||
#define DB_LOGVERSION 2 /* Current log version. */
|
||||
#define DB_LOGOLDVER 2 /* Oldest log version supported. */
|
||||
#define DB_LOGMAGIC 0x040988
|
||||
|
||||
struct __db_info {
|
||||
int db_lorder; /* Byte order. */
|
||||
size_t db_cachesize; /* Underlying cache size. */
|
||||
size_t db_pagesize; /* Underlying page size. */
|
||||
|
||||
/* Local heap allocation. */
|
||||
void *(DB_CALLBACK *db_malloc) __P((size_t));
|
||||
|
||||
/* Btree access method. */
|
||||
u_int32_t bt_maxkey; /* Maximum keys per page. */
|
||||
u_int32_t bt_minkey; /* Minimum keys per page. */
|
||||
int (DB_CALLBACK *bt_compare) /* Comparison function. */
|
||||
__P((const DBT *, const DBT *));
|
||||
size_t (DB_CALLBACK *bt_prefix) /* Prefix function. */
|
||||
__P((const DBT *, const DBT *));
|
||||
|
||||
/* Hash access method. */
|
||||
u_int32_t h_ffactor; /* Fill factor. */
|
||||
u_int32_t h_nelem; /* Number of elements. */
|
||||
u_int32_t (DB_CALLBACK *h_hash) /* Hash function. */
|
||||
__P((const void *, u_int32_t));
|
||||
|
||||
/* Recno access method. */
|
||||
int re_pad; /* Fixed-length padding byte. */
|
||||
int re_delim; /* Variable-length delimiting byte. */
|
||||
u_int32_t re_len; /* Length for fixed-length records. */
|
||||
char *re_source; /* Source file name. */
|
||||
|
||||
#define DB_DELIMITER 0x0001 /* Recno: re_delim set. */
|
||||
#define DB_DUP 0x0002 /* Btree, Hash: duplicate keys. */
|
||||
#define DB_FIXEDLEN 0x0004 /* Recno: fixed-length records. */
|
||||
#define DB_PAD 0x0008 /* Recno: re_pad set. */
|
||||
#define DB_RECNUM 0x0010 /* Btree: record numbers. */
|
||||
#define DB_RENUMBER 0x0020 /* Recno: renumber on insert/delete. */
|
||||
#define DB_SNAPSHOT 0x0040 /* Recno: snapshot the input. */
|
||||
u_int32_t flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* DB access method and cursor operation codes. These are implemented as
|
||||
* bit fields for future flexibility, but currently only a single one may
|
||||
* be specified to any function.
|
||||
*/
|
||||
#define DB_AFTER 0x000001 /* c_put() */
|
||||
#define DB_APPEND 0x000002 /* put() */
|
||||
#define DB_BEFORE 0x000004 /* c_put() */
|
||||
#define DB_CHECKPOINT 0x000008 /* log_put(), log_get() */
|
||||
#define DB_CURRENT 0x000010 /* c_get(), c_put(), log_get() */
|
||||
#define DB_FIRST 0x000020 /* c_get(), log_get() */
|
||||
#define DB_FLUSH 0x000040 /* log_put() */
|
||||
#define DB_GET_RECNO 0x000080 /* get(), c_get() */
|
||||
#define DB_KEYFIRST 0x000100 /* c_put() */
|
||||
#define DB_KEYLAST 0x000200 /* c_put() */
|
||||
#define DB_LAST 0x000400 /* c_get(), log_get() */
|
||||
#define DB_NEXT 0x000800 /* c_get(), log_get() */
|
||||
#define DB_NOOVERWRITE 0x001000 /* put() */
|
||||
#define DB_NOSYNC 0x002000 /* close() */
|
||||
#define DB_PREV 0x004000 /* c_get(), log_get() */
|
||||
#define DB_RECORDCOUNT 0x008000 /* stat() */
|
||||
#define DB_SET 0x010000 /* c_get(), log_get() */
|
||||
#define DB_SET_RANGE 0x020000 /* c_get() */
|
||||
#define DB_SET_RECNO 0x040000 /* c_get() */
|
||||
#define DB_CURLSN 0x080000 /* log_put() */
|
||||
|
||||
/*
|
||||
* DB (user visible) error return codes.
|
||||
*
|
||||
* XXX
|
||||
* Changes to any of the user visible error return codes must be reflected
|
||||
* in java/src/com/sleepycat/db/Db.java.
|
||||
*/
|
||||
#define DB_INCOMPLETE ( -1) /* Sync didn't finish. */
|
||||
#define DB_KEYEMPTY ( -2) /* The key/data pair was deleted or
|
||||
was never created by the user. */
|
||||
#define DB_KEYEXIST ( -3) /* The key/data pair already exists. */
|
||||
#define DB_LOCK_DEADLOCK ( -4) /* Locker killed to resolve deadlock. */
|
||||
#define DB_LOCK_NOTGRANTED ( -5) /* Lock unavailable, no-wait set. */
|
||||
#define DB_LOCK_NOTHELD ( -6) /* Lock not held by locker. */
|
||||
#define DB_NOTFOUND ( -7) /* Key/data pair not found (EOF). */
|
||||
|
||||
/* DB (private) error return codes. */
|
||||
#define DB_DELETED ( -8) /* Recovery file marked deleted. */
|
||||
#define DB_NEEDSPLIT ( -9) /* Page needs to be split. */
|
||||
#define DB_REGISTERED (-10) /* Entry was previously registered. */
|
||||
#define DB_SWAPBYTES (-11) /* Database needs byte swapping. */
|
||||
#define DB_TXN_CKP (-12) /* Encountered ckp record in log. */
|
||||
|
||||
struct __db_ilock { /* Internal DB access method lock. */
|
||||
db_pgno_t pgno; /* Page being locked. */
|
||||
/* File id. */
|
||||
u_int8_t fileid[DB_FILE_ID_LEN];
|
||||
};
|
||||
|
||||
/* DB access method description structure. */
|
||||
struct __db {
|
||||
void *mutexp; /* Synchronization for free threading */
|
||||
DBTYPE type; /* DB access method. */
|
||||
DB_ENV *dbenv; /* DB_ENV structure. */
|
||||
DB_ENV *mp_dbenv; /* DB_ENV for local mpool creation. */
|
||||
|
||||
DB *master; /* Original DB created by db_open. */
|
||||
void *internal; /* Access method private. */
|
||||
|
||||
DB_MPOOL *mp; /* The access method's mpool. */
|
||||
DB_MPOOLFILE *mpf; /* The access method's mpool file. */
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Explicit representations of structures in queue.h.
|
||||
*
|
||||
* TAILQ_HEAD(curs_queue, __dbc);
|
||||
*/
|
||||
struct {
|
||||
struct __dbc *tqh_first;
|
||||
struct __dbc **tqh_last;
|
||||
} curs_queue;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Explicit representations of structures in queue.h.
|
||||
*
|
||||
* LIST_HEAD(handleq, __db);
|
||||
* LIST_ENTRY(__db);
|
||||
*/
|
||||
struct {
|
||||
struct __db *lh_first;
|
||||
} handleq; /* List of handles for this DB. */
|
||||
struct {
|
||||
struct __db *le_next;
|
||||
struct __db **le_prev;
|
||||
} links; /* Links for the handle list. */
|
||||
|
||||
u_int32_t log_fileid; /* Logging file id. */
|
||||
|
||||
DB_TXN *txn; /* Current transaction. */
|
||||
u_int32_t locker; /* Default process' locker id. */
|
||||
DBT lock_dbt; /* DBT referencing lock. */
|
||||
struct __db_ilock lock; /* Lock. */
|
||||
|
||||
size_t pgsize; /* Logical page size of file. */
|
||||
|
||||
/* Local heap allocation. */
|
||||
void *(DB_CALLBACK *db_malloc) __P((size_t));
|
||||
|
||||
/* Functions. */
|
||||
int (DB_CALLBACK *close) __P((DB *, u_int32_t));
|
||||
int (DB_CALLBACK *cursor) __P((DB *, DB_TXN *, DBC **));
|
||||
int (DB_CALLBACK *del) __P((DB *, DB_TXN *, DBT *, u_int32_t));
|
||||
int (DB_CALLBACK *fd) __P((DB *, int *));
|
||||
int (DB_CALLBACK *get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
|
||||
int (DB_CALLBACK *put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
|
||||
int (DB_CALLBACK *stat) __P((DB *, void *, void *(*)(size_t), u_int32_t));
|
||||
int (DB_CALLBACK *sync) __P((DB *, u_int32_t));
|
||||
|
||||
#define DB_AM_DUP 0x000001 /* DB_DUP (internal). */
|
||||
#define DB_AM_INMEM 0x000002 /* In-memory; no sync on close. */
|
||||
#define DB_AM_LOCKING 0x000004 /* Perform locking. */
|
||||
#define DB_AM_LOGGING 0x000008 /* Perform logging. */
|
||||
#define DB_AM_MLOCAL 0x000010 /* Database memory pool is local. */
|
||||
#define DB_AM_PGDEF 0x000020 /* Page size was defaulted. */
|
||||
#define DB_AM_RDONLY 0x000040 /* Database is readonly. */
|
||||
#define DB_AM_RECOVER 0x000080 /* In recovery (do not log or lock). */
|
||||
#define DB_AM_SWAP 0x000100 /* Pages need to be byte-swapped. */
|
||||
#define DB_AM_THREAD 0x000200 /* DB is multi-threaded. */
|
||||
#define DB_BT_RECNUM 0x000400 /* DB_RECNUM (internal) */
|
||||
#define DB_HS_DIRTYMETA 0x000800 /* Hash: Metadata page modified. */
|
||||
#define DB_RE_DELIMITER 0x001000 /* DB_DELIMITER (internal). */
|
||||
#define DB_RE_FIXEDLEN 0x002000 /* DB_FIXEDLEN (internal). */
|
||||
#define DB_RE_PAD 0x004000 /* DB_PAD (internal). */
|
||||
#define DB_RE_RENUMBER 0x008000 /* DB_RENUMBER (internal). */
|
||||
#define DB_RE_SNAPSHOT 0x010000 /* DB_SNAPSHOT (internal). */
|
||||
u_int32_t flags;
|
||||
};
|
||||
|
||||
/* Cursor description structure. */
|
||||
struct __dbc {
|
||||
DB *dbp; /* Related DB access method. */
|
||||
DB_TXN *txn; /* Associated transaction. */
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Explicit representations of structures in queue.h.
|
||||
*
|
||||
* TAILQ_ENTRY(__dbc);
|
||||
*/
|
||||
struct {
|
||||
struct __dbc *tqe_next;
|
||||
struct __dbc **tqe_prev;
|
||||
} links;
|
||||
|
||||
void *internal; /* Access method private. */
|
||||
|
||||
int (DB_CALLBACK *c_close) __P((DBC *));
|
||||
int (DB_CALLBACK *c_del) __P((DBC *, u_int32_t));
|
||||
int (__cdecl __loadds *c_get) __P((DBC *, DBT *, DBT *, u_int32_t));
|
||||
int (__cdecl __loadds *c_put) __P((DBC *, DBT *, DBT *, u_int32_t));
|
||||
};
|
||||
|
||||
/* Btree/recno statistics structure. */
|
||||
struct __db_bt_stat {
|
||||
u_int32_t bt_flags; /* Open flags. */
|
||||
u_int32_t bt_maxkey; /* Maxkey value. */
|
||||
u_int32_t bt_minkey; /* Minkey value. */
|
||||
u_int32_t bt_re_len; /* Fixed-length record length. */
|
||||
u_int32_t bt_re_pad; /* Fixed-length record pad. */
|
||||
u_int32_t bt_pagesize; /* Page size. */
|
||||
u_int32_t bt_levels; /* Tree levels. */
|
||||
u_int32_t bt_nrecs; /* Number of records. */
|
||||
u_int32_t bt_int_pg; /* Internal pages. */
|
||||
u_int32_t bt_leaf_pg; /* Leaf pages. */
|
||||
u_int32_t bt_dup_pg; /* Duplicate pages. */
|
||||
u_int32_t bt_over_pg; /* Overflow pages. */
|
||||
u_int32_t bt_free; /* Pages on the free list. */
|
||||
u_int32_t bt_freed; /* Pages freed for reuse. */
|
||||
u_int32_t bt_int_pgfree; /* Bytes free in internal pages. */
|
||||
u_int32_t bt_leaf_pgfree; /* Bytes free in leaf pages. */
|
||||
u_int32_t bt_dup_pgfree; /* Bytes free in duplicate pages. */
|
||||
u_int32_t bt_over_pgfree; /* Bytes free in overflow pages. */
|
||||
u_int32_t bt_pfxsaved; /* Bytes saved by prefix compression. */
|
||||
u_int32_t bt_split; /* Total number of splits. */
|
||||
u_int32_t bt_rootsplit; /* Root page splits. */
|
||||
u_int32_t bt_fastsplit; /* Fast splits. */
|
||||
u_int32_t bt_added; /* Items added. */
|
||||
u_int32_t bt_deleted; /* Items deleted. */
|
||||
u_int32_t bt_get; /* Items retrieved. */
|
||||
u_int32_t bt_cache_hit; /* Hits in fast-insert code. */
|
||||
u_int32_t bt_cache_miss; /* Misses in fast-insert code. */
|
||||
u_int32_t bt_magic; /* Magic number. */
|
||||
u_int32_t bt_version; /* Version number. */
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int db_appinit __P((const char *, char * const *, DB_ENV *, u_int32_t));
|
||||
int db_appexit __P((DB_ENV *));
|
||||
int db_jump_set __P((void *, int));
|
||||
int db_open __P((const char *,
|
||||
DBTYPE, u_int32_t, int, DB_ENV *, DB_INFO *, DB **));
|
||||
int db_value_set __P((int, int));
|
||||
char *db_version __P((int *, int *, int *));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************
|
||||
* Locking
|
||||
*******************************************************/
|
||||
#define DB_LOCKVERSION 1
|
||||
#define DB_LOCKMAGIC 0x090193
|
||||
|
||||
/* Flag values for lock_vec(). */
|
||||
#define DB_LOCK_NOWAIT 0x01 /* Don't wait on unavailable lock. */
|
||||
|
||||
/* Flag values for lock_detect(). */
|
||||
#define DB_LOCK_CONFLICT 0x01 /* Run on any conflict. */
|
||||
|
||||
/*
|
||||
* Request types.
|
||||
*
|
||||
* XXX
|
||||
* Changes here must be reflected in java/src/com/sleepycat/db/Db.java.
|
||||
*/
|
||||
typedef enum {
|
||||
DB_LOCK_DUMP=0, /* Display held locks. */
|
||||
DB_LOCK_GET, /* Get the lock. */
|
||||
DB_LOCK_PUT, /* Release the lock. */
|
||||
DB_LOCK_PUT_ALL, /* Release locker's locks. */
|
||||
DB_LOCK_PUT_OBJ /* Release locker's locks on obj. */
|
||||
} db_lockop_t;
|
||||
|
||||
/*
|
||||
* Simple R/W lock modes and for multi-granularity intention locking.
|
||||
*
|
||||
* XXX
|
||||
* Changes here must be reflected in java/src/com/sleepycat/db/Db.java.
|
||||
*/
|
||||
typedef enum {
|
||||
DB_LOCK_NG=0, /* Not granted. */
|
||||
DB_LOCK_READ, /* Shared/read. */
|
||||
DB_LOCK_WRITE, /* Exclusive/write. */
|
||||
DB_LOCK_IREAD, /* Intent to share/read. */
|
||||
DB_LOCK_IWRITE, /* Intent exclusive/write. */
|
||||
DB_LOCK_IWR /* Intent to read and write. */
|
||||
} db_lockmode_t;
|
||||
|
||||
/*
|
||||
* Status of a lock.
|
||||
*/
|
||||
typedef enum {
|
||||
DB_LSTAT_ABORTED, /* Lock belongs to an aborted txn. */
|
||||
DB_LSTAT_ERR, /* Lock is bad. */
|
||||
DB_LSTAT_FREE, /* Lock is unallocated. */
|
||||
DB_LSTAT_HELD, /* Lock is currently held. */
|
||||
DB_LSTAT_NOGRANT, /* Lock was not granted. */
|
||||
DB_LSTAT_PENDING, /* Lock was waiting and has been
|
||||
* promoted; waiting for the owner
|
||||
* to run and upgrade it to held. */
|
||||
DB_LSTAT_WAITING /* Lock is on the wait queue. */
|
||||
} db_status_t;
|
||||
|
||||
/* Lock request structure. */
|
||||
struct __db_lockreq {
|
||||
db_lockop_t op; /* Operation. */
|
||||
db_lockmode_t mode; /* Requested mode. */
|
||||
u_int32_t locker; /* Locker identity. */
|
||||
DBT *obj; /* Object being locked. */
|
||||
DB_LOCK lock; /* Lock returned. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Commonly used conflict matrices.
|
||||
*
|
||||
* Standard Read/Write (or exclusive/shared) locks.
|
||||
*/
|
||||
#define DB_LOCK_RW_N 3
|
||||
extern const u_int8_t db_rw_conflicts[];
|
||||
|
||||
/* Multi-granularity locking. */
|
||||
#define DB_LOCK_RIW_N 6
|
||||
extern const u_int8_t db_riw_conflicts[];
|
||||
|
||||
struct __db_lock_stat {
|
||||
u_int32_t st_magic; /* Lock file magic number. */
|
||||
u_int32_t st_version; /* Lock file version number. */
|
||||
u_int32_t st_maxlocks; /* Maximum number of locks in table. */
|
||||
u_int32_t st_nmodes; /* Number of lock modes. */
|
||||
u_int32_t st_numobjs; /* Number of objects. */
|
||||
u_int32_t st_nlockers; /* Number of lockers. */
|
||||
u_int32_t st_nconflicts; /* Number of lock conflicts. */
|
||||
u_int32_t st_nrequests; /* Number of lock gets. */
|
||||
u_int32_t st_nreleases; /* Number of lock puts. */
|
||||
u_int32_t st_ndeadlocks; /* Number of lock deadlocks. */
|
||||
u_int32_t st_region_wait; /* Region lock granted after wait. */
|
||||
u_int32_t st_region_nowait; /* Region lock granted without wait. */
|
||||
u_int32_t st_refcnt; /* Region reference count. */
|
||||
u_int32_t st_regsize; /* Region size. */
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int lock_close __P((DB_LOCKTAB *));
|
||||
int lock_detect __P((DB_LOCKTAB *, u_int32_t, u_int32_t));
|
||||
int lock_get __P((DB_LOCKTAB *,
|
||||
u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *));
|
||||
int lock_id __P((DB_LOCKTAB *, u_int32_t *));
|
||||
int lock_open __P((const char *,
|
||||
u_int32_t, int, DB_ENV *, DB_LOCKTAB **));
|
||||
int lock_put __P((DB_LOCKTAB *, DB_LOCK));
|
||||
int lock_stat __P((DB_LOCKTAB *, DB_LOCK_STAT **, void *(*)(size_t)));
|
||||
int lock_unlink __P((const char *, int, DB_ENV *));
|
||||
int lock_vec __P((DB_LOCKTAB *,
|
||||
u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************
|
||||
* Logging.
|
||||
*******************************************************/
|
||||
/* Flag values for log_archive(). */
|
||||
#define DB_ARCH_ABS 0x001 /* Absolute pathnames. */
|
||||
#define DB_ARCH_DATA 0x002 /* Data files. */
|
||||
#define DB_ARCH_LOG 0x004 /* Log files. */
|
||||
|
||||
/*
|
||||
* A DB_LSN has two parts, a fileid which identifies a specific file, and an
|
||||
* offset within that file. The fileid is an unsigned 4-byte quantity that
|
||||
* uniquely identifies a file within the log directory -- currently a simple
|
||||
* counter inside the log. The offset is also an unsigned 4-byte value. The
|
||||
* log manager guarantees the offset is never more than 4 bytes by switching
|
||||
* to a new log file before the maximum length imposed by an unsigned 4-byte
|
||||
* offset is reached.
|
||||
*/
|
||||
struct __db_lsn {
|
||||
u_int32_t file; /* File ID. */
|
||||
u_int32_t offset; /* File offset. */
|
||||
};
|
||||
|
||||
/* Log statistics structure. */
|
||||
struct __db_log_stat {
|
||||
u_int32_t st_magic; /* Log file magic number. */
|
||||
u_int32_t st_version; /* Log file version number. */
|
||||
int st_mode; /* Log file mode. */
|
||||
u_int32_t st_lg_max; /* Maximum log file size. */
|
||||
u_int32_t st_w_bytes; /* Bytes to log. */
|
||||
u_int32_t st_w_mbytes; /* Megabytes to log. */
|
||||
u_int32_t st_wc_bytes; /* Bytes to log since checkpoint. */
|
||||
u_int32_t st_wc_mbytes; /* Megabytes to log since checkpoint. */
|
||||
u_int32_t st_wcount; /* Total syncs to the log. */
|
||||
u_int32_t st_scount; /* Total writes to the log. */
|
||||
u_int32_t st_region_wait; /* Region lock granted after wait. */
|
||||
u_int32_t st_region_nowait; /* Region lock granted without wait. */
|
||||
u_int32_t st_cur_file; /* Current log file number. */
|
||||
u_int32_t st_cur_offset; /* Current log file offset. */
|
||||
u_int32_t st_refcnt; /* Region reference count. */
|
||||
u_int32_t st_regsize; /* Region size. */
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int log_archive __P((DB_LOG *, char **[], u_int32_t, void *(*)(size_t)));
|
||||
int log_close __P((DB_LOG *));
|
||||
int log_compare __P((const DB_LSN *, const DB_LSN *));
|
||||
int log_file __P((DB_LOG *, const DB_LSN *, char *, size_t));
|
||||
int log_flush __P((DB_LOG *, const DB_LSN *));
|
||||
int log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t));
|
||||
int log_open __P((const char *, u_int32_t, int, DB_ENV *, DB_LOG **));
|
||||
int log_put __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t));
|
||||
int log_register __P((DB_LOG *, DB *, const char *, DBTYPE, u_int32_t *));
|
||||
int log_stat __P((DB_LOG *, DB_LOG_STAT **, void *(*)(size_t)));
|
||||
int log_unlink __P((const char *, int, DB_ENV *));
|
||||
int log_unregister __P((DB_LOG *, u_int32_t));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************
|
||||
* Mpool
|
||||
*******************************************************/
|
||||
/* Flag values for memp_fget(). */
|
||||
#define DB_MPOOL_CREATE 0x001 /* Create a page. */
|
||||
#define DB_MPOOL_LAST 0x002 /* Return the last page. */
|
||||
#define DB_MPOOL_NEW 0x004 /* Create a new page. */
|
||||
|
||||
/* Flag values for memp_fput(), memp_fset(). */
|
||||
#define DB_MPOOL_CLEAN 0x001 /* Clear modified bit. */
|
||||
#define DB_MPOOL_DIRTY 0x002 /* Page is modified. */
|
||||
#define DB_MPOOL_DISCARD 0x004 /* Don't cache the page. */
|
||||
|
||||
/* Mpool statistics structure. */
|
||||
struct __db_mpool_stat {
|
||||
size_t st_cachesize; /* Cache size. */
|
||||
u_int32_t st_cache_hit; /* Pages found in the cache. */
|
||||
u_int32_t st_cache_miss; /* Pages not found in the cache. */
|
||||
u_int32_t st_map; /* Pages from mapped files. */
|
||||
u_int32_t st_page_create; /* Pages created in the cache. */
|
||||
u_int32_t st_page_in; /* Pages read in. */
|
||||
u_int32_t st_page_out; /* Pages written out. */
|
||||
u_int32_t st_ro_evict; /* Clean pages forced from the cache. */
|
||||
u_int32_t st_rw_evict; /* Dirty pages forced from the cache. */
|
||||
u_int32_t st_hash_buckets; /* Number of hash buckets. */
|
||||
u_int32_t st_hash_searches; /* Total hash chain searches. */
|
||||
u_int32_t st_hash_longest; /* Longest hash chain searched. */
|
||||
u_int32_t st_hash_examined; /* Total hash entries searched. */
|
||||
u_int32_t st_page_clean; /* Clean pages. */
|
||||
u_int32_t st_page_dirty; /* Dirty pages. */
|
||||
u_int32_t st_page_trickle; /* Pages written by memp_trickle. */
|
||||
u_int32_t st_region_wait; /* Region lock granted after wait. */
|
||||
u_int32_t st_region_nowait; /* Region lock granted without wait. */
|
||||
u_int32_t st_refcnt; /* Region reference count. */
|
||||
u_int32_t st_regsize; /* Region size. */
|
||||
};
|
||||
|
||||
/* Mpool file open information structure. */
|
||||
struct __db_mpool_finfo {
|
||||
int ftype; /* File type. */
|
||||
DBT *pgcookie; /* Byte-string passed to pgin/pgout. */
|
||||
u_int8_t *fileid; /* Unique file ID. */
|
||||
int32_t lsn_offset; /* LSN offset in page. */
|
||||
u_int32_t clear_len; /* Cleared length on created pages. */
|
||||
};
|
||||
|
||||
/* Mpool file statistics structure. */
|
||||
struct __db_mpool_fstat {
|
||||
char *file_name; /* File name. */
|
||||
size_t st_pagesize; /* Page size. */
|
||||
u_int32_t st_cache_hit; /* Pages found in the cache. */
|
||||
u_int32_t st_cache_miss; /* Pages not found in the cache. */
|
||||
u_int32_t st_map; /* Pages from mapped files. */
|
||||
u_int32_t st_page_create; /* Pages created in the cache. */
|
||||
u_int32_t st_page_in; /* Pages read in. */
|
||||
u_int32_t st_page_out; /* Pages written out. */
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int memp_close __P((DB_MPOOL *));
|
||||
int memp_fclose __P((DB_MPOOLFILE *));
|
||||
int memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *));
|
||||
int memp_fopen __P((DB_MPOOL *, const char *,
|
||||
u_int32_t, int, size_t, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
|
||||
int memp_fput __P((DB_MPOOLFILE *, void *, u_int32_t));
|
||||
int memp_fset __P((DB_MPOOLFILE *, void *, u_int32_t));
|
||||
int memp_fsync __P((DB_MPOOLFILE *));
|
||||
int memp_open __P((const char *, u_int32_t, int, DB_ENV *, DB_MPOOL **));
|
||||
int memp_register __P((DB_MPOOL *, int,
|
||||
int (*)(db_pgno_t, void *, DBT *),
|
||||
int (*)(db_pgno_t, void *, DBT *)));
|
||||
int memp_stat __P((DB_MPOOL *,
|
||||
DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, void *(*)(size_t)));
|
||||
int memp_sync __P((DB_MPOOL *, DB_LSN *));
|
||||
int memp_trickle __P((DB_MPOOL *, int, int *));
|
||||
int memp_unlink __P((const char *, int, DB_ENV *));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************
|
||||
* Transactions.
|
||||
*******************************************************/
|
||||
#define DB_TXNVERSION 1
|
||||
#define DB_TXNMAGIC 0x041593
|
||||
|
||||
/* Operations values to the tx_recover() function. */
|
||||
#define DB_TXN_BACKWARD_ROLL 1 /* Read the log backwards. */
|
||||
#define DB_TXN_FORWARD_ROLL 2 /* Read the log forwards. */
|
||||
#define DB_TXN_OPENFILES 3 /* Read for open files. */
|
||||
#define DB_TXN_REDO 4 /* Redo the operation. */
|
||||
#define DB_TXN_UNDO 5 /* Undo the operation. */
|
||||
|
||||
/* Internal transaction status values. */
|
||||
|
||||
/* Transaction statistics structure. */
|
||||
struct __db_txn_active {
|
||||
u_int32_t txnid; /* Transaction ID */
|
||||
DB_LSN lsn; /* Lsn of the begin record */
|
||||
};
|
||||
|
||||
struct __db_txn_stat {
|
||||
DB_LSN st_last_ckp; /* lsn of the last checkpoint */
|
||||
DB_LSN st_pending_ckp; /* last checkpoint did not finish */
|
||||
time_t st_time_ckp; /* time of last checkpoint */
|
||||
u_int32_t st_last_txnid; /* last transaction id given out */
|
||||
u_int32_t st_maxtxns; /* maximum number of active txns */
|
||||
u_int32_t st_naborts; /* number of aborted transactions */
|
||||
u_int32_t st_nbegins; /* number of begun transactions */
|
||||
u_int32_t st_ncommits; /* number of committed transactions */
|
||||
u_int32_t st_nactive; /* number of active transactions */
|
||||
DB_TXN_ACTIVE
|
||||
*st_txnarray; /* array of active transactions */
|
||||
u_int32_t st_region_wait; /* Region lock granted after wait. */
|
||||
u_int32_t st_region_nowait; /* Region lock granted without wait. */
|
||||
u_int32_t st_refcnt; /* Region reference count. */
|
||||
u_int32_t st_regsize; /* Region size. */
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int txn_abort __P((DB_TXN *));
|
||||
int txn_begin __P((DB_TXNMGR *, DB_TXN *, DB_TXN **));
|
||||
int txn_checkpoint __P((const DB_TXNMGR *, u_int32_t, u_int32_t));
|
||||
int txn_commit __P((DB_TXN *));
|
||||
int txn_close __P((DB_TXNMGR *));
|
||||
u_int32_t txn_id __P((DB_TXN *));
|
||||
int txn_open __P((const char *, u_int32_t, int, DB_ENV *, DB_TXNMGR **));
|
||||
int txn_prepare __P((DB_TXN *));
|
||||
int txn_stat __P((DB_TXNMGR *, DB_TXN_STAT **, void *(*)(size_t)));
|
||||
int txn_unlink __P((const char *, int, DB_ENV *));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef DB_DBM_HSEARCH
|
||||
#define DB_DBM_HSEARCH 0 /* No historic interfaces by default. */
|
||||
#endif
|
||||
#if DB_DBM_HSEARCH != 0
|
||||
/*******************************************************
|
||||
* Dbm/Ndbm historic interfaces.
|
||||
*******************************************************/
|
||||
#define DBM_INSERT 0 /* Flags to dbm_store(). */
|
||||
#define DBM_REPLACE 1
|
||||
|
||||
/*
|
||||
* The db(3) support for ndbm(3) always appends this suffix to the
|
||||
* file name to avoid overwriting the user's original database.
|
||||
*/
|
||||
#define DBM_SUFFIX ".db"
|
||||
|
||||
#if defined(_XPG4_2)
|
||||
typedef struct {
|
||||
char *dptr;
|
||||
size_t dsize;
|
||||
} datum;
|
||||
#else
|
||||
typedef struct {
|
||||
char *dptr;
|
||||
int dsize;
|
||||
} datum;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Translate DBM calls into DB calls so that DB doesn't step on the
|
||||
* application's name space.
|
||||
*
|
||||
* The global variables dbrdonly, dirf and pagf were not retained when
|
||||
* 4BSD replaced the dbm interface with ndbm, and are not support here.
|
||||
*/
|
||||
#define dbminit(a) __db_dbm_init(a)
|
||||
#if !defined(__cplusplus)
|
||||
#define delete(a) __db_dbm_delete(a)
|
||||
#endif
|
||||
#define fetch(a) __db_dbm_fetch(a)
|
||||
#define firstkey __db_dbm_firstkey
|
||||
#define nextkey(a) __db_dbm_nextkey(a)
|
||||
#define store(a, b) __db_dbm_store(a, b)
|
||||
|
||||
/* Prototype the DB calls. */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int __db_dbm_init __P((char *));
|
||||
int __db_dbm_delete __P((datum));
|
||||
int __db_dbm_dbrdonly __P((void));
|
||||
int __db_dbm_dirf __P((void));
|
||||
datum __db_dbm_fetch __P((datum));
|
||||
datum __db_dbm_firstkey __P((void));
|
||||
datum __db_dbm_nextkey __P((datum));
|
||||
int __db_dbm_pagf __P((void));
|
||||
int __db_dbm_store __P((datum, datum));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Translate NDBM calls into DB calls so that DB doesn't step on the
|
||||
* application's name space.
|
||||
*/
|
||||
#define dbm_clearerr(a) __db_ndbm_clearerr(a)
|
||||
#define dbm_close(a) __db_ndbm_close(a)
|
||||
#define dbm_delete(a, b) __db_ndbm_delete(a, b)
|
||||
#define dbm_dirfno(a) __db_ndbm_dirfno(a)
|
||||
#define dbm_error(a) __db_ndbm_error(a)
|
||||
#define dbm_fetch(a, b) __db_ndbm_fetch(a, b)
|
||||
#define dbm_firstkey(a) __db_ndbm_firstkey(a)
|
||||
#define dbm_nextkey(a) __db_ndbm_nextkey(a)
|
||||
#define dbm_open(a, b, c) __db_ndbm_open(a, b, c)
|
||||
#define dbm_pagfno(a) __db_ndbm_pagfno(a)
|
||||
#define dbm_rdonly(a) __db_ndbm_rdonly(a)
|
||||
#define dbm_store(a, b, c, d) __db_ndbm_store(a, b, c, d)
|
||||
|
||||
/* Prototype the DB calls. */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int __db_ndbm_clearerr __P((DBM *));
|
||||
void __db_ndbm_close __P((DBM *));
|
||||
int __db_ndbm_delete __P((DBM *, datum));
|
||||
int __db_ndbm_dirfno __P((DBM *));
|
||||
int __db_ndbm_error __P((DBM *));
|
||||
datum __db_ndbm_fetch __P((DBM *, datum));
|
||||
datum __db_ndbm_firstkey __P((DBM *));
|
||||
datum __db_ndbm_nextkey __P((DBM *));
|
||||
DBM *__db_ndbm_open __P((const char *, int, int));
|
||||
int __db_ndbm_pagfno __P((DBM *));
|
||||
int __db_ndbm_rdonly __P((DBM *));
|
||||
int __db_ndbm_store __P((DBM *, datum, datum, int));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************
|
||||
* Hsearch historic interface.
|
||||
*******************************************************/
|
||||
typedef enum {
|
||||
FIND, ENTER
|
||||
} ACTION;
|
||||
|
||||
typedef struct entry {
|
||||
char *key;
|
||||
char *data;
|
||||
} ENTRY;
|
||||
|
||||
/*
|
||||
* Translate HSEARCH calls into DB calls so that DB doesn't step on the
|
||||
* application's name space.
|
||||
*/
|
||||
#define hcreate(a) __db_hcreate(a)
|
||||
#define hdestroy __db_hdestroy
|
||||
#define hsearch(a, b) __db_hsearch(a, b)
|
||||
|
||||
/* Prototype the DB calls. */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int __db_hcreate __P((size_t));
|
||||
void __db_hdestroy __P((void));
|
||||
ENTRY *__db_hsearch __P((ENTRY, ACTION));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* DB_DBM_HSEARCH */
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* MacOS: Reset Metrowerks C enum sizes.
|
||||
*/
|
||||
#ifdef __MWERKS__
|
||||
#pragma enumsalwaysint reset
|
||||
#endif
|
||||
#endif /* !_DB_H_ */
|
|
@ -1,401 +0,0 @@
|
|||
/* DO NOT EDIT: automatically built by dist/distrib. */
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* @(#)db_int.h.src 10.62 (Sleepycat) 5/23/98
|
||||
*/
|
||||
|
||||
#ifndef _DB_INTERNAL_H_
|
||||
#define _DB_INTERNAL_H_
|
||||
|
||||
#include "db.h" /* Standard DB include file. */
|
||||
#include "queue.h"
|
||||
|
||||
/*******************************************************
|
||||
* General purpose constants and macros.
|
||||
*******************************************************/
|
||||
#define UINT16_T_MAX 0xffff /* Maximum 16 bit unsigned. */
|
||||
#define UINT32_T_MAX 0xffffffff /* Maximum 32 bit unsigned. */
|
||||
|
||||
#define DB_MIN_PGSIZE 0x000200 /* Minimum page size. */
|
||||
#define DB_MAX_PGSIZE 0x010000 /* Maximum page size. */
|
||||
|
||||
#define DB_MINCACHE 10 /* Minimum cached pages */
|
||||
|
||||
#define MEGABYTE 1048576
|
||||
|
||||
/*
|
||||
* If we are unable to determine the underlying filesystem block size, use
|
||||
* 8K on the grounds that most OS's use less than 8K as their VM page size.
|
||||
*/
|
||||
#define DB_DEF_IOSIZE (8 * 1024)
|
||||
|
||||
/*
|
||||
* Aligning items to particular sizes or in pages or memory. ALIGNP is a
|
||||
* separate macro, as we've had to cast the pointer to different integral
|
||||
* types on different architectures.
|
||||
*
|
||||
* We cast pointers into unsigned longs when manipulating them because C89
|
||||
* guarantees that u_long is the largest available integral type and further,
|
||||
* to never generate overflows. However, neither C89 or C9X requires that
|
||||
* any integer type be large enough to hold a pointer, although C9X created
|
||||
* the intptr_t type, which is guaranteed to hold a pointer but may or may
|
||||
* not exist. At some point in the future, we should test for intptr_t and
|
||||
* use it where available.
|
||||
*/
|
||||
#undef ALIGNTYPE
|
||||
#define ALIGNTYPE u_long
|
||||
#undef ALIGNP
|
||||
#define ALIGNP(value, bound) ALIGN((ALIGNTYPE)value, bound)
|
||||
#undef ALIGN
|
||||
#define ALIGN(value, bound) (((value) + (bound) - 1) & ~((bound) - 1))
|
||||
|
||||
/*
|
||||
* There are several on-page structures that are declared to have a number of
|
||||
* fields followed by a variable length array of items. The structure size
|
||||
* without including the variable length array or the address of the first of
|
||||
* those elements can be found using SSZ.
|
||||
*
|
||||
* This macro can also be used to find the offset of a structure element in a
|
||||
* structure. This is used in various places to copy structure elements from
|
||||
* unaligned memory references, e.g., pointers into a packed page.
|
||||
*
|
||||
* There are two versions because compilers object if you take the address of
|
||||
* an array.
|
||||
*/
|
||||
#undef SSZ
|
||||
#define SSZ(name, field) ((int)&(((name *)0)->field))
|
||||
|
||||
#undef SSZA
|
||||
#define SSZA(name, field) ((int)&(((name *)0)->field[0]))
|
||||
|
||||
/* Macros to return per-process address, offsets based on shared regions. */
|
||||
#define R_ADDR(base, offset) ((void *)((u_int8_t *)((base)->addr) + offset))
|
||||
#define R_OFFSET(base, p) ((u_int8_t *)(p) - (u_int8_t *)(base)->addr)
|
||||
|
||||
/* Free and free-string macros that overwrite memory. */
|
||||
#ifdef DIAGNOSTIC
|
||||
#undef FREE
|
||||
#define FREE(p, len) { \
|
||||
memset(p, 0xff, len); \
|
||||
__db_free(p); \
|
||||
}
|
||||
#undef FREES
|
||||
#define FREES(p) { \
|
||||
FREE(p, strlen(p)); \
|
||||
}
|
||||
#else
|
||||
#undef FREE
|
||||
#define FREE(p, len) { \
|
||||
__db_free(p); \
|
||||
}
|
||||
#undef FREES
|
||||
#define FREES(p) { \
|
||||
__db_free(p); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Structure used to print flag values. */
|
||||
typedef struct __fn {
|
||||
u_int32_t mask; /* Flag value. */
|
||||
const char *name; /* Flag name. */
|
||||
} FN;
|
||||
|
||||
/* Set, clear and test flags. */
|
||||
#define F_SET(p, f) (p)->flags |= (f)
|
||||
#define F_CLR(p, f) (p)->flags &= ~(f)
|
||||
#define F_ISSET(p, f) ((p)->flags & (f))
|
||||
#define LF_SET(f) (flags |= (f))
|
||||
#define LF_CLR(f) (flags &= ~(f))
|
||||
#define LF_ISSET(f) (flags & (f))
|
||||
|
||||
/* Display separator string. */
|
||||
#undef DB_LINE
|
||||
#define DB_LINE "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
|
||||
|
||||
/* Global variables. */
|
||||
typedef struct __db_globals {
|
||||
int db_mutexlocks; /* DB_MUTEXLOCKS */
|
||||
int db_region_anon; /* DB_REGION_ANON, DB_REGION_NAME */
|
||||
int db_region_init; /* DB_REGION_INIT */
|
||||
int db_tsl_spins; /* DB_TSL_SPINS */
|
||||
int db_pageyield; /* DB_PAGEYIELD */
|
||||
} DB_GLOBALS;
|
||||
extern DB_GLOBALS __db_global_values;
|
||||
#define DB_GLOBAL(v) __db_global_values.v
|
||||
|
||||
/* Unused, or not-used-yet variable. "Shut that bloody compiler up!" */
|
||||
#define COMPQUIET(n, v) (n) = (v)
|
||||
|
||||
/*
|
||||
* Win16 needs specific syntax on callback functions. Nobody else cares.
|
||||
*/
|
||||
#ifndef DB_CALLBACK
|
||||
#define DB_CALLBACK /* Nothing. */
|
||||
#endif
|
||||
|
||||
/*******************************************************
|
||||
* Files.
|
||||
*******************************************************/
|
||||
/*
|
||||
* We use 1024 as the maximum path length. It's too hard to figure out what
|
||||
* the real path length is, as it was traditionally stored in <sys/param.h>,
|
||||
* and that file isn't always available.
|
||||
*/
|
||||
#undef MAXPATHLEN
|
||||
#define MAXPATHLEN 1024
|
||||
|
||||
#define PATH_DOT "." /* Current working directory. */
|
||||
#define PATH_SEPARATOR "\\/" /* Path separator character. */
|
||||
|
||||
/*******************************************************
|
||||
* Mutex support.
|
||||
*******************************************************/
|
||||
typedef unsigned int tsl_t;
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* Various systems require different alignments for mutexes (the worst we've
|
||||
* seen so far is 16-bytes on some HP architectures). The mutex (tsl_t) must
|
||||
* be first in the db_mutex_t structure, which must itself be first in the
|
||||
* region. This ensures the alignment is as returned by mmap(2), which should
|
||||
* be sufficient. All other mutex users must ensure proper alignment locally.
|
||||
*/
|
||||
#define MUTEX_ALIGNMENT sizeof(unsigned int)
|
||||
|
||||
/*
|
||||
* The offset of a mutex in memory.
|
||||
*
|
||||
* !!!
|
||||
* Not an u_int32_t, so backing file offsets MUST be less than 4Gb. See the
|
||||
* off field of the db_mutex_t as well.
|
||||
*/
|
||||
#define MUTEX_LOCK_OFFSET(a, b) ((u_int32_t)((u_int8_t *)b - (u_int8_t *)a))
|
||||
|
||||
typedef struct _db_mutex_t {
|
||||
#ifdef HAVE_SPINLOCKS
|
||||
tsl_t tsl_resource; /* Resource test and set. */
|
||||
#ifdef DIAGNOSTIC
|
||||
u_int32_t pid; /* Lock holder: 0 or process pid. */
|
||||
#endif
|
||||
#else
|
||||
u_int32_t off; /* Backing file offset. */
|
||||
u_int32_t pid; /* Lock holder: 0 or process pid. */
|
||||
#endif
|
||||
u_int32_t spins; /* Spins before block. */
|
||||
u_int32_t mutex_set_wait; /* Granted after wait. */
|
||||
u_int32_t mutex_set_nowait; /* Granted without waiting. */
|
||||
} db_mutex_t;
|
||||
|
||||
#include "mutex_ext.h"
|
||||
|
||||
/*******************************************************
|
||||
* Access methods.
|
||||
*******************************************************/
|
||||
/* Lock/unlock a DB thread. */
|
||||
#define DB_THREAD_LOCK(dbp) \
|
||||
if (F_ISSET(dbp, DB_AM_THREAD)) \
|
||||
(void)__db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1);
|
||||
#define DB_THREAD_UNLOCK(dbp) \
|
||||
if (F_ISSET(dbp, DB_AM_THREAD)) \
|
||||
(void)__db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1);
|
||||
|
||||
/* Btree/recno local statistics structure. */
|
||||
struct __db_bt_lstat; typedef struct __db_bt_lstat DB_BTREE_LSTAT;
|
||||
struct __db_bt_lstat {
|
||||
u_int32_t bt_freed; /* Pages freed for reuse. */
|
||||
u_int32_t bt_pfxsaved; /* Bytes saved by prefix compression. */
|
||||
u_int32_t bt_split; /* Total number of splits. */
|
||||
u_int32_t bt_rootsplit; /* Root page splits. */
|
||||
u_int32_t bt_fastsplit; /* Fast splits. */
|
||||
u_int32_t bt_added; /* Items added. */
|
||||
u_int32_t bt_deleted; /* Items deleted. */
|
||||
u_int32_t bt_get; /* Items retrieved. */
|
||||
u_int32_t bt_cache_hit; /* Hits in fast-insert code. */
|
||||
u_int32_t bt_cache_miss; /* Misses in fast-insert code. */
|
||||
};
|
||||
|
||||
/*******************************************************
|
||||
* Environment.
|
||||
*******************************************************/
|
||||
/* Type passed to __db_appname(). */
|
||||
typedef enum {
|
||||
DB_APP_NONE=0, /* No type (region). */
|
||||
DB_APP_DATA, /* Data file. */
|
||||
DB_APP_LOG, /* Log file. */
|
||||
DB_APP_TMP /* Temporary file. */
|
||||
} APPNAME;
|
||||
|
||||
/*******************************************************
|
||||
* Shared memory regions.
|
||||
*******************************************************/
|
||||
/*
|
||||
* The shared memory regions share an initial structure so that the general
|
||||
* region code can handle races between the region being deleted and other
|
||||
* processes waiting on the region mutex.
|
||||
*
|
||||
* !!!
|
||||
* Note, the mutex must be the first entry in the region; see comment above.
|
||||
*/
|
||||
typedef struct _rlayout {
|
||||
db_mutex_t lock; /* Region mutex. */
|
||||
#define DB_REGIONMAGIC 0x120897
|
||||
u_int32_t valid; /* Valid magic number. */
|
||||
u_int32_t refcnt; /* Region reference count. */
|
||||
size_t size; /* Region length. */
|
||||
int majver; /* Major version number. */
|
||||
int minver; /* Minor version number. */
|
||||
int patch; /* Patch version number. */
|
||||
#define INVALID_SEGID -1
|
||||
int segid; /* shmget(2) ID, or Win16 segment ID. */
|
||||
|
||||
#define REGION_ANONYMOUS 0x01 /* Region is/should be in anon mem. */
|
||||
u_int32_t flags;
|
||||
} RLAYOUT;
|
||||
|
||||
/*
|
||||
* DB creates all regions on 4K boundaries out of sheer paranoia, so that
|
||||
* we don't make the underlying VM unhappy.
|
||||
*/
|
||||
#define DB_VMPAGESIZE (4 * 1024)
|
||||
#define DB_ROUNDOFF(i) { \
|
||||
(i) += DB_VMPAGESIZE - 1; \
|
||||
(i) -= (i) % DB_VMPAGESIZE; \
|
||||
}
|
||||
|
||||
/*
|
||||
* The interface to region attach is nasty, there is a lot of complex stuff
|
||||
* going on, which has to be retained between create/attach and detach. The
|
||||
* REGINFO structure keeps track of it.
|
||||
*/
|
||||
struct __db_reginfo; typedef struct __db_reginfo REGINFO;
|
||||
struct __db_reginfo {
|
||||
/* Arguments. */
|
||||
DB_ENV *dbenv; /* Region naming info. */
|
||||
APPNAME appname; /* Region naming info. */
|
||||
char *path; /* Region naming info. */
|
||||
const char *file; /* Region naming info. */
|
||||
int mode; /* Region mode, if a file. */
|
||||
size_t size; /* Region size. */
|
||||
u_int32_t dbflags; /* Region file open flags, if a file. */
|
||||
|
||||
/* Results. */
|
||||
char *name; /* Region name. */
|
||||
void *addr; /* Region address. */
|
||||
int fd; /* Fcntl(2) locking file descriptor.
|
||||
NB: this is only valid if a regular
|
||||
file is backing the shared region,
|
||||
and mmap(2) is being used to map it
|
||||
into our address space. */
|
||||
int segid; /* shmget(2) ID, or Win16 segment ID. */
|
||||
|
||||
/* Shared flags. */
|
||||
/* 0x0001 COMMON MASK with RLAYOUT structure. */
|
||||
#define REGION_CANGROW 0x0002 /* Can grow. */
|
||||
#define REGION_CREATED 0x0004 /* Created. */
|
||||
#define REGION_HOLDINGSYS 0x0008 /* Holding system resources. */
|
||||
#define REGION_LASTDETACH 0x0010 /* Delete on last detach. */
|
||||
#define REGION_MALLOC 0x0020 /* Created in malloc'd memory. */
|
||||
#define REGION_PRIVATE 0x0040 /* Private to thread/process. */
|
||||
#define REGION_REMOVED 0x0080 /* Already deleted. */
|
||||
#define REGION_SIZEDEF 0x0100 /* Use default region size if exists. */
|
||||
u_int32_t flags;
|
||||
};
|
||||
|
||||
/*******************************************************
|
||||
* Mpool.
|
||||
*******************************************************/
|
||||
/*
|
||||
* File types for DB access methods. Negative numbers are reserved to DB.
|
||||
*/
|
||||
#define DB_FTYPE_BTREE -1 /* Btree. */
|
||||
#define DB_FTYPE_HASH -2 /* Hash. */
|
||||
|
||||
/* Structure used as the DB pgin/pgout pgcookie. */
|
||||
typedef struct __dbpginfo {
|
||||
size_t db_pagesize; /* Underlying page size. */
|
||||
int needswap; /* If swapping required. */
|
||||
} DB_PGINFO;
|
||||
|
||||
/*******************************************************
|
||||
* Log.
|
||||
*******************************************************/
|
||||
/* Initialize an LSN to 'zero'. */
|
||||
#define ZERO_LSN(LSN) { \
|
||||
(LSN).file = 0; \
|
||||
(LSN).offset = 0; \
|
||||
}
|
||||
|
||||
/* Return 1 if LSN is a 'zero' lsn, otherwise return 0. */
|
||||
#define IS_ZERO_LSN(LSN) ((LSN).file == 0)
|
||||
|
||||
/* Test if we need to log a change. */
|
||||
#define DB_LOGGING(dbp) \
|
||||
(F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER))
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
/*
|
||||
* Debugging macro to log operations.
|
||||
* If DEBUG_WOP is defined, log operations that modify the database.
|
||||
* If DEBUG_ROP is defined, log operations that read the database.
|
||||
*
|
||||
* D dbp
|
||||
* T txn
|
||||
* O operation (string)
|
||||
* K key
|
||||
* A data
|
||||
* F flags
|
||||
*/
|
||||
#define LOG_OP(D, T, O, K, A, F) { \
|
||||
DB_LSN _lsn; \
|
||||
DBT _op; \
|
||||
if (DB_LOGGING((D))) { \
|
||||
memset(&_op, 0, sizeof(_op)); \
|
||||
_op.data = O; \
|
||||
_op.size = strlen(O) + 1; \
|
||||
(void)__db_debug_log((D)->dbenv->lg_info, \
|
||||
T, &_lsn, 0, &_op, (D)->log_fileid, K, A, F); \
|
||||
} \
|
||||
}
|
||||
#ifdef DEBUG_ROP
|
||||
#define DEBUG_LREAD(D, T, O, K, A, F) LOG_OP(D, T, O, K, A, F)
|
||||
#else
|
||||
#define DEBUG_LREAD(D, T, O, K, A, F)
|
||||
#endif
|
||||
#ifdef DEBUG_WOP
|
||||
#define DEBUG_LWRITE(D, T, O, K, A, F) LOG_OP(D, T, O, K, A, F)
|
||||
#else
|
||||
#define DEBUG_LWRITE(D, T, O, K, A, F)
|
||||
#endif
|
||||
#else
|
||||
#define DEBUG_LREAD(D, T, O, K, A, F)
|
||||
#define DEBUG_LWRITE(D, T, O, K, A, F)
|
||||
#endif /* DIAGNOSTIC */
|
||||
|
||||
/*******************************************************
|
||||
* Transactions and recovery.
|
||||
*******************************************************/
|
||||
/*
|
||||
* Out of band value for a lock. The locks are returned to callers as offsets
|
||||
* into the lock regions. Since the RLAYOUT structure begins all regions, an
|
||||
* offset of 0 is guaranteed not to be a valid lock.
|
||||
*/
|
||||
#define LOCK_INVALID 0
|
||||
|
||||
/* The structure allocated for every transaction. */
|
||||
struct __db_txn {
|
||||
DB_TXNMGR *mgrp; /* Pointer to transaction manager. */
|
||||
DB_TXN *parent; /* Pointer to transaction's parent. */
|
||||
DB_LSN last_lsn; /* Lsn of last log write. */
|
||||
u_int32_t txnid; /* Unique transaction id. */
|
||||
size_t off; /* Detail structure within region. */
|
||||
TAILQ_ENTRY(__db_txn) links;
|
||||
};
|
||||
|
||||
#include "os_func.h"
|
||||
#include "os_ext.h"
|
||||
|
||||
#endif /* !_DB_INTERNAL_H_ */
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* "@(#)dllmain.c 10.2 (Netscape) 4/25/98";
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
extern int __os_segdata_init(void);
|
||||
extern int __os_segdata_destroy(void);
|
||||
|
||||
int FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg,
|
||||
WORD wHeapSize, LPSTR lpszCmdLine)
|
||||
{
|
||||
if( wHeapSize > 0 ) {
|
||||
UnlockData(0);
|
||||
}
|
||||
|
||||
if( 0 != __os_segdata_init() ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FAR PASCAL _export WEP(int nParam)
|
||||
{
|
||||
(void)__os_segdata_destroy();
|
||||
return 1;
|
||||
}
|
|
@ -1,326 +0,0 @@
|
|||
# DO NOT EDIT: automatically built by dist/distrib.
|
||||
# See the file LICENSE for redistribution information.
|
||||
#
|
||||
# Copyright (c) 1996, 1997, 1998
|
||||
# Sleepycat Software. All rights reserved.
|
||||
#
|
||||
# @(#)test.tcl 10.28 (Sleepycat) 5/31/98
|
||||
|
||||
source ./include.tcl
|
||||
source ../test/testutils.tcl
|
||||
source ../test/byteorder.tcl
|
||||
|
||||
set testdir ./TESTDIR
|
||||
if { [file exists $testdir] != 1 } {
|
||||
exec $MKDIR $testdir
|
||||
}
|
||||
|
||||
set is_windows_test 1
|
||||
|
||||
set parms(test001) 10000
|
||||
set parms(test002) 10000
|
||||
set parms(test003) ""
|
||||
set parms(test004) {10000 4 0}
|
||||
set parms(test005) 10000
|
||||
set parms(test006) {10000 6}
|
||||
set parms(test007) 10000
|
||||
set parms(test008) {10000 8 0}
|
||||
set parms(test009) 10000
|
||||
set parms(test010) {10000 5 10}
|
||||
set parms(test011) {10000 5 11}
|
||||
set parms(test012) ""
|
||||
set parms(test013) 10000
|
||||
set parms(test014) 10000
|
||||
set parms(test015) {7500 0}
|
||||
set parms(test016) 10000
|
||||
set parms(test017) 10000
|
||||
set parms(test018) 10000
|
||||
set parms(test019) 10000
|
||||
set parms(test020) 10000
|
||||
set parms(test021) 10000
|
||||
set parms(test022) ""
|
||||
set parms(test023) ""
|
||||
set parms(test024) 10000
|
||||
set parms(test025) 10000
|
||||
set parms(test026) {2000 5 26}
|
||||
set parms(test027) {100}
|
||||
set parms(test028) ""
|
||||
set parms(test029) 10000
|
||||
|
||||
set dict ../test/wordlist
|
||||
set alphabet "abcdefghijklmnopqrstuvwxyz"
|
||||
set recd_debug 0
|
||||
|
||||
set loadtests 33
|
||||
set runtests 29
|
||||
set recdtests 5
|
||||
set deadtests 2
|
||||
set bugtests 7
|
||||
set rsrctests 1
|
||||
for { set i 1 } { $i <= $loadtests } {incr i} {
|
||||
set name [format "test%03d.tcl" $i]
|
||||
source ../test/$name
|
||||
}
|
||||
for { set i 1 } { $i <= $recdtests } {incr i} {
|
||||
set name [format "recd%03d.tcl" $i]
|
||||
source ../test/$name
|
||||
}
|
||||
for { set i 1 } { $i <= $deadtests } {incr i} {
|
||||
set name [format "dead%03d.tcl" $i]
|
||||
source ../test/$name
|
||||
}
|
||||
for { set i 1 } { $i <= $bugtests } {incr i} {
|
||||
set name [format "bug%03d.tcl" $i]
|
||||
source ../test/$name
|
||||
}
|
||||
for { set i 1 } { $i <= $rsrctests } {incr i} {
|
||||
set name [format "rsrc%03d.tcl" $i]
|
||||
source ../test/$name
|
||||
}
|
||||
|
||||
source ../test/archive.tcl
|
||||
source ../test/dbm.tcl
|
||||
source ../test/hsearch.tcl
|
||||
source ../test/lock.tcl
|
||||
source ../test/mpool.tcl
|
||||
source ../test/mlock.tcl
|
||||
source ../test/mutex.tcl
|
||||
source ../test/ndbm.tcl
|
||||
source ../test/randomlock.tcl
|
||||
source ../test/log.tcl
|
||||
source ../test/txn.tcl
|
||||
|
||||
# Test driver programs
|
||||
|
||||
# Use args for options
|
||||
proc run_method { method {start 1} {stop 0} args } {
|
||||
global parms
|
||||
global debug_print
|
||||
global debug_on
|
||||
global runtests
|
||||
if { $stop == 0 } {
|
||||
set stop $runtests
|
||||
}
|
||||
puts "run_method: $method $start $stop $args"
|
||||
|
||||
for { set i $start } { $i <= $stop } {incr i} {
|
||||
puts "[timestamp]"
|
||||
set name [format "test%03d" $i]
|
||||
eval $name $method $parms($name) $args
|
||||
if { $debug_print != 0 } {
|
||||
puts ""
|
||||
}
|
||||
if { $debug_on != 0 } {
|
||||
debug
|
||||
}
|
||||
flush stdout
|
||||
flush stderr
|
||||
}
|
||||
}
|
||||
|
||||
proc r { args } {
|
||||
global recdtests
|
||||
|
||||
set l [ lindex $args 0 ]
|
||||
switch $l {
|
||||
ampool { eval mpool -shmem anon [lrange $args 1 end] }
|
||||
archive { eval archive [lrange $args 1 end] }
|
||||
byte {
|
||||
foreach method "DB_HASH DB_BTREE DB_RECNO DB_RRECNO" {
|
||||
byteorder $method
|
||||
}
|
||||
}
|
||||
dbm { eval dbm }
|
||||
dead {
|
||||
eval dead001 [lrange $args 1 end]
|
||||
eval dead002 [lrange $args 1 end]
|
||||
}
|
||||
hsearch { eval htest }
|
||||
lock { eval locktest [lrange $args 1 end] }
|
||||
log { eval logtest [lrange $args 1 end] }
|
||||
mpool { eval mpool [lrange $args 1 end] }
|
||||
nmpool { eval mpool -shmem named [lrange $args 1 end] }
|
||||
mutex { eval mutex [lrange $args 1 end] }
|
||||
ndbm { eval ndbm }
|
||||
recd {
|
||||
foreach method "DB_HASH DB_BTREE DB_RECNO DB_RRECNO" {
|
||||
for { set i 1 } {$i <= $recdtests} {incr i} {
|
||||
set name [format "recd%03d" $i]
|
||||
eval $name $method
|
||||
flush stdout
|
||||
flush stderr
|
||||
}
|
||||
}
|
||||
}
|
||||
rsrc {
|
||||
eval rsrc001
|
||||
}
|
||||
txn { eval txntest [lrange $args 1 end] }
|
||||
default { eval run_method $args }
|
||||
}
|
||||
flush stdout
|
||||
flush stderr
|
||||
}
|
||||
|
||||
proc run_all { } {
|
||||
source include.tcl
|
||||
global runtests
|
||||
global recdtests
|
||||
exec $RM -rf ALL.OUT
|
||||
foreach i "archive byte lock log mpool ampool nmpool mutex txn" {
|
||||
puts "Running $i tests"
|
||||
if [catch {exec ./dbtest << "r $i" >>& ALL.OUT } res] {
|
||||
set o [open ALL.OUT a]
|
||||
puts $o "FAIL: $i test"
|
||||
close $o
|
||||
}
|
||||
}
|
||||
|
||||
# Add deadlock detector tests
|
||||
puts "Running deadlock detection tests."
|
||||
if [catch {exec ./dbtest << "r dead" >>& ALL.OUT} res] {
|
||||
set o [open ALL.OUT a]
|
||||
puts $o "FAIL: deadlock detector test"
|
||||
close $o
|
||||
}
|
||||
|
||||
|
||||
foreach i "DB_BTREE DB_RBTREE DB_HASH DB_RECNO DB_RRECNO" {
|
||||
puts "Running $i tests"
|
||||
for { set j 1 } { $j <= $runtests } {incr j} {
|
||||
if [catch {exec ./dbtest << "run_method $i $j $j" \
|
||||
>>& ALL.OUT } res] {
|
||||
set o [open ALL.OUT a]
|
||||
puts $o "FAIL: [format "test%03d" $j] $i"
|
||||
close $o
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
puts "Running RECNO source tests"
|
||||
if [catch {exec ./dbtest << "r rsrc" >>& ALL.OUT } res] {
|
||||
set o [open ALL.OUT a]
|
||||
puts $o "FAIL: $i test"
|
||||
close $o
|
||||
}
|
||||
|
||||
# Run recovery tests
|
||||
foreach method "DB_HASH DB_BTREE DB_RECNO DB_RRECNO" {
|
||||
puts "Running recovery tests for $method"
|
||||
for { set i 1 } {$i <= $recdtests} {incr i} {
|
||||
set name [format "recd%03d" $i]
|
||||
if [catch {exec ./dbtest << "$name $method" \
|
||||
>>& ALL.OUT } res] {
|
||||
set o [open ALL.OUT a]
|
||||
puts $o "FAIL: $name $method"
|
||||
close $o
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Check historic interfaces
|
||||
foreach t "dbm ndbm hsearch" {
|
||||
if [catch {exec ./dbtest << "r $t" >>& ALL.OUT} res] {
|
||||
set o [open ALL.OUT a]
|
||||
puts $o "FAIL: $t test"
|
||||
close $o
|
||||
}
|
||||
}
|
||||
|
||||
catch { exec $SED -e /^FAIL/p -e d ALL.OUT } res
|
||||
if { [string length $res] == 0 } {
|
||||
puts "Regression Tests Succeeded"
|
||||
} else {
|
||||
puts "Regression Tests Failed; see ALL.OUT for log"
|
||||
}
|
||||
}
|
||||
|
||||
proc convert_method { method } {
|
||||
switch $method {
|
||||
rrecno { return DB_RECNO }
|
||||
RRECNO { return DB_RECNO }
|
||||
db_rrecno { return DB_RECNO }
|
||||
DB_RRECNO { return DB_RECNO }
|
||||
rrec { return DB_RECNO }
|
||||
recno { return DB_RECNO }
|
||||
RECNO { return DB_RECNO }
|
||||
db_recno { return DB_RECNO }
|
||||
DB_RECNO { return DB_RECNO }
|
||||
rec { return DB_RECNO }
|
||||
btree { return DB_BTREE }
|
||||
BTREE { return DB_BTREE }
|
||||
db_btree { return DB_BTREE }
|
||||
DB_BTREE { return DB_BTREE }
|
||||
bt { return DB_BTREE }
|
||||
rbtree { return DB_BTREE }
|
||||
RBTREE { return DB_BTREE }
|
||||
db_rbtree { return DB_BTREE }
|
||||
DB_RBTREE { return DB_BTREE }
|
||||
rbt { return DB_BTREE }
|
||||
hash { return DB_HASH }
|
||||
HASH { return DB_HASH }
|
||||
db_hash { return DB_HASH }
|
||||
DB_HASH { return DB_HASH }
|
||||
h { return DB_HASH }
|
||||
}
|
||||
}
|
||||
|
||||
proc is_rrecno { method } {
|
||||
set names { rrecno RRECNO db_rrecno DB_RRECNO rrec }
|
||||
if { [lsearch $names $method] >= 0 } {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
proc is_rbtree { method } {
|
||||
set names { rbtree RBTREE db_rbtree DB_RBTREE rbt }
|
||||
if { [lsearch $names $method] >= 0 } {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# If recno-with-renumbering or btree-with-renumbering is specified, then
|
||||
# fix the arguments to specify the DB_RENUMBER/DB_RECNUM option for the
|
||||
# -flags argument.
|
||||
proc convert_args { method {largs ""} } {
|
||||
source ./include.tcl
|
||||
set do_flags 0
|
||||
if { [is_rrecno $method] == 1 } {
|
||||
return [add_to_args $DB_RENUMBER $largs]
|
||||
} elseif { [is_rbtree $method] == 1 } {
|
||||
return [add_to_args $DB_RECNUM $largs]
|
||||
}
|
||||
return $largs
|
||||
}
|
||||
|
||||
# Make sure the DB_RECNUM flag is set if we are doing btree.
|
||||
proc number_btree { method {largs ""} } {
|
||||
source ./include.tcl
|
||||
if { [string compare $method "DB_BTREE"] == 0 } {
|
||||
return [add_to_args $DB_RECNUM $largs]
|
||||
}
|
||||
return $largs
|
||||
}
|
||||
|
||||
# We want to set a flag value. Since there already might be one in
|
||||
# args, we need to add to it.
|
||||
proc add_to_args { flag_val {largs ""} } {
|
||||
source ./include.tcl
|
||||
set ndx [lsearch $largs -flags]
|
||||
if { $ndx >= 0 } {
|
||||
# There is already a flags argument
|
||||
incr ndx
|
||||
set f [lindex $largs $ndx]
|
||||
set f [expr $f | $flag_val]
|
||||
set largs [lreplace $largs $ndx $ndx $f]
|
||||
} else {
|
||||
# There is no flags argument
|
||||
lappend largs -flags $flag_val
|
||||
}
|
||||
return $largs
|
||||
}
|
|
@ -1,398 +0,0 @@
|
|||
Microsoft Developer Studio Workspace File, Format Version 5.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "DB_DLL"=.\DB_DLL.DSP - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "DB_Static"=.\DB_Static.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_archive"=.\db_archive.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_buildall"=.\db_buildall.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name db_archive
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name db_checkpoint
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name db_deadlock
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name db_dump
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name db_load
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name db_printlog
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name db_recover
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name db_stat
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name ex_access
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name ex_appinit
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name ex_lock
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name ex_mpool
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name ex_tpcb
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name excxx_access
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name excxx_appinit
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name excxx_lock
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name excxx_mpool
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name excxx_tpcb
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_checkpoint"=.\db_checkpoint.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_deadlock"=.\db_deadlock.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_dump"=.\db_dump.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_load"=.\db_load.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_printlog"=.\db_printlog.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_recover"=.\db_recover.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_stat"=.\db_stat.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "dbtest"=.\dbtest.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "ex_access"=.\ex_access.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "ex_appinit"=.\ex_appinit.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "ex_lock"=.\ex_lock.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "ex_mpool"=.\ex_mpool.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "ex_tpcb"=.\ex_tpcb.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "excxx_access"=.\excxx_access.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "excxx_appinit"=.\excxx_appinit.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "excxx_lock"=.\excxx_lock.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "excxx_mpool"=.\excxx_mpool.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "excxx_tpcb"=.\excxx_tpcb.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Двоичные данные
db/build.win32/DB_DLL.mdp
Двоичные данные
db/build.win32/DB_DLL.mdp
Двоичный файл не отображается.
|
@ -1,19 +0,0 @@
|
|||
Building the Win32 version of DB:
|
||||
|
||||
This directory contains project files for both MSVC4.X and 5.0:
|
||||
|
||||
DB_DLL.mdp Visual C++ 4.0 project file
|
||||
DB_DLL.mak Makefile exported by Visual C++ 4.0.
|
||||
Berkeley_DB.dsw Visual C++ 5.0 project file
|
||||
*.dsp Visual C++ 5.0 subprojects
|
||||
|
||||
In MSVC5.0, open the file "Berkeley_DB.dsw". The 5.0 project files are
|
||||
fully developed, allowing you to build both DLL and static versions of
|
||||
libdb, the test harness and the command-line utilities. If you want to
|
||||
build absolutely everything, select the "db_buildall" subproject and
|
||||
build.
|
||||
|
||||
In MSVC4.X, first move your distribution directory to \db (so that this
|
||||
file is \db\build.win32\README for some drive letter). Then open the file
|
||||
"DB_DLL.mdp". The 4.X project files currently only allow you to build
|
||||
the DLL version of libdb.
|
|
@ -1,209 +0,0 @@
|
|||
/*
|
||||
* @(#)config.h 8.28 (Sleepycat) 5/2/98
|
||||
*
|
||||
* Generated by hand.
|
||||
*/
|
||||
|
||||
/* Define to empty if the keyword does not work. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define if your struct stat has st_blksize. */
|
||||
/* #undef HAVE_ST_BLKSIZE */
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
/* #undef mode_t */
|
||||
|
||||
/* Define to `long' if <sys/types.h> doesn't define. */
|
||||
/* #undef off_t */
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
/* #undef pid_t */
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> doesn't define. */
|
||||
/* #undef size_t */
|
||||
|
||||
/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
|
||||
/* #undef STAT_MACROS_BROKEN */
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define if your processor stores words with the most significant
|
||||
byte first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
/* #undef WORDS_BIGENDIAN */
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
typedef int ssize_t;
|
||||
|
||||
/* Define if you want a debugging version. */
|
||||
/* #undef DEBUG */
|
||||
#if defined(_DEBUG)
|
||||
#if !defined(DEBUG)
|
||||
#define DEBUG 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define if you want a version with run-time diagnostic checking. */
|
||||
/* #undef DIAGNOSTIC */
|
||||
|
||||
/* Define if you have sigfillset (and sigprocmask). */
|
||||
/* #undef HAVE_SIGFILLSET */
|
||||
|
||||
/* Define if building on AIX, HP, Solaris to get big-file environment. */
|
||||
/* #undef HAVE_FILE_OFFSET_BITS */
|
||||
#ifdef HAVE_FILE_OFFSET_BITS
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
|
||||
/* Define if you have spinlocks. */
|
||||
#define HAVE_SPINLOCKS 1
|
||||
|
||||
/* Define if you want to use mc68020/gcc assembly spinlocks. */
|
||||
/* #undef HAVE_ASSEM_MC68020_GCC */
|
||||
|
||||
/* Define if you want to use parisc/gcc assembly spinlocks. */
|
||||
/* #undef HAVE_ASSEM_PARISC_GCC */
|
||||
|
||||
/* Define if you want to use sco/cc assembly spinlocks. */
|
||||
/* #undef HAVE_ASSEM_SCO_CC */
|
||||
|
||||
/* Define if you want to use sparc/gcc assembly spinlocks. */
|
||||
/* #undef HAVE_ASSEM_SPARC_GCC */
|
||||
|
||||
/* Define if you want to use uts4/cc assembly spinlocks. */
|
||||
/* #undef HAVE_ASSEM_UTS4_CC */
|
||||
|
||||
/* Define if you want to use x86/gcc assembly spinlocks. */
|
||||
/* #undef HAVE_ASSEM_X86_GCC */
|
||||
|
||||
/* Define if you have the AIX _check_lock spinlocks. */
|
||||
/* #undef HAVE_FUNC_AIX */
|
||||
|
||||
/* Define if you have the OSF1 or HPPA msemaphore spinlocks. */
|
||||
/* #undef HAVE_FUNC_MSEM */
|
||||
|
||||
/* Define if you have the SGI abilock_t spinlocks. */
|
||||
/* #undef HAVE_FUNC_SGI */
|
||||
|
||||
/* Define if you have the ReliantUNIX spinlock_t spinlocks. */
|
||||
/* #undef HAVE_FUNC_RELIANT */
|
||||
|
||||
/* Define if you have the Solaris mutex_t spinlocks. */
|
||||
/* #undef HAVE_FUNC_SOLARIS */
|
||||
|
||||
/* Define if your sprintf returns a pointer, not a length. */
|
||||
/* #undef SPRINTF_RET_CHARPNT */
|
||||
|
||||
/* Define if you have the directio function. */
|
||||
/* #undef HAVE_DIRECTIO */
|
||||
|
||||
/* Define if you have the getcwd function. */
|
||||
/* #undef HAVE_GETCWD */
|
||||
|
||||
/* Define if you have the getopt function. */
|
||||
/* #undef HAVE_GETOPT */
|
||||
extern int getopt(int, char * const *, const char *);
|
||||
|
||||
/* Define if you have the getuid function. */
|
||||
/* #undef HAVE_GETUID */
|
||||
|
||||
/* Define if you have the memcmp function. */
|
||||
#define HAVE_MEMCMP 1
|
||||
|
||||
/* Define if you have the memcpy function. */
|
||||
#define HAVE_MEMCPY 1
|
||||
|
||||
/* Define if you have the memmove function. */
|
||||
#define HAVE_MEMMOVE 1
|
||||
|
||||
/* Define if you have the mmap function. */
|
||||
/* #undef HAVE_MMAP */
|
||||
|
||||
/* Define if you have the raise function. */
|
||||
#define HAVE_RAISE 1
|
||||
|
||||
/* Define if you have the select function. */
|
||||
/* #undef HAVE_SELECT */
|
||||
|
||||
/* Define if you have the shmget function. */
|
||||
/* #undef HAVE_SHMGET */
|
||||
|
||||
/* Define if you have the snprintf function. */
|
||||
#define HAVE_SNPRINTF 1
|
||||
|
||||
/* Define if you have the strerror function. */
|
||||
#define HAVE_STRERROR 1
|
||||
|
||||
/* Define if you have the strsep function. */
|
||||
/* #undef HAVE_STRSEP */
|
||||
|
||||
/* Define if you have the sysconf function. */
|
||||
/* #undef HAVE_SYSCONF */
|
||||
|
||||
/* Define if you have the vsnprintf function. */
|
||||
#define HAVE_VSNPRINTF 1
|
||||
|
||||
/* Define if you have the <dirent.h> header file. */
|
||||
/* #undef HAVE_DIRENT_H */
|
||||
|
||||
/* Define if you have the <ndir.h> header file. */
|
||||
/* #undef HAVE_NDIR_H */
|
||||
|
||||
/* Define if you have the <sys/dir.h> header file. */
|
||||
/* #undef HAVE_SYS_DIR_H */
|
||||
|
||||
/* Define if you have the <sys/ndir.h> header file. */
|
||||
/* #undef HAVE_SYS_NDIR_H */
|
||||
|
||||
/* Define if you have the <sys/select.h> header file. */
|
||||
/* #undef HAVE_SYS_SELECT_H */
|
||||
|
||||
/* Define if you have the <sys/time.h> header file. */
|
||||
/* #undef HAVE_SYS_TIME_H */
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* The following is not part of the automatic configuration setup,
|
||||
* but provides the information necessary to build DB.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <limits.h>
|
||||
#include <memory.h>
|
||||
#include <process.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#include <iostream.h>
|
||||
#endif
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include "queue.h"
|
||||
#include "shqueue.h"
|
||||
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
|
||||
#define NO_SYSTEM_INCLUDES
|
||||
|
||||
/*
|
||||
* This is a grievous hack -- once we've included windows.h, we have no choice
|
||||
* but to use ANSI-style varargs (because it pulls in stdarg.h for us). DB's
|
||||
* code decides which type of varargs to use based on the state of __STDC__.
|
||||
* Sensible. Unfortunately, Microsoft's compiler _doesn't_ define __STDC__
|
||||
* unless you invoke it with arguments turning OFF all vendor extensions. Even
|
||||
* more unfortunately, if we do that, it fails to parse windows.h!!!!! So, we
|
||||
* define __STDC__ here, after windows.h comes in. Note: the compiler knows
|
||||
* we've defined it, and starts enforcing strict ANSI compilance from this point
|
||||
* on.
|
||||
*/
|
||||
#define __STDC__ 1
|
|
@ -1,997 +0,0 @@
|
|||
/* DO NOT EDIT: automatically built by dist/distrib. */
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* @(#)db.h.src 10.131 (Sleepycat) 6/2/98
|
||||
*/
|
||||
|
||||
#ifndef _DB_H_
|
||||
#define _DB_H_
|
||||
|
||||
#ifndef __NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* MacOS: ensure that Metrowerks C makes enumeration types int sized.
|
||||
*/
|
||||
#ifdef __MWERKS__
|
||||
#pragma enumsalwaysint on
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Handle function prototypes and the keyword "const". This steps on name
|
||||
* space that DB doesn't control, but all of the other solutions are worse.
|
||||
*
|
||||
* XXX
|
||||
* While Microsoft's compiler is ANSI C compliant, it doesn't have _STDC_
|
||||
* defined by default, you specify a command line flag or #pragma to turn
|
||||
* it on. Don't do that, however, because some of Microsoft's own header
|
||||
* files won't compile.
|
||||
*/
|
||||
#undef __P
|
||||
#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER)
|
||||
#define __P(protos) protos /* ANSI C prototypes */
|
||||
#else
|
||||
#define const
|
||||
#define __P(protos) () /* K&R C preprocessor */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* DB needs basic information about specifically sized types. If they're
|
||||
* not provided by the system, typedef them here.
|
||||
*
|
||||
* We protect them against multiple inclusion using __BIT_TYPES_DEFINED__,
|
||||
* as does BIND and Kerberos, since we don't know for sure what #include
|
||||
* files the user is using.
|
||||
*
|
||||
* !!!
|
||||
* We also provide the standard u_int, u_long etc., if they're not provided
|
||||
* by the system.
|
||||
*/
|
||||
#ifndef __BIT_TYPES_DEFINED__
|
||||
#define __BIT_TYPES_DEFINED__
|
||||
typedef unsigned char u_int8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short u_int16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int u_int32_t;
|
||||
#endif
|
||||
|
||||
#if !defined(_WINSOCKAPI_)
|
||||
typedef unsigned char u_char;
|
||||
typedef unsigned short u_short;
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned long u_long;
|
||||
#endif
|
||||
|
||||
#define DB_VERSION_MAJOR 2
|
||||
#define DB_VERSION_MINOR 4
|
||||
#define DB_VERSION_PATCH 14
|
||||
#define DB_VERSION_STRING "Sleepycat Software: DB 2.4.14: (6/2/98)"
|
||||
|
||||
typedef u_int32_t db_pgno_t; /* Page number type. */
|
||||
typedef u_int16_t db_indx_t; /* Page offset type. */
|
||||
#define DB_MAX_PAGES 0xffffffff /* >= # of pages in a file */
|
||||
|
||||
typedef u_int32_t db_recno_t; /* Record number type. */
|
||||
typedef size_t DB_LOCK; /* Object returned by lock manager. */
|
||||
#define DB_MAX_RECORDS 0xffffffff /* >= # of records in a tree */
|
||||
|
||||
#define DB_FILE_ID_LEN 20 /* DB file ID length. */
|
||||
|
||||
/* Forward structure declarations, so applications get type checking. */
|
||||
struct __db; typedef struct __db DB;
|
||||
#ifdef DB_DBM_HSEARCH
|
||||
typedef struct __db DBM;
|
||||
#endif
|
||||
struct __db_bt_stat; typedef struct __db_bt_stat DB_BTREE_STAT;
|
||||
struct __db_dbt; typedef struct __db_dbt DBT;
|
||||
struct __db_env; typedef struct __db_env DB_ENV;
|
||||
struct __db_info; typedef struct __db_info DB_INFO;
|
||||
struct __db_lock_stat; typedef struct __db_lock_stat DB_LOCK_STAT;
|
||||
struct __db_lockregion; typedef struct __db_lockregion DB_LOCKREGION;
|
||||
struct __db_lockreq; typedef struct __db_lockreq DB_LOCKREQ;
|
||||
struct __db_locktab; typedef struct __db_locktab DB_LOCKTAB;
|
||||
struct __db_log; typedef struct __db_log DB_LOG;
|
||||
struct __db_log_stat; typedef struct __db_log_stat DB_LOG_STAT;
|
||||
struct __db_lsn; typedef struct __db_lsn DB_LSN;
|
||||
struct __db_mpool; typedef struct __db_mpool DB_MPOOL;
|
||||
struct __db_mpool_finfo;typedef struct __db_mpool_finfo DB_MPOOL_FINFO;
|
||||
struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT;
|
||||
struct __db_mpool_stat; typedef struct __db_mpool_stat DB_MPOOL_STAT;
|
||||
struct __db_mpoolfile; typedef struct __db_mpoolfile DB_MPOOLFILE;
|
||||
struct __db_txn; typedef struct __db_txn DB_TXN;
|
||||
struct __db_txn_active; typedef struct __db_txn_active DB_TXN_ACTIVE;
|
||||
struct __db_txn_stat; typedef struct __db_txn_stat DB_TXN_STAT;
|
||||
struct __db_txnmgr; typedef struct __db_txnmgr DB_TXNMGR;
|
||||
struct __db_txnregion; typedef struct __db_txnregion DB_TXNREGION;
|
||||
struct __dbc; typedef struct __dbc DBC;
|
||||
|
||||
/* Key/data structure -- a Data-Base Thang. */
|
||||
struct __db_dbt {
|
||||
void *data; /* key/data */
|
||||
u_int32_t size; /* key/data length */
|
||||
u_int32_t ulen; /* RO: length of user buffer. */
|
||||
u_int32_t dlen; /* RO: get/put record length. */
|
||||
u_int32_t doff; /* RO: get/put record offset. */
|
||||
|
||||
#define DB_DBT_INTERNAL 0x01 /* Perform any mallocs using regular
|
||||
malloc, not the user's malloc. */
|
||||
#define DB_DBT_MALLOC 0x02 /* Return in allocated memory. */
|
||||
#define DB_DBT_PARTIAL 0x04 /* Partial put/get. */
|
||||
#define DB_DBT_USERMEM 0x08 /* Return in user's memory. */
|
||||
u_int32_t flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* DB internal configuration.
|
||||
*
|
||||
* There are a set of functions that the application can replace with its
|
||||
* own versions, and some other knobs which can be turned at run-time.
|
||||
*/
|
||||
#define DB_FUNC_CALLOC 1 /* DELETED: ANSI C calloc. */
|
||||
#define DB_FUNC_CLOSE 2 /* POSIX 1003.1 close. */
|
||||
#define DB_FUNC_DIRFREE 3 /* DB: free directory list. */
|
||||
#define DB_FUNC_DIRLIST 4 /* DB: create directory list. */
|
||||
#define DB_FUNC_EXISTS 5 /* DB: return if file exists. */
|
||||
#define DB_FUNC_FREE 6 /* ANSI C free. */
|
||||
#define DB_FUNC_FSYNC 7 /* POSIX 1003.1 fsync. */
|
||||
#define DB_FUNC_IOINFO 8 /* DB: return file I/O information. */
|
||||
#define DB_FUNC_MALLOC 9 /* ANSI C malloc. */
|
||||
#define DB_FUNC_MAP 10 /* DB: map file into shared memory. */
|
||||
#define DB_FUNC_OPEN 11 /* POSIX 1003.1 open. */
|
||||
#define DB_FUNC_READ 12 /* POSIX 1003.1 read. */
|
||||
#define DB_FUNC_REALLOC 13 /* ANSI C realloc. */
|
||||
#define DB_FUNC_SEEK 14 /* POSIX 1003.1 lseek. */
|
||||
#define DB_FUNC_SLEEP 15 /* DB: sleep secs/usecs. */
|
||||
#define DB_FUNC_STRDUP 16 /* DELETED: DB: strdup(3). */
|
||||
#define DB_FUNC_UNLINK 17 /* POSIX 1003.1 unlink. */
|
||||
#define DB_FUNC_UNMAP 18 /* DB: unmap shared memory file. */
|
||||
#define DB_FUNC_WRITE 19 /* POSIX 1003.1 write. */
|
||||
#define DB_FUNC_YIELD 20 /* DB: yield thread to scheduler. */
|
||||
#define DB_TSL_SPINS 21 /* DB: initialize spin count. */
|
||||
#define DB_FUNC_RUNLINK 22 /* DB: remove a shared region. */
|
||||
#define DB_REGION_ANON 23 /* DB: anonymous, unnamed regions. */
|
||||
#define DB_REGION_INIT 24 /* DB: page-fault regions in create. */
|
||||
#define DB_REGION_NAME 25 /* DB: anonymous, named regions. */
|
||||
#define DB_MUTEXLOCKS 26 /* DB: turn off all mutex locks. */
|
||||
#define DB_PAGEYIELD 27 /* DB: yield the CPU on pool get. */
|
||||
|
||||
/*
|
||||
* Database configuration and initialization.
|
||||
*/
|
||||
/*
|
||||
* Flags understood by both db_open(3) and db_appinit(3).
|
||||
*/
|
||||
#define DB_CREATE 0x000001 /* O_CREAT: create file as necessary. */
|
||||
#define DB_NOMMAP 0x000002 /* Don't mmap underlying file. */
|
||||
#define DB_THREAD 0x000004 /* Free-thread DB package handles. */
|
||||
|
||||
/*
|
||||
* Flags understood by db_appinit(3).
|
||||
*/
|
||||
/* 0x000007 COMMON MASK. */
|
||||
#define DB_INIT_LOCK 0x000008 /* Initialize locking. */
|
||||
#define DB_INIT_LOG 0x000010 /* Initialize logging. */
|
||||
#define DB_INIT_MPOOL 0x000020 /* Initialize mpool. */
|
||||
#define DB_INIT_TXN 0x000040 /* Initialize transactions. */
|
||||
#define DB_MPOOL_PRIVATE 0x000080 /* Mpool: private memory pool. */
|
||||
#define __UNUSED_100 0x000100
|
||||
#define DB_RECOVER 0x000200 /* Run normal recovery. */
|
||||
#define DB_RECOVER_FATAL 0x000400 /* Run catastrophic recovery. */
|
||||
#define DB_TXN_NOSYNC 0x000800 /* Do not sync log on commit. */
|
||||
#define DB_USE_ENVIRON 0x001000 /* Use the environment. */
|
||||
#define DB_USE_ENVIRON_ROOT 0x002000 /* Use the environment if root. */
|
||||
|
||||
/* CURRENTLY UNUSED LOCK FLAGS. */
|
||||
#define DB_TXN_LOCK_2PL 0x000000 /* Two-phase locking. */
|
||||
#define DB_TXN_LOCK_OPTIMIST 0x000000 /* Optimistic locking. */
|
||||
#define DB_TXN_LOCK_MASK 0x000000 /* Lock flags mask. */
|
||||
|
||||
/* CURRENTLY UNUSED LOG FLAGS. */
|
||||
#define DB_TXN_LOG_REDO 0x000000 /* Redo-only logging. */
|
||||
#define DB_TXN_LOG_UNDO 0x000000 /* Undo-only logging. */
|
||||
#define DB_TXN_LOG_UNDOREDO 0x000000 /* Undo/redo write-ahead logging. */
|
||||
#define DB_TXN_LOG_MASK 0x000000 /* Log flags mask. */
|
||||
|
||||
/*
|
||||
* Flags understood by db_open(3).
|
||||
*
|
||||
* DB_EXCL and DB_TEMPORARY are internal only, and are not documented.
|
||||
* DB_SEQUENTIAL is currently internal, but may be exported some day.
|
||||
*/
|
||||
/* 0x000007 COMMON MASK. */
|
||||
/* 0x003fff ALREADY USED. */
|
||||
#define __UNUSED_4000 0x004000
|
||||
#define DB_EXCL 0x008000 /* O_EXCL: exclusive open. */
|
||||
#define DB_RDONLY 0x010000 /* O_RDONLY: read-only. */
|
||||
#define DB_SEQUENTIAL 0x020000 /* Indicate sequential access. */
|
||||
#define DB_TEMPORARY 0x040000 /* Remove on last close. */
|
||||
#define DB_TRUNCATE 0x080000 /* O_TRUNCATE: replace existing DB. */
|
||||
|
||||
/*
|
||||
* Deadlock detector modes; used in the DBENV structure to configure the
|
||||
* locking subsystem.
|
||||
*/
|
||||
#define DB_LOCK_NORUN 0x0
|
||||
#define DB_LOCK_DEFAULT 0x1 /* Default policy. */
|
||||
#define DB_LOCK_OLDEST 0x2 /* Abort oldest transaction. */
|
||||
#define DB_LOCK_RANDOM 0x3 /* Abort random transaction. */
|
||||
#define DB_LOCK_YOUNGEST 0x4 /* Abort youngest transaction. */
|
||||
|
||||
struct __db_env {
|
||||
int db_lorder; /* Byte order. */
|
||||
|
||||
/* Error message callback. */
|
||||
void (*db_errcall) __P((const char *, char *));
|
||||
FILE *db_errfile; /* Error message file stream. */
|
||||
const char *db_errpfx; /* Error message prefix. */
|
||||
int db_verbose; /* Generate debugging messages. */
|
||||
|
||||
/* User paths. */
|
||||
char *db_home; /* Database home. */
|
||||
char *db_log_dir; /* Database log file directory. */
|
||||
char *db_tmp_dir; /* Database tmp file directory. */
|
||||
|
||||
char **db_data_dir; /* Database data file directories. */
|
||||
int data_cnt; /* Database data file slots. */
|
||||
int data_next; /* Next Database data file slot. */
|
||||
|
||||
/* Locking. */
|
||||
DB_LOCKTAB *lk_info; /* Return from lock_open(). */
|
||||
u_int8_t *lk_conflicts; /* Two dimensional conflict matrix. */
|
||||
u_int32_t lk_modes; /* Number of lock modes in table. */
|
||||
u_int32_t lk_max; /* Maximum number of locks. */
|
||||
u_int32_t lk_detect; /* Deadlock detect on all conflicts. */
|
||||
|
||||
/* Logging. */
|
||||
DB_LOG *lg_info; /* Return from log_open(). */
|
||||
u_int32_t lg_max; /* Maximum file size. */
|
||||
|
||||
/* Memory pool. */
|
||||
DB_MPOOL *mp_info; /* Return from memp_open(). */
|
||||
size_t mp_mmapsize; /* Maximum file size for mmap. */
|
||||
size_t mp_size; /* Bytes in the mpool cache. */
|
||||
|
||||
/* Transactions. */
|
||||
DB_TXNMGR *tx_info; /* Return from txn_open(). */
|
||||
u_int32_t tx_max; /* Maximum number of transactions. */
|
||||
int (*tx_recover) /* Dispatch function for recovery. */
|
||||
__P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
|
||||
#define DB_ENV_APPINIT 0x01 /* Paths initialized by db_appinit(). */
|
||||
#define DB_ENV_STANDALONE 0x02 /* Test: freestanding environment. */
|
||||
#define DB_ENV_THREAD 0x04 /* DB_ENV is multi-threaded. */
|
||||
u_int32_t flags; /* Flags. */
|
||||
};
|
||||
|
||||
/*******************************************************
|
||||
* Access methods.
|
||||
*******************************************************/
|
||||
/*
|
||||
* XXX
|
||||
* Changes here must be reflected in java/src/com/sleepycat/db/Db.java.
|
||||
*/
|
||||
typedef enum {
|
||||
DB_BTREE=1, /* B+tree. */
|
||||
DB_HASH, /* Extended Linear Hashing. */
|
||||
DB_RECNO, /* Fixed and variable-length records. */
|
||||
DB_UNKNOWN /* Figure it out on open. */
|
||||
} DBTYPE;
|
||||
|
||||
#define DB_BTREEVERSION 6 /* Current btree version. */
|
||||
#define DB_BTREEOLDVER 6 /* Oldest btree version supported. */
|
||||
#define DB_BTREEMAGIC 0x053162
|
||||
|
||||
#define DB_HASHVERSION 5 /* Current hash version. */
|
||||
#define DB_HASHOLDVER 4 /* Oldest hash version supported. */
|
||||
#define DB_HASHMAGIC 0x061561
|
||||
|
||||
#define DB_LOGVERSION 2 /* Current log version. */
|
||||
#define DB_LOGOLDVER 2 /* Oldest log version supported. */
|
||||
#define DB_LOGMAGIC 0x040988
|
||||
|
||||
struct __db_info {
|
||||
int db_lorder; /* Byte order. */
|
||||
size_t db_cachesize; /* Underlying cache size. */
|
||||
size_t db_pagesize; /* Underlying page size. */
|
||||
|
||||
/* Local heap allocation. */
|
||||
void *(*db_malloc) __P((size_t));
|
||||
|
||||
/* Btree access method. */
|
||||
u_int32_t bt_maxkey; /* Maximum keys per page. */
|
||||
u_int32_t bt_minkey; /* Minimum keys per page. */
|
||||
int (*bt_compare) /* Comparison function. */
|
||||
__P((const DBT *, const DBT *));
|
||||
size_t (*bt_prefix) /* Prefix function. */
|
||||
__P((const DBT *, const DBT *));
|
||||
|
||||
/* Hash access method. */
|
||||
u_int32_t h_ffactor; /* Fill factor. */
|
||||
u_int32_t h_nelem; /* Number of elements. */
|
||||
u_int32_t (*h_hash) /* Hash function. */
|
||||
__P((const void *, u_int32_t));
|
||||
|
||||
/* Recno access method. */
|
||||
int re_pad; /* Fixed-length padding byte. */
|
||||
int re_delim; /* Variable-length delimiting byte. */
|
||||
u_int32_t re_len; /* Length for fixed-length records. */
|
||||
char *re_source; /* Source file name. */
|
||||
|
||||
#define DB_DELIMITER 0x0001 /* Recno: re_delim set. */
|
||||
#define DB_DUP 0x0002 /* Btree, Hash: duplicate keys. */
|
||||
#define DB_FIXEDLEN 0x0004 /* Recno: fixed-length records. */
|
||||
#define DB_PAD 0x0008 /* Recno: re_pad set. */
|
||||
#define DB_RECNUM 0x0010 /* Btree: record numbers. */
|
||||
#define DB_RENUMBER 0x0020 /* Recno: renumber on insert/delete. */
|
||||
#define DB_SNAPSHOT 0x0040 /* Recno: snapshot the input. */
|
||||
u_int32_t flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* DB access method and cursor operation codes. These are implemented as
|
||||
* bit fields for future flexibility, but currently only a single one may
|
||||
* be specified to any function.
|
||||
*/
|
||||
#define DB_AFTER 0x000001 /* c_put() */
|
||||
#define DB_APPEND 0x000002 /* put() */
|
||||
#define DB_BEFORE 0x000004 /* c_put() */
|
||||
#define DB_CHECKPOINT 0x000008 /* log_put(), log_get() */
|
||||
#define DB_CURRENT 0x000010 /* c_get(), c_put(), log_get() */
|
||||
#define DB_FIRST 0x000020 /* c_get(), log_get() */
|
||||
#define DB_FLUSH 0x000040 /* log_put() */
|
||||
#define DB_GET_RECNO 0x000080 /* get(), c_get() */
|
||||
#define DB_KEYFIRST 0x000100 /* c_put() */
|
||||
#define DB_KEYLAST 0x000200 /* c_put() */
|
||||
#define DB_LAST 0x000400 /* c_get(), log_get() */
|
||||
#define DB_NEXT 0x000800 /* c_get(), log_get() */
|
||||
#define DB_NOOVERWRITE 0x001000 /* put() */
|
||||
#define DB_NOSYNC 0x002000 /* close() */
|
||||
#define DB_PREV 0x004000 /* c_get(), log_get() */
|
||||
#define DB_RECORDCOUNT 0x008000 /* stat() */
|
||||
#define DB_SET 0x010000 /* c_get(), log_get() */
|
||||
#define DB_SET_RANGE 0x020000 /* c_get() */
|
||||
#define DB_SET_RECNO 0x040000 /* c_get() */
|
||||
#define DB_CURLSN 0x080000 /* log_put() */
|
||||
|
||||
/*
|
||||
* DB (user visible) error return codes.
|
||||
*
|
||||
* XXX
|
||||
* Changes to any of the user visible error return codes must be reflected
|
||||
* in java/src/com/sleepycat/db/Db.java.
|
||||
*/
|
||||
#define DB_INCOMPLETE ( -1) /* Sync didn't finish. */
|
||||
#define DB_KEYEMPTY ( -2) /* The key/data pair was deleted or
|
||||
was never created by the user. */
|
||||
#define DB_KEYEXIST ( -3) /* The key/data pair already exists. */
|
||||
#define DB_LOCK_DEADLOCK ( -4) /* Locker killed to resolve deadlock. */
|
||||
#define DB_LOCK_NOTGRANTED ( -5) /* Lock unavailable, no-wait set. */
|
||||
#define DB_LOCK_NOTHELD ( -6) /* Lock not held by locker. */
|
||||
#define DB_NOTFOUND ( -7) /* Key/data pair not found (EOF). */
|
||||
|
||||
/* DB (private) error return codes. */
|
||||
#define DB_DELETED ( -8) /* Recovery file marked deleted. */
|
||||
#define DB_NEEDSPLIT ( -9) /* Page needs to be split. */
|
||||
#define DB_REGISTERED (-10) /* Entry was previously registered. */
|
||||
#define DB_SWAPBYTES (-11) /* Database needs byte swapping. */
|
||||
#define DB_TXN_CKP (-12) /* Encountered ckp record in log. */
|
||||
|
||||
struct __db_ilock { /* Internal DB access method lock. */
|
||||
db_pgno_t pgno; /* Page being locked. */
|
||||
/* File id. */
|
||||
u_int8_t fileid[DB_FILE_ID_LEN];
|
||||
};
|
||||
|
||||
/* DB access method description structure. */
|
||||
struct __db {
|
||||
void *mutexp; /* Synchronization for free threading */
|
||||
DBTYPE type; /* DB access method. */
|
||||
DB_ENV *dbenv; /* DB_ENV structure. */
|
||||
DB_ENV *mp_dbenv; /* DB_ENV for local mpool creation. */
|
||||
|
||||
DB *master; /* Original DB created by db_open. */
|
||||
void *internal; /* Access method private. */
|
||||
|
||||
DB_MPOOL *mp; /* The access method's mpool. */
|
||||
DB_MPOOLFILE *mpf; /* The access method's mpool file. */
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Explicit representations of structures in queue.h.
|
||||
*
|
||||
* TAILQ_HEAD(curs_queue, __dbc);
|
||||
*/
|
||||
struct {
|
||||
struct __dbc *tqh_first;
|
||||
struct __dbc **tqh_last;
|
||||
} curs_queue;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Explicit representations of structures in queue.h.
|
||||
*
|
||||
* LIST_HEAD(handleq, __db);
|
||||
* LIST_ENTRY(__db);
|
||||
*/
|
||||
struct {
|
||||
struct __db *lh_first;
|
||||
} handleq; /* List of handles for this DB. */
|
||||
struct {
|
||||
struct __db *le_next;
|
||||
struct __db **le_prev;
|
||||
} links; /* Links for the handle list. */
|
||||
|
||||
u_int32_t log_fileid; /* Logging file id. */
|
||||
|
||||
DB_TXN *txn; /* Current transaction. */
|
||||
u_int32_t locker; /* Default process' locker id. */
|
||||
DBT lock_dbt; /* DBT referencing lock. */
|
||||
struct __db_ilock lock; /* Lock. */
|
||||
|
||||
size_t pgsize; /* Logical page size of file. */
|
||||
|
||||
/* Local heap allocation. */
|
||||
void *(*db_malloc) __P((size_t));
|
||||
|
||||
/* Functions. */
|
||||
int (*close) __P((DB *, u_int32_t));
|
||||
int (*cursor) __P((DB *, DB_TXN *, DBC **));
|
||||
int (*del) __P((DB *, DB_TXN *, DBT *, u_int32_t));
|
||||
int (*fd) __P((DB *, int *));
|
||||
int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
|
||||
int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
|
||||
int (*stat) __P((DB *, void *, void *(*)(size_t), u_int32_t));
|
||||
int (*sync) __P((DB *, u_int32_t));
|
||||
|
||||
#define DB_AM_DUP 0x000001 /* DB_DUP (internal). */
|
||||
#define DB_AM_INMEM 0x000002 /* In-memory; no sync on close. */
|
||||
#define DB_AM_LOCKING 0x000004 /* Perform locking. */
|
||||
#define DB_AM_LOGGING 0x000008 /* Perform logging. */
|
||||
#define DB_AM_MLOCAL 0x000010 /* Database memory pool is local. */
|
||||
#define DB_AM_PGDEF 0x000020 /* Page size was defaulted. */
|
||||
#define DB_AM_RDONLY 0x000040 /* Database is readonly. */
|
||||
#define DB_AM_RECOVER 0x000080 /* In recovery (do not log or lock). */
|
||||
#define DB_AM_SWAP 0x000100 /* Pages need to be byte-swapped. */
|
||||
#define DB_AM_THREAD 0x000200 /* DB is multi-threaded. */
|
||||
#define DB_BT_RECNUM 0x000400 /* DB_RECNUM (internal) */
|
||||
#define DB_HS_DIRTYMETA 0x000800 /* Hash: Metadata page modified. */
|
||||
#define DB_RE_DELIMITER 0x001000 /* DB_DELIMITER (internal). */
|
||||
#define DB_RE_FIXEDLEN 0x002000 /* DB_FIXEDLEN (internal). */
|
||||
#define DB_RE_PAD 0x004000 /* DB_PAD (internal). */
|
||||
#define DB_RE_RENUMBER 0x008000 /* DB_RENUMBER (internal). */
|
||||
#define DB_RE_SNAPSHOT 0x010000 /* DB_SNAPSHOT (internal). */
|
||||
u_int32_t flags;
|
||||
};
|
||||
|
||||
/* Cursor description structure. */
|
||||
struct __dbc {
|
||||
DB *dbp; /* Related DB access method. */
|
||||
DB_TXN *txn; /* Associated transaction. */
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Explicit representations of structures in queue.h.
|
||||
*
|
||||
* TAILQ_ENTRY(__dbc);
|
||||
*/
|
||||
struct {
|
||||
struct __dbc *tqe_next;
|
||||
struct __dbc **tqe_prev;
|
||||
} links;
|
||||
|
||||
void *internal; /* Access method private. */
|
||||
|
||||
int (*c_close) __P((DBC *));
|
||||
int (*c_del) __P((DBC *, u_int32_t));
|
||||
int (*c_get) __P((DBC *, DBT *, DBT *, u_int32_t));
|
||||
int (*c_put) __P((DBC *, DBT *, DBT *, u_int32_t));
|
||||
};
|
||||
|
||||
/* Btree/recno statistics structure. */
|
||||
struct __db_bt_stat {
|
||||
u_int32_t bt_flags; /* Open flags. */
|
||||
u_int32_t bt_maxkey; /* Maxkey value. */
|
||||
u_int32_t bt_minkey; /* Minkey value. */
|
||||
u_int32_t bt_re_len; /* Fixed-length record length. */
|
||||
u_int32_t bt_re_pad; /* Fixed-length record pad. */
|
||||
u_int32_t bt_pagesize; /* Page size. */
|
||||
u_int32_t bt_levels; /* Tree levels. */
|
||||
u_int32_t bt_nrecs; /* Number of records. */
|
||||
u_int32_t bt_int_pg; /* Internal pages. */
|
||||
u_int32_t bt_leaf_pg; /* Leaf pages. */
|
||||
u_int32_t bt_dup_pg; /* Duplicate pages. */
|
||||
u_int32_t bt_over_pg; /* Overflow pages. */
|
||||
u_int32_t bt_free; /* Pages on the free list. */
|
||||
u_int32_t bt_freed; /* Pages freed for reuse. */
|
||||
u_int32_t bt_int_pgfree; /* Bytes free in internal pages. */
|
||||
u_int32_t bt_leaf_pgfree; /* Bytes free in leaf pages. */
|
||||
u_int32_t bt_dup_pgfree; /* Bytes free in duplicate pages. */
|
||||
u_int32_t bt_over_pgfree; /* Bytes free in overflow pages. */
|
||||
u_int32_t bt_pfxsaved; /* Bytes saved by prefix compression. */
|
||||
u_int32_t bt_split; /* Total number of splits. */
|
||||
u_int32_t bt_rootsplit; /* Root page splits. */
|
||||
u_int32_t bt_fastsplit; /* Fast splits. */
|
||||
u_int32_t bt_added; /* Items added. */
|
||||
u_int32_t bt_deleted; /* Items deleted. */
|
||||
u_int32_t bt_get; /* Items retrieved. */
|
||||
u_int32_t bt_cache_hit; /* Hits in fast-insert code. */
|
||||
u_int32_t bt_cache_miss; /* Misses in fast-insert code. */
|
||||
u_int32_t bt_magic; /* Magic number. */
|
||||
u_int32_t bt_version; /* Version number. */
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int db_appinit __P((const char *, char * const *, DB_ENV *, u_int32_t));
|
||||
int db_appexit __P((DB_ENV *));
|
||||
int db_jump_set __P((void *, int));
|
||||
int db_open __P((const char *,
|
||||
DBTYPE, u_int32_t, int, DB_ENV *, DB_INFO *, DB **));
|
||||
int db_value_set __P((int, int));
|
||||
char *db_version __P((int *, int *, int *));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************
|
||||
* Locking
|
||||
*******************************************************/
|
||||
#define DB_LOCKVERSION 1
|
||||
#define DB_LOCKMAGIC 0x090193
|
||||
|
||||
/* Flag values for lock_vec(). */
|
||||
#define DB_LOCK_NOWAIT 0x01 /* Don't wait on unavailable lock. */
|
||||
|
||||
/* Flag values for lock_detect(). */
|
||||
#define DB_LOCK_CONFLICT 0x01 /* Run on any conflict. */
|
||||
|
||||
/*
|
||||
* Request types.
|
||||
*
|
||||
* XXX
|
||||
* Changes here must be reflected in java/src/com/sleepycat/db/Db.java.
|
||||
*/
|
||||
typedef enum {
|
||||
DB_LOCK_DUMP=0, /* Display held locks. */
|
||||
DB_LOCK_GET, /* Get the lock. */
|
||||
DB_LOCK_PUT, /* Release the lock. */
|
||||
DB_LOCK_PUT_ALL, /* Release locker's locks. */
|
||||
DB_LOCK_PUT_OBJ /* Release locker's locks on obj. */
|
||||
} db_lockop_t;
|
||||
|
||||
/*
|
||||
* Simple R/W lock modes and for multi-granularity intention locking.
|
||||
*
|
||||
* XXX
|
||||
* Changes here must be reflected in java/src/com/sleepycat/db/Db.java.
|
||||
*/
|
||||
typedef enum {
|
||||
DB_LOCK_NG=0, /* Not granted. */
|
||||
DB_LOCK_READ, /* Shared/read. */
|
||||
DB_LOCK_WRITE, /* Exclusive/write. */
|
||||
DB_LOCK_IREAD, /* Intent to share/read. */
|
||||
DB_LOCK_IWRITE, /* Intent exclusive/write. */
|
||||
DB_LOCK_IWR /* Intent to read and write. */
|
||||
} db_lockmode_t;
|
||||
|
||||
/*
|
||||
* Status of a lock.
|
||||
*/
|
||||
typedef enum {
|
||||
DB_LSTAT_ABORTED, /* Lock belongs to an aborted txn. */
|
||||
DB_LSTAT_ERR, /* Lock is bad. */
|
||||
DB_LSTAT_FREE, /* Lock is unallocated. */
|
||||
DB_LSTAT_HELD, /* Lock is currently held. */
|
||||
DB_LSTAT_NOGRANT, /* Lock was not granted. */
|
||||
DB_LSTAT_PENDING, /* Lock was waiting and has been
|
||||
* promoted; waiting for the owner
|
||||
* to run and upgrade it to held. */
|
||||
DB_LSTAT_WAITING /* Lock is on the wait queue. */
|
||||
} db_status_t;
|
||||
|
||||
/* Lock request structure. */
|
||||
struct __db_lockreq {
|
||||
db_lockop_t op; /* Operation. */
|
||||
db_lockmode_t mode; /* Requested mode. */
|
||||
u_int32_t locker; /* Locker identity. */
|
||||
DBT *obj; /* Object being locked. */
|
||||
DB_LOCK lock; /* Lock returned. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Commonly used conflict matrices.
|
||||
*
|
||||
* Standard Read/Write (or exclusive/shared) locks.
|
||||
*/
|
||||
#define DB_LOCK_RW_N 3
|
||||
extern const u_int8_t db_rw_conflicts[];
|
||||
|
||||
/* Multi-granularity locking. */
|
||||
#define DB_LOCK_RIW_N 6
|
||||
extern const u_int8_t db_riw_conflicts[];
|
||||
|
||||
struct __db_lock_stat {
|
||||
u_int32_t st_magic; /* Lock file magic number. */
|
||||
u_int32_t st_version; /* Lock file version number. */
|
||||
u_int32_t st_maxlocks; /* Maximum number of locks in table. */
|
||||
u_int32_t st_nmodes; /* Number of lock modes. */
|
||||
u_int32_t st_numobjs; /* Number of objects. */
|
||||
u_int32_t st_nlockers; /* Number of lockers. */
|
||||
u_int32_t st_nconflicts; /* Number of lock conflicts. */
|
||||
u_int32_t st_nrequests; /* Number of lock gets. */
|
||||
u_int32_t st_nreleases; /* Number of lock puts. */
|
||||
u_int32_t st_ndeadlocks; /* Number of lock deadlocks. */
|
||||
u_int32_t st_region_wait; /* Region lock granted after wait. */
|
||||
u_int32_t st_region_nowait; /* Region lock granted without wait. */
|
||||
u_int32_t st_refcnt; /* Region reference count. */
|
||||
u_int32_t st_regsize; /* Region size. */
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int lock_close __P((DB_LOCKTAB *));
|
||||
int lock_detect __P((DB_LOCKTAB *, u_int32_t, u_int32_t));
|
||||
int lock_get __P((DB_LOCKTAB *,
|
||||
u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *));
|
||||
int lock_id __P((DB_LOCKTAB *, u_int32_t *));
|
||||
int lock_open __P((const char *,
|
||||
u_int32_t, int, DB_ENV *, DB_LOCKTAB **));
|
||||
int lock_put __P((DB_LOCKTAB *, DB_LOCK));
|
||||
int lock_stat __P((DB_LOCKTAB *, DB_LOCK_STAT **, void *(*)(size_t)));
|
||||
int lock_unlink __P((const char *, int, DB_ENV *));
|
||||
int lock_vec __P((DB_LOCKTAB *,
|
||||
u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************
|
||||
* Logging.
|
||||
*******************************************************/
|
||||
/* Flag values for log_archive(). */
|
||||
#define DB_ARCH_ABS 0x001 /* Absolute pathnames. */
|
||||
#define DB_ARCH_DATA 0x002 /* Data files. */
|
||||
#define DB_ARCH_LOG 0x004 /* Log files. */
|
||||
|
||||
/*
|
||||
* A DB_LSN has two parts, a fileid which identifies a specific file, and an
|
||||
* offset within that file. The fileid is an unsigned 4-byte quantity that
|
||||
* uniquely identifies a file within the log directory -- currently a simple
|
||||
* counter inside the log. The offset is also an unsigned 4-byte value. The
|
||||
* log manager guarantees the offset is never more than 4 bytes by switching
|
||||
* to a new log file before the maximum length imposed by an unsigned 4-byte
|
||||
* offset is reached.
|
||||
*/
|
||||
struct __db_lsn {
|
||||
u_int32_t file; /* File ID. */
|
||||
u_int32_t offset; /* File offset. */
|
||||
};
|
||||
|
||||
/* Log statistics structure. */
|
||||
struct __db_log_stat {
|
||||
u_int32_t st_magic; /* Log file magic number. */
|
||||
u_int32_t st_version; /* Log file version number. */
|
||||
int st_mode; /* Log file mode. */
|
||||
u_int32_t st_lg_max; /* Maximum log file size. */
|
||||
u_int32_t st_w_bytes; /* Bytes to log. */
|
||||
u_int32_t st_w_mbytes; /* Megabytes to log. */
|
||||
u_int32_t st_wc_bytes; /* Bytes to log since checkpoint. */
|
||||
u_int32_t st_wc_mbytes; /* Megabytes to log since checkpoint. */
|
||||
u_int32_t st_wcount; /* Total syncs to the log. */
|
||||
u_int32_t st_scount; /* Total writes to the log. */
|
||||
u_int32_t st_region_wait; /* Region lock granted after wait. */
|
||||
u_int32_t st_region_nowait; /* Region lock granted without wait. */
|
||||
u_int32_t st_cur_file; /* Current log file number. */
|
||||
u_int32_t st_cur_offset; /* Current log file offset. */
|
||||
u_int32_t st_refcnt; /* Region reference count. */
|
||||
u_int32_t st_regsize; /* Region size. */
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int log_archive __P((DB_LOG *, char **[], u_int32_t, void *(*)(size_t)));
|
||||
int log_close __P((DB_LOG *));
|
||||
int log_compare __P((const DB_LSN *, const DB_LSN *));
|
||||
int log_file __P((DB_LOG *, const DB_LSN *, char *, size_t));
|
||||
int log_flush __P((DB_LOG *, const DB_LSN *));
|
||||
int log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t));
|
||||
int log_open __P((const char *, u_int32_t, int, DB_ENV *, DB_LOG **));
|
||||
int log_put __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t));
|
||||
int log_register __P((DB_LOG *, DB *, const char *, DBTYPE, u_int32_t *));
|
||||
int log_stat __P((DB_LOG *, DB_LOG_STAT **, void *(*)(size_t)));
|
||||
int log_unlink __P((const char *, int, DB_ENV *));
|
||||
int log_unregister __P((DB_LOG *, u_int32_t));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************
|
||||
* Mpool
|
||||
*******************************************************/
|
||||
/* Flag values for memp_fget(). */
|
||||
#define DB_MPOOL_CREATE 0x001 /* Create a page. */
|
||||
#define DB_MPOOL_LAST 0x002 /* Return the last page. */
|
||||
#define DB_MPOOL_NEW 0x004 /* Create a new page. */
|
||||
|
||||
/* Flag values for memp_fput(), memp_fset(). */
|
||||
#define DB_MPOOL_CLEAN 0x001 /* Clear modified bit. */
|
||||
#define DB_MPOOL_DIRTY 0x002 /* Page is modified. */
|
||||
#define DB_MPOOL_DISCARD 0x004 /* Don't cache the page. */
|
||||
|
||||
/* Mpool statistics structure. */
|
||||
struct __db_mpool_stat {
|
||||
size_t st_cachesize; /* Cache size. */
|
||||
u_int32_t st_cache_hit; /* Pages found in the cache. */
|
||||
u_int32_t st_cache_miss; /* Pages not found in the cache. */
|
||||
u_int32_t st_map; /* Pages from mapped files. */
|
||||
u_int32_t st_page_create; /* Pages created in the cache. */
|
||||
u_int32_t st_page_in; /* Pages read in. */
|
||||
u_int32_t st_page_out; /* Pages written out. */
|
||||
u_int32_t st_ro_evict; /* Clean pages forced from the cache. */
|
||||
u_int32_t st_rw_evict; /* Dirty pages forced from the cache. */
|
||||
u_int32_t st_hash_buckets; /* Number of hash buckets. */
|
||||
u_int32_t st_hash_searches; /* Total hash chain searches. */
|
||||
u_int32_t st_hash_longest; /* Longest hash chain searched. */
|
||||
u_int32_t st_hash_examined; /* Total hash entries searched. */
|
||||
u_int32_t st_page_clean; /* Clean pages. */
|
||||
u_int32_t st_page_dirty; /* Dirty pages. */
|
||||
u_int32_t st_page_trickle; /* Pages written by memp_trickle. */
|
||||
u_int32_t st_region_wait; /* Region lock granted after wait. */
|
||||
u_int32_t st_region_nowait; /* Region lock granted without wait. */
|
||||
u_int32_t st_refcnt; /* Region reference count. */
|
||||
u_int32_t st_regsize; /* Region size. */
|
||||
};
|
||||
|
||||
/* Mpool file open information structure. */
|
||||
struct __db_mpool_finfo {
|
||||
int ftype; /* File type. */
|
||||
DBT *pgcookie; /* Byte-string passed to pgin/pgout. */
|
||||
u_int8_t *fileid; /* Unique file ID. */
|
||||
int32_t lsn_offset; /* LSN offset in page. */
|
||||
u_int32_t clear_len; /* Cleared length on created pages. */
|
||||
};
|
||||
|
||||
/* Mpool file statistics structure. */
|
||||
struct __db_mpool_fstat {
|
||||
char *file_name; /* File name. */
|
||||
size_t st_pagesize; /* Page size. */
|
||||
u_int32_t st_cache_hit; /* Pages found in the cache. */
|
||||
u_int32_t st_cache_miss; /* Pages not found in the cache. */
|
||||
u_int32_t st_map; /* Pages from mapped files. */
|
||||
u_int32_t st_page_create; /* Pages created in the cache. */
|
||||
u_int32_t st_page_in; /* Pages read in. */
|
||||
u_int32_t st_page_out; /* Pages written out. */
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int memp_close __P((DB_MPOOL *));
|
||||
int memp_fclose __P((DB_MPOOLFILE *));
|
||||
int memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *));
|
||||
int memp_fopen __P((DB_MPOOL *, const char *,
|
||||
u_int32_t, int, size_t, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
|
||||
int memp_fput __P((DB_MPOOLFILE *, void *, u_int32_t));
|
||||
int memp_fset __P((DB_MPOOLFILE *, void *, u_int32_t));
|
||||
int memp_fsync __P((DB_MPOOLFILE *));
|
||||
int memp_open __P((const char *, u_int32_t, int, DB_ENV *, DB_MPOOL **));
|
||||
int memp_register __P((DB_MPOOL *, int,
|
||||
int (*)(db_pgno_t, void *, DBT *),
|
||||
int (*)(db_pgno_t, void *, DBT *)));
|
||||
int memp_stat __P((DB_MPOOL *,
|
||||
DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, void *(*)(size_t)));
|
||||
int memp_sync __P((DB_MPOOL *, DB_LSN *));
|
||||
int memp_trickle __P((DB_MPOOL *, int, int *));
|
||||
int memp_unlink __P((const char *, int, DB_ENV *));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************
|
||||
* Transactions.
|
||||
*******************************************************/
|
||||
#define DB_TXNVERSION 1
|
||||
#define DB_TXNMAGIC 0x041593
|
||||
|
||||
/* Operations values to the tx_recover() function. */
|
||||
#define DB_TXN_BACKWARD_ROLL 1 /* Read the log backwards. */
|
||||
#define DB_TXN_FORWARD_ROLL 2 /* Read the log forwards. */
|
||||
#define DB_TXN_OPENFILES 3 /* Read for open files. */
|
||||
#define DB_TXN_REDO 4 /* Redo the operation. */
|
||||
#define DB_TXN_UNDO 5 /* Undo the operation. */
|
||||
|
||||
/* Internal transaction status values. */
|
||||
|
||||
/* Transaction statistics structure. */
|
||||
struct __db_txn_active {
|
||||
u_int32_t txnid; /* Transaction ID */
|
||||
DB_LSN lsn; /* Lsn of the begin record */
|
||||
};
|
||||
|
||||
struct __db_txn_stat {
|
||||
DB_LSN st_last_ckp; /* lsn of the last checkpoint */
|
||||
DB_LSN st_pending_ckp; /* last checkpoint did not finish */
|
||||
time_t st_time_ckp; /* time of last checkpoint */
|
||||
u_int32_t st_last_txnid; /* last transaction id given out */
|
||||
u_int32_t st_maxtxns; /* maximum number of active txns */
|
||||
u_int32_t st_naborts; /* number of aborted transactions */
|
||||
u_int32_t st_nbegins; /* number of begun transactions */
|
||||
u_int32_t st_ncommits; /* number of committed transactions */
|
||||
u_int32_t st_nactive; /* number of active transactions */
|
||||
DB_TXN_ACTIVE
|
||||
*st_txnarray; /* array of active transactions */
|
||||
u_int32_t st_region_wait; /* Region lock granted after wait. */
|
||||
u_int32_t st_region_nowait; /* Region lock granted without wait. */
|
||||
u_int32_t st_refcnt; /* Region reference count. */
|
||||
u_int32_t st_regsize; /* Region size. */
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int txn_abort __P((DB_TXN *));
|
||||
int txn_begin __P((DB_TXNMGR *, DB_TXN *, DB_TXN **));
|
||||
int txn_checkpoint __P((const DB_TXNMGR *, u_int32_t, u_int32_t));
|
||||
int txn_commit __P((DB_TXN *));
|
||||
int txn_close __P((DB_TXNMGR *));
|
||||
u_int32_t txn_id __P((DB_TXN *));
|
||||
int txn_open __P((const char *, u_int32_t, int, DB_ENV *, DB_TXNMGR **));
|
||||
int txn_prepare __P((DB_TXN *));
|
||||
int txn_stat __P((DB_TXNMGR *, DB_TXN_STAT **, void *(*)(size_t)));
|
||||
int txn_unlink __P((const char *, int, DB_ENV *));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef DB_DBM_HSEARCH
|
||||
#define DB_DBM_HSEARCH 0 /* No historic interfaces by default. */
|
||||
#endif
|
||||
#if DB_DBM_HSEARCH != 0
|
||||
/*******************************************************
|
||||
* Dbm/Ndbm historic interfaces.
|
||||
*******************************************************/
|
||||
#define DBM_INSERT 0 /* Flags to dbm_store(). */
|
||||
#define DBM_REPLACE 1
|
||||
|
||||
/*
|
||||
* The db(3) support for ndbm(3) always appends this suffix to the
|
||||
* file name to avoid overwriting the user's original database.
|
||||
*/
|
||||
#define DBM_SUFFIX ".db"
|
||||
|
||||
#if defined(_XPG4_2)
|
||||
typedef struct {
|
||||
char *dptr;
|
||||
size_t dsize;
|
||||
} datum;
|
||||
#else
|
||||
typedef struct {
|
||||
char *dptr;
|
||||
int dsize;
|
||||
} datum;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Translate DBM calls into DB calls so that DB doesn't step on the
|
||||
* application's name space.
|
||||
*
|
||||
* The global variables dbrdonly, dirf and pagf were not retained when
|
||||
* 4BSD replaced the dbm interface with ndbm, and are not support here.
|
||||
*/
|
||||
#define dbminit(a) __db_dbm_init(a)
|
||||
#if !defined(__cplusplus)
|
||||
#define delete(a) __db_dbm_delete(a)
|
||||
#endif
|
||||
#define fetch(a) __db_dbm_fetch(a)
|
||||
#define firstkey __db_dbm_firstkey
|
||||
#define nextkey(a) __db_dbm_nextkey(a)
|
||||
#define store(a, b) __db_dbm_store(a, b)
|
||||
|
||||
/* Prototype the DB calls. */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int __db_dbm_init __P((char *));
|
||||
int __db_dbm_delete __P((datum));
|
||||
int __db_dbm_dbrdonly __P((void));
|
||||
int __db_dbm_dirf __P((void));
|
||||
datum __db_dbm_fetch __P((datum));
|
||||
datum __db_dbm_firstkey __P((void));
|
||||
datum __db_dbm_nextkey __P((datum));
|
||||
int __db_dbm_pagf __P((void));
|
||||
int __db_dbm_store __P((datum, datum));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Translate NDBM calls into DB calls so that DB doesn't step on the
|
||||
* application's name space.
|
||||
*/
|
||||
#define dbm_clearerr(a) __db_ndbm_clearerr(a)
|
||||
#define dbm_close(a) __db_ndbm_close(a)
|
||||
#define dbm_delete(a, b) __db_ndbm_delete(a, b)
|
||||
#define dbm_dirfno(a) __db_ndbm_dirfno(a)
|
||||
#define dbm_error(a) __db_ndbm_error(a)
|
||||
#define dbm_fetch(a, b) __db_ndbm_fetch(a, b)
|
||||
#define dbm_firstkey(a) __db_ndbm_firstkey(a)
|
||||
#define dbm_nextkey(a) __db_ndbm_nextkey(a)
|
||||
#define dbm_open(a, b, c) __db_ndbm_open(a, b, c)
|
||||
#define dbm_pagfno(a) __db_ndbm_pagfno(a)
|
||||
#define dbm_rdonly(a) __db_ndbm_rdonly(a)
|
||||
#define dbm_store(a, b, c, d) __db_ndbm_store(a, b, c, d)
|
||||
|
||||
/* Prototype the DB calls. */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int __db_ndbm_clearerr __P((DBM *));
|
||||
void __db_ndbm_close __P((DBM *));
|
||||
int __db_ndbm_delete __P((DBM *, datum));
|
||||
int __db_ndbm_dirfno __P((DBM *));
|
||||
int __db_ndbm_error __P((DBM *));
|
||||
datum __db_ndbm_fetch __P((DBM *, datum));
|
||||
datum __db_ndbm_firstkey __P((DBM *));
|
||||
datum __db_ndbm_nextkey __P((DBM *));
|
||||
DBM *__db_ndbm_open __P((const char *, int, int));
|
||||
int __db_ndbm_pagfno __P((DBM *));
|
||||
int __db_ndbm_rdonly __P((DBM *));
|
||||
int __db_ndbm_store __P((DBM *, datum, datum, int));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************
|
||||
* Hsearch historic interface.
|
||||
*******************************************************/
|
||||
typedef enum {
|
||||
FIND, ENTER
|
||||
} ACTION;
|
||||
|
||||
typedef struct entry {
|
||||
char *key;
|
||||
char *data;
|
||||
} ENTRY;
|
||||
|
||||
/*
|
||||
* Translate HSEARCH calls into DB calls so that DB doesn't step on the
|
||||
* application's name space.
|
||||
*/
|
||||
#define hcreate(a) __db_hcreate(a)
|
||||
#define hdestroy __db_hdestroy
|
||||
#define hsearch(a, b) __db_hsearch(a, b)
|
||||
|
||||
/* Prototype the DB calls. */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
int __db_hcreate __P((size_t));
|
||||
void __db_hdestroy __P((void));
|
||||
ENTRY *__db_hsearch __P((ENTRY, ACTION));
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* DB_DBM_HSEARCH */
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* MacOS: Reset Metrowerks C enum sizes.
|
||||
*/
|
||||
#ifdef __MWERKS__
|
||||
#pragma enumsalwaysint reset
|
||||
#endif
|
||||
#endif /* !_DB_H_ */
|
|
@ -1,99 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="db_archive" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=db_archive - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_archive.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_archive.mak" CFG="db_archive - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "db_archive - Win32 Release" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE "db_archive - Win32 Debug" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "db_archive - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "db_archi"
|
||||
# PROP BASE Intermediate_Dir "db_archi"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "db_archive - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "db_arch0"
|
||||
# PROP BASE Intermediate_Dir "db_arch0"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "db_archive - Win32 Release"
|
||||
# Name "db_archive - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db_archive\db_archive.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getopt.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,80 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="db_buildall" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) External Target" 0x0106
|
||||
|
||||
CFG=DB_BUILDALL - WIN32 DEBUG
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_buildall.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_buildall.mak" CFG="DB_BUILDALL - WIN32 DEBUG"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "db_buildall - Win32 Release" (based on "Win32 (x86) External Target")
|
||||
!MESSAGE "db_buildall - Win32 Debug" (based on "Win32 (x86) External Target")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
|
||||
!IF "$(CFG)" == "db_buildall - Win32 Release"
|
||||
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Cmd_Line "NMAKE /f db_buildall.mak"
|
||||
# PROP BASE Rebuild_Opt "/a"
|
||||
# PROP BASE Target_File "db_buildall.exe"
|
||||
# PROP BASE Bsc_Name "db_buildall.bsc"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Cmd_Line "echo DB release version built."
|
||||
# PROP Rebuild_Opt ""
|
||||
# PROP Target_File "db_buildall.exe"
|
||||
# PROP Bsc_Name "db_buildall.bsc"
|
||||
# PROP Target_Dir ""
|
||||
|
||||
!ELSEIF "$(CFG)" == "db_buildall - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Cmd_Line "NMAKE /f db_buildall.mak"
|
||||
# PROP BASE Rebuild_Opt "/a"
|
||||
# PROP BASE Target_File "db_buildall.exe"
|
||||
# PROP BASE Bsc_Name "db_buildall.bsc"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Cmd_Line "echo DB debug version built."
|
||||
# PROP Rebuild_Opt ""
|
||||
# PROP Target_File "db_buildall.exe"
|
||||
# PROP Bsc_Name "db_buildall.bsc"
|
||||
# PROP Target_Dir ""
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "db_buildall - Win32 Release"
|
||||
# Name "db_buildall - Win32 Debug"
|
||||
|
||||
!IF "$(CFG)" == "db_buildall - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "db_buildall - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,103 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="db_checkpoint" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=db_checkpoint - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_checkpoint.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_checkpoint.mak" CFG="db_checkpoint - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "db_checkpoint - Win32 Release" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE "db_checkpoint - Win32 Debug" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "db_checkpoint - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "db_checkpoint - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "db_check"
|
||||
# PROP BASE Intermediate_Dir "db_check"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "db_checkpoint - Win32 Release"
|
||||
# Name "db_checkpoint - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db_checkpoint\db_checkpoint.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getlong.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getopt.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,103 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="db_deadlock" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=db_deadlock - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_deadlock.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_deadlock.mak" CFG="db_deadlock - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "db_deadlock - Win32 Release" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE "db_deadlock - Win32 Debug" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "db_deadlock - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "db_deadlock - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "db_deadl"
|
||||
# PROP BASE Intermediate_Dir "db_deadl"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "db_deadlock - Win32 Release"
|
||||
# Name "db_deadlock - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db_deadlock\db_deadlock.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getlong.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getopt.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,491 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="DB_DLL" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=DB_DLL - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "DB_DLL.MAK".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "DB_DLL.MAK" CFG="DB_DLL - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "DB_DLL - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "DB_DLL - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "DB_DLL - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
||||
# ADD LINK32 /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb.dll"
|
||||
|
||||
!ELSEIF "$(CFG)" == "DB_DLL - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /YX"config.h" /FD /c
|
||||
# SUBTRACT CPP /Fr
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb.dll" /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "DB_DLL - Win32 Release"
|
||||
# Name "DB_DLL - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_close.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_compare.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_conv.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_cursor.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_delete.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_open.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_page.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_put.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_rec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_recno.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_rsearch.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_search.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_split.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_stat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\btree_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_app.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_except.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_lock.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_log.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_mpool.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_table.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_txn.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\db.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_appinit.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_apprec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_byteorder.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_conv.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_dispatch.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_dup.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\db_int.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_log2.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_overflow.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_pr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_rec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_region.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_ret.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_salloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_shash.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_thread.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\dbm\dbm.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dllmain.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_conv.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_debug.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_dup.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_func.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_page.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_rec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_stat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hsearch\hsearch.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\libdb.def
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\libdb.rc
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\lock\lock.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\lock\lock_conflict.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\lock\lock_deadlock.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\lock\lock_region.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\lock\lock_util.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_archive.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_compare.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_findckp.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_get.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_put.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_rec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_register.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_bh.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_fget.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_fopen.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_fput.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_fset.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_open.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_pr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_region.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_sync.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mutex\mutex.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_abs.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_alloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_config.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_dir.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_fid.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_fsync.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_map.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_oflags.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_open.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_rpath.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_rw.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_seek.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_sleep.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_spin.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_stat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_unlink.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\strsep.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\txn\txn.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\txn\txn_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\txn\txn_rec.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,101 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="db_dump" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=db_dump - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_dump.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_dump.mak" CFG="db_dump - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "db_dump - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "db_dump - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "db_dump - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "db_dump - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "db_dump_"
|
||||
# PROP BASE Intermediate_Dir "db_dump_"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "db_dump - Win32 Release"
|
||||
# Name "db_dump - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\db.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db_dump\db_dump.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getopt.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,401 +0,0 @@
|
|||
/* DO NOT EDIT: automatically built by dist/distrib. */
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* @(#)db_int.h.src 10.62 (Sleepycat) 5/23/98
|
||||
*/
|
||||
|
||||
#ifndef _DB_INTERNAL_H_
|
||||
#define _DB_INTERNAL_H_
|
||||
|
||||
#include "db.h" /* Standard DB include file. */
|
||||
#include "queue.h"
|
||||
|
||||
/*******************************************************
|
||||
* General purpose constants and macros.
|
||||
*******************************************************/
|
||||
#define UINT16_T_MAX 0xffff /* Maximum 16 bit unsigned. */
|
||||
#define UINT32_T_MAX 0xffffffff /* Maximum 32 bit unsigned. */
|
||||
|
||||
#define DB_MIN_PGSIZE 0x000200 /* Minimum page size. */
|
||||
#define DB_MAX_PGSIZE 0x010000 /* Maximum page size. */
|
||||
|
||||
#define DB_MINCACHE 10 /* Minimum cached pages */
|
||||
|
||||
#define MEGABYTE 1048576
|
||||
|
||||
/*
|
||||
* If we are unable to determine the underlying filesystem block size, use
|
||||
* 8K on the grounds that most OS's use less than 8K as their VM page size.
|
||||
*/
|
||||
#define DB_DEF_IOSIZE (8 * 1024)
|
||||
|
||||
/*
|
||||
* Aligning items to particular sizes or in pages or memory. ALIGNP is a
|
||||
* separate macro, as we've had to cast the pointer to different integral
|
||||
* types on different architectures.
|
||||
*
|
||||
* We cast pointers into unsigned longs when manipulating them because C89
|
||||
* guarantees that u_long is the largest available integral type and further,
|
||||
* to never generate overflows. However, neither C89 or C9X requires that
|
||||
* any integer type be large enough to hold a pointer, although C9X created
|
||||
* the intptr_t type, which is guaranteed to hold a pointer but may or may
|
||||
* not exist. At some point in the future, we should test for intptr_t and
|
||||
* use it where available.
|
||||
*/
|
||||
#undef ALIGNTYPE
|
||||
#define ALIGNTYPE u_long
|
||||
#undef ALIGNP
|
||||
#define ALIGNP(value, bound) ALIGN((ALIGNTYPE)value, bound)
|
||||
#undef ALIGN
|
||||
#define ALIGN(value, bound) (((value) + (bound) - 1) & ~((bound) - 1))
|
||||
|
||||
/*
|
||||
* There are several on-page structures that are declared to have a number of
|
||||
* fields followed by a variable length array of items. The structure size
|
||||
* without including the variable length array or the address of the first of
|
||||
* those elements can be found using SSZ.
|
||||
*
|
||||
* This macro can also be used to find the offset of a structure element in a
|
||||
* structure. This is used in various places to copy structure elements from
|
||||
* unaligned memory references, e.g., pointers into a packed page.
|
||||
*
|
||||
* There are two versions because compilers object if you take the address of
|
||||
* an array.
|
||||
*/
|
||||
#undef SSZ
|
||||
#define SSZ(name, field) ((int)&(((name *)0)->field))
|
||||
|
||||
#undef SSZA
|
||||
#define SSZA(name, field) ((int)&(((name *)0)->field[0]))
|
||||
|
||||
/* Macros to return per-process address, offsets based on shared regions. */
|
||||
#define R_ADDR(base, offset) ((void *)((u_int8_t *)((base)->addr) + offset))
|
||||
#define R_OFFSET(base, p) ((u_int8_t *)(p) - (u_int8_t *)(base)->addr)
|
||||
|
||||
/* Free and free-string macros that overwrite memory. */
|
||||
#ifdef DIAGNOSTIC
|
||||
#undef FREE
|
||||
#define FREE(p, len) { \
|
||||
memset(p, 0xff, len); \
|
||||
__db_free(p); \
|
||||
}
|
||||
#undef FREES
|
||||
#define FREES(p) { \
|
||||
FREE(p, strlen(p)); \
|
||||
}
|
||||
#else
|
||||
#undef FREE
|
||||
#define FREE(p, len) { \
|
||||
__db_free(p); \
|
||||
}
|
||||
#undef FREES
|
||||
#define FREES(p) { \
|
||||
__db_free(p); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Structure used to print flag values. */
|
||||
typedef struct __fn {
|
||||
u_int32_t mask; /* Flag value. */
|
||||
const char *name; /* Flag name. */
|
||||
} FN;
|
||||
|
||||
/* Set, clear and test flags. */
|
||||
#define F_SET(p, f) (p)->flags |= (f)
|
||||
#define F_CLR(p, f) (p)->flags &= ~(f)
|
||||
#define F_ISSET(p, f) ((p)->flags & (f))
|
||||
#define LF_SET(f) (flags |= (f))
|
||||
#define LF_CLR(f) (flags &= ~(f))
|
||||
#define LF_ISSET(f) (flags & (f))
|
||||
|
||||
/* Display separator string. */
|
||||
#undef DB_LINE
|
||||
#define DB_LINE "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
|
||||
|
||||
/* Global variables. */
|
||||
typedef struct __db_globals {
|
||||
int db_mutexlocks; /* DB_MUTEXLOCKS */
|
||||
int db_region_anon; /* DB_REGION_ANON, DB_REGION_NAME */
|
||||
int db_region_init; /* DB_REGION_INIT */
|
||||
int db_tsl_spins; /* DB_TSL_SPINS */
|
||||
int db_pageyield; /* DB_PAGEYIELD */
|
||||
} DB_GLOBALS;
|
||||
extern DB_GLOBALS __db_global_values;
|
||||
#define DB_GLOBAL(v) __db_global_values.v
|
||||
|
||||
/* Unused, or not-used-yet variable. "Shut that bloody compiler up!" */
|
||||
#define COMPQUIET(n, v) (n) = (v)
|
||||
|
||||
/*
|
||||
* Win16 needs specific syntax on callback functions. Nobody else cares.
|
||||
*/
|
||||
#ifndef DB_CALLBACK
|
||||
#define DB_CALLBACK /* Nothing. */
|
||||
#endif
|
||||
|
||||
/*******************************************************
|
||||
* Files.
|
||||
*******************************************************/
|
||||
/*
|
||||
* We use 1024 as the maximum path length. It's too hard to figure out what
|
||||
* the real path length is, as it was traditionally stored in <sys/param.h>,
|
||||
* and that file isn't always available.
|
||||
*/
|
||||
#undef MAXPATHLEN
|
||||
#define MAXPATHLEN 1024
|
||||
|
||||
#define PATH_DOT "." /* Current working directory. */
|
||||
#define PATH_SEPARATOR "\\/" /* Path separator character. */
|
||||
|
||||
/*******************************************************
|
||||
* Mutex support.
|
||||
*******************************************************/
|
||||
typedef unsigned int tsl_t;
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* Various systems require different alignments for mutexes (the worst we've
|
||||
* seen so far is 16-bytes on some HP architectures). The mutex (tsl_t) must
|
||||
* be first in the db_mutex_t structure, which must itself be first in the
|
||||
* region. This ensures the alignment is as returned by mmap(2), which should
|
||||
* be sufficient. All other mutex users must ensure proper alignment locally.
|
||||
*/
|
||||
#define MUTEX_ALIGNMENT sizeof(unsigned int)
|
||||
|
||||
/*
|
||||
* The offset of a mutex in memory.
|
||||
*
|
||||
* !!!
|
||||
* Not an off_t, so backing file offsets MUST be less than 4Gb. See the
|
||||
* off field of the db_mutex_t as well.
|
||||
*/
|
||||
#define MUTEX_LOCK_OFFSET(a, b) ((u_int32_t)((u_int8_t *)b - (u_int8_t *)a))
|
||||
|
||||
typedef struct _db_mutex_t {
|
||||
#ifdef HAVE_SPINLOCKS
|
||||
tsl_t tsl_resource; /* Resource test and set. */
|
||||
#ifdef DIAGNOSTIC
|
||||
u_int32_t pid; /* Lock holder: 0 or process pid. */
|
||||
#endif
|
||||
#else
|
||||
u_int32_t off; /* Backing file offset. */
|
||||
u_int32_t pid; /* Lock holder: 0 or process pid. */
|
||||
#endif
|
||||
u_int32_t spins; /* Spins before block. */
|
||||
u_int32_t mutex_set_wait; /* Granted after wait. */
|
||||
u_int32_t mutex_set_nowait; /* Granted without waiting. */
|
||||
} db_mutex_t;
|
||||
|
||||
#include "mutex_ext.h"
|
||||
|
||||
/*******************************************************
|
||||
* Access methods.
|
||||
*******************************************************/
|
||||
/* Lock/unlock a DB thread. */
|
||||
#define DB_THREAD_LOCK(dbp) \
|
||||
if (F_ISSET(dbp, DB_AM_THREAD)) \
|
||||
(void)__db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1);
|
||||
#define DB_THREAD_UNLOCK(dbp) \
|
||||
if (F_ISSET(dbp, DB_AM_THREAD)) \
|
||||
(void)__db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1);
|
||||
|
||||
/* Btree/recno local statistics structure. */
|
||||
struct __db_bt_lstat; typedef struct __db_bt_lstat DB_BTREE_LSTAT;
|
||||
struct __db_bt_lstat {
|
||||
u_int32_t bt_freed; /* Pages freed for reuse. */
|
||||
u_int32_t bt_pfxsaved; /* Bytes saved by prefix compression. */
|
||||
u_int32_t bt_split; /* Total number of splits. */
|
||||
u_int32_t bt_rootsplit; /* Root page splits. */
|
||||
u_int32_t bt_fastsplit; /* Fast splits. */
|
||||
u_int32_t bt_added; /* Items added. */
|
||||
u_int32_t bt_deleted; /* Items deleted. */
|
||||
u_int32_t bt_get; /* Items retrieved. */
|
||||
u_int32_t bt_cache_hit; /* Hits in fast-insert code. */
|
||||
u_int32_t bt_cache_miss; /* Misses in fast-insert code. */
|
||||
};
|
||||
|
||||
/*******************************************************
|
||||
* Environment.
|
||||
*******************************************************/
|
||||
/* Type passed to __db_appname(). */
|
||||
typedef enum {
|
||||
DB_APP_NONE=0, /* No type (region). */
|
||||
DB_APP_DATA, /* Data file. */
|
||||
DB_APP_LOG, /* Log file. */
|
||||
DB_APP_TMP /* Temporary file. */
|
||||
} APPNAME;
|
||||
|
||||
/*******************************************************
|
||||
* Shared memory regions.
|
||||
*******************************************************/
|
||||
/*
|
||||
* The shared memory regions share an initial structure so that the general
|
||||
* region code can handle races between the region being deleted and other
|
||||
* processes waiting on the region mutex.
|
||||
*
|
||||
* !!!
|
||||
* Note, the mutex must be the first entry in the region; see comment above.
|
||||
*/
|
||||
typedef struct _rlayout {
|
||||
db_mutex_t lock; /* Region mutex. */
|
||||
#define DB_REGIONMAGIC 0x120897
|
||||
u_int32_t valid; /* Valid magic number. */
|
||||
u_int32_t refcnt; /* Region reference count. */
|
||||
size_t size; /* Region length. */
|
||||
int majver; /* Major version number. */
|
||||
int minver; /* Minor version number. */
|
||||
int patch; /* Patch version number. */
|
||||
#define INVALID_SEGID -1
|
||||
int segid; /* shmget(2) ID, or Win16 segment ID. */
|
||||
|
||||
#define REGION_ANONYMOUS 0x01 /* Region is/should be in anon mem. */
|
||||
u_int32_t flags;
|
||||
} RLAYOUT;
|
||||
|
||||
/*
|
||||
* DB creates all regions on 4K boundaries out of sheer paranoia, so that
|
||||
* we don't make the underlying VM unhappy.
|
||||
*/
|
||||
#define DB_VMPAGESIZE (4 * 1024)
|
||||
#define DB_ROUNDOFF(i) { \
|
||||
(i) += DB_VMPAGESIZE - 1; \
|
||||
(i) -= (i) % DB_VMPAGESIZE; \
|
||||
}
|
||||
|
||||
/*
|
||||
* The interface to region attach is nasty, there is a lot of complex stuff
|
||||
* going on, which has to be retained between create/attach and detach. The
|
||||
* REGINFO structure keeps track of it.
|
||||
*/
|
||||
struct __db_reginfo; typedef struct __db_reginfo REGINFO;
|
||||
struct __db_reginfo {
|
||||
/* Arguments. */
|
||||
DB_ENV *dbenv; /* Region naming info. */
|
||||
APPNAME appname; /* Region naming info. */
|
||||
char *path; /* Region naming info. */
|
||||
const char *file; /* Region naming info. */
|
||||
int mode; /* Region mode, if a file. */
|
||||
size_t size; /* Region size. */
|
||||
u_int32_t dbflags; /* Region file open flags, if a file. */
|
||||
|
||||
/* Results. */
|
||||
char *name; /* Region name. */
|
||||
void *addr; /* Region address. */
|
||||
int fd; /* Fcntl(2) locking file descriptor.
|
||||
NB: this is only valid if a regular
|
||||
file is backing the shared region,
|
||||
and mmap(2) is being used to map it
|
||||
into our address space. */
|
||||
int segid; /* shmget(2) ID, or Win16 segment ID. */
|
||||
|
||||
/* Shared flags. */
|
||||
/* 0x0001 COMMON MASK with RLAYOUT structure. */
|
||||
#define REGION_CANGROW 0x0002 /* Can grow. */
|
||||
#define REGION_CREATED 0x0004 /* Created. */
|
||||
#define REGION_HOLDINGSYS 0x0008 /* Holding system resources. */
|
||||
#define REGION_LASTDETACH 0x0010 /* Delete on last detach. */
|
||||
#define REGION_MALLOC 0x0020 /* Created in malloc'd memory. */
|
||||
#define REGION_PRIVATE 0x0040 /* Private to thread/process. */
|
||||
#define REGION_REMOVED 0x0080 /* Already deleted. */
|
||||
#define REGION_SIZEDEF 0x0100 /* Use default region size if exists. */
|
||||
u_int32_t flags;
|
||||
};
|
||||
|
||||
/*******************************************************
|
||||
* Mpool.
|
||||
*******************************************************/
|
||||
/*
|
||||
* File types for DB access methods. Negative numbers are reserved to DB.
|
||||
*/
|
||||
#define DB_FTYPE_BTREE -1 /* Btree. */
|
||||
#define DB_FTYPE_HASH -2 /* Hash. */
|
||||
|
||||
/* Structure used as the DB pgin/pgout pgcookie. */
|
||||
typedef struct __dbpginfo {
|
||||
size_t db_pagesize; /* Underlying page size. */
|
||||
int needswap; /* If swapping required. */
|
||||
} DB_PGINFO;
|
||||
|
||||
/*******************************************************
|
||||
* Log.
|
||||
*******************************************************/
|
||||
/* Initialize an LSN to 'zero'. */
|
||||
#define ZERO_LSN(LSN) { \
|
||||
(LSN).file = 0; \
|
||||
(LSN).offset = 0; \
|
||||
}
|
||||
|
||||
/* Return 1 if LSN is a 'zero' lsn, otherwise return 0. */
|
||||
#define IS_ZERO_LSN(LSN) ((LSN).file == 0)
|
||||
|
||||
/* Test if we need to log a change. */
|
||||
#define DB_LOGGING(dbp) \
|
||||
(F_ISSET(dbp, DB_AM_LOGGING) && !F_ISSET(dbp, DB_AM_RECOVER))
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
/*
|
||||
* Debugging macro to log operations.
|
||||
* If DEBUG_WOP is defined, log operations that modify the database.
|
||||
* If DEBUG_ROP is defined, log operations that read the database.
|
||||
*
|
||||
* D dbp
|
||||
* T txn
|
||||
* O operation (string)
|
||||
* K key
|
||||
* A data
|
||||
* F flags
|
||||
*/
|
||||
#define LOG_OP(D, T, O, K, A, F) { \
|
||||
DB_LSN _lsn; \
|
||||
DBT _op; \
|
||||
if (DB_LOGGING((D))) { \
|
||||
memset(&_op, 0, sizeof(_op)); \
|
||||
_op.data = O; \
|
||||
_op.size = strlen(O) + 1; \
|
||||
(void)__db_debug_log((D)->dbenv->lg_info, \
|
||||
T, &_lsn, 0, &_op, (D)->log_fileid, K, A, F); \
|
||||
} \
|
||||
}
|
||||
#ifdef DEBUG_ROP
|
||||
#define DEBUG_LREAD(D, T, O, K, A, F) LOG_OP(D, T, O, K, A, F)
|
||||
#else
|
||||
#define DEBUG_LREAD(D, T, O, K, A, F)
|
||||
#endif
|
||||
#ifdef DEBUG_WOP
|
||||
#define DEBUG_LWRITE(D, T, O, K, A, F) LOG_OP(D, T, O, K, A, F)
|
||||
#else
|
||||
#define DEBUG_LWRITE(D, T, O, K, A, F)
|
||||
#endif
|
||||
#else
|
||||
#define DEBUG_LREAD(D, T, O, K, A, F)
|
||||
#define DEBUG_LWRITE(D, T, O, K, A, F)
|
||||
#endif /* DIAGNOSTIC */
|
||||
|
||||
/*******************************************************
|
||||
* Transactions and recovery.
|
||||
*******************************************************/
|
||||
/*
|
||||
* Out of band value for a lock. The locks are returned to callers as offsets
|
||||
* into the lock regions. Since the RLAYOUT structure begins all regions, an
|
||||
* offset of 0 is guaranteed not to be a valid lock.
|
||||
*/
|
||||
#define LOCK_INVALID 0
|
||||
|
||||
/* The structure allocated for every transaction. */
|
||||
struct __db_txn {
|
||||
DB_TXNMGR *mgrp; /* Pointer to transaction manager. */
|
||||
DB_TXN *parent; /* Pointer to transaction's parent. */
|
||||
DB_LSN last_lsn; /* Lsn of last log write. */
|
||||
u_int32_t txnid; /* Unique transaction id. */
|
||||
size_t off; /* Detail structure within region. */
|
||||
TAILQ_ENTRY(__db_txn) links;
|
||||
};
|
||||
|
||||
#include "os_func.h"
|
||||
#include "os_ext.h"
|
||||
|
||||
#endif /* !_DB_INTERNAL_H_ */
|
|
@ -1,101 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="db_load" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=db_load - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_load.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_load.mak" CFG="db_load - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "db_load - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "db_load - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "db_load - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "db_load - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "db_load_"
|
||||
# PROP BASE Intermediate_Dir "db_load_"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "db_load - Win32 Release"
|
||||
# Name "db_load - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db_load\db_load.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getlong.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getopt.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,99 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="db_printlog" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=db_printlog - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_printlog.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_printlog.mak" CFG="db_printlog - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "db_printlog - Win32 Release" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE "db_printlog - Win32 Debug" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "db_printlog - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "db_printlog - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "db_printlog_"
|
||||
# PROP BASE Intermediate_Dir "db_printlog_"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "db_printlog - Win32 Release"
|
||||
# Name "db_printlog - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db_printlog\db_printlog.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getopt.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,99 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="db_recover" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=db_recover - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_recover.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_recover.mak" CFG="db_recover - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "db_recover - Win32 Release" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE "db_recover - Win32 Debug" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "db_recover - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "db_recover - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "db_recov"
|
||||
# PROP BASE Intermediate_Dir "db_recov"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "db_recover - Win32 Release"
|
||||
# Name "db_recover - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db_recover\db_recover.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getopt.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,97 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="db_stat" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=db_stat - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_stat.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "db_stat.mak" CFG="db_stat - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "db_stat - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "db_stat - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "db_stat - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "db_stat - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "db_stat_"
|
||||
# PROP BASE Intermediate_Dir "db_stat_"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "db_stat - Win32 Release"
|
||||
# Name "db_stat - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db_stat\db_stat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getopt.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,466 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="DB_Static" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=DB_Static - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "DB_Static.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "DB_Static.mak" CFG="DB_Static - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "DB_Static - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "DB_Static - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
|
||||
!IF "$(CFG)" == "DB_Static - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "DB_Stati"
|
||||
# PROP BASE Intermediate_Dir "DB_Stati"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release_libdbs"
|
||||
# PROP Intermediate_Dir "Release_libdbs"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"release\libdbs.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "DB_Static - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "DB_Stat0"
|
||||
# PROP BASE Intermediate_Dir "DB_Stat0"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug_libdbs"
|
||||
# PROP Intermediate_Dir "Debug_libdbs"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"debug\libdbs.lib"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "DB_Static - Win32 Release"
|
||||
# Name "DB_Static - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_close.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_compare.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_conv.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_cursor.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_delete.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_open.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_page.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_put.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_rec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_recno.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_rsearch.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_search.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_split.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\bt_stat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\btree\btree_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_app.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_except.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_lock.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_log.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_mpool.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_table.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\cxx\cxx_txn.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\db.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_appinit.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_apprec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_byteorder.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_conv.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_dispatch.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_dup.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\db_int.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_log2.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_overflow.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_pr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_rec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_region.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_ret.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_salloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\common\db_shash.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\db\db_thread.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\dbm\dbm.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_conv.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_debug.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_dup.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_func.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_page.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_rec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hash\hash_stat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\hsearch\hsearch.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\lock\lock.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\lock\lock_conflict.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\lock\lock_deadlock.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\lock\lock_region.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\lock\lock_util.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_archive.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_compare.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_findckp.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_get.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_put.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_rec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\log\log_register.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_bh.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_fget.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_fopen.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_fput.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_fset.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_open.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_pr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_region.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mp\mp_sync.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mutex\mutex.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_abs.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_alloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_config.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_dir.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_fid.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_fsync.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_map.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_oflags.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_open.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_rpath.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_rw.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_seek.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_sleep.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os.win32\os_spin.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_stat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\os\os_unlink.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\strsep.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\txn\txn.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\txn\txn_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\txn\txn_rec.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,129 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="dbtest" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=dbtest - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "dbtest.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "dbtest.mak" CFG="dbtest - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "dbtest - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "dbtest - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "dbtest - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "dbtest__"
|
||||
# PROP BASE Intermediate_Dir "dbtest__"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdbs.lib tcl80vc.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "dbtest - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "dbtest_0"
|
||||
# PROP BASE Intermediate_Dir "dbtest_0"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir ""
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdbs.lib tcl80.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "dbtest - Win32 Release"
|
||||
# Name "dbtest - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\test\tcl_dbm.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\test\tcl_hsearch.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\test\tcl_lock.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\test\tcl_log.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\test\tcl_mpool.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\test\tcl_mutex.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\test\tcl_ndbm.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\test\tcl_txn.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\test\tclAppInit.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\test\tclWin32Init.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\test\utils.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,94 +0,0 @@
|
|||
//--------------------------------------------------------------------------//
|
||||
// Copyright (C) 1997 Netscape Communications Corporation //
|
||||
//--------------------------------------------------------------------------//
|
||||
/*
|
||||
* @(#)dllmain.c 8.1 (Sleepycat) 3/5/97
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
static int ProcessesAttached = 0;
|
||||
static HINSTANCE Instance; /* Global library instance handle. */
|
||||
|
||||
/*
|
||||
* The following declaration is for the VC++ DLL entry point.
|
||||
*/
|
||||
|
||||
BOOL APIENTRY DllMain (HINSTANCE hInst,
|
||||
DWORD reason, LPVOID reserved);
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* DllEntryPoint --
|
||||
*
|
||||
* This wrapper function is used by Borland to invoke the
|
||||
* initialization code for Tcl. It simply calls the DllMain
|
||||
* routine.
|
||||
*
|
||||
* Results:
|
||||
* See DllMain.
|
||||
*
|
||||
* Side effects:
|
||||
* See DllMain.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
BOOL APIENTRY
|
||||
DllEntryPoint(hInst, reason, reserved)
|
||||
HINSTANCE hInst; /* Library instance handle. */
|
||||
DWORD reason; /* Reason this function is being called. */
|
||||
LPVOID reserved; /* Not used. */
|
||||
{
|
||||
return DllMain(hInst, reason, reserved);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* DllMain --
|
||||
*
|
||||
* This routine is called by the VC++ C run time library init
|
||||
* code, or the DllEntryPoint routine. It is responsible for
|
||||
* initializing various dynamically loaded libraries.
|
||||
*
|
||||
* Results:
|
||||
* TRUE on sucess, FALSE on failure.
|
||||
*
|
||||
* Side effects:
|
||||
* Establishes 32-to-16 bit thunk and initializes sockets library.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
BOOL APIENTRY
|
||||
DllMain(hInst, reason, reserved)
|
||||
HINSTANCE hInst; /* Library instance handle. */
|
||||
DWORD reason; /* Reason this function is being called. */
|
||||
LPVOID reserved; /* Not used. */
|
||||
{
|
||||
switch (reason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
|
||||
/*
|
||||
* Registration of UT need to be done only once for first
|
||||
* attaching process. At that time set the tclWin32s flag
|
||||
* to indicate if the DLL is executing under Win32s or not.
|
||||
*/
|
||||
|
||||
if (ProcessesAttached++) {
|
||||
return FALSE; /* Not the first initialization. */
|
||||
}
|
||||
|
||||
Instance = hInst;
|
||||
return TRUE;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
|
||||
ProcessesAttached--;
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="ex_access" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=ex_access - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ex_access.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ex_access.mak" CFG="ex_access - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "ex_access - Win32 Release" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE "ex_access - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "ex_access - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "ex_acces"
|
||||
# PROP BASE Intermediate_Dir "ex_acces"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 Release/libdb.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "ex_access - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "ex_acce0"
|
||||
# PROP BASE Intermediate_Dir "ex_acce0"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "ex_access - Win32 Release"
|
||||
# Name "ex_access - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\examples\ex_access.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getopt.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,99 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="ex_appinit" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=ex_appinit - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ex_appinit.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ex_appinit.mak" CFG="ex_appinit - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "ex_appinit - Win32 Release" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE "ex_appinit - Win32 Debug" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "ex_appinit - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "ex_appin"
|
||||
# PROP BASE Intermediate_Dir "ex_appin"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 Release/libdb.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "ex_appinit - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "ex_appi0"
|
||||
# PROP BASE Intermediate_Dir "ex_appi0"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "ex_appinit - Win32 Release"
|
||||
# Name "ex_appinit - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\examples\ex_appinit.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getopt.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,97 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="ex_lock" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=ex_lock - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ex_lock.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ex_lock.mak" CFG="ex_lock - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "ex_lock - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "ex_lock - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "ex_lock - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "ex_lock_"
|
||||
# PROP BASE Intermediate_Dir "ex_lock_"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "ex_lock - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "ex_lock0"
|
||||
# PROP BASE Intermediate_Dir "ex_lock0"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "ex_lock - Win32 Release"
|
||||
# Name "ex_lock - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\examples\ex_lock.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getopt.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,98 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="ex_mpool" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=ex_mpool - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ex_mpool.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ex_mpool.mak" CFG="ex_mpool - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "ex_mpool - Win32 Release" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE "ex_mpool - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "ex_mpool - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "ex_mpool"
|
||||
# PROP BASE Intermediate_Dir "ex_mpool"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release\libdb.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "ex_mpool - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "ex_mpoo0"
|
||||
# PROP BASE Intermediate_Dir "ex_mpoo0"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "ex_mpool - Win32 Release"
|
||||
# Name "ex_mpool - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\examples\ex_mpool.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getopt.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,99 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="ex_tpcb" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=ex_tpcb - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ex_tpcb.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ex_tpcb.mak" CFG="ex_tpcb - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "ex_tpcb - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "ex_tpcb - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "ex_tpcb - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "ex_tpcb_"
|
||||
# PROP BASE Intermediate_Dir "ex_tpcb_"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release\libdb.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "ex_tpcb - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "ex_tpcb0"
|
||||
# PROP BASE Intermediate_Dir "ex_tpcb0"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# SUBTRACT CPP /Fr
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /debugtype:both /machine:I386 /fixed:no
|
||||
# SUBTRACT LINK32 /profile
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "ex_tpcb - Win32 Release"
|
||||
# Name "ex_tpcb - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\examples\ex_tpcb.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\clib\getopt.c
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,91 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="excxx_access" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=excxx_access - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "excxx_access.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "excxx_access.mak" CFG="excxx_access - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "excxx_access - Win32 Release" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE "excxx_access - Win32 Debug" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "excxx_access - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "DB_USE_DLL" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "excxx_access - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "DB_USE_DLL" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "excxx_access - Win32 Release"
|
||||
# Name "excxx_access - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\examples_cxx\AccessExample.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,91 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="excxx_appinit" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=excxx_appinit - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "excxx_appinit.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "excxx_appinit.mak" CFG="excxx_appinit - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "excxx_appinit - Win32 Release" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE "excxx_appinit - Win32 Debug" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "excxx_appinit - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "DB_USE_DLL" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "excxx_appinit - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "DB_USE_DLL" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "excxx_appinit - Win32 Release"
|
||||
# Name "excxx_appinit - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\examples_cxx\AppinitExample.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,91 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="excxx_lock" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=excxx_lock - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "excxx_lock.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "excxx_lock.mak" CFG="excxx_lock - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "excxx_lock - Win32 Release" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE "excxx_lock - Win32 Debug" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "excxx_lock - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "DB_USE_DLL" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "excxx_lock - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "DB_USE_DLL" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "excxx_lock - Win32 Release"
|
||||
# Name "excxx_lock - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\examples_cxx\LockExample.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,91 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="excxx_mpool" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=excxx_mpool - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "excxx_mpool.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "excxx_mpool.mak" CFG="excxx_mpool - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "excxx_mpool - Win32 Release" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE "excxx_mpool - Win32 Debug" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "excxx_mpool - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "DB_USE_DLL" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "excxx_mpool - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "DB_USE_DLL" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "excxx_mpool - Win32 Release"
|
||||
# Name "excxx_mpool - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\examples_cxx\MpoolExample.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,91 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="excxx_tpcb" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=excxx_tpcb - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "excxx_tpcb.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "excxx_tpcb.mak" CFG="excxx_tpcb - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "excxx_tpcb - Win32 Release" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE "excxx_tpcb - Win32 Debug" (based on\
|
||||
"Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "excxx_tpcb - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "DB_USE_DLL" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 release/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "excxx_tpcb - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "DB_USE_DLL" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 debug/libdb.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "excxx_tpcb - Win32 Release"
|
||||
# Name "excxx_tpcb - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\examples_cxx\TpcbExample.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,184 +0,0 @@
|
|||
# DO NOT EDIT: automatically built by dist/distrib.
|
||||
global dict
|
||||
global testdir
|
||||
|
||||
set CP c:/tools/cp.exe
|
||||
set DIFF c:/tools/diff.exe
|
||||
set KILL c:/tools/kill.exe
|
||||
set LS c:/tools/ls.exe
|
||||
set MKDIR c:/tools/mkdir.exe
|
||||
set MV c:/tools/mv.exe
|
||||
set RM c:/tools/rm.exe
|
||||
set SED c:/tools/sed.exe
|
||||
set SLEEP c:/tools/sleep.exe
|
||||
set SORT c:/tools/sort.exe
|
||||
set TR c:/tools/tr.exe
|
||||
|
||||
set DB_LOCK_GET 0
|
||||
set DB_LOCK_PUT 1
|
||||
set DB_LOCK_PUT_ALL 2
|
||||
set DB_LOCK_PUT_OBJ 3
|
||||
set DB_LOCK_NG 0
|
||||
set DB_LOCK_READ 1
|
||||
set DB_LOCK_WRITE 2
|
||||
set DB_LOCK_IREAD 3
|
||||
set DB_LOCK_IWRITE 4
|
||||
set DB_LOCK_IWR 5
|
||||
set DB_VERSION_MAJOR 2
|
||||
set DB_VERSION_MINOR 4
|
||||
set DB_VERSION_PATCH 14
|
||||
set DB_MAX_PAGES 0xffffffff
|
||||
set DB_MAX_RECORDS 0xffffffff
|
||||
set DB_FILE_ID_LEN 20
|
||||
set DB_DBT_INTERNAL 0x01
|
||||
set DB_DBT_MALLOC 0x02
|
||||
set DB_DBT_PARTIAL 0x04
|
||||
set DB_DBT_USERMEM 0x08
|
||||
set DB_FUNC_CALLOC 1
|
||||
set DB_FUNC_CLOSE 2
|
||||
set DB_FUNC_DIRFREE 3
|
||||
set DB_FUNC_DIRLIST 4
|
||||
set DB_FUNC_EXISTS 5
|
||||
set DB_FUNC_FREE 6
|
||||
set DB_FUNC_FSYNC 7
|
||||
set DB_FUNC_IOINFO 8
|
||||
set DB_FUNC_MALLOC 9
|
||||
set DB_FUNC_MAP 10
|
||||
set DB_FUNC_OPEN 11
|
||||
set DB_FUNC_READ 12
|
||||
set DB_FUNC_REALLOC 13
|
||||
set DB_FUNC_SEEK 14
|
||||
set DB_FUNC_SLEEP 15
|
||||
set DB_FUNC_STRDUP 16
|
||||
set DB_FUNC_UNLINK 17
|
||||
set DB_FUNC_UNMAP 18
|
||||
set DB_FUNC_WRITE 19
|
||||
set DB_FUNC_YIELD 20
|
||||
set DB_TSL_SPINS 21
|
||||
set DB_FUNC_RUNLINK 22
|
||||
set DB_REGION_ANON 23
|
||||
set DB_REGION_INIT 24
|
||||
set DB_REGION_NAME 25
|
||||
set DB_MUTEXLOCKS 26
|
||||
set DB_PAGEYIELD 27
|
||||
set DB_CREATE 0x000001
|
||||
set DB_NOMMAP 0x000002
|
||||
set DB_THREAD 0x000004
|
||||
set DB_INIT_LOCK 0x000008
|
||||
set DB_INIT_LOG 0x000010
|
||||
set DB_INIT_MPOOL 0x000020
|
||||
set DB_INIT_TXN 0x000040
|
||||
set DB_MPOOL_PRIVATE 0x000080
|
||||
set DB_RECOVER 0x000200
|
||||
set DB_RECOVER_FATAL 0x000400
|
||||
set DB_TXN_NOSYNC 0x000800
|
||||
set DB_USE_ENVIRON 0x001000
|
||||
set DB_USE_ENVIRON_ROOT 0x002000
|
||||
set DB_TXN_LOCK_2PL 0x000000
|
||||
set DB_TXN_LOCK_OPTIMIST 0x000000
|
||||
set DB_TXN_LOCK_MASK 0x000000
|
||||
set DB_TXN_LOG_REDO 0x000000
|
||||
set DB_TXN_LOG_UNDO 0x000000
|
||||
set DB_TXN_LOG_UNDOREDO 0x000000
|
||||
set DB_TXN_LOG_MASK 0x000000
|
||||
set DB_EXCL 0x008000
|
||||
set DB_RDONLY 0x010000
|
||||
set DB_SEQUENTIAL 0x020000
|
||||
set DB_TEMPORARY 0x040000
|
||||
set DB_TRUNCATE 0x080000
|
||||
set DB_LOCK_NORUN 0x0
|
||||
set DB_LOCK_DEFAULT 0x1
|
||||
set DB_LOCK_OLDEST 0x2
|
||||
set DB_LOCK_RANDOM 0x3
|
||||
set DB_LOCK_YOUNGEST 0x4
|
||||
set DB_ENV_APPINIT 0x01
|
||||
set DB_ENV_STANDALONE 0x02
|
||||
set DB_ENV_THREAD 0x04
|
||||
set DB_BTREEVERSION 6
|
||||
set DB_BTREEOLDVER 6
|
||||
set DB_BTREEMAGIC 0x053162
|
||||
set DB_HASHVERSION 5
|
||||
set DB_HASHOLDVER 4
|
||||
set DB_HASHMAGIC 0x061561
|
||||
set DB_LOGVERSION 2
|
||||
set DB_LOGOLDVER 2
|
||||
set DB_LOGMAGIC 0x040988
|
||||
set DB_DELIMITER 0x0001
|
||||
set DB_DUP 0x0002
|
||||
set DB_FIXEDLEN 0x0004
|
||||
set DB_PAD 0x0008
|
||||
set DB_RECNUM 0x0010
|
||||
set DB_RENUMBER 0x0020
|
||||
set DB_SNAPSHOT 0x0040
|
||||
set DB_AFTER 0x000001
|
||||
set DB_APPEND 0x000002
|
||||
set DB_BEFORE 0x000004
|
||||
set DB_CHECKPOINT 0x000008
|
||||
set DB_CURRENT 0x000010
|
||||
set DB_FIRST 0x000020
|
||||
set DB_FLUSH 0x000040
|
||||
set DB_GET_RECNO 0x000080
|
||||
set DB_KEYFIRST 0x000100
|
||||
set DB_KEYLAST 0x000200
|
||||
set DB_LAST 0x000400
|
||||
set DB_NEXT 0x000800
|
||||
set DB_NOOVERWRITE 0x001000
|
||||
set DB_NOSYNC 0x002000
|
||||
set DB_PREV 0x004000
|
||||
set DB_RECORDCOUNT 0x008000
|
||||
set DB_SET 0x010000
|
||||
set DB_SET_RANGE 0x020000
|
||||
set DB_SET_RECNO 0x040000
|
||||
set DB_CURLSN 0x080000
|
||||
set DB_INCOMPLETE -1
|
||||
set DB_KEYEMPTY -2
|
||||
set DB_KEYEXIST -3
|
||||
set DB_LOCK_DEADLOCK -4
|
||||
set DB_LOCK_NOTGRANTED -5
|
||||
set DB_LOCK_NOTHELD -6
|
||||
set DB_NOTFOUND -7
|
||||
set DB_DELETED -8
|
||||
set DB_NEEDSPLIT -9
|
||||
set DB_REGISTERED -10
|
||||
set DB_SWAPBYTES -11
|
||||
set DB_TXN_CKP -12
|
||||
set DB_AM_DUP 0x000001
|
||||
set DB_AM_INMEM 0x000002
|
||||
set DB_AM_LOCKING 0x000004
|
||||
set DB_AM_LOGGING 0x000008
|
||||
set DB_AM_MLOCAL 0x000010
|
||||
set DB_AM_PGDEF 0x000020
|
||||
set DB_AM_RDONLY 0x000040
|
||||
set DB_AM_RECOVER 0x000080
|
||||
set DB_AM_SWAP 0x000100
|
||||
set DB_AM_THREAD 0x000200
|
||||
set DB_BT_RECNUM 0x000400
|
||||
set DB_HS_DIRTYMETA 0x000800
|
||||
set DB_RE_DELIMITER 0x001000
|
||||
set DB_RE_FIXEDLEN 0x002000
|
||||
set DB_RE_PAD 0x004000
|
||||
set DB_RE_RENUMBER 0x008000
|
||||
set DB_RE_SNAPSHOT 0x010000
|
||||
set DB_LOCKVERSION 1
|
||||
set DB_LOCKMAGIC 0x090193
|
||||
set DB_LOCK_NOWAIT 0x01
|
||||
set DB_LOCK_CONFLICT 0x01
|
||||
set DB_LOCK_RW_N 3
|
||||
set DB_LOCK_RIW_N 6
|
||||
set DB_ARCH_ABS 0x001
|
||||
set DB_ARCH_DATA 0x002
|
||||
set DB_ARCH_LOG 0x004
|
||||
set DB_MPOOL_CREATE 0x001
|
||||
set DB_MPOOL_LAST 0x002
|
||||
set DB_MPOOL_NEW 0x004
|
||||
set DB_MPOOL_CLEAN 0x001
|
||||
set DB_MPOOL_DIRTY 0x002
|
||||
set DB_MPOOL_DISCARD 0x004
|
||||
set DB_TXNVERSION 1
|
||||
set DB_TXNMAGIC 0x041593
|
||||
set DB_TXN_BACKWARD_ROLL 1
|
||||
set DB_TXN_FORWARD_ROLL 2
|
||||
set DB_TXN_OPENFILES 3
|
||||
set DB_TXN_REDO 4
|
||||
set DB_TXN_UNDO 5
|
||||
set DB_DBM_HSEARCH 0
|
|
@ -1,112 +0,0 @@
|
|||
; @(#)libdb.def 8.16 (Sleepycat) 5/23/98
|
||||
|
||||
DESCRIPTION 'Berkeley DB 2.0 Library'
|
||||
CODE SHARED READ EXECUTE
|
||||
DATA SHARED READ WRITE
|
||||
EXPORTS
|
||||
db_open @2
|
||||
lock_close @3
|
||||
lock_get @4
|
||||
lock_id @5
|
||||
lock_open @6
|
||||
lock_put @7
|
||||
lock_unlink @8
|
||||
lock_vec @9
|
||||
log_close @10
|
||||
log_compare @11
|
||||
log_file @12
|
||||
log_flush @13
|
||||
log_get @14
|
||||
log_open @15
|
||||
log_put @16
|
||||
log_register @17
|
||||
log_unlink @19
|
||||
log_unregister @20
|
||||
memp_close @21
|
||||
memp_fclose @22
|
||||
memp_fget @23
|
||||
memp_fopen @24
|
||||
memp_fput @25
|
||||
memp_fset @26
|
||||
memp_fsync @27
|
||||
memp_open @28
|
||||
memp_register @29
|
||||
memp_sync @30
|
||||
memp_unlink @31
|
||||
txn_abort @32
|
||||
txn_begin @33
|
||||
txn_checkpoint @34
|
||||
txn_commit @35
|
||||
txn_close @36
|
||||
txn_open @37
|
||||
txn_prepare @38
|
||||
txn_unlink @39
|
||||
db_appexit @48
|
||||
db_version @49
|
||||
db_appinit @50
|
||||
memp_stat @51
|
||||
log_archive @52
|
||||
lock_detect @53
|
||||
txn_id @54
|
||||
txn_stat @55
|
||||
memp_trickle @56
|
||||
db_jump_set @57
|
||||
db_value_set @58
|
||||
log_stat @59
|
||||
lock_stat @60
|
||||
; these are only for testing
|
||||
__db_loadme @201
|
||||
__db_mutex_unlock @207
|
||||
__db_mutex_init @208
|
||||
__db_runlink @210
|
||||
__db_mutex_lock @211
|
||||
__ham_func2 @214
|
||||
__ham_func3 @215
|
||||
__ham_func4 @216
|
||||
__ham_func5 @217
|
||||
__db_hcreate @218
|
||||
__db_hsearch @219
|
||||
__db_hdestroy @220
|
||||
__db_dbm_init @221
|
||||
__db_dbm_delete @222
|
||||
__db_dbm_fetch @223
|
||||
__db_dbm_store @224
|
||||
__db_dbm_firstkey @225
|
||||
__db_dbm_nextkey @226
|
||||
__db_rdetach @227
|
||||
__db_rattach @228
|
||||
__db_ndbm_open @229
|
||||
__db_ndbm_store @230
|
||||
__db_ndbm_rdonly @231
|
||||
__db_ndbm_pagfno @232
|
||||
__db_ndbm_nextkey @233
|
||||
__db_ndbm_firstkey @234
|
||||
__db_ndbm_fetch @235
|
||||
__db_ndbm_error @236
|
||||
__db_ndbm_dirfno @237
|
||||
__db_ndbm_delete @238
|
||||
__db_ndbm_close @239
|
||||
__db_ndbm_clearerr @240
|
||||
__db_close @241
|
||||
__db_read @242
|
||||
__db_open @243
|
||||
__db_write @244
|
||||
__lock_dump_region @245
|
||||
__memp_dump_region @246
|
||||
; these are needed for linking tools
|
||||
__db_dump @401
|
||||
__db_rpath @402
|
||||
__db_dispatch @403
|
||||
__db_err @404
|
||||
__db_init_print @405
|
||||
__txn_init_print @406
|
||||
__log_init_print @407
|
||||
__ham_init_print @408
|
||||
__bam_init_print @409
|
||||
__db_jump @410
|
||||
__ham_pgin @411
|
||||
__ham_pgout @412
|
||||
__bam_pgin @413
|
||||
__bam_pgout @414
|
||||
__db_omode @415
|
||||
__db_prdbt @416
|
|
@ -1,33 +0,0 @@
|
|||
1 VERSIONINFO
|
||||
FILEVERSION 2,0,4,14
|
||||
PRODUCTVERSION 2,0,4,14
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Sleepycat Software\0"
|
||||
VALUE "FileDescription", "Berkeley DB 2.0 DLL\0"
|
||||
VALUE "FileVersion", "2.4.14\0"
|
||||
VALUE "InternalName", "libdb.dll\0"
|
||||
VALUE "LegalCopyright", "Copyright © Sleepycat Software Inc. 1997, 1998\0"
|
||||
VALUE "OriginalFilename", "libdb.dll\0"
|
||||
VALUE "ProductName", "Sleepycat Software libdb\0"
|
||||
VALUE "ProductVersion", "2.4.14\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
|
@ -1,33 +0,0 @@
|
|||
1 VERSIONINFO
|
||||
FILEVERSION %MAJOR%,0,%MINOR%,%PATCH%
|
||||
PRODUCTVERSION %MAJOR%,0,%MINOR%,%PATCH%
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Sleepycat Software\0"
|
||||
VALUE "FileDescription", "Berkeley DB 2.0 DLL\0"
|
||||
VALUE "FileVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
|
||||
VALUE "InternalName", "libdb.dll\0"
|
||||
VALUE "LegalCopyright", "Copyright © Sleepycat Software Inc. 1997, 1998\0"
|
||||
VALUE "OriginalFilename", "libdb.dll\0"
|
||||
VALUE "ProductName", "Sleepycat Software libdb\0"
|
||||
VALUE "ProductVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
168
db/clib/err.c
168
db/clib/err.c
|
@ -1,168 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)err.c 10.4 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "db.h"
|
||||
#include "clib_ext.h"
|
||||
|
||||
extern char *progname;
|
||||
|
||||
/*
|
||||
* err, warn --
|
||||
* Error routines.
|
||||
*
|
||||
* PUBLIC: #ifdef __STDC__
|
||||
* PUBLIC: void err __P((int eval, const char *, ...));
|
||||
* PUBLIC: #else
|
||||
* PUBLIC: void err();
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void
|
||||
#ifdef __STDC__
|
||||
err(int eval, const char *fmt, ...)
|
||||
#else
|
||||
err(eval, fmt, va_alist)
|
||||
int eval;
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
int sverrno;
|
||||
|
||||
#ifdef __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
|
||||
sverrno = errno;
|
||||
(void)fprintf(stderr, "%s: ", progname);
|
||||
if (fmt != NULL) {
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
(void)fprintf(stderr, ": ");
|
||||
}
|
||||
(void)fprintf(stderr, "%s\n", strerror(sverrno));
|
||||
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
/*
|
||||
* PUBLIC: #ifdef __STDC__
|
||||
* PUBLIC: void errx __P((int eval, const char *, ...));
|
||||
* PUBLIC: #else
|
||||
* PUBLIC: void errx();
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void
|
||||
#ifdef __STDC__
|
||||
errx(int eval, const char *fmt, ...)
|
||||
#else
|
||||
errx(eval, fmt, va_alist)
|
||||
int eval;
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#ifdef __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
|
||||
(void)fprintf(stderr, "%s: ", progname);
|
||||
if (fmt != NULL)
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
/*
|
||||
* PUBLIC: #ifdef __STDC__
|
||||
* PUBLIC: void warn __P((const char *, ...));
|
||||
* PUBLIC: #else
|
||||
* PUBLIC: void warn();
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void
|
||||
#ifdef __STDC__
|
||||
warn(const char *fmt, ...)
|
||||
#else
|
||||
warn(fmt, va_alist)
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
int sverrno;
|
||||
|
||||
#ifdef __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
sverrno = errno;
|
||||
|
||||
(void)fprintf(stderr, "%s: ", progname);
|
||||
if (fmt != NULL) {
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
(void)fprintf(stderr, ": ");
|
||||
}
|
||||
(void)fprintf(stderr, "%s\n", strerror(sverrno));
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* PUBLIC: #ifdef __STDC__
|
||||
* PUBLIC: void warnx __P((const char *, ...));
|
||||
* PUBLIC: #else
|
||||
* PUBLIC: void warnx();
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void
|
||||
#ifdef __STDC__
|
||||
warnx(const char *fmt, ...)
|
||||
#else
|
||||
warnx(fmt, va_alist)
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
#ifdef __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
|
||||
(void)fprintf(stderr, "%s: ", progname);
|
||||
if (fmt != NULL)
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
}
|
274
db/clib/getcwd.c
274
db/clib/getcwd.c
|
@ -1,274 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1989, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)getcwd.c 10.7 (Sleepycat) 4/18/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
# define NAMLEN(dirent) strlen((dirent)->d_name)
|
||||
#else
|
||||
# define dirent direct
|
||||
# define NAMLEN(dirent) (dirent)->d_namlen
|
||||
# if HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "db_int.h"
|
||||
|
||||
#define ISDOT(dp) \
|
||||
(dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
|
||||
(dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
|
||||
|
||||
#ifndef dirfd
|
||||
#define dirfd(dirp) ((dirp)->dd_fd)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* getcwd --
|
||||
* Get the current working directory.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_GETCWD
|
||||
* PUBLIC: char *getcwd __P((char *, size_t));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
char *
|
||||
getcwd(pt, size)
|
||||
char *pt;
|
||||
size_t size;
|
||||
{
|
||||
register struct dirent *dp;
|
||||
register DIR *dir;
|
||||
register dev_t dev;
|
||||
register ino_t ino;
|
||||
register int first;
|
||||
register char *bpt, *bup;
|
||||
struct stat s;
|
||||
dev_t root_dev;
|
||||
ino_t root_ino;
|
||||
size_t ptsize, upsize;
|
||||
int save_errno;
|
||||
char *ept, *eup, *up;
|
||||
|
||||
/*
|
||||
* If no buffer specified by the user, allocate one as necessary.
|
||||
* If a buffer is specified, the size has to be non-zero. The path
|
||||
* is built from the end of the buffer backwards.
|
||||
*/
|
||||
if (pt) {
|
||||
ptsize = 0;
|
||||
if (!size) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
if (size == 1) {
|
||||
errno = ERANGE;
|
||||
return (NULL);
|
||||
}
|
||||
ept = pt + size;
|
||||
} else {
|
||||
if ((pt = (char *)__db_malloc(ptsize = 1024 - 4)) == NULL)
|
||||
return (NULL);
|
||||
ept = pt + ptsize;
|
||||
}
|
||||
bpt = ept - 1;
|
||||
*bpt = '\0';
|
||||
|
||||
/*
|
||||
* Allocate bytes (1024 - malloc space) for the string of "../"'s.
|
||||
* Should always be enough (it's 340 levels). If it's not, allocate
|
||||
* as necessary. Special case the first stat, it's ".", not "..".
|
||||
*/
|
||||
if ((up = (char *)__db_malloc(upsize = 1024 - 4)) == NULL)
|
||||
goto err;
|
||||
eup = up + 1024;
|
||||
bup = up;
|
||||
up[0] = '.';
|
||||
up[1] = '\0';
|
||||
|
||||
/* Save root values, so know when to stop. */
|
||||
if (stat("/", &s))
|
||||
goto err;
|
||||
root_dev = s.st_dev;
|
||||
root_ino = s.st_ino;
|
||||
|
||||
errno = 0; /* XXX readdir has no error return. */
|
||||
|
||||
for (first = 1;; first = 0) {
|
||||
/* Stat the current level. */
|
||||
if (lstat(up, &s))
|
||||
goto err;
|
||||
|
||||
/* Save current node values. */
|
||||
ino = s.st_ino;
|
||||
dev = s.st_dev;
|
||||
|
||||
/* Check for reaching root. */
|
||||
if (root_dev == dev && root_ino == ino) {
|
||||
*--bpt = PATH_SEPARATOR[0];
|
||||
/*
|
||||
* It's unclear that it's a requirement to copy the
|
||||
* path to the beginning of the buffer, but it's always
|
||||
* been that way and stuff would probably break.
|
||||
*/
|
||||
bcopy(bpt, pt, ept - bpt);
|
||||
__db_free(up);
|
||||
return (pt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Build pointer to the parent directory, allocating memory
|
||||
* as necessary. Max length is 3 for "../", the largest
|
||||
* possible component name, plus a trailing NULL.
|
||||
*/
|
||||
if (bup + 3 + MAXNAMLEN + 1 >= eup) {
|
||||
if ((up =
|
||||
(char *)__db_realloc(up, upsize *= 2)) == NULL)
|
||||
goto err;
|
||||
bup = up;
|
||||
eup = up + upsize;
|
||||
}
|
||||
*bup++ = '.';
|
||||
*bup++ = '.';
|
||||
*bup = '\0';
|
||||
|
||||
/* Open and stat parent directory. */
|
||||
if (!(dir = opendir(up)) || fstat(dirfd(dir), &s))
|
||||
goto err;
|
||||
|
||||
/* Add trailing slash for next directory. */
|
||||
*bup++ = PATH_SEPARATOR[0];
|
||||
|
||||
/*
|
||||
* If it's a mount point, have to stat each element because
|
||||
* the inode number in the directory is for the entry in the
|
||||
* parent directory, not the inode number of the mounted file.
|
||||
*/
|
||||
save_errno = 0;
|
||||
if (s.st_dev == dev) {
|
||||
for (;;) {
|
||||
if (!(dp = readdir(dir)))
|
||||
goto notfound;
|
||||
if (dp->d_fileno == ino)
|
||||
break;
|
||||
}
|
||||
} else
|
||||
for (;;) {
|
||||
if (!(dp = readdir(dir)))
|
||||
goto notfound;
|
||||
if (ISDOT(dp))
|
||||
continue;
|
||||
bcopy(dp->d_name, bup, dp->d_namlen + 1);
|
||||
|
||||
/* Save the first error for later. */
|
||||
if (lstat(up, &s)) {
|
||||
if (!save_errno)
|
||||
save_errno = errno;
|
||||
errno = 0;
|
||||
continue;
|
||||
}
|
||||
if (s.st_dev == dev && s.st_ino == ino)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for length of the current name, preceding slash,
|
||||
* leading slash.
|
||||
*/
|
||||
if (bpt - pt < dp->d_namlen + (first ? 1 : 2)) {
|
||||
size_t len, off;
|
||||
|
||||
if (!ptsize) {
|
||||
errno = ERANGE;
|
||||
goto err;
|
||||
}
|
||||
off = bpt - pt;
|
||||
len = ept - bpt;
|
||||
if ((pt =
|
||||
(char *)__db_realloc(pt, ptsize *= 2)) == NULL)
|
||||
goto err;
|
||||
bpt = pt + off;
|
||||
ept = pt + ptsize;
|
||||
bcopy(bpt, ept - len, len);
|
||||
bpt = ept - len;
|
||||
}
|
||||
if (!first)
|
||||
*--bpt = PATH_SEPARATOR[0];
|
||||
bpt -= dp->d_namlen;
|
||||
bcopy(dp->d_name, bpt, dp->d_namlen);
|
||||
(void)closedir(dir);
|
||||
|
||||
/* Truncate any file name. */
|
||||
*bup = '\0';
|
||||
}
|
||||
|
||||
notfound:
|
||||
/*
|
||||
* If readdir set errno, use it, not any saved error; otherwise,
|
||||
* didn't find the current directory in its parent directory, set
|
||||
* errno to ENOENT.
|
||||
*/
|
||||
if (!errno)
|
||||
errno = save_errno ? save_errno : ENOENT;
|
||||
/* FALLTHROUGH */
|
||||
err:
|
||||
if (ptsize)
|
||||
__db_free(pt);
|
||||
__db_free(up);
|
||||
return (NULL);
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)getlong.c 10.3 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "db.h"
|
||||
#include "clib_ext.h"
|
||||
|
||||
/*
|
||||
* get_long --
|
||||
* Return a long value inside of basic parameters.
|
||||
*
|
||||
* PUBLIC: void get_long __P((char *, long, long, long *));
|
||||
*/
|
||||
void
|
||||
get_long(p, min, max, storep)
|
||||
char *p;
|
||||
long min, max, *storep;
|
||||
{
|
||||
long val;
|
||||
char *end;
|
||||
|
||||
errno = 0;
|
||||
val = strtol(p, &end, 10);
|
||||
if ((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE)
|
||||
err(1, "%s", p);
|
||||
if (p[0] == '\0' || end[0] != '\0')
|
||||
errx(1, "%s: Invalid numeric argument", p);
|
||||
if (val < min)
|
||||
errx(1, "%s: Less than minimum value (%ld)", p, min);
|
||||
if (val > max)
|
||||
errx(1, "%s: Greater than maximum value (%ld)", p, max);
|
||||
*storep = val;
|
||||
}
|
143
db/clib/getopt.c
143
db/clib/getopt.c
|
@ -1,143 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1987, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)getopt.c 10.6 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
|
||||
int opterr = 1, /* if error message should be printed */
|
||||
optind = 1, /* index into parent argv vector */
|
||||
optopt, /* character checked for validity */
|
||||
optreset; /* reset getopt */
|
||||
char *optarg; /* argument associated with option */
|
||||
|
||||
#undef BADCH
|
||||
#define BADCH (int)'?'
|
||||
#undef BADARG
|
||||
#define BADARG (int)':'
|
||||
#undef EMSG
|
||||
#define EMSG ""
|
||||
|
||||
/*
|
||||
* getopt --
|
||||
* Parse argc/argv argument vector.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_GETOPT
|
||||
* PUBLIC: int getopt __P((int, char * const *, const char *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
int
|
||||
getopt(nargc, nargv, ostr)
|
||||
int nargc;
|
||||
char * const *nargv;
|
||||
const char *ostr;
|
||||
{
|
||||
static char *progname;
|
||||
static char *place = EMSG; /* option letter processing */
|
||||
char *oli; /* option letter list index */
|
||||
|
||||
if (!progname) {
|
||||
if ((progname = __db_rpath(*nargv)) == NULL)
|
||||
progname = *nargv;
|
||||
else
|
||||
++progname;
|
||||
}
|
||||
|
||||
if (optreset || !*place) { /* update scanning pointer */
|
||||
optreset = 0;
|
||||
if (optind >= nargc || *(place = nargv[optind]) != '-') {
|
||||
place = EMSG;
|
||||
return (EOF);
|
||||
}
|
||||
if (place[1] && *++place == '-') { /* found "--" */
|
||||
++optind;
|
||||
place = EMSG;
|
||||
return (EOF);
|
||||
}
|
||||
} /* option letter okay? */
|
||||
if ((optopt = (int)*place++) == (int)':' ||
|
||||
!(oli = strchr(ostr, optopt))) {
|
||||
/*
|
||||
* if the user didn't specify '-' as an option,
|
||||
* assume it means EOF.
|
||||
*/
|
||||
if (optopt == (int)'-')
|
||||
return (EOF);
|
||||
if (!*place)
|
||||
++optind;
|
||||
if (opterr && *ostr != ':')
|
||||
(void)fprintf(stderr,
|
||||
"%s: illegal option -- %c\n", progname, optopt);
|
||||
return (BADCH);
|
||||
}
|
||||
if (*++oli != ':') { /* don't need argument */
|
||||
optarg = NULL;
|
||||
if (!*place)
|
||||
++optind;
|
||||
}
|
||||
else { /* need an argument */
|
||||
if (*place) /* no white space */
|
||||
optarg = place;
|
||||
else if (nargc <= ++optind) { /* no arg */
|
||||
place = EMSG;
|
||||
if (*ostr == ':')
|
||||
return (BADARG);
|
||||
if (opterr)
|
||||
(void)fprintf(stderr,
|
||||
"%s: option requires an argument -- %c\n",
|
||||
progname, optopt);
|
||||
return (BADCH);
|
||||
}
|
||||
else /* white space */
|
||||
optarg = nargv[optind];
|
||||
place = EMSG;
|
||||
++optind;
|
||||
}
|
||||
return (optopt); /* dump back option letter */
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)memcmp.c 10.3 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
* memcmp --
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_MEMCMP
|
||||
* PUBLIC: int memcmp __P((const void *, const void *, size_t));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
int
|
||||
memcmp(s1, s2, n)
|
||||
char *s1, *s2;
|
||||
size_t n;
|
||||
{
|
||||
if (n != 0) {
|
||||
unsigned char *p1 = (unsigned char *)s1,
|
||||
*p2 = (unsigned char *)s2;
|
||||
do {
|
||||
if (*p1++ != *p2++)
|
||||
return (*--p1 - *--p2);
|
||||
} while (--n != 0);
|
||||
}
|
||||
return (0);
|
||||
}
|
159
db/clib/memcpy.c
159
db/clib/memcpy.c
|
@ -1,159 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)memmove.c 10.2 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* sizeof(word) MUST BE A POWER OF TWO
|
||||
* SO THAT wmask BELOW IS ALL ONES
|
||||
*/
|
||||
typedef int word; /* "word" used for optimal copy speed */
|
||||
|
||||
#undef wsize
|
||||
#define wsize sizeof(word)
|
||||
#undef wmask
|
||||
#define wmask (wsize - 1)
|
||||
|
||||
/*
|
||||
* Copy a block of memory, handling overlap.
|
||||
* This is the routine that actually implements
|
||||
* (the portable versions of) bcopy, memcpy, and memmove.
|
||||
*/
|
||||
#ifdef MEMCOPY
|
||||
/*
|
||||
* PUBLIC: #ifndef HAVE_MEMCPY
|
||||
* PUBLIC: void *memcpy __P((void *, const void *, size_t));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void *
|
||||
memcpy(dst0, src0, length)
|
||||
#else
|
||||
#ifdef MEMMOVE
|
||||
/*
|
||||
* PUBLIC: #ifndef HAVE_MEMMOVE
|
||||
* PUBLIC: void *memmove __P((void *, const void *, size_t));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void *
|
||||
memmove(dst0, src0, length)
|
||||
#else
|
||||
void
|
||||
bcopy(src0, dst0, length)
|
||||
#endif
|
||||
#endif
|
||||
void *dst0;
|
||||
const void *src0;
|
||||
register size_t length;
|
||||
{
|
||||
register char *dst = dst0;
|
||||
register const char *src = src0;
|
||||
register size_t t;
|
||||
|
||||
if (length == 0 || dst == src) /* nothing to do */
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Macros: loop-t-times; and loop-t-times, t>0
|
||||
*/
|
||||
#undef TLOOP
|
||||
#define TLOOP(s) if (t) TLOOP1(s)
|
||||
#undef TLOOP1
|
||||
#define TLOOP1(s) do { s; } while (--t)
|
||||
|
||||
if ((unsigned long)dst < (unsigned long)src) {
|
||||
/*
|
||||
* Copy forward.
|
||||
*/
|
||||
t = (int)src; /* only need low bits */
|
||||
if ((t | (int)dst) & wmask) {
|
||||
/*
|
||||
* Try to align operands. This cannot be done
|
||||
* unless the low bits match.
|
||||
*/
|
||||
if ((t ^ (int)dst) & wmask || length < wsize)
|
||||
t = length;
|
||||
else
|
||||
t = wsize - (t & wmask);
|
||||
length -= t;
|
||||
TLOOP1(*dst++ = *src++);
|
||||
}
|
||||
/*
|
||||
* Copy whole words, then mop up any trailing bytes.
|
||||
*/
|
||||
t = length / wsize;
|
||||
TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
|
||||
t = length & wmask;
|
||||
TLOOP(*dst++ = *src++);
|
||||
} else {
|
||||
/*
|
||||
* Copy backwards. Otherwise essentially the same.
|
||||
* Alignment works as before, except that it takes
|
||||
* (t&wmask) bytes to align, not wsize-(t&wmask).
|
||||
*/
|
||||
src += length;
|
||||
dst += length;
|
||||
t = (int)src;
|
||||
if ((t | (int)dst) & wmask) {
|
||||
if ((t ^ (int)dst) & wmask || length <= wsize)
|
||||
t = length;
|
||||
else
|
||||
t &= wmask;
|
||||
length -= t;
|
||||
TLOOP1(*--dst = *--src);
|
||||
}
|
||||
t = length / wsize;
|
||||
TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
|
||||
t = length & wmask;
|
||||
TLOOP(*--dst = *--src);
|
||||
}
|
||||
done:
|
||||
#if defined(MEMCOPY) || defined(MEMMOVE)
|
||||
return (dst0);
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)memmove.c 10.2 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* sizeof(word) MUST BE A POWER OF TWO
|
||||
* SO THAT wmask BELOW IS ALL ONES
|
||||
*/
|
||||
typedef int word; /* "word" used for optimal copy speed */
|
||||
|
||||
#undef wsize
|
||||
#define wsize sizeof(word)
|
||||
#undef wmask
|
||||
#define wmask (wsize - 1)
|
||||
|
||||
/*
|
||||
* Copy a block of memory, handling overlap.
|
||||
* This is the routine that actually implements
|
||||
* (the portable versions of) bcopy, memcpy, and memmove.
|
||||
*/
|
||||
#ifdef MEMCOPY
|
||||
/*
|
||||
* PUBLIC: #ifndef HAVE_MEMCPY
|
||||
* PUBLIC: void *memcpy __P((void *, const void *, size_t));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void *
|
||||
memcpy(dst0, src0, length)
|
||||
#else
|
||||
#ifdef MEMMOVE
|
||||
/*
|
||||
* PUBLIC: #ifndef HAVE_MEMMOVE
|
||||
* PUBLIC: void *memmove __P((void *, const void *, size_t));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void *
|
||||
memmove(dst0, src0, length)
|
||||
#else
|
||||
void
|
||||
bcopy(src0, dst0, length)
|
||||
#endif
|
||||
#endif
|
||||
void *dst0;
|
||||
const void *src0;
|
||||
register size_t length;
|
||||
{
|
||||
register char *dst = dst0;
|
||||
register const char *src = src0;
|
||||
register size_t t;
|
||||
|
||||
if (length == 0 || dst == src) /* nothing to do */
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Macros: loop-t-times; and loop-t-times, t>0
|
||||
*/
|
||||
#undef TLOOP
|
||||
#define TLOOP(s) if (t) TLOOP1(s)
|
||||
#undef TLOOP1
|
||||
#define TLOOP1(s) do { s; } while (--t)
|
||||
|
||||
if ((unsigned long)dst < (unsigned long)src) {
|
||||
/*
|
||||
* Copy forward.
|
||||
*/
|
||||
t = (int)src; /* only need low bits */
|
||||
if ((t | (int)dst) & wmask) {
|
||||
/*
|
||||
* Try to align operands. This cannot be done
|
||||
* unless the low bits match.
|
||||
*/
|
||||
if ((t ^ (int)dst) & wmask || length < wsize)
|
||||
t = length;
|
||||
else
|
||||
t = wsize - (t & wmask);
|
||||
length -= t;
|
||||
TLOOP1(*dst++ = *src++);
|
||||
}
|
||||
/*
|
||||
* Copy whole words, then mop up any trailing bytes.
|
||||
*/
|
||||
t = length / wsize;
|
||||
TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
|
||||
t = length & wmask;
|
||||
TLOOP(*dst++ = *src++);
|
||||
} else {
|
||||
/*
|
||||
* Copy backwards. Otherwise essentially the same.
|
||||
* Alignment works as before, except that it takes
|
||||
* (t&wmask) bytes to align, not wsize-(t&wmask).
|
||||
*/
|
||||
src += length;
|
||||
dst += length;
|
||||
t = (int)src;
|
||||
if ((t | (int)dst) & wmask) {
|
||||
if ((t ^ (int)dst) & wmask || length <= wsize)
|
||||
t = length;
|
||||
else
|
||||
t &= wmask;
|
||||
length -= t;
|
||||
TLOOP1(*--dst = *--src);
|
||||
}
|
||||
t = length / wsize;
|
||||
TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
|
||||
t = length & wmask;
|
||||
TLOOP(*--dst = *--src);
|
||||
}
|
||||
done:
|
||||
#if defined(MEMCOPY) || defined(MEMMOVE)
|
||||
return (dst0);
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)raise.c 10.4 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* raise --
|
||||
* Send a signal to the current process.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_RAISE
|
||||
* PUBLIC: int raise __P((int));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
int
|
||||
raise(s)
|
||||
int s;
|
||||
{
|
||||
return (kill(getpid(), s));
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)snprintf.c 10.3 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* snprintf --
|
||||
* Bounded version of sprintf.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_SNPRINTF
|
||||
* PUBLIC: #ifdef __STDC__
|
||||
* PUBLIC: int snprintf __P((char *, size_t, const char *, ...));
|
||||
* PUBLIC: #else
|
||||
* PUBLIC: int snprintf();
|
||||
* PUBLIC: #endif
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
#ifndef HAVE_SNPRINTF
|
||||
int
|
||||
#ifdef __STDC__
|
||||
snprintf(char *str, size_t n, const char *fmt, ...)
|
||||
#else
|
||||
snprintf(str, n, fmt, va_alist)
|
||||
char *str;
|
||||
size_t n;
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
int rval;
|
||||
#ifdef __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
#ifdef SPRINTF_RET_CHARPNT
|
||||
(void)vsprintf(str, fmt, ap);
|
||||
va_end(ap);
|
||||
return (strlen(str));
|
||||
#else
|
||||
rval = vsprintf(str, fmt, ap);
|
||||
va_end(ap);
|
||||
return (rval);
|
||||
#endif
|
||||
}
|
||||
#endif
|
|
@ -1,81 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)strerror.c 10.3 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* strerror --
|
||||
* Return the string associated with an errno.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_STRERROR
|
||||
* PUBLIC: char *strerror __P((int));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
char *
|
||||
strerror(num)
|
||||
int num;
|
||||
{
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
#undef UPREFIX
|
||||
#define UPREFIX "Unknown error: "
|
||||
static char ebuf[40] = UPREFIX; /* 64-bit number + slop */
|
||||
int errnum;
|
||||
char *p, *t, tmp[40];
|
||||
|
||||
errnum = num; /* convert to unsigned */
|
||||
if (errnum < sys_nerr)
|
||||
return(sys_errlist[errnum]);
|
||||
|
||||
/* Do this by hand, so we don't include stdio(3). */
|
||||
t = tmp;
|
||||
do {
|
||||
*t++ = "0123456789"[errnum % 10];
|
||||
} while (errnum /= 10);
|
||||
for (p = ebuf + sizeof(UPREFIX) - 1;;) {
|
||||
*p++ = *--t;
|
||||
if (t <= tmp)
|
||||
break;
|
||||
}
|
||||
return(ebuf);
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)strsep.c 10.2 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Get next token from string *stringp, where tokens are possibly-empty
|
||||
* strings separated by characters from delim.
|
||||
*
|
||||
* Writes NULs into the string at *stringp to end tokens.
|
||||
* delim need not remain constant from call to call.
|
||||
* On return, *stringp points past the last NUL written (if there might
|
||||
* be further tokens), or is NULL (if there are definitely no more tokens).
|
||||
*
|
||||
* If *stringp is NULL, strsep returns NULL.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_STRSEP
|
||||
* PUBLIC: char *strsep __P((char **, const char *));
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
char *
|
||||
strsep(stringp, delim)
|
||||
register char **stringp;
|
||||
register const char *delim;
|
||||
{
|
||||
register char *s;
|
||||
register const char *spanp;
|
||||
register int c, sc;
|
||||
char *tok;
|
||||
|
||||
if ((s = *stringp) == NULL)
|
||||
return (NULL);
|
||||
for (tok = s;;) {
|
||||
c = *s++;
|
||||
spanp = delim;
|
||||
do {
|
||||
if ((sc = *spanp++) == c) {
|
||||
if (c == 0)
|
||||
s = NULL;
|
||||
else
|
||||
s[-1] = 0;
|
||||
*stringp = s;
|
||||
return (tok);
|
||||
}
|
||||
} while (sc != 0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)vsnprintf.c 10.2 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* vsnprintf --
|
||||
* Bounded version of vsprintf.
|
||||
*
|
||||
* PUBLIC: #ifndef HAVE_VSNPRINTF
|
||||
* PUBLIC: int vsnprintf();
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
#ifndef HAVE_VSNPRINTF
|
||||
int
|
||||
vsnprintf(str, n, fmt, ap)
|
||||
char *str;
|
||||
size_t n;
|
||||
const char *fmt;
|
||||
va_list ap;
|
||||
{
|
||||
#ifdef SPRINTF_RET_CHARPNT
|
||||
(void)vsprintf(str, fmt, ap);
|
||||
return (strlen(str));
|
||||
#else
|
||||
return (vsprintf(str, fmt, ap));
|
||||
#endif
|
||||
}
|
||||
#endif
|
|
@ -1,795 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_appinit.c 10.52 (Sleepycat) 6/2/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "shqueue.h"
|
||||
#include "db_page.h"
|
||||
#include "btree.h"
|
||||
#include "hash.h"
|
||||
#include "log.h"
|
||||
#include "txn.h"
|
||||
#include "clib_ext.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
static int __db_home __P((DB_ENV *, const char *, u_int32_t));
|
||||
static int __db_parse __P((DB_ENV *, char *));
|
||||
static int __db_tmp_dir __P((DB_ENV *, u_int32_t));
|
||||
static int __db_tmp_open __P((DB_ENV *, u_int32_t, char *, int *));
|
||||
|
||||
/*
|
||||
* db_version --
|
||||
* Return version information.
|
||||
*/
|
||||
char *
|
||||
db_version(majverp, minverp, patchp)
|
||||
int *majverp, *minverp, *patchp;
|
||||
{
|
||||
if (majverp != NULL)
|
||||
*majverp = DB_VERSION_MAJOR;
|
||||
if (minverp != NULL)
|
||||
*minverp = DB_VERSION_MINOR;
|
||||
if (patchp != NULL)
|
||||
*patchp = DB_VERSION_PATCH;
|
||||
return ((char *)DB_VERSION_STRING);
|
||||
}
|
||||
|
||||
/*
|
||||
* db_appinit --
|
||||
* Initialize the application environment.
|
||||
*/
|
||||
int
|
||||
db_appinit(db_home, db_config, dbenv, flags)
|
||||
const char *db_home;
|
||||
char * const *db_config;
|
||||
DB_ENV *dbenv;
|
||||
u_int32_t flags;
|
||||
{
|
||||
FILE *fp;
|
||||
int mode, ret;
|
||||
char * const *p;
|
||||
char *lp, buf[MAXPATHLEN * 2];
|
||||
|
||||
/* Validate arguments. */
|
||||
if (dbenv == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
|
||||
#ifdef HAVE_SPINLOCKS
|
||||
#define OKFLAGS \
|
||||
(DB_CREATE | DB_NOMMAP | DB_THREAD | DB_INIT_LOCK | DB_INIT_LOG | \
|
||||
DB_INIT_MPOOL | DB_INIT_TXN | DB_MPOOL_PRIVATE | DB_RECOVER | \
|
||||
DB_RECOVER_FATAL | DB_TXN_NOSYNC | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT)
|
||||
#else
|
||||
#define OKFLAGS \
|
||||
(DB_CREATE | DB_NOMMAP | DB_INIT_LOCK | DB_INIT_LOG | \
|
||||
DB_INIT_MPOOL | DB_INIT_TXN | DB_MPOOL_PRIVATE | DB_RECOVER | \
|
||||
DB_RECOVER_FATAL | DB_TXN_NOSYNC | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT)
|
||||
#endif
|
||||
if ((ret = __db_fchk(dbenv, "db_appinit", flags, OKFLAGS)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Transactions imply logging. */
|
||||
if (LF_ISSET(DB_INIT_TXN))
|
||||
LF_SET(DB_INIT_LOG);
|
||||
|
||||
/* Convert the db_appinit(3) flags. */
|
||||
if (LF_ISSET(DB_THREAD))
|
||||
F_SET(dbenv, DB_ENV_THREAD);
|
||||
|
||||
fp = NULL;
|
||||
|
||||
/* Set the database home. */
|
||||
if ((ret = __db_home(dbenv, db_home, flags)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Parse the config array. */
|
||||
for (p = db_config; p != NULL && *p != NULL; ++p)
|
||||
if ((ret = __db_parse(dbenv, *p)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Parse the config file.
|
||||
*
|
||||
* XXX
|
||||
* Don't use sprintf(3)/snprintf(3) -- the former is dangerous, and
|
||||
* the latter isn't standard, and we're manipulating strings handed
|
||||
* us by the application.
|
||||
*/
|
||||
if (dbenv->db_home != NULL) {
|
||||
#define CONFIG_NAME "/DB_CONFIG"
|
||||
if (strlen(dbenv->db_home) +
|
||||
strlen(CONFIG_NAME) + 1 > sizeof(buf)) {
|
||||
ret = ENAMETOOLONG;
|
||||
goto err;
|
||||
}
|
||||
(void)strcpy(buf, dbenv->db_home);
|
||||
(void)strcat(buf, CONFIG_NAME);
|
||||
if ((fp = fopen(buf, "r")) != NULL) {
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
if ((lp = strchr(buf, '\n')) != NULL)
|
||||
*lp = '\0';
|
||||
if ((ret = __db_parse(dbenv, buf)) != 0)
|
||||
goto err;
|
||||
}
|
||||
(void)fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up the tmp directory path. */
|
||||
if (dbenv->db_tmp_dir == NULL &&
|
||||
(ret = __db_tmp_dir(dbenv, flags)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Indicate that the path names have been set. */
|
||||
F_SET(dbenv, DB_ENV_APPINIT);
|
||||
|
||||
/*
|
||||
* If we are doing recovery, remove all the old shared memory
|
||||
* regions.
|
||||
*/
|
||||
if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL)) {
|
||||
if ((ret = log_unlink(NULL, 1, dbenv)) != 0)
|
||||
goto err;
|
||||
if ((ret = memp_unlink(NULL, 1, dbenv)) != 0)
|
||||
goto err;
|
||||
if ((ret = lock_unlink(NULL, 1, dbenv)) != 0)
|
||||
goto err;
|
||||
if ((ret = txn_unlink(NULL, 1, dbenv)) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the new shared regions.
|
||||
*
|
||||
* Default permissions are read-write for both owner and group.
|
||||
*/
|
||||
mode = __db_omode("rwrw--");
|
||||
if (LF_ISSET(DB_INIT_LOCK) && (ret = lock_open(NULL,
|
||||
LF_ISSET(DB_CREATE | DB_THREAD),
|
||||
mode, dbenv, &dbenv->lk_info)) != 0)
|
||||
goto err;
|
||||
if (LF_ISSET(DB_INIT_LOG) && (ret = log_open(NULL,
|
||||
LF_ISSET(DB_CREATE | DB_THREAD),
|
||||
mode, dbenv, &dbenv->lg_info)) != 0)
|
||||
goto err;
|
||||
if (LF_ISSET(DB_INIT_MPOOL) && (ret = memp_open(NULL,
|
||||
LF_ISSET(DB_CREATE | DB_MPOOL_PRIVATE | DB_NOMMAP | DB_THREAD),
|
||||
mode, dbenv, &dbenv->mp_info)) != 0)
|
||||
goto err;
|
||||
if (LF_ISSET(DB_INIT_TXN) && (ret = txn_open(NULL,
|
||||
LF_ISSET(DB_CREATE | DB_THREAD | DB_TXN_NOSYNC),
|
||||
mode, dbenv, &dbenv->tx_info)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* If the application is running with transactions, initialize the
|
||||
* function tables. Once that's done, do recovery for any previous
|
||||
* run.
|
||||
*/
|
||||
if (LF_ISSET(DB_INIT_TXN)) {
|
||||
if ((ret = __bam_init_recover(dbenv)) != 0)
|
||||
goto err;
|
||||
if ((ret = __db_init_recover(dbenv)) != 0)
|
||||
goto err;
|
||||
if ((ret = __ham_init_recover(dbenv)) != 0)
|
||||
goto err;
|
||||
if ((ret = __log_init_recover(dbenv)) != 0)
|
||||
goto err;
|
||||
if ((ret = __txn_init_recover(dbenv)) != 0)
|
||||
goto err;
|
||||
|
||||
if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) &&
|
||||
(ret = __db_apprec(dbenv,
|
||||
LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
|
||||
err: if (fp != NULL)
|
||||
(void)fclose(fp);
|
||||
|
||||
(void)db_appexit(dbenv);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* db_appexit --
|
||||
* Close down the default application environment.
|
||||
*/
|
||||
int
|
||||
db_appexit(dbenv)
|
||||
DB_ENV *dbenv;
|
||||
{
|
||||
int ret, t_ret;
|
||||
char **p;
|
||||
|
||||
ret = 0;
|
||||
|
||||
/* Close subsystems. */
|
||||
if (dbenv->tx_info && (t_ret = txn_close(dbenv->tx_info)) != 0)
|
||||
if (ret == 0)
|
||||
ret = t_ret;
|
||||
if (dbenv->mp_info && (t_ret = memp_close(dbenv->mp_info)) != 0)
|
||||
if (ret == 0)
|
||||
ret = t_ret;
|
||||
if (dbenv->lg_info && (t_ret = log_close(dbenv->lg_info)) != 0)
|
||||
if (ret == 0)
|
||||
ret = t_ret;
|
||||
if (dbenv->lk_info && (t_ret = lock_close(dbenv->lk_info)) != 0)
|
||||
if (ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/* Free allocated memory. */
|
||||
if (dbenv->db_home != NULL)
|
||||
FREES(dbenv->db_home);
|
||||
if ((p = dbenv->db_data_dir) != NULL) {
|
||||
for (; *p != NULL; ++p)
|
||||
FREES(*p);
|
||||
FREE(dbenv->db_data_dir, dbenv->data_cnt * sizeof(char **));
|
||||
}
|
||||
if (dbenv->db_log_dir != NULL)
|
||||
FREES(dbenv->db_log_dir);
|
||||
if (dbenv->db_tmp_dir != NULL)
|
||||
FREES(dbenv->db_tmp_dir);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#define DB_ADDSTR(str) { \
|
||||
if ((str) != NULL) { \
|
||||
/* If leading slash, start over. */ \
|
||||
if (__db_abspath(str)) { \
|
||||
p = start; \
|
||||
slash = 0; \
|
||||
} \
|
||||
/* Append to the current string. */ \
|
||||
len = strlen(str); \
|
||||
if (slash) \
|
||||
*p++ = PATH_SEPARATOR[0]; \
|
||||
memcpy(p, str, len); \
|
||||
p += len; \
|
||||
slash = strchr(PATH_SEPARATOR, p[-1]) == NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_appname --
|
||||
* Given an optional DB environment, directory and file name and type
|
||||
* of call, build a path based on the db_appinit(3) rules, and return
|
||||
* it in allocated space.
|
||||
*
|
||||
* PUBLIC: int __db_appname __P((DB_ENV *,
|
||||
* PUBLIC: APPNAME, const char *, const char *, u_int32_t, int *, char **));
|
||||
*/
|
||||
int
|
||||
__db_appname(dbenv, appname, dir, file, tmp_oflags, fdp, namep)
|
||||
DB_ENV *dbenv;
|
||||
APPNAME appname;
|
||||
const char *dir, *file;
|
||||
u_int32_t tmp_oflags;
|
||||
int *fdp;
|
||||
char **namep;
|
||||
{
|
||||
DB_ENV etmp;
|
||||
size_t len;
|
||||
int data_entry, ret, slash, tmp_create, tmp_free;
|
||||
const char *a, *b, *c;
|
||||
char *p, *start;
|
||||
|
||||
a = b = c = NULL;
|
||||
data_entry = -1;
|
||||
tmp_create = tmp_free = 0;
|
||||
|
||||
/*
|
||||
* We don't return a name when creating temporary files, just an fd.
|
||||
* Default to error now.
|
||||
*/
|
||||
if (fdp != NULL)
|
||||
*fdp = -1;
|
||||
if (namep != NULL)
|
||||
*namep = NULL;
|
||||
|
||||
/*
|
||||
* Absolute path names are never modified. If the file is an absolute
|
||||
* path, we're done. If the directory is, simply append the file and
|
||||
* return.
|
||||
*/
|
||||
if (file != NULL && __db_abspath(file))
|
||||
return ((*namep =
|
||||
(char *)__db_strdup(file)) == NULL ? ENOMEM : 0);
|
||||
if (dir != NULL && __db_abspath(dir)) {
|
||||
a = dir;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* DB_ENV DIR APPNAME RESULT
|
||||
* -------------------------------------------
|
||||
* null null none <tmp>/file
|
||||
* null set none DIR/file
|
||||
* set null none DB_HOME/file
|
||||
* set set none DB_HOME/DIR/file
|
||||
*
|
||||
* DB_ENV FILE APPNAME RESULT
|
||||
* -------------------------------------------
|
||||
* null null DB_APP_DATA <tmp>/<create>
|
||||
* null set DB_APP_DATA ./file
|
||||
* set null DB_APP_DATA <tmp>/<create>
|
||||
* set set DB_APP_DATA DB_HOME/DB_DATA_DIR/file
|
||||
*
|
||||
* DB_ENV DIR APPNAME RESULT
|
||||
* -------------------------------------------
|
||||
* null null DB_APP_LOG <tmp>/file
|
||||
* null set DB_APP_LOG DIR/file
|
||||
* set null DB_APP_LOG DB_HOME/DB_LOG_DIR/file
|
||||
* set set DB_APP_LOG DB_HOME/DB_LOG_DIR/DIR/file
|
||||
*
|
||||
* DB_ENV APPNAME RESULT
|
||||
* -------------------------------------------
|
||||
* null DB_APP_TMP* <tmp>/<create>
|
||||
* set DB_APP_TMP* DB_HOME/DB_TMP_DIR/<create>
|
||||
*/
|
||||
retry: switch (appname) {
|
||||
case DB_APP_NONE:
|
||||
if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) {
|
||||
if (dir == NULL)
|
||||
goto tmp;
|
||||
a = dir;
|
||||
} else {
|
||||
a = dbenv->db_home;
|
||||
b = dir;
|
||||
}
|
||||
break;
|
||||
case DB_APP_DATA:
|
||||
if (dir != NULL) {
|
||||
__db_err(dbenv,
|
||||
"DB_APP_DATA: illegal directory specification");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (file == NULL) {
|
||||
tmp_create = 1;
|
||||
goto tmp;
|
||||
}
|
||||
if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT))
|
||||
a = PATH_DOT;
|
||||
else {
|
||||
a = dbenv->db_home;
|
||||
if (dbenv->db_data_dir != NULL &&
|
||||
(b = dbenv->db_data_dir[++data_entry]) == NULL) {
|
||||
data_entry = -1;
|
||||
b = dbenv->db_data_dir[0];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DB_APP_LOG:
|
||||
if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) {
|
||||
if (dir == NULL)
|
||||
goto tmp;
|
||||
a = dir;
|
||||
} else {
|
||||
a = dbenv->db_home;
|
||||
b = dbenv->db_log_dir;
|
||||
c = dir;
|
||||
}
|
||||
break;
|
||||
case DB_APP_TMP:
|
||||
if (dir != NULL || file != NULL) {
|
||||
__db_err(dbenv,
|
||||
"DB_APP_TMP: illegal directory or file specification");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
tmp_create = 1;
|
||||
if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT))
|
||||
goto tmp;
|
||||
else {
|
||||
a = dbenv->db_home;
|
||||
b = dbenv->db_tmp_dir;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reference a file from the appropriate temporary directory. */
|
||||
if (0) {
|
||||
tmp: if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) {
|
||||
memset(&etmp, 0, sizeof(etmp));
|
||||
if ((ret = __db_tmp_dir(&etmp, DB_USE_ENVIRON)) != 0)
|
||||
return (ret);
|
||||
tmp_free = 1;
|
||||
a = etmp.db_tmp_dir;
|
||||
} else
|
||||
a = dbenv->db_tmp_dir;
|
||||
}
|
||||
|
||||
done: len =
|
||||
(a == NULL ? 0 : strlen(a) + 1) +
|
||||
(b == NULL ? 0 : strlen(b) + 1) +
|
||||
(c == NULL ? 0 : strlen(c) + 1) +
|
||||
(file == NULL ? 0 : strlen(file) + 1);
|
||||
|
||||
/*
|
||||
* Allocate space to hold the current path information, as well as any
|
||||
* temporary space that we're going to need to create a temporary file
|
||||
* name.
|
||||
*/
|
||||
#define DB_TRAIL "XXXXXX"
|
||||
if ((start =
|
||||
(char *)__db_malloc(len + sizeof(DB_TRAIL) + 10)) == NULL) {
|
||||
__db_err(dbenv, "%s", strerror(ENOMEM));
|
||||
if (tmp_free)
|
||||
FREES(etmp.db_tmp_dir);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
slash = 0;
|
||||
p = start;
|
||||
DB_ADDSTR(a);
|
||||
DB_ADDSTR(b);
|
||||
DB_ADDSTR(file);
|
||||
*p = '\0';
|
||||
|
||||
/*
|
||||
* If we're opening a data file, see if it exists. If it does,
|
||||
* return it, otherwise, try and find another one to open.
|
||||
*/
|
||||
if (data_entry != -1 && __db_exists(start, NULL) != 0) {
|
||||
FREES(start);
|
||||
a = b = c = NULL;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Discard any space allocated to find the temp directory. */
|
||||
if (tmp_free)
|
||||
FREES(etmp.db_tmp_dir);
|
||||
|
||||
/* Create the file if so requested. */
|
||||
if (tmp_create &&
|
||||
(ret = __db_tmp_open(dbenv, tmp_oflags, start, fdp)) != 0) {
|
||||
FREES(start);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if (namep != NULL)
|
||||
*namep = start;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_home --
|
||||
* Find the database home.
|
||||
*/
|
||||
static int
|
||||
__db_home(dbenv, db_home, flags)
|
||||
DB_ENV *dbenv;
|
||||
const char *db_home;
|
||||
u_int32_t flags;
|
||||
{
|
||||
const char *p;
|
||||
|
||||
p = db_home;
|
||||
|
||||
/* Use the environment if it's permitted and initialized. */
|
||||
#ifdef HAVE_GETUID
|
||||
if (LF_ISSET(DB_USE_ENVIRON) ||
|
||||
(LF_ISSET(DB_USE_ENVIRON_ROOT) && getuid() == 0)) {
|
||||
#else
|
||||
if (LF_ISSET(DB_USE_ENVIRON)) {
|
||||
#endif
|
||||
if ((p = getenv("DB_HOME")) == NULL)
|
||||
p = db_home;
|
||||
else if (p[0] == '\0') {
|
||||
__db_err(dbenv,
|
||||
"illegal DB_HOME environment variable");
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (p == NULL)
|
||||
return (0);
|
||||
|
||||
if ((dbenv->db_home = (char *)__db_strdup(p)) == NULL) {
|
||||
__db_err(dbenv, "%s", strerror(ENOMEM));
|
||||
return (ENOMEM);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_parse --
|
||||
* Parse a single NAME VALUE pair.
|
||||
*/
|
||||
static int
|
||||
__db_parse(dbenv, s)
|
||||
DB_ENV *dbenv;
|
||||
char *s;
|
||||
{
|
||||
int ret;
|
||||
char *local_s, *name, *value, **p, *tp;
|
||||
|
||||
ret = 0;
|
||||
|
||||
/*
|
||||
* We need to strdup the argument in case the caller passed us
|
||||
* static data.
|
||||
*/
|
||||
if ((local_s = (char *)__db_strdup(s)) == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
tp = local_s;
|
||||
while ((name = strsep(&tp, " \t")) != NULL && *name == '\0')
|
||||
;
|
||||
if (name == NULL)
|
||||
goto illegal;
|
||||
while ((value = strsep(&tp, " \t")) != NULL && *value == '\0')
|
||||
;
|
||||
if (value == NULL) {
|
||||
illegal: ret = EINVAL;
|
||||
__db_err(dbenv, "illegal name-value pair: %s", s);
|
||||
goto err;
|
||||
}
|
||||
|
||||
#define DATA_INIT_CNT 20 /* Start with 20 data slots. */
|
||||
if (!strcmp(name, "DB_DATA_DIR")) {
|
||||
if (dbenv->db_data_dir == NULL) {
|
||||
if ((dbenv->db_data_dir =
|
||||
(char **)__db_calloc(DATA_INIT_CNT,
|
||||
sizeof(char **))) == NULL)
|
||||
goto nomem;
|
||||
dbenv->data_cnt = DATA_INIT_CNT;
|
||||
} else if (dbenv->data_next == dbenv->data_cnt - 1) {
|
||||
dbenv->data_cnt *= 2;
|
||||
if ((dbenv->db_data_dir =
|
||||
(char **)__db_realloc(dbenv->db_data_dir,
|
||||
dbenv->data_cnt * sizeof(char **))) == NULL)
|
||||
goto nomem;
|
||||
}
|
||||
p = &dbenv->db_data_dir[dbenv->data_next++];
|
||||
} else if (!strcmp(name, "DB_LOG_DIR")) {
|
||||
if (dbenv->db_log_dir != NULL)
|
||||
FREES(dbenv->db_log_dir);
|
||||
p = &dbenv->db_log_dir;
|
||||
} else if (!strcmp(name, "DB_TMP_DIR")) {
|
||||
if (dbenv->db_tmp_dir != NULL)
|
||||
FREES(dbenv->db_tmp_dir);
|
||||
p = &dbenv->db_tmp_dir;
|
||||
} else
|
||||
goto err;
|
||||
|
||||
if ((*p = (char *)__db_strdup(value)) == NULL) {
|
||||
nomem: ret = ENOMEM;
|
||||
__db_err(dbenv, "%s", strerror(ENOMEM));
|
||||
}
|
||||
|
||||
err: FREES(local_s);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef macintosh
|
||||
#include <TFileSpec.h>
|
||||
|
||||
static char *sTempFolder;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* tmp --
|
||||
* Set the temporary directory path.
|
||||
*/
|
||||
static int
|
||||
__db_tmp_dir(dbenv, flags)
|
||||
DB_ENV *dbenv;
|
||||
u_int32_t flags;
|
||||
{
|
||||
static const char * list[] = { /* Ordered: see db_appinit(3). */
|
||||
"/var/tmp",
|
||||
"/usr/tmp",
|
||||
"/temp", /* WIN32. */
|
||||
"/tmp",
|
||||
"C:/temp", /* WIN32. */
|
||||
"C:/tmp", /* WIN32. */
|
||||
NULL
|
||||
};
|
||||
const char **lp, *p;
|
||||
|
||||
/* Use the environment if it's permitted and initialized. */
|
||||
p = NULL;
|
||||
#ifdef HAVE_GETEUID
|
||||
if (LF_ISSET(DB_USE_ENVIRON) ||
|
||||
(LF_ISSET(DB_USE_ENVIRON_ROOT) && getuid() == 0)) {
|
||||
#else
|
||||
if (LF_ISSET(DB_USE_ENVIRON)) {
|
||||
#endif
|
||||
if ((p = getenv("TMPDIR")) != NULL && p[0] == '\0') {
|
||||
__db_err(dbenv, "illegal TMPDIR environment variable");
|
||||
return (EINVAL);
|
||||
}
|
||||
/* WIN32 */
|
||||
if (p == NULL && (p = getenv("TEMP")) != NULL && p[0] == '\0') {
|
||||
__db_err(dbenv, "illegal TEMP environment variable");
|
||||
return (EINVAL);
|
||||
}
|
||||
/* WIN32 */
|
||||
if (p == NULL && (p = getenv("TMP")) != NULL && p[0] == '\0') {
|
||||
__db_err(dbenv, "illegal TMP environment variable");
|
||||
return (EINVAL);
|
||||
}
|
||||
/* Macintosh */
|
||||
if (p == NULL &&
|
||||
(p = getenv("TempFolder")) != NULL && p[0] == '\0') {
|
||||
__db_err(dbenv,
|
||||
"illegal TempFolder environment variable");
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef macintosh
|
||||
/* Get the path to the temporary folder. */
|
||||
if (p == NULL) {
|
||||
FSSpec spec;
|
||||
|
||||
if (!Special2FSSpec(kTemporaryFolderType,
|
||||
kOnSystemDisk, 0, &spec)) {
|
||||
p = FSp2FullPath(&spec);
|
||||
sTempFolder = __db_malloc(strlen(p) + 1);
|
||||
strcpy(sTempFolder, p);
|
||||
p = sTempFolder;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Step through the list looking for a possibility. */
|
||||
if (p == NULL)
|
||||
for (lp = list; *lp != NULL; ++lp)
|
||||
if (__db_exists(p = *lp, NULL) == 0)
|
||||
break;
|
||||
|
||||
if (p == NULL)
|
||||
return (0);
|
||||
|
||||
if ((dbenv->db_tmp_dir = (char *)__db_strdup(p)) == NULL) {
|
||||
__db_err(dbenv, "%s", strerror(ENOMEM));
|
||||
return (ENOMEM);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_tmp_open --
|
||||
* Create a temporary file.
|
||||
*/
|
||||
static int
|
||||
__db_tmp_open(dbenv, flags, path, fdp)
|
||||
DB_ENV *dbenv;
|
||||
u_int32_t flags;
|
||||
char *path;
|
||||
int *fdp;
|
||||
{
|
||||
#ifdef HAVE_SIGFILLSET
|
||||
sigset_t set, oset;
|
||||
#endif
|
||||
u_long pid;
|
||||
int mode, isdir, ret;
|
||||
char *p, *trv;
|
||||
|
||||
/*
|
||||
* Check the target directory; if you have six X's and it doesn't
|
||||
* exist, this runs for a *very* long time.
|
||||
*/
|
||||
if ((ret = __db_exists(path, &isdir)) != 0) {
|
||||
__db_err(dbenv, "%s: %s", path, strerror(ret));
|
||||
return (ret);
|
||||
}
|
||||
if (!isdir) {
|
||||
__db_err(dbenv, "%s: %s", path, strerror(EINVAL));
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/* Build the path. */
|
||||
for (trv = path; *trv != '\0'; ++trv)
|
||||
;
|
||||
*trv = PATH_SEPARATOR[0];
|
||||
for (p = DB_TRAIL; (*++trv = *p) != '\0'; ++p)
|
||||
;
|
||||
|
||||
/*
|
||||
* Replace the X's with the process ID. Pid should be a pid_t,
|
||||
* but we use unsigned long for portability.
|
||||
*/
|
||||
for (pid = getpid(); *--trv == 'X'; pid /= 10)
|
||||
switch (pid % 10) {
|
||||
case 0: *trv = '0'; break;
|
||||
case 1: *trv = '1'; break;
|
||||
case 2: *trv = '2'; break;
|
||||
case 3: *trv = '3'; break;
|
||||
case 4: *trv = '4'; break;
|
||||
case 5: *trv = '5'; break;
|
||||
case 6: *trv = '6'; break;
|
||||
case 7: *trv = '7'; break;
|
||||
case 8: *trv = '8'; break;
|
||||
case 9: *trv = '9'; break;
|
||||
}
|
||||
++trv;
|
||||
|
||||
/* Set up open flags and mode. */
|
||||
LF_SET(DB_CREATE | DB_EXCL);
|
||||
mode = __db_omode("rw----");
|
||||
|
||||
/*
|
||||
* Try to open a file. We block every signal we can get our hands
|
||||
* on so that, if we're interrupted at the wrong time, the temporary
|
||||
* file isn't left around -- of course, if we drop core in-between
|
||||
* the calls we'll hang forever, but that's probably okay. ;-}
|
||||
*/
|
||||
#ifdef HAVE_SIGFILLSET
|
||||
if (LF_ISSET(DB_TEMPORARY))
|
||||
(void)sigfillset(&set);
|
||||
#endif
|
||||
for (;;) {
|
||||
#ifdef HAVE_SIGFILLSET
|
||||
if (LF_ISSET(DB_TEMPORARY))
|
||||
(void)sigprocmask(SIG_BLOCK, &set, &oset);
|
||||
#endif
|
||||
ret = __db_open(path, flags, flags, mode, fdp);
|
||||
#ifdef HAVE_SIGFILLSET
|
||||
if (LF_ISSET(DB_TEMPORARY))
|
||||
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
|
||||
#endif
|
||||
if (ret == 0)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* XXX:
|
||||
* If we don't get an EEXIST error, then there's something
|
||||
* seriously wrong. Unfortunately, if the implementation
|
||||
* doesn't return EEXIST for O_CREAT and O_EXCL regardless
|
||||
* of other possible errors, we've lost.
|
||||
*/
|
||||
if (ret != EEXIST) {
|
||||
__db_err(dbenv,
|
||||
"tmp_open: %s: %s", path, strerror(ret));
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tricky little algorithm for backward compatibility.
|
||||
* Assumes the ASCII ordering of lower-case characters.
|
||||
*/
|
||||
for (;;) {
|
||||
if (*trv == '\0')
|
||||
return (EINVAL);
|
||||
if (*trv == 'z')
|
||||
*trv++ = 'a';
|
||||
else {
|
||||
if (isdigit(*trv))
|
||||
*trv = 'a';
|
||||
else
|
||||
++*trv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
|
@ -1,210 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1996, 1997, 1998\n\
|
||||
Sleepycat Software Inc. All rights reserved.\n";
|
||||
static const char sccsid[] = "@(#)db_apprec.c 10.30 (Sleepycat) 5/3/98";
|
||||
#endif
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "shqueue.h"
|
||||
#include "db_page.h"
|
||||
#include "db_dispatch.h"
|
||||
#include "db_am.h"
|
||||
#include "log.h"
|
||||
#include "txn.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
/*
|
||||
* __db_apprec --
|
||||
* Perform recovery.
|
||||
*
|
||||
* PUBLIC: int __db_apprec __P((DB_ENV *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_apprec(dbenv, flags)
|
||||
DB_ENV *dbenv;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DBT data;
|
||||
DB_LOG *lp;
|
||||
DB_LSN ckp_lsn, first_lsn, lsn;
|
||||
time_t now;
|
||||
u_int32_t is_thread;
|
||||
int ret;
|
||||
void *txninfo;
|
||||
|
||||
lp = dbenv->lg_info;
|
||||
|
||||
/* Initialize the transaction list. */
|
||||
if ((ret = __db_txnlist_init(&txninfo)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* Save the state of the thread flag -- we don't need it on at the
|
||||
* moment because we're single-threaded until recovery is complete.
|
||||
*/
|
||||
is_thread = F_ISSET(lp, DB_AM_THREAD);
|
||||
F_CLR(lp, DB_AM_THREAD);
|
||||
|
||||
/*
|
||||
* Recovery is done in three passes:
|
||||
* Pass #1:
|
||||
* Read forward through the log from the last checkpoint to the
|
||||
* end of the log, opening and closing files so that at the end
|
||||
* of the log we have the "current" set of files open.
|
||||
* Pass #2:
|
||||
* Read backward through the log undoing any uncompleted TXNs.
|
||||
* If doing catastrophic recovery, we read to the beginning of
|
||||
* the log, otherwise, to the most recent checkpoint that occurs
|
||||
* before the most recent checkpoint LSN, which is returned by
|
||||
* __log_findckp(). During this pass, checkpoint file information
|
||||
* is ignored, and file openings and closings are undone.
|
||||
* Pass #3:
|
||||
* Read forward through the log from the LSN found in pass #2,
|
||||
* redoing any committed TXNs. During this pass, checkpoint
|
||||
* file information is ignored, and file openings and closings
|
||||
* are redone.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Find the last checkpoint in the log. This is the point from which
|
||||
* we want to begin pass #1 (the TXN_OPENFILES pass).
|
||||
*/
|
||||
memset(&data, 0, sizeof(data));
|
||||
if ((ret = log_get(lp, &ckp_lsn, &data, DB_CHECKPOINT)) != 0) {
|
||||
/*
|
||||
* If we don't find a checkpoint, start from the beginning.
|
||||
* If that fails, we're done. Note, we do not require that
|
||||
* there be log records if we're performing recovery.
|
||||
*/
|
||||
if ((ret = log_get(lp, &ckp_lsn, &data, DB_FIRST)) != 0) {
|
||||
if (ret == DB_NOTFOUND)
|
||||
ret = 0;
|
||||
else
|
||||
__db_err(dbenv, "First log record not found");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, ckp_lsn is either the lsn of the last checkpoint or the lsn
|
||||
* of the first record in the log. Begin the TXN_OPENFILES pass from
|
||||
* that lsn, and proceed to the end of the log.
|
||||
*/
|
||||
lsn = ckp_lsn;
|
||||
for (;;) {
|
||||
ret = __db_dispatch(lp, &data, &lsn, TXN_OPENFILES, txninfo);
|
||||
if (ret != 0 && ret != DB_TXN_CKP)
|
||||
goto msgerr;
|
||||
if ((ret = log_get(lp, &lsn, &data, DB_NEXT)) != 0) {
|
||||
if (ret == DB_NOTFOUND)
|
||||
break;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass #2.
|
||||
*
|
||||
* Before we can begin pass #2, backward roll phase, we determine how
|
||||
* far back in the log to recover. If we are doing catastrophic
|
||||
* recovery, then we go as far back as we have files. If we are
|
||||
* doing normal recovery, we go as back to the most recent checkpoint
|
||||
* that occurs before the most recent checkpoint LSN.
|
||||
*/
|
||||
if (LF_ISSET(DB_RECOVER_FATAL)) {
|
||||
ZERO_LSN(first_lsn);
|
||||
} else
|
||||
if ((ret = __log_findckp(lp, &first_lsn)) == DB_NOTFOUND) {
|
||||
/*
|
||||
* We don't require that log files exist if recovery
|
||||
* was specified.
|
||||
*/
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dbenv->db_verbose)
|
||||
__db_err(lp->dbenv, "Recovery starting from [%lu][%lu]",
|
||||
(u_long)first_lsn.file, (u_long)first_lsn.offset);
|
||||
|
||||
for (ret = log_get(lp, &lsn, &data, DB_LAST);
|
||||
ret == 0 && log_compare(&lsn, &first_lsn) > 0;
|
||||
ret = log_get(lp, &lsn, &data, DB_PREV)) {
|
||||
ret = __db_dispatch(lp,
|
||||
&data, &lsn, TXN_BACKWARD_ROLL, txninfo);
|
||||
if (ret != 0)
|
||||
if (ret != DB_TXN_CKP)
|
||||
goto msgerr;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
if (ret != 0 && ret != DB_NOTFOUND)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Pass #3.
|
||||
*/
|
||||
for (ret = log_get(lp, &lsn, &data, DB_NEXT);
|
||||
ret == 0; ret = log_get(lp, &lsn, &data, DB_NEXT)) {
|
||||
ret = __db_dispatch(lp, &data, &lsn, TXN_FORWARD_ROLL, txninfo);
|
||||
if (ret != 0)
|
||||
if (ret != DB_TXN_CKP)
|
||||
goto msgerr;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
if (ret != DB_NOTFOUND)
|
||||
goto out;
|
||||
|
||||
/* Now close all the db files that are open. */
|
||||
__log_close_files(lp);
|
||||
|
||||
/*
|
||||
* Now set the last checkpoint lsn and the current time,
|
||||
* take a checkpoint, and reset the txnid.
|
||||
*/
|
||||
(void)time(&now);
|
||||
dbenv->tx_info->region->last_ckp = ckp_lsn;
|
||||
dbenv->tx_info->region->time_ckp = (u_int32_t)now;
|
||||
if ((ret = txn_checkpoint(dbenv->tx_info, 0, 0)) != 0)
|
||||
goto out;
|
||||
dbenv->tx_info->region->last_txnid = TXN_MINIMUM;
|
||||
|
||||
if (dbenv->db_verbose) {
|
||||
__db_err(lp->dbenv, "Recovery complete at %.24s", ctime(&now));
|
||||
__db_err(lp->dbenv, "%s %lx %s [%lu][%lu]",
|
||||
"Maximum transaction id",
|
||||
((DB_TXNHEAD *)txninfo)->maxid,
|
||||
"Recovery checkpoint",
|
||||
(u_long)dbenv->tx_info->region->last_ckp.file,
|
||||
(u_long)dbenv->tx_info->region->last_ckp.offset);
|
||||
}
|
||||
|
||||
if (0) {
|
||||
msgerr: __db_err(dbenv, "Recovery function for LSN %lu %lu failed",
|
||||
(u_long)lsn.file, (u_long)lsn.offset);
|
||||
}
|
||||
|
||||
out: F_SET(lp, is_thread);
|
||||
__db_txnlist_end(txninfo);
|
||||
|
||||
return (ret);
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_byteorder.c 10.5 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_ENDIAN_H
|
||||
#include <endian.h>
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define WORDS_BIGENDIAN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
/*
|
||||
* __db_byteorder --
|
||||
* Return if we need to do byte swapping, checking for illegal
|
||||
* values.
|
||||
*
|
||||
* PUBLIC: int __db_byteorder __P((DB_ENV *, int));
|
||||
*/
|
||||
int
|
||||
__db_byteorder(dbenv, lorder)
|
||||
DB_ENV *dbenv;
|
||||
int lorder;
|
||||
{
|
||||
switch (lorder) {
|
||||
case 0:
|
||||
break;
|
||||
case 1234:
|
||||
#if defined(WORDS_BIGENDIAN)
|
||||
return (DB_SWAPBYTES);
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
case 4321:
|
||||
#if defined(WORDS_BIGENDIAN)
|
||||
break;
|
||||
#else
|
||||
return (DB_SWAPBYTES);
|
||||
#endif
|
||||
default:
|
||||
__db_err(dbenv,
|
||||
"illegal byte order, only big and little-endian supported");
|
||||
return (EINVAL);
|
||||
}
|
||||
return (0);
|
||||
}
|
|
@ -1,615 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_err.c 10.25 (Sleepycat) 5/2/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
static int __db_keyempty __P((const DB_ENV *));
|
||||
static int __db_rdonly __P((const DB_ENV *, const char *));
|
||||
|
||||
/*
|
||||
* __db_err --
|
||||
* Standard DB error routine.
|
||||
*
|
||||
* PUBLIC: #ifdef __STDC__
|
||||
* PUBLIC: void __db_err __P((const DB_ENV *dbenv, const char *fmt, ...));
|
||||
* PUBLIC: #else
|
||||
* PUBLIC: void __db_err();
|
||||
* PUBLIC: #endif
|
||||
*/
|
||||
void
|
||||
#ifdef __STDC__
|
||||
__db_err(const DB_ENV *dbenv, const char *fmt, ...)
|
||||
#else
|
||||
__db_err(dbenv, fmt, va_alist)
|
||||
const DB_ENV *dbenv;
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
char errbuf[2048]; /* XXX: END OF THE STACK DON'T TRUST SPRINTF. */
|
||||
|
||||
if (dbenv == NULL)
|
||||
return;
|
||||
|
||||
#ifdef __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
if (dbenv->db_errcall != NULL) {
|
||||
(void)vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
|
||||
dbenv->db_errcall(dbenv->db_errpfx, errbuf);
|
||||
}
|
||||
if (dbenv->db_errfile != NULL) {
|
||||
if (dbenv->db_errpfx != NULL)
|
||||
(void)fprintf(dbenv->db_errfile, "%s: ",
|
||||
dbenv->db_errpfx);
|
||||
(void)vfprintf(dbenv->db_errfile, fmt, ap);
|
||||
(void)fprintf(dbenv->db_errfile, "\n");
|
||||
(void)fflush(dbenv->db_errfile);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Provide ANSI C prototypes for the panic functions. Some compilers, (e.g.,
|
||||
* MS VC 4.2) get upset if they aren't here, even though the K&R declaration
|
||||
* appears before the assignment in the __db__panic() call.
|
||||
*/
|
||||
static int __db_ecursor __P((DB *, DB_TXN *, DBC **));
|
||||
static int __db_edel __P((DB *, DB_TXN *, DBT *, u_int32_t));
|
||||
static int __db_efd __P((DB *, int *));
|
||||
static int __db_egp __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
|
||||
static int __db_estat __P((DB *, void *, void *(*)(size_t), u_int32_t));
|
||||
static int __db_esync __P((DB *, u_int32_t));
|
||||
|
||||
/*
|
||||
* __db_ecursor --
|
||||
* After-panic cursor routine.
|
||||
*/
|
||||
static int
|
||||
__db_ecursor(a, b, c)
|
||||
DB *a;
|
||||
DB_TXN *b;
|
||||
DBC **c;
|
||||
{
|
||||
COMPQUIET(a, NULL);
|
||||
COMPQUIET(b, NULL);
|
||||
COMPQUIET(c, NULL);
|
||||
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_edel --
|
||||
* After-panic delete routine.
|
||||
*/
|
||||
static int
|
||||
__db_edel(a, b, c, d)
|
||||
DB *a;
|
||||
DB_TXN *b;
|
||||
DBT *c;
|
||||
u_int32_t d;
|
||||
{
|
||||
COMPQUIET(a, NULL);
|
||||
COMPQUIET(b, NULL);
|
||||
COMPQUIET(c, NULL);
|
||||
COMPQUIET(d, 0);
|
||||
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_efd --
|
||||
* After-panic fd routine.
|
||||
*/
|
||||
static int
|
||||
__db_efd(a, b)
|
||||
DB *a;
|
||||
int *b;
|
||||
{
|
||||
COMPQUIET(a, NULL);
|
||||
COMPQUIET(b, NULL);
|
||||
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_egp --
|
||||
* After-panic get/put routine.
|
||||
*/
|
||||
static int
|
||||
__db_egp(a, b, c, d, e)
|
||||
DB *a;
|
||||
DB_TXN *b;
|
||||
DBT *c, *d;
|
||||
u_int32_t e;
|
||||
{
|
||||
COMPQUIET(a, NULL);
|
||||
COMPQUIET(b, NULL);
|
||||
COMPQUIET(c, NULL);
|
||||
COMPQUIET(d, NULL);
|
||||
COMPQUIET(e, 0);
|
||||
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_estat --
|
||||
* After-panic stat routine.
|
||||
*/
|
||||
static int
|
||||
__db_estat(a, b, c, d)
|
||||
DB *a;
|
||||
void *b;
|
||||
void *(*c) __P((size_t));
|
||||
u_int32_t d;
|
||||
{
|
||||
COMPQUIET(a, NULL);
|
||||
COMPQUIET(b, NULL);
|
||||
COMPQUIET(c, NULL);
|
||||
COMPQUIET(d, 0);
|
||||
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_esync --
|
||||
* After-panic sync routine.
|
||||
*/
|
||||
static int
|
||||
__db_esync(a, b)
|
||||
DB *a;
|
||||
u_int32_t b;
|
||||
{
|
||||
COMPQUIET(a, NULL);
|
||||
COMPQUIET(b, 0);
|
||||
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_panic --
|
||||
* Lock out the tree due to unrecoverable error.
|
||||
*
|
||||
* PUBLIC: int __db_panic __P((DB *));
|
||||
*/
|
||||
int
|
||||
__db_panic(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
/*
|
||||
* XXX
|
||||
* We should shut down all of the process's cursors, too.
|
||||
*
|
||||
* We should call mpool and have it shut down the file, so we get
|
||||
* other processes sharing this file as well.
|
||||
*
|
||||
* Chaos reigns within.
|
||||
* Reflect, repent, and reboot.
|
||||
* Order shall return.
|
||||
*/
|
||||
dbp->cursor = __db_ecursor;
|
||||
dbp->del = __db_edel;
|
||||
dbp->fd = __db_efd;
|
||||
dbp->get = __db_egp;
|
||||
dbp->put = __db_egp;
|
||||
dbp->stat = __db_estat;
|
||||
dbp->sync = __db_esync;
|
||||
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
/* Check for invalid flags. */
|
||||
#undef DB_CHECK_FLAGS
|
||||
#define DB_CHECK_FLAGS(dbenv, name, flags, ok_flags) \
|
||||
if ((flags) & ~(ok_flags)) \
|
||||
return (__db_ferr(dbenv, name, 0));
|
||||
/* Check for invalid flag combinations. */
|
||||
#undef DB_CHECK_FCOMBO
|
||||
#define DB_CHECK_FCOMBO(dbenv, name, flags, flag1, flag2) \
|
||||
if ((flags) & (flag1) && (flags) & (flag2)) \
|
||||
return (__db_ferr(dbenv, name, 1));
|
||||
|
||||
/*
|
||||
* __db_fchk --
|
||||
* General flags checking routine.
|
||||
*
|
||||
* PUBLIC: int __db_fchk __P((DB_ENV *, const char *, u_int32_t, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_fchk(dbenv, name, flags, ok_flags)
|
||||
DB_ENV *dbenv;
|
||||
const char *name;
|
||||
u_int32_t flags, ok_flags;
|
||||
{
|
||||
DB_CHECK_FLAGS(dbenv, name, flags, ok_flags);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_fcchk --
|
||||
* General combination flags checking routine.
|
||||
*
|
||||
* PUBLIC: int __db_fcchk
|
||||
* PUBLIC: __P((DB_ENV *, const char *, u_int32_t, u_int32_t, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_fcchk(dbenv, name, flags, flag1, flag2)
|
||||
DB_ENV *dbenv;
|
||||
const char *name;
|
||||
u_int32_t flags, flag1, flag2;
|
||||
{
|
||||
DB_CHECK_FCOMBO(dbenv, name, flags, flag1, flag2);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_cdelchk --
|
||||
* Common cursor delete argument checking routine.
|
||||
*
|
||||
* PUBLIC: int __db_cdelchk __P((const DB *, u_int32_t, int, int));
|
||||
*/
|
||||
int
|
||||
__db_cdelchk(dbp, flags, isrdonly, isvalid)
|
||||
const DB *dbp;
|
||||
u_int32_t flags;
|
||||
int isrdonly, isvalid;
|
||||
{
|
||||
/* Check for changes to a read-only tree. */
|
||||
if (isrdonly)
|
||||
return (__db_rdonly(dbp->dbenv, "c_del"));
|
||||
|
||||
/* Check for invalid dbc->c_del() function flags. */
|
||||
DB_CHECK_FLAGS(dbp->dbenv, "c_del", flags, 0);
|
||||
|
||||
/*
|
||||
* The cursor must be initialized, return -1 for an invalid cursor,
|
||||
* otherwise 0.
|
||||
*/
|
||||
return (isvalid ? 0 : EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_cgetchk --
|
||||
* Common cursor get argument checking routine.
|
||||
*
|
||||
* PUBLIC: int __db_cgetchk __P((const DB *, DBT *, DBT *, u_int32_t, int));
|
||||
*/
|
||||
int
|
||||
__db_cgetchk(dbp, key, data, flags, isvalid)
|
||||
const DB *dbp;
|
||||
DBT *key, *data;
|
||||
u_int32_t flags;
|
||||
int isvalid;
|
||||
{
|
||||
int key_einval, key_flags;
|
||||
|
||||
key_flags = key_einval = 0;
|
||||
|
||||
/* Check for invalid dbc->c_get() function flags. */
|
||||
switch (flags) {
|
||||
case DB_CURRENT:
|
||||
case DB_FIRST:
|
||||
case DB_LAST:
|
||||
case DB_NEXT:
|
||||
case DB_PREV:
|
||||
key_flags = 1;
|
||||
break;
|
||||
case DB_SET_RANGE:
|
||||
key_einval = key_flags = 1;
|
||||
break;
|
||||
case DB_SET:
|
||||
key_einval = 1;
|
||||
break;
|
||||
case DB_GET_RECNO:
|
||||
if (!F_ISSET(dbp, DB_BT_RECNUM))
|
||||
goto err;
|
||||
break;
|
||||
case DB_SET_RECNO:
|
||||
if (!F_ISSET(dbp, DB_BT_RECNUM))
|
||||
goto err;
|
||||
key_einval = key_flags = 1;
|
||||
break;
|
||||
default:
|
||||
err: return (__db_ferr(dbp->dbenv, "c_get", 0));
|
||||
}
|
||||
|
||||
/* Check for invalid key/data flags. */
|
||||
if (key_flags)
|
||||
DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags,
|
||||
DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
|
||||
DB_CHECK_FLAGS(dbp->dbenv, "data", data->flags,
|
||||
DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
|
||||
|
||||
/* Check dbt's for valid flags when multi-threaded. */
|
||||
if (F_ISSET(dbp, DB_AM_THREAD)) {
|
||||
if (!F_ISSET(data, DB_DBT_USERMEM | DB_DBT_MALLOC))
|
||||
return (__db_ferr(dbp->dbenv, "threaded data", 1));
|
||||
if (key_flags &&
|
||||
!F_ISSET(key, DB_DBT_USERMEM | DB_DBT_MALLOC))
|
||||
return (__db_ferr(dbp->dbenv, "threaded key", 1));
|
||||
}
|
||||
|
||||
/* Check for missing keys. */
|
||||
if (key_einval && (key->data == NULL || key->size == 0))
|
||||
return (__db_keyempty(dbp->dbenv));
|
||||
|
||||
/*
|
||||
* The cursor must be initialized for DB_CURRENT, return -1 for an
|
||||
* invalid cursor, otherwise 0.
|
||||
*/
|
||||
return (isvalid || flags != DB_CURRENT ? 0 : EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_cputchk --
|
||||
* Common cursor put argument checking routine.
|
||||
*
|
||||
* PUBLIC: int __db_cputchk __P((const DB *,
|
||||
* PUBLIC: const DBT *, DBT *, u_int32_t, int, int));
|
||||
*/
|
||||
int
|
||||
__db_cputchk(dbp, key, data, flags, isrdonly, isvalid)
|
||||
const DB *dbp;
|
||||
const DBT *key;
|
||||
DBT *data;
|
||||
u_int32_t flags;
|
||||
int isrdonly, isvalid;
|
||||
{
|
||||
int key_einval, key_flags;
|
||||
|
||||
/* Check for changes to a read-only tree. */
|
||||
if (isrdonly)
|
||||
return (__db_rdonly(dbp->dbenv, "c_put"));
|
||||
|
||||
/* Check for invalid dbc->c_put() function flags. */
|
||||
key_einval = key_flags = 0;
|
||||
switch (flags) {
|
||||
case DB_AFTER:
|
||||
case DB_BEFORE:
|
||||
if (dbp->type == DB_RECNO && !F_ISSET(dbp, DB_RE_RENUMBER))
|
||||
goto err;
|
||||
if (dbp->type != DB_RECNO && !F_ISSET(dbp, DB_AM_DUP))
|
||||
goto err;
|
||||
break;
|
||||
case DB_CURRENT:
|
||||
break;
|
||||
case DB_KEYFIRST:
|
||||
case DB_KEYLAST:
|
||||
if (dbp->type == DB_RECNO)
|
||||
goto err;
|
||||
key_einval = key_flags = 1;
|
||||
break;
|
||||
default:
|
||||
err: return (__db_ferr(dbp->dbenv, "c_put", 0));
|
||||
}
|
||||
|
||||
/* Check for invalid key/data flags. */
|
||||
if (key_flags)
|
||||
DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags,
|
||||
DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
|
||||
DB_CHECK_FLAGS(dbp->dbenv, "data", data->flags,
|
||||
DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
|
||||
|
||||
/* Check for missing keys. */
|
||||
if (key_einval && (key->data == NULL || key->size == 0))
|
||||
return (__db_keyempty(dbp->dbenv));
|
||||
|
||||
/*
|
||||
* The cursor must be initialized for anything other than DB_KEYFIRST
|
||||
* and DB_KEYLAST, return -1 for an invalid cursor, otherwise 0.
|
||||
*/
|
||||
return (isvalid ||
|
||||
(flags != DB_KEYFIRST && flags != DB_KEYLAST) ? 0 : EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_delchk --
|
||||
* Common delete argument checking routine.
|
||||
*
|
||||
* PUBLIC: int __db_delchk __P((const DB *, DBT *, u_int32_t, int));
|
||||
*/
|
||||
int
|
||||
__db_delchk(dbp, key, flags, isrdonly)
|
||||
const DB *dbp;
|
||||
DBT *key;
|
||||
u_int32_t flags;
|
||||
int isrdonly;
|
||||
{
|
||||
/* Check for changes to a read-only tree. */
|
||||
if (isrdonly)
|
||||
return (__db_rdonly(dbp->dbenv, "delete"));
|
||||
|
||||
/* Check for invalid db->del() function flags. */
|
||||
DB_CHECK_FLAGS(dbp->dbenv, "delete", flags, 0);
|
||||
|
||||
/* Check for missing keys. */
|
||||
if (key->data == NULL || key->size == 0)
|
||||
return (__db_keyempty(dbp->dbenv));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_getchk --
|
||||
* Common get argument checking routine.
|
||||
*
|
||||
* PUBLIC: int __db_getchk __P((const DB *, const DBT *, DBT *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_getchk(dbp, key, data, flags)
|
||||
const DB *dbp;
|
||||
const DBT *key;
|
||||
DBT *data;
|
||||
u_int32_t flags;
|
||||
{
|
||||
/* Check for invalid db->get() function flags. */
|
||||
DB_CHECK_FLAGS(dbp->dbenv,
|
||||
"get", flags, F_ISSET(dbp, DB_BT_RECNUM) ? DB_SET_RECNO : 0);
|
||||
|
||||
/* Check for invalid key/data flags. */
|
||||
DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags, 0);
|
||||
DB_CHECK_FLAGS(dbp->dbenv, "data", data->flags,
|
||||
DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
|
||||
DB_CHECK_FCOMBO(dbp->dbenv,
|
||||
"data", data->flags, DB_DBT_MALLOC, DB_DBT_USERMEM);
|
||||
if (F_ISSET(dbp, DB_AM_THREAD) &&
|
||||
!F_ISSET(data, DB_DBT_MALLOC | DB_DBT_USERMEM))
|
||||
return (__db_ferr(dbp->dbenv, "threaded data", 1));
|
||||
|
||||
/* Check for missing keys. */
|
||||
if (key->data == NULL || key->size == 0)
|
||||
return (__db_keyempty(dbp->dbenv));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_putchk --
|
||||
* Common put argument checking routine.
|
||||
*
|
||||
* PUBLIC: int __db_putchk
|
||||
* PUBLIC: __P((const DB *, DBT *, const DBT *, u_int32_t, int, int));
|
||||
*/
|
||||
int
|
||||
__db_putchk(dbp, key, data, flags, isrdonly, isdup)
|
||||
const DB *dbp;
|
||||
DBT *key;
|
||||
const DBT *data;
|
||||
u_int32_t flags;
|
||||
int isrdonly, isdup;
|
||||
{
|
||||
/* Check for changes to a read-only tree. */
|
||||
if (isrdonly)
|
||||
return (__db_rdonly(dbp->dbenv, "put"));
|
||||
|
||||
/* Check for invalid db->put() function flags. */
|
||||
DB_CHECK_FLAGS(dbp->dbenv, "put", flags,
|
||||
DB_NOOVERWRITE | (dbp->type == DB_RECNO ? DB_APPEND : 0));
|
||||
|
||||
/* Check for invalid key/data flags. */
|
||||
DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags, 0);
|
||||
DB_CHECK_FLAGS(dbp->dbenv, "data", data->flags,
|
||||
DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
|
||||
DB_CHECK_FCOMBO(dbp->dbenv,
|
||||
"data", data->flags, DB_DBT_MALLOC, DB_DBT_USERMEM);
|
||||
|
||||
/* Check for missing keys. */
|
||||
if (key->data == NULL || key->size == 0)
|
||||
return (__db_keyempty(dbp->dbenv));
|
||||
|
||||
/* Check for partial puts in the presence of duplicates. */
|
||||
if (isdup && F_ISSET(data, DB_DBT_PARTIAL)) {
|
||||
__db_err(dbp->dbenv,
|
||||
"a partial put in the presence of duplicates requires a cursor operation");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_statchk --
|
||||
* Common stat argument checking routine.
|
||||
*
|
||||
* PUBLIC: int __db_statchk __P((const DB *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_statchk(dbp, flags)
|
||||
const DB *dbp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
/* Check for invalid db->stat() function flags. */
|
||||
DB_CHECK_FLAGS(dbp->dbenv, "stat", flags, DB_RECORDCOUNT);
|
||||
|
||||
if (LF_ISSET(DB_RECORDCOUNT) &&
|
||||
dbp->type == DB_BTREE && !F_ISSET(dbp, DB_BT_RECNUM))
|
||||
return (__db_ferr(dbp->dbenv, "stat", 0));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_syncchk --
|
||||
* Common sync argument checking routine.
|
||||
*
|
||||
* PUBLIC: int __db_syncchk __P((const DB *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_syncchk(dbp, flags)
|
||||
const DB *dbp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
/* Check for invalid db->sync() function flags. */
|
||||
DB_CHECK_FLAGS(dbp->dbenv, "sync", flags, 0);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_ferr --
|
||||
* Common flag errors.
|
||||
*
|
||||
* PUBLIC: int __db_ferr __P((const DB_ENV *, const char *, int));
|
||||
*/
|
||||
int
|
||||
__db_ferr(dbenv, name, iscombo)
|
||||
const DB_ENV *dbenv;
|
||||
const char *name;
|
||||
int iscombo;
|
||||
{
|
||||
__db_err(dbenv, "illegal flag %sspecified to %s",
|
||||
iscombo ? "combination " : "", name);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_rdonly --
|
||||
* Common readonly message.
|
||||
*/
|
||||
static int
|
||||
__db_rdonly(dbenv, name)
|
||||
const DB_ENV *dbenv;
|
||||
const char *name;
|
||||
{
|
||||
__db_err(dbenv, "%s: attempt to modify a read-only tree", name);
|
||||
return (EACCES);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_keyempty --
|
||||
* Common missing or empty key value message.
|
||||
*/
|
||||
static int
|
||||
__db_keyempty(dbenv)
|
||||
const DB_ENV *dbenv;
|
||||
{
|
||||
__db_err(dbenv, "missing or empty key value specified");
|
||||
return (EINVAL);
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995, 1996
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Margo Seltzer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_log2.c 10.5 (Sleepycat) 4/26/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
/*
|
||||
* PUBLIC: u_int32_t __db_log2 __P((u_int32_t));
|
||||
*/
|
||||
u_int32_t
|
||||
__db_log2(num)
|
||||
u_int32_t num;
|
||||
{
|
||||
u_int32_t i, limit;
|
||||
|
||||
limit = 1;
|
||||
for (i = 0; limit < num; limit = limit << 1, i++)
|
||||
;
|
||||
return (i);
|
||||
}
|
|
@ -1,861 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_region.c 10.46 (Sleepycat) 5/26/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
static int __db_growregion __P((REGINFO *, size_t));
|
||||
|
||||
/*
|
||||
* __db_rattach --
|
||||
* Optionally create and attach to a shared memory region.
|
||||
*
|
||||
* PUBLIC: int __db_rattach __P((REGINFO *));
|
||||
*/
|
||||
int
|
||||
__db_rattach(infop)
|
||||
REGINFO *infop;
|
||||
{
|
||||
RLAYOUT *rlp, rl;
|
||||
size_t grow_region, size;
|
||||
ssize_t nr, nw;
|
||||
u_int32_t flags, mbytes, bytes;
|
||||
u_int8_t *p;
|
||||
int malloc_possible, ret, retry_cnt;
|
||||
|
||||
grow_region = 0;
|
||||
malloc_possible = 1;
|
||||
ret = retry_cnt = 0;
|
||||
|
||||
/* Round off the requested size to the next page boundary. */
|
||||
DB_ROUNDOFF(infop->size);
|
||||
|
||||
/* Some architectures have hard limits on the maximum region size. */
|
||||
#ifdef DB_REGIONSIZE_MAX
|
||||
if (infop->size > DB_REGIONSIZE_MAX) {
|
||||
__db_err(infop->dbenv, "__db_rattach: cache size too large");
|
||||
return (EINVAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Intialize the return information in the REGINFO structure. */
|
||||
loop: infop->addr = NULL;
|
||||
infop->fd = -1;
|
||||
infop->segid = INVALID_SEGID;
|
||||
if (infop->name != NULL) {
|
||||
FREES(infop->name);
|
||||
infop->name = NULL;
|
||||
}
|
||||
F_CLR(infop, REGION_CANGROW | REGION_CREATED);
|
||||
|
||||
#ifndef HAVE_SPINLOCKS
|
||||
/*
|
||||
* XXX
|
||||
* Lacking spinlocks, we must have a file descriptor for fcntl(2)
|
||||
* locking, which implies using mmap(2) to map in a regular file.
|
||||
* (Theoretically, we could probably get a file descriptor to lock
|
||||
* other types of shared regions, but I don't see any reason to
|
||||
* bother.)
|
||||
*/
|
||||
malloc_possible = 0;
|
||||
#endif
|
||||
|
||||
#ifdef __hppa
|
||||
/*
|
||||
* XXX
|
||||
* HP-UX won't permit mutexes to live in anything but shared memory.
|
||||
* Instantiate a shared region file on that architecture, regardless.
|
||||
*/
|
||||
malloc_possible = 0;
|
||||
#endif
|
||||
/*
|
||||
* If a region is truly private, malloc the memory. That's faster
|
||||
* than either anonymous memory or a shared file.
|
||||
*/
|
||||
if (malloc_possible && F_ISSET(infop, REGION_PRIVATE)) {
|
||||
if ((infop->addr = __db_malloc(infop->size)) == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
/*
|
||||
* It's sometimes significantly faster to page-fault in all
|
||||
* of the region's pages before we run the application, as
|
||||
* we can see fairly nasty side-effects when we page-fault
|
||||
* while holding various locks, i.e., the lock takes a long
|
||||
* time, and other threads convoy behind the lock holder.
|
||||
*/
|
||||
if (DB_GLOBAL(db_region_init))
|
||||
for (p = infop->addr;
|
||||
p < (u_int8_t *)infop->addr + infop->size;
|
||||
p += DB_VMPAGESIZE)
|
||||
p[0] = '\0';
|
||||
|
||||
F_SET(infop, REGION_CREATED | REGION_MALLOC);
|
||||
goto region_init;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the name of the region (creating the file if a temporary file
|
||||
* is being used). The dbenv contains the current DB environment,
|
||||
* including naming information. The path argument may be a file or
|
||||
* a directory. If path is a directory, it must exist and file is the
|
||||
* file name to be created inside the directory. If path is a file,
|
||||
* then file must be NULL.
|
||||
*/
|
||||
if ((ret = __db_appname(infop->dbenv, infop->appname, infop->path,
|
||||
infop->file, infop->dbflags, &infop->fd, &infop->name)) != 0)
|
||||
return (ret);
|
||||
if (infop->fd != -1)
|
||||
F_SET(infop, REGION_CREATED);
|
||||
|
||||
/*
|
||||
* Try to create the file, if we have authority. We have to make sure
|
||||
* that multiple threads/processes attempting to simultaneously create
|
||||
* the region are properly ordered, so we open it using DB_CREATE and
|
||||
* DB_EXCL, so two attempts to create the region will return failure in
|
||||
* one.
|
||||
*/
|
||||
if (infop->fd == -1 && infop->dbflags & DB_CREATE) {
|
||||
flags = infop->dbflags;
|
||||
LF_SET(DB_EXCL);
|
||||
if ((ret = __db_open(infop->name,
|
||||
flags, flags, infop->mode, &infop->fd)) == 0)
|
||||
F_SET(infop, REGION_CREATED);
|
||||
else
|
||||
if (ret != EEXIST)
|
||||
goto errmsg;
|
||||
}
|
||||
|
||||
/* If we couldn't create the file, try and open it. */
|
||||
if (infop->fd == -1) {
|
||||
flags = infop->dbflags;
|
||||
LF_CLR(DB_CREATE | DB_EXCL);
|
||||
if ((ret = __db_open(infop->name,
|
||||
flags, flags, infop->mode, &infop->fd)) != 0)
|
||||
goto errmsg;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are three cases we support:
|
||||
* 1. Named anonymous memory (shmget(2)).
|
||||
* 2. Unnamed anonymous memory (mmap(2): MAP_ANON/MAP_ANONYMOUS).
|
||||
* 3. Memory backed by a regular file (mmap(2)).
|
||||
*
|
||||
* We instantiate a backing file in all cases, which contains at least
|
||||
* the RLAYOUT structure, and in case #4, contains the actual region.
|
||||
* This is necessary for a couple of reasons:
|
||||
*
|
||||
* First, the mpool region uses temporary files to name regions, and
|
||||
* since you may have multiple regions in the same directory, we need
|
||||
* a filesystem name to ensure that they don't collide.
|
||||
*
|
||||
* Second, applications are allowed to forcibly remove regions, even
|
||||
* if they don't know anything about them other than the name. If a
|
||||
* region is backed by anonymous memory, there has to be some way for
|
||||
* the application to find out that information, and, in some cases,
|
||||
* determine ID information for the anonymous memory.
|
||||
*/
|
||||
if (F_ISSET(infop, REGION_CREATED)) {
|
||||
/*
|
||||
* If we're using anonymous memory to back this region, set
|
||||
* the flag.
|
||||
*/
|
||||
if (DB_GLOBAL(db_region_anon))
|
||||
F_SET(infop, REGION_ANONYMOUS);
|
||||
|
||||
/*
|
||||
* If we're using a regular file to back a region we created,
|
||||
* grow it to the specified size.
|
||||
*/
|
||||
if (!DB_GLOBAL(db_region_anon) &&
|
||||
(ret = __db_growregion(infop, infop->size)) != 0)
|
||||
goto err;
|
||||
} else {
|
||||
/*
|
||||
* If we're joining a region, figure out what it looks like.
|
||||
*
|
||||
* XXX
|
||||
* We have to figure out if the file is a regular file backing
|
||||
* a region that we want to map into our address space, or a
|
||||
* file with the information we need to find a shared anonymous
|
||||
* region that we want to map into our address space.
|
||||
*
|
||||
* All this noise is because some systems don't have a coherent
|
||||
* VM and buffer cache, and worse, if you mix operations on the
|
||||
* VM and buffer cache, half the time you hang the system.
|
||||
*
|
||||
* There are two possibilities. If the file is the size of an
|
||||
* RLAYOUT structure, then we know that the real region is in
|
||||
* shared memory, because otherwise it would be bigger. (As
|
||||
* the RLAYOUT structure size is smaller than a disk sector,
|
||||
* the only way it can be this size is if deliberately written
|
||||
* that way.) In which case, retrieve the information we need
|
||||
* from the RLAYOUT structure and use it to acquire the shared
|
||||
* memory.
|
||||
*
|
||||
* If the structure is larger than an RLAYOUT structure, then
|
||||
* the file is backing the shared memory region, and we use
|
||||
* the current size of the file without reading any information
|
||||
* from the file itself so that we don't confuse the VM.
|
||||
*
|
||||
* And yes, this makes me want to take somebody and kill them,
|
||||
* but I can't think of any other solution.
|
||||
*/
|
||||
if ((ret = __db_ioinfo(infop->name,
|
||||
infop->fd, &mbytes, &bytes, NULL)) != 0)
|
||||
goto errmsg;
|
||||
size = mbytes * MEGABYTE + bytes;
|
||||
|
||||
if (size <= sizeof(RLAYOUT)) {
|
||||
/*
|
||||
* If the size is too small, the read fails or the
|
||||
* valid flag is incorrect, assume it's because the
|
||||
* RLAYOUT information hasn't been written out yet,
|
||||
* and retry.
|
||||
*/
|
||||
if (size < sizeof(RLAYOUT))
|
||||
goto retry;
|
||||
if ((ret =
|
||||
__db_read(infop->fd, &rl, sizeof(rl), &nr)) != 0)
|
||||
goto retry;
|
||||
if (rl.valid != DB_REGIONMAGIC)
|
||||
goto retry;
|
||||
|
||||
/* Copy the size, memory id and characteristics. */
|
||||
size = rl.size;
|
||||
infop->segid = rl.segid;
|
||||
if (F_ISSET(&rl, REGION_ANONYMOUS))
|
||||
F_SET(infop, REGION_ANONYMOUS);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the region is larger than we think, that's okay, use the
|
||||
* current size. If it's smaller than we think, and we were
|
||||
* just using the default size, that's okay, use the current
|
||||
* size. If it's smaller than we think and we really care,
|
||||
* save the size and we'll catch that further down -- we can't
|
||||
* correct it here because we have to have a lock to grow the
|
||||
* region.
|
||||
*/
|
||||
if (infop->size > size && !F_ISSET(infop, REGION_SIZEDEF))
|
||||
grow_region = infop->size;
|
||||
infop->size = size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Map the region into our address space. If we're creating it, the
|
||||
* underlying routines will make it the right size.
|
||||
*
|
||||
* There are at least two cases where we can "reasonably" fail when
|
||||
* we attempt to map in the region. On Windows/95, closing the last
|
||||
* reference to a region causes it to be zeroed out. On UNIX, when
|
||||
* using the shmget(2) interfaces, the region will no longer exist
|
||||
* if the system was rebooted. In these cases, the underlying map call
|
||||
* returns EAGAIN, and we *remove* our file and try again. There are
|
||||
* obvious races in doing this, but it should eventually settle down
|
||||
* to a winner and then things should proceed normally.
|
||||
*/
|
||||
if ((ret = __db_mapregion(infop->name, infop)) != 0)
|
||||
if (ret == EAGAIN) {
|
||||
/*
|
||||
* Pretend we created the region even if we didn't so
|
||||
* that our error processing unlinks it.
|
||||
*/
|
||||
F_SET(infop, REGION_CREATED);
|
||||
ret = 0;
|
||||
goto retry;
|
||||
} else
|
||||
goto err;
|
||||
|
||||
region_init:
|
||||
/*
|
||||
* Initialize the common region information.
|
||||
*
|
||||
* !!!
|
||||
* We have to order the region creates so that two processes don't try
|
||||
* to simultaneously create the region. This is handled by using the
|
||||
* DB_CREATE and DB_EXCL flags when we create the "backing" region file.
|
||||
*
|
||||
* We also have to order region joins so that processes joining regions
|
||||
* never see inconsistent data. We'd like to play permissions games
|
||||
* with the backing file, but we can't because WNT filesystems won't
|
||||
* open a file mode 0.
|
||||
*/
|
||||
rlp = (RLAYOUT *)infop->addr;
|
||||
if (F_ISSET(infop, REGION_CREATED)) {
|
||||
/*
|
||||
* The process creating the region acquires a lock before it
|
||||
* sets the valid flag. Any processes joining the region will
|
||||
* check the valid flag before acquiring the lock.
|
||||
*
|
||||
* Check the return of __db_mutex_init() and __db_mutex_lock(),
|
||||
* even though we don't usually check elsewhere. This is the
|
||||
* first lock we initialize and acquire, and we have to know if
|
||||
* it fails. (It CAN fail, e.g., SunOS, when using fcntl(2)
|
||||
* for locking, with an in-memory filesystem specified as the
|
||||
* database home.)
|
||||
*/
|
||||
if ((ret = __db_mutex_init(&rlp->lock,
|
||||
MUTEX_LOCK_OFFSET(rlp, &rlp->lock))) != 0 ||
|
||||
(ret = __db_mutex_lock(&rlp->lock, infop->fd)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Initialize the remaining region information. */
|
||||
rlp->refcnt = 1;
|
||||
rlp->size = infop->size;
|
||||
db_version(&rlp->majver, &rlp->minver, &rlp->patch);
|
||||
rlp->segid = infop->segid;
|
||||
rlp->flags = 0;
|
||||
if (F_ISSET(infop, REGION_ANONYMOUS))
|
||||
F_SET(rlp, REGION_ANONYMOUS);
|
||||
|
||||
/*
|
||||
* Fill in the valid field last -- use a magic number, memory
|
||||
* may not be zero-filled, and we want to minimize the chance
|
||||
* for collision.
|
||||
*/
|
||||
rlp->valid = DB_REGIONMAGIC;
|
||||
|
||||
/*
|
||||
* If the region is anonymous, write the RLAYOUT information
|
||||
* into the backing file so that future region join and unlink
|
||||
* calls can find it.
|
||||
*
|
||||
* XXX
|
||||
* We MUST do the seek before we do the write. On Win95, while
|
||||
* closing the last reference to an anonymous shared region
|
||||
* doesn't discard the region, it does zero it out. So, the
|
||||
* REGION_CREATED may be set, but the file may have already
|
||||
* been written and the file descriptor may be at the end of
|
||||
* the file.
|
||||
*/
|
||||
if (F_ISSET(infop, REGION_ANONYMOUS)) {
|
||||
if ((ret = __db_seek(infop->fd, 0, 0, 0, 0, 0)) != 0)
|
||||
goto err;
|
||||
if ((ret =
|
||||
__db_write(infop->fd, rlp, sizeof(*rlp), &nw)) != 0)
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Check the valid flag to ensure the region is initialized.
|
||||
* If the valid flag has not been set, the mutex may not have
|
||||
* been initialized, and an attempt to get it could lead to
|
||||
* random behavior.
|
||||
*/
|
||||
if (rlp->valid != DB_REGIONMAGIC)
|
||||
goto retry;
|
||||
|
||||
/* Get the region lock. */
|
||||
(void)__db_mutex_lock(&rlp->lock, infop->fd);
|
||||
|
||||
/*
|
||||
* We now own the region. There are a couple of things that
|
||||
* may have gone wrong, however.
|
||||
*
|
||||
* Problem #1: while we were waiting for the lock, the region
|
||||
* was deleted. Detected by re-checking the valid flag, since
|
||||
* it's cleared by the delete region routines.
|
||||
*/
|
||||
if (rlp->valid != DB_REGIONMAGIC) {
|
||||
(void)__db_mutex_unlock(&rlp->lock, infop->fd);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/*
|
||||
* Problem #2: We want a bigger region than has previously been
|
||||
* created. Detected by checking if the region is smaller than
|
||||
* our caller requested. If it is, we grow the region, (which
|
||||
* does the detach and re-attach for us).
|
||||
*/
|
||||
if (grow_region != 0 &&
|
||||
(ret = __db_rgrow(infop, grow_region)) != 0) {
|
||||
(void)__db_mutex_unlock(&rlp->lock, infop->fd);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Problem #3: when we checked the size of the file, it was
|
||||
* still growing as part of creation. Detected by the fact
|
||||
* that infop->size isn't the same size as the region.
|
||||
*/
|
||||
if (infop->size != rlp->size) {
|
||||
(void)__db_mutex_unlock(&rlp->lock, infop->fd);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Increment the reference count. */
|
||||
++rlp->refcnt;
|
||||
}
|
||||
|
||||
/* Return the region in a locked condition. */
|
||||
|
||||
if (0) {
|
||||
errmsg: __db_err(infop->dbenv, "%s: %s", infop->name, strerror(ret));
|
||||
|
||||
err:
|
||||
retry: /* Discard the region. */
|
||||
if (infop->addr != NULL) {
|
||||
(void)__db_unmapregion(infop);
|
||||
infop->addr = NULL;
|
||||
}
|
||||
|
||||
/* Discard the backing file. */
|
||||
if (infop->fd != -1) {
|
||||
(void)__db_close(infop->fd);
|
||||
infop->fd = -1;
|
||||
|
||||
if (F_ISSET(infop, REGION_CREATED))
|
||||
(void)__db_unlink(infop->name);
|
||||
}
|
||||
|
||||
/* Discard the name. */
|
||||
if (infop->name != NULL) {
|
||||
FREES(infop->name);
|
||||
infop->name = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we had a temporary error, wait a few seconds and
|
||||
* try again.
|
||||
*/
|
||||
if (ret == 0) {
|
||||
if (++retry_cnt <= 3) {
|
||||
__db_sleep(retry_cnt * 2, 0);
|
||||
goto loop;
|
||||
}
|
||||
ret = EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* HP-UX won't permit mutexes to live in anything but shared memory.
|
||||
* Instantiate a shared region file on that architecture, regardless.
|
||||
*
|
||||
* XXX
|
||||
* There's a problem in cleaning this up on application exit, or on
|
||||
* application failure. If an application opens a database without
|
||||
* an environment, we create a temporary backing mpool region for it.
|
||||
* That region is marked REGION_PRIVATE, but as HP-UX won't permit
|
||||
* mutexes to live in anything but shared memory, we instantiate a
|
||||
* real file plus a memory region of some form. If the application
|
||||
* crashes, the necessary information to delete the backing file and
|
||||
* any system region (e.g., the shmget(2) segment ID) is no longer
|
||||
* available. We can't completely fix the problem, but we try.
|
||||
*
|
||||
* The underlying UNIX __db_mapregion() code preferentially uses the
|
||||
* mmap(2) interface with the MAP_ANON/MAP_ANONYMOUS flags for regions
|
||||
* that are marked REGION_PRIVATE. This means that we normally aren't
|
||||
* holding any system resources when we get here, in which case we can
|
||||
* delete the backing file. This results in a short race, from the
|
||||
* __db_open() call above to here.
|
||||
*
|
||||
* If, for some reason, we are holding system resources when we get
|
||||
* here, we don't have any choice -- we can't delete the backing file
|
||||
* because we may need it to detach from the resources. Set the
|
||||
* REGION_LASTDETACH flag, so that we do all necessary cleanup when
|
||||
* the application closes the region.
|
||||
*/
|
||||
if (F_ISSET(infop, REGION_PRIVATE) && !F_ISSET(infop, REGION_MALLOC))
|
||||
if (F_ISSET(infop, REGION_HOLDINGSYS))
|
||||
F_SET(infop, REGION_LASTDETACH);
|
||||
else {
|
||||
F_SET(infop, REGION_REMOVED);
|
||||
F_CLR(infop, REGION_CANGROW);
|
||||
|
||||
(void)__db_close(infop->fd);
|
||||
(void)__db_unlink(infop->name);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_rdetach --
|
||||
* De-attach from a shared memory region.
|
||||
*
|
||||
* PUBLIC: int __db_rdetach __P((REGINFO *));
|
||||
*/
|
||||
int
|
||||
__db_rdetach(infop)
|
||||
REGINFO *infop;
|
||||
{
|
||||
RLAYOUT *rlp;
|
||||
int detach, ret, t_ret;
|
||||
|
||||
ret = 0;
|
||||
|
||||
/*
|
||||
* If the region was removed when it was created, no further action
|
||||
* is required.
|
||||
*/
|
||||
if (F_ISSET(infop, REGION_REMOVED))
|
||||
goto done;
|
||||
/*
|
||||
* If the region was created in memory returned by malloc, the only
|
||||
* action required is freeing the memory.
|
||||
*/
|
||||
if (F_ISSET(infop, REGION_MALLOC)) {
|
||||
__db_free(infop->addr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Otherwise, attach to the region and optionally delete it. */
|
||||
rlp = infop->addr;
|
||||
|
||||
/* Get the lock. */
|
||||
(void)__db_mutex_lock(&rlp->lock, infop->fd);
|
||||
|
||||
/* Decrement the reference count. */
|
||||
if (rlp->refcnt == 0)
|
||||
__db_err(infop->dbenv,
|
||||
"region rdetach: reference count went to zero!");
|
||||
else
|
||||
--rlp->refcnt;
|
||||
|
||||
/*
|
||||
* If we're going to remove the region, clear the valid flag so
|
||||
* that any region join that's blocked waiting for us will know
|
||||
* what happened.
|
||||
*/
|
||||
detach = 0;
|
||||
if (F_ISSET(infop, REGION_LASTDETACH))
|
||||
if (rlp->refcnt == 0) {
|
||||
detach = 1;
|
||||
rlp->valid = 0;
|
||||
} else
|
||||
ret = EBUSY;
|
||||
|
||||
/* Release the lock. */
|
||||
(void)__db_mutex_unlock(&rlp->lock, infop->fd);
|
||||
|
||||
/* Close the backing file descriptor. */
|
||||
(void)__db_close(infop->fd);
|
||||
infop->fd = -1;
|
||||
|
||||
/* Discard our mapping of the region. */
|
||||
if ((t_ret = __db_unmapregion(infop)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/* Discard the region itself. */
|
||||
if (detach) {
|
||||
if ((t_ret =
|
||||
__db_unlinkregion(infop->name, infop) != 0) && ret == 0)
|
||||
ret = t_ret;
|
||||
if ((t_ret = __db_unlink(infop->name) != 0) && ret == 0)
|
||||
ret = t_ret;
|
||||
}
|
||||
|
||||
done: /* Discard the name. */
|
||||
if (infop->name != NULL) {
|
||||
FREES(infop->name);
|
||||
infop->name = NULL;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_runlink --
|
||||
* Remove a region.
|
||||
*
|
||||
* PUBLIC: int __db_runlink __P((REGINFO *, int));
|
||||
*/
|
||||
int
|
||||
__db_runlink(infop, force)
|
||||
REGINFO *infop;
|
||||
int force;
|
||||
{
|
||||
RLAYOUT rl, *rlp;
|
||||
size_t size;
|
||||
ssize_t nr;
|
||||
u_int32_t mbytes, bytes;
|
||||
int fd, ret, t_ret;
|
||||
char *name;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* We assume that we've created a new REGINFO structure for this
|
||||
* call, not used one that was already initialized. Regardless,
|
||||
* if anyone is planning to use it after we're done, they're going
|
||||
* to be sorely disappointed.
|
||||
*
|
||||
* If force isn't set, we attach to the region, set a flag to delete
|
||||
* the region on last close, and let the region delete code do the
|
||||
* work.
|
||||
*/
|
||||
if (!force) {
|
||||
if ((ret = __db_rattach(infop)) != 0)
|
||||
return (ret);
|
||||
|
||||
rlp = (RLAYOUT *)infop->addr;
|
||||
(void)__db_mutex_unlock(&rlp->lock, infop->fd);
|
||||
|
||||
F_SET(infop, REGION_LASTDETACH);
|
||||
|
||||
return (__db_rdetach(infop));
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, we don't want to attach to the region. We may have been
|
||||
* called to clean up if a process died leaving a region locked and/or
|
||||
* corrupted, which could cause the attach to hang.
|
||||
*/
|
||||
if ((ret = __db_appname(infop->dbenv, infop->appname,
|
||||
infop->path, infop->file, infop->dbflags, NULL, &name)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* An underlying file is created for all regions other than private
|
||||
* (REGION_PRIVATE) ones, regardless of whether or not it's used to
|
||||
* back the region. If that file doesn't exist, we're done.
|
||||
*/
|
||||
if (__db_exists(name, NULL) != 0) {
|
||||
FREES(name);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* See the comments in __db_rattach -- figure out if this is a regular
|
||||
* file backing a region or if it's a regular file with information
|
||||
* about a region.
|
||||
*/
|
||||
if ((ret = __db_open(name, DB_RDONLY, DB_RDONLY, 0, &fd)) != 0)
|
||||
goto errmsg;
|
||||
if ((ret = __db_ioinfo(name, fd, &mbytes, &bytes, NULL)) != 0)
|
||||
goto errmsg;
|
||||
size = mbytes * MEGABYTE + bytes;
|
||||
|
||||
if (size <= sizeof(RLAYOUT)) {
|
||||
if ((ret = __db_read(fd, &rl, sizeof(rl), &nr)) != 0)
|
||||
goto errmsg;
|
||||
if (rl.valid != DB_REGIONMAGIC) {
|
||||
__db_err(infop->dbenv,
|
||||
"%s: illegal region magic number", name);
|
||||
ret = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Set the size, memory id and characteristics. */
|
||||
infop->size = rl.size;
|
||||
infop->segid = rl.segid;
|
||||
if (F_ISSET(&rl, REGION_ANONYMOUS))
|
||||
F_SET(infop, REGION_ANONYMOUS);
|
||||
} else {
|
||||
infop->size = size;
|
||||
infop->segid = INVALID_SEGID;
|
||||
}
|
||||
|
||||
/* Remove the underlying region. */
|
||||
ret = __db_unlinkregion(name, infop);
|
||||
|
||||
/*
|
||||
* Unlink the backing file. Close the open file descriptor first,
|
||||
* because some architectures (e.g., Win32) won't unlink a file if
|
||||
* open file descriptors remain.
|
||||
*/
|
||||
(void)__db_close(fd);
|
||||
if ((t_ret = __db_unlink(name)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
if (0) {
|
||||
errmsg: __db_err(infop->dbenv, "%s: %s", name, strerror(ret));
|
||||
err: (void)__db_close(fd);
|
||||
}
|
||||
|
||||
FREES(name);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_rgrow --
|
||||
* Extend a region.
|
||||
*
|
||||
* PUBLIC: int __db_rgrow __P((REGINFO *, size_t));
|
||||
*/
|
||||
int
|
||||
__db_rgrow(infop, new_size)
|
||||
REGINFO *infop;
|
||||
size_t new_size;
|
||||
{
|
||||
RLAYOUT *rlp;
|
||||
size_t increment;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* This routine MUST be called with the region already locked.
|
||||
*/
|
||||
|
||||
/* The underlying routines have flagged if this region can grow. */
|
||||
if (!F_ISSET(infop, REGION_CANGROW))
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* Round off the requested size to the next page boundary, and
|
||||
* determine the additional space required.
|
||||
*/
|
||||
rlp = (RLAYOUT *)infop->addr;
|
||||
DB_ROUNDOFF(new_size);
|
||||
increment = new_size - rlp->size;
|
||||
|
||||
if ((ret = __db_growregion(infop, increment)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Update the on-disk region size. */
|
||||
rlp->size = new_size;
|
||||
|
||||
/* Detach from and reattach to the region. */
|
||||
return (__db_rreattach(infop, new_size));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_growregion --
|
||||
* Grow a shared memory region.
|
||||
*/
|
||||
static int
|
||||
__db_growregion(infop, increment)
|
||||
REGINFO *infop;
|
||||
size_t increment;
|
||||
{
|
||||
db_pgno_t pages;
|
||||
size_t i;
|
||||
ssize_t nr, nw;
|
||||
u_int32_t relative;
|
||||
int ret;
|
||||
char buf[DB_VMPAGESIZE];
|
||||
|
||||
/* Seek to the end of the region. */
|
||||
if ((ret = __db_seek(infop->fd, 0, 0, 0, 0, SEEK_END)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Write nuls to the new bytes. */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
/*
|
||||
* Some systems require that all of the bytes of the region be
|
||||
* written before it can be mapped and accessed randomly, and
|
||||
* other systems don't zero out the pages.
|
||||
*/
|
||||
if (__db_mapinit())
|
||||
/* Extend the region by writing each new page. */
|
||||
for (i = 0; i < increment; i += DB_VMPAGESIZE) {
|
||||
if ((ret =
|
||||
__db_write(infop->fd, buf, sizeof(buf), &nw)) != 0)
|
||||
goto err;
|
||||
if (nw != sizeof(buf))
|
||||
goto eio;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Extend the region by writing the last page. If the region
|
||||
* is >4Gb, increment may be larger than the maximum possible
|
||||
* seek "relative" argument, as it's an unsigned 32-bit value.
|
||||
* Break the offset into pages of 1MB each so that we don't
|
||||
* overflow (2^20 + 2^32 is bigger than any memory I expect
|
||||
* to see for awhile).
|
||||
*/
|
||||
pages = (increment - DB_VMPAGESIZE) / MEGABYTE;
|
||||
relative = (increment - DB_VMPAGESIZE) % MEGABYTE;
|
||||
if ((ret = __db_seek(infop->fd,
|
||||
MEGABYTE, pages, relative, 0, SEEK_CUR)) != 0)
|
||||
goto err;
|
||||
if ((ret = __db_write(infop->fd, buf, sizeof(buf), &nw)) != 0)
|
||||
goto err;
|
||||
if (nw != sizeof(buf))
|
||||
goto eio;
|
||||
|
||||
/*
|
||||
* It's sometimes significantly faster to page-fault in all
|
||||
* of the region's pages before we run the application, as
|
||||
* we can see fairly nasty side-effects when we page-fault
|
||||
* while holding various locks, i.e., the lock takes a long
|
||||
* time, and other threads convoy behind the lock holder.
|
||||
*/
|
||||
if (DB_GLOBAL(db_region_init)) {
|
||||
pages = increment / MEGABYTE;
|
||||
relative = increment % MEGABYTE;
|
||||
if ((ret = __db_seek(infop->fd,
|
||||
MEGABYTE, pages, relative, 1, SEEK_END)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Read a byte from each page. */
|
||||
for (i = 0; i < increment; i += DB_VMPAGESIZE) {
|
||||
if ((ret =
|
||||
__db_read(infop->fd, buf, 1, &nr)) != 0)
|
||||
goto err;
|
||||
if (nr != 1)
|
||||
goto eio;
|
||||
if ((ret = __db_seek(infop->fd,
|
||||
0, 0, DB_VMPAGESIZE - 1, 0, SEEK_CUR)) != 0)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
|
||||
eio: ret = EIO;
|
||||
err: __db_err(infop->dbenv, "region grow: %s", strerror(ret));
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_rreattach --
|
||||
* Detach from and reattach to a region.
|
||||
*
|
||||
* PUBLIC: int __db_rreattach __P((REGINFO *, size_t));
|
||||
*/
|
||||
int
|
||||
__db_rreattach(infop, new_size)
|
||||
REGINFO *infop;
|
||||
size_t new_size;
|
||||
{
|
||||
int ret;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (infop->name == NULL) {
|
||||
__db_err(infop->dbenv, "__db_rreattach: name was NULL");
|
||||
return (EINVAL);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* If we're growing an already mapped region, we have to unmap it
|
||||
* and get it back. We have it locked, so nobody else can get in,
|
||||
* which makes it fairly straight-forward to do, as everybody else
|
||||
* is going to block while we do the unmap/remap. NB: if we fail
|
||||
* to get it back, the pooch is genuinely screwed, because we can
|
||||
* never release the lock we're holding.
|
||||
*
|
||||
* Detach from the region. We have to do this first so architectures
|
||||
* that don't permit a file to be mapped into different places in the
|
||||
* address space simultaneously, e.g., HP's PaRisc, will work.
|
||||
*/
|
||||
if ((ret = __db_unmapregion(infop)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Update the caller's REGINFO size to the new map size. */
|
||||
infop->size = new_size;
|
||||
|
||||
/* Attach to the region. */
|
||||
ret = __db_mapregion(infop->name, infop);
|
||||
|
||||
return (ret);
|
||||
}
|
|
@ -1,301 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_salloc.c 10.13 (Sleepycat) 5/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "shqueue.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
/*
|
||||
* Implement shared memory region allocation, using simple first-fit algorithm.
|
||||
* The model is that we take a "chunk" of shared memory store and begin carving
|
||||
* it up into areas, similarly to how malloc works. We do coalescing on free.
|
||||
*
|
||||
* The "len" field in the __data struct contains the length of the free region
|
||||
* (less the size_t bytes that holds the length). We use the address provided
|
||||
* by the caller to find this length, which allows us to free a chunk without
|
||||
* requiring that the caller pass in the length of the chunk they're freeing.
|
||||
*/
|
||||
SH_LIST_HEAD(__head);
|
||||
struct __data {
|
||||
size_t len;
|
||||
SH_LIST_ENTRY links;
|
||||
};
|
||||
|
||||
/*
|
||||
* __db_shalloc_init --
|
||||
* Initialize the area as one large chunk.
|
||||
*
|
||||
* PUBLIC: void __db_shalloc_init __P((void *, size_t));
|
||||
*/
|
||||
void
|
||||
__db_shalloc_init(area, size)
|
||||
void *area;
|
||||
size_t size;
|
||||
{
|
||||
struct __data *elp;
|
||||
struct __head *hp;
|
||||
|
||||
hp = area;
|
||||
SH_LIST_INIT(hp);
|
||||
|
||||
elp = (struct __data *)(hp + 1);
|
||||
elp->len = size - sizeof(struct __head) - sizeof(elp->len);
|
||||
SH_LIST_INSERT_HEAD(hp, elp, links, __data);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_shalloc --
|
||||
* Allocate some space from the shared region.
|
||||
*
|
||||
* PUBLIC: int __db_shalloc __P((void *, size_t, size_t, void *));
|
||||
*/
|
||||
int
|
||||
__db_shalloc(p, len, align, retp)
|
||||
void *p, *retp;
|
||||
size_t len, align;
|
||||
{
|
||||
struct __data *elp;
|
||||
size_t *sp;
|
||||
void *rp;
|
||||
|
||||
/*
|
||||
* We never allocate less than the size of a struct __data, align
|
||||
* to less than a size_t boundary, or align to something that's not
|
||||
* a multiple of a size_t.
|
||||
*/
|
||||
if (len < sizeof(struct __data))
|
||||
len = sizeof(struct __data);
|
||||
align = align <= sizeof(size_t) ?
|
||||
sizeof(size_t) : ALIGN(align, sizeof(size_t));
|
||||
|
||||
/* Walk the list, looking for a slot. */
|
||||
for (elp = SH_LIST_FIRST((struct __head *)p, __data);
|
||||
elp != NULL;
|
||||
elp = SH_LIST_NEXT(elp, links, __data)) {
|
||||
/*
|
||||
* Calculate the value of the returned pointer if we were to
|
||||
* use this chunk.
|
||||
* + Find the end of the chunk.
|
||||
* + Subtract the memory the user wants.
|
||||
* + Find the closest previous correctly-aligned address.
|
||||
*/
|
||||
rp = (u_int8_t *)elp + sizeof(size_t) + elp->len;
|
||||
rp = (u_int8_t *)rp - len;
|
||||
rp = (u_int8_t *)((ALIGNTYPE)rp & ~(align - 1));
|
||||
|
||||
/*
|
||||
* Rp may now point before elp->links, in which case the chunk
|
||||
* was too small, and we have to try again.
|
||||
*/
|
||||
if ((u_int8_t *)rp < (u_int8_t *)&elp->links)
|
||||
continue;
|
||||
|
||||
*(void **)retp = rp;
|
||||
|
||||
#define SHALLOC_FRAGMENT 32
|
||||
/*
|
||||
* If there are at least SHALLOC_FRAGMENT additional bytes of
|
||||
* memory, divide the chunk into two chunks.
|
||||
*/
|
||||
if ((u_int8_t *)rp >=
|
||||
(u_int8_t *)&elp->links + SHALLOC_FRAGMENT) {
|
||||
sp = rp;
|
||||
*--sp = elp->len -
|
||||
((u_int8_t *)rp - (u_int8_t *)&elp->links);
|
||||
elp->len -= *sp + sizeof(size_t);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, we return the entire chunk, wasting some amount
|
||||
* of space to keep the list compact. However, because the
|
||||
* address we're returning to the user may not be the address
|
||||
* of the start of the region for alignment reasons, set the
|
||||
* size_t length fields back to the "real" length field to a
|
||||
* flag value, so that we can find the real length during free.
|
||||
*/
|
||||
#define ILLEGAL_SIZE 1
|
||||
SH_LIST_REMOVE(elp, links, __data);
|
||||
for (sp = rp; (u_int8_t *)--sp >= (u_int8_t *)&elp->links;)
|
||||
*sp = ILLEGAL_SIZE;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Nothing found large enough; need to grow the region. */
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_shalloc_free --
|
||||
* Free a shared memory allocation.
|
||||
*
|
||||
* PUBLIC: void __db_shalloc_free __P((void *, void *));
|
||||
*/
|
||||
void
|
||||
__db_shalloc_free(regionp, ptr)
|
||||
void *regionp, *ptr;
|
||||
{
|
||||
struct __data *elp, *lastp, *newp;
|
||||
struct __head *hp;
|
||||
size_t free_size, *sp;
|
||||
int merged;
|
||||
|
||||
/*
|
||||
* Step back over flagged length fields to find the beginning of
|
||||
* the object and its real size.
|
||||
*/
|
||||
for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp)
|
||||
;
|
||||
ptr = sp;
|
||||
|
||||
newp = (struct __data *)((u_int8_t *)ptr - sizeof(size_t));
|
||||
free_size = newp->len;
|
||||
|
||||
/* Trash the returned memory. */
|
||||
#ifdef DIAGNOSTIC
|
||||
memset(ptr, 0xff, free_size);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Walk the list, looking for where this entry goes.
|
||||
*
|
||||
* We keep the free list sorted by address so that coalescing is
|
||||
* trivial.
|
||||
*
|
||||
* XXX
|
||||
* Probably worth profiling this to see how expensive it is.
|
||||
*/
|
||||
hp = (struct __head *)regionp;
|
||||
for (elp = SH_LIST_FIRST(hp, __data), lastp = NULL;
|
||||
elp != NULL && (void *)elp < (void *)ptr;
|
||||
lastp = elp, elp = SH_LIST_NEXT(elp, links, __data))
|
||||
;
|
||||
|
||||
/*
|
||||
* Elp is either NULL (we reached the end of the list), or the slot
|
||||
* after the one that's being returned. Lastp is either NULL (we're
|
||||
* returning the first element of the list) or the element before the
|
||||
* one being returned.
|
||||
*
|
||||
* Check for coalescing with the next element.
|
||||
*/
|
||||
merged = 0;
|
||||
if ((u_int8_t *)ptr + free_size == (u_int8_t *)elp) {
|
||||
newp->len += elp->len + sizeof(size_t);
|
||||
SH_LIST_REMOVE(elp, links, __data);
|
||||
if (lastp != NULL)
|
||||
SH_LIST_INSERT_AFTER(lastp, newp, links, __data);
|
||||
else
|
||||
SH_LIST_INSERT_HEAD(hp, newp, links, __data);
|
||||
merged = 1;
|
||||
}
|
||||
|
||||
/* Check for coalescing with the previous element. */
|
||||
if (lastp != NULL && (u_int8_t *)lastp +
|
||||
lastp->len + sizeof(size_t) == (u_int8_t *)newp) {
|
||||
lastp->len += newp->len + sizeof(size_t);
|
||||
|
||||
/*
|
||||
* If we have already put the new element into the list take
|
||||
* it back off again because it's just been merged with the
|
||||
* previous element.
|
||||
*/
|
||||
if (merged)
|
||||
SH_LIST_REMOVE(newp, links, __data);
|
||||
merged = 1;
|
||||
}
|
||||
|
||||
if (!merged)
|
||||
if (lastp == NULL)
|
||||
SH_LIST_INSERT_HEAD(hp, newp, links, __data);
|
||||
else
|
||||
SH_LIST_INSERT_AFTER(lastp, newp, links, __data);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_shalloc_count --
|
||||
* Return the amount of memory on the free list.
|
||||
*
|
||||
* PUBLIC: size_t __db_shalloc_count __P((void *));
|
||||
*/
|
||||
size_t
|
||||
__db_shalloc_count(addr)
|
||||
void *addr;
|
||||
{
|
||||
struct __data *elp;
|
||||
size_t count;
|
||||
|
||||
count = 0;
|
||||
for (elp = SH_LIST_FIRST((struct __head *)addr, __data);
|
||||
elp != NULL;
|
||||
elp = SH_LIST_NEXT(elp, links, __data))
|
||||
count += elp->len;
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_shsizeof --
|
||||
* Return the size of a shalloc'd piece of memory.
|
||||
*
|
||||
* PUBLIC: size_t __db_shsizeof __P((void *));
|
||||
*/
|
||||
size_t
|
||||
__db_shsizeof(ptr)
|
||||
void *ptr;
|
||||
{
|
||||
struct __data *elp;
|
||||
size_t *sp;
|
||||
|
||||
/*
|
||||
* Step back over flagged length fields to find the beginning of
|
||||
* the object and its real size.
|
||||
*/
|
||||
for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp)
|
||||
;
|
||||
|
||||
elp = (struct __data *)((u_int8_t *)sp - sizeof(size_t));
|
||||
return (elp->len);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_shalloc_dump --
|
||||
*
|
||||
* PUBLIC: void __db_shalloc_dump __P((void *, FILE *));
|
||||
*/
|
||||
void
|
||||
__db_shalloc_dump(addr, fp)
|
||||
void *addr;
|
||||
FILE *fp;
|
||||
{
|
||||
struct __data *elp;
|
||||
|
||||
/* Make it easy to call from the debugger. */
|
||||
if (fp == NULL)
|
||||
fp = stderr;
|
||||
|
||||
fprintf(fp, "%s\nMemory free list\n", DB_LINE);
|
||||
|
||||
for (elp = SH_LIST_FIRST((struct __head *)addr, __data);
|
||||
elp != NULL;
|
||||
elp = SH_LIST_NEXT(elp, links, __data))
|
||||
fprintf(fp, "%#lx: %lu\t", (u_long)elp, (u_long)elp->len);
|
||||
fprintf(fp, "\n");
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_shash.c 10.9 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "shqueue.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
/*
|
||||
* Table of good hash values. Up to ~250,000 buckets, we use powers of 2.
|
||||
* After that, we slow the rate of increase by half. For each choice, we
|
||||
* then use a nearby prime number as the hash value.
|
||||
*
|
||||
* If a terabyte is the maximum cache we'll see, and we assume there are
|
||||
* 10 1K buckets on each hash chain, then 107374182 is the maximum number
|
||||
* of buckets we'll ever need.
|
||||
*/
|
||||
static const struct {
|
||||
u_int32_t power;
|
||||
u_int32_t prime;
|
||||
} list[] = {
|
||||
{ 64, 67}, /* 2^6 */
|
||||
{ 128, 131}, /* 2^7 */
|
||||
{ 256, 257}, /* 2^8 */
|
||||
{ 512, 521}, /* 2^9 */
|
||||
{ 1024, 1031}, /* 2^10 */
|
||||
{ 2048, 2053}, /* 2^11 */
|
||||
{ 4096, 4099}, /* 2^12 */
|
||||
{ 8192, 8191}, /* 2^13 */
|
||||
{ 16384, 16381}, /* 2^14 */
|
||||
{ 32768, 32771}, /* 2^15 */
|
||||
{ 65536, 65537}, /* 2^16 */
|
||||
{ 131072, 131071}, /* 2^17 */
|
||||
{ 262144, 262147}, /* 2^18 */
|
||||
{ 393216, 393209}, /* 2^18 + 2^18/2 */
|
||||
{ 524288, 524287}, /* 2^19 */
|
||||
{ 786432, 786431}, /* 2^19 + 2^19/2 */
|
||||
{ 1048576, 1048573}, /* 2^20 */
|
||||
{ 1572864, 1572869}, /* 2^20 + 2^20/2 */
|
||||
{ 2097152, 2097169}, /* 2^21 */
|
||||
{ 3145728, 3145721}, /* 2^21 + 2^21/2 */
|
||||
{ 4194304, 4194301}, /* 2^22 */
|
||||
{ 6291456, 6291449}, /* 2^22 + 2^22/2 */
|
||||
{ 8388608, 8388617}, /* 2^23 */
|
||||
{ 12582912, 12582917}, /* 2^23 + 2^23/2 */
|
||||
{ 16777216, 16777213}, /* 2^24 */
|
||||
{ 25165824, 25165813}, /* 2^24 + 2^24/2 */
|
||||
{ 33554432, 33554393}, /* 2^25 */
|
||||
{ 50331648, 50331653}, /* 2^25 + 2^25/2 */
|
||||
{ 67108864, 67108859}, /* 2^26 */
|
||||
{ 100663296, 100663291}, /* 2^26 + 2^26/2 */
|
||||
{ 134217728, 134217757}, /* 2^27 */
|
||||
{ 201326592, 201326611}, /* 2^27 + 2^27/2 */
|
||||
{ 268435456, 268435459}, /* 2^28 */
|
||||
{ 402653184, 402653189}, /* 2^28 + 2^28/2 */
|
||||
{ 536870912, 536870909}, /* 2^29 */
|
||||
{ 805306368, 805306357}, /* 2^29 + 2^29/2 */
|
||||
{1073741824, 1073741827}, /* 2^30 */
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* __db_tablesize --
|
||||
* Choose a size for the hash table.
|
||||
*
|
||||
* PUBLIC: int __db_tablesize __P((u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_tablesize(n_buckets)
|
||||
u_int32_t n_buckets;
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* We try to be clever about how big we make the hash tables. Use a
|
||||
* prime number close to the "suggested" number of elements that will
|
||||
* be in the hash table. Use 64 as the minimum hash table size.
|
||||
*
|
||||
* Ref: Sedgewick, Algorithms in C, "Hash Functions"
|
||||
*/
|
||||
if (n_buckets < 64)
|
||||
n_buckets = 64;
|
||||
|
||||
for (i = 0;; ++i) {
|
||||
if (list[i].power == 0) {
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
if (list[i].power >= n_buckets)
|
||||
break;
|
||||
}
|
||||
return (list[i].prime);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_hashinit --
|
||||
* Initialize a hash table that resides in shared memory.
|
||||
*
|
||||
* PUBLIC: void __db_hashinit __P((void *, u_int32_t));
|
||||
*/
|
||||
void
|
||||
__db_hashinit(begin, nelements)
|
||||
void *begin;
|
||||
u_int32_t nelements;
|
||||
{
|
||||
u_int32_t i;
|
||||
SH_TAILQ_HEAD(hash_head) *headp;
|
||||
|
||||
headp = (struct hash_head *)begin;
|
||||
|
||||
for (i = 0; i < nelements; i++, headp++)
|
||||
SH_TAILQ_INIT(headp);
|
||||
}
|
|
@ -1,256 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)cxx_app.cpp 10.14 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "db_cxx.h"
|
||||
#include "cxx_int.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <iostream.h>
|
||||
#include <fstream.h>
|
||||
#include <stdio.h> // needed for setErrorStream
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DbEnv //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static DbEnv *currentApp = 0;
|
||||
|
||||
ostream *DbEnv::error_stream_ = 0;
|
||||
|
||||
DbEnv::DbEnv(const char *homeDir, char *const *db_config, u_int32_t flags_arg)
|
||||
: error_model_(Exception)
|
||||
{
|
||||
DB_ENV *env = this;
|
||||
memset(env, 0, sizeof(DB_ENV));
|
||||
|
||||
int err;
|
||||
|
||||
if ((err = db_appinit(homeDir, db_config, env, flags_arg)) != 0) {
|
||||
DB_ERROR("DbEnv::DbEnv", err);
|
||||
}
|
||||
currentApp = this;
|
||||
}
|
||||
|
||||
DbEnv::DbEnv()
|
||||
: error_model_(Exception)
|
||||
{
|
||||
DB_ENV *env = this;
|
||||
memset(env, 0, sizeof(DB_ENV));
|
||||
}
|
||||
|
||||
DbEnv::~DbEnv()
|
||||
{
|
||||
if (currentApp == this)
|
||||
currentApp = 0;
|
||||
DB_ENV *env = this;
|
||||
|
||||
// having a zeroed environment is a signal that
|
||||
// appexit() has already been done.
|
||||
//
|
||||
DB_ENV zeroed;
|
||||
memset(&zeroed, 0, sizeof(DB_ENV));
|
||||
if (memcmp(&zeroed, env, sizeof(DB_ENV)) != 0) {
|
||||
(void)appexit(); // ignore error return
|
||||
}
|
||||
}
|
||||
|
||||
int DbEnv::appinit(const char *homeDir, char *const *db_config, u_int32_t flags_arg)
|
||||
{
|
||||
DB_ENV *env = this;
|
||||
|
||||
int err;
|
||||
|
||||
if ((err = db_appinit(homeDir, db_config, env, flags_arg)) != 0) {
|
||||
DB_ERROR("DbEnv::appinit", err);
|
||||
}
|
||||
currentApp = this;
|
||||
return err;
|
||||
}
|
||||
|
||||
int DbEnv::appexit()
|
||||
{
|
||||
DB_ENV *env = this;
|
||||
|
||||
int err;
|
||||
|
||||
if ((err = db_appexit(env)) != 0) {
|
||||
DB_ERROR("DbEnv::appexit", err);
|
||||
}
|
||||
memset(env, 0, sizeof(DB_ENV));
|
||||
currentApp = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
void DbEnv::set_error_model(ErrorModel model)
|
||||
{
|
||||
error_model_ = model;
|
||||
}
|
||||
|
||||
int DbEnv::runtime_error(const char *caller, int err, int in_destructor)
|
||||
{
|
||||
int throwit = (!currentApp ||
|
||||
(currentApp && currentApp->error_model_ == Exception));
|
||||
|
||||
if (throwit && !in_destructor) {
|
||||
throw DbException(caller, err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// Note: This actually behaves a bit like a static function,
|
||||
// since DB_ENV.db_errcall has no information about which
|
||||
// db_env triggered the call. A user that has multiple DB_ENVs
|
||||
// will simply not be able to have different streams for each one.
|
||||
//
|
||||
void DbEnv::set_error_stream(class ostream *stream)
|
||||
{
|
||||
error_stream_ = stream;
|
||||
|
||||
db_errcall = stream_error_function;
|
||||
}
|
||||
|
||||
ostream *DbEnv::get_error_stream() const
|
||||
{
|
||||
return error_stream_;
|
||||
}
|
||||
|
||||
void DbEnv::stream_error_function(const char *prefix, char *message)
|
||||
{
|
||||
if (error_stream_) {
|
||||
if (prefix) {
|
||||
(*error_stream_) << prefix << ": ";
|
||||
}
|
||||
if (message) {
|
||||
(*error_stream_) << message;
|
||||
}
|
||||
(*error_stream_) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
DB_RW_ACCESS(DbEnv, int, lorder, db_lorder)
|
||||
DB_RW_ACCESS(DbEnv, DbEnv::db_errcall_fcn, errcall, db_errcall)
|
||||
DB_RW_ACCESS(DbEnv, FILE *, errfile, db_errfile)
|
||||
DB_RW_ACCESS(DbEnv, const char *, errpfx, db_errpfx)
|
||||
DB_RW_ACCESS(DbEnv, int, verbose, db_verbose)
|
||||
DB_RW_ACCESS(DbEnv, char *, home, db_home)
|
||||
DB_RW_ACCESS(DbEnv, char *, log_dir, db_log_dir)
|
||||
DB_RW_ACCESS(DbEnv, char *, tmp_dir, db_tmp_dir)
|
||||
DB_RW_ACCESS(DbEnv, char **, data_dir, db_data_dir)
|
||||
DB_RW_ACCESS(DbEnv, int, data_cnt, data_cnt)
|
||||
DB_RW_ACCESS(DbEnv, int, data_next, data_next)
|
||||
DB_RW_ACCESS(DbEnv, u_int8_t *, lk_conflicts, lk_conflicts)
|
||||
DB_RW_ACCESS(DbEnv, int, lk_modes, lk_modes)
|
||||
DB_RW_ACCESS(DbEnv, unsigned int, lk_max, lk_max)
|
||||
DB_RW_ACCESS(DbEnv, u_int32_t, lk_detect, lk_detect)
|
||||
DB_RW_ACCESS(DbEnv, u_int32_t, lg_max, lg_max)
|
||||
DB_RW_ACCESS(DbEnv, size_t, mp_mmapsize, mp_mmapsize)
|
||||
DB_RW_ACCESS(DbEnv, size_t, mp_size, mp_size)
|
||||
DB_RW_ACCESS(DbEnv, unsigned int, tx_max, tx_max)
|
||||
DB_RW_ACCESS(DbEnv, DbEnv::tx_recover_fcn, tx_recover, tx_recover)
|
||||
DB_RW_ACCESS(DbEnv, u_int32_t, flags, flags)
|
||||
|
||||
// These access methods require construction of
|
||||
// wrapper options DB_FOO* to DbFoo* .
|
||||
//
|
||||
|
||||
DbLockTab *DbEnv::get_lk_info() const
|
||||
{
|
||||
if (!lk_info)
|
||||
return 0;
|
||||
DbLockTab *result = new DbLockTab();
|
||||
result->imp_ = wrap(lk_info);
|
||||
return result;
|
||||
}
|
||||
|
||||
DbLog *DbEnv::get_lg_info() const
|
||||
{
|
||||
if (!lg_info)
|
||||
return 0;
|
||||
DbLog *result = new DbLog();
|
||||
result->imp_ = wrap(lg_info);
|
||||
return result;
|
||||
}
|
||||
|
||||
DbMpool *DbEnv::get_mp_info() const
|
||||
{
|
||||
if (!mp_info)
|
||||
return 0;
|
||||
DbMpool *result = new DbMpool();
|
||||
result->imp_ = wrap(mp_info);
|
||||
return result;
|
||||
}
|
||||
|
||||
DbTxnMgr *DbEnv::get_tx_info() const
|
||||
{
|
||||
if (!tx_info)
|
||||
return 0;
|
||||
DbTxnMgr *result = new DbTxnMgr();
|
||||
result->imp_ = wrap(tx_info);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DbInfo //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Note: in theory, the db_home and db_*_dir fields will always be zero
|
||||
// when managed by DbInfo. That's because they are set by
|
||||
// db_appinit, not by the user, and we make a copy of the db_env used by
|
||||
// the application.
|
||||
//
|
||||
|
||||
DbInfo::DbInfo()
|
||||
{
|
||||
DB_INFO *info = this;
|
||||
memset(info, 0, sizeof(DB_INFO));
|
||||
}
|
||||
|
||||
DbInfo::~DbInfo()
|
||||
{
|
||||
}
|
||||
|
||||
DbInfo::DbInfo(const DbInfo &that)
|
||||
{
|
||||
DB_INFO *to = this;
|
||||
const DB_INFO *from = &that;
|
||||
memcpy(to, from, sizeof(DB_INFO));
|
||||
}
|
||||
|
||||
DbInfo &DbInfo::operator = (const DbInfo &that)
|
||||
{
|
||||
DB_INFO *to = this;
|
||||
const DB_INFO *from = &that;
|
||||
memcpy(to, from, sizeof(DB_INFO));
|
||||
return *this;
|
||||
}
|
||||
|
||||
DB_RW_ACCESS(DbInfo, int, lorder, db_lorder)
|
||||
DB_RW_ACCESS(DbInfo, size_t, cachesize, db_cachesize)
|
||||
DB_RW_ACCESS(DbInfo, size_t, pagesize, db_pagesize)
|
||||
DB_RW_ACCESS(DbInfo, DbInfo::db_malloc_fcn, malloc, db_malloc)
|
||||
DB_RW_ACCESS(DbInfo, int, bt_maxkey, bt_maxkey)
|
||||
DB_RW_ACCESS(DbInfo, int, bt_minkey, bt_minkey)
|
||||
DB_RW_ACCESS(DbInfo, DbInfo::bt_compare_fcn, bt_compare, bt_compare)
|
||||
DB_RW_ACCESS(DbInfo, DbInfo::bt_prefix_fcn, bt_prefix, bt_prefix)
|
||||
DB_RW_ACCESS(DbInfo, unsigned int, h_ffactor, h_ffactor)
|
||||
DB_RW_ACCESS(DbInfo, unsigned int, h_nelem, h_nelem)
|
||||
DB_RW_ACCESS(DbInfo, DbInfo::h_hash_fcn, h_hash, h_hash)
|
||||
DB_RW_ACCESS(DbInfo, int, re_pad, re_pad)
|
||||
DB_RW_ACCESS(DbInfo, int, re_delim, re_delim)
|
||||
DB_RW_ACCESS(DbInfo, u_int32_t, re_len, re_len)
|
||||
DB_RW_ACCESS(DbInfo, char *, re_source, re_source)
|
||||
DB_RW_ACCESS(DbInfo, u_int32_t, flags, flags)
|
|
@ -1,126 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)cxx_except.cpp 10.6 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "db_cxx.h"
|
||||
#include "cxx_int.h"
|
||||
#include <string.h>
|
||||
|
||||
// tmpString is used to create strings on the stack
|
||||
//
|
||||
class tmpString
|
||||
{
|
||||
public:
|
||||
tmpString(const char *str1,
|
||||
const char *str2 = 0,
|
||||
const char *str3 = 0,
|
||||
const char *str4 = 0,
|
||||
const char *str5 = 0)
|
||||
{
|
||||
int len = strlen(str1);
|
||||
if (str2)
|
||||
len += strlen(str2);
|
||||
if (str3)
|
||||
len += strlen(str3);
|
||||
if (str4)
|
||||
len += strlen(str4);
|
||||
if (str5)
|
||||
len += strlen(str5);
|
||||
|
||||
s_ = new char[len+1];
|
||||
|
||||
strcpy(s_, str1);
|
||||
if (str2)
|
||||
strcat(s_, str2);
|
||||
if (str3)
|
||||
strcat(s_, str3);
|
||||
if (str4)
|
||||
strcat(s_, str4);
|
||||
if (str5)
|
||||
strcat(s_, str5);
|
||||
}
|
||||
~tmpString() { delete [] s_; }
|
||||
operator const char *() { return s_; }
|
||||
|
||||
private:
|
||||
char *s_;
|
||||
};
|
||||
|
||||
// Note: would not be needed if we can inherit from exception
|
||||
// It does not appear to be possible to inherit from exception
|
||||
// with the current Microsoft library (VC5.0).
|
||||
//
|
||||
static char *dupString(const char *s)
|
||||
{
|
||||
char *r = new char[strlen(s)+1];
|
||||
strcpy(r, s);
|
||||
return r;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DbException //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbException::~DbException()
|
||||
{
|
||||
if (what_)
|
||||
delete [] what_;
|
||||
}
|
||||
|
||||
DbException::DbException(int err)
|
||||
: err_(err)
|
||||
{
|
||||
what_ = dupString(strerror(err));
|
||||
}
|
||||
|
||||
DbException::DbException(const char *description)
|
||||
: err_(0)
|
||||
{
|
||||
what_ = dupString(tmpString(description));
|
||||
}
|
||||
|
||||
DbException::DbException(const char *prefix, int err)
|
||||
: err_(err)
|
||||
{
|
||||
what_ = dupString(tmpString(prefix, ": ", strerror(err)));
|
||||
}
|
||||
|
||||
DbException::DbException(const char *prefix1, const char *prefix2, int err)
|
||||
: err_(err)
|
||||
{
|
||||
what_ = dupString(tmpString(prefix1, ": ", prefix2, ": ", strerror(err)));
|
||||
}
|
||||
|
||||
DbException::DbException(const DbException &that)
|
||||
: err_(that.err_)
|
||||
{
|
||||
what_ = dupString(that.what_);
|
||||
}
|
||||
|
||||
DbException &DbException::operator = (const DbException &that)
|
||||
{
|
||||
err_ = that.err_;
|
||||
what_ = dupString(that.what_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const int DbException::get_errno()
|
||||
{
|
||||
return err_;
|
||||
}
|
||||
|
||||
const char *DbException::what() const
|
||||
{
|
||||
return what_;
|
||||
}
|
|
@ -1,201 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)cxx_lock.cpp 10.7 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "db_cxx.h"
|
||||
#include "cxx_int.h"
|
||||
#include <errno.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DbLockTab //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbLockTab::DbLockTab()
|
||||
: imp_(0)
|
||||
{
|
||||
}
|
||||
|
||||
DbLockTab::~DbLockTab()
|
||||
{
|
||||
}
|
||||
|
||||
int DbLockTab::close()
|
||||
{
|
||||
DB_LOCKTAB *locktab = unwrap(this);
|
||||
int err;
|
||||
|
||||
if (!locktab) {
|
||||
return EINVAL; // handle never assigned
|
||||
}
|
||||
|
||||
if ((err = lock_close(locktab)) != 0) {
|
||||
DB_ERROR("DbLockTab::close", err);
|
||||
return err;
|
||||
}
|
||||
imp_ = 0; // extra safety
|
||||
|
||||
// This may seem weird, but is legal as long as we don't access
|
||||
// any data before returning.
|
||||
//
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbLockTab::detect(u_int32_t flags, int atype)
|
||||
{
|
||||
DB_LOCKTAB *locktab = unwrap(this);
|
||||
|
||||
if (!locktab) {
|
||||
return EINVAL; // handle never assigned
|
||||
}
|
||||
|
||||
int err = 0;
|
||||
if ((err = lock_detect(locktab, flags, atype)) != 0) {
|
||||
DB_ERROR("DbLockTab::detect", err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int DbLockTab::get(u_int32_t locker, u_int32_t flags, const Dbt *obj,
|
||||
db_lockmode_t lock_mode, DbLock *lock)
|
||||
{
|
||||
DB_LOCKTAB *locktab = unwrap(this);
|
||||
|
||||
if (!locktab) {
|
||||
return EINVAL; // handle never assigned
|
||||
}
|
||||
|
||||
int err = 0;
|
||||
if ((err = lock_get(locktab, locker, flags, obj,
|
||||
lock_mode, &lock->lock_)) != 0) {
|
||||
DB_ERROR("DbLockTab::get", err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int DbLockTab::id(u_int32_t *idp)
|
||||
{
|
||||
DB_LOCKTAB *locktab = unwrap(this);
|
||||
|
||||
if (!locktab) {
|
||||
return EINVAL; // handle never assigned
|
||||
}
|
||||
|
||||
int err;
|
||||
if ((err = lock_id(locktab, idp)) != 0) {
|
||||
DB_ERROR("DbLockTab::id", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int DbLockTab::vec(u_int32_t locker, u_int32_t flags,
|
||||
DB_LOCKREQ list[],
|
||||
int nlist, DB_LOCKREQ **elist_returned)
|
||||
{
|
||||
DB_LOCKTAB *locktab = unwrap(this);
|
||||
|
||||
if (!locktab) {
|
||||
return EINVAL; // handle never assigned
|
||||
}
|
||||
|
||||
int err;
|
||||
if ((err = lock_vec(locktab, locker, flags, list,
|
||||
nlist, elist_returned)) != 0) {
|
||||
DB_ERROR("DbLockTab::vec", err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// static method
|
||||
int DbLockTab::open(const char *dir, u_int32_t flags, int mode,
|
||||
DbEnv *dbenv, DbLockTab **regionp)
|
||||
{
|
||||
*regionp = 0;
|
||||
DB_LOCKTAB *result = 0;
|
||||
int err;
|
||||
if ((err = lock_open(dir, flags, mode, dbenv, &result)) != 0) {
|
||||
DB_ERROR("DbLockTab::open", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
*regionp = new DbLockTab();
|
||||
(*regionp)->imp_ = wrap(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static method
|
||||
int DbLockTab::unlink(const char *dir, int force, DbEnv *dbenv)
|
||||
{
|
||||
int err;
|
||||
if ((err = lock_unlink(dir, force, dbenv)) != 0) {
|
||||
DB_ERROR("DbLockTab::unlink", err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DbLock //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbLock::DbLock(unsigned int value)
|
||||
: lock_(value)
|
||||
{
|
||||
}
|
||||
|
||||
DbLock::DbLock()
|
||||
: lock_(0)
|
||||
{
|
||||
}
|
||||
|
||||
DbLock::DbLock(const DbLock &that)
|
||||
: lock_(that.lock_)
|
||||
{
|
||||
}
|
||||
|
||||
DbLock &DbLock::operator = (const DbLock &that)
|
||||
{
|
||||
lock_ = that.lock_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned int DbLock::get_lock_id()
|
||||
{
|
||||
return lock_;
|
||||
}
|
||||
|
||||
void DbLock::set_lock_id(unsigned int value)
|
||||
{
|
||||
lock_ = value;
|
||||
}
|
||||
|
||||
int DbLock::put(DbLockTab *locktab)
|
||||
{
|
||||
DB_LOCKTAB *db_locktab = unwrap(locktab);
|
||||
|
||||
if (!db_locktab) {
|
||||
return EINVAL; // handle never assigned
|
||||
}
|
||||
|
||||
int err;
|
||||
if ((err = lock_put(db_locktab, lock_)) != 0) {
|
||||
DB_ERROR("DbLock::put", err);
|
||||
}
|
||||
return err;
|
||||
}
|
|
@ -1,157 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)cxx_log.cpp 10.7 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "db_cxx.h"
|
||||
#include "cxx_int.h"
|
||||
#include <errno.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DbLog //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbLog::DbLog()
|
||||
: imp_(0)
|
||||
{
|
||||
}
|
||||
|
||||
DbLog::~DbLog()
|
||||
{
|
||||
}
|
||||
|
||||
int DbLog::archive(char **list[], u_int32_t flags, void *(*db_malloc)(size_t))
|
||||
{
|
||||
int err;
|
||||
DB_LOG *log = unwrap(this);
|
||||
if ((err = log_archive(log, list, flags, db_malloc)) != 0) {
|
||||
DB_ERROR("DbLog::archive", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbLog::close()
|
||||
{
|
||||
int err;
|
||||
DB_LOG *log = unwrap(this);
|
||||
if ((err = log_close(log)) != 0) {
|
||||
DB_ERROR("DbLog::close", err);
|
||||
return err;
|
||||
}
|
||||
imp_ = 0; // extra safety
|
||||
|
||||
// This may seem weird, but is legal as long as we don't access
|
||||
// any data before returning.
|
||||
//
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbLog::compare(const DbLsn *lsn0, const DbLsn *lsn1)
|
||||
{
|
||||
return log_compare(lsn0, lsn1);
|
||||
}
|
||||
|
||||
int DbLog::file(DbLsn *lsn, char *namep, int len)
|
||||
{
|
||||
int err;
|
||||
DB_LOG *log = unwrap(this);
|
||||
if ((err = log_file(log, lsn, namep, len)) != 0) {
|
||||
DB_ERROR("DbLog::file", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbLog::flush(const DbLsn *lsn)
|
||||
{
|
||||
int err;
|
||||
DB_LOG *log = unwrap(this);
|
||||
if ((err = log_flush(log, lsn)) != 0) {
|
||||
DB_ERROR("DbLog::flush", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbLog::get(DbLsn *lsn, Dbt *data, u_int32_t flags)
|
||||
{
|
||||
int err;
|
||||
DB_LOG *log = unwrap(this);
|
||||
if ((err = log_get(log, lsn, data, flags)) != 0) {
|
||||
DB_ERROR("DbLog::get", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbLog::put(DbLsn *lsn, const Dbt *data, u_int32_t flags)
|
||||
{
|
||||
int err = 0;
|
||||
DB_LOG *log = unwrap(this);
|
||||
if ((err = log_put(log, lsn, data, flags)) != 0) {
|
||||
DB_ERROR("DbLog::put", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbLog::db_register(Db *dbp, const char *name, DBTYPE type, u_int32_t *fidp)
|
||||
{
|
||||
int err = 0;
|
||||
DB_LOG *log = unwrap(this);
|
||||
if ((err = log_register(log, unwrap(dbp), name, type, fidp)) != 0) {
|
||||
DB_ERROR("DbLog::db_register", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbLog::db_unregister(u_int32_t fid)
|
||||
{
|
||||
int err;
|
||||
DB_LOG *log = unwrap(this);
|
||||
if ((err = log_unregister(log, fid)) != 0) {
|
||||
DB_ERROR("DbLog::db_unregister", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static method
|
||||
int DbLog::open(const char *dir, u_int32_t flags, int mode,
|
||||
DbEnv *dbenv, DbLog **regionp)
|
||||
{
|
||||
*regionp = 0;
|
||||
DB_LOG *result = 0;
|
||||
int err;
|
||||
if ((err = log_open(dir, flags, mode, dbenv, &result)) != 0) {
|
||||
DB_ERROR("DbLog::open", err);
|
||||
return err;
|
||||
}
|
||||
*regionp = new DbLog();
|
||||
(*regionp)->imp_ = wrap(result);
|
||||
return err;
|
||||
}
|
||||
|
||||
// static method
|
||||
int DbLog::unlink(const char *dir, int force, DbEnv *dbenv)
|
||||
{
|
||||
int err;
|
||||
if ((err = log_unlink(dir, force, dbenv)) != 0) {
|
||||
DB_ERROR("DbLog::unlink", err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
|
@ -1,243 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)cxx_mpool.cpp 10.9 (Sleepycat) 5/2/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "db_cxx.h"
|
||||
#include "cxx_int.h"
|
||||
#include <errno.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DbMpoolFile //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbMpoolFile::DbMpoolFile()
|
||||
: imp_(0)
|
||||
{
|
||||
}
|
||||
|
||||
DbMpoolFile::~DbMpoolFile()
|
||||
{
|
||||
}
|
||||
|
||||
int DbMpoolFile::open(DbMpool *mp, const char *file,
|
||||
u_int32_t flags, int mode, size_t pagesize,
|
||||
DB_MPOOL_FINFO *finfop, DbMpoolFile **result)
|
||||
{
|
||||
int err;
|
||||
|
||||
DB_MPOOLFILE *mpf;
|
||||
if ((err = memp_fopen(unwrap(mp), file, flags, mode, pagesize,
|
||||
finfop, &mpf)) != 0) {
|
||||
DB_ERROR("DbMpoolFile::open", err);
|
||||
return err;
|
||||
}
|
||||
*result = new DbMpoolFile();
|
||||
(*result)->imp_ = wrap(mpf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbMpoolFile::close()
|
||||
{
|
||||
DB_MPOOLFILE *mpf = unwrap(this);
|
||||
int err = 0;
|
||||
if (!mpf) {
|
||||
err = EINVAL;
|
||||
}
|
||||
else if ((err = memp_fclose(mpf)) != 0) {
|
||||
DB_ERROR("DbMpoolFile::close", err);
|
||||
return err;
|
||||
}
|
||||
imp_ = 0; // extra safety
|
||||
|
||||
// This may seem weird, but is legal as long as we don't access
|
||||
// any data before returning.
|
||||
//
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbMpoolFile::get(db_pgno_t *pgnoaddr, u_int32_t flags, void *pagep)
|
||||
{
|
||||
DB_MPOOLFILE *mpf = unwrap(this);
|
||||
int err = 0;
|
||||
if (!mpf) {
|
||||
err = EINVAL;
|
||||
}
|
||||
else if ((err = memp_fget(mpf, pgnoaddr, flags, pagep)) != 0) {
|
||||
DB_ERROR("DbMpoolFile::get", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int DbMpoolFile::put(void *pgaddr, u_int32_t flags)
|
||||
{
|
||||
DB_MPOOLFILE *mpf = unwrap(this);
|
||||
int err = 0;
|
||||
if (!mpf) {
|
||||
err = EINVAL;
|
||||
}
|
||||
else if ((err = memp_fput(mpf, pgaddr, flags)) != 0) {
|
||||
DB_ERROR("DbMpoolFile::put", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int DbMpoolFile::set(void *pgaddr, u_int32_t flags)
|
||||
{
|
||||
DB_MPOOLFILE *mpf = unwrap(this);
|
||||
int err = 0;
|
||||
if (!mpf) {
|
||||
err = EINVAL;
|
||||
}
|
||||
else if ((err = memp_fset(mpf, pgaddr, flags)) != 0) {
|
||||
DB_ERROR("DbMpoolFile::set", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int DbMpoolFile::sync()
|
||||
{
|
||||
DB_MPOOLFILE *mpf = unwrap(this);
|
||||
int err = 0;
|
||||
if (!mpf) {
|
||||
err = EINVAL;
|
||||
}
|
||||
else if ((err = memp_fsync(mpf)) != 0) {
|
||||
DB_ERROR("DbMpoolFile::sync", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DbMpool //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbMpool::DbMpool()
|
||||
: imp_(0)
|
||||
{
|
||||
}
|
||||
|
||||
DbMpool::~DbMpool()
|
||||
{
|
||||
}
|
||||
|
||||
int DbMpool::close()
|
||||
{
|
||||
DB_MPOOL *mpool = unwrap(this);
|
||||
int err;
|
||||
|
||||
if (!mpool) {
|
||||
return EINVAL; // already closed
|
||||
}
|
||||
|
||||
if ((err = memp_close(mpool)) != 0) {
|
||||
DB_ERROR("DbMpool::close", err);
|
||||
return err;
|
||||
}
|
||||
imp_ = 0; // extra safety
|
||||
|
||||
// This may seem weird, but is legal as long as we don't access
|
||||
// any data before returning.
|
||||
//
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbMpool::db_register(int ftype,
|
||||
int (*pgin)(db_pgno_t pgno, void *pgaddr, DBT *pgcookie),
|
||||
int (*pgout)(db_pgno_t pgno, void *pgaddr, DBT *pgcookie))
|
||||
{
|
||||
DB_MPOOL *mpool = unwrap(this);
|
||||
int err = 0;
|
||||
if (!mpool) {
|
||||
err = EINVAL;
|
||||
}
|
||||
else if ((err = memp_register(mpool, ftype, pgin, pgout)) != 0) {
|
||||
DB_ERROR("DbMpool::db_register", err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int DbMpool::stat(DB_MPOOL_STAT **gsp, DB_MPOOL_FSTAT ***fsp,
|
||||
void *(*alternate_malloc)(size_t))
|
||||
{
|
||||
DB_MPOOL *mpool = unwrap(this);
|
||||
int err = 0;
|
||||
if (!mpool) {
|
||||
err = EINVAL;
|
||||
}
|
||||
else if ((err = memp_stat(mpool, gsp, fsp, alternate_malloc)) != 0) {
|
||||
DB_ERROR("DbMpool::stat", err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int DbMpool::sync(DbLsn *sn)
|
||||
{
|
||||
DB_MPOOL *mpool = unwrap(this);
|
||||
int err = 0;
|
||||
if (!mpool) {
|
||||
err = EINVAL;
|
||||
}
|
||||
else if ((err = memp_sync(mpool, sn)) != 0) {
|
||||
DB_ERROR("DbMpool::sync", err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int DbMpool::trickle(int pct, int *nwrotep)
|
||||
{
|
||||
DB_MPOOL *mpool = unwrap(this);
|
||||
int err = 0;
|
||||
if (!mpool) {
|
||||
err = EINVAL;
|
||||
}
|
||||
else if ((err = memp_trickle(mpool, pct, nwrotep)) != 0) {
|
||||
DB_ERROR("DbMpool::trickle", err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
// static method
|
||||
int DbMpool::open(const char *dir, u_int32_t flags, int mode,
|
||||
DbEnv *dbenv, DbMpool **regionp)
|
||||
{
|
||||
*regionp = 0;
|
||||
DB_MPOOL *result = 0;
|
||||
int err;
|
||||
if ((err = memp_open(dir, flags, mode, dbenv, &result)) != 0) {
|
||||
DB_ERROR("DbMpool::open", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
*regionp = new DbMpool();
|
||||
(*regionp)->imp_ = wrap(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static method
|
||||
int DbMpool::unlink(const char *dir, int force, DbEnv *dbenv)
|
||||
{
|
||||
int err;
|
||||
if ((err = memp_unlink(dir, force, dbenv)) != 0) {
|
||||
DB_ERROR("DbMpool::unlink", err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
|
@ -1,310 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)cxx_table.cpp 10.11 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "db_cxx.h"
|
||||
#include "cxx_int.h"
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Db //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Db::Db()
|
||||
: imp_(0)
|
||||
{
|
||||
}
|
||||
|
||||
Db::~Db()
|
||||
{
|
||||
}
|
||||
|
||||
int Db::close(u_int32_t flags)
|
||||
{
|
||||
DB *db = unwrap(this);
|
||||
if (!db) {
|
||||
DB_ERROR("Db::close", EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
int err;
|
||||
if ((err = db->close(db, flags)) != 0) {
|
||||
DB_ERROR("Db::close", err);
|
||||
return err;
|
||||
}
|
||||
imp_ = 0; // extra safety
|
||||
|
||||
// This may seem weird, but is legal as long as we don't access
|
||||
// any data before returning.
|
||||
//
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Db::cursor(DbTxn *txnid, Dbc **cursorp)
|
||||
{
|
||||
DB *db = unwrap(this);
|
||||
int err;
|
||||
|
||||
if (!db) {
|
||||
DB_ERROR("Db::cursor", EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
DBC *dbc = 0;
|
||||
if ((err = db->cursor(db, unwrap(txnid), &dbc)) != 0) {
|
||||
DB_ERROR("Db::cursor", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
// The following cast implies that Dbc can be no larger than DBC
|
||||
*cursorp = (Dbc*)dbc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Db::del(DbTxn *txnid, Dbt *key, u_int32_t flags)
|
||||
{
|
||||
DB *db = unwrap(this);
|
||||
int err;
|
||||
|
||||
if (!db) {
|
||||
DB_ERROR("Db::del", EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
if ((err = db->del(db, unwrap(txnid), key, flags)) != 0) {
|
||||
DB_ERROR("Db::del", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Db::fd(int *fdp)
|
||||
{
|
||||
DB *db = unwrap(this);
|
||||
if (!db) {
|
||||
DB_ERROR("Db::fd", EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
int err;
|
||||
if ((err = db->fd(db, fdp)) != 0) {
|
||||
DB_ERROR("Db::fd", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Db::get(DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags)
|
||||
{
|
||||
|
||||
DB *db = unwrap(this);
|
||||
int err;
|
||||
|
||||
if (!db) {
|
||||
DB_ERROR("Db::get", EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
if ((err = db->get(db, unwrap(txnid), key, value, flags)) != 0) {
|
||||
// DB_NOTFOUND is a "normal" return, so should not be
|
||||
// thrown as an error
|
||||
//
|
||||
if (err != DB_NOTFOUND) {
|
||||
DB_ERROR("Db::get", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// static method
|
||||
int Db::open(const char *fname, DBTYPE type, u_int32_t flags,
|
||||
int mode, DbEnv *dbenv, DbInfo *info, Db **table_returned)
|
||||
{
|
||||
*table_returned = 0;
|
||||
DB *newtable;
|
||||
int err;
|
||||
if ((err = db_open(fname, type, flags, mode, dbenv,
|
||||
info, &newtable)) != 0) {
|
||||
DB_ERROR("Db::open", err);
|
||||
return err;
|
||||
}
|
||||
*table_returned = new Db();
|
||||
(*table_returned)->imp_ = wrap(newtable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Db::put(DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags)
|
||||
{
|
||||
DB *db = unwrap(this);
|
||||
int err;
|
||||
|
||||
if (!db) {
|
||||
DB_ERROR("Db::put", EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
if ((err = db->put(db, unwrap(txnid), key, value, flags)) != 0) {
|
||||
|
||||
// DB_KEYEXIST is a "normal" return, so should not be
|
||||
// thrown as an error
|
||||
//
|
||||
if (err != DB_KEYEXIST) {
|
||||
DB_ERROR("Db::put", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int Db::stat(void *sp, void *(*db_malloc)(size_t), u_int32_t flags)
|
||||
{
|
||||
DB *db = unwrap(this);
|
||||
if (!db) {
|
||||
DB_ERROR("Db::stat", EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
int err;
|
||||
if ((err = db->stat(db, sp, db_malloc, flags)) != 0) {
|
||||
DB_ERROR("Db::stat", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Db::sync(u_int32_t flags)
|
||||
{
|
||||
DB *db = unwrap(this);
|
||||
if (!db) {
|
||||
DB_ERROR("Db::sync", EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
int err;
|
||||
if ((err = db->sync(db, flags)) != 0) {
|
||||
DB_ERROR("Db::sync", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DBTYPE Db::get_type() const
|
||||
{
|
||||
const DB *db = unwrapConst(this);
|
||||
return db->type;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Dbc //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// It's private, and should never be called, but VC4.0 needs it resolved
|
||||
//
|
||||
Dbc::~Dbc()
|
||||
{
|
||||
}
|
||||
|
||||
int Dbc::close()
|
||||
{
|
||||
DBC *cursor = this;
|
||||
int err;
|
||||
|
||||
if ((err = cursor->c_close(cursor)) != 0) {
|
||||
DB_ERROR("Db::close", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Dbc::del(u_int32_t flags)
|
||||
{
|
||||
DBC *cursor = this;
|
||||
int err;
|
||||
|
||||
if ((err = cursor->c_del(cursor, flags)) != 0) {
|
||||
DB_ERROR("Db::del", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Dbc::get(Dbt* key, Dbt *data, u_int32_t flags)
|
||||
{
|
||||
DBC *cursor = this;
|
||||
int err;
|
||||
|
||||
if ((err = cursor->c_get(cursor, key, data, flags)) != 0) {
|
||||
if (err != DB_NOTFOUND) {
|
||||
DB_ERROR("Db::get", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int Dbc::put(Dbt* key, Dbt *data, u_int32_t flags)
|
||||
{
|
||||
DBC *cursor = this;
|
||||
int err;
|
||||
|
||||
if ((err = cursor->c_put(cursor, key, data, flags)) != 0) {
|
||||
DB_ERROR("Db::put", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Dbt //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Dbt::Dbt()
|
||||
{
|
||||
DBT *dbt = this;
|
||||
memset(dbt, 0, sizeof(DBT));
|
||||
}
|
||||
|
||||
Dbt::Dbt(void *data_arg, size_t size_arg)
|
||||
{
|
||||
DBT *dbt = this;
|
||||
memset(dbt, 0, sizeof(DBT));
|
||||
set_data(data_arg);
|
||||
set_size(size_arg);
|
||||
}
|
||||
|
||||
Dbt::~Dbt()
|
||||
{
|
||||
}
|
||||
|
||||
Dbt::Dbt(const Dbt &that)
|
||||
{
|
||||
const DBT *from = &that;
|
||||
DBT *to = this;
|
||||
memcpy(to, from, sizeof(DBT));
|
||||
}
|
||||
|
||||
Dbt &Dbt::operator = (const Dbt &that)
|
||||
{
|
||||
const DBT *from = &that;
|
||||
DBT *to = this;
|
||||
memcpy(to, from, sizeof(DBT));
|
||||
return *this;
|
||||
}
|
||||
|
||||
DB_RW_ACCESS(Dbt, void *, data, data)
|
||||
DB_RW_ACCESS(Dbt, u_int32_t, size, size)
|
||||
DB_RW_ACCESS(Dbt, u_int32_t, ulen, ulen)
|
||||
DB_RW_ACCESS(Dbt, u_int32_t, dlen, dlen)
|
||||
DB_RW_ACCESS(Dbt, u_int32_t, doff, doff)
|
||||
DB_RW_ACCESS(Dbt, u_int32_t, flags, flags)
|
|
@ -1,178 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)cxx_txn.cpp 10.8 (Sleepycat) 4/10/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "db_cxx.h"
|
||||
#include "cxx_int.h"
|
||||
#include <errno.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DbTxnMgr //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbTxnMgr::DbTxnMgr()
|
||||
: imp_(0)
|
||||
{
|
||||
}
|
||||
|
||||
DbTxnMgr::~DbTxnMgr()
|
||||
{
|
||||
}
|
||||
|
||||
int DbTxnMgr::begin(DbTxn *pid, DbTxn **tid)
|
||||
{
|
||||
int err;
|
||||
DB_TXNMGR *mgr = unwrap(this);
|
||||
DB_TXN *txn;
|
||||
|
||||
if ((err = txn_begin(mgr, unwrap(pid), &txn)) != 0) {
|
||||
DB_ERROR("DbTxn::begin", err);
|
||||
return err;
|
||||
}
|
||||
DbTxn *result = new DbTxn();
|
||||
result->imp_ = wrap(txn);
|
||||
*tid = result;
|
||||
return err;
|
||||
}
|
||||
|
||||
int DbTxnMgr::checkpoint(u_int32_t kbyte, u_int32_t min) const
|
||||
{
|
||||
int err;
|
||||
const DB_TXNMGR *mgr = unwrapConst(this);
|
||||
if ((err = txn_checkpoint(mgr, kbyte, min)) != 0) {
|
||||
DB_ERROR("DbTxnMgr::checkpoint", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbTxnMgr::close()
|
||||
{
|
||||
int err;
|
||||
DB_TXNMGR *mgr = unwrap(this);
|
||||
if ((err = txn_close(mgr)) != 0) {
|
||||
DB_ERROR("DbTxnMgr::close", err);
|
||||
return err;
|
||||
}
|
||||
imp_ = 0; // extra safety
|
||||
|
||||
// This may seem weird, but is legal as long as we don't access
|
||||
// any data before returning.
|
||||
//
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static method
|
||||
int DbTxnMgr::open(const char *dir, u_int32_t flags, int mode,
|
||||
DbEnv *dbenv, DbTxnMgr **regionp)
|
||||
{
|
||||
*regionp = 0;
|
||||
DB_TXNMGR *result = 0;
|
||||
int err;
|
||||
if ((err = txn_open(dir, flags, mode, dbenv, &result)) != 0) {
|
||||
DB_ERROR("DbTxnMgr::open", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
*regionp = new DbTxnMgr();
|
||||
(*regionp)->imp_ = wrap(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbTxnMgr::stat(DB_TXN_STAT **statp, void *(*db_malloc)(size_t))
|
||||
{
|
||||
int err;
|
||||
DB_TXNMGR *mgr = unwrap(this);
|
||||
if ((err = txn_stat(mgr, statp, db_malloc)) != 0) {
|
||||
DB_ERROR("DbTxnMgr::stat", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static method
|
||||
int DbTxnMgr::unlink(const char *dir, int force, DbEnv *dbenv)
|
||||
{
|
||||
int err;
|
||||
if ((err = txn_unlink(dir, force, dbenv)) != 0) {
|
||||
DB_ERROR("DbTxnMgr::unlink", err);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DbTxn //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbTxn::DbTxn()
|
||||
: imp_(0)
|
||||
{
|
||||
}
|
||||
|
||||
DbTxn::~DbTxn()
|
||||
{
|
||||
}
|
||||
|
||||
int DbTxn::abort()
|
||||
{
|
||||
int err;
|
||||
DB_TXN *txn = unwrap(this);
|
||||
if ((err = txn_abort(txn)) != 0) {
|
||||
DB_ERROR("DbTxn::abort", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
// This may seem weird, but is legal as long as we don't access
|
||||
// any data before returning.
|
||||
//
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DbTxn::commit()
|
||||
{
|
||||
int err;
|
||||
DB_TXN *txn = unwrap(this);
|
||||
if ((err = txn_commit(txn)) != 0) {
|
||||
DB_ERROR("DbTxn::commit", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
// This may seem weird, but is legal as long as we don't access
|
||||
// any data before returning.
|
||||
//
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
u_int32_t DbTxn::id()
|
||||
{
|
||||
DB_TXN *txn = unwrap(this);
|
||||
return txn_id(txn); // no error
|
||||
}
|
||||
|
||||
int DbTxn::prepare()
|
||||
{
|
||||
int err;
|
||||
DB_TXN *txn = unwrap(this);
|
||||
if ((err = txn_prepare(txn)) != 0) {
|
||||
DB_ERROR("DbTxn::prepare", err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
@(#)namemap.txt 10.1 (Sleepycat) 7/17/97
|
||||
|
||||
The bulk of DB provides for wrapper classes and appropriately named methods
|
||||
that call into DB. For the most part, there is a straightforward mapping of
|
||||
names. For the purposes of referencing documentation, this chart shows the
|
||||
underlying C structure name for each C++ class. In some cases, using the
|
||||
given C prefix with a C++ method name gives the underlying C function name.
|
||||
For example, DBMemPoolFile::close() is implemented by memp_fclose().
|
||||
|
||||
|
||||
C++ C C prefix
|
||||
|
||||
DBApp none
|
||||
DBAppOptions DB_ENV
|
||||
DBConfig none
|
||||
DBException none
|
||||
DBIterator DBC (cursor)
|
||||
DBLock DB_LOCK lock_
|
||||
DBLockRequest DB_LOCKREQ
|
||||
DBLockTable DB_LOCKTAB
|
||||
DBLog DB_LOG log_
|
||||
DBMemPool DB_MPOOL memp_
|
||||
DBMemPoolFile DB_MPOOLFILE memp_f
|
||||
DBMemPoolFileStat reserved
|
||||
DBMemPoolStat reserved
|
||||
DBOpenType DBTYPE
|
||||
DBOpenParams DB_INFO
|
||||
DBSequenceNumber DB_LSN
|
||||
DBTable DB
|
||||
DBThunk DBT
|
||||
DBTransaction DB_TXN txn_
|
||||
DBTransactionManager DB_TXNMGR txn_
|
||||
DBVersion none
|
||||
|
||||
|
||||
There are a few exceptions to the above, mostly to allow for
|
||||
natural constructors or to avoid conflicts with reserved words:
|
||||
|
||||
C++ name C name
|
||||
|
||||
DBLog::identify log_register
|
||||
DBLog::unidentify log_unregister
|
||||
DBTransaction::DBTransaction txn_begin
|
||||
DBTransactionManager::DBTransactionManager txn_open
|
||||
DBLockTable::DBLockTable lock_open
|
||||
DBLog::DBLog log_open
|
||||
DBMemPool::DBMemPool memp_open
|
||||
DBMemPoolFile::DBMemPoolFile memp_fopen
|
||||
DBApp::removeLockTableFile lock_unlink
|
||||
DBApp::removeMemPoolFile memp_unlink
|
||||
DBApp::removeLoggingFile log_unlink
|
||||
DBApp::removeTransactionManagerFile txn_unlink
|
||||
DBTable::remove (*del)
|
866
db/db/db.c
866
db/db/db.c
|
@ -1,866 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db.c 10.57 (Sleepycat) 5/7/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "shqueue.h"
|
||||
#include "db_page.h"
|
||||
#include "db_shash.h"
|
||||
#include "db_swap.h"
|
||||
#include "btree.h"
|
||||
#include "hash.h"
|
||||
#include "mp.h"
|
||||
#include "db_am.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
static int db_close __P((DB *, u_int32_t));
|
||||
static int db_fd __P((DB *, int *));
|
||||
|
||||
/*
|
||||
* If the metadata page has the flag set, set the local flag. If the page
|
||||
* does NOT have the flag set, return EINVAL if the user's dbinfo argument
|
||||
* caused us to already set the local flag.
|
||||
*/
|
||||
#define DBINFO_FCHK(dbp, fn, meta_flags, m_name, dbp_name) { \
|
||||
if ((meta_flags) & (m_name)) \
|
||||
F_SET(dbp, dbp_name); \
|
||||
else \
|
||||
if (F_ISSET(dbp, dbp_name)) { \
|
||||
__db_err(dbenv, \
|
||||
"%s: %s specified in dbinfo argument but not set in file", \
|
||||
fname, fn); \
|
||||
goto einval; \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* db_open --
|
||||
* Main library interface to the DB access methods.
|
||||
*/
|
||||
int
|
||||
db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
|
||||
const char *fname;
|
||||
DBTYPE type;
|
||||
u_int32_t flags;
|
||||
int mode;
|
||||
DB_ENV *dbenv;
|
||||
DB_INFO *dbinfo;
|
||||
DB **dbpp;
|
||||
{
|
||||
BTMETA *btm;
|
||||
DB *dbp;
|
||||
DBT pgcookie;
|
||||
DB_ENV *envp, t_dbenv;
|
||||
DB_MPOOL_FINFO finfo;
|
||||
DB_PGINFO pginfo;
|
||||
HASHHDR *hashm;
|
||||
size_t cachesize;
|
||||
ssize_t nr;
|
||||
u_int32_t iopsize;
|
||||
int fd, ftype, need_fileid, restore, ret, retry_cnt, swapped;
|
||||
char *real_name, mbuf[512];
|
||||
|
||||
/* Validate arguments. */
|
||||
#ifdef HAVE_SPINLOCKS
|
||||
#define OKFLAGS (DB_CREATE | DB_NOMMAP | DB_RDONLY | DB_THREAD | DB_TRUNCATE)
|
||||
#else
|
||||
#define OKFLAGS (DB_CREATE | DB_NOMMAP | DB_RDONLY | DB_TRUNCATE)
|
||||
#endif
|
||||
if ((ret = __db_fchk(dbenv, "db_open", flags, OKFLAGS)) != 0)
|
||||
return (ret);
|
||||
|
||||
if (dbenv != NULL) {
|
||||
/*
|
||||
* You can't specify threads during the db_open() if the
|
||||
* environment wasn't configured with them.
|
||||
*/
|
||||
if (LF_ISSET(DB_THREAD) && !F_ISSET(dbenv, DB_ENV_THREAD)) {
|
||||
__db_err(dbenv,
|
||||
"environment not created using DB_THREAD");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Specifying a cachesize to db_open(3), after creating an
|
||||
* environment, is a common mistake.
|
||||
*/
|
||||
if (dbinfo != NULL && dbinfo->db_cachesize != 0) {
|
||||
__db_err(dbenv,
|
||||
"cachesize will be ignored if environment exists");
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize for error return. */
|
||||
fd = -1;
|
||||
need_fileid = 1;
|
||||
real_name = NULL;
|
||||
|
||||
/* Allocate the DB structure, reference the DB_ENV structure. */
|
||||
if ((dbp = (DB *)__db_calloc(1, sizeof(DB))) == NULL) {
|
||||
__db_err(dbenv, "%s", strerror(ENOMEM));
|
||||
return (ENOMEM);
|
||||
}
|
||||
dbp->dbenv = dbenv;
|
||||
|
||||
/* Convert the db_open(3) flags. */
|
||||
if (LF_ISSET(DB_RDONLY))
|
||||
F_SET(dbp, DB_AM_RDONLY);
|
||||
if (LF_ISSET(DB_THREAD))
|
||||
F_SET(dbp, DB_AM_THREAD);
|
||||
|
||||
/* Convert the dbinfo structure flags. */
|
||||
if (dbinfo != NULL) {
|
||||
/*
|
||||
* !!!
|
||||
* We can't check for illegal flags until we know what type
|
||||
* of open we're doing.
|
||||
*/
|
||||
if (F_ISSET(dbinfo, DB_DELIMITER))
|
||||
F_SET(dbp, DB_RE_DELIMITER);
|
||||
if (F_ISSET(dbinfo, DB_DUP))
|
||||
F_SET(dbp, DB_AM_DUP);
|
||||
if (F_ISSET(dbinfo, DB_FIXEDLEN))
|
||||
F_SET(dbp, DB_RE_FIXEDLEN);
|
||||
if (F_ISSET(dbinfo, DB_PAD))
|
||||
F_SET(dbp, DB_RE_PAD);
|
||||
if (F_ISSET(dbinfo, DB_RECNUM))
|
||||
F_SET(dbp, DB_BT_RECNUM);
|
||||
if (F_ISSET(dbinfo, DB_RENUMBER))
|
||||
F_SET(dbp, DB_RE_RENUMBER);
|
||||
if (F_ISSET(dbinfo, DB_SNAPSHOT))
|
||||
F_SET(dbp, DB_RE_SNAPSHOT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Always set the master and initialize the queues, so we can
|
||||
* use these fields without checking the thread bit.
|
||||
*/
|
||||
dbp->master = dbp;
|
||||
LIST_INIT(&dbp->handleq);
|
||||
LIST_INSERT_HEAD(&dbp->handleq, dbp, links);
|
||||
TAILQ_INIT(&dbp->curs_queue);
|
||||
|
||||
/*
|
||||
* Set based on the dbenv fields, although no logging or transactions
|
||||
* are possible for temporary files.
|
||||
*/
|
||||
if (dbenv != NULL) {
|
||||
if (dbenv->lk_info != NULL)
|
||||
F_SET(dbp, DB_AM_LOCKING);
|
||||
if (fname != NULL && dbenv->lg_info != NULL)
|
||||
F_SET(dbp, DB_AM_LOGGING);
|
||||
}
|
||||
|
||||
/* Set the common fields. */
|
||||
if (dbinfo == NULL) {
|
||||
dbp->pgsize = 0;
|
||||
dbp->db_malloc = NULL;
|
||||
} else {
|
||||
dbp->pgsize = dbinfo->db_pagesize;
|
||||
dbp->db_malloc = dbinfo->db_malloc;
|
||||
}
|
||||
|
||||
/* Fill in the default file mode. */
|
||||
if (mode == 0)
|
||||
mode = __db_omode("rwrw--");
|
||||
|
||||
/* Check if the user wants us to swap byte order. */
|
||||
if (dbinfo != NULL)
|
||||
switch (ret = __db_byteorder(dbenv, dbinfo->db_lorder)) {
|
||||
case 0:
|
||||
break;
|
||||
case DB_SWAPBYTES:
|
||||
F_SET(dbp, DB_AM_SWAP);
|
||||
break;
|
||||
default:
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a file name, try and read the first page, figure out
|
||||
* what type of file it is, and initialize everything we can based
|
||||
* on that file's meta-data page.
|
||||
*
|
||||
* XXX
|
||||
* We don't actually expect zero-length strings as arguments. We
|
||||
* do the check, permitting them, because scripting languages, e.g.,
|
||||
* the Tcl test suite, doesn't know anything about passing NULL's.
|
||||
*/
|
||||
if (fname != NULL && fname[0] != '\0') {
|
||||
/* Get the real file name. */
|
||||
if ((ret = __db_appname(dbenv,
|
||||
DB_APP_DATA, NULL, fname, 0, NULL, &real_name)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Open the backing file. We need to make sure that multiple
|
||||
* processes attempting to create the file at the same time
|
||||
* are properly ordered so that only one of them creates the
|
||||
* "unique" file id, so we open it O_EXCL and O_CREAT so two
|
||||
* simultaneous attempts to create the region will return
|
||||
* failure in one of the attempts. If we're one of the ones
|
||||
* that fail, we simply retry without the O_CREAT flag, which
|
||||
* will require that the meta-data page exist.
|
||||
*/
|
||||
retry_cnt = 0;
|
||||
open_retry: if (LF_ISSET(DB_CREATE)) {
|
||||
if ((ret = __db_open(real_name, flags | DB_EXCL,
|
||||
OKFLAGS | DB_EXCL, mode, &fd)) != 0)
|
||||
if (ret == EEXIST) {
|
||||
LF_CLR(DB_CREATE);
|
||||
goto open_retry;
|
||||
} else {
|
||||
__db_err(dbenv,
|
||||
"%s: %s", fname, strerror(ret));
|
||||
goto err;
|
||||
}
|
||||
} else
|
||||
if ((ret = __db_open(real_name,
|
||||
flags, OKFLAGS, mode, &fd)) != 0) {
|
||||
__db_err(dbenv, "%s: %s", fname, strerror(ret));
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the optimum I/O size as the pagesize if a pagesize not
|
||||
* specified. Some filesystems have 64K as their optimum I/O
|
||||
* size, but as that results in impossibly large default cache
|
||||
* sizes, we limit the default pagesize to 16K.
|
||||
*/
|
||||
if (dbp->pgsize == 0) {
|
||||
if ((ret = __db_ioinfo(real_name,
|
||||
fd, NULL, NULL, &iopsize)) != 0) {
|
||||
__db_err(dbenv,
|
||||
"%s: %s", real_name, strerror(ret));
|
||||
goto err;
|
||||
}
|
||||
if (iopsize < 512)
|
||||
iopsize = 512;
|
||||
if (iopsize > 16 * 1024)
|
||||
iopsize = 16 * 1024;
|
||||
dbp->pgsize = iopsize;
|
||||
F_SET(dbp, DB_AM_PGDEF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try and read the first disk sector -- this code assumes
|
||||
* that the meta-data for all access methods fits in 512
|
||||
* bytes, and that no database will be smaller than that.
|
||||
*/
|
||||
if ((ret = __db_read(fd, mbuf, sizeof(mbuf), &nr)) != 0)
|
||||
goto err;
|
||||
|
||||
/* The fd is no longer needed. */
|
||||
(void)__db_close(fd);
|
||||
fd = -1;
|
||||
|
||||
if (nr != sizeof(mbuf)) {
|
||||
if (nr != 0) {
|
||||
__db_err(dbenv,
|
||||
"%s: unexpected file format", fname);
|
||||
goto einval;
|
||||
}
|
||||
/*
|
||||
* The only way we can reach here with the DB_CREATE
|
||||
* flag set is if we created the file. If that's not
|
||||
* the case, then a) someone else created the file
|
||||
* but has not yet written out the meta-data page, or
|
||||
* b) we truncated the file (DB_TRUNCATE) leaving it
|
||||
* zero-length. In the case of a), we want to sleep
|
||||
* and give the file creator some time to write the
|
||||
* metadata page. In the case of b), charge forward.
|
||||
* Note, there is a race in the case of two processes
|
||||
* opening the file with the DB_TRUNCATE flag set at
|
||||
* roughly the same time, and they could theoretically
|
||||
* hurt each other, although it's pretty unlikely.
|
||||
*/
|
||||
if (retry_cnt++ < 3 &&
|
||||
!LF_ISSET(DB_CREATE | DB_TRUNCATE)) {
|
||||
__db_sleep(1, 0);
|
||||
goto open_retry;
|
||||
}
|
||||
if (type == DB_UNKNOWN) {
|
||||
__db_err(dbenv,
|
||||
"%s: DBTYPE of unknown with empty file",
|
||||
fname);
|
||||
goto einval;
|
||||
}
|
||||
goto empty;
|
||||
}
|
||||
|
||||
/*
|
||||
* A found file overrides some user information. We'll check
|
||||
* for possible error conditions based on conflicts between
|
||||
* the file and the user's arguments below.
|
||||
*/
|
||||
swapped = 0;
|
||||
F_CLR(dbp, DB_AM_SWAP);
|
||||
|
||||
retry: switch (((BTMETA *)mbuf)->magic) {
|
||||
case DB_BTREEMAGIC:
|
||||
if (type != DB_BTREE &&
|
||||
type != DB_RECNO && type != DB_UNKNOWN)
|
||||
goto einval;
|
||||
|
||||
btm = (BTMETA *)mbuf;
|
||||
if (swapped && (ret = __bam_mswap((PAGE *)btm)) != 0)
|
||||
goto err;
|
||||
|
||||
if (btm->version < DB_BTREEOLDVER ||
|
||||
btm->version > DB_BTREEVERSION) {
|
||||
__db_err(dbenv,
|
||||
"%s: unsupported btree version number %lu",
|
||||
fname, (u_long)btm->version);
|
||||
goto einval;
|
||||
}
|
||||
dbp->pgsize = btm->pagesize;
|
||||
F_CLR(dbp, DB_AM_PGDEF);
|
||||
|
||||
if ((ret = __db_fchk(dbenv,
|
||||
"db_open", btm->flags, BTM_MASK)) != 0)
|
||||
goto err;
|
||||
DBINFO_FCHK(dbp, "DB_DUP",
|
||||
btm->flags, BTM_DUP, DB_AM_DUP);
|
||||
if (F_ISSET(btm, BTM_RECNO)) {
|
||||
DBINFO_FCHK(dbp, "DB_FIXEDLEN",
|
||||
btm->flags, BTM_FIXEDLEN, DB_RE_FIXEDLEN);
|
||||
DBINFO_FCHK(dbp, "DB_RENUMBER",
|
||||
btm->flags, BTM_RENUMBER, DB_RE_RENUMBER);
|
||||
type = DB_RECNO;
|
||||
} else {
|
||||
DBINFO_FCHK(dbp, "DB_RECNUM",
|
||||
btm->flags, BTM_RECNUM, DB_BT_RECNUM);
|
||||
type = DB_BTREE;
|
||||
}
|
||||
|
||||
/* Copy the file's unique id. */
|
||||
need_fileid = 0;
|
||||
memcpy(dbp->lock.fileid, btm->uid, DB_FILE_ID_LEN);
|
||||
break;
|
||||
case DB_HASHMAGIC:
|
||||
if (type != DB_HASH && type != DB_UNKNOWN)
|
||||
goto einval;
|
||||
|
||||
hashm = (HASHHDR *)mbuf;
|
||||
if (swapped && (ret = __ham_mswap((PAGE *)hashm)) != 0)
|
||||
goto err;
|
||||
|
||||
if (hashm->version < DB_HASHOLDVER ||
|
||||
hashm->version > DB_HASHVERSION) {
|
||||
__db_err(dbenv,
|
||||
"%s: unsupported hash version number %lu",
|
||||
fname, hashm->version);
|
||||
goto einval;
|
||||
}
|
||||
dbp->pgsize = hashm->pagesize;
|
||||
F_CLR(dbp, DB_AM_PGDEF);
|
||||
|
||||
if ((ret = __db_fchk(dbenv,
|
||||
"db_open", hashm->flags, DB_HASH_DUP)) != 0)
|
||||
goto err;
|
||||
DBINFO_FCHK(dbp, "DB_DUP",
|
||||
hashm->flags, DB_HASH_DUP, DB_AM_DUP);
|
||||
type = DB_HASH;
|
||||
|
||||
/* Copy the file's unique id. */
|
||||
need_fileid = 0;
|
||||
memcpy(dbp->lock.fileid, hashm->uid, DB_FILE_ID_LEN);
|
||||
break;
|
||||
default:
|
||||
if (swapped) {
|
||||
__db_err(dbenv, "unrecognized file type");
|
||||
goto einval;
|
||||
}
|
||||
M_32_SWAP(((BTMETA *)mbuf)->magic);
|
||||
F_SET(dbp, DB_AM_SWAP);
|
||||
|
||||
swapped = 1;
|
||||
goto retry;
|
||||
}
|
||||
} else {
|
||||
fname = real_name = NULL;
|
||||
|
||||
if (type == DB_UNKNOWN) {
|
||||
__db_err(dbenv,
|
||||
"DBTYPE of unknown without existing file");
|
||||
goto einval;
|
||||
}
|
||||
F_SET(dbp, DB_AM_INMEM);
|
||||
}
|
||||
|
||||
empty: /*
|
||||
* By the time we get here we've either set the type or we're taking
|
||||
* it from the user.
|
||||
*/
|
||||
dbp->type = type;
|
||||
|
||||
/*
|
||||
* Set the page size to the best value for I/O to this file. Don't
|
||||
* overflow the page offset type. The page size must be db_indx_t
|
||||
* aligned and >= MIN_PAGE_SIZE.
|
||||
*
|
||||
* XXX
|
||||
* Should we be checking for a page size that's not a multiple of 512?
|
||||
*/
|
||||
if (dbp->pgsize == 0) {
|
||||
F_SET(dbp, DB_AM_PGDEF);
|
||||
dbp->pgsize = 8 * 1024;
|
||||
}
|
||||
if (dbp->pgsize < DB_MIN_PGSIZE ||
|
||||
dbp->pgsize > DB_MAX_PGSIZE ||
|
||||
dbp->pgsize & (sizeof(db_indx_t) - 1)) {
|
||||
__db_err(dbenv, "illegal page size");
|
||||
goto einval;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no mpool supplied by the application, attach to a local,
|
||||
* created buffer pool.
|
||||
*
|
||||
* XXX
|
||||
* If the user has a DB_ENV structure, we have to use a temporary
|
||||
* one so that we don't step on their values. If the user doesn't,
|
||||
* we have to create one, and keep it around until the call to the
|
||||
* memp_close() function. This is all so the mpool functions get
|
||||
* the error stuff right.
|
||||
*/
|
||||
if (dbenv == NULL || dbenv->mp_info == NULL) {
|
||||
F_SET(dbp, DB_AM_MLOCAL);
|
||||
|
||||
if (dbenv == NULL) {
|
||||
if ((dbp->mp_dbenv =
|
||||
(DB_ENV *)__db_calloc(sizeof(DB_ENV), 1)) == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
envp = dbp->mp_dbenv;
|
||||
restore = 0;
|
||||
} else {
|
||||
t_dbenv = *dbenv;
|
||||
|
||||
envp = dbenv;
|
||||
restore = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set and/or correct the cache size; must be a multiple of
|
||||
* the page size.
|
||||
*/
|
||||
if (dbinfo == NULL || dbinfo->db_cachesize == 0)
|
||||
cachesize = dbp->pgsize * DB_MINCACHE;
|
||||
else {
|
||||
cachesize = dbinfo->db_cachesize;
|
||||
if (cachesize & (dbp->pgsize - 1))
|
||||
cachesize +=
|
||||
(~cachesize & (dbp->pgsize - 1)) + 1;
|
||||
if (cachesize < dbp->pgsize * DB_MINCACHE)
|
||||
cachesize = dbp->pgsize * DB_MINCACHE;
|
||||
if (cachesize < 20 * 1024)
|
||||
cachesize = 20 * 1024;
|
||||
}
|
||||
envp->mp_size = cachesize;
|
||||
|
||||
if ((ret = memp_open(NULL, DB_CREATE | DB_MPOOL_PRIVATE |
|
||||
(F_ISSET(dbp, DB_AM_THREAD) ? DB_THREAD : 0),
|
||||
__db_omode("rw----"), envp, &dbp->mp)) != 0)
|
||||
goto err;
|
||||
if (restore)
|
||||
*dbenv = t_dbenv;
|
||||
} else
|
||||
dbp->mp = dbenv->mp_info;
|
||||
|
||||
/* Register DB's pgin/pgout functions. */
|
||||
if ((ret = memp_register(dbp->mp,
|
||||
DB_FTYPE_BTREE, __bam_pgin, __bam_pgout)) != 0)
|
||||
goto err;
|
||||
if ((ret = memp_register(dbp->mp,
|
||||
DB_FTYPE_HASH, __ham_pgin, __ham_pgout)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* If we don't already have one, get a unique file ID. If the file
|
||||
* is a temporary file, then we have to create a unique file ID --
|
||||
* no backing file will be created until the mpool cache is filled
|
||||
* forcing it to go to disk. The created ID must never match any
|
||||
* potential real file ID -- we know it won't because real file IDs
|
||||
* contain a time stamp after the dev/ino pair, and we're simply
|
||||
* storing a 4-byte locker ID.
|
||||
*
|
||||
* XXX
|
||||
* Store the file id in the locker structure -- we can get it from
|
||||
* there as necessary, and it saves having two copies.
|
||||
*/
|
||||
if (need_fileid)
|
||||
if (fname == NULL) {
|
||||
memset(dbp->lock.fileid, 0, DB_FILE_ID_LEN);
|
||||
if (F_ISSET(dbp, DB_AM_LOCKING) &&
|
||||
(ret = lock_id(dbenv->lk_info,
|
||||
(u_int32_t *)dbp->lock.fileid)) != 0)
|
||||
goto err;
|
||||
} else
|
||||
if ((ret = __db_fileid(dbenv,
|
||||
real_name, 1, dbp->lock.fileid)) != 0)
|
||||
goto err;
|
||||
|
||||
/* No further use for the real name. */
|
||||
if (real_name != NULL)
|
||||
FREES(real_name);
|
||||
real_name = NULL;
|
||||
|
||||
/*
|
||||
* Open a backing file in the memory pool.
|
||||
*
|
||||
* If we need to process the file's pages on I/O, set the file type.
|
||||
* If it's a hash file, always call pgin and pgout routines. This
|
||||
* means that hash files can never be mapped into process memory. If
|
||||
* it's a btree file and requires swapping, we need to page the file
|
||||
* in and out. This has to be right -- we can't mmap files that are
|
||||
* being paged in and out.
|
||||
*/
|
||||
if (type == DB_HASH)
|
||||
ftype = DB_FTYPE_HASH;
|
||||
else
|
||||
ftype = F_ISSET(dbp, DB_AM_SWAP) ? DB_FTYPE_BTREE : 0;
|
||||
pginfo.db_pagesize = dbp->pgsize;
|
||||
pginfo.needswap = F_ISSET(dbp, DB_AM_SWAP);
|
||||
pgcookie.data = &pginfo;
|
||||
pgcookie.size = sizeof(DB_PGINFO);
|
||||
|
||||
/*
|
||||
* Set up additional memp_fopen information.
|
||||
*/
|
||||
memset(&finfo, 0, sizeof(finfo));
|
||||
finfo.ftype = ftype;
|
||||
finfo.pgcookie = &pgcookie;
|
||||
finfo.fileid = dbp->lock.fileid;
|
||||
finfo.lsn_offset = 0;
|
||||
finfo.clear_len = DB_PAGE_CLEAR_LEN;
|
||||
if ((ret = memp_fopen(dbp->mp, fname,
|
||||
F_ISSET(dbp, DB_AM_RDONLY) ? DB_RDONLY : 0,
|
||||
0, dbp->pgsize, &finfo, &dbp->mpf)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Truly spectacular layering violation. We need a per-thread mutex
|
||||
* that lives in shared memory (thanks, HP-UX!) and so we acquire a
|
||||
* pointer to the mpool one.
|
||||
*/
|
||||
if (F_ISSET(dbp, DB_AM_THREAD))
|
||||
dbp->mutexp = dbp->mpf->mutexp;
|
||||
|
||||
/* Get a log file id. */
|
||||
if (F_ISSET(dbp, DB_AM_LOGGING) &&
|
||||
(ret = log_register(dbenv->lg_info,
|
||||
dbp, fname, type, &dbp->log_fileid)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Get a locker id for this DB, and build the lock cookie: the first
|
||||
* db_pgno_t bytes are the page number, the next N bytes are the file
|
||||
* id.
|
||||
*/
|
||||
if (F_ISSET(dbp, DB_AM_LOCKING)) {
|
||||
if ((ret = lock_id(dbenv->lk_info, &dbp->locker)) != 0)
|
||||
goto err;
|
||||
dbp->lock_dbt.size = sizeof(dbp->lock);
|
||||
dbp->lock_dbt.data = &dbp->lock;
|
||||
}
|
||||
|
||||
/* Call the real open function. */
|
||||
switch (type) {
|
||||
case DB_BTREE:
|
||||
if (dbinfo != NULL && (ret = __db_fchk(dbenv,
|
||||
"db_open", dbinfo->flags, DB_RECNUM | DB_DUP)) != 0)
|
||||
goto err;
|
||||
if (dbinfo != NULL && (ret = __db_fcchk(dbenv,
|
||||
"db_open", dbinfo->flags, DB_DUP, DB_RECNUM)) != 0)
|
||||
goto err;
|
||||
if ((ret = __bam_open(dbp, type, dbinfo)) != 0)
|
||||
goto err;
|
||||
break;
|
||||
case DB_HASH:
|
||||
if (dbinfo != NULL && (ret = __db_fchk(dbenv,
|
||||
"db_open", dbinfo->flags, DB_DUP)) != 0)
|
||||
goto err;
|
||||
if ((ret = __ham_open(dbp, dbinfo)) != 0)
|
||||
goto err;
|
||||
break;
|
||||
case DB_RECNO:
|
||||
#define DB_INFO_FLAGS \
|
||||
(DB_DELIMITER | DB_FIXEDLEN | DB_PAD | DB_RENUMBER | DB_SNAPSHOT)
|
||||
if (dbinfo != NULL && (ret = __db_fchk(dbenv,
|
||||
"db_open", dbinfo->flags, DB_INFO_FLAGS)) != 0)
|
||||
goto err;
|
||||
if ((ret = __ram_open(dbp, type, dbinfo)) != 0)
|
||||
goto err;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Call a local close routine. */
|
||||
dbp->close = db_close;
|
||||
dbp->fd = db_fd;
|
||||
|
||||
*dbpp = dbp;
|
||||
return (0);
|
||||
|
||||
einval: ret = EINVAL;
|
||||
err: /* Close the file descriptor. */
|
||||
if (fd != -1)
|
||||
(void)__db_close(fd);
|
||||
|
||||
/* Discard the log file id. */
|
||||
if (dbp->log_fileid != 0)
|
||||
(void)log_unregister(dbenv->lg_info, dbp->log_fileid);
|
||||
|
||||
/* Close the memory pool file. */
|
||||
if (dbp->mpf != NULL)
|
||||
(void)memp_fclose(dbp->mpf);
|
||||
|
||||
/* If the memory pool was local, close it. */
|
||||
if (F_ISSET(dbp, DB_AM_MLOCAL) && dbp->mp != NULL)
|
||||
(void)memp_close(dbp->mp);
|
||||
|
||||
/* If we allocated a DB_ENV, discard it. */
|
||||
if (dbp->mp_dbenv != NULL)
|
||||
FREE(dbp->mp_dbenv, sizeof(DB_ENV));
|
||||
|
||||
if (real_name != NULL)
|
||||
FREES(real_name);
|
||||
if (dbp != NULL)
|
||||
FREE(dbp, sizeof(DB));
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* db_close --
|
||||
* Close a DB tree.
|
||||
*/
|
||||
static int
|
||||
db_close(dbp, flags)
|
||||
DB *dbp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DBC *dbc;
|
||||
DB *tdbp;
|
||||
int ret, t_ret;
|
||||
|
||||
/* Validate arguments. */
|
||||
if ((ret = __db_fchk(dbp->dbenv, "db_close", flags, DB_NOSYNC)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Sync the underlying file. */
|
||||
if (!LF_ISSET(DB_NOSYNC) &&
|
||||
(t_ret = dbp->sync(dbp, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/*
|
||||
* Call the underlying access method close routine for all the
|
||||
* cursors and handles.
|
||||
*/
|
||||
for (tdbp = LIST_FIRST(&dbp->handleq);
|
||||
tdbp != NULL; tdbp = LIST_NEXT(tdbp, links)) {
|
||||
while ((dbc = TAILQ_FIRST(&tdbp->curs_queue)) != NULL)
|
||||
switch (tdbp->type) {
|
||||
case DB_BTREE:
|
||||
if ((t_ret =
|
||||
__bam_c_iclose(tdbp, dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
break;
|
||||
case DB_HASH:
|
||||
if ((t_ret =
|
||||
__ham_c_iclose(tdbp, dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
break;
|
||||
case DB_RECNO:
|
||||
if ((t_ret =
|
||||
__ram_c_iclose(tdbp, dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
switch (tdbp->type) {
|
||||
case DB_BTREE:
|
||||
if ((t_ret = __bam_close(tdbp)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
break;
|
||||
case DB_HASH:
|
||||
if ((t_ret = __ham_close(tdbp)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
break;
|
||||
case DB_RECNO:
|
||||
if ((t_ret = __ram_close(tdbp)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* Sync the memory pool. */
|
||||
if (!LF_ISSET(DB_NOSYNC) && (t_ret = memp_fsync(dbp->mpf)) != 0 &&
|
||||
t_ret != DB_INCOMPLETE && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/* Close the memory pool file. */
|
||||
if ((t_ret = memp_fclose(dbp->mpf)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/* If the memory pool was local, close it. */
|
||||
if (F_ISSET(dbp, DB_AM_MLOCAL) &&
|
||||
(t_ret = memp_close(dbp->mp)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/* Discard the log file id. */
|
||||
if (F_ISSET(dbp, DB_AM_LOGGING))
|
||||
(void)log_unregister(dbp->dbenv->lg_info, dbp->log_fileid);
|
||||
|
||||
/* Discard the lock cookie for all handles. */
|
||||
for (tdbp = LIST_FIRST(&dbp->handleq);
|
||||
tdbp != NULL; tdbp = LIST_NEXT(tdbp, links))
|
||||
if (F_ISSET(tdbp, DB_AM_LOCKING)) {
|
||||
#ifdef DEBUG
|
||||
DB_LOCKREQ request;
|
||||
|
||||
/*
|
||||
* If we're running tests, display any locks currently
|
||||
* held. It's possible that some applications may hold
|
||||
* locks for long periods, e.g., conference room locks,
|
||||
* but the DB tests should never close holding locks.
|
||||
*/
|
||||
request.op = DB_LOCK_DUMP;
|
||||
if ((t_ret = lock_vec(tdbp->dbenv->lk_info,
|
||||
tdbp->locker, 0, &request, 1, NULL)) != 0 &&
|
||||
ret == 0)
|
||||
ret = EAGAIN;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If we allocated a DB_ENV, discard it. */
|
||||
if (dbp->mp_dbenv != NULL)
|
||||
FREE(dbp->mp_dbenv, sizeof(DB_ENV));
|
||||
|
||||
/* Free all of the DB's. */
|
||||
LIST_REMOVE(dbp, links);
|
||||
while ((tdbp = LIST_FIRST(&dbp->handleq)) != NULL) {
|
||||
LIST_REMOVE(tdbp, links);
|
||||
FREE(tdbp, sizeof(*tdbp));
|
||||
}
|
||||
FREE(dbp, sizeof(*dbp));
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* db_fd --
|
||||
* Return a file descriptor for flock'ing.
|
||||
*/
|
||||
static int
|
||||
db_fd(dbp, fdp)
|
||||
DB *dbp;
|
||||
int *fdp;
|
||||
{
|
||||
/*
|
||||
* XXX
|
||||
* Truly spectacular layering violation.
|
||||
*/
|
||||
return (__mp_xxx_fd(dbp->mpf, fdp));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_pgerr --
|
||||
* Error when unable to retrieve a specified page.
|
||||
*
|
||||
* PUBLIC: int __db_pgerr __P((DB *, db_pgno_t));
|
||||
*/
|
||||
int
|
||||
__db_pgerr(dbp, pgno)
|
||||
DB *dbp;
|
||||
db_pgno_t pgno;
|
||||
{
|
||||
/*
|
||||
* Three things are certain:
|
||||
* Death, taxes, and lost data.
|
||||
* Guess which has occurred.
|
||||
*/
|
||||
__db_err(dbp->dbenv,
|
||||
"unable to create/retrieve page %lu", (u_long)pgno);
|
||||
return (__db_panic(dbp));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_pgfmt --
|
||||
* Error when a page has the wrong format.
|
||||
*
|
||||
* PUBLIC: int __db_pgfmt __P((DB *, db_pgno_t));
|
||||
*/
|
||||
int
|
||||
__db_pgfmt(dbp, pgno)
|
||||
DB *dbp;
|
||||
db_pgno_t pgno;
|
||||
{
|
||||
__db_err(dbp->dbenv,
|
||||
"page %lu: illegal page type or format", (u_long)pgno);
|
||||
return (__db_panic(dbp));
|
||||
}
|
159
db/db/db.src
159
db/db/db.src
|
@ -1,159 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* @(#)db.src 10.6 (Sleepycat) 4/28/98
|
||||
*/
|
||||
|
||||
PREFIX db
|
||||
|
||||
/*
|
||||
* addrem -- Add or remove an entry from a duplicate page.
|
||||
*
|
||||
* opcode: identifies if this is an add or delete.
|
||||
* fileid: file identifier of the file being modified.
|
||||
* pgno: duplicate page number.
|
||||
* indx: location at which to insert or delete.
|
||||
* nbytes: number of bytes added/removed to/from the page.
|
||||
* hdr: header for the data item.
|
||||
* dbt: data that is deleted or is to be added.
|
||||
* pagelsn: former lsn of the page.
|
||||
*
|
||||
* If the hdr was NULL then, the dbt is a regular B_KEYDATA.
|
||||
* If the dbt was NULL then the hdr is a complete item to be
|
||||
* pasted on the page.
|
||||
*/
|
||||
BEGIN addrem
|
||||
ARG opcode u_int32_t lu
|
||||
ARG fileid u_int32_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
ARG indx u_int32_t lu
|
||||
ARG nbytes size_t lu
|
||||
DBT hdr DBT s
|
||||
DBT dbt DBT s
|
||||
POINTER pagelsn DB_LSN * lu
|
||||
END
|
||||
|
||||
/*
|
||||
* split -- Handles the split of a duplicate page.
|
||||
*
|
||||
* opcode: defines whether we are splitting from or splitting onto
|
||||
* fileid: file identifier of the file being modified.
|
||||
* pgno: page number being split.
|
||||
* pageimage: entire page contents.
|
||||
* pagelsn: former lsn of the page.
|
||||
*/
|
||||
BEGIN split
|
||||
ARG opcode u_int32_t lu
|
||||
ARG fileid u_int32_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
DBT pageimage DBT s
|
||||
POINTER pagelsn DB_LSN * lu
|
||||
END
|
||||
|
||||
/*
|
||||
* big -- Handles addition and deletion of big key/data items.
|
||||
*
|
||||
* opcode: identifies get/put.
|
||||
* fileid: file identifier of the file being modified.
|
||||
* pgno: page onto which data is being added/removed.
|
||||
* prev_pgno: the page before the one we are logging.
|
||||
* next_pgno: the page after the one we are logging.
|
||||
* dbt: data being written onto the page.
|
||||
* pagelsn: former lsn of the orig_page.
|
||||
* prevlsn: former lsn of the prev_pgno.
|
||||
* nextlsn: former lsn of the next_pgno. This is not currently used, but
|
||||
* may be used later if we actually do overwrites of big key/
|
||||
* data items in place.
|
||||
*/
|
||||
BEGIN big
|
||||
ARG opcode u_int32_t lu
|
||||
ARG fileid u_int32_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
ARG prev_pgno db_pgno_t lu
|
||||
ARG next_pgno db_pgno_t lu
|
||||
DBT dbt DBT s
|
||||
POINTER pagelsn DB_LSN * lu
|
||||
POINTER prevlsn DB_LSN * lu
|
||||
POINTER nextlsn DB_LSN * lu
|
||||
END
|
||||
|
||||
/*
|
||||
* ovref -- Handles increment/decrement of overflow page reference count.
|
||||
*
|
||||
* fileid: identifies the file being modified.
|
||||
* pgno: page number whose ref count is being incremented/decremented.
|
||||
* adjust: the adjustment being made.
|
||||
* lsn: the page's original lsn.
|
||||
*/
|
||||
BEGIN ovref
|
||||
ARG fileid u_int32_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
ARG adjust int32_t ld
|
||||
POINTER lsn DB_LSN * lu
|
||||
END
|
||||
|
||||
/*
|
||||
* relink -- Handles relinking around a page.
|
||||
*
|
||||
* pgno: the page being changed.
|
||||
* lsn the page's original lsn.
|
||||
* prev: the previous page.
|
||||
* lsn_prev: the previous page's original lsn.
|
||||
* next: the next page.
|
||||
* lsn_next: the previous page's original lsn.
|
||||
*/
|
||||
BEGIN relink
|
||||
ARG fileid u_int32_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER lsn DB_LSN * lu
|
||||
ARG prev db_pgno_t lu
|
||||
POINTER lsn_prev DB_LSN * lu
|
||||
ARG next db_pgno_t lu
|
||||
POINTER lsn_next DB_LSN * lu
|
||||
END
|
||||
|
||||
/*
|
||||
* Addpage -- Handles adding a new duplicate page onto the end of
|
||||
* an existing duplicate page.
|
||||
* fileid: identifies the file being changed.
|
||||
* pgno: page number to which a new page is being added.
|
||||
* lsn: lsn of pgno
|
||||
* nextpgno: new page number being added.
|
||||
* nextlsn: lsn of nextpgno;
|
||||
*/
|
||||
BEGIN addpage
|
||||
ARG fileid u_int32_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER lsn DB_LSN * lu
|
||||
ARG nextpgno db_pgno_t lu
|
||||
POINTER nextlsn DB_LSN * lu
|
||||
END
|
||||
|
||||
/*
|
||||
* Debug -- log an operation upon entering an access method.
|
||||
* op: Operation (cursor, c_close, c_get, c_put, c_del,
|
||||
* get, put, delete).
|
||||
* fileid: identifies the file being acted upon.
|
||||
* key: key paramater
|
||||
* data: data parameter
|
||||
* flags: flags parameter
|
||||
*/
|
||||
BEGIN debug
|
||||
DBT op DBT s
|
||||
ARG fileid u_int32_t lu
|
||||
DBT key DBT s
|
||||
DBT data DBT s
|
||||
ARG arg_flags u_int32_t lu
|
||||
END
|
||||
|
||||
/*
|
||||
* noop -- do nothing, but get an LSN.
|
||||
*/
|
||||
BEGIN noop
|
||||
ARG fileid u_int32_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER prevlsn DB_LSN * lu
|
||||
END
|
1494
db/db/db_auto.c
1494
db/db/db_auto.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
255
db/db/db_conv.c
255
db/db/db_conv.c
|
@ -1,255 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_conv.c 10.13 (Sleepycat) 4/26/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "db_swap.h"
|
||||
#include "db_am.h"
|
||||
|
||||
static int __db_convert __P((db_pgno_t, void *, size_t, int));
|
||||
|
||||
/*
|
||||
* __db_pgin --
|
||||
*
|
||||
* PUBLIC: int __db_pgin __P((db_pgno_t, size_t, void *));
|
||||
*/
|
||||
int
|
||||
__db_pgin(pg, pagesize, pp)
|
||||
db_pgno_t pg;
|
||||
size_t pagesize;
|
||||
void *pp;
|
||||
{
|
||||
return (__db_convert(pg, pp, pagesize, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_pgout --
|
||||
*
|
||||
* PUBLIC: int __db_pgout __P((db_pgno_t, size_t, void *));
|
||||
*/
|
||||
int
|
||||
__db_pgout(pg, pagesize, pp)
|
||||
db_pgno_t pg;
|
||||
size_t pagesize;
|
||||
void *pp;
|
||||
{
|
||||
return (__db_convert(pg, pp, pagesize, 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_convert --
|
||||
* Actually convert a page.
|
||||
*/
|
||||
static int
|
||||
__db_convert(pg, pp, pagesize, pgin)
|
||||
db_pgno_t pg;
|
||||
void *pp;
|
||||
size_t pagesize;
|
||||
int pgin;
|
||||
{
|
||||
BINTERNAL *bi;
|
||||
BKEYDATA *bk;
|
||||
BOVERFLOW *bo;
|
||||
PAGE *h;
|
||||
RINTERNAL *ri;
|
||||
db_indx_t i, len, tmp;
|
||||
u_int8_t *p, *end;
|
||||
|
||||
COMPQUIET(pg, 0);
|
||||
|
||||
h = pp;
|
||||
if (pgin) {
|
||||
M_32_SWAP(h->lsn.file);
|
||||
M_32_SWAP(h->lsn.offset);
|
||||
M_32_SWAP(h->pgno);
|
||||
M_32_SWAP(h->prev_pgno);
|
||||
M_32_SWAP(h->next_pgno);
|
||||
M_16_SWAP(h->entries);
|
||||
M_16_SWAP(h->hf_offset);
|
||||
}
|
||||
|
||||
switch (h->type) {
|
||||
case P_HASH:
|
||||
for (i = 0; i < NUM_ENT(h); i++) {
|
||||
if (pgin)
|
||||
M_16_SWAP(h->inp[i]);
|
||||
|
||||
switch (HPAGE_TYPE(h, i)) {
|
||||
case H_KEYDATA:
|
||||
break;
|
||||
case H_DUPLICATE:
|
||||
len = LEN_HKEYDATA(h, pagesize, i);
|
||||
p = HKEYDATA_DATA(P_ENTRY(h, i));
|
||||
for (end = p + len; p < end;) {
|
||||
if (pgin) {
|
||||
P_16_SWAP(p);
|
||||
memcpy(&tmp,
|
||||
p, sizeof(db_indx_t));
|
||||
p += sizeof(db_indx_t);
|
||||
} else {
|
||||
memcpy(&tmp,
|
||||
p, sizeof(db_indx_t));
|
||||
SWAP16(p);
|
||||
}
|
||||
p += tmp;
|
||||
SWAP16(p);
|
||||
}
|
||||
break;
|
||||
case H_OFFDUP:
|
||||
p = HOFFPAGE_PGNO(P_ENTRY(h, i));
|
||||
SWAP32(p); /* pgno */
|
||||
break;
|
||||
case H_OFFPAGE:
|
||||
p = HOFFPAGE_PGNO(P_ENTRY(h, i));
|
||||
SWAP32(p); /* pgno */
|
||||
SWAP32(p); /* tlen */
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* The offsets in the inp array are used to determine
|
||||
* the size of entries on a page; therefore they
|
||||
* cannot be converted until we've done all the
|
||||
* entries.
|
||||
*/
|
||||
if (!pgin)
|
||||
for (i = 0; i < NUM_ENT(h); i++)
|
||||
M_16_SWAP(h->inp[i]);
|
||||
break;
|
||||
case P_LBTREE:
|
||||
case P_LRECNO:
|
||||
case P_DUPLICATE:
|
||||
for (i = 0; i < NUM_ENT(h); i++) {
|
||||
if (pgin)
|
||||
M_16_SWAP(h->inp[i]);
|
||||
|
||||
bk = GET_BKEYDATA(h, i);
|
||||
switch (B_TYPE(bk->type)) {
|
||||
case B_KEYDATA:
|
||||
M_16_SWAP(bk->len);
|
||||
break;
|
||||
case B_DUPLICATE:
|
||||
case B_OVERFLOW:
|
||||
bo = (BOVERFLOW *)bk;
|
||||
M_32_SWAP(bo->pgno);
|
||||
M_32_SWAP(bo->tlen);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pgin)
|
||||
M_16_SWAP(h->inp[i]);
|
||||
}
|
||||
break;
|
||||
case P_IBTREE:
|
||||
for (i = 0; i < NUM_ENT(h); i++) {
|
||||
if (pgin)
|
||||
M_16_SWAP(h->inp[i]);
|
||||
|
||||
bi = GET_BINTERNAL(h, i);
|
||||
M_16_SWAP(bi->len);
|
||||
M_32_SWAP(bi->pgno);
|
||||
M_32_SWAP(bi->nrecs);
|
||||
|
||||
switch (B_TYPE(bi->type)) {
|
||||
case B_KEYDATA:
|
||||
break;
|
||||
case B_DUPLICATE:
|
||||
case B_OVERFLOW:
|
||||
bo = (BOVERFLOW *)bi->data;
|
||||
M_32_SWAP(bo->pgno);
|
||||
M_32_SWAP(bo->tlen);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pgin)
|
||||
M_16_SWAP(h->inp[i]);
|
||||
}
|
||||
break;
|
||||
case P_IRECNO:
|
||||
for (i = 0; i < NUM_ENT(h); i++) {
|
||||
if (pgin)
|
||||
M_16_SWAP(h->inp[i]);
|
||||
|
||||
ri = GET_RINTERNAL(h, i);
|
||||
M_32_SWAP(ri->pgno);
|
||||
M_32_SWAP(ri->nrecs);
|
||||
|
||||
if (!pgin)
|
||||
M_16_SWAP(h->inp[i]);
|
||||
}
|
||||
break;
|
||||
case P_OVERFLOW:
|
||||
case P_INVALID:
|
||||
/* Nothing to do. */
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (!pgin) {
|
||||
/* Swap the header information. */
|
||||
M_32_SWAP(h->lsn.file);
|
||||
M_32_SWAP(h->lsn.offset);
|
||||
M_32_SWAP(h->pgno);
|
||||
M_32_SWAP(h->prev_pgno);
|
||||
M_32_SWAP(h->next_pgno);
|
||||
M_16_SWAP(h->entries);
|
||||
M_16_SWAP(h->hf_offset);
|
||||
}
|
||||
return (0);
|
||||
}
|
|
@ -1,323 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995, 1996
|
||||
* The President and Fellows of Harvard University. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Margo Seltzer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_dispatch.c 10.14 (Sleepycat) 5/3/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "db_dispatch.h"
|
||||
#include "db_am.h"
|
||||
#include "common_ext.h"
|
||||
#include "log_auto.h"
|
||||
#include "txn_auto.h"
|
||||
|
||||
/*
|
||||
* Data structures to manage the DB dispatch table. The dispatch table
|
||||
* is a dynamically allocated array of pointers to dispatch functions.
|
||||
* The dispatch_size is the number of entries possible in the current
|
||||
* dispatch table and the dispatch_valid is the number of valid entries
|
||||
* in the dispatch table.
|
||||
*/
|
||||
static int (**dispatch_table) __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
static u_int32_t dispatch_size = 0;
|
||||
|
||||
/*
|
||||
* __db_dispatch --
|
||||
*
|
||||
* This is the transaction dispatch function used by the db access methods.
|
||||
* It is designed to handle the record format used by all the access
|
||||
* methods (the one automatically generated by the db_{h,log,read}.sh
|
||||
* scripts in the tools directory). An application using a different
|
||||
* recovery paradigm will supply a different dispatch function to txn_open.
|
||||
*
|
||||
* PUBLIC: int __db_dispatch __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__db_dispatch(logp, db, lsnp, redo, info)
|
||||
DB_LOG *logp; /* The log file. */
|
||||
DBT *db; /* The log record upon which to dispatch. */
|
||||
DB_LSN *lsnp; /* The lsn of the record being dispatched. */
|
||||
int redo; /* Redo this op (or undo it). */
|
||||
void *info;
|
||||
{
|
||||
u_int32_t rectype, txnid;
|
||||
|
||||
memcpy(&rectype, db->data, sizeof(rectype));
|
||||
memcpy(&txnid, (u_int8_t *)db->data + sizeof(rectype), sizeof(txnid));
|
||||
|
||||
switch (redo) {
|
||||
case TXN_REDO:
|
||||
case TXN_UNDO:
|
||||
return ((dispatch_table[rectype])(logp, db, lsnp, redo, info));
|
||||
case TXN_OPENFILES:
|
||||
if (rectype < DB_txn_BEGIN )
|
||||
return ((dispatch_table[rectype])(logp,
|
||||
db, lsnp, redo, info));
|
||||
break;
|
||||
case TXN_BACKWARD_ROLL:
|
||||
/*
|
||||
* Running full recovery in the backward pass. If we've
|
||||
* seen this txnid before and added to it our commit list,
|
||||
* then we do nothing during this pass. If we've never
|
||||
* seen it, then we call the appropriate recovery routine
|
||||
* in "abort mode".
|
||||
*/
|
||||
if (rectype == DB_log_register || rectype == DB_txn_ckp ||
|
||||
__db_txnlist_find(info, txnid) == DB_NOTFOUND)
|
||||
return ((dispatch_table[rectype])(logp,
|
||||
db, lsnp, TXN_UNDO, info));
|
||||
break;
|
||||
case TXN_FORWARD_ROLL:
|
||||
/*
|
||||
* In the forward pass, if we haven't seen the transaction,
|
||||
* do nothing, else recovery it.
|
||||
*/
|
||||
if (rectype == DB_log_register || rectype == DB_txn_ckp ||
|
||||
__db_txnlist_find(info, txnid) != DB_NOTFOUND)
|
||||
return ((dispatch_table[rectype])(logp,
|
||||
db, lsnp, TXN_REDO, info));
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_add_recovery --
|
||||
*
|
||||
* PUBLIC: int __db_add_recovery __P((DB_ENV *,
|
||||
* PUBLIC: int (*)(DB_LOG *, DBT *, DB_LSN *, int, void *), u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_add_recovery(dbenv, func, ndx)
|
||||
DB_ENV *dbenv;
|
||||
int (*func) __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
u_int32_t ndx;
|
||||
{
|
||||
u_int32_t i;
|
||||
|
||||
/* Check if function is already registered. */
|
||||
if (dispatch_table && ndx < dispatch_size &&
|
||||
dispatch_table[ndx] != 0 && dispatch_table[ndx] != func)
|
||||
return (DB_REGISTERED);
|
||||
|
||||
/* Check if we have to grow the table. */
|
||||
if (ndx >= dispatch_size) {
|
||||
if (dispatch_table == NULL)
|
||||
dispatch_table = (int (**)
|
||||
__P((DB_LOG *, DBT *, DB_LSN *, int, void *)))
|
||||
__db_malloc(DB_user_BEGIN * sizeof(dispatch_table[0]));
|
||||
else
|
||||
dispatch_table = (int (**)
|
||||
__P((DB_LOG *, DBT *, DB_LSN *, int, void *)))
|
||||
__db_realloc(dispatch_table, (DB_user_BEGIN +
|
||||
dispatch_size) * sizeof(dispatch_table[0]));
|
||||
if (dispatch_table == NULL) {
|
||||
__db_err(dbenv, "%s", strerror(ENOMEM));
|
||||
return (ENOMEM);
|
||||
}
|
||||
for (i = dispatch_size,
|
||||
dispatch_size += DB_user_BEGIN; i < dispatch_size; ++i)
|
||||
dispatch_table[i] = NULL;
|
||||
}
|
||||
|
||||
dispatch_table[ndx] = func;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_txnlist_init --
|
||||
* Initialize transaction linked list.
|
||||
*
|
||||
* PUBLIC: int __db_txnlist_init __P((void *));
|
||||
*/
|
||||
int
|
||||
__db_txnlist_init(retp)
|
||||
void *retp;
|
||||
{
|
||||
DB_TXNHEAD *headp;
|
||||
|
||||
if ((headp = (DB_TXNHEAD *)__db_malloc(sizeof(DB_TXNHEAD))) == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
LIST_INIT(&headp->head);
|
||||
headp->maxid = 0;
|
||||
headp->generation = 1;
|
||||
|
||||
*(void **)retp = headp;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_txnlist_add --
|
||||
* Add an element to our transaction linked list.
|
||||
*
|
||||
* PUBLIC: int __db_txnlist_add __P((void *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_txnlist_add(listp, txnid)
|
||||
void *listp;
|
||||
u_int32_t txnid;
|
||||
{
|
||||
DB_TXNHEAD *hp;
|
||||
DB_TXNLIST *elp;
|
||||
|
||||
if ((elp = (DB_TXNLIST *)__db_malloc(sizeof(DB_TXNLIST))) == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
elp->txnid = txnid;
|
||||
hp = (DB_TXNHEAD *)listp;
|
||||
LIST_INSERT_HEAD(&hp->head, elp, links);
|
||||
if (txnid > hp->maxid)
|
||||
hp->maxid = txnid;
|
||||
elp->generation = hp->generation;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_txnlist_find --
|
||||
* Checks to see if a txnid with the current generation is in the
|
||||
* txnid list.
|
||||
*
|
||||
* PUBLIC: int __db_txnlist_find __P((void *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_txnlist_find(listp, txnid)
|
||||
void *listp;
|
||||
u_int32_t txnid;
|
||||
{
|
||||
DB_TXNHEAD *hp;
|
||||
DB_TXNLIST *p;
|
||||
|
||||
if ((hp = (DB_TXNHEAD *)listp) == NULL)
|
||||
return (DB_NOTFOUND);
|
||||
|
||||
for (p = hp->head.lh_first; p != NULL; p = p->links.le_next)
|
||||
if (p->txnid == txnid && hp->generation == p->generation)
|
||||
return (0);
|
||||
|
||||
return (DB_NOTFOUND);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_txnlist_end --
|
||||
* Discard transaction linked list.
|
||||
*
|
||||
* PUBLIC: void __db_txnlist_end __P((void *));
|
||||
*/
|
||||
void
|
||||
__db_txnlist_end(listp)
|
||||
void *listp;
|
||||
{
|
||||
DB_TXNHEAD *hp;
|
||||
DB_TXNLIST *p;
|
||||
|
||||
hp = (DB_TXNHEAD *)listp;
|
||||
while ((p = LIST_FIRST(&hp->head)) != LIST_END(&hp->head)) {
|
||||
LIST_REMOVE(p, links);
|
||||
__db_free(p);
|
||||
}
|
||||
__db_free(listp);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_txnlist_gen --
|
||||
* Change the current generation number.
|
||||
*
|
||||
* PUBLIC: void __db_txnlist_gen __P((void *, int));
|
||||
*/
|
||||
void
|
||||
__db_txnlist_gen(listp, incr)
|
||||
void *listp;
|
||||
int incr;
|
||||
{
|
||||
DB_TXNHEAD *hp;
|
||||
|
||||
/*
|
||||
* During recovery generation numbers keep track of how many "restart"
|
||||
* checkpoints we've seen. Restart checkpoints occur whenever we take
|
||||
* a checkpoint and there are no outstanding transactions. When that
|
||||
* happens, we can reset transaction IDs back to 1. It always happens
|
||||
* at recovery and it prevents us from exhausting the transaction IDs
|
||||
* name space.
|
||||
*/
|
||||
hp = (DB_TXNHEAD *)listp;
|
||||
hp->generation += incr;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* __db_txnlist_print --
|
||||
* Print out the transaction list.
|
||||
*
|
||||
* PUBLIC: void __db_txnlist_print __P((void *));
|
||||
*/
|
||||
void
|
||||
__db_txnlist_print(listp)
|
||||
void *listp;
|
||||
{
|
||||
DB_TXNHEAD *hp;
|
||||
DB_TXNLIST *p;
|
||||
|
||||
hp = (DB_TXNHEAD *)listp;
|
||||
printf("Maxid: %lu Generation: %lu\n", (u_long)hp->maxid,
|
||||
(u_long)hp->generation);
|
||||
for (p = hp->head.lh_first; p != NULL; p = p->links.le_next)
|
||||
printf("TXNID: %lu(%lu)\n", (u_long)p->txnid,
|
||||
(u_long)p->generation);
|
||||
}
|
||||
#endif
|
668
db/db/db_dup.c
668
db/db/db_dup.c
|
@ -1,668 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_dup.c 10.18 (Sleepycat) 5/31/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "btree.h"
|
||||
#include "db_am.h"
|
||||
|
||||
static int __db_addpage __P((DB *,
|
||||
PAGE **, db_indx_t *, int (*)(DB *, u_int32_t, PAGE **)));
|
||||
static int __db_dsplit __P((DB *,
|
||||
PAGE **, db_indx_t *, u_int32_t, int (*)(DB *, u_int32_t, PAGE **)));
|
||||
|
||||
/*
|
||||
* __db_dput --
|
||||
* Put a duplicate item onto a duplicate page at the given index.
|
||||
*
|
||||
* PUBLIC: int __db_dput __P((DB *,
|
||||
* PUBLIC: DBT *, PAGE **, db_indx_t *, int (*)(DB *, u_int32_t, PAGE **)));
|
||||
*/
|
||||
int
|
||||
__db_dput(dbp, dbt, pp, indxp, newfunc)
|
||||
DB *dbp;
|
||||
DBT *dbt;
|
||||
PAGE **pp;
|
||||
db_indx_t *indxp;
|
||||
int (*newfunc) __P((DB *, u_int32_t, PAGE **));
|
||||
{
|
||||
BOVERFLOW bo;
|
||||
DBT *data_dbtp, hdr_dbt, *hdr_dbtp;
|
||||
PAGE *pagep;
|
||||
db_indx_t size, isize;
|
||||
db_pgno_t pgno;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* We need some access method independent threshold for when we put
|
||||
* a duplicate item onto an overflow page.
|
||||
*/
|
||||
if (dbt->size > 0.25 * dbp->pgsize) {
|
||||
if ((ret = __db_poff(dbp, dbt, &pgno, newfunc)) != 0)
|
||||
return (ret);
|
||||
B_TSET(bo.type, B_OVERFLOW, 0);
|
||||
bo.tlen = dbt->size;
|
||||
bo.pgno = pgno;
|
||||
hdr_dbt.data = &bo;
|
||||
hdr_dbt.size = isize = BOVERFLOW_SIZE;
|
||||
hdr_dbtp = &hdr_dbt;
|
||||
size = BOVERFLOW_PSIZE;
|
||||
data_dbtp = NULL;
|
||||
} else {
|
||||
size = BKEYDATA_PSIZE(dbt->size);
|
||||
isize = BKEYDATA_SIZE(dbt->size);
|
||||
hdr_dbtp = NULL;
|
||||
data_dbtp = dbt;
|
||||
}
|
||||
|
||||
pagep = *pp;
|
||||
if (size > P_FREESPACE(pagep)) {
|
||||
if (*indxp == NUM_ENT(*pp) && NEXT_PGNO(*pp) == PGNO_INVALID)
|
||||
ret = __db_addpage(dbp, pp, indxp, newfunc);
|
||||
else
|
||||
ret = __db_dsplit(dbp, pp, indxp, isize, newfunc);
|
||||
if (ret != 0)
|
||||
/* XXX: Pages not returned to free list. */
|
||||
return (ret);
|
||||
pagep = *pp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, pagep references the page on which to insert and indx is the
|
||||
* the location to insert.
|
||||
*/
|
||||
if ((ret = __db_pitem(dbp,
|
||||
pagep, (u_int32_t)*indxp, isize, hdr_dbtp, data_dbtp)) != 0)
|
||||
return (ret);
|
||||
|
||||
(void)memp_fset(dbp->mpf, pagep, DB_MPOOL_DIRTY);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_drem --
|
||||
* Remove a duplicate at the given index on the given page.
|
||||
*
|
||||
* PUBLIC: int __db_drem __P((DB *,
|
||||
* PUBLIC: PAGE **, u_int32_t, int (*)(DB *, PAGE *)));
|
||||
*/
|
||||
int
|
||||
__db_drem(dbp, pp, indx, freefunc)
|
||||
DB *dbp;
|
||||
PAGE **pp;
|
||||
u_int32_t indx;
|
||||
int (*freefunc) __P((DB *, PAGE *));
|
||||
{
|
||||
PAGE *pagep;
|
||||
int ret;
|
||||
|
||||
pagep = *pp;
|
||||
|
||||
/* Check if we are freeing a big item. */
|
||||
if (B_TYPE(GET_BKEYDATA(pagep, indx)->type) == B_OVERFLOW) {
|
||||
if ((ret = __db_doff(dbp,
|
||||
GET_BOVERFLOW(pagep, indx)->pgno, freefunc)) != 0)
|
||||
return (ret);
|
||||
ret = __db_ditem(dbp, pagep, indx, BOVERFLOW_SIZE);
|
||||
} else
|
||||
ret = __db_ditem(dbp, pagep, indx,
|
||||
BKEYDATA_SIZE(GET_BKEYDATA(pagep, indx)->len));
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
if (NUM_ENT(pagep) == 0) {
|
||||
/*
|
||||
* If the page is emptied, then the page is freed and the pp
|
||||
* parameter is set to reference the next, locked page in the
|
||||
* duplicate chain, if one exists. If there was no such page,
|
||||
* then it is set to NULL.
|
||||
*
|
||||
* !!!
|
||||
* __db_relink will set the dirty bit for us.
|
||||
*/
|
||||
if ((ret = __db_relink(dbp, pagep, pp, 0)) != 0)
|
||||
return (ret);
|
||||
if ((ret = freefunc(dbp, pagep)) != 0)
|
||||
return (ret);
|
||||
} else
|
||||
(void)memp_fset(dbp->mpf, pagep, DB_MPOOL_DIRTY);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_dend --
|
||||
* Find the last page in a set of offpage duplicates.
|
||||
*
|
||||
* PUBLIC: int __db_dend __P((DB *, db_pgno_t, PAGE **));
|
||||
*/
|
||||
int
|
||||
__db_dend(dbp, pgno, pagep)
|
||||
DB *dbp;
|
||||
db_pgno_t pgno;
|
||||
PAGE **pagep;
|
||||
{
|
||||
PAGE *h;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* This implements DB_KEYLAST. The last page is returned in pp; pgno
|
||||
* should be the page number of the first page of the duplicate chain.
|
||||
*/
|
||||
for (;;) {
|
||||
if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
|
||||
(void)__db_pgerr(dbp, pgno);
|
||||
return (ret);
|
||||
}
|
||||
if ((pgno = NEXT_PGNO(h)) == PGNO_INVALID)
|
||||
break;
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
}
|
||||
|
||||
*pagep = h;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_dsplit --
|
||||
* Split a page of duplicates, calculating the split point based
|
||||
* on an element of size "size" being added at "*indxp".
|
||||
* On entry hp contains a pointer to the page-pointer of the original
|
||||
* page. On exit, it returns a pointer to the page containing "*indxp"
|
||||
* and "indxp" has been modified to reflect the index on the new page
|
||||
* where the element should be added. The function returns with
|
||||
* the page on which the insert should happen, not yet put.
|
||||
*/
|
||||
static int
|
||||
__db_dsplit(dbp, hp, indxp, size, newfunc)
|
||||
DB *dbp;
|
||||
PAGE **hp;
|
||||
db_indx_t *indxp;
|
||||
u_int32_t size;
|
||||
int (*newfunc) __P((DB *, u_int32_t, PAGE **));
|
||||
{
|
||||
PAGE *h, *np, *tp;
|
||||
BKEYDATA *bk;
|
||||
DBT page_dbt;
|
||||
db_indx_t halfbytes, i, indx, lastsum, nindex, oindex, s, sum;
|
||||
int did_indx, ret;
|
||||
|
||||
h = *hp;
|
||||
indx = *indxp;
|
||||
|
||||
/* Create a temporary page to do compaction onto. */
|
||||
if ((tp = (PAGE *)__db_malloc(dbp->pgsize)) == NULL)
|
||||
return (ENOMEM);
|
||||
#ifdef DIAGNOSTIC
|
||||
memset(tp, 0xff, dbp->pgsize);
|
||||
#endif
|
||||
/* Create new page for the split. */
|
||||
if ((ret = newfunc(dbp, P_DUPLICATE, &np)) != 0) {
|
||||
FREE(tp, dbp->pgsize);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
P_INIT(np, dbp->pgsize, PGNO(np), PGNO(h), NEXT_PGNO(h), 0,
|
||||
P_DUPLICATE);
|
||||
P_INIT(tp, dbp->pgsize, PGNO(h), PREV_PGNO(h), PGNO(np), 0,
|
||||
P_DUPLICATE);
|
||||
|
||||
/* Figure out the split point */
|
||||
halfbytes = (dbp->pgsize - HOFFSET(h)) / 2;
|
||||
did_indx = 0;
|
||||
for (sum = 0, lastsum = 0, i = 0; i < NUM_ENT(h); i++) {
|
||||
if (i == indx) {
|
||||
sum += size;
|
||||
did_indx = 1;
|
||||
if (lastsum < halfbytes && sum >= halfbytes) {
|
||||
/* We've crossed the halfway point. */
|
||||
if ((db_indx_t)(halfbytes - lastsum) <
|
||||
(db_indx_t)(sum - halfbytes)) {
|
||||
*hp = np;
|
||||
*indxp = 0;
|
||||
i--;
|
||||
} else
|
||||
*indxp = i;
|
||||
break;
|
||||
}
|
||||
*indxp = i;
|
||||
lastsum = sum;
|
||||
}
|
||||
if (B_TYPE(GET_BKEYDATA(h, i)->type) == B_KEYDATA)
|
||||
sum += BKEYDATA_SIZE(GET_BKEYDATA(h, i)->len);
|
||||
else
|
||||
sum += BOVERFLOW_SIZE;
|
||||
|
||||
if (lastsum < halfbytes && sum >= halfbytes) {
|
||||
/* We've crossed the halfway point. */
|
||||
if ((db_indx_t)(halfbytes - lastsum) <
|
||||
(db_indx_t)(sum - halfbytes))
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we have set the return values of the index pointer and
|
||||
* page pointer.
|
||||
*/
|
||||
if (!did_indx) {
|
||||
*hp = np;
|
||||
*indxp = indx - i - 1;
|
||||
}
|
||||
|
||||
if (DB_LOGGING(dbp)) {
|
||||
page_dbt.size = dbp->pgsize;
|
||||
page_dbt.data = h;
|
||||
if ((ret = __db_split_log(dbp->dbenv->lg_info,
|
||||
dbp->txn, &LSN(h), 0, DB_SPLITOLD, dbp->log_fileid,
|
||||
PGNO(h), &page_dbt, &LSN(h))) != 0) {
|
||||
FREE(tp, dbp->pgsize);
|
||||
return (ret);
|
||||
}
|
||||
LSN(tp) = LSN(h);
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's a btree, adjust the cursors.
|
||||
*
|
||||
* i is the index of the last element to stay on the page.
|
||||
*/
|
||||
if (dbp->type == DB_BTREE || dbp->type == DB_RECNO)
|
||||
__bam_ca_split(dbp, PGNO(h), PGNO(h), PGNO(np), i + 1, 0);
|
||||
|
||||
for (nindex = 0, oindex = i + 1; oindex < NUM_ENT(h); oindex++) {
|
||||
bk = GET_BKEYDATA(h, oindex);
|
||||
if (B_TYPE(bk->type) == B_KEYDATA)
|
||||
s = BKEYDATA_SIZE(bk->len);
|
||||
else
|
||||
s = BOVERFLOW_SIZE;
|
||||
|
||||
np->inp[nindex++] = HOFFSET(np) -= s;
|
||||
memcpy((u_int8_t *)np + HOFFSET(np), bk, s);
|
||||
NUM_ENT(np)++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now do data compaction by copying the remaining stuff onto the
|
||||
* temporary page and then copying it back to the real page.
|
||||
*/
|
||||
for (nindex = 0, oindex = 0; oindex <= i; oindex++) {
|
||||
bk = GET_BKEYDATA(h, oindex);
|
||||
if (B_TYPE(bk->type) == B_KEYDATA)
|
||||
s = BKEYDATA_SIZE(bk->len);
|
||||
else
|
||||
s = BOVERFLOW_SIZE;
|
||||
|
||||
tp->inp[nindex++] = HOFFSET(tp) -= s;
|
||||
memcpy((u_int8_t *)tp + HOFFSET(tp), bk, s);
|
||||
NUM_ENT(tp)++;
|
||||
}
|
||||
|
||||
/*
|
||||
* This page (the temporary) should be only half full, so we do two
|
||||
* memcpy's, one for the top of the page and one for the bottom of
|
||||
* the page. This way we avoid copying the middle which should be
|
||||
* about half a page.
|
||||
*/
|
||||
memcpy(h, tp, LOFFSET(tp));
|
||||
memcpy((u_int8_t *)h + HOFFSET(tp),
|
||||
(u_int8_t *)tp + HOFFSET(tp), dbp->pgsize - HOFFSET(tp));
|
||||
FREE(tp, dbp->pgsize);
|
||||
|
||||
if (DB_LOGGING(dbp)) {
|
||||
page_dbt.size = dbp->pgsize;
|
||||
page_dbt.data = h;
|
||||
if ((ret = __db_split_log(dbp->dbenv->lg_info,
|
||||
dbp->txn, &LSN(h), 0, DB_SPLITNEW, dbp->log_fileid,
|
||||
PGNO(h), &page_dbt, &LSN(h))) != 0)
|
||||
return (ret);
|
||||
|
||||
page_dbt.size = dbp->pgsize;
|
||||
page_dbt.data = np;
|
||||
if ((ret = __db_split_log(dbp->dbenv->lg_info,
|
||||
dbp->txn, &LSN(np), 0, DB_SPLITNEW, dbp->log_fileid,
|
||||
PGNO(np), &page_dbt, &LSN(np))) != 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out if the location we're interested in is on the new
|
||||
* page, and if so, reset the callers' pointer. Push the other
|
||||
* page back to the store.
|
||||
*/
|
||||
if (*hp == h)
|
||||
ret = memp_fput(dbp->mpf, np, DB_MPOOL_DIRTY);
|
||||
else
|
||||
ret = memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_ditem --
|
||||
* Remove an item from a page.
|
||||
*
|
||||
* PUBLIC: int __db_ditem __P((DB *, PAGE *, u_int32_t, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_ditem(dbp, pagep, indx, nbytes)
|
||||
DB *dbp;
|
||||
PAGE *pagep;
|
||||
u_int32_t indx, nbytes;
|
||||
{
|
||||
DBT ldbt;
|
||||
db_indx_t cnt, offset;
|
||||
int ret;
|
||||
u_int8_t *from;
|
||||
|
||||
if (DB_LOGGING(dbp)) {
|
||||
ldbt.data = P_ENTRY(pagep, indx);
|
||||
ldbt.size = nbytes;
|
||||
if ((ret = __db_addrem_log(dbp->dbenv->lg_info, dbp->txn,
|
||||
&LSN(pagep), 0, DB_REM_DUP, dbp->log_fileid, PGNO(pagep),
|
||||
(u_int32_t)indx, nbytes, &ldbt, NULL, &LSN(pagep))) != 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's only a single item on the page, we don't have to
|
||||
* work hard.
|
||||
*/
|
||||
if (NUM_ENT(pagep) == 1) {
|
||||
NUM_ENT(pagep) = 0;
|
||||
HOFFSET(pagep) = dbp->pgsize;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pack the remaining key/data items at the end of the page. Use
|
||||
* memmove(3), the regions may overlap.
|
||||
*/
|
||||
from = (u_int8_t *)pagep + HOFFSET(pagep);
|
||||
memmove(from + nbytes, from, pagep->inp[indx] - HOFFSET(pagep));
|
||||
HOFFSET(pagep) += nbytes;
|
||||
|
||||
/* Adjust the indices' offsets. */
|
||||
offset = pagep->inp[indx];
|
||||
for (cnt = 0; cnt < NUM_ENT(pagep); ++cnt)
|
||||
if (pagep->inp[cnt] < offset)
|
||||
pagep->inp[cnt] += nbytes;
|
||||
|
||||
/* Shift the indices down. */
|
||||
--NUM_ENT(pagep);
|
||||
if (indx != NUM_ENT(pagep))
|
||||
memmove(&pagep->inp[indx], &pagep->inp[indx + 1],
|
||||
sizeof(db_indx_t) * (NUM_ENT(pagep) - indx));
|
||||
|
||||
/* If it's a btree, adjust the cursors. */
|
||||
if (dbp->type == DB_BTREE || dbp->type == DB_RECNO)
|
||||
__bam_ca_di(dbp, PGNO(pagep), indx, -1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_pitem --
|
||||
* Put an item on a page.
|
||||
*
|
||||
* PUBLIC: int __db_pitem
|
||||
* PUBLIC: __P((DB *, PAGE *, u_int32_t, u_int32_t, DBT *, DBT *));
|
||||
*/
|
||||
int
|
||||
__db_pitem(dbp, pagep, indx, nbytes, hdr, data)
|
||||
DB *dbp;
|
||||
PAGE *pagep;
|
||||
u_int32_t indx;
|
||||
u_int32_t nbytes;
|
||||
DBT *hdr, *data;
|
||||
{
|
||||
BKEYDATA bk;
|
||||
DBT thdr;
|
||||
int ret;
|
||||
u_int8_t *p;
|
||||
|
||||
/*
|
||||
* Put a single item onto a page. The logic figuring out where to
|
||||
* insert and whether it fits is handled in the caller. All we do
|
||||
* here is manage the page shuffling. We cheat a little bit in that
|
||||
* we don't want to copy the dbt on a normal put twice. If hdr is
|
||||
* NULL, we create a BKEYDATA structure on the page, otherwise, just
|
||||
* copy the caller's information onto the page.
|
||||
*
|
||||
* This routine is also used to put entries onto the page where the
|
||||
* entry is pre-built, e.g., during recovery. In this case, the hdr
|
||||
* will point to the entry, and the data argument will be NULL.
|
||||
*
|
||||
* !!!
|
||||
* There's a tremendous potential for off-by-one errors here, since
|
||||
* the passed in header sizes must be adjusted for the structure's
|
||||
* placeholder for the trailing variable-length data field.
|
||||
*/
|
||||
if (DB_LOGGING(dbp))
|
||||
if ((ret = __db_addrem_log(dbp->dbenv->lg_info, dbp->txn,
|
||||
&LSN(pagep), 0, DB_ADD_DUP, dbp->log_fileid, PGNO(pagep),
|
||||
(u_int32_t)indx, nbytes, hdr, data, &LSN(pagep))) != 0)
|
||||
return (ret);
|
||||
|
||||
if (hdr == NULL) {
|
||||
B_TSET(bk.type, B_KEYDATA, 0);
|
||||
bk.len = data == NULL ? 0 : data->size;
|
||||
|
||||
thdr.data = &bk;
|
||||
thdr.size = SSZA(BKEYDATA, data);
|
||||
hdr = &thdr;
|
||||
}
|
||||
|
||||
/* Adjust the index table, then put the item on the page. */
|
||||
if (indx != NUM_ENT(pagep))
|
||||
memmove(&pagep->inp[indx + 1], &pagep->inp[indx],
|
||||
sizeof(db_indx_t) * (NUM_ENT(pagep) - indx));
|
||||
HOFFSET(pagep) -= nbytes;
|
||||
pagep->inp[indx] = HOFFSET(pagep);
|
||||
++NUM_ENT(pagep);
|
||||
|
||||
p = P_ENTRY(pagep, indx);
|
||||
memcpy(p, hdr->data, hdr->size);
|
||||
if (data != NULL)
|
||||
memcpy(p + hdr->size, data->data, data->size);
|
||||
|
||||
/* If it's a btree, adjust the cursors. */
|
||||
if (dbp->type == DB_BTREE || dbp->type == DB_RECNO)
|
||||
__bam_ca_di(dbp, PGNO(pagep), indx, 1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_relink --
|
||||
* Relink around a deleted page.
|
||||
*
|
||||
* PUBLIC: int __db_relink __P((DB *, PAGE *, PAGE **, int));
|
||||
*/
|
||||
int
|
||||
__db_relink(dbp, pagep, new_next, needlock)
|
||||
DB *dbp;
|
||||
PAGE *pagep, **new_next;
|
||||
int needlock;
|
||||
{
|
||||
PAGE *np, *pp;
|
||||
DB_LOCK npl, ppl;
|
||||
DB_LSN *nlsnp, *plsnp;
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
np = pp = NULL;
|
||||
npl = ppl = LOCK_INVALID;
|
||||
nlsnp = plsnp = NULL;
|
||||
|
||||
/* Retrieve and lock the two pages. */
|
||||
if (pagep->next_pgno != PGNO_INVALID) {
|
||||
if (needlock && (ret = __bam_lget(dbp,
|
||||
0, pagep->next_pgno, DB_LOCK_WRITE, &npl)) != 0)
|
||||
goto err;
|
||||
if ((ret = memp_fget(dbp->mpf,
|
||||
&pagep->next_pgno, 0, &np)) != 0) {
|
||||
(void)__db_pgerr(dbp, pagep->next_pgno);
|
||||
goto err;
|
||||
}
|
||||
nlsnp = &np->lsn;
|
||||
}
|
||||
if (pagep->prev_pgno != PGNO_INVALID) {
|
||||
if (needlock && (ret = __bam_lget(dbp,
|
||||
0, pagep->prev_pgno, DB_LOCK_WRITE, &ppl)) != 0)
|
||||
goto err;
|
||||
if ((ret = memp_fget(dbp->mpf,
|
||||
&pagep->prev_pgno, 0, &pp)) != 0) {
|
||||
(void)__db_pgerr(dbp, pagep->next_pgno);
|
||||
goto err;
|
||||
}
|
||||
plsnp = &pp->lsn;
|
||||
}
|
||||
|
||||
/* Log the change. */
|
||||
if (DB_LOGGING(dbp)) {
|
||||
if ((ret = __db_relink_log(dbp->dbenv->lg_info, dbp->txn,
|
||||
&pagep->lsn, 0, dbp->log_fileid, pagep->pgno, &pagep->lsn,
|
||||
pagep->prev_pgno, plsnp, pagep->next_pgno, nlsnp)) != 0)
|
||||
goto err;
|
||||
if (np != NULL)
|
||||
np->lsn = pagep->lsn;
|
||||
if (pp != NULL)
|
||||
pp->lsn = pagep->lsn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Modify and release the two pages.
|
||||
*
|
||||
* !!!
|
||||
* The parameter new_next gets set to the page following the page we
|
||||
* are removing. If there is no following page, then new_next gets
|
||||
* set to NULL.
|
||||
*/
|
||||
if (np != NULL) {
|
||||
np->prev_pgno = pagep->prev_pgno;
|
||||
if (new_next == NULL)
|
||||
ret = memp_fput(dbp->mpf, np, DB_MPOOL_DIRTY);
|
||||
else {
|
||||
*new_next = np;
|
||||
ret = memp_fset(dbp->mpf, np, DB_MPOOL_DIRTY);
|
||||
}
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
if (needlock)
|
||||
(void)__bam_lput(dbp, npl);
|
||||
} else if (new_next != NULL)
|
||||
*new_next = NULL;
|
||||
|
||||
if (pp != NULL) {
|
||||
pp->next_pgno = pagep->next_pgno;
|
||||
if ((ret = memp_fput(dbp->mpf, pp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto err;
|
||||
if (needlock)
|
||||
(void)__bam_lput(dbp, ppl);
|
||||
}
|
||||
return (0);
|
||||
|
||||
err: if (np != NULL)
|
||||
(void)memp_fput(dbp->mpf, np, 0);
|
||||
if (needlock && npl != LOCK_INVALID)
|
||||
(void)__bam_lput(dbp, npl);
|
||||
if (pp != NULL)
|
||||
(void)memp_fput(dbp->mpf, pp, 0);
|
||||
if (needlock && ppl != LOCK_INVALID)
|
||||
(void)__bam_lput(dbp, ppl);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_ddup --
|
||||
* Delete an offpage chain of duplicates.
|
||||
*
|
||||
* PUBLIC: int __db_ddup __P((DB *, db_pgno_t, int (*)(DB *, PAGE *)));
|
||||
*/
|
||||
int
|
||||
__db_ddup(dbp, pgno, freefunc)
|
||||
DB *dbp;
|
||||
db_pgno_t pgno;
|
||||
int (*freefunc) __P((DB *, PAGE *));
|
||||
{
|
||||
PAGE *pagep;
|
||||
DBT tmp_dbt;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
if ((ret = memp_fget(dbp->mpf, &pgno, 0, &pagep)) != 0) {
|
||||
(void)__db_pgerr(dbp, pgno);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if (DB_LOGGING(dbp)) {
|
||||
tmp_dbt.data = pagep;
|
||||
tmp_dbt.size = dbp->pgsize;
|
||||
if ((ret = __db_split_log(dbp->dbenv->lg_info, dbp->txn,
|
||||
&LSN(pagep), 0, DB_SPLITOLD, dbp->log_fileid,
|
||||
PGNO(pagep), &tmp_dbt, &LSN(pagep))) != 0)
|
||||
return (ret);
|
||||
}
|
||||
pgno = pagep->next_pgno;
|
||||
if ((ret = freefunc(dbp, pagep)) != 0)
|
||||
return (ret);
|
||||
} while (pgno != PGNO_INVALID);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_addpage --
|
||||
* Create a new page and link it onto the next_pgno field of the
|
||||
* current page.
|
||||
*/
|
||||
static int
|
||||
__db_addpage(dbp, hp, indxp, newfunc)
|
||||
DB *dbp;
|
||||
PAGE **hp;
|
||||
db_indx_t *indxp;
|
||||
int (*newfunc) __P((DB *, u_int32_t, PAGE **));
|
||||
{
|
||||
PAGE *newpage;
|
||||
int ret;
|
||||
|
||||
if ((ret = newfunc(dbp, P_DUPLICATE, &newpage)) != 0)
|
||||
return (ret);
|
||||
|
||||
if (DB_LOGGING(dbp)) {
|
||||
if ((ret = __db_addpage_log(dbp->dbenv->lg_info,
|
||||
dbp->txn, &LSN(*hp), 0, dbp->log_fileid,
|
||||
PGNO(*hp), &LSN(*hp), PGNO(newpage), &LSN(newpage))) != 0) {
|
||||
return (ret);
|
||||
}
|
||||
LSN(newpage) = LSN(*hp);
|
||||
}
|
||||
|
||||
PREV_PGNO(newpage) = PGNO(*hp);
|
||||
NEXT_PGNO(*hp) = PGNO(newpage);
|
||||
|
||||
if ((ret = memp_fput(dbp->mpf, *hp, DB_MPOOL_DIRTY)) != 0)
|
||||
return (ret);
|
||||
*hp = newpage;
|
||||
*indxp = 0;
|
||||
return (0);
|
||||
}
|
|
@ -1,382 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Mike Olson.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_overflow.c 10.11 (Sleepycat) 5/7/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "db_am.h"
|
||||
|
||||
/*
|
||||
* Big key/data code.
|
||||
*
|
||||
* Big key and data entries are stored on linked lists of pages. The initial
|
||||
* reference is a structure with the total length of the item and the page
|
||||
* number where it begins. Each entry in the linked list contains a pointer
|
||||
* to the next page of data, and so on.
|
||||
*/
|
||||
|
||||
/*
|
||||
* __db_goff --
|
||||
* Get an offpage item.
|
||||
*
|
||||
* PUBLIC: int __db_goff __P((DB *, DBT *,
|
||||
* PUBLIC: u_int32_t, db_pgno_t, void **, u_int32_t *));
|
||||
*/
|
||||
int
|
||||
__db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
|
||||
DB *dbp;
|
||||
DBT *dbt;
|
||||
u_int32_t tlen;
|
||||
db_pgno_t pgno;
|
||||
void **bpp;
|
||||
u_int32_t *bpsz;
|
||||
{
|
||||
PAGE *h;
|
||||
db_indx_t bytes;
|
||||
u_int32_t curoff, needed, start;
|
||||
u_int8_t *p, *src;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Check if the buffer is big enough; if it is not and we are
|
||||
* allowed to malloc space, then we'll malloc it. If we are
|
||||
* not (DB_DBT_USERMEM), then we'll set the dbt and return
|
||||
* appropriately.
|
||||
*/
|
||||
if (F_ISSET(dbt, DB_DBT_PARTIAL)) {
|
||||
start = dbt->doff;
|
||||
needed = dbt->dlen;
|
||||
} else {
|
||||
start = 0;
|
||||
needed = tlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate any necessary memory.
|
||||
*
|
||||
* XXX: Never allocate 0 bytes;
|
||||
*/
|
||||
if (F_ISSET(dbt, DB_DBT_USERMEM)) {
|
||||
if (needed > dbt->ulen) {
|
||||
dbt->size = needed;
|
||||
return (ENOMEM);
|
||||
}
|
||||
} else if (F_ISSET(dbt, DB_DBT_MALLOC)) {
|
||||
dbt->data = dbp->db_malloc == NULL ?
|
||||
(void *)__db_malloc(needed + 1) :
|
||||
(void *)dbp->db_malloc(needed + 1);
|
||||
if (dbt->data == NULL)
|
||||
return (ENOMEM);
|
||||
} else if (*bpsz == 0 || *bpsz < needed) {
|
||||
*bpp = (*bpp == NULL ?
|
||||
(void *)__db_malloc(needed + 1) :
|
||||
(void *)__db_realloc(*bpp, needed + 1));
|
||||
if (*bpp == NULL)
|
||||
return (ENOMEM);
|
||||
*bpsz = needed + 1;
|
||||
dbt->data = *bpp;
|
||||
} else
|
||||
dbt->data = *bpp;
|
||||
|
||||
/*
|
||||
* Step through the linked list of pages, copying the data on each
|
||||
* one into the buffer. Never copy more than the total data length.
|
||||
*/
|
||||
dbt->size = needed;
|
||||
for (curoff = 0, p = dbt->data; pgno != P_INVALID && needed > 0;) {
|
||||
if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
|
||||
(void)__db_pgerr(dbp, pgno);
|
||||
return (ret);
|
||||
}
|
||||
/* Check if we need any bytes from this page. */
|
||||
if (curoff + OV_LEN(h) >= start) {
|
||||
src = (u_int8_t *)h + P_OVERHEAD;
|
||||
bytes = OV_LEN(h);
|
||||
if (start > curoff) {
|
||||
src += start - curoff;
|
||||
bytes -= start - curoff;
|
||||
}
|
||||
if (bytes > needed)
|
||||
bytes = needed;
|
||||
memcpy(p, src, bytes);
|
||||
p += bytes;
|
||||
needed -= bytes;
|
||||
}
|
||||
curoff += OV_LEN(h);
|
||||
pgno = h->next_pgno;
|
||||
memp_fput(dbp->mpf, h, 0);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_poff --
|
||||
* Put an offpage item.
|
||||
*
|
||||
* PUBLIC: int __db_poff __P((DB *, const DBT *, db_pgno_t *,
|
||||
* PUBLIC: int (*)(DB *, u_int32_t, PAGE **)));
|
||||
*/
|
||||
int
|
||||
__db_poff(dbp, dbt, pgnop, newfunc)
|
||||
DB *dbp;
|
||||
const DBT *dbt;
|
||||
db_pgno_t *pgnop;
|
||||
int (*newfunc) __P((DB *, u_int32_t, PAGE **));
|
||||
{
|
||||
PAGE *pagep, *lastp;
|
||||
DB_LSN new_lsn, null_lsn;
|
||||
DBT tmp_dbt;
|
||||
db_indx_t pagespace;
|
||||
u_int32_t sz;
|
||||
u_int8_t *p;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Allocate pages and copy the key/data item into them. Calculate the
|
||||
* number of bytes we get for pages we fill completely with a single
|
||||
* item.
|
||||
*/
|
||||
pagespace = P_MAXSPACE(dbp->pgsize);
|
||||
|
||||
lastp = NULL;
|
||||
for (p = dbt->data,
|
||||
sz = dbt->size; sz > 0; p += pagespace, sz -= pagespace) {
|
||||
/*
|
||||
* Reduce pagespace so we terminate the loop correctly and
|
||||
* don't copy too much data.
|
||||
*/
|
||||
if (sz < pagespace)
|
||||
pagespace = sz;
|
||||
|
||||
/*
|
||||
* Allocate and initialize a new page and copy all or part of
|
||||
* the item onto the page. If sz is less than pagespace, we
|
||||
* have a partial record.
|
||||
*/
|
||||
if ((ret = newfunc(dbp, P_OVERFLOW, &pagep)) != 0)
|
||||
return (ret);
|
||||
if (DB_LOGGING(dbp)) {
|
||||
tmp_dbt.data = p;
|
||||
tmp_dbt.size = pagespace;
|
||||
ZERO_LSN(null_lsn);
|
||||
if ((ret = __db_big_log(dbp->dbenv->lg_info, dbp->txn,
|
||||
&new_lsn, 0, DB_ADD_BIG, dbp->log_fileid,
|
||||
PGNO(pagep), lastp ? PGNO(lastp) : PGNO_INVALID,
|
||||
PGNO_INVALID, &tmp_dbt, &LSN(pagep),
|
||||
lastp == NULL ? &null_lsn : &LSN(lastp),
|
||||
&null_lsn)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Move lsn onto page. */
|
||||
if (lastp)
|
||||
LSN(lastp) = new_lsn;
|
||||
LSN(pagep) = new_lsn;
|
||||
}
|
||||
|
||||
P_INIT(pagep, dbp->pgsize,
|
||||
PGNO(pagep), PGNO_INVALID, PGNO_INVALID, 0, P_OVERFLOW);
|
||||
OV_LEN(pagep) = pagespace;
|
||||
OV_REF(pagep) = 1;
|
||||
memcpy((u_int8_t *)pagep + P_OVERHEAD, p, pagespace);
|
||||
|
||||
/*
|
||||
* If this is the first entry, update the user's info.
|
||||
* Otherwise, update the entry on the last page filled
|
||||
* in and release that page.
|
||||
*/
|
||||
if (lastp == NULL)
|
||||
*pgnop = PGNO(pagep);
|
||||
else {
|
||||
lastp->next_pgno = PGNO(pagep);
|
||||
pagep->prev_pgno = PGNO(lastp);
|
||||
(void)memp_fput(dbp->mpf, lastp, DB_MPOOL_DIRTY);
|
||||
}
|
||||
lastp = pagep;
|
||||
}
|
||||
(void)memp_fput(dbp->mpf, lastp, DB_MPOOL_DIRTY);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_ovref --
|
||||
* Increment/decrement the reference count on an overflow page.
|
||||
*
|
||||
* PUBLIC: int __db_ovref __P((DB *, db_pgno_t, int32_t));
|
||||
*/
|
||||
int
|
||||
__db_ovref(dbp, pgno, adjust)
|
||||
DB *dbp;
|
||||
db_pgno_t pgno;
|
||||
int32_t adjust;
|
||||
{
|
||||
PAGE *h;
|
||||
int ret;
|
||||
|
||||
if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
|
||||
(void)__db_pgerr(dbp, pgno);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if (DB_LOGGING(dbp))
|
||||
if ((ret = __db_ovref_log(dbp->dbenv->lg_info, dbp->txn,
|
||||
&LSN(h), 0, dbp->log_fileid, h->pgno, adjust,
|
||||
&LSN(h))) != 0)
|
||||
return (ret);
|
||||
OV_REF(h) += adjust;
|
||||
|
||||
(void)memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_doff --
|
||||
* Delete an offpage chain of overflow pages.
|
||||
*
|
||||
* PUBLIC: int __db_doff __P((DB *, db_pgno_t, int (*)(DB *, PAGE *)));
|
||||
*/
|
||||
int
|
||||
__db_doff(dbp, pgno, freefunc)
|
||||
DB *dbp;
|
||||
db_pgno_t pgno;
|
||||
int (*freefunc) __P((DB *, PAGE *));
|
||||
{
|
||||
PAGE *pagep;
|
||||
DB_LSN null_lsn;
|
||||
DBT tmp_dbt;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
if ((ret = memp_fget(dbp->mpf, &pgno, 0, &pagep)) != 0) {
|
||||
(void)__db_pgerr(dbp, pgno);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's an overflow page and it's referenced by more than
|
||||
* one key/data item, decrement the reference count and return.
|
||||
*/
|
||||
if (TYPE(pagep) == P_OVERFLOW && OV_REF(pagep) > 1) {
|
||||
(void)memp_fput(dbp->mpf, pagep, 0);
|
||||
return (__db_ovref(dbp, pgno, -1));
|
||||
}
|
||||
|
||||
if (DB_LOGGING(dbp)) {
|
||||
tmp_dbt.data = (u_int8_t *)pagep + P_OVERHEAD;
|
||||
tmp_dbt.size = OV_LEN(pagep);
|
||||
ZERO_LSN(null_lsn);
|
||||
if ((ret = __db_big_log(dbp->dbenv->lg_info, dbp->txn,
|
||||
&LSN(pagep), 0, DB_REM_BIG, dbp->log_fileid,
|
||||
PGNO(pagep), PREV_PGNO(pagep), NEXT_PGNO(pagep),
|
||||
&tmp_dbt, &LSN(pagep), &null_lsn, &null_lsn)) != 0)
|
||||
return (ret);
|
||||
}
|
||||
pgno = pagep->next_pgno;
|
||||
if ((ret = freefunc(dbp, pagep)) != 0)
|
||||
return (ret);
|
||||
} while (pgno != PGNO_INVALID);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_moff --
|
||||
* Match on overflow pages.
|
||||
*
|
||||
* Given a starting page number and a key, return <0, 0, >0 to indicate if the
|
||||
* key on the page is less than, equal to or greater than the key specified.
|
||||
*
|
||||
* PUBLIC: int __db_moff __P((DB *, const DBT *, db_pgno_t));
|
||||
*/
|
||||
int
|
||||
__db_moff(dbp, dbt, pgno)
|
||||
DB *dbp;
|
||||
const DBT *dbt;
|
||||
db_pgno_t pgno;
|
||||
{
|
||||
PAGE *pagep;
|
||||
u_int32_t cmp_bytes, key_left;
|
||||
u_int8_t *p1, *p2;
|
||||
int ret;
|
||||
|
||||
/* While there are both keys to compare. */
|
||||
for (ret = 0, p1 = dbt->data,
|
||||
key_left = dbt->size; key_left > 0 && pgno != PGNO_INVALID;) {
|
||||
if (memp_fget(dbp->mpf, &pgno, 0, &pagep) != 0) {
|
||||
(void)__db_pgerr(dbp, pgno);
|
||||
return (0); /* No system error return. */
|
||||
}
|
||||
|
||||
cmp_bytes = OV_LEN(pagep) < key_left ? OV_LEN(pagep) : key_left;
|
||||
key_left -= cmp_bytes;
|
||||
for (p2 =
|
||||
(u_int8_t *)pagep + P_OVERHEAD; cmp_bytes-- > 0; ++p1, ++p2)
|
||||
if (*p1 != *p2) {
|
||||
ret = (long)*p1 - (long)*p2;
|
||||
break;
|
||||
}
|
||||
pgno = NEXT_PGNO(pagep);
|
||||
(void)memp_fput(dbp->mpf, pagep, 0);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
}
|
||||
if (key_left > 0) /* DBT is longer than page key. */
|
||||
return (-1);
|
||||
if (pgno != PGNO_INVALID) /* DBT is shorter than page key. */
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
829
db/db/db_pr.c
829
db/db/db_pr.c
|
@ -1,829 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_pr.c 10.29 (Sleepycat) 5/23/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "btree.h"
|
||||
#include "hash.h"
|
||||
#include "db_am.h"
|
||||
|
||||
static void __db_proff __P((void *));
|
||||
static void __db_psize __P((DB_MPOOLFILE *));
|
||||
|
||||
/*
|
||||
* __db_loadme --
|
||||
* Force loading of this file.
|
||||
*
|
||||
* PUBLIC: void __db_loadme __P((void));
|
||||
*/
|
||||
void
|
||||
__db_loadme()
|
||||
{
|
||||
getpid();
|
||||
}
|
||||
|
||||
static FILE *set_fp;
|
||||
|
||||
/*
|
||||
* 64K is the maximum page size, so by default we check for offsets
|
||||
* larger than that, and, where possible, we refine the test.
|
||||
*/
|
||||
#define PSIZE_BOUNDARY (64 * 1024 + 1)
|
||||
static size_t set_psize = PSIZE_BOUNDARY;
|
||||
|
||||
/*
|
||||
* __db_prinit --
|
||||
* Initialize tree printing routines.
|
||||
*
|
||||
* PUBLIC: FILE *__db_prinit __P((FILE *));
|
||||
*/
|
||||
FILE *
|
||||
__db_prinit(fp)
|
||||
FILE *fp;
|
||||
{
|
||||
if (set_fp == NULL)
|
||||
set_fp = fp == NULL ? stdout : fp;
|
||||
return (set_fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_dump --
|
||||
* Dump the tree to a file.
|
||||
*
|
||||
* PUBLIC: int __db_dump __P((DB *, char *, int));
|
||||
*/
|
||||
int
|
||||
__db_dump(dbp, name, all)
|
||||
DB *dbp;
|
||||
char *name;
|
||||
int all;
|
||||
{
|
||||
FILE *fp, *save_fp;
|
||||
|
||||
COMPQUIET(save_fp, NULL);
|
||||
|
||||
if (set_psize == PSIZE_BOUNDARY)
|
||||
__db_psize(dbp->mpf);
|
||||
|
||||
if (name != NULL) {
|
||||
if ((fp = fopen(name, "w")) == NULL)
|
||||
return (errno);
|
||||
save_fp = set_fp;
|
||||
set_fp = fp;
|
||||
} else
|
||||
fp = __db_prinit(NULL);
|
||||
|
||||
(void)__db_prdb(dbp);
|
||||
if (dbp->type == DB_HASH)
|
||||
(void)__db_prhash(dbp);
|
||||
else
|
||||
(void)__db_prbtree(dbp);
|
||||
fprintf(fp, "%s\n", DB_LINE);
|
||||
__db_prtree(dbp->mpf, all);
|
||||
|
||||
if (name != NULL) {
|
||||
(void)fclose(fp);
|
||||
set_fp = save_fp;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_prdb --
|
||||
* Print out the DB structure information.
|
||||
*
|
||||
* PUBLIC: int __db_prdb __P((DB *));
|
||||
*/
|
||||
int
|
||||
__db_prdb(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
static const FN fn[] = {
|
||||
{ DB_AM_DUP, "duplicates" },
|
||||
{ DB_AM_INMEM, "in-memory" },
|
||||
{ DB_AM_LOCKING, "locking" },
|
||||
{ DB_AM_LOGGING, "logging" },
|
||||
{ DB_AM_MLOCAL, "local mpool" },
|
||||
{ DB_AM_PGDEF, "default page size" },
|
||||
{ DB_AM_RDONLY, "read-only" },
|
||||
{ DB_AM_RECOVER, "recover" },
|
||||
{ DB_AM_SWAP, "needswap" },
|
||||
{ DB_AM_THREAD, "thread" },
|
||||
{ DB_BT_RECNUM, "btree:records" },
|
||||
{ DB_HS_DIRTYMETA, "hash:dirty-meta" },
|
||||
{ DB_RE_DELIMITER, "recno:delimiter" },
|
||||
{ DB_RE_FIXEDLEN, "recno:fixed-length" },
|
||||
{ DB_RE_PAD, "recno:pad" },
|
||||
{ DB_RE_RENUMBER, "recno:renumber" },
|
||||
{ DB_RE_SNAPSHOT, "recno:snapshot" },
|
||||
{ 0 },
|
||||
};
|
||||
FILE *fp;
|
||||
const char *t;
|
||||
|
||||
fp = __db_prinit(NULL);
|
||||
|
||||
switch (dbp->type) {
|
||||
case DB_BTREE:
|
||||
t = "btree";
|
||||
break;
|
||||
case DB_HASH:
|
||||
t = "hash";
|
||||
break;
|
||||
case DB_RECNO:
|
||||
t = "recno";
|
||||
break;
|
||||
default:
|
||||
t = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(fp, "%s ", t);
|
||||
__db_prflags(dbp->flags, fn, fp);
|
||||
fprintf(fp, "\n");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_prbtree --
|
||||
* Print out the btree internal information.
|
||||
*
|
||||
* PUBLIC: int __db_prbtree __P((DB *));
|
||||
*/
|
||||
int
|
||||
__db_prbtree(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
static const FN mfn[] = {
|
||||
{ BTM_DUP, "duplicates" },
|
||||
{ BTM_RECNO, "recno" },
|
||||
{ BTM_RECNUM, "btree:records" },
|
||||
{ BTM_FIXEDLEN, "recno:fixed-length" },
|
||||
{ BTM_RENUMBER, "recno:renumber" },
|
||||
{ 0 },
|
||||
};
|
||||
BTMETA *mp;
|
||||
BTREE *t;
|
||||
EPG *epg;
|
||||
FILE *fp;
|
||||
PAGE *h;
|
||||
RECNO *rp;
|
||||
db_pgno_t i;
|
||||
int ret;
|
||||
|
||||
t = dbp->internal;
|
||||
fp = __db_prinit(NULL);
|
||||
|
||||
(void)fprintf(fp, "%s\nOn-page metadata:\n", DB_LINE);
|
||||
|
||||
i = PGNO_METADATA;
|
||||
if ((ret = __bam_pget(dbp, (PAGE **)&mp, &i, 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
(void)fprintf(fp, "magic %#lx\n", (u_long)mp->magic);
|
||||
(void)fprintf(fp, "version %#lx\n", (u_long)mp->version);
|
||||
(void)fprintf(fp, "pagesize %lu\n", (u_long)mp->pagesize);
|
||||
(void)fprintf(fp, "maxkey: %lu minkey: %lu\n",
|
||||
(u_long)mp->maxkey, (u_long)mp->minkey);
|
||||
|
||||
(void)fprintf(fp, "free %lu", (u_long)mp->free);
|
||||
for (i = mp->free; i != PGNO_INVALID;) {
|
||||
if ((ret = __bam_pget(dbp, &h, &i, 0)) != 0)
|
||||
return (ret);
|
||||
i = h->next_pgno;
|
||||
(void)memp_fput(dbp->mpf, h, 0);
|
||||
(void)fprintf(fp, ", %lu", (u_long)i);
|
||||
}
|
||||
(void)fprintf(fp, "\n");
|
||||
|
||||
(void)fprintf(fp, "flags %#lx", (u_long)mp->flags);
|
||||
__db_prflags(mp->flags, mfn, fp);
|
||||
(void)fprintf(fp, "\n");
|
||||
(void)memp_fput(dbp->mpf, mp, 0);
|
||||
|
||||
(void)fprintf(fp, "%s\nDB_INFO:\n", DB_LINE);
|
||||
(void)fprintf(fp, "bt_maxkey: %lu bt_minkey: %lu\n",
|
||||
(u_long)t->bt_maxkey, (u_long)t->bt_minkey);
|
||||
(void)fprintf(fp, "bt_compare: %#lx bt_prefix: %#lx\n",
|
||||
(u_long)t->bt_compare, (u_long)t->bt_prefix);
|
||||
if ((rp = t->bt_recno) != NULL) {
|
||||
(void)fprintf(fp,
|
||||
"re_delim: %#lx re_pad: %#lx re_len: %lu re_source: %s\n",
|
||||
(u_long)rp->re_delim, (u_long)rp->re_pad,
|
||||
(u_long)rp->re_len,
|
||||
rp->re_source == NULL ? "" : rp->re_source);
|
||||
(void)fprintf(fp,
|
||||
"cmap: %#lx smap: %#lx emap: %#lx msize: %lu\n",
|
||||
(u_long)rp->re_cmap, (u_long)rp->re_smap,
|
||||
(u_long)rp->re_emap, (u_long)rp->re_msize);
|
||||
}
|
||||
(void)fprintf(fp, "stack:");
|
||||
for (epg = t->bt_stack; epg < t->bt_sp; ++epg)
|
||||
(void)fprintf(fp, " %lu", (u_long)epg->page->pgno);
|
||||
(void)fprintf(fp, "\n");
|
||||
(void)fprintf(fp, "ovflsize: %lu\n", (u_long)t->bt_ovflsize);
|
||||
(void)fflush(fp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_prhash --
|
||||
* Print out the hash internal information.
|
||||
*
|
||||
* PUBLIC: int __db_prhash __P((DB *));
|
||||
*/
|
||||
int
|
||||
__db_prhash(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
FILE *fp;
|
||||
HTAB *t;
|
||||
int i, put_page, ret;
|
||||
db_pgno_t pgno;
|
||||
|
||||
t = dbp->internal;
|
||||
|
||||
fp = __db_prinit(NULL);
|
||||
|
||||
fprintf(fp, "\thash_accesses %lu\n", (u_long)t->hash_accesses);
|
||||
fprintf(fp, "\thash_collisions %lu\n", (u_long)t->hash_collisions);
|
||||
fprintf(fp, "\thash_expansions %lu\n", (u_long)t->hash_expansions);
|
||||
fprintf(fp, "\thash_overflows %lu\n", (u_long)t->hash_overflows);
|
||||
fprintf(fp, "\thash_bigpages %lu\n", (u_long)t->hash_bigpages);
|
||||
fprintf(fp, "\n");
|
||||
|
||||
if (t->hdr == NULL) {
|
||||
pgno = PGNO_METADATA;
|
||||
if ((ret = memp_fget(dbp->mpf, &pgno, 0, &t->hdr)) != 0)
|
||||
return (ret);
|
||||
put_page = 1;
|
||||
} else
|
||||
put_page = 0;
|
||||
|
||||
fprintf(fp, "\tmagic %#lx\n", (u_long)t->hdr->magic);
|
||||
fprintf(fp, "\tversion %lu\n", (u_long)t->hdr->version);
|
||||
fprintf(fp, "\tpagesize %lu\n", (u_long)t->hdr->pagesize);
|
||||
fprintf(fp, "\tovfl_point %lu\n", (u_long)t->hdr->ovfl_point);
|
||||
fprintf(fp, "\tlast_freed %lu\n", (u_long)t->hdr->last_freed);
|
||||
fprintf(fp, "\tmax_bucket %lu\n", (u_long)t->hdr->max_bucket);
|
||||
fprintf(fp, "\thigh_mask %#lx\n", (u_long)t->hdr->high_mask);
|
||||
fprintf(fp, "\tlow_mask %#lx\n", (u_long)t->hdr->low_mask);
|
||||
fprintf(fp, "\tffactor %lu\n", (u_long)t->hdr->ffactor);
|
||||
fprintf(fp, "\tnelem %lu\n", (u_long)t->hdr->nelem);
|
||||
fprintf(fp, "\th_charkey %#lx\n", (u_long)t->hdr->h_charkey);
|
||||
|
||||
for (i = 0; i < NCACHED; i++)
|
||||
fprintf(fp, "%lu ", (u_long)t->hdr->spares[i]);
|
||||
fprintf(fp, "\n");
|
||||
|
||||
(void)fflush(fp);
|
||||
if (put_page) {
|
||||
(void)memp_fput(dbp->mpf, (PAGE *)t->hdr, 0);
|
||||
t->hdr = NULL;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_prtree --
|
||||
* Print out the entire tree.
|
||||
*
|
||||
* PUBLIC: int __db_prtree __P((DB_MPOOLFILE *, int));
|
||||
*/
|
||||
int
|
||||
__db_prtree(mpf, all)
|
||||
DB_MPOOLFILE *mpf;
|
||||
int all;
|
||||
{
|
||||
PAGE *h;
|
||||
db_pgno_t i;
|
||||
int ret, t_ret;
|
||||
|
||||
if (set_psize == PSIZE_BOUNDARY)
|
||||
__db_psize(mpf);
|
||||
|
||||
ret = 0;
|
||||
for (i = PGNO_ROOT;; ++i) {
|
||||
if ((ret = memp_fget(mpf, &i, 0, &h)) != 0)
|
||||
break;
|
||||
if (TYPE(h) != P_INVALID)
|
||||
if ((t_ret = __db_prpage(h, all)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
(void)memp_fput(mpf, h, 0);
|
||||
}
|
||||
(void)fflush(__db_prinit(NULL));
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_prnpage
|
||||
* -- Print out a specific page.
|
||||
*
|
||||
* PUBLIC: int __db_prnpage __P((DB_MPOOLFILE *, db_pgno_t));
|
||||
*/
|
||||
int
|
||||
__db_prnpage(mpf, pgno)
|
||||
DB_MPOOLFILE *mpf;
|
||||
db_pgno_t pgno;
|
||||
{
|
||||
PAGE *h;
|
||||
int ret;
|
||||
|
||||
if (set_psize == PSIZE_BOUNDARY)
|
||||
__db_psize(mpf);
|
||||
|
||||
if ((ret = memp_fget(mpf, &pgno, 0, &h)) != 0)
|
||||
return (ret);
|
||||
|
||||
ret = __db_prpage(h, 1);
|
||||
(void)fflush(__db_prinit(NULL));
|
||||
|
||||
(void)memp_fput(mpf, h, 0);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_prpage
|
||||
* -- Print out a page.
|
||||
*
|
||||
* PUBLIC: int __db_prpage __P((PAGE *, int));
|
||||
*/
|
||||
int
|
||||
__db_prpage(h, all)
|
||||
PAGE *h;
|
||||
int all;
|
||||
{
|
||||
BINTERNAL *bi;
|
||||
BKEYDATA *bk;
|
||||
HOFFPAGE a_hkd;
|
||||
FILE *fp;
|
||||
RINTERNAL *ri;
|
||||
db_indx_t dlen, len, i;
|
||||
db_pgno_t pgno;
|
||||
int deleted, ret;
|
||||
const char *s;
|
||||
u_int8_t *ep, *hk, *p;
|
||||
void *sp;
|
||||
|
||||
fp = __db_prinit(NULL);
|
||||
|
||||
switch (TYPE(h)) {
|
||||
case P_DUPLICATE:
|
||||
s = "duplicate";
|
||||
break;
|
||||
case P_HASH:
|
||||
s = "hash";
|
||||
break;
|
||||
case P_IBTREE:
|
||||
s = "btree internal";
|
||||
break;
|
||||
case P_INVALID:
|
||||
s = "invalid";
|
||||
break;
|
||||
case P_IRECNO:
|
||||
s = "recno internal";
|
||||
break;
|
||||
case P_LBTREE:
|
||||
s = "btree leaf";
|
||||
break;
|
||||
case P_LRECNO:
|
||||
s = "recno leaf";
|
||||
break;
|
||||
case P_OVERFLOW:
|
||||
s = "overflow";
|
||||
break;
|
||||
default:
|
||||
fprintf(fp, "ILLEGAL PAGE TYPE: page: %lu type: %lu\n",
|
||||
(u_long)h->pgno, (u_long)TYPE(h));
|
||||
return (1);
|
||||
}
|
||||
fprintf(fp, "page %4lu: (%s)\n", (u_long)h->pgno, s);
|
||||
fprintf(fp, " lsn.file: %lu lsn.offset: %lu",
|
||||
(u_long)LSN(h).file, (u_long)LSN(h).offset);
|
||||
if (TYPE(h) == P_IBTREE || TYPE(h) == P_IRECNO ||
|
||||
(TYPE(h) == P_LRECNO && h->pgno == PGNO_ROOT))
|
||||
fprintf(fp, " total records: %4lu", (u_long)RE_NREC(h));
|
||||
fprintf(fp, "\n");
|
||||
if (TYPE(h) == P_LBTREE || TYPE(h) == P_LRECNO ||
|
||||
TYPE(h) == P_DUPLICATE || TYPE(h) == P_OVERFLOW)
|
||||
fprintf(fp, " prev: %4lu next: %4lu",
|
||||
(u_long)PREV_PGNO(h), (u_long)NEXT_PGNO(h));
|
||||
if (TYPE(h) == P_IBTREE || TYPE(h) == P_LBTREE)
|
||||
fprintf(fp, " level: %2lu", (u_long)h->level);
|
||||
if (TYPE(h) == P_OVERFLOW) {
|
||||
fprintf(fp, " ref cnt: %4lu ", (u_long)OV_REF(h));
|
||||
__db_pr((u_int8_t *)h + P_OVERHEAD, OV_LEN(h));
|
||||
return (0);
|
||||
}
|
||||
fprintf(fp, " entries: %4lu", (u_long)NUM_ENT(h));
|
||||
fprintf(fp, " offset: %4lu\n", (u_long)HOFFSET(h));
|
||||
|
||||
if (!all || TYPE(h) == P_INVALID)
|
||||
return (0);
|
||||
|
||||
ret = 0;
|
||||
for (i = 0; i < NUM_ENT(h); i++) {
|
||||
if (P_ENTRY(h, i) - (u_int8_t *)h < P_OVERHEAD ||
|
||||
(size_t)(P_ENTRY(h, i) - (u_int8_t *)h) >= set_psize) {
|
||||
fprintf(fp,
|
||||
"ILLEGAL PAGE OFFSET: indx: %lu of %lu\n",
|
||||
(u_long)i, (u_long)h->inp[i]);
|
||||
ret = EINVAL;
|
||||
continue;
|
||||
}
|
||||
deleted = 0;
|
||||
switch (TYPE(h)) {
|
||||
case P_HASH:
|
||||
case P_IBTREE:
|
||||
case P_IRECNO:
|
||||
sp = P_ENTRY(h, i);
|
||||
break;
|
||||
case P_LBTREE:
|
||||
sp = P_ENTRY(h, i);
|
||||
deleted = i % 2 == 0 &&
|
||||
B_DISSET(GET_BKEYDATA(h, i + O_INDX)->type);
|
||||
break;
|
||||
case P_LRECNO:
|
||||
case P_DUPLICATE:
|
||||
sp = P_ENTRY(h, i);
|
||||
deleted = B_DISSET(GET_BKEYDATA(h, i)->type);
|
||||
break;
|
||||
default:
|
||||
fprintf(fp,
|
||||
"ILLEGAL PAGE ITEM: %lu\n", (u_long)TYPE(h));
|
||||
ret = EINVAL;
|
||||
continue;
|
||||
}
|
||||
fprintf(fp, " %s[%03lu] %4lu ",
|
||||
deleted ? "D" : " ", (u_long)i, (u_long)h->inp[i]);
|
||||
switch (TYPE(h)) {
|
||||
case P_HASH:
|
||||
hk = sp;
|
||||
switch (HPAGE_PTYPE(hk)) {
|
||||
case H_OFFDUP:
|
||||
memcpy(&pgno,
|
||||
HOFFDUP_PGNO(hk), sizeof(db_pgno_t));
|
||||
fprintf(fp,
|
||||
"%4lu [offpage dups]\n", (u_long)pgno);
|
||||
break;
|
||||
case H_DUPLICATE:
|
||||
/*
|
||||
* If this is the first item on a page, then
|
||||
* we cannot figure out how long it is, so
|
||||
* we only print the first one in the duplicate
|
||||
* set.
|
||||
*/
|
||||
if (i != 0)
|
||||
len = LEN_HKEYDATA(h, 0, i);
|
||||
else
|
||||
len = 1;
|
||||
|
||||
fprintf(fp, "Duplicates:\n");
|
||||
for (p = HKEYDATA_DATA(hk),
|
||||
ep = p + len; p < ep;) {
|
||||
memcpy(&dlen, p, sizeof(db_indx_t));
|
||||
p += sizeof(db_indx_t);
|
||||
fprintf(fp, "\t\t");
|
||||
__db_pr(p, dlen);
|
||||
p += sizeof(db_indx_t) + dlen;
|
||||
}
|
||||
break;
|
||||
case H_KEYDATA:
|
||||
if (i != 0)
|
||||
__db_pr(HKEYDATA_DATA(hk),
|
||||
LEN_HKEYDATA(h, 0, i));
|
||||
else
|
||||
fprintf(fp, "%s\n", HKEYDATA_DATA(hk));
|
||||
break;
|
||||
case H_OFFPAGE:
|
||||
memcpy(&a_hkd, hk, HOFFPAGE_SIZE);
|
||||
fprintf(fp,
|
||||
"overflow: total len: %4lu page: %4lu\n",
|
||||
(u_long)a_hkd.tlen, (u_long)a_hkd.pgno);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case P_IBTREE:
|
||||
bi = sp;
|
||||
fprintf(fp, "count: %4lu pgno: %4lu ",
|
||||
(u_long)bi->nrecs, (u_long)bi->pgno);
|
||||
switch (B_TYPE(bi->type)) {
|
||||
case B_KEYDATA:
|
||||
__db_pr(bi->data, bi->len);
|
||||
break;
|
||||
case B_DUPLICATE:
|
||||
case B_OVERFLOW:
|
||||
__db_proff(bi->data);
|
||||
break;
|
||||
default:
|
||||
fprintf(fp, "ILLEGAL BINTERNAL TYPE: %lu\n",
|
||||
(u_long)B_TYPE(bi->type));
|
||||
ret = EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case P_IRECNO:
|
||||
ri = sp;
|
||||
fprintf(fp, "entries %4lu pgno %4lu\n",
|
||||
(u_long)ri->nrecs, (u_long)ri->pgno);
|
||||
break;
|
||||
case P_LBTREE:
|
||||
case P_LRECNO:
|
||||
case P_DUPLICATE:
|
||||
bk = sp;
|
||||
switch (B_TYPE(bk->type)) {
|
||||
case B_KEYDATA:
|
||||
__db_pr(bk->data, bk->len);
|
||||
break;
|
||||
case B_DUPLICATE:
|
||||
case B_OVERFLOW:
|
||||
__db_proff(bk);
|
||||
break;
|
||||
default:
|
||||
fprintf(fp,
|
||||
"ILLEGAL DUPLICATE/LBTREE/LRECNO TYPE: %lu\n",
|
||||
(u_long)B_TYPE(bk->type));
|
||||
ret = EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
(void)fflush(fp);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_isbad
|
||||
* -- Decide if a page is corrupted.
|
||||
*
|
||||
* PUBLIC: int __db_isbad __P((PAGE *, int));
|
||||
*/
|
||||
int
|
||||
__db_isbad(h, die)
|
||||
PAGE *h;
|
||||
int die;
|
||||
{
|
||||
BINTERNAL *bi;
|
||||
BKEYDATA *bk;
|
||||
FILE *fp;
|
||||
db_indx_t i;
|
||||
u_int type;
|
||||
|
||||
fp = __db_prinit(NULL);
|
||||
|
||||
switch (TYPE(h)) {
|
||||
case P_DUPLICATE:
|
||||
case P_HASH:
|
||||
case P_IBTREE:
|
||||
case P_INVALID:
|
||||
case P_IRECNO:
|
||||
case P_LBTREE:
|
||||
case P_LRECNO:
|
||||
case P_OVERFLOW:
|
||||
break;
|
||||
default:
|
||||
fprintf(fp, "ILLEGAL PAGE TYPE: page: %lu type: %lu\n",
|
||||
(u_long)h->pgno, (u_long)TYPE(h));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_ENT(h); i++) {
|
||||
if (P_ENTRY(h, i) - (u_int8_t *)h < P_OVERHEAD ||
|
||||
(size_t)(P_ENTRY(h, i) - (u_int8_t *)h) >= set_psize) {
|
||||
fprintf(fp,
|
||||
"ILLEGAL PAGE OFFSET: indx: %lu of %lu\n",
|
||||
(u_long)i, (u_long)h->inp[i]);
|
||||
goto bad;
|
||||
}
|
||||
switch (TYPE(h)) {
|
||||
case P_HASH:
|
||||
type = HPAGE_TYPE(h, i);
|
||||
if (type != H_OFFDUP &&
|
||||
type != H_DUPLICATE &&
|
||||
type != H_KEYDATA &&
|
||||
type != H_OFFPAGE) {
|
||||
fprintf(fp, "ILLEGAL HASH TYPE: %lu\n",
|
||||
(u_long)type);
|
||||
goto bad;
|
||||
}
|
||||
break;
|
||||
case P_IBTREE:
|
||||
bi = GET_BINTERNAL(h, i);
|
||||
if (B_TYPE(bi->type) != B_KEYDATA &&
|
||||
B_TYPE(bi->type) != B_DUPLICATE &&
|
||||
B_TYPE(bi->type) != B_OVERFLOW) {
|
||||
fprintf(fp, "ILLEGAL BINTERNAL TYPE: %lu\n",
|
||||
(u_long)B_TYPE(bi->type));
|
||||
goto bad;
|
||||
}
|
||||
break;
|
||||
case P_IRECNO:
|
||||
case P_LBTREE:
|
||||
case P_LRECNO:
|
||||
break;
|
||||
case P_DUPLICATE:
|
||||
bk = GET_BKEYDATA(h, i);
|
||||
if (B_TYPE(bk->type) != B_KEYDATA &&
|
||||
B_TYPE(bk->type) != B_DUPLICATE &&
|
||||
B_TYPE(bk->type) != B_OVERFLOW) {
|
||||
fprintf(fp,
|
||||
"ILLEGAL DUPLICATE/LBTREE/LRECNO TYPE: %lu\n",
|
||||
(u_long)B_TYPE(bk->type));
|
||||
goto bad;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(fp,
|
||||
"ILLEGAL PAGE ITEM: %lu\n", (u_long)TYPE(h));
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
|
||||
bad: if (die) {
|
||||
abort();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_pr --
|
||||
* Print out a data element.
|
||||
*
|
||||
* PUBLIC: void __db_pr __P((u_int8_t *, u_int32_t));
|
||||
*/
|
||||
void
|
||||
__db_pr(p, len)
|
||||
u_int8_t *p;
|
||||
u_int32_t len;
|
||||
{
|
||||
FILE *fp;
|
||||
u_int lastch;
|
||||
int i;
|
||||
|
||||
fp = __db_prinit(NULL);
|
||||
|
||||
fprintf(fp, "len: %3lu", (u_long)len);
|
||||
lastch = '.';
|
||||
if (len != 0) {
|
||||
fprintf(fp, " data: ");
|
||||
for (i = len <= 20 ? len : 20; i > 0; --i, ++p) {
|
||||
lastch = *p;
|
||||
if (isprint(*p) || *p == '\n')
|
||||
fprintf(fp, "%c", *p);
|
||||
else
|
||||
fprintf(fp, "0x%.2x", (u_int)*p);
|
||||
}
|
||||
if (len > 20) {
|
||||
fprintf(fp, "...");
|
||||
lastch = '.';
|
||||
}
|
||||
}
|
||||
if (lastch != '\n')
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_prdbt --
|
||||
* Print out a DBT data element.
|
||||
*
|
||||
* PUBLIC: int __db_prdbt __P((DBT *, int, FILE *));
|
||||
*/
|
||||
int
|
||||
__db_prdbt(dbtp, checkprint, fp)
|
||||
DBT *dbtp;
|
||||
int checkprint;
|
||||
FILE *fp;
|
||||
{
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
u_int8_t *p;
|
||||
u_int32_t len;
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* This routine is the routine that dumps out items in the format
|
||||
* used by db_dump(1) and db_load(1). This means that the format
|
||||
* cannot change.
|
||||
*/
|
||||
if (checkprint) {
|
||||
for (len = dbtp->size, p = dbtp->data; len--; ++p)
|
||||
if (isprint(*p)) {
|
||||
if (*p == '\\' && fprintf(fp, "\\") != 1)
|
||||
return (EIO);
|
||||
if (fprintf(fp, "%c", *p) != 1)
|
||||
return (EIO);
|
||||
} else
|
||||
if (fprintf(fp, "\\%c%c",
|
||||
hex[(u_int8_t)(*p & 0xf0) >> 4],
|
||||
hex[*p & 0x0f]) != 3)
|
||||
return (EIO);
|
||||
} else
|
||||
for (len = dbtp->size, p = dbtp->data; len--; ++p)
|
||||
if (fprintf(fp, "%c%c",
|
||||
hex[(u_int8_t)(*p & 0xf0) >> 4],
|
||||
hex[*p & 0x0f]) != 2)
|
||||
return (EIO);
|
||||
|
||||
return (fprintf(fp, "\n") == 1 ? 0 : EIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_proff --
|
||||
* Print out an off-page element.
|
||||
*/
|
||||
static void
|
||||
__db_proff(vp)
|
||||
void *vp;
|
||||
{
|
||||
FILE *fp;
|
||||
BOVERFLOW *bo;
|
||||
|
||||
fp = __db_prinit(NULL);
|
||||
|
||||
bo = vp;
|
||||
switch (B_TYPE(bo->type)) {
|
||||
case B_OVERFLOW:
|
||||
fprintf(fp, "overflow: total len: %4lu page: %4lu\n",
|
||||
(u_long)bo->tlen, (u_long)bo->pgno);
|
||||
break;
|
||||
case B_DUPLICATE:
|
||||
fprintf(fp, "duplicate: page: %4lu\n", (u_long)bo->pgno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_prflags --
|
||||
* Print out flags values.
|
||||
*
|
||||
* PUBLIC: void __db_prflags __P((u_int32_t, const FN *, FILE *));
|
||||
*/
|
||||
void
|
||||
__db_prflags(flags, fn, fp)
|
||||
u_int32_t flags;
|
||||
FN const *fn;
|
||||
FILE *fp;
|
||||
{
|
||||
const FN *fnp;
|
||||
int found;
|
||||
const char *sep;
|
||||
|
||||
sep = " (";
|
||||
for (found = 0, fnp = fn; fnp->mask != 0; ++fnp)
|
||||
if (LF_ISSET(fnp->mask)) {
|
||||
fprintf(fp, "%s%s", sep, fnp->name);
|
||||
sep = ", ";
|
||||
found = 1;
|
||||
}
|
||||
if (found)
|
||||
fprintf(fp, ")");
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_psize --
|
||||
* Get the page size.
|
||||
*/
|
||||
static void
|
||||
__db_psize(mpf)
|
||||
DB_MPOOLFILE *mpf;
|
||||
{
|
||||
BTMETA *mp;
|
||||
db_pgno_t pgno;
|
||||
|
||||
set_psize = PSIZE_BOUNDARY - 1;
|
||||
|
||||
pgno = PGNO_METADATA;
|
||||
if (memp_fget(mpf, &pgno, 0, &mp) != 0)
|
||||
return;
|
||||
|
||||
switch (mp->magic) {
|
||||
case DB_BTREEMAGIC:
|
||||
case DB_HASHMAGIC:
|
||||
set_psize = mp->pagesize;
|
||||
break;
|
||||
}
|
||||
(void)memp_fput(mpf, mp, 0);
|
||||
}
|
639
db/db/db_rec.c
639
db/db/db_rec.c
|
@ -1,639 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_rec.c 10.16 (Sleepycat) 4/28/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "shqueue.h"
|
||||
#include "db_page.h"
|
||||
#include "log.h"
|
||||
#include "hash.h"
|
||||
#include "btree.h"
|
||||
|
||||
/*
|
||||
* PUBLIC: int __db_addrem_recover
|
||||
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*
|
||||
* This log message is generated whenever we add or remove a duplicate
|
||||
* to/from a duplicate page. On recover, we just do the opposite.
|
||||
*/
|
||||
int
|
||||
__db_addrem_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__db_addrem_args *argp;
|
||||
DB *file_dbp, *mdbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
u_int32_t change;
|
||||
int cmp_n, cmp_p, ret;
|
||||
|
||||
REC_PRINT(__db_addrem_print);
|
||||
REC_INTRO(__db_addrem_read);
|
||||
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (!redo) {
|
||||
/*
|
||||
* We are undoing and the page doesn't exist. That
|
||||
* is equivalent to having a pagelsn of 0, so we
|
||||
* would not have to undo anything. In this case,
|
||||
* don't bother creating a page.
|
||||
*/
|
||||
*lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else
|
||||
if ((ret = memp_fget(mpf,
|
||||
&argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
|
||||
change = 0;
|
||||
if ((cmp_p == 0 && redo && argp->opcode == DB_ADD_DUP) ||
|
||||
(cmp_n == 0 && !redo && argp->opcode == DB_REM_DUP)) {
|
||||
|
||||
/* Need to redo an add, or undo a delete. */
|
||||
if ((ret = __db_pitem(file_dbp, pagep, argp->indx, argp->nbytes,
|
||||
argp->hdr.size == 0 ? NULL : &argp->hdr,
|
||||
argp->dbt.size == 0 ? NULL : &argp->dbt)) != 0)
|
||||
goto out;
|
||||
|
||||
change = DB_MPOOL_DIRTY;
|
||||
|
||||
} else if ((cmp_n == 0 && !redo && argp->opcode == DB_ADD_DUP) ||
|
||||
(cmp_p == 0 && redo && argp->opcode == DB_REM_DUP)) {
|
||||
/* Need to undo an add, or redo a delete. */
|
||||
if ((ret = __db_ditem(file_dbp,
|
||||
pagep, argp->indx, argp->nbytes)) != 0)
|
||||
goto out;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
}
|
||||
|
||||
if (change)
|
||||
if (redo)
|
||||
LSN(pagep) = *lsnp;
|
||||
else
|
||||
LSN(pagep) = argp->pagelsn;
|
||||
|
||||
if ((ret = memp_fput(mpf, pagep, change)) == 0)
|
||||
*lsnp = argp->prev_lsn;
|
||||
|
||||
out: REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* PUBLIC: int __db_split_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__db_split_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__db_split_args *argp;
|
||||
DB *file_dbp, *mdbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
int change, cmp_n, cmp_p, ret;
|
||||
|
||||
REC_PRINT(__db_split_print);
|
||||
REC_INTRO(__db_split_read);
|
||||
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (!redo) {
|
||||
/*
|
||||
* We are undoing and the page doesn't exist. That
|
||||
* is equivalent to having a pagelsn of 0, so we
|
||||
* would not have to undo anything. In this case,
|
||||
* don't bother creating a page.
|
||||
*/
|
||||
*lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else
|
||||
if ((ret = memp_fget(mpf,
|
||||
&argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are two types of log messages here, one for the old page
|
||||
* and one for the new pages created. The original image in the
|
||||
* SPLITOLD record is used for undo. The image in the SPLITNEW
|
||||
* is used for redo. We should never have a case where there is
|
||||
* a redo operation and the SPLITOLD record is on disk, but not
|
||||
* the SPLITNEW record. Therefore, we only redo NEW messages
|
||||
* and only undo OLD messages.
|
||||
*/
|
||||
|
||||
change = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
|
||||
if (cmp_p == 0 && redo) {
|
||||
if (argp->opcode == DB_SPLITNEW) {
|
||||
/* Need to redo the split described. */
|
||||
memcpy(pagep,
|
||||
argp->pageimage.data, argp->pageimage.size);
|
||||
}
|
||||
LSN(pagep) = *lsnp;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
if (argp->opcode == DB_SPLITOLD) {
|
||||
/* Put back the old image. */
|
||||
memcpy(pagep,
|
||||
argp->pageimage.data, argp->pageimage.size);
|
||||
}
|
||||
LSN(pagep) = argp->pagelsn;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, change)) == 0)
|
||||
*lsnp = argp->prev_lsn;
|
||||
|
||||
out: REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* PUBLIC: int __db_big_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__db_big_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__db_big_args *argp;
|
||||
DB *file_dbp, *mdbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
u_int32_t change;
|
||||
int cmp_n, cmp_p, ret;
|
||||
|
||||
REC_PRINT(__db_big_print);
|
||||
REC_INTRO(__db_big_read);
|
||||
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (!redo) {
|
||||
/*
|
||||
* We are undoing and the page doesn't exist. That
|
||||
* is equivalent to having a pagelsn of 0, so we
|
||||
* would not have to undo anything. In this case,
|
||||
* don't bother creating a page.
|
||||
*/
|
||||
ret = 0;
|
||||
goto ppage;
|
||||
} else
|
||||
if ((ret = memp_fget(mpf,
|
||||
&argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are three pages we need to check. The one on which we are
|
||||
* adding data, the previous one whose next_pointer may have
|
||||
* been updated, and the next one whose prev_pointer may have
|
||||
* been updated.
|
||||
*/
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
|
||||
change = 0;
|
||||
if ((cmp_p == 0 && redo && argp->opcode == DB_ADD_BIG) ||
|
||||
(cmp_n == 0 && !redo && argp->opcode == DB_REM_BIG)) {
|
||||
/* We are either redo-ing an add, or undoing a delete. */
|
||||
P_INIT(pagep, file_dbp->pgsize, argp->pgno, argp->prev_pgno,
|
||||
argp->next_pgno, 0, P_OVERFLOW);
|
||||
OV_LEN(pagep) = argp->dbt.size;
|
||||
OV_REF(pagep) = 1;
|
||||
memcpy((u_int8_t *)pagep + P_OVERHEAD, argp->dbt.data,
|
||||
argp->dbt.size);
|
||||
PREV_PGNO(pagep) = argp->prev_pgno;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
} else if ((cmp_n == 0 && !redo && argp->opcode == DB_ADD_BIG) ||
|
||||
(cmp_p == 0 && redo && argp->opcode == DB_REM_BIG)) {
|
||||
/*
|
||||
* We are either undo-ing an add or redo-ing a delete.
|
||||
* The page is about to be reclaimed in either case, so
|
||||
* there really isn't anything to do here.
|
||||
*/
|
||||
change = DB_MPOOL_DIRTY;
|
||||
}
|
||||
if (change)
|
||||
LSN(pagep) = redo ? *lsnp : argp->pagelsn;
|
||||
|
||||
if ((ret = memp_fput(mpf, pagep, change)) != 0)
|
||||
goto out;
|
||||
|
||||
/* Now check the previous page. */
|
||||
ppage: if (argp->prev_pgno != PGNO_INVALID) {
|
||||
change = 0;
|
||||
if ((ret = memp_fget(mpf, &argp->prev_pgno, 0, &pagep)) != 0)
|
||||
if (!redo) {
|
||||
/*
|
||||
* We are undoing and the page doesn't exist.
|
||||
* That is equivalent to having a pagelsn of 0,
|
||||
* so we would not have to undo anything. In
|
||||
* this case, don't bother creating a page.
|
||||
*/
|
||||
*lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
goto npage;
|
||||
} else
|
||||
if ((ret = memp_fget(mpf, &argp->prev_pgno,
|
||||
DB_MPOOL_CREATE, &pagep)) != 0)
|
||||
goto out;
|
||||
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
|
||||
|
||||
if ((cmp_p == 0 && redo && argp->opcode == DB_ADD_BIG) ||
|
||||
(cmp_n == 0 && !redo && argp->opcode == DB_REM_BIG)) {
|
||||
/* Redo add, undo delete. */
|
||||
NEXT_PGNO(pagep) = argp->pgno;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
} else if ((cmp_n == 0 &&
|
||||
!redo && argp->opcode == DB_ADD_BIG) ||
|
||||
(cmp_p == 0 && redo && argp->opcode == DB_REM_BIG)) {
|
||||
/* Redo delete, undo add. */
|
||||
NEXT_PGNO(pagep) = argp->next_pgno;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
}
|
||||
if (change)
|
||||
LSN(pagep) = redo ? *lsnp : argp->prevlsn;
|
||||
if ((ret = memp_fput(mpf, pagep, change)) != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Now check the next page. Can only be set on a delete. */
|
||||
npage: if (argp->next_pgno != PGNO_INVALID) {
|
||||
change = 0;
|
||||
if ((ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep)) != 0)
|
||||
if (!redo) {
|
||||
/*
|
||||
* We are undoing and the page doesn't exist.
|
||||
* That is equivalent to having a pagelsn of 0,
|
||||
* so we would not have to undo anything. In
|
||||
* this case, don't bother creating a page.
|
||||
*/
|
||||
*lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else
|
||||
if ((ret = memp_fget(mpf, &argp->next_pgno,
|
||||
DB_MPOOL_CREATE, &pagep)) != 0)
|
||||
goto out;
|
||||
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->nextlsn);
|
||||
if (cmp_p == 0 && redo) {
|
||||
PREV_PGNO(pagep) = PGNO_INVALID;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
PREV_PGNO(pagep) = argp->pgno;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
}
|
||||
if (change)
|
||||
LSN(pagep) = redo ? *lsnp : argp->nextlsn;
|
||||
if ((ret = memp_fput(mpf, pagep, change)) != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
*lsnp = argp->prev_lsn;
|
||||
|
||||
out: REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_ovref_recover --
|
||||
* Recovery function for __db_ovref().
|
||||
*
|
||||
* PUBLIC: int __db_ovref_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__db_ovref_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__db_ovref_args *argp;
|
||||
DB *file_dbp, *mdbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
int modified, ret;
|
||||
|
||||
REC_PRINT(__db_ovref_print);
|
||||
REC_INTRO(__db_ovref_read);
|
||||
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
(void)__db_pgerr(file_dbp, argp->pgno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
modified = 0;
|
||||
if (log_compare(&LSN(pagep), &argp->lsn) == 0 && redo) {
|
||||
/* Need to redo update described. */
|
||||
OV_REF(pagep) += argp->adjust;
|
||||
|
||||
pagep->lsn = *lsnp;
|
||||
modified = 1;
|
||||
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && !redo) {
|
||||
/* Need to undo update described. */
|
||||
OV_REF(pagep) -= argp->adjust;
|
||||
|
||||
pagep->lsn = argp->lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) == 0)
|
||||
*lsnp = argp->prev_lsn;
|
||||
|
||||
out: REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_relink_recover --
|
||||
* Recovery function for relink.
|
||||
*
|
||||
* PUBLIC: int __db_relink_recover
|
||||
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__db_relink_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__db_relink_args *argp;
|
||||
DB *file_dbp, *mdbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
int modified, ret;
|
||||
|
||||
REC_PRINT(__db_relink_print);
|
||||
REC_INTRO(__db_relink_read);
|
||||
|
||||
/*
|
||||
* There are three pages we need to check -- the page, and the
|
||||
* previous and next pages, if they existed.
|
||||
*/
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (redo) {
|
||||
(void)__db_pgerr(file_dbp, argp->pgno);
|
||||
goto out;
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
modified = 0;
|
||||
if (log_compare(&LSN(pagep), &argp->lsn) == 0 && redo) {
|
||||
/* Redo the relink. */
|
||||
pagep->lsn = *lsnp;
|
||||
modified = 1;
|
||||
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && !redo) {
|
||||
/* Undo the relink. */
|
||||
pagep->next_pgno = argp->next;
|
||||
pagep->prev_pgno = argp->prev;
|
||||
|
||||
pagep->lsn = argp->lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) {
|
||||
(void)__db_panic(file_dbp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
next: if ((ret = memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
|
||||
if (redo) {
|
||||
(void)__db_pgerr(file_dbp, argp->next);
|
||||
goto out;
|
||||
}
|
||||
goto prev;
|
||||
}
|
||||
modified = 0;
|
||||
if (log_compare(&LSN(pagep), &argp->lsn_next) == 0 && redo) {
|
||||
/* Redo the relink. */
|
||||
pagep->prev_pgno = argp->prev;
|
||||
|
||||
pagep->lsn = *lsnp;
|
||||
modified = 1;
|
||||
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && !redo) {
|
||||
/* Undo the relink. */
|
||||
pagep->prev_pgno = argp->pgno;
|
||||
|
||||
pagep->lsn = argp->lsn_next;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) {
|
||||
(void)__db_panic(file_dbp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
prev: if ((ret = memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) {
|
||||
if (redo) {
|
||||
(void)__db_pgerr(file_dbp, argp->prev);
|
||||
goto out;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
modified = 0;
|
||||
if (log_compare(&LSN(pagep), &argp->lsn_prev) == 0 && redo) {
|
||||
/* Redo the relink. */
|
||||
pagep->next_pgno = argp->next;
|
||||
|
||||
pagep->lsn = *lsnp;
|
||||
modified = 1;
|
||||
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && !redo) {
|
||||
/* Undo the relink. */
|
||||
pagep->next_pgno = argp->pgno;
|
||||
|
||||
pagep->lsn = argp->lsn_prev;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) {
|
||||
(void) __db_panic(file_dbp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* PUBLIC: int __db_addpage_recover
|
||||
* PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__db_addpage_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__db_addpage_args *argp;
|
||||
DB *file_dbp, *mdbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
u_int32_t change;
|
||||
int cmp_n, cmp_p, ret;
|
||||
|
||||
REC_PRINT(__db_addpage_print);
|
||||
REC_INTRO(__db_addpage_read);
|
||||
|
||||
/*
|
||||
* We need to check two pages: the old one and the new one onto
|
||||
* which we're going to add duplicates. Do the old one first.
|
||||
*/
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0)
|
||||
goto out;
|
||||
|
||||
change = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
|
||||
if (cmp_p == 0 && redo) {
|
||||
NEXT_PGNO(pagep) = argp->nextpgno;
|
||||
|
||||
LSN(pagep) = *lsnp;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
NEXT_PGNO(pagep) = PGNO_INVALID;
|
||||
|
||||
LSN(pagep) = argp->lsn;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
}
|
||||
if ((ret = memp_fput(mpf, pagep, change)) != 0)
|
||||
goto out;
|
||||
|
||||
if ((ret = memp_fget(mpf, &argp->nextpgno, 0, &pagep)) != 0)
|
||||
if (!redo) {
|
||||
/*
|
||||
* We are undoing and the page doesn't exist. That
|
||||
* is equivalent to having a pagelsn of 0, so we
|
||||
* would not have to undo anything. In this case,
|
||||
* don't bother creating a page.
|
||||
*/
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else
|
||||
if ((ret = memp_fget(mpf,
|
||||
&argp->nextpgno, DB_MPOOL_CREATE, &pagep)) != 0)
|
||||
goto out;
|
||||
|
||||
change = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->nextlsn);
|
||||
if (cmp_p == 0 && redo) {
|
||||
PREV_PGNO(pagep) = argp->pgno;
|
||||
|
||||
LSN(pagep) = *lsnp;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
PREV_PGNO(pagep) = PGNO_INVALID;
|
||||
|
||||
LSN(pagep) = argp->nextlsn;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
}
|
||||
ret = memp_fput(mpf, pagep, change);
|
||||
|
||||
out: if (ret == 0)
|
||||
*lsnp = argp->prev_lsn;
|
||||
REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_debug_recover --
|
||||
* Recovery function for debug.
|
||||
*
|
||||
* PUBLIC: int __db_debug_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__db_debug_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__db_debug_args *argp;
|
||||
int ret;
|
||||
|
||||
COMPQUIET(redo, 0);
|
||||
COMPQUIET(logp, NULL);
|
||||
|
||||
REC_PRINT(__db_debug_print);
|
||||
REC_NOOP_INTRO(__db_debug_read);
|
||||
|
||||
*lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
REC_NOOP_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_noop_recover --
|
||||
* Recovery function for noop.
|
||||
*
|
||||
* PUBLIC: int __db_noop_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
|
||||
*/
|
||||
int
|
||||
__db_noop_recover(logp, dbtp, lsnp, redo, info)
|
||||
DB_LOG *logp;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
int redo;
|
||||
void *info;
|
||||
{
|
||||
__db_noop_args *argp;
|
||||
DB *file_dbp, *mdbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
u_int32_t change;
|
||||
int cmp_n, cmp_p, ret;
|
||||
|
||||
REC_PRINT(__db_noop_print);
|
||||
REC_INTRO(__db_noop_read);
|
||||
|
||||
if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0)
|
||||
goto out;
|
||||
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
|
||||
change = 0;
|
||||
if (cmp_p == 0 && redo) {
|
||||
LSN(pagep) = *lsnp;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
} else if (cmp_n == 0 && !redo) {
|
||||
LSN(pagep) = argp->prevlsn;
|
||||
change = DB_MPOOL_DIRTY;
|
||||
}
|
||||
*lsnp = argp->prev_lsn;
|
||||
ret = memp_fput(mpf, pagep, change);
|
||||
|
||||
out: REC_CLOSE;
|
||||
}
|
160
db/db/db_ret.c
160
db/db/db_ret.c
|
@ -1,160 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_ret.c 10.13 (Sleepycat) 5/7/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "btree.h"
|
||||
#include "db_am.h"
|
||||
|
||||
/*
|
||||
* __db_ret --
|
||||
* Build return DBT.
|
||||
*
|
||||
* PUBLIC: int __db_ret __P((DB *,
|
||||
* PUBLIC: PAGE *, u_int32_t, DBT *, void **, u_int32_t *));
|
||||
*/
|
||||
int
|
||||
__db_ret(dbp, h, indx, dbt, memp, memsize)
|
||||
DB *dbp;
|
||||
PAGE *h;
|
||||
u_int32_t indx;
|
||||
DBT *dbt;
|
||||
void **memp;
|
||||
u_int32_t *memsize;
|
||||
{
|
||||
BKEYDATA *bk;
|
||||
HOFFPAGE ho;
|
||||
BOVERFLOW *bo;
|
||||
u_int32_t len;
|
||||
u_int8_t *hk;
|
||||
void *data;
|
||||
|
||||
switch (TYPE(h)) {
|
||||
case P_HASH:
|
||||
hk = P_ENTRY(h, indx);
|
||||
if (HPAGE_PTYPE(hk) == H_OFFPAGE) {
|
||||
memcpy(&ho, hk, sizeof(HOFFPAGE));
|
||||
return (__db_goff(dbp, dbt,
|
||||
ho.tlen, ho.pgno, memp, memsize));
|
||||
}
|
||||
len = LEN_HKEYDATA(h, dbp->pgsize, indx);
|
||||
data = HKEYDATA_DATA(hk);
|
||||
break;
|
||||
case P_DUPLICATE:
|
||||
case P_LBTREE:
|
||||
case P_LRECNO:
|
||||
bk = GET_BKEYDATA(h, indx);
|
||||
if (B_TYPE(bk->type) == B_OVERFLOW) {
|
||||
bo = (BOVERFLOW *)bk;
|
||||
return (__db_goff(dbp, dbt,
|
||||
bo->tlen, bo->pgno, memp, memsize));
|
||||
}
|
||||
len = bk->len;
|
||||
data = bk->data;
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbp, h->pgno));
|
||||
}
|
||||
|
||||
return (__db_retcopy(dbt, data, len, memp, memsize,
|
||||
F_ISSET(dbt, DB_DBT_INTERNAL) ? NULL : dbp->db_malloc));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_retcopy --
|
||||
* Copy the returned data into the user's DBT, handling special flags.
|
||||
*
|
||||
* PUBLIC: int __db_retcopy __P((DBT *,
|
||||
* PUBLIC: void *, u_int32_t, void **, u_int32_t *, void *(*)(size_t)));
|
||||
*/
|
||||
int
|
||||
__db_retcopy(dbt, data, len, memp, memsize, db_malloc)
|
||||
DBT *dbt;
|
||||
void *data;
|
||||
u_int32_t len;
|
||||
void **memp;
|
||||
u_int32_t *memsize;
|
||||
void *(*db_malloc) __P((size_t));
|
||||
{
|
||||
/* If returning a partial record, reset the length. */
|
||||
if (F_ISSET(dbt, DB_DBT_PARTIAL)) {
|
||||
data = (u_int8_t *)data + dbt->doff;
|
||||
if (len > dbt->doff) {
|
||||
len -= dbt->doff;
|
||||
if (len > dbt->dlen)
|
||||
len = dbt->dlen;
|
||||
} else
|
||||
len = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the length of the returned record in the DBT size field.
|
||||
* This satisfies the requirement that if we're using user memory
|
||||
* and insufficient memory was provided, return the amount necessary
|
||||
* in the size field.
|
||||
*/
|
||||
dbt->size = len;
|
||||
|
||||
/*
|
||||
* Allocate memory to be owned by the application: DB_DBT_MALLOC.
|
||||
*
|
||||
* !!!
|
||||
* We always allocate memory, even if we're copying out 0 bytes. This
|
||||
* guarantees consistency, i.e., the application can always free memory
|
||||
* without concern as to how many bytes of the record were requested.
|
||||
*
|
||||
* XXX
|
||||
* Never allocate 0 bytes, it's known to make malloc/realloc unhappy.
|
||||
*
|
||||
* Use the memory specified by the application: DB_DBT_USERMEM.
|
||||
*
|
||||
* !!!
|
||||
* If the length we're going to copy is 0, the application-supplied
|
||||
* memory pointer is allowed to be NULL.
|
||||
*/
|
||||
if (F_ISSET(dbt, DB_DBT_MALLOC)) {
|
||||
dbt->data = db_malloc == NULL ?
|
||||
(void *)__db_malloc(len) :
|
||||
(void *)db_malloc(len + 1);
|
||||
if (dbt->data == NULL)
|
||||
return (ENOMEM);
|
||||
} else if (F_ISSET(dbt, DB_DBT_USERMEM)) {
|
||||
if (len != 0 && (dbt->data == NULL || dbt->ulen < len))
|
||||
return (ENOMEM);
|
||||
} else if (memp == NULL || memsize == NULL) {
|
||||
return (EINVAL);
|
||||
} else {
|
||||
if (len != 0 && (*memsize == 0 || *memsize < len)) {
|
||||
*memp = *memp == NULL ?
|
||||
(void *)__db_malloc(len) :
|
||||
(void *)__db_realloc(*memp, len);
|
||||
if (*memp == NULL) {
|
||||
*memsize = 0;
|
||||
return (ENOMEM);
|
||||
}
|
||||
*memsize = len;
|
||||
}
|
||||
dbt->data = *memp;
|
||||
}
|
||||
|
||||
if (len != 0)
|
||||
memcpy(dbt->data, data, len);
|
||||
return (0);
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)db_thread.c 8.15 (Sleepycat) 4/26/98";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db_page.h"
|
||||
#include "db_am.h"
|
||||
|
||||
static int __db_getlockid __P((DB *, DB *));
|
||||
|
||||
/*
|
||||
* __db_gethandle --
|
||||
* Called by db access method routines when the DB_THREAD flag is set.
|
||||
* This routine returns a handle, either an existing handle from the
|
||||
* chain of handles, or creating one if necessary.
|
||||
*
|
||||
* PUBLIC: int __db_gethandle __P((DB *, int (*)(DB *, DB *), DB **));
|
||||
*/
|
||||
int
|
||||
__db_gethandle(dbp, am_func, dbpp)
|
||||
DB *dbp, **dbpp;
|
||||
int (*am_func) __P((DB *, DB *));
|
||||
{
|
||||
DB *ret_dbp;
|
||||
int ret, t_ret;
|
||||
|
||||
if ((ret = __db_mutex_lock((db_mutex_t *)dbp->mutexp, -1)) != 0)
|
||||
return (ret);
|
||||
|
||||
if ((ret_dbp = LIST_FIRST(&dbp->handleq)) != NULL)
|
||||
/* Simply take one off the list. */
|
||||
LIST_REMOVE(ret_dbp, links);
|
||||
else {
|
||||
/* Allocate a new handle. */
|
||||
if ((ret_dbp = (DB *)__db_malloc(sizeof(*dbp))) == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
memcpy(ret_dbp, dbp, sizeof(*dbp));
|
||||
ret_dbp->internal = NULL;
|
||||
TAILQ_INIT(&ret_dbp->curs_queue);
|
||||
|
||||
/* Set the locker, the lock structure and the lock DBT. */
|
||||
if ((ret = __db_getlockid(dbp, ret_dbp)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Finally, call the access method specific dup function. */
|
||||
if ((ret = am_func(dbp, ret_dbp)) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
*dbpp = ret_dbp;
|
||||
|
||||
if (0) {
|
||||
err: if (ret_dbp != NULL)
|
||||
FREE(ret_dbp, sizeof(*ret_dbp));
|
||||
}
|
||||
if ((t_ret =
|
||||
__db_mutex_unlock((db_mutex_t *)dbp->mutexp, -1)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_puthandle --
|
||||
* Return a DB handle to the pool for later use.
|
||||
*
|
||||
* PUBLIC: int __db_puthandle __P((DB *));
|
||||
*/
|
||||
int
|
||||
__db_puthandle(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
DB *master;
|
||||
int ret;
|
||||
|
||||
master = dbp->master;
|
||||
if ((ret = __db_mutex_lock((db_mutex_t *)master->mutexp, -1)) != 0)
|
||||
return (ret);
|
||||
|
||||
LIST_INSERT_HEAD(&master->handleq, dbp, links);
|
||||
|
||||
return (__db_mutex_unlock((db_mutex_t *)master->mutexp, -1));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_getlockid --
|
||||
* Create a new locker ID and copy the file lock information from
|
||||
* the old DB into the new one.
|
||||
*/
|
||||
static int
|
||||
__db_getlockid(dbp, new_dbp)
|
||||
DB *dbp, *new_dbp;
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (F_ISSET(dbp, DB_AM_LOCKING)) {
|
||||
if ((ret = lock_id(dbp->dbenv->lk_info, &new_dbp->locker)) != 0)
|
||||
return (ret);
|
||||
memcpy(new_dbp->lock.fileid, dbp->lock.fileid, DB_FILE_ID_LEN);
|
||||
new_dbp->lock_dbt.size = sizeof(new_dbp->lock);
|
||||
new_dbp->lock_dbt.data = &new_dbp->lock;
|
||||
}
|
||||
return (0);
|
||||
}
|
484
db/db185/db185.c
484
db/db185/db185.c
|
@ -1,484 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1996, 1997, 1998\n\
|
||||
Sleepycat Software Inc. All rights reserved.\n";
|
||||
static const char sccsid[] = "@(#)db185.c 8.17 (Sleepycat) 5/7/98";
|
||||
#endif
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "db185_int.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
static int db185_close __P((DB185 *));
|
||||
static int db185_del __P((const DB185 *, const DBT185 *, u_int));
|
||||
static int db185_fd __P((const DB185 *));
|
||||
static int db185_get __P((const DB185 *, const DBT185 *, DBT185 *, u_int));
|
||||
static int db185_put __P((const DB185 *, DBT185 *, const DBT185 *, u_int));
|
||||
static int db185_seq __P((const DB185 *, DBT185 *, DBT185 *, u_int));
|
||||
static int db185_sync __P((const DB185 *, u_int));
|
||||
|
||||
DB185 *
|
||||
dbopen(file, oflags, mode, type, openinfo)
|
||||
const char *file;
|
||||
int oflags, mode;
|
||||
DBTYPE type;
|
||||
const void *openinfo;
|
||||
{
|
||||
const BTREEINFO *bi;
|
||||
const HASHINFO *hi;
|
||||
const RECNOINFO *ri;
|
||||
DB *dbp;
|
||||
DB185 *db185p;
|
||||
DB_INFO dbinfo, *dbinfop;
|
||||
int s_errno;
|
||||
|
||||
if ((db185p = (DB185 *)__db_calloc(1, sizeof(DB185))) == NULL)
|
||||
return (NULL);
|
||||
dbinfop = NULL;
|
||||
memset(&dbinfo, 0, sizeof(dbinfo));
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* The DBTYPE enum wasn't initialized in DB 185, so it's off-by-one
|
||||
* from DB 2.0.
|
||||
*/
|
||||
switch (type) {
|
||||
case 0: /* DB_BTREE */
|
||||
type = DB_BTREE;
|
||||
if ((bi = openinfo) != NULL) {
|
||||
dbinfop = &dbinfo;
|
||||
if (bi->flags & ~R_DUP)
|
||||
goto einval;
|
||||
if (bi->flags & R_DUP)
|
||||
dbinfop->flags |= DB_DUP;
|
||||
dbinfop->db_cachesize = bi->cachesize;
|
||||
dbinfop->bt_maxkey = bi->maxkeypage;
|
||||
dbinfop->bt_minkey = bi->minkeypage;
|
||||
dbinfop->db_pagesize = bi->psize;
|
||||
/*
|
||||
* !!!
|
||||
* Comparisons and prefix calls work because the DBT
|
||||
* structures in 1.85 and 2.0 have the same initial
|
||||
* fields.
|
||||
*/
|
||||
dbinfop->bt_compare = bi->compare;
|
||||
dbinfop->bt_prefix = bi->prefix;
|
||||
dbinfop->db_lorder = bi->lorder;
|
||||
}
|
||||
break;
|
||||
case 1: /* DB_HASH */
|
||||
type = DB_HASH;
|
||||
if ((hi = openinfo) != NULL) {
|
||||
dbinfop = &dbinfo;
|
||||
dbinfop->db_pagesize = hi->bsize;
|
||||
dbinfop->h_ffactor = hi->ffactor;
|
||||
dbinfop->h_nelem = hi->nelem;
|
||||
dbinfop->db_cachesize = hi->cachesize;
|
||||
dbinfop->h_hash = hi->hash;
|
||||
dbinfop->db_lorder = hi->lorder;
|
||||
}
|
||||
|
||||
break;
|
||||
case 2: /* DB_RECNO */
|
||||
type = DB_RECNO;
|
||||
dbinfop = &dbinfo;
|
||||
|
||||
/* DB 1.85 did renumbering by default. */
|
||||
dbinfop->flags |= DB_RENUMBER;
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* The file name given to DB 1.85 recno is the name of the DB
|
||||
* 2.0 backing file. If the file doesn't exist, create it if
|
||||
* the user has the O_CREAT flag set, DB 1.85 did it for you,
|
||||
* and DB 2.0 doesn't.
|
||||
*
|
||||
* !!!
|
||||
* Setting the file name to NULL specifies that we're creating
|
||||
* a temporary backing file, in DB 2.X. If we're opening the
|
||||
* DB file read-only, change the flags to read-write, because
|
||||
* temporary backing files cannot be opened read-only, and DB
|
||||
* 2.X will return an error. We are cheating here -- if the
|
||||
* application does a put on the database, it will succeed --
|
||||
* although that would be a stupid thing for the application
|
||||
* to do.
|
||||
*
|
||||
* !!!
|
||||
* Note, the file name in DB 1.85 was a const -- we don't do
|
||||
* that in DB 2.0, so do that cast.
|
||||
*/
|
||||
if (file != NULL) {
|
||||
if (oflags & O_CREAT && __db_exists(file, NULL) != 0)
|
||||
(void)__os_close(__os_open(file, oflags, mode));
|
||||
dbinfop->re_source = (char *)file;
|
||||
|
||||
if (O_RDONLY)
|
||||
oflags &= ~O_RDONLY;
|
||||
oflags |= O_RDWR;
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
if ((ri = openinfo) != NULL) {
|
||||
/*
|
||||
* !!!
|
||||
* We can't support the bfname field.
|
||||
*/
|
||||
#define BFMSG "DB: DB 1.85's recno bfname field is not supported.\n"
|
||||
if (ri->bfname != NULL) {
|
||||
(void)__os_write(2, BFMSG, sizeof(BFMSG) - 1);
|
||||
goto einval;
|
||||
}
|
||||
|
||||
if (ri->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
|
||||
goto einval;
|
||||
if (ri->flags & R_FIXEDLEN) {
|
||||
dbinfop->flags |= DB_FIXEDLEN;
|
||||
if (ri->bval != 0) {
|
||||
dbinfop->flags |= DB_PAD;
|
||||
dbinfop->re_pad = ri->bval;
|
||||
}
|
||||
} else
|
||||
if (ri->bval != 0) {
|
||||
dbinfop->flags |= DB_DELIMITER;
|
||||
dbinfop->re_delim = ri->bval;
|
||||
}
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* We ignore the R_NOKEY flag, but that's okay, it was
|
||||
* only an optimization that was never implemented.
|
||||
*/
|
||||
|
||||
if (ri->flags & R_SNAPSHOT)
|
||||
dbinfop->flags |= DB_SNAPSHOT;
|
||||
|
||||
dbinfop->db_cachesize = ri->cachesize;
|
||||
dbinfop->db_pagesize = ri->psize;
|
||||
dbinfop->db_lorder = ri->lorder;
|
||||
dbinfop->re_len = ri->reclen;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto einval;
|
||||
}
|
||||
|
||||
db185p->close = db185_close;
|
||||
db185p->del = db185_del;
|
||||
db185p->fd = db185_fd;
|
||||
db185p->get = db185_get;
|
||||
db185p->put = db185_put;
|
||||
db185p->seq = db185_seq;
|
||||
db185p->sync = db185_sync;
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* Store the returned pointer to the real DB 2.0 structure in the
|
||||
* internal pointer. Ugly, but we're not going for pretty, here.
|
||||
*/
|
||||
if ((errno = db_open(file,
|
||||
type, __db_oflags(oflags), mode, NULL, dbinfop, &dbp)) != 0) {
|
||||
__db_free(db185p);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Create the cursor used for sequential ops. */
|
||||
if ((errno = dbp->cursor(dbp, NULL, &((DB185 *)db185p)->dbc)) != 0) {
|
||||
s_errno = errno;
|
||||
(void)dbp->close(dbp, 0);
|
||||
__db_free(db185p);
|
||||
errno = s_errno;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
db185p->internal = dbp;
|
||||
return (db185p);
|
||||
|
||||
einval: __db_free(db185p);
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
db185_close(db185p)
|
||||
DB185 *db185p;
|
||||
{
|
||||
DB *dbp;
|
||||
|
||||
dbp = (DB *)db185p->internal;
|
||||
|
||||
errno = dbp->close(dbp, 0);
|
||||
|
||||
__db_free(db185p);
|
||||
|
||||
return (errno == 0 ? 0 : -1);
|
||||
}
|
||||
|
||||
static int
|
||||
db185_del(db185p, key185, flags)
|
||||
const DB185 *db185p;
|
||||
const DBT185 *key185;
|
||||
u_int flags;
|
||||
{
|
||||
DB *dbp;
|
||||
DBT key;
|
||||
|
||||
dbp = (DB *)db185p->internal;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.data = key185->data;
|
||||
key.size = key185->size;
|
||||
|
||||
if (flags & ~R_CURSOR)
|
||||
goto einval;
|
||||
if (flags & R_CURSOR)
|
||||
errno = db185p->dbc->c_del(db185p->dbc, 0);
|
||||
else
|
||||
errno = dbp->del(dbp, NULL, &key, 0);
|
||||
|
||||
switch (errno) {
|
||||
case 0:
|
||||
return (0);
|
||||
case DB_NOTFOUND:
|
||||
return (1);
|
||||
}
|
||||
return (-1);
|
||||
|
||||
einval: errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
db185_fd(db185p)
|
||||
const DB185 *db185p;
|
||||
{
|
||||
DB *dbp;
|
||||
int fd;
|
||||
|
||||
dbp = (DB *)db185p->internal;
|
||||
|
||||
return ((errno = dbp->fd(dbp, &fd)) == 0 ? fd : -1);
|
||||
}
|
||||
|
||||
static int
|
||||
db185_get(db185p, key185, data185, flags)
|
||||
const DB185 *db185p;
|
||||
const DBT185 *key185;
|
||||
DBT185 *data185;
|
||||
u_int flags;
|
||||
{
|
||||
DB *dbp;
|
||||
DBT key, data;
|
||||
|
||||
dbp = (DB *)db185p->internal;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.data = key185->data;
|
||||
key.size = key185->size;
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.data = data185->data;
|
||||
data.size = data185->size;
|
||||
|
||||
if (flags)
|
||||
goto einval;
|
||||
|
||||
switch (errno = dbp->get(dbp, NULL, &key, &data, 0)) {
|
||||
case 0:
|
||||
data185->data = data.data;
|
||||
data185->size = data.size;
|
||||
return (0);
|
||||
case DB_NOTFOUND:
|
||||
return (1);
|
||||
}
|
||||
return (-1);
|
||||
|
||||
einval: errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
db185_put(db185p, key185, data185, flags)
|
||||
const DB185 *db185p;
|
||||
DBT185 *key185;
|
||||
const DBT185 *data185;
|
||||
u_int flags;
|
||||
{
|
||||
DB *dbp;
|
||||
DBC *dbcp_put;
|
||||
DBT key, data;
|
||||
int s_errno;
|
||||
|
||||
dbp = (DB *)db185p->internal;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.data = key185->data;
|
||||
key.size = key185->size;
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.data = data185->data;
|
||||
data.size = data185->size;
|
||||
|
||||
switch (flags) {
|
||||
case 0:
|
||||
errno = dbp->put(dbp, NULL, &key, &data, 0);
|
||||
break;
|
||||
case R_CURSOR:
|
||||
errno =
|
||||
db185p->dbc->c_put(db185p->dbc, &key, &data, DB_CURRENT);
|
||||
break;
|
||||
case R_IAFTER:
|
||||
case R_IBEFORE:
|
||||
if (dbp->type != DB_RECNO)
|
||||
goto einval;
|
||||
|
||||
if ((errno = dbp->cursor(dbp, NULL, &dbcp_put)) != 0)
|
||||
return (-1);
|
||||
if ((errno =
|
||||
dbcp_put->c_get(dbcp_put, &key, &data, DB_SET)) != 0) {
|
||||
s_errno = errno;
|
||||
(void)dbcp_put->c_close(dbcp_put);
|
||||
errno = s_errno;
|
||||
return (-1);
|
||||
}
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.data = data185->data;
|
||||
data.size = data185->size;
|
||||
errno = dbcp_put->c_put(dbcp_put,
|
||||
&key, &data, flags == R_IAFTER ? DB_AFTER : DB_BEFORE);
|
||||
s_errno = errno;
|
||||
(void)dbcp_put->c_close(dbcp_put);
|
||||
errno = s_errno;
|
||||
break;
|
||||
case R_NOOVERWRITE:
|
||||
errno = dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE);
|
||||
break;
|
||||
case R_SETCURSOR:
|
||||
if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
|
||||
goto einval;
|
||||
|
||||
if ((errno = dbp->put(dbp, NULL, &key, &data, 0)) != 0)
|
||||
break;
|
||||
errno =
|
||||
db185p->dbc->c_get(db185p->dbc, &key, &data, DB_SET_RANGE);
|
||||
break;
|
||||
default:
|
||||
goto einval;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
case 0:
|
||||
key185->data = key.data;
|
||||
key185->size = key.size;
|
||||
return (0);
|
||||
case DB_KEYEXIST:
|
||||
return (1);
|
||||
}
|
||||
return (-1);
|
||||
|
||||
einval: errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
db185_seq(db185p, key185, data185, flags)
|
||||
const DB185 *db185p;
|
||||
DBT185 *key185, *data185;
|
||||
u_int flags;
|
||||
{
|
||||
DB *dbp;
|
||||
DBT key, data;
|
||||
|
||||
dbp = (DB *)db185p->internal;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.data = key185->data;
|
||||
key.size = key185->size;
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.data = data185->data;
|
||||
data.size = data185->size;
|
||||
|
||||
switch (flags) {
|
||||
case R_CURSOR:
|
||||
flags = DB_SET_RANGE;
|
||||
break;
|
||||
case R_FIRST:
|
||||
flags = DB_FIRST;
|
||||
break;
|
||||
case R_LAST:
|
||||
if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
|
||||
goto einval;
|
||||
flags = DB_LAST;
|
||||
break;
|
||||
case R_NEXT:
|
||||
flags = DB_NEXT;
|
||||
break;
|
||||
case R_PREV:
|
||||
if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
|
||||
goto einval;
|
||||
flags = DB_PREV;
|
||||
break;
|
||||
default:
|
||||
goto einval;
|
||||
}
|
||||
switch (errno = db185p->dbc->c_get(db185p->dbc, &key, &data, flags)) {
|
||||
case 0:
|
||||
key185->data = key.data;
|
||||
key185->size = key.size;
|
||||
data185->data = data.data;
|
||||
data185->size = data.size;
|
||||
return (0);
|
||||
case DB_NOTFOUND:
|
||||
return (1);
|
||||
}
|
||||
return (-1);
|
||||
|
||||
einval: errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
db185_sync(db185p, flags)
|
||||
const DB185 *db185p;
|
||||
u_int flags;
|
||||
{
|
||||
DB *dbp;
|
||||
|
||||
dbp = (DB *)db185p->internal;
|
||||
|
||||
switch (flags) {
|
||||
case 0:
|
||||
break;
|
||||
case R_RECNOSYNC:
|
||||
/*
|
||||
* !!!
|
||||
* We can't support the R_RECNOSYNC flag.
|
||||
*/
|
||||
#define RSMSG "DB: DB 1.85's R_RECNOSYNC sync flag is not supported.\n"
|
||||
(void)__os_write(2, RSMSG, sizeof(RSMSG) - 1);
|
||||
goto einval;
|
||||
default:
|
||||
goto einval;
|
||||
}
|
||||
|
||||
return ((errno = dbp->sync(dbp, 0)) == 0 ? 0 : -1);
|
||||
|
||||
einval: errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994, 1995, 1996
|
||||
* Keith Bostic. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)db185_int.h 8.7 (Sleepycat) 4/10/98
|
||||
*/
|
||||
|
||||
#ifndef _DB185_H_
|
||||
#define _DB185_H_
|
||||
|
||||
/* Routine flags. */
|
||||
#define R_CURSOR 1 /* del, put, seq */
|
||||
#define __R_UNUSED 2 /* UNUSED */
|
||||
#define R_FIRST 3 /* seq */
|
||||
#define R_IAFTER 4 /* put (RECNO) */
|
||||
#define R_IBEFORE 5 /* put (RECNO) */
|
||||
#define R_LAST 6 /* seq (BTREE, RECNO) */
|
||||
#define R_NEXT 7 /* seq */
|
||||
#define R_NOOVERWRITE 8 /* put */
|
||||
#define R_PREV 9 /* seq (BTREE, RECNO) */
|
||||
#define R_SETCURSOR 10 /* put (RECNO) */
|
||||
#define R_RECNOSYNC 11 /* sync (RECNO) */
|
||||
|
||||
typedef struct {
|
||||
void *data; /* data */
|
||||
size_t size; /* data length */
|
||||
} DBT185;
|
||||
|
||||
/* Access method description structure. */
|
||||
typedef struct __db185 {
|
||||
DBTYPE type; /* Underlying db type. */
|
||||
int (*close) __P((struct __db185 *));
|
||||
int (*del) __P((const struct __db185 *, const DBT185 *, u_int));
|
||||
int (*get)
|
||||
__P((const struct __db185 *, const DBT185 *, DBT185 *, u_int));
|
||||
int (*put)
|
||||
__P((const struct __db185 *, DBT185 *, const DBT185 *, u_int));
|
||||
int (*seq)
|
||||
__P((const struct __db185 *, DBT185 *, DBT185 *, u_int));
|
||||
int (*sync) __P((const struct __db185 *, u_int));
|
||||
void *internal; /* Access method private. */
|
||||
int (*fd) __P((const struct __db185 *));
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* Added to the end of the DB 1.85 DB structure, it's needed to
|
||||
* hold the DB 2.0 cursor used for DB 1.85 sequential operations.
|
||||
*/
|
||||
DBC *dbc; /* DB 1.85 sequential cursor. */
|
||||
} DB185;
|
||||
|
||||
/* Structure used to pass parameters to the btree routines. */
|
||||
typedef struct {
|
||||
#define R_DUP 0x01 /* duplicate keys */
|
||||
u_int32_t flags;
|
||||
u_int32_t cachesize; /* bytes to cache */
|
||||
u_int32_t maxkeypage; /* maximum keys per page */
|
||||
u_int32_t minkeypage; /* minimum keys per page */
|
||||
u_int32_t psize; /* page size */
|
||||
int (*compare) /* comparison function */
|
||||
__P((const DBT *, const DBT *));
|
||||
size_t (*prefix) /* prefix function */
|
||||
__P((const DBT *, const DBT *));
|
||||
int lorder; /* byte order */
|
||||
} BTREEINFO;
|
||||
|
||||
/* Structure used to pass parameters to the hashing routines. */
|
||||
typedef struct {
|
||||
u_int32_t bsize; /* bucket size */
|
||||
u_int32_t ffactor; /* fill factor */
|
||||
u_int32_t nelem; /* number of elements */
|
||||
u_int32_t cachesize; /* bytes to cache */
|
||||
u_int32_t /* hash function */
|
||||
(*hash) __P((const void *, size_t));
|
||||
int lorder; /* byte order */
|
||||
} HASHINFO;
|
||||
|
||||
/* Structure used to pass parameters to the record routines. */
|
||||
typedef struct {
|
||||
#define R_FIXEDLEN 0x01 /* fixed-length records */
|
||||
#define R_NOKEY 0x02 /* key not required */
|
||||
#define R_SNAPSHOT 0x04 /* snapshot the input */
|
||||
u_int32_t flags;
|
||||
u_int32_t cachesize; /* bytes to cache */
|
||||
u_int32_t psize; /* page size */
|
||||
int lorder; /* byte order */
|
||||
size_t reclen; /* record length (fixed-length records) */
|
||||
u_char bval; /* delimiting byte (variable-length records */
|
||||
char *bfname; /* btree file name */
|
||||
} RECNOINFO;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
DB185 *dbopen __P((const char *, int, int, DBTYPE, const void *));
|
||||
#if defined(__cplusplus)
|
||||
};
|
||||
#endif
|
||||
#endif /* !_DB185_H_ */
|
|
@ -1,167 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1996, 1997, 1998\n\
|
||||
Sleepycat Software Inc. All rights reserved.\n";
|
||||
static const char sccsid[] = "@(#)db_archive.c 10.17 (Sleepycat) 4/10/98";
|
||||
#endif
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "shqueue.h"
|
||||
#include "log.h"
|
||||
#include "db_dispatch.h"
|
||||
#include "clib_ext.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
DB_ENV *db_init __P((char *, int));
|
||||
void onint __P((int));
|
||||
int main __P((int, char *[]));
|
||||
void siginit __P((void));
|
||||
void usage __P((void));
|
||||
|
||||
int interrupted;
|
||||
const char
|
||||
*progname = "db_archive"; /* Program name. */
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
DB_ENV *dbenv;
|
||||
u_int32_t flags;
|
||||
int ch, verbose;
|
||||
char *home, **list;
|
||||
|
||||
flags = verbose = 0;
|
||||
home = NULL;
|
||||
while ((ch = getopt(argc, argv, "ah:lsv")) != EOF)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
flags |= DB_ARCH_ABS;
|
||||
break;
|
||||
case 'h':
|
||||
home = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
flags |= DB_ARCH_LOG;
|
||||
break;
|
||||
case 's':
|
||||
flags |= DB_ARCH_DATA;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 0)
|
||||
usage();
|
||||
|
||||
/* Initialize the environment. */
|
||||
dbenv = db_init(home, verbose);
|
||||
|
||||
/* Get the list of names. */
|
||||
if ((errno = log_archive(dbenv->lg_info, &list, flags, NULL)) != 0) {
|
||||
(void)db_appexit(dbenv);
|
||||
err(1, "log_archive");
|
||||
}
|
||||
|
||||
/* Print the names. */
|
||||
if (list != NULL)
|
||||
for (; *list != NULL; ++list)
|
||||
printf("%s\n", *list);
|
||||
|
||||
return (db_appexit(dbenv) ? 1 : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* db_init --
|
||||
* Initialize the environment.
|
||||
*/
|
||||
DB_ENV *
|
||||
db_init(home, verbose)
|
||||
char *home;
|
||||
int verbose;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
|
||||
if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
err(1, NULL);
|
||||
}
|
||||
dbenv->db_errfile = stderr;
|
||||
dbenv->db_errpfx = progname;
|
||||
dbenv->db_verbose = verbose;
|
||||
|
||||
if ((errno = db_appinit(home, NULL, dbenv,
|
||||
DB_CREATE | DB_INIT_LOG | DB_INIT_TXN | DB_USE_ENVIRON)) != 0)
|
||||
err(1, "db_appinit");
|
||||
|
||||
siginit();
|
||||
|
||||
return (dbenv);
|
||||
}
|
||||
|
||||
/*
|
||||
* siginit --
|
||||
* Initialize the set of signals for which we want to clean up.
|
||||
* Generally, we try not to leave the shared regions locked if
|
||||
* we can.
|
||||
*/
|
||||
void
|
||||
siginit()
|
||||
{
|
||||
#ifdef SIGHUP
|
||||
(void)signal(SIGHUP, onint);
|
||||
#endif
|
||||
(void)signal(SIGINT, onint);
|
||||
#ifdef SIGKILL
|
||||
(void)signal(SIGKILL, onint);
|
||||
#endif
|
||||
(void)signal(SIGTERM, onint);
|
||||
}
|
||||
|
||||
/*
|
||||
* oninit --
|
||||
* Interrupt signal handler.
|
||||
*/
|
||||
void
|
||||
onint(signo)
|
||||
int signo;
|
||||
{
|
||||
if ((interrupted = signo) == 0)
|
||||
interrupted = SIGINT;
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: db_archive [-alsv] [-h home]\n");
|
||||
exit(1);
|
||||
}
|
|
@ -1,264 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1996, 1997, 1998\n\
|
||||
Sleepycat Software Inc. All rights reserved.\n";
|
||||
static const char sccsid[] = "@(#)db_checkpoint.c 10.17 (Sleepycat) 5/3/98";
|
||||
#endif
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "shqueue.h"
|
||||
#include "db_page.h"
|
||||
#include "log.h"
|
||||
#include "btree.h"
|
||||
#include "hash.h"
|
||||
#include "clib_ext.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
char *check __P((DB_ENV *, long, long));
|
||||
DB_ENV *db_init __P((char *));
|
||||
int logpid __P((char *, int));
|
||||
int main __P((int, char *[]));
|
||||
void onint __P((int));
|
||||
void siginit __P((void));
|
||||
void usage __P((void));
|
||||
|
||||
int interrupted;
|
||||
const char
|
||||
*progname = "db_checkpoint"; /* Program name. */
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
DB_ENV *dbenv;
|
||||
time_t now;
|
||||
long argval;
|
||||
u_int32_t kbytes, minutes, seconds;
|
||||
int ch, eval, once, verbose;
|
||||
char *home, *logfile;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Don't allow a fully unsigned 32-bit number, some compilers get
|
||||
* upset and require it to be specified in hexadecimal and so on.
|
||||
*/
|
||||
#define MAX_UINT32_T 2147483647
|
||||
|
||||
kbytes = minutes = 0;
|
||||
once = verbose = 0;
|
||||
home = logfile = NULL;
|
||||
while ((ch = getopt(argc, argv, "1h:k:L:p:v")) != EOF)
|
||||
switch (ch) {
|
||||
case '1':
|
||||
once = 1;
|
||||
break;
|
||||
case 'h':
|
||||
home = optarg;
|
||||
break;
|
||||
case 'k':
|
||||
get_long(optarg, 1, (long)MAX_UINT32_T, &argval);
|
||||
kbytes = argval;
|
||||
break;
|
||||
case 'L':
|
||||
logfile = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
get_long(optarg, 1, (long)MAX_UINT32_T, &argval);
|
||||
minutes = argval;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 0)
|
||||
usage();
|
||||
|
||||
if (once == 0 && kbytes == 0 && minutes == 0) {
|
||||
warnx("at least one of -1, -k and -p must be specified");
|
||||
usage();
|
||||
}
|
||||
|
||||
/* Initialize the environment. */
|
||||
dbenv = db_init(home);
|
||||
|
||||
if (logfile != NULL && logpid(logfile, 1)) {
|
||||
(void)db_appexit(dbenv);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have only a time delay, then we'll sleep the right amount
|
||||
* to wake up when a checkpoint is necessary. If we have a "kbytes"
|
||||
* field set, then we'll check every 30 seconds.
|
||||
*/
|
||||
eval = 0;
|
||||
seconds = kbytes != 0 ? 30 : minutes * 60;
|
||||
while (!interrupted) {
|
||||
if (verbose) {
|
||||
(void)time(&now);
|
||||
printf("checkpoint: %s", ctime(&now));
|
||||
}
|
||||
errno = txn_checkpoint(dbenv->tx_info, kbytes, minutes);
|
||||
|
||||
while (errno == DB_INCOMPLETE) {
|
||||
if (verbose)
|
||||
__db_err(dbenv,
|
||||
"checkpoint did not finish, retrying");
|
||||
(void)__db_sleep(2, 0);
|
||||
errno = txn_checkpoint(dbenv->tx_info, 0, 0);
|
||||
}
|
||||
|
||||
if (errno != 0) {
|
||||
eval = 1;
|
||||
__db_err(dbenv, "checkpoint: %s", strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
if (once)
|
||||
break;
|
||||
|
||||
(void)__db_sleep(seconds, 0);
|
||||
}
|
||||
|
||||
if (logfile != NULL && logpid(logfile, 0))
|
||||
eval = 1;
|
||||
|
||||
if (interrupted) {
|
||||
(void)signal(interrupted, SIG_DFL);
|
||||
(void)raise(interrupted);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
return (db_appexit(dbenv) || eval ? 1 : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* db_init --
|
||||
* Initialize the environment.
|
||||
*/
|
||||
DB_ENV *
|
||||
db_init(home)
|
||||
char *home;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
|
||||
if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
err(1, NULL);
|
||||
}
|
||||
dbenv->db_errfile = stderr;
|
||||
dbenv->db_errpfx = progname;
|
||||
|
||||
if ((errno = db_appinit(home, NULL, dbenv,
|
||||
DB_INIT_LOG | DB_INIT_TXN | DB_INIT_MPOOL | DB_USE_ENVIRON)) != 0)
|
||||
err(1, "db_appinit");
|
||||
|
||||
if (memp_register(dbenv->mp_info,
|
||||
DB_FTYPE_BTREE, __bam_pgin, __bam_pgout) ||
|
||||
memp_register(dbenv->mp_info,
|
||||
DB_FTYPE_HASH, __ham_pgin, __ham_pgout)) {
|
||||
(void)db_appexit(dbenv);
|
||||
errx(1,
|
||||
"db_appinit: failed to register access method functions");
|
||||
}
|
||||
|
||||
siginit();
|
||||
|
||||
return (dbenv);
|
||||
}
|
||||
|
||||
/*
|
||||
* logpid --
|
||||
* Log that we're running.
|
||||
*/
|
||||
int
|
||||
logpid(fname, is_open)
|
||||
char *fname;
|
||||
int is_open;
|
||||
{
|
||||
FILE *fp;
|
||||
time_t now;
|
||||
|
||||
if (is_open) {
|
||||
if ((fp = fopen(fname, "w")) == NULL) {
|
||||
warn("%s", fname);
|
||||
return (1);
|
||||
}
|
||||
(void)time(&now);
|
||||
fprintf(fp,
|
||||
"%.24s: %lu %s", progname, (u_long)getpid(), ctime(&now));
|
||||
fclose(fp);
|
||||
} else
|
||||
(void)remove(fname);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* siginit --
|
||||
* Initialize the set of signals for which we want to clean up.
|
||||
* Generally, we try not to leave the shared regions locked if
|
||||
* we can.
|
||||
*/
|
||||
void
|
||||
siginit()
|
||||
{
|
||||
#ifdef SIGHUP
|
||||
(void)signal(SIGHUP, onint);
|
||||
#endif
|
||||
(void)signal(SIGINT, onint);
|
||||
#ifdef SIGKILL
|
||||
(void)signal(SIGKILL, onint);
|
||||
#endif
|
||||
(void)signal(SIGTERM, onint);
|
||||
}
|
||||
|
||||
/*
|
||||
* oninit --
|
||||
* Interrupt signal handler.
|
||||
*/
|
||||
void
|
||||
onint(signo)
|
||||
int signo;
|
||||
{
|
||||
if ((interrupted = signo) == 0)
|
||||
interrupted = SIGINT;
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: db_checkpoint [-1v] [-h home] [-k kbytes] [-L file] [-p min]\n");
|
||||
exit(1);
|
||||
}
|
|
@ -1,241 +0,0 @@
|
|||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1996, 1997, 1998\n\
|
||||
Sleepycat Software Inc. All rights reserved.\n";
|
||||
static const char sccsid[] = "@(#)db_deadlock.c 10.19 (Sleepycat) 4/10/98";
|
||||
#endif
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "clib_ext.h"
|
||||
#include "common_ext.h"
|
||||
|
||||
#define BAD_KILLID 0xffffffff
|
||||
|
||||
DB_ENV *db_init __P((char *, int));
|
||||
int logpid __P((char *, int));
|
||||
int main __P((int, char *[]));
|
||||
void onint __P((int));
|
||||
void siginit __P((void));
|
||||
void usage __P((void));
|
||||
|
||||
int interrupted;
|
||||
const char
|
||||
*progname = "db_deadlock"; /* Program name. */
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
DB_ENV *dbenv;
|
||||
u_int32_t atype;
|
||||
time_t now;
|
||||
long usecs;
|
||||
u_int32_t flags;
|
||||
int ch, verbose;
|
||||
char *home, *logfile;
|
||||
|
||||
atype = DB_LOCK_DEFAULT;
|
||||
home = logfile = NULL;
|
||||
usecs = 0;
|
||||
flags = 0;
|
||||
verbose = 0;
|
||||
while ((ch = getopt(argc, argv, "a:h:L:t:vw")) != EOF)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
switch (optarg[0]) {
|
||||
case 'o':
|
||||
atype = DB_LOCK_OLDEST;
|
||||
break;
|
||||
case 'y':
|
||||
atype = DB_LOCK_YOUNGEST;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
if (optarg[1] != '\0')
|
||||
usage();
|
||||
break;
|
||||
case 'h':
|
||||
home = optarg;
|
||||
break;
|
||||
case 'L':
|
||||
logfile = optarg;
|
||||
break;
|
||||
case 't':
|
||||
get_long(optarg, 1, LONG_MAX, &usecs);
|
||||
usecs *= 1000000;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'w':
|
||||
LF_SET(DB_LOCK_CONFLICT);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 0)
|
||||
usage();
|
||||
|
||||
if (usecs == 0 && !LF_ISSET(DB_LOCK_CONFLICT)) {
|
||||
warnx("at least one of -t and -w must be specified");
|
||||
usage();
|
||||
}
|
||||
|
||||
/*
|
||||
* We detect every 100ms (100000 us) when we're running in
|
||||
* DB_LOCK_CONFLICT mode.
|
||||
*/
|
||||
if (usecs == 0)
|
||||
usecs = 100000;
|
||||
|
||||
/* Initialize the deadlock detector by opening the lock manager. */
|
||||
dbenv = db_init(home, verbose);
|
||||
|
||||
if (logfile != NULL && logpid(logfile, 1)) {
|
||||
(void)db_appexit(dbenv);
|
||||
return (1);
|
||||
}
|
||||
|
||||
while (!interrupted) {
|
||||
if (dbenv->db_verbose != 0) {
|
||||
time(&now);
|
||||
__db_err(dbenv, "Running at %.24s", ctime(&now));
|
||||
}
|
||||
|
||||
if ((errno = lock_detect(dbenv->lk_info, flags, atype)) != 0)
|
||||
break;
|
||||
|
||||
/* Make a pass every "usecs" usecs. */
|
||||
(void)__db_sleep(0, usecs);
|
||||
}
|
||||
|
||||
if (logfile != NULL)
|
||||
(void)logpid(logfile, 0);
|
||||
|
||||
if (interrupted) {
|
||||
(void)signal(interrupted, SIG_DFL);
|
||||
(void)raise(interrupted);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
return (db_appexit(dbenv));
|
||||
}
|
||||
|
||||
DB_ENV *
|
||||
db_init(home, verbose)
|
||||
char *home;
|
||||
int verbose;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
|
||||
if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
err(1, NULL);
|
||||
}
|
||||
dbenv->db_errfile = stderr;
|
||||
dbenv->db_errpfx = progname;
|
||||
dbenv->db_verbose = verbose;
|
||||
|
||||
if ((errno = db_appinit(home,
|
||||
NULL, dbenv, DB_INIT_LOCK | DB_USE_ENVIRON)) != 0)
|
||||
err(1, "db_appinit");
|
||||
|
||||
siginit();
|
||||
|
||||
return (dbenv);
|
||||
}
|
||||
|
||||
/*
|
||||
* logpid --
|
||||
* Log that we're running.
|
||||
*/
|
||||
int
|
||||
logpid(fname, is_open)
|
||||
char *fname;
|
||||
int is_open;
|
||||
{
|
||||
FILE *fp;
|
||||
time_t now;
|
||||
|
||||
if (is_open) {
|
||||
if ((fp = fopen(fname, "w")) == NULL) {
|
||||
warn("%s", fname);
|
||||
return (1);
|
||||
}
|
||||
(void)time(&now);
|
||||
fprintf(fp,
|
||||
"%.24s: %lu %s", progname, (u_long)getpid(), ctime(&now));
|
||||
fclose(fp);
|
||||
} else
|
||||
(void)remove(fname);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* siginit --
|
||||
* Initialize the set of signals for which we want to clean up.
|
||||
* Generally, we try not to leave the shared regions locked if
|
||||
* we can.
|
||||
*/
|
||||
void
|
||||
siginit()
|
||||
{
|
||||
#ifdef SIGHUP
|
||||
(void)signal(SIGHUP, onint);
|
||||
#endif
|
||||
(void)signal(SIGINT, onint);
|
||||
#ifdef SIGKILL
|
||||
(void)signal(SIGKILL, onint);
|
||||
#endif
|
||||
(void)signal(SIGTERM, onint);
|
||||
}
|
||||
|
||||
/*
|
||||
* oninit --
|
||||
* Interrupt signal handler.
|
||||
*/
|
||||
void
|
||||
onint(signo)
|
||||
int signo;
|
||||
{
|
||||
if ((interrupted = signo) == 0)
|
||||
interrupted = SIGINT;
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: db_deadlock [-vw] [-a m | o | y] [-h home] [-L file] [-t sec]\n");
|
||||
exit(1);
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче