Cheery picked Antony's patch to allow for Window's builds in 5.1

This commit is contained in:
brian@zim.(none) 2006-08-15 21:49:26 -07:00
parent 8d83366bac
commit 183f028633
461 changed files with 2 additions and 178414 deletions

View file

@ -6571,7 +6571,7 @@ void Field_varstring::sql_type(String &res) const
}
uint Field_varstring::data_length(const char *from)
uint32 Field_varstring::data_length(const char *from)
{
return length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
}

View file

@ -1126,7 +1126,7 @@ public:
int key_cmp(const byte *str, uint length);
uint packed_col_length(const char *to, uint length);
uint max_packed_col_length(uint max_length);
uint data_length(const char *from);
uint32 data_length(const char *from);
uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; }
bool has_charset(void) const

File diff suppressed because it is too large Load diff

View file

@ -1,213 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* 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. 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.
*
* $Id: bt_compare.c,v 12.1 2005/06/16 20:20:13 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/btree.h"
/*
* __bam_cmp --
* Compare a key to a given record.
*
* PUBLIC: int __bam_cmp __P((DB *, const DBT *, PAGE *,
* PUBLIC: u_int32_t, int (*)(DB *, const DBT *, const DBT *), int *));
*/
int
__bam_cmp(dbp, dbt, h, indx, func, cmpp)
DB *dbp;
const DBT *dbt;
PAGE *h;
u_int32_t indx;
int (*func)__P((DB *, const DBT *, const DBT *));
int *cmpp;
{
BINTERNAL *bi;
BKEYDATA *bk;
BOVERFLOW *bo;
DBT pg_dbt;
/*
* Returns:
* < 0 if dbt is < page record
* = 0 if dbt is = page record
* > 0 if dbt is > page record
*
* !!!
* We do not clear the pg_dbt DBT even though it's likely to contain
* random bits. That should be okay, because the app's comparison
* routine had better not be looking at fields other than data/size.
* We don't clear it because we go through this path a lot and it's
* expensive.
*/
switch (TYPE(h)) {
case P_LBTREE:
case P_LDUP:
case P_LRECNO:
bk = GET_BKEYDATA(dbp, h, indx);
if (B_TYPE(bk->type) == B_OVERFLOW)
bo = (BOVERFLOW *)bk;
else {
pg_dbt.data = bk->data;
pg_dbt.size = bk->len;
*cmpp = func(dbp, dbt, &pg_dbt);
return (0);
}
break;
case P_IBTREE:
/*
* The following code guarantees that the left-most key on an
* internal page at any place in the tree sorts less than any
* user-specified key. The reason is that if we have reached
* this internal page, we know the user key must sort greater
* than the key we're storing for this page in any internal
* pages at levels above us in the tree. It then follows that
* any user-specified key cannot sort less than the first page
* which we reference, and so there's no reason to call the
* comparison routine. While this may save us a comparison
* routine call or two, the real reason for this is because
* we don't maintain a copy of the smallest key in the tree,
* so that we don't have to update all the levels of the tree
* should the application store a new smallest key. And, so,
* we may not have a key to compare, which makes doing the
* comparison difficult and error prone.
*/
if (indx == 0) {
*cmpp = 1;
return (0);
}
bi = GET_BINTERNAL(dbp, h, indx);
if (B_TYPE(bi->type) == B_OVERFLOW)
bo = (BOVERFLOW *)(bi->data);
else {
pg_dbt.data = bi->data;
pg_dbt.size = bi->len;
*cmpp = func(dbp, dbt, &pg_dbt);
return (0);
}
break;
default:
return (__db_pgfmt(dbp->dbenv, PGNO(h)));
}
/*
* Overflow.
*/
return (__db_moff(dbp, dbt,
bo->pgno, bo->tlen, func == __bam_defcmp ? NULL : func, cmpp));
}
/*
* __bam_defcmp --
* Default comparison routine.
*
* PUBLIC: int __bam_defcmp __P((DB *, const DBT *, const DBT *));
*/
int
__bam_defcmp(dbp, a, b)
DB *dbp;
const DBT *a, *b;
{
size_t len;
u_int8_t *p1, *p2;
COMPQUIET(dbp, NULL);
/*
* 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((DB *, const DBT *, const DBT *));
*/
size_t
__bam_defpfx(dbp, a, b)
DB *dbp;
const DBT *a, *b;
{
size_t cnt, len;
u_int8_t *p1, *p2;
COMPQUIET(dbp, NULL);
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);
/*
* They match up to the smaller of the two sizes.
* Collate the longer after the shorter.
*/
if (a->size < b->size)
return (a->size + 1);
if (b->size < a->size)
return (b->size + 1);
return (b->size);
}

View file

@ -1,100 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_conv.c,v 12.2 2005/06/16 20:20:13 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_swap.h"
#include "dbinc/btree.h"
/*
* __bam_pgin --
* Convert host-specific page layout from the host-independent format
* stored on disk.
*
* PUBLIC: int __bam_pgin __P((DB_ENV *, DB *, db_pgno_t, void *, DBT *));
*/
int
__bam_pgin(dbenv, dummydbp, pg, pp, cookie)
DB_ENV *dbenv;
DB *dummydbp;
db_pgno_t pg;
void *pp;
DBT *cookie;
{
DB_PGINFO *pginfo;
PAGE *h;
pginfo = (DB_PGINFO *)cookie->data;
if (!F_ISSET(pginfo, DB_AM_SWAP))
return (0);
h = pp;
return (TYPE(h) == P_BTREEMETA ? __bam_mswap(pp) :
__db_byteswap(dbenv, dummydbp, pg, pp, pginfo->db_pagesize, 1));
}
/*
* __bam_pgout --
* Convert host-specific page layout to the host-independent format
* stored on disk.
*
* PUBLIC: int __bam_pgout __P((DB_ENV *, DB *, db_pgno_t, void *, DBT *));
*/
int
__bam_pgout(dbenv, dummydbp, pg, pp, cookie)
DB_ENV *dbenv;
DB *dummydbp;
db_pgno_t pg;
void *pp;
DBT *cookie;
{
DB_PGINFO *pginfo;
PAGE *h;
pginfo = (DB_PGINFO *)cookie->data;
if (!F_ISSET(pginfo, DB_AM_SWAP))
return (0);
h = pp;
return (TYPE(h) == P_BTREEMETA ? __bam_mswap(pp) :
__db_byteswap(dbenv, dummydbp, pg, pp, pginfo->db_pagesize, 0));
}
/*
* __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;
__db_metaswap(pg);
p = (u_int8_t *)pg + sizeof(DBMETA);
p += sizeof(u_int32_t); /* unused */
SWAP32(p); /* minkey */
SWAP32(p); /* re_len */
SWAP32(p); /* re_pad */
SWAP32(p); /* root */
p += 92 * sizeof(u_int32_t); /* unused */
SWAP32(p); /* crypto_magic */
return (0);
}

View file

@ -1,590 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_curadj.c,v 12.3 2005/07/20 16:50:45 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/btree.h"
static int __bam_opd_cursor __P((DB *, DBC *, db_pgno_t, u_int32_t, u_int32_t));
/*
* Cursor adjustments are logged if they are for subtransactions. This is
* because it's possible for a subtransaction to adjust cursors which will
* still be active after the subtransaction aborts, and so which must be
* restored to their previous locations. Cursors that can be both affected
* by our cursor adjustments and active after our transaction aborts can
* only be found in our parent transaction -- cursors in other transactions,
* including other child transactions of our parent, must have conflicting
* locker IDs, and so cannot be affected by adjustments in this transaction.
*/
/*
* __bam_ca_delete --
* Update the cursors when items are deleted and when already deleted
* items are overwritten. Return the number of relevant cursors found.
*
* PUBLIC: int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, int, int *));
*/
int
__bam_ca_delete(dbp, pgno, indx, delete, countp)
DB *dbp;
db_pgno_t pgno;
u_int32_t indx;
int delete, *countp;
{
BTREE_CURSOR *cp;
DB *ldbp;
DB_ENV *dbenv;
DBC *dbc;
int count; /* !!!: Has to contain max number of cursors. */
dbenv = dbp->dbenv;
/*
* Adjust the cursors. We have the page write locked, so the
* only other cursors that can be pointing at a page are
* those in the same thread of control. Unfortunately, we don't
* know that they're using the same DB handle, so traverse
* all matching DB handles in the same DB_ENV, then all cursors
* on each matching DB handle.
*
* Each cursor is single-threaded, so we only need to lock the
* list of DBs and then the list of cursors in each DB.
*/
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (count = 0, ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (BTREE_CURSOR *)dbc->internal;
if (cp->pgno == pgno && cp->indx == indx) {
/*
* [#8032] This assert is checking
* for possible race conditions where we
* hold a cursor position without a lock.
* Unfortunately, there are paths in the
* Btree code that do not satisfy these
* conditions. None of them are known to
* be a problem, but this assert should
* be re-activated when the Btree stack
* code is re-written.
DB_ASSERT(!STD_LOCKING(dbc) ||
cp->lock_mode != DB_LOCK_NG);
*/
if (delete)
F_SET(cp, C_DELETED);
else
F_CLR(cp, C_DELETED);
++count;
}
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (countp != NULL)
*countp = count;
return (0);
}
/*
* __ram_ca_delete --
* Return if any relevant cursors found.
*
* PUBLIC: int __ram_ca_delete __P((DB *, db_pgno_t, int *));
*/
int
__ram_ca_delete(dbp, root_pgno, foundp)
DB *dbp;
db_pgno_t root_pgno;
int *foundp;
{
DB *ldbp;
DBC *dbc;
DB_ENV *dbenv;
int found;
found = 0;
dbenv = dbp->dbenv;
/*
* Review the cursors. See the comment in __bam_ca_delete().
*/
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
found == 0 && ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
found == 0 && dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
if (dbc->internal->root == root_pgno)
found = 1;
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
*foundp = found;
return (0);
}
/*
* __bam_ca_di --
* Adjust the cursors during a delete or insert.
*
* PUBLIC: int __bam_ca_di __P((DBC *, db_pgno_t, u_int32_t, int));
*/
int
__bam_ca_di(my_dbc, pgno, indx, adjust)
DBC *my_dbc;
db_pgno_t pgno;
u_int32_t indx;
int adjust;
{
DB *dbp, *ldbp;
DB_ENV *dbenv;
DB_LSN lsn;
DB_TXN *my_txn;
DBC *dbc;
DBC_INTERNAL *cp;
int found, ret;
dbp = my_dbc->dbp;
dbenv = dbp->dbenv;
my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL;
/*
* Adjust the cursors. See the comment in __bam_ca_delete().
*/
found = 0;
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO)
continue;
cp = dbc->internal;
if (cp->pgno == pgno && cp->indx >= indx) {
/* Cursor indices should never be negative. */
DB_ASSERT(cp->indx != 0 || adjust > 0);
/* [#8032]
DB_ASSERT(!STD_LOCKING(dbc) ||
cp->lock_mode != DB_LOCK_NG);
*/
cp->indx += adjust;
if (my_txn != NULL && dbc->txn != my_txn)
found = 1;
}
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn, &lsn, 0,
DB_CA_DI, pgno, 0, 0, (u_int32_t)adjust, indx, 0)) != 0)
return (ret);
}
return (0);
}
/*
* __bam_opd_cursor -- create a new opd cursor.
*/
static int
__bam_opd_cursor(dbp, dbc, first, tpgno, ti)
DB *dbp;
DBC *dbc;
db_pgno_t tpgno;
u_int32_t first, ti;
{
BTREE_CURSOR *cp, *orig_cp;
DBC *dbc_nopd;
int ret;
orig_cp = (BTREE_CURSOR *)dbc->internal;
dbc_nopd = NULL;
/*
* Allocate a new cursor and create the stack. If duplicates
* are sorted, we've just created an off-page duplicate Btree.
* If duplicates aren't sorted, we've just created a Recno tree.
*
* Note that in order to get here at all, there shouldn't be
* an old off-page dup cursor--to augment the checking db_c_newopd
* will do, assert this.
*/
DB_ASSERT(orig_cp->opd == NULL);
if ((ret = __db_c_newopd(dbc, tpgno, orig_cp->opd, &dbc_nopd)) != 0)
return (ret);
cp = (BTREE_CURSOR *)dbc_nopd->internal;
cp->pgno = tpgno;
cp->indx = ti;
if (dbp->dup_compare == NULL) {
/*
* Converting to off-page Recno trees is tricky. The
* record number for the cursor is the index + 1 (to
* convert to 1-based record numbers).
*/
cp->recno = ti + 1;
}
/*
* Transfer the deleted flag from the top-level cursor to the
* created one.
*/
if (F_ISSET(orig_cp, C_DELETED)) {
F_SET(cp, C_DELETED);
F_CLR(orig_cp, C_DELETED);
}
/* Stack the cursors and reset the initial cursor's index. */
orig_cp->opd = dbc_nopd;
orig_cp->indx = first;
return (0);
}
/*
* __bam_ca_dup --
* Adjust the cursors when moving items from a leaf page to a duplicates
* page.
*
* PUBLIC: int __bam_ca_dup __P((DBC *,
* PUBLIC: u_int32_t, db_pgno_t, u_int32_t, db_pgno_t, u_int32_t));
*/
int
__bam_ca_dup(my_dbc, first, fpgno, fi, tpgno, ti)
DBC *my_dbc;
db_pgno_t fpgno, tpgno;
u_int32_t first, fi, ti;
{
BTREE_CURSOR *orig_cp;
DB *dbp, *ldbp;
DBC *dbc;
DB_ENV *dbenv;
DB_LSN lsn;
DB_TXN *my_txn;
int found, ret;
dbp = my_dbc->dbp;
dbenv = dbp->dbenv;
my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL;
/*
* Adjust the cursors. See the comment in __bam_ca_delete().
*/
found = 0;
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
loop: MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
/* Find cursors pointing to this record. */
orig_cp = (BTREE_CURSOR *)dbc->internal;
if (orig_cp->pgno != fpgno || orig_cp->indx != fi)
continue;
/*
* Since we rescan the list see if this is already
* converted.
*/
if (orig_cp->opd != NULL)
continue;
MUTEX_UNLOCK(dbenv, dbp->mutex);
/* [#8032]
DB_ASSERT(!STD_LOCKING(dbc) ||
orig_cp->lock_mode != DB_LOCK_NG);
*/
if ((ret = __bam_opd_cursor(dbp,
dbc, first, tpgno, ti)) !=0)
return (ret);
if (my_txn != NULL && dbc->txn != my_txn)
found = 1;
/* We released the mutex to get a cursor, start over. */
goto loop;
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn,
&lsn, 0, DB_CA_DUP, fpgno, tpgno, 0, first, fi, ti)) != 0)
return (ret);
}
return (0);
}
/*
* __bam_ca_undodup --
* Adjust the cursors when returning items to a leaf page
* from a duplicate page.
* Called only during undo processing.
*
* PUBLIC: int __bam_ca_undodup __P((DB *,
* PUBLIC: u_int32_t, db_pgno_t, u_int32_t, u_int32_t));
*/
int
__bam_ca_undodup(dbp, first, fpgno, fi, ti)
DB *dbp;
db_pgno_t fpgno;
u_int32_t first, fi, ti;
{
BTREE_CURSOR *orig_cp;
DB *ldbp;
DBC *dbc;
DB_ENV *dbenv;
int ret;
dbenv = dbp->dbenv;
/*
* Adjust the cursors. See the comment in __bam_ca_delete().
*/
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
loop: MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
orig_cp = (BTREE_CURSOR *)dbc->internal;
/*
* A note on the orig_cp->opd != NULL requirement here:
* it's possible that there's a cursor that refers to
* the same duplicate set, but which has no opd cursor,
* because it refers to a different item and we took
* care of it while processing a previous record.
*/
if (orig_cp->pgno != fpgno ||
orig_cp->indx != first ||
orig_cp->opd == NULL || ((BTREE_CURSOR *)
orig_cp->opd->internal)->indx != ti)
continue;
MUTEX_UNLOCK(dbenv, dbp->mutex);
if ((ret = __db_c_close(orig_cp->opd)) != 0)
return (ret);
orig_cp->opd = NULL;
orig_cp->indx = fi;
/*
* We released the mutex to free a cursor,
* start over.
*/
goto loop;
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (0);
}
/*
* __bam_ca_rsplit --
* Adjust the cursors when doing reverse splits.
*
* PUBLIC: int __bam_ca_rsplit __P((DBC *, db_pgno_t, db_pgno_t));
*/
int
__bam_ca_rsplit(my_dbc, fpgno, tpgno)
DBC* my_dbc;
db_pgno_t fpgno, tpgno;
{
DB *dbp, *ldbp;
DBC *dbc;
DB_ENV *dbenv;
DB_LSN lsn;
DB_TXN *my_txn;
int found, ret;
dbp = my_dbc->dbp;
dbenv = dbp->dbenv;
my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL;
/*
* Adjust the cursors. See the comment in __bam_ca_delete().
*/
found = 0;
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO)
continue;
if (dbc->internal->pgno == fpgno) {
dbc->internal->pgno = tpgno;
/* [#8032]
DB_ASSERT(!STD_LOCKING(dbc) ||
dbc->internal->lock_mode != DB_LOCK_NG);
*/
if (my_txn != NULL && dbc->txn != my_txn)
found = 1;
}
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn,
&lsn, 0, DB_CA_RSPLIT, fpgno, tpgno, 0, 0, 0, 0)) != 0)
return (ret);
}
return (0);
}
/*
* __bam_ca_split --
* Adjust the cursors when splitting a page.
*
* PUBLIC: int __bam_ca_split __P((DBC *,
* PUBLIC: db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t, int));
*/
int
__bam_ca_split(my_dbc, ppgno, lpgno, rpgno, split_indx, cleft)
DBC *my_dbc;
db_pgno_t ppgno, lpgno, rpgno;
u_int32_t split_indx;
int cleft;
{
DB *dbp, *ldbp;
DBC *dbc;
DBC_INTERNAL *cp;
DB_ENV *dbenv;
DB_LSN lsn;
DB_TXN *my_txn;
int found, ret;
dbp = my_dbc->dbp;
dbenv = dbp->dbenv;
my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL;
/*
* Adjust the cursors. See the comment in __bam_ca_delete().
*
* If splitting the page that a cursor was on, the cursor has to be
* adjusted to point to the same record as before the split. Most
* of the time we don't adjust pointers to the left page, because
* we're going to copy its contents back over the original page. If
* the cursor is on the right page, it is decremented by the number of
* records split to the left page.
*/
found = 0;
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO)
continue;
cp = dbc->internal;
if (cp->pgno == ppgno) {
/* [#8032]
DB_ASSERT(!STD_LOCKING(dbc) ||
cp->lock_mode != DB_LOCK_NG);
*/
if (my_txn != NULL && dbc->txn != my_txn)
found = 1;
if (cp->indx < split_indx) {
if (cleft)
cp->pgno = lpgno;
} else {
cp->pgno = rpgno;
cp->indx -= split_indx;
}
}
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp,
my_dbc->txn, &lsn, 0, DB_CA_SPLIT, ppgno, rpgno,
cleft ? lpgno : PGNO_INVALID, 0, split_indx, 0)) != 0)
return (ret);
}
return (0);
}
/*
* __bam_ca_undosplit --
* Adjust the cursors when undoing a split of a page.
* If we grew a level we will execute this for both the
* left and the right pages.
* Called only during undo processing.
*
* PUBLIC: int __bam_ca_undosplit __P((DB *,
* PUBLIC: db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t));
*/
int
__bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx)
DB *dbp;
db_pgno_t frompgno, topgno, lpgno;
u_int32_t split_indx;
{
DB *ldbp;
DBC *dbc;
DB_ENV *dbenv;
DBC_INTERNAL *cp;
dbenv = dbp->dbenv;
/*
* Adjust the cursors. See the comment in __bam_ca_delete().
*
* When backing out a split, we move the cursor back
* to the original offset and bump it by the split_indx.
*/
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO)
continue;
cp = dbc->internal;
if (cp->pgno == topgno) {
cp->pgno = frompgno;
cp->indx += split_indx;
} else if (cp->pgno == lpgno)
cp->pgno = frompgno;
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (0);
}

File diff suppressed because it is too large Load diff

View file

@ -1,643 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* 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. 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.
*
* $Id: bt_delete.c,v 12.13 2005/10/20 18:14:59 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/btree.h"
#include "dbinc/lock.h"
#include "dbinc/mp.h"
/*
* __bam_ditem --
* Delete one or more entries from a page.
*
* PUBLIC: int __bam_ditem __P((DBC *, PAGE *, u_int32_t));
*/
int
__bam_ditem(dbc, h, indx)
DBC *dbc;
PAGE *h;
u_int32_t indx;
{
BINTERNAL *bi;
BKEYDATA *bk;
DB *dbp;
DB_MPOOLFILE *mpf;
u_int32_t nbytes;
int ret;
db_indx_t *inp;
dbp = dbc->dbp;
mpf = dbp->mpf;
inp = P_INP(dbp, h);
switch (TYPE(h)) {
case P_IBTREE:
bi = GET_BINTERNAL(dbp, h, indx);
switch (B_TYPE(bi->type)) {
case B_DUPLICATE:
case B_KEYDATA:
nbytes = BINTERNAL_SIZE(bi->len);
break;
case B_OVERFLOW:
nbytes = BINTERNAL_SIZE(bi->len);
if ((ret =
__db_doff(dbc, ((BOVERFLOW *)bi->data)->pgno)) != 0)
return (ret);
break;
default:
return (__db_pgfmt(dbp->dbenv, PGNO(h)));
}
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.
*
* !!!
* 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) &&
inp[indx] == inp[indx + P_INDX])
return (__bam_adjindx(dbc,
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 && inp[indx] == inp[indx - P_INDX])
return (__bam_adjindx(dbc,
h, indx, indx - P_INDX, 0));
}
/* FALLTHROUGH */
case P_LDUP:
case P_LRECNO:
bk = GET_BKEYDATA(dbp, h, indx);
switch (B_TYPE(bk->type)) {
case B_DUPLICATE:
nbytes = BOVERFLOW_SIZE;
break;
case B_OVERFLOW:
nbytes = BOVERFLOW_SIZE;
if ((ret = __db_doff(
dbc, (GET_BOVERFLOW(dbp, h, indx))->pgno)) != 0)
return (ret);
break;
case B_KEYDATA:
nbytes = BKEYDATA_SIZE(bk->len);
break;
default:
return (__db_pgfmt(dbp->dbenv, PGNO(h)));
}
break;
default:
return (__db_pgfmt(dbp->dbenv, PGNO(h)));
}
/* Delete the item and mark the page dirty. */
if ((ret = __db_ditem(dbc, h, indx, nbytes)) != 0)
return (ret);
if ((ret = __memp_fset(mpf, h, DB_MPOOL_DIRTY)) != 0)
return (ret);
return (0);
}
/*
* __bam_adjindx --
* Adjust an index on the page.
*
* PUBLIC: int __bam_adjindx __P((DBC *, PAGE *, u_int32_t, u_int32_t, int));
*/
int
__bam_adjindx(dbc, h, indx, indx_copy, is_insert)
DBC *dbc;
PAGE *h;
u_int32_t indx, indx_copy;
int is_insert;
{
DB *dbp;
DB_MPOOLFILE *mpf;
db_indx_t copy, *inp;
int ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
inp = P_INP(dbp, h);
/* Log the change. */
if (DBC_LOGGING(dbc)) {
if ((ret = __bam_adj_log(dbp, dbc->txn, &LSN(h), 0,
PGNO(h), &LSN(h), indx, indx_copy, (u_int32_t)is_insert)) != 0)
return (ret);
} else
LSN_NOT_LOGGED(LSN(h));
/* Shuffle the indices and mark the page dirty. */
if (is_insert) {
copy = inp[indx_copy];
if (indx != NUM_ENT(h))
memmove(&inp[indx + O_INDX], &inp[indx],
sizeof(db_indx_t) * (NUM_ENT(h) - indx));
inp[indx] = copy;
++NUM_ENT(h);
} else {
--NUM_ENT(h);
if (indx != NUM_ENT(h))
memmove(&inp[indx], &inp[indx + O_INDX],
sizeof(db_indx_t) * (NUM_ENT(h) - indx));
}
if ((ret = __memp_fset(mpf, h, DB_MPOOL_DIRTY)) != 0)
return (ret);
return (0);
}
/*
* __bam_dpages --
* Delete a set of locked pages.
*
* PUBLIC: int __bam_dpages __P((DBC *, int, int));
*/
int
__bam_dpages(dbc, use_top, update)
DBC *dbc;
int use_top;
int update;
{
BTREE_CURSOR *cp;
BINTERNAL *bi;
DB *dbp;
DBT a, b;
DB_LOCK c_lock, p_lock;
DB_MPOOLFILE *mpf;
EPG *epg, *save_sp, *stack_epg;
PAGE *child, *parent;
db_indx_t nitems;
db_pgno_t pgno, root_pgno;
db_recno_t rcnt;
int done, ret, t_ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
nitems = 0;
pgno = PGNO_INVALID;
/*
* We have the entire stack of deletable pages locked.
*
* Btree calls us with the first page in the stack is to have a
* single item deleted, and the rest of the pages are to be removed.
*
* Recno always has a stack to the root and __bam_merge operations
* may have unneeded items in the sack. We find the lowest page
* in the stack that has more than one record in it and start there.
*/
ret = 0;
if (use_top)
stack_epg = cp->sp;
else
for (stack_epg = cp->csp; stack_epg > cp->sp; --stack_epg)
if (NUM_ENT(stack_epg->page) > 1)
break;
epg = stack_epg;
/*
* !!!
* 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. Before we unlink the subtree, we relink the
* leaf page chain.
*/
if (LEVEL(cp->csp->page) == 1 &&
(ret = __bam_relink(dbc, cp->csp->page, PGNO_INVALID)) != 0)
goto discard;
/*
* Delete the last item that references the underlying pages that are
* to be deleted, and adjust cursors that reference that page. Then,
* save that page's page number and item count and release it. If
* the application isn't retaining locks because it's running without
* transactions, this lets the rest of the tree get back to business
* immediately.
*/
if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0)
goto discard;
if ((ret = __bam_ca_di(dbc, PGNO(epg->page), epg->indx, -1)) != 0)
goto discard;
if (update && epg->indx == 0) {
save_sp = cp->csp;
cp->csp = epg;
ret = __bam_pupdate(dbc, epg->page);
cp->csp = save_sp;
if (ret != 0)
goto discard;
}
pgno = PGNO(epg->page);
nitems = NUM_ENT(epg->page);
ret = __memp_fput(mpf, epg->page, 0);
if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
goto err_inc;
/* Then, discard any pages that we don't care about. */
discard: for (epg = cp->sp; epg < stack_epg; ++epg) {
if ((t_ret = __memp_fput(mpf, epg->page, 0)) != 0 && ret == 0)
ret = t_ret;
epg->page = NULL;
if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
ret = t_ret;
}
if (ret != 0)
goto err;
/* Free the rest of the pages in the stack. */
while (++epg <= cp->csp) {
/*
* Delete page entries so they will be restored as part of
* recovery. We don't need to do cursor adjustment here as
* the pages are being emptied by definition and so cannot
* be referenced by a cursor.
*/
if (NUM_ENT(epg->page) != 0) {
DB_ASSERT(LEVEL(epg->page) != 1);
if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0)
goto err;
/*
* Sheer paranoia: if we find any pages that aren't
* emptied by the delete, someone else added an item
* while we were walking the tree, and we discontinue
* the delete. Shouldn't be possible, but we check
* regardless.
*/
if (NUM_ENT(epg->page) != 0)
goto err;
}
ret = __db_free(dbc, epg->page);
if (cp->page == epg->page)
cp->page = NULL;
epg->page = NULL;
if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
goto err_inc;
}
if (0) {
err_inc: ++epg;
err: for (; epg <= cp->csp; ++epg) {
if (epg->page != NULL)
(void)__memp_fput(mpf, epg->page, 0);
(void)__TLPUT(dbc, epg->lock);
}
BT_STK_CLR(cp);
return (ret);
}
BT_STK_CLR(cp);
/*
* If we just deleted the next-to-last item from the root page, the
* tree can collapse one or more levels. While there remains only a
* single item on the root page, write lock the last page referenced
* by the root page and copy it over the root page.
*/
root_pgno = cp->root;
if (pgno != root_pgno || nitems != 1)
return (0);
for (done = 0; !done;) {
/* Initialize. */
parent = child = NULL;
LOCK_INIT(p_lock);
LOCK_INIT(c_lock);
/* Lock the root. */
pgno = root_pgno;
if ((ret =
__db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &p_lock)) != 0)
goto stop;
if ((ret = __memp_fget(mpf, &pgno, 0, &parent)) != 0)
goto stop;
if (NUM_ENT(parent) != 1)
goto stop;
switch (TYPE(parent)) {
case P_IBTREE:
/*
* If this is overflow, then try to delete it.
* The child may or may not still point at it.
*/
bi = GET_BINTERNAL(dbp, parent, 0);
if (B_TYPE(bi->type) == B_OVERFLOW)
if ((ret = __db_doff(dbc,
((BOVERFLOW *)bi->data)->pgno)) != 0)
goto stop;
pgno = bi->pgno;
break;
case P_IRECNO:
pgno = GET_RINTERNAL(dbp, parent, 0)->pgno;
break;
default:
goto stop;
}
/* Lock the child page. */
if ((ret =
__db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &c_lock)) != 0)
goto stop;
if ((ret = __memp_fget(mpf, &pgno, 0, &child)) != 0)
goto stop;
/* Log the change. */
if (DBC_LOGGING(dbc)) {
memset(&a, 0, sizeof(a));
a.data = child;
a.size = dbp->pgsize;
memset(&b, 0, sizeof(b));
b.data = P_ENTRY(dbp, parent, 0);
b.size = TYPE(parent) == P_IRECNO ? RINTERNAL_SIZE :
BINTERNAL_SIZE(((BINTERNAL *)b.data)->len);
if ((ret = __bam_rsplit_log(dbp, dbc->txn,
&child->lsn, 0, PGNO(child), &a, PGNO(parent),
RE_NREC(parent), &b, &parent->lsn)) != 0)
goto stop;
} else
LSN_NOT_LOGGED(child->lsn);
/*
* Make the switch.
*
* One fixup -- internal pages below the top level do not store
* a record count, so we have to preserve it if we're not
* converting to a leaf page. Note also that we are about to
* overwrite the parent page, including its LSN. This is OK
* because the log message we wrote describing this update
* stores its LSN on the child page. When the child is copied
* onto the parent, the correct LSN is copied into place.
*/
COMPQUIET(rcnt, 0);
if (F_ISSET(cp, C_RECNUM) && LEVEL(child) > LEAFLEVEL)
rcnt = RE_NREC(parent);
memcpy(parent, child, dbp->pgsize);
PGNO(parent) = root_pgno;
if (F_ISSET(cp, C_RECNUM) && LEVEL(child) > LEAFLEVEL)
RE_NREC_SET(parent, rcnt);
/* Mark the pages dirty. */
if ((ret = __memp_fset(mpf, parent, DB_MPOOL_DIRTY)) != 0)
goto stop;
if ((ret = __memp_fset(mpf, child, DB_MPOOL_DIRTY)) != 0)
goto stop;
/* Adjust the cursors. */
if ((ret = __bam_ca_rsplit(dbc, PGNO(child), root_pgno)) != 0)
goto stop;
/*
* Free the page copied onto the root page and discard its
* lock. (The call to __db_free() discards our reference
* to the page.)
*/
if ((ret = __db_free(dbc, child)) != 0) {
child = NULL;
goto stop;
}
child = NULL;
if (0) {
stop: done = 1;
}
if ((t_ret = __TLPUT(dbc, p_lock)) != 0 && ret == 0)
ret = t_ret;
if (parent != NULL &&
(t_ret = __memp_fput(mpf, parent, 0)) != 0 && ret == 0)
ret = t_ret;
if ((t_ret = __TLPUT(dbc, c_lock)) != 0 && ret == 0)
ret = t_ret;
if (child != NULL &&
(t_ret = __memp_fput(mpf, child, 0)) != 0 && ret == 0)
ret = t_ret;
}
return (ret);
}
/*
* __bam_relink --
* Relink around a deleted page.
*
* PUBLIC: int __bam_relink __P((DBC *, PAGE *, db_pgno_t));
*/
int
__bam_relink(dbc, pagep, new_pgno)
DBC *dbc;
PAGE *pagep;
db_pgno_t new_pgno;
{
DB *dbp;
PAGE *np, *pp;
DB_LOCK npl, ppl;
DB_LSN *nlsnp, *plsnp, ret_lsn;
DB_MPOOLFILE *mpf;
int ret, t_ret;
dbp = dbc->dbp;
np = pp = NULL;
LOCK_INIT(npl);
LOCK_INIT(ppl);
nlsnp = plsnp = NULL;
mpf = dbp->mpf;
ret = 0;
/*
* Retrieve and lock the one/two pages. For a remove, we may need
* two pages (the before and after). For an add, we only need one
* because, the split took care of the prev.
*/
if (pagep->next_pgno != PGNO_INVALID) {
if ((ret = __db_lget(dbc,
0, pagep->next_pgno, DB_LOCK_WRITE, 0, &npl)) != 0)
goto err;
if ((ret = __memp_fget(mpf, &pagep->next_pgno, 0, &np)) != 0) {
ret = __db_pgerr(dbp, pagep->next_pgno, ret);
goto err;
}
nlsnp = &np->lsn;
}
if (pagep->prev_pgno != PGNO_INVALID) {
if ((ret = __db_lget(dbc,
0, pagep->prev_pgno, DB_LOCK_WRITE, 0, &ppl)) != 0)
goto err;
if ((ret = __memp_fget(mpf, &pagep->prev_pgno, 0, &pp)) != 0) {
ret = __db_pgerr(dbp, pagep->prev_pgno, ret);
goto err;
}
plsnp = &pp->lsn;
}
/* Log the change. */
if (DBC_LOGGING(dbc)) {
if ((ret = __bam_relink_log(dbp, dbc->txn, &ret_lsn, 0,
pagep->pgno, new_pgno, pagep->prev_pgno, plsnp,
pagep->next_pgno, nlsnp)) != 0)
goto err;
} else
LSN_NOT_LOGGED(ret_lsn);
if (np != NULL)
np->lsn = ret_lsn;
if (pp != NULL)
pp->lsn = ret_lsn;
/*
* Modify and release the two pages.
*/
if (np != NULL) {
if (new_pgno == PGNO_INVALID)
np->prev_pgno = pagep->prev_pgno;
else
np->prev_pgno = new_pgno;
ret = __memp_fput(mpf, np, DB_MPOOL_DIRTY);
if ((t_ret = __TLPUT(dbc, npl)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
goto err;
}
if (pp != NULL) {
if (new_pgno == PGNO_INVALID)
pp->next_pgno = pagep->next_pgno;
else
pp->next_pgno = new_pgno;
ret = __memp_fput(mpf, pp, DB_MPOOL_DIRTY);
if ((t_ret = __TLPUT(dbc, ppl)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
goto err;
}
return (0);
err: if (np != NULL)
(void)__memp_fput(mpf, np, 0);
(void)__TLPUT(dbc, npl);
if (pp != NULL)
(void)__memp_fput(mpf, pp, 0);
(void)__TLPUT(dbc, ppl);
return (ret);
}
/*
* __bam_pupdate --
* Update parent key pointers up the tree.
*
* PUBLIC: int __bam_pupdate __P((DBC *, PAGE *));
*/
int
__bam_pupdate(dbc, lpg)
DBC *dbc;
PAGE *lpg;
{
BTREE_CURSOR *cp;
DB_ENV *dbenv;
EPG *epg;
int ret;
dbenv = dbc->dbp->dbenv;
cp = (BTREE_CURSOR *)dbc->internal;
ret = 0;
/*
* Update the parents up the tree. __bam_pinsert only looks at the
* left child if is a leaf page, so we don't need to change it. We
* just do a delete and insert; a replace is possible but reusing
* pinsert is better.
*/
for (epg = &cp->csp[-1]; epg >= cp->sp; epg--) {
if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0)
return (ret);
epg->indx--;
if ((ret = __bam_pinsert(dbc, epg,
lpg, epg[1].page, BPI_NORECNUM)) != 0) {
if (ret == DB_NEEDSPLIT) {
/* This should not happen. */
__db_err(dbenv,
"Not enough room in parent: %s: page %lu",
dbc->dbp->fname, (u_long)PGNO(epg->page));
ret = __db_panic(dbenv, EINVAL);
}
return (ret);
}
}
return (ret);
}

View file

@ -1,514 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1999-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_method.c,v 12.2 2005/06/16 20:20:16 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/btree.h"
#include "dbinc/qam.h"
static int __bam_set_bt_minkey __P((DB *, u_int32_t));
static int __bam_set_bt_prefix
__P((DB *, size_t(*)(DB *, const DBT *, const DBT *)));
static int __ram_get_re_delim __P((DB *, int *));
static int __ram_set_re_delim __P((DB *, int));
static int __ram_set_re_len __P((DB *, u_int32_t));
static int __ram_set_re_pad __P((DB *, int));
static int __ram_get_re_source __P((DB *, const char **));
static int __ram_set_re_source __P((DB *, const char *));
/*
* __bam_db_create --
* Btree specific initialization of the DB structure.
*
* PUBLIC: int __bam_db_create __P((DB *));
*/
int
__bam_db_create(dbp)
DB *dbp;
{
BTREE *t;
int ret;
/* Allocate and initialize the private btree structure. */
if ((ret = __os_calloc(dbp->dbenv, 1, sizeof(BTREE), &t)) != 0)
return (ret);
dbp->bt_internal = t;
t->bt_minkey = DEFMINKEYPAGE; /* Btree */
t->bt_compare = __bam_defcmp;
t->bt_prefix = __bam_defpfx;
dbp->set_bt_compare = __bam_set_bt_compare;
dbp->get_bt_minkey = __bam_get_bt_minkey;
dbp->set_bt_minkey = __bam_set_bt_minkey;
dbp->set_bt_prefix = __bam_set_bt_prefix;
t->re_pad = ' '; /* Recno */
t->re_delim = '\n';
t->re_eof = 1;
dbp->get_re_delim = __ram_get_re_delim;
dbp->set_re_delim = __ram_set_re_delim;
dbp->get_re_len = __ram_get_re_len;
dbp->set_re_len = __ram_set_re_len;
dbp->get_re_pad = __ram_get_re_pad;
dbp->set_re_pad = __ram_set_re_pad;
dbp->get_re_source = __ram_get_re_source;
dbp->set_re_source = __ram_set_re_source;
return (0);
}
/*
* __bam_db_close --
* Btree specific discard of the DB structure.
*
* PUBLIC: int __bam_db_close __P((DB *));
*/
int
__bam_db_close(dbp)
DB *dbp;
{
BTREE *t;
if ((t = dbp->bt_internal) == NULL)
return (0);
/* Recno */
/* Close any backing source file descriptor. */
if (t->re_fp != NULL)
(void)fclose(t->re_fp);
/* Free any backing source file name. */
if (t->re_source != NULL)
__os_free(dbp->dbenv, t->re_source);
__os_free(dbp->dbenv, t);
dbp->bt_internal = NULL;
return (0);
}
/*
* __bam_map_flags --
* Map Btree specific flags from public to the internal values.
*
* PUBLIC: void __bam_map_flags __P((DB *, u_int32_t *, u_int32_t *));
*/
void
__bam_map_flags(dbp, inflagsp, outflagsp)
DB *dbp;
u_int32_t *inflagsp, *outflagsp;
{
COMPQUIET(dbp, NULL);
if (FLD_ISSET(*inflagsp, DB_DUP)) {
FLD_SET(*outflagsp, DB_AM_DUP);
FLD_CLR(*inflagsp, DB_DUP);
}
if (FLD_ISSET(*inflagsp, DB_DUPSORT)) {
FLD_SET(*outflagsp, DB_AM_DUP | DB_AM_DUPSORT);
FLD_CLR(*inflagsp, DB_DUPSORT);
}
if (FLD_ISSET(*inflagsp, DB_RECNUM)) {
FLD_SET(*outflagsp, DB_AM_RECNUM);
FLD_CLR(*inflagsp, DB_RECNUM);
}
if (FLD_ISSET(*inflagsp, DB_REVSPLITOFF)) {
FLD_SET(*outflagsp, DB_AM_REVSPLITOFF);
FLD_CLR(*inflagsp, DB_REVSPLITOFF);
}
}
/*
* __bam_set_flags --
* Set Btree specific flags.
*
* PUBLIC: int __bam_set_flags __P((DB *, u_int32_t *flagsp));
*/
int
__bam_set_flags(dbp, flagsp)
DB *dbp;
u_int32_t *flagsp;
{
u_int32_t flags;
flags = *flagsp;
if (LF_ISSET(DB_DUP | DB_DUPSORT | DB_RECNUM | DB_REVSPLITOFF))
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_flags");
/*
* The DB_DUP and DB_DUPSORT flags are shared by the Hash
* and Btree access methods.
*/
if (LF_ISSET(DB_DUP | DB_DUPSORT))
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH);
if (LF_ISSET(DB_RECNUM | DB_REVSPLITOFF))
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
/* DB_DUP/DB_DUPSORT is incompatible with DB_RECNUM. */
if (LF_ISSET(DB_DUP | DB_DUPSORT) && F_ISSET(dbp, DB_AM_RECNUM))
goto incompat;
/* DB_RECNUM is incompatible with DB_DUP/DB_DUPSORT. */
if (LF_ISSET(DB_RECNUM) && F_ISSET(dbp, DB_AM_DUP))
goto incompat;
if (LF_ISSET(DB_DUPSORT) && dbp->dup_compare == NULL)
dbp->dup_compare = __bam_defcmp;
__bam_map_flags(dbp, flagsp, &dbp->flags);
return (0);
incompat:
return (__db_ferr(dbp->dbenv, "DB->set_flags", 1));
}
/*
* __bam_set_bt_compare --
* Set the comparison function.
*
* PUBLIC: int __bam_set_bt_compare
* PUBLIC: __P((DB *, int (*)(DB *, const DBT *, const DBT *)));
*/
int
__bam_set_bt_compare(dbp, func)
DB *dbp;
int (*func) __P((DB *, const DBT *, const DBT *));
{
BTREE *t;
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_compare");
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
t = dbp->bt_internal;
/*
* Can't default the prefix routine if the user supplies a comparison
* routine; shortening the keys can break their comparison algorithm.
*/
t->bt_compare = func;
if (t->bt_prefix == __bam_defpfx)
t->bt_prefix = NULL;
return (0);
}
/*
* __db_get_bt_minkey --
* Get the minimum keys per page.
*
* PUBLIC: int __bam_get_bt_minkey __P((DB *, u_int32_t *));
*/
int
__bam_get_bt_minkey(dbp, bt_minkeyp)
DB *dbp;
u_int32_t *bt_minkeyp;
{
BTREE *t;
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
t = dbp->bt_internal;
*bt_minkeyp = t->bt_minkey;
return (0);
}
/*
* __bam_set_bt_minkey --
* Set the minimum keys per page.
*/
static int
__bam_set_bt_minkey(dbp, bt_minkey)
DB *dbp;
u_int32_t bt_minkey;
{
BTREE *t;
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_minkey");
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
t = dbp->bt_internal;
if (bt_minkey < 2) {
__db_err(dbp->dbenv, "minimum bt_minkey value is 2");
return (EINVAL);
}
t->bt_minkey = bt_minkey;
return (0);
}
/*
* __bam_set_bt_prefix --
* Set the prefix function.
*/
static int
__bam_set_bt_prefix(dbp, func)
DB *dbp;
size_t (*func) __P((DB *, const DBT *, const DBT *));
{
BTREE *t;
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_prefix");
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
t = dbp->bt_internal;
t->bt_prefix = func;
return (0);
}
/*
* __ram_map_flags --
* Map Recno specific flags from public to the internal values.
*
* PUBLIC: void __ram_map_flags __P((DB *, u_int32_t *, u_int32_t *));
*/
void
__ram_map_flags(dbp, inflagsp, outflagsp)
DB *dbp;
u_int32_t *inflagsp, *outflagsp;
{
COMPQUIET(dbp, NULL);
if (FLD_ISSET(*inflagsp, DB_RENUMBER)) {
FLD_SET(*outflagsp, DB_AM_RENUMBER);
FLD_CLR(*inflagsp, DB_RENUMBER);
}
if (FLD_ISSET(*inflagsp, DB_SNAPSHOT)) {
FLD_SET(*outflagsp, DB_AM_SNAPSHOT);
FLD_CLR(*inflagsp, DB_SNAPSHOT);
}
}
/*
* __ram_set_flags --
* Set Recno specific flags.
*
* PUBLIC: int __ram_set_flags __P((DB *, u_int32_t *flagsp));
*/
int
__ram_set_flags(dbp, flagsp)
DB *dbp;
u_int32_t *flagsp;
{
u_int32_t flags;
flags = *flagsp;
if (LF_ISSET(DB_RENUMBER | DB_SNAPSHOT)) {
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_flags");
DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
}
__ram_map_flags(dbp, flagsp, &dbp->flags);
return (0);
}
/*
* __db_get_re_delim --
* Get the variable-length input record delimiter.
*/
static int
__ram_get_re_delim(dbp, re_delimp)
DB *dbp;
int *re_delimp;
{
BTREE *t;
DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
t = dbp->bt_internal;
*re_delimp = t->re_delim;
return (0);
}
/*
* __ram_set_re_delim --
* Set the variable-length input record delimiter.
*/
static int
__ram_set_re_delim(dbp, re_delim)
DB *dbp;
int re_delim;
{
BTREE *t;
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_delim");
DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
t = dbp->bt_internal;
t->re_delim = re_delim;
F_SET(dbp, DB_AM_DELIMITER);
return (0);
}
/*
* __db_get_re_len --
* Get the variable-length input record length.
*
* PUBLIC: int __ram_get_re_len __P((DB *, u_int32_t *));
*/
int
__ram_get_re_len(dbp, re_lenp)
DB *dbp;
u_int32_t *re_lenp;
{
BTREE *t;
QUEUE *q;
DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
/*
* This has to work for all access methods, before or after opening the
* database. When the record length is set with __ram_set_re_len, the
* value in both the BTREE and QUEUE structs will be correct.
* Otherwise, this only makes sense after the database in opened, in
* which case we know the type.
*/
if (dbp->type == DB_QUEUE) {
q = dbp->q_internal;
*re_lenp = q->re_len;
} else {
t = dbp->bt_internal;
*re_lenp = t->re_len;
}
return (0);
}
/*
* __ram_set_re_len --
* Set the variable-length input record length.
*/
static int
__ram_set_re_len(dbp, re_len)
DB *dbp;
u_int32_t re_len;
{
BTREE *t;
QUEUE *q;
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_len");
DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
t = dbp->bt_internal;
t->re_len = re_len;
q = dbp->q_internal;
q->re_len = re_len;
F_SET(dbp, DB_AM_FIXEDLEN);
return (0);
}
/*
* __db_get_re_pad --
* Get the fixed-length record pad character.
*
* PUBLIC: int __ram_get_re_pad __P((DB *, int *));
*/
int
__ram_get_re_pad(dbp, re_padp)
DB *dbp;
int *re_padp;
{
BTREE *t;
QUEUE *q;
DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
/*
* This has to work for all access methods, before or after opening the
* database. When the record length is set with __ram_set_re_pad, the
* value in both the BTREE and QUEUE structs will be correct.
* Otherwise, this only makes sense after the database in opened, in
* which case we know the type.
*/
if (dbp->type == DB_QUEUE) {
q = dbp->q_internal;
*re_padp = q->re_pad;
} else {
t = dbp->bt_internal;
*re_padp = t->re_pad;
}
return (0);
}
/*
* __ram_set_re_pad --
* Set the fixed-length record pad character.
*/
static int
__ram_set_re_pad(dbp, re_pad)
DB *dbp;
int re_pad;
{
BTREE *t;
QUEUE *q;
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_pad");
DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
t = dbp->bt_internal;
t->re_pad = re_pad;
q = dbp->q_internal;
q->re_pad = re_pad;
F_SET(dbp, DB_AM_PAD);
return (0);
}
/*
* __db_get_re_source --
* Get the backing source file name.
*/
static int
__ram_get_re_source(dbp, re_sourcep)
DB *dbp;
const char **re_sourcep;
{
BTREE *t;
DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
t = dbp->bt_internal;
*re_sourcep = t->re_source;
return (0);
}
/*
* __ram_set_re_source --
* Set the backing source file name.
*/
static int
__ram_set_re_source(dbp, re_source)
DB *dbp;
const char *re_source;
{
BTREE *t;
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_source");
DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
t = dbp->bt_internal;
return (__os_strdup(dbp->dbenv, re_source, &t->re_source));
}

View file

@ -1,607 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* 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. 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.
*
* $Id: bt_open.c,v 12.5 2005/09/28 17:44:17 margo Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/crypto.h"
#include "dbinc/db_page.h"
#include "dbinc/db_swap.h"
#include "dbinc/btree.h"
#include "dbinc/db_shash.h"
#include "dbinc/lock.h"
#include "dbinc/log.h"
#include "dbinc/mp.h"
#include "dbinc/fop.h"
static void __bam_init_meta __P((DB *, BTMETA *, db_pgno_t, DB_LSN *));
/*
* __bam_open --
* Open a btree.
*
* PUBLIC: int __bam_open __P((DB *,
* PUBLIC: DB_TXN *, const char *, db_pgno_t, u_int32_t));
*/
int
__bam_open(dbp, txn, name, base_pgno, flags)
DB *dbp;
DB_TXN *txn;
const char *name;
db_pgno_t base_pgno;
u_int32_t flags;
{
BTREE *t;
COMPQUIET(name, NULL);
t = dbp->bt_internal;
/*
* We don't permit the user to specify a prefix routine if they didn't
* also specify a comparison routine, they can't know enough about our
* comparison routine to get it right.
*/
if (t->bt_compare == __bam_defcmp && t->bt_prefix != __bam_defpfx) {
__db_err(dbp->dbenv,
"prefix comparison may not be specified for default comparison routine");
return (EINVAL);
}
/*
* Verify that the bt_minkey value specified won't cause the
* calculation of ovflsize to underflow [#2406] for this pagesize.
*/
if (B_MINKEY_TO_OVFLSIZE(dbp, t->bt_minkey, dbp->pgsize) >
B_MINKEY_TO_OVFLSIZE(dbp, DEFMINKEYPAGE, dbp->pgsize)) {
__db_err(dbp->dbenv,
"bt_minkey value of %lu too high for page size of %lu",
(u_long)t->bt_minkey, (u_long)dbp->pgsize);
return (EINVAL);
}
/* Start up the tree. */
return (__bam_read_root(dbp, txn, base_pgno, flags));
}
/*
* __bam_metachk --
*
* PUBLIC: int __bam_metachk __P((DB *, const char *, BTMETA *));
*/
int
__bam_metachk(dbp, name, btm)
DB *dbp;
const char *name;
BTMETA *btm;
{
DB_ENV *dbenv;
u_int32_t vers;
int ret;
dbenv = dbp->dbenv;
/*
* At this point, all we know is that the magic number is for a Btree.
* Check the version, the database may be out of date.
*/
vers = btm->dbmeta.version;
if (F_ISSET(dbp, DB_AM_SWAP))
M_32_SWAP(vers);
switch (vers) {
case 6:
case 7:
__db_err(dbenv,
"%s: btree version %lu requires a version upgrade",
name, (u_long)vers);
return (DB_OLD_VERSION);
case 8:
case 9:
break;
default:
__db_err(dbenv,
"%s: unsupported btree version: %lu", name, (u_long)vers);
return (EINVAL);
}
/* Swap the page if we need to. */
if (F_ISSET(dbp, DB_AM_SWAP) && (ret = __bam_mswap((PAGE *)btm)) != 0)
return (ret);
/*
* Check application info against metadata info, and set info, flags,
* and type based on metadata info.
*/
if ((ret =
__db_fchk(dbenv, "DB->open", btm->dbmeta.flags, BTM_MASK)) != 0)
return (ret);
if (F_ISSET(&btm->dbmeta, BTM_RECNO)) {
if (dbp->type == DB_BTREE)
goto wrong_type;
dbp->type = DB_RECNO;
DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
} else {
if (dbp->type == DB_RECNO)
goto wrong_type;
dbp->type = DB_BTREE;
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
}
if (F_ISSET(&btm->dbmeta, BTM_DUP))
F_SET(dbp, DB_AM_DUP);
else
if (F_ISSET(dbp, DB_AM_DUP)) {
__db_err(dbenv,
"%s: DB_DUP specified to open method but not set in database",
name);
return (EINVAL);
}
if (F_ISSET(&btm->dbmeta, BTM_RECNUM)) {
if (dbp->type != DB_BTREE)
goto wrong_type;
F_SET(dbp, DB_AM_RECNUM);
if ((ret = __db_fcchk(dbenv,
"DB->open", dbp->flags, DB_AM_DUP, DB_AM_RECNUM)) != 0)
return (ret);
} else
if (F_ISSET(dbp, DB_AM_RECNUM)) {
__db_err(dbenv,
"%s: DB_RECNUM specified to open method but not set in database",
name);
return (EINVAL);
}
if (F_ISSET(&btm->dbmeta, BTM_FIXEDLEN)) {
if (dbp->type != DB_RECNO)
goto wrong_type;
F_SET(dbp, DB_AM_FIXEDLEN);
} else
if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
__db_err(dbenv,
"%s: DB_FIXEDLEN specified to open method but not set in database",
name);
return (EINVAL);
}
if (F_ISSET(&btm->dbmeta, BTM_RENUMBER)) {
if (dbp->type != DB_RECNO)
goto wrong_type;
F_SET(dbp, DB_AM_RENUMBER);
} else
if (F_ISSET(dbp, DB_AM_RENUMBER)) {
__db_err(dbenv,
"%s: DB_RENUMBER specified to open method but not set in database",
name);
return (EINVAL);
}
if (F_ISSET(&btm->dbmeta, BTM_SUBDB))
F_SET(dbp, DB_AM_SUBDB);
else
if (F_ISSET(dbp, DB_AM_SUBDB)) {
__db_err(dbenv,
"%s: multiple databases specified but not supported by file",
name);
return (EINVAL);
}
if (F_ISSET(&btm->dbmeta, BTM_DUPSORT)) {
if (dbp->dup_compare == NULL)
dbp->dup_compare = __bam_defcmp;
F_SET(dbp, DB_AM_DUPSORT);
} else
if (dbp->dup_compare != NULL) {
__db_err(dbenv,
"%s: duplicate sort specified but not supported in database",
name);
return (EINVAL);
}
/* Set the page size. */
dbp->pgsize = btm->dbmeta.pagesize;
/* Copy the file's ID. */
memcpy(dbp->fileid, btm->dbmeta.uid, DB_FILE_ID_LEN);
return (0);
wrong_type:
if (dbp->type == DB_BTREE)
__db_err(dbenv,
"open method type is Btree, database type is Recno");
else
__db_err(dbenv,
"open method type is Recno, database type is Btree");
return (EINVAL);
}
/*
* __bam_read_root --
* Read the root page and check a tree.
*
* PUBLIC: int __bam_read_root __P((DB *, DB_TXN *, db_pgno_t, u_int32_t));
*/
int
__bam_read_root(dbp, txn, base_pgno, flags)
DB *dbp;
DB_TXN *txn;
db_pgno_t base_pgno;
u_int32_t flags;
{
BTMETA *meta;
BTREE *t;
DBC *dbc;
DB_LOCK metalock;
DB_MPOOLFILE *mpf;
int ret, t_ret;
COMPQUIET(flags, 0);
meta = NULL;
t = dbp->bt_internal;
LOCK_INIT(metalock);
mpf = dbp->mpf;
ret = 0;
/* Get a cursor. */
if ((ret = __db_cursor(dbp, txn, &dbc, 0)) != 0)
return (ret);
/* Get the metadata page. */
if ((ret =
__db_lget(dbc, 0, base_pgno, DB_LOCK_READ, 0, &metalock)) != 0)
goto err;
if ((ret = __memp_fget(mpf, &base_pgno, 0, &meta)) != 0)
goto err;
/*
* If the magic number is set, the tree has been created. Correct
* any fields that may not be right. Note, all of the local flags
* were set by DB->open.
*
* Otherwise, we'd better be in recovery or abort, in which case the
* metadata page will be created/initialized elsewhere.
*/
if (meta->dbmeta.magic == DB_BTREEMAGIC) {
t->bt_minkey = meta->minkey;
t->re_pad = (int)meta->re_pad;
t->re_len = meta->re_len;
t->bt_meta = base_pgno;
t->bt_root = meta->root;
} else {
DB_ASSERT(IS_RECOVERING(dbp->dbenv) ||
F_ISSET(dbp, DB_AM_RECOVER));
}
/*
* !!!
* If creating a subdatabase, we've already done an insert when
* we put the subdatabase's entry into the master database, so
* our last-page-inserted value is wrongly initialized for the
* master database, not the subdatabase we're creating. I'm not
* sure where the *right* place to clear this value is, it's not
* intuitively obvious that it belongs here.
*/
t->bt_lpgno = PGNO_INVALID;
err: /* Put the metadata page back. */
if (meta != NULL &&
(t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
ret = t_ret;
if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
ret = t_ret;
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
/*
* __bam_init_meta --
*
* Initialize a btree meta-data page. The following fields may need
* to be updated later: last_pgno, root.
*/
static void
__bam_init_meta(dbp, meta, pgno, lsnp)
DB *dbp;
BTMETA *meta;
db_pgno_t pgno;
DB_LSN *lsnp;
{
BTREE *t;
memset(meta, 0, sizeof(BTMETA));
meta->dbmeta.lsn = *lsnp;
meta->dbmeta.pgno = pgno;
meta->dbmeta.magic = DB_BTREEMAGIC;
meta->dbmeta.version = DB_BTREEVERSION;
meta->dbmeta.pagesize = dbp->pgsize;
if (F_ISSET(dbp, DB_AM_CHKSUM))
FLD_SET(meta->dbmeta.metaflags, DBMETA_CHKSUM);
if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
meta->dbmeta.encrypt_alg =
((DB_CIPHER *)dbp->dbenv->crypto_handle)->alg;
DB_ASSERT(meta->dbmeta.encrypt_alg != 0);
meta->crypto_magic = meta->dbmeta.magic;
}
meta->dbmeta.type = P_BTREEMETA;
meta->dbmeta.free = PGNO_INVALID;
meta->dbmeta.last_pgno = pgno;
if (F_ISSET(dbp, DB_AM_DUP))
F_SET(&meta->dbmeta, BTM_DUP);
if (F_ISSET(dbp, DB_AM_FIXEDLEN))
F_SET(&meta->dbmeta, BTM_FIXEDLEN);
if (F_ISSET(dbp, DB_AM_RECNUM))
F_SET(&meta->dbmeta, BTM_RECNUM);
if (F_ISSET(dbp, DB_AM_RENUMBER))
F_SET(&meta->dbmeta, BTM_RENUMBER);
if (F_ISSET(dbp, DB_AM_SUBDB))
F_SET(&meta->dbmeta, BTM_SUBDB);
if (dbp->dup_compare != NULL)
F_SET(&meta->dbmeta, BTM_DUPSORT);
if (dbp->type == DB_RECNO)
F_SET(&meta->dbmeta, BTM_RECNO);
memcpy(meta->dbmeta.uid, dbp->fileid, DB_FILE_ID_LEN);
t = dbp->bt_internal;
meta->minkey = t->bt_minkey;
meta->re_len = t->re_len;
meta->re_pad = (u_int32_t)t->re_pad;
}
/*
* __bam_new_file --
* Create the necessary pages to begin a new database file.
*
* This code appears more complex than it is because of the two cases (named
* and unnamed). The way to read the code is that for each page being created,
* there are three parts: 1) a "get page" chunk (which either uses malloc'd
* memory or calls __memp_fget), 2) the initialization, and 3) the "put page"
* chunk which either does a fop write or an __memp_fput.
*
* PUBLIC: int __bam_new_file __P((DB *, DB_TXN *, DB_FH *, const char *));
*/
int
__bam_new_file(dbp, txn, fhp, name)
DB *dbp;
DB_TXN *txn;
DB_FH *fhp;
const char *name;
{
BTMETA *meta;
DB_ENV *dbenv;
DB_LSN lsn;
DB_MPOOLFILE *mpf;
DB_PGINFO pginfo;
DBT pdbt;
PAGE *root;
db_pgno_t pgno;
int ret, t_ret;
void *buf;
dbenv = dbp->dbenv;
mpf = dbp->mpf;
root = NULL;
meta = NULL;
buf = NULL;
if (F_ISSET(dbp, DB_AM_INMEM)) {
/* Build the meta-data page. */
pgno = PGNO_BASE_MD;
if ((ret =
__memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &meta)) != 0)
return (ret);
LSN_NOT_LOGGED(lsn);
__bam_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
meta->root = 1;
meta->dbmeta.last_pgno = 1;
if ((ret =
__db_log_page(dbp, txn, &lsn, pgno, (PAGE *)meta)) != 0)
goto err;
ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY);
meta = NULL;
if (ret != 0)
goto err;
/* Build the root page. */
pgno = 1;
if ((ret =
__memp_fget(mpf, &pgno, DB_MPOOL_CREATE, &root)) != 0)
goto err;
P_INIT(root, dbp->pgsize, 1, PGNO_INVALID, PGNO_INVALID,
LEAFLEVEL, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE);
LSN_NOT_LOGGED(root->lsn);
if ((ret =
__db_log_page(dbp, txn, &root->lsn, pgno, root)) != 0)
goto err;
ret = __memp_fput(mpf, root, DB_MPOOL_DIRTY);
root = NULL;
if (ret != 0)
goto err;
} else {
memset(&pdbt, 0, sizeof(pdbt));
/* Build the meta-data page. */
pginfo.db_pagesize = dbp->pgsize;
pginfo.flags =
F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
pginfo.type = dbp->type;
pdbt.data = &pginfo;
pdbt.size = sizeof(pginfo);
if ((ret = __os_calloc(dbenv, 1, dbp->pgsize, &buf)) != 0)
return (ret);
meta = (BTMETA *)buf;
LSN_NOT_LOGGED(lsn);
__bam_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
meta->root = 1;
meta->dbmeta.last_pgno = 1;
if ((ret = __db_pgout(dbenv, PGNO_BASE_MD, meta, &pdbt)) != 0)
goto err;
if ((ret = __fop_write(dbenv, txn, name, DB_APP_DATA, fhp,
dbp->pgsize, 0, 0, buf, dbp->pgsize, 1, F_ISSET(
dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0)) != 0)
goto err;
meta = NULL;
/* Build the root page. */
#ifdef DIAGNOSTIC
memset(buf, CLEAR_BYTE, dbp->pgsize);
#endif
root = (PAGE *)buf;
P_INIT(root, dbp->pgsize, 1, PGNO_INVALID, PGNO_INVALID,
LEAFLEVEL, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE);
LSN_NOT_LOGGED(root->lsn);
if ((ret = __db_pgout(dbenv, root->pgno, root, &pdbt)) != 0)
goto err;
if ((ret = __fop_write(dbenv, txn, name, DB_APP_DATA, fhp,
dbp->pgsize, 1, 0, buf, dbp->pgsize, 1, F_ISSET(
dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0)) != 0)
goto err;
root = NULL;
}
err: if (buf != NULL)
__os_free(dbenv, buf);
else {
if (meta != NULL &&
(t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
ret = t_ret;
if (root != NULL &&
(t_ret = __memp_fput(mpf, root, 0)) != 0 && ret == 0)
ret = t_ret;
}
return (ret);
}
/*
* __bam_new_subdb --
* Create a metadata page and a root page for a new btree.
*
* PUBLIC: int __bam_new_subdb __P((DB *, DB *, DB_TXN *));
*/
int
__bam_new_subdb(mdbp, dbp, txn)
DB *mdbp, *dbp;
DB_TXN *txn;
{
BTMETA *meta;
DBC *dbc;
DB_ENV *dbenv;
DB_LOCK metalock;
DB_LSN lsn;
DB_MPOOLFILE *mpf;
PAGE *root;
int ret, t_ret;
dbenv = mdbp->dbenv;
mpf = mdbp->mpf;
dbc = NULL;
meta = NULL;
root = NULL;
if ((ret = __db_cursor(mdbp, txn,
&dbc, CDB_LOCKING(dbenv) ? DB_WRITECURSOR : 0)) != 0)
return (ret);
/* Get, and optionally create the metadata page. */
if ((ret = __db_lget(dbc,
0, dbp->meta_pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
goto err;
if ((ret =
__memp_fget(mpf, &dbp->meta_pgno, DB_MPOOL_CREATE, &meta)) != 0)
goto err;
/* Build meta-data page. */
lsn = meta->dbmeta.lsn;
__bam_init_meta(dbp, meta, dbp->meta_pgno, &lsn);
if ((ret = __db_log_page(mdbp,
txn, &meta->dbmeta.lsn, dbp->meta_pgno, (PAGE *)meta)) != 0)
goto err;
/* Create and initialize a root page. */
if ((ret = __db_new(dbc,
dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE, &root)) != 0)
goto err;
root->level = LEAFLEVEL;
if (DBENV_LOGGING(dbenv) &&
(ret = __bam_root_log(mdbp, txn, &meta->dbmeta.lsn, 0,
meta->dbmeta.pgno, root->pgno, &meta->dbmeta.lsn)) != 0)
goto err;
meta->root = root->pgno;
if ((ret =
__db_log_page(mdbp, txn, &root->lsn, root->pgno, root)) != 0)
goto err;
/* Release the metadata and root pages. */
if ((ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY)) != 0)
goto err;
meta = NULL;
if ((ret = __memp_fput(mpf, root, DB_MPOOL_DIRTY)) != 0)
goto err;
root = NULL;
err:
if (meta != NULL)
if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
ret = t_ret;
if (root != NULL)
if ((t_ret = __memp_fput(mpf, root, 0)) != 0 && ret == 0)
ret = t_ret;
if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
ret = t_ret;
if (dbc != NULL)
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}

View file

@ -1,912 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* 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. 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.
*
* $Id: bt_put.c,v 12.10 2005/10/20 18:57:00 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/btree.h"
#include "dbinc/mp.h"
static int __bam_build
__P((DBC *, u_int32_t, DBT *, PAGE *, u_int32_t, u_int32_t));
static int __bam_dup_check __P((DBC *, u_int32_t,
PAGE *, u_int32_t, u_int32_t, db_indx_t *));
static int __bam_dup_convert __P((DBC *, PAGE *, u_int32_t, u_int32_t));
static int __bam_ovput
__P((DBC *, u_int32_t, db_pgno_t, PAGE *, u_int32_t, DBT *));
static u_int32_t
__bam_partsize __P((DB *, u_int32_t, DBT *, PAGE *, u_int32_t));
/*
* __bam_iitem --
* Insert an item into the tree.
*
* PUBLIC: int __bam_iitem __P((DBC *, DBT *, DBT *, u_int32_t, u_int32_t));
*/
int
__bam_iitem(dbc, key, data, op, flags)
DBC *dbc;
DBT *key, *data;
u_int32_t op, flags;
{
DB_ENV *dbenv;
BKEYDATA *bk, bk_tmp;
BTREE *t;
BTREE_CURSOR *cp;
DB *dbp;
DBT bk_hdr, tdbt;
DB_MPOOLFILE *mpf;
PAGE *h;
db_indx_t cnt, indx;
u_int32_t data_size, have_bytes, need_bytes, needed, pages, pagespace;
int cmp, bigkey, bigdata, dupadjust, padrec, replace, ret, was_deleted;
COMPQUIET(bk, NULL);
COMPQUIET(cnt, 0);
dbp = dbc->dbp;
dbenv = dbp->dbenv;
mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
t = dbp->bt_internal;
h = cp->page;
indx = cp->indx;
dupadjust = replace = was_deleted = 0;
/*
* Fixed-length records with partial puts: it's an error to specify
* anything other simple overwrite.
*/
if (F_ISSET(dbp, DB_AM_FIXEDLEN) &&
F_ISSET(data, DB_DBT_PARTIAL) && data->size != data->dlen)
return (__db_rec_repl(dbenv, data->size, data->dlen));
/*
* Figure out how much space the data will take, including if it's a
* partial record.
*
* Fixed-length records: it's an error to specify a record that's
* longer than the fixed-length, and we never require less than
* the fixed-length record size.
*/
data_size = F_ISSET(data, DB_DBT_PARTIAL) ?
__bam_partsize(dbp, op, data, h, indx) : data->size;
padrec = 0;
if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
if (data_size > t->re_len)
return (__db_rec_toobig(dbenv, data_size, t->re_len));
/* Records that are deleted anyway needn't be padded out. */
if (!LF_ISSET(BI_DELETED) && data_size < t->re_len) {
padrec = 1;
data_size = t->re_len;
}
}
/*
* Handle partial puts or short fixed-length records: build the
* real record.
*/
if (padrec || F_ISSET(data, DB_DBT_PARTIAL)) {
tdbt = *data;
if ((ret =
__bam_build(dbc, op, &tdbt, h, indx, data_size)) != 0)
return (ret);
data = &tdbt;
}
/*
* If the user has specified a duplicate comparison function, return
* an error if DB_CURRENT was specified and the replacement data
* doesn't compare equal to the current data. This stops apps from
* screwing up the duplicate sort order. We have to do this after
* we build the real record so that we're comparing the real items.
*/
if (op == DB_CURRENT && dbp->dup_compare != NULL) {
if ((ret = __bam_cmp(dbp, data, h,
indx + (TYPE(h) == P_LBTREE ? O_INDX : 0),
dbp->dup_compare, &cmp)) != 0)
return (ret);
if (cmp != 0) {
__db_err(dbenv,
"Existing data sorts differently from put data");
return (EINVAL);
}
}
/*
* If the key or data item won't fit on a page, we'll have to store
* them on overflow pages.
*/
needed = 0;
bigdata = data_size > cp->ovflsize;
switch (op) {
case DB_KEYFIRST:
/* We're adding a new key and data pair. */
bigkey = key->size > cp->ovflsize;
if (bigkey)
needed += BOVERFLOW_PSIZE;
else
needed += BKEYDATA_PSIZE(key->size);
if (bigdata)
needed += BOVERFLOW_PSIZE;
else
needed += BKEYDATA_PSIZE(data_size);
break;
case DB_AFTER:
case DB_BEFORE:
case DB_CURRENT:
/*
* We're either overwriting the data item of a key/data pair
* or we're creating a new on-page duplicate and only adding
* a data item.
*
* !!!
* We're not currently correcting for space reclaimed from
* already deleted items, but I don't think it's worth the
* complexity.
*/
bigkey = 0;
if (op == DB_CURRENT) {
bk = GET_BKEYDATA(dbp, h,
indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));
if (B_TYPE(bk->type) == B_KEYDATA)
have_bytes = BKEYDATA_PSIZE(bk->len);
else
have_bytes = BOVERFLOW_PSIZE;
need_bytes = 0;
} else {
have_bytes = 0;
need_bytes = sizeof(db_indx_t);
}
if (bigdata)
need_bytes += BOVERFLOW_PSIZE;
else
need_bytes += BKEYDATA_PSIZE(data_size);
if (have_bytes < need_bytes)
needed += need_bytes - have_bytes;
break;
default:
return (__db_unknown_flag(dbenv, "DB->put", op));
}
/* Split the page if there's not enough room. */
if (P_FREESPACE(dbp, h) < needed)
return (DB_NEEDSPLIT);
/*
* Check to see if we will convert to off page duplicates -- if
* so, we'll need a page.
*/
if (F_ISSET(dbp, DB_AM_DUP) &&
TYPE(h) == P_LBTREE && op != DB_KEYFIRST &&
P_FREESPACE(dbp, h) - needed <= dbp->pgsize / 2 &&
__bam_dup_check(dbc, op, h, indx, needed, &cnt)) {
pages = 1;
dupadjust = 1;
} else
pages = 0;
/*
* If we are not using transactions and there is a page limit
* set on the file, then figure out if things will fit before
* taking action.
*/
if (dbc->txn == NULL && dbp->mpf->mfp->maxpgno != 0) {
pagespace = P_MAXSPACE(dbp, dbp->pgsize);
if (bigdata)
pages += ((data_size - 1) / pagespace) + 1;
if (bigkey)
pages += ((key->size - 1) / pagespace) + 1;
if (pages > (dbp->mpf->mfp->maxpgno - dbp->mpf->mfp->last_pgno))
return (__db_space_err(dbp));
}
/*
* The code breaks it up into five cases:
*
* 1. Insert a new key/data pair.
* 2. Append a new data item (a new duplicate).
* 3. Insert a new data item (a new duplicate).
* 4. Delete and re-add the data item (overflow item).
* 5. Overwrite the data item.
*/
switch (op) {
case DB_KEYFIRST: /* 1. Insert a new key/data pair. */
if (bigkey) {
if ((ret = __bam_ovput(dbc,
B_OVERFLOW, PGNO_INVALID, h, indx, key)) != 0)
return (ret);
} else
if ((ret = __db_pitem(dbc, h, indx,
BKEYDATA_SIZE(key->size), NULL, key)) != 0)
return (ret);
if ((ret = __bam_ca_di(dbc, PGNO(h), indx, 1)) != 0)
return (ret);
++indx;
break;
case DB_AFTER: /* 2. Append a new data item. */
if (TYPE(h) == P_LBTREE) {
/* Copy the key for the duplicate and adjust cursors. */
if ((ret =
__bam_adjindx(dbc, h, indx + P_INDX, indx, 1)) != 0)
return (ret);
if ((ret =
__bam_ca_di(dbc, PGNO(h), indx + P_INDX, 1)) != 0)
return (ret);
indx += 3;
cp->indx += 2;
} else {
++indx;
cp->indx += 1;
}
break;
case DB_BEFORE: /* 3. Insert a new data item. */
if (TYPE(h) == P_LBTREE) {
/* Copy the key for the duplicate and adjust cursors. */
if ((ret = __bam_adjindx(dbc, h, indx, indx, 1)) != 0)
return (ret);
if ((ret = __bam_ca_di(dbc, PGNO(h), indx, 1)) != 0)
return (ret);
++indx;
}
break;
case DB_CURRENT:
/*
* Clear the cursor's deleted flag. The problem is that if
* we deadlock or fail while deleting the overflow item or
* replacing the non-overflow item, a subsequent cursor close
* will try and remove the item because the cursor's delete
* flag is set.
*/
if ((ret = __bam_ca_delete(dbp, PGNO(h), indx, 0, NULL)) != 0)
return (ret);
if (TYPE(h) == P_LBTREE) {
++indx;
}
/*
* In a Btree deleted records aren't counted (deleted records
* are counted in a Recno because all accesses are based on
* record number). If it's a Btree and it's a DB_CURRENT
* operation overwriting a previously deleted record, increment
* the record count.
*/
if (TYPE(h) == P_LBTREE || TYPE(h) == P_LDUP)
was_deleted = B_DISSET(bk->type);
/*
* 4. Delete and re-add the data item.
*
* If we're changing the type of the on-page structure, or we
* are referencing offpage items, we have to delete and then
* re-add the item. We do not do any cursor adjustments here
* because we're going to immediately re-add the item into the
* same slot.
*/
if (bigdata || B_TYPE(bk->type) != B_KEYDATA) {
if ((ret = __bam_ditem(dbc, h, indx)) != 0)
return (ret);
break;
}
/* 5. Overwrite the data item. */
replace = 1;
break;
default:
return (__db_unknown_flag(dbenv, "DB->put", op));
}
/* Add the data. */
if (bigdata) {
/*
* We do not have to handle deleted (BI_DELETED) records
* in this case; the actual records should never be created.
*/
DB_ASSERT(!LF_ISSET(BI_DELETED));
if ((ret = __bam_ovput(dbc,
B_OVERFLOW, PGNO_INVALID, h, indx, data)) != 0)
return (ret);
} else {
if (LF_ISSET(BI_DELETED)) {
B_TSET(bk_tmp.type, B_KEYDATA, 1);
bk_tmp.len = data->size;
bk_hdr.data = &bk_tmp;
bk_hdr.size = SSZA(BKEYDATA, data);
ret = __db_pitem(dbc, h, indx,
BKEYDATA_SIZE(data->size), &bk_hdr, data);
} else if (replace)
ret = __bam_ritem(dbc, h, indx, data);
else
ret = __db_pitem(dbc, h, indx,
BKEYDATA_SIZE(data->size), NULL, data);
if (ret != 0)
return (ret);
}
if ((ret = __memp_fset(mpf, h, DB_MPOOL_DIRTY)) != 0)
return (ret);
/*
* Re-position the cursors if necessary and reset the current cursor
* to point to the new item.
*/
if (op != DB_CURRENT) {
if ((ret = __bam_ca_di(dbc, PGNO(h), indx, 1)) != 0)
return (ret);
cp->indx = TYPE(h) == P_LBTREE ? indx - O_INDX : indx;
}
/*
* If we've changed the record count, update the tree. There's no
* need to adjust the count if the operation not performed on the
* current record or when the current record was previously deleted.
*/
if (F_ISSET(cp, C_RECNUM) && (op != DB_CURRENT || was_deleted))
if ((ret = __bam_adjust(dbc, 1)) != 0)
return (ret);
/*
* If a Btree leaf page is at least 50% full and we may have added or
* modified a duplicate data item, see if the set of duplicates takes
* up at least 25% of the space on the page. If it does, move it onto
* its own page.
*/
if (dupadjust &&
(ret = __bam_dup_convert(dbc, h, indx - O_INDX, cnt)) != 0)
return (ret);
/* If we've modified a recno file, set the flag. */
if (dbc->dbtype == DB_RECNO)
t->re_modified = 1;
return (ret);
}
/*
* __bam_partsize --
* Figure out how much space a partial data item is in total.
*/
static u_int32_t
__bam_partsize(dbp, op, data, h, indx)
DB *dbp;
u_int32_t op, indx;
DBT *data;
PAGE *h;
{
BKEYDATA *bk;
u_int32_t nbytes;
/*
* If the record doesn't already exist, it's simply the data we're
* provided.
*/
if (op != DB_CURRENT)
return (data->doff + data->size);
/*
* Otherwise, it's the data provided plus any already existing data
* that we're not replacing.
*/
bk = GET_BKEYDATA(dbp, h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0));
nbytes =
B_TYPE(bk->type) == B_OVERFLOW ? ((BOVERFLOW *)bk)->tlen : bk->len;
return (__db_partsize(nbytes, data));
}
/*
* __bam_build --
* Build the real record for a partial put, or short fixed-length record.
*/
static int
__bam_build(dbc, op, dbt, h, indx, nbytes)
DBC *dbc;
u_int32_t op, indx, nbytes;
DBT *dbt;
PAGE *h;
{
BKEYDATA *bk, tbk;
BOVERFLOW *bo;
BTREE *t;
DB *dbp;
DBT copy, *rdata;
u_int32_t len, tlen;
u_int8_t *p;
int ret;
COMPQUIET(bo, NULL);
dbp = dbc->dbp;
t = dbp->bt_internal;
/* We use the record data return memory, it's only a short-term use. */
rdata = &dbc->my_rdata;
if (rdata->ulen < nbytes) {
if ((ret = __os_realloc(dbp->dbenv,
nbytes, &rdata->data)) != 0) {
rdata->ulen = 0;
rdata->data = NULL;
return (ret);
}
rdata->ulen = nbytes;
}
/*
* We use nul or pad bytes for any part of the record that isn't
* specified; get it over with.
*/
memset(rdata->data,
F_ISSET(dbp, DB_AM_FIXEDLEN) ? t->re_pad : 0, nbytes);
/*
* In the next clauses, we need to do three things: a) set p to point
* to the place at which to copy the user's data, b) set tlen to the
* total length of the record, not including the bytes contributed by
* the user, and c) copy any valid data from an existing record. If
* it's not a partial put (this code is called for both partial puts
* and fixed-length record padding) or it's a new key, we can cut to
* the chase.
*/
if (!F_ISSET(dbt, DB_DBT_PARTIAL) || op != DB_CURRENT) {
p = (u_int8_t *)rdata->data + dbt->doff;
tlen = dbt->doff;
goto user_copy;
}
/* Find the current record. */
if (indx < NUM_ENT(h)) {
bk = GET_BKEYDATA(dbp, h, indx + (TYPE(h) == P_LBTREE ?
O_INDX : 0));
bo = (BOVERFLOW *)bk;
} else {
bk = &tbk;
B_TSET(bk->type, B_KEYDATA, 0);
bk->len = 0;
}
if (B_TYPE(bk->type) == B_OVERFLOW) {
/*
* In the case of an overflow record, we shift things around
* in the current record rather than allocate a separate copy.
*/
memset(&copy, 0, sizeof(copy));
if ((ret = __db_goff(dbp, &copy, bo->tlen,
bo->pgno, &rdata->data, &rdata->ulen)) != 0)
return (ret);
/* Skip any leading data from the original record. */
tlen = dbt->doff;
p = (u_int8_t *)rdata->data + dbt->doff;
/*
* Copy in any trailing data from the original record.
*
* If the original record was larger than the original offset
* plus the bytes being deleted, there is trailing data in the
* original record we need to preserve. If we aren't deleting
* the same number of bytes as we're inserting, copy it up or
* down, into place.
*
* Use memmove(), the regions may overlap.
*/
if (bo->tlen > dbt->doff + dbt->dlen) {
len = bo->tlen - (dbt->doff + dbt->dlen);
if (dbt->dlen != dbt->size)
memmove(p + dbt->size, p + dbt->dlen, len);
tlen += len;
}
} else {
/* Copy in any leading data from the original record. */
memcpy(rdata->data,
bk->data, dbt->doff > bk->len ? bk->len : dbt->doff);
tlen = dbt->doff;
p = (u_int8_t *)rdata->data + dbt->doff;
/* Copy in any trailing data from the original record. */
len = dbt->doff + dbt->dlen;
if (bk->len > len) {
memcpy(p + dbt->size, bk->data + len, bk->len - len);
tlen += bk->len - len;
}
}
user_copy:
/*
* Copy in the application provided data -- p and tlen must have been
* initialized above.
*/
memcpy(p, dbt->data, dbt->size);
tlen += dbt->size;
/* Set the DBT to reference our new record. */
rdata->size = F_ISSET(dbp, DB_AM_FIXEDLEN) ? t->re_len : tlen;
rdata->dlen = 0;
rdata->doff = 0;
rdata->flags = 0;
*dbt = *rdata;
return (0);
}
/*
* __bam_ritem --
* Replace an item on a page.
*
* PUBLIC: int __bam_ritem __P((DBC *, PAGE *, u_int32_t, DBT *));
*/
int
__bam_ritem(dbc, h, indx, data)
DBC *dbc;
PAGE *h;
u_int32_t indx;
DBT *data;
{
BKEYDATA *bk;
DB *dbp;
DBT orig, repl;
db_indx_t cnt, lo, ln, min, off, prefix, suffix;
int32_t nbytes;
int ret;
db_indx_t *inp;
u_int8_t *p, *t;
dbp = dbc->dbp;
/*
* Replace 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.
*/
bk = GET_BKEYDATA(dbp, h, indx);
/* Log the change. */
if (DBC_LOGGING(dbc)) {
/*
* We might as well check to see if the two data items share
* a common prefix and suffix -- it can save us a lot of log
* message if they're large.
*/
min = data->size < bk->len ? data->size : bk->len;
for (prefix = 0,
p = bk->data, t = data->data;
prefix < min && *p == *t; ++prefix, ++p, ++t)
;
min -= prefix;
for (suffix = 0,
p = (u_int8_t *)bk->data + bk->len - 1,
t = (u_int8_t *)data->data + data->size - 1;
suffix < min && *p == *t; ++suffix, --p, --t)
;
/* We only log the parts of the keys that have changed. */
orig.data = (u_int8_t *)bk->data + prefix;
orig.size = bk->len - (prefix + suffix);
repl.data = (u_int8_t *)data->data + prefix;
repl.size = data->size - (prefix + suffix);
if ((ret = __bam_repl_log(dbp, dbc->txn, &LSN(h), 0, PGNO(h),
&LSN(h), (u_int32_t)indx, (u_int32_t)B_DISSET(bk->type),
&orig, &repl, (u_int32_t)prefix, (u_int32_t)suffix)) != 0)
return (ret);
} else
LSN_NOT_LOGGED(LSN(h));
/*
* Set references to the first in-use byte on the page and the
* first byte of the item being replaced.
*/
inp = P_INP(dbp, h);
p = (u_int8_t *)h + HOFFSET(h);
t = (u_int8_t *)bk;
/*
* If the entry is growing in size, shift the beginning of the data
* part of the page down. If the entry is shrinking in size, shift
* the beginning of the data part of the page up. Use memmove(3),
* the regions overlap.
*/
lo = BKEYDATA_SIZE(bk->len);
ln = (db_indx_t)BKEYDATA_SIZE(data->size);
if (lo != ln) {
nbytes = lo - ln; /* Signed difference. */
if (p == t) /* First index is fast. */
inp[indx] += nbytes;
else { /* Else, shift the page. */
memmove(p + nbytes, p, (size_t)(t - p));
/* Adjust the indices' offsets. */
off = inp[indx];
for (cnt = 0; cnt < NUM_ENT(h); ++cnt)
if (inp[cnt] <= off)
inp[cnt] += nbytes;
}
/* Clean up the page and adjust the item's reference. */
HOFFSET(h) += nbytes;
t += nbytes;
}
/* Copy the new item onto the page. */
bk = (BKEYDATA *)t;
B_TSET(bk->type, B_KEYDATA, 0);
bk->len = data->size;
memcpy(bk->data, data->data, data->size);
return (0);
}
/*
* __bam_dup_check --
* Check to see if the duplicate set at indx should have its own page.
*/
static int
__bam_dup_check(dbc, op, h, indx, sz, cntp)
DBC *dbc;
u_int32_t op;
PAGE *h;
u_int32_t indx, sz;
db_indx_t *cntp;
{
BKEYDATA *bk;
DB *dbp;
db_indx_t cnt, first, *inp;
dbp = dbc->dbp;
inp = P_INP(dbp, h);
/*
* Count the duplicate records and calculate how much room they're
* using on the page.
*/
while (indx > 0 && inp[indx] == inp[indx - P_INDX])
indx -= P_INDX;
/* Count the key once. */
bk = GET_BKEYDATA(dbp, h, indx);
sz += B_TYPE(bk->type) == B_KEYDATA ?
BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE;
/* Sum up all the data items. */
first = indx;
/*
* Account for the record being inserted. If we are replacing it,
* don't count it twice.
*
* We execute the loop with first == indx to get the size of the
* first record.
*/
cnt = op == DB_CURRENT ? 0 : 1;
for (first = indx;
indx < NUM_ENT(h) && inp[first] == inp[indx];
++cnt, indx += P_INDX) {
bk = GET_BKEYDATA(dbp, h, indx + O_INDX);
sz += B_TYPE(bk->type) == B_KEYDATA ?
BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE;
}
/*
* We have to do these checks when the user is replacing the cursor's
* data item -- if the application replaces a duplicate item with a
* larger data item, it can increase the amount of space used by the
* duplicates, requiring this check. But that means we may have done
* this check when it wasn't a duplicate item after all.
*/
if (cnt == 1)
return (0);
/*
* If this set of duplicates is using more than 25% of the page, move
* them off. The choice of 25% is a WAG, but the value must be small
* enough that we can always split a page without putting duplicates
* on two different pages.
*/
if (sz < dbp->pgsize / 4)
return (0);
*cntp = cnt;
return (1);
}
/*
* __bam_dup_convert --
* Move a set of duplicates off-page and into their own tree.
*/
static int
__bam_dup_convert(dbc, h, indx, cnt)
DBC *dbc;
PAGE *h;
u_int32_t indx, cnt;
{
BKEYDATA *bk;
DB *dbp;
DBT hdr;
DB_MPOOLFILE *mpf;
PAGE *dp;
db_indx_t cpindx, dindx, first, *inp;
int ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
inp = P_INP(dbp, h);
/* Move to the beginning of the dup set. */
while (indx > 0 && inp[indx] == inp[indx - P_INDX])
indx -= P_INDX;
/* Get a new page. */
if ((ret = __db_new(dbc,
dbp->dup_compare == NULL ? P_LRECNO : P_LDUP, &dp)) != 0)
return (ret);
P_INIT(dp, dbp->pgsize, dp->pgno,
PGNO_INVALID, PGNO_INVALID, LEAFLEVEL, TYPE(dp));
/*
* Move this set of duplicates off the page. First points to the first
* key of the first duplicate key/data pair, cnt is the number of pairs
* we're dealing with.
*/
memset(&hdr, 0, sizeof(hdr));
first = indx;
dindx = indx;
cpindx = 0;
do {
/* Move cursors referencing the old entry to the new entry. */
if ((ret = __bam_ca_dup(dbc, first,
PGNO(h), indx, PGNO(dp), cpindx)) != 0)
goto err;
/*
* Copy the entry to the new page. If the off-duplicate page
* If the off-duplicate page is a Btree page (i.e. dup_compare
* will be non-NULL, we use Btree pages for sorted dups,
* and Recno pages for unsorted dups), move all entries
* normally, even deleted ones. If it's a Recno page,
* deleted entries are discarded (if the deleted entry is
* overflow, then free up those pages).
*/
bk = GET_BKEYDATA(dbp, h, dindx + 1);
hdr.data = bk;
hdr.size = B_TYPE(bk->type) == B_KEYDATA ?
BKEYDATA_SIZE(bk->len) : BOVERFLOW_SIZE;
if (dbp->dup_compare == NULL && B_DISSET(bk->type)) {
/*
* Unsorted dups, i.e. recno page, and we have
* a deleted entry, don't move it, but if it was
* an overflow entry, we need to free those pages.
*/
if (B_TYPE(bk->type) == B_OVERFLOW &&
(ret = __db_doff(dbc,
(GET_BOVERFLOW(dbp, h, dindx + 1))->pgno)) != 0)
goto err;
} else {
if ((ret = __db_pitem(
dbc, dp, cpindx, hdr.size, &hdr, NULL)) != 0)
goto err;
++cpindx;
}
/* Delete all but the last reference to the key. */
if (cnt != 1) {
if ((ret = __bam_adjindx(dbc,
h, dindx, first + 1, 0)) != 0)
goto err;
} else
dindx++;
/* Delete the data item. */
if ((ret = __db_ditem(dbc, h, dindx, hdr.size)) != 0)
goto err;
indx += P_INDX;
} while (--cnt);
/* Put in a new data item that points to the duplicates page. */
if ((ret = __bam_ovput(dbc,
B_DUPLICATE, dp->pgno, h, first + 1, NULL)) != 0)
goto err;
/* Adjust cursors for all the above movements. */
if ((ret = __bam_ca_di(dbc,
PGNO(h), first + P_INDX, (int)(first + P_INDX - indx))) != 0)
goto err;
return (__memp_fput(mpf, dp, DB_MPOOL_DIRTY));
err: (void)__memp_fput(mpf, dp, 0);
return (ret);
}
/*
* __bam_ovput --
* Build an item for an off-page duplicates page or overflow page and
* insert it on the page.
*/
static int
__bam_ovput(dbc, type, pgno, h, indx, item)
DBC *dbc;
u_int32_t type, indx;
db_pgno_t pgno;
PAGE *h;
DBT *item;
{
BOVERFLOW bo;
DBT hdr;
int ret;
UMRW_SET(bo.unused1);
B_TSET(bo.type, type, 0);
UMRW_SET(bo.unused2);
/*
* If we're creating an overflow item, do so and acquire the page
* number for it. If we're creating an off-page duplicates tree,
* we are giving the page number as an argument.
*/
if (type == B_OVERFLOW) {
if ((ret = __db_poff(dbc, item, &bo.pgno)) != 0)
return (ret);
bo.tlen = item->size;
} else {
bo.pgno = pgno;
bo.tlen = 0;
}
/* Store the new record on the page. */
memset(&hdr, 0, sizeof(hdr));
hdr.data = &bo;
hdr.size = BOVERFLOW_SIZE;
return (__db_pitem(dbc, h, indx, BOVERFLOW_SIZE, &hdr, NULL));
}

File diff suppressed because it is too large Load diff

View file

@ -1,76 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1998-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_reclaim.c,v 12.2 2005/06/16 20:20:19 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/btree.h"
/*
* __bam_reclaim --
* Free a database.
*
* PUBLIC: int __bam_reclaim __P((DB *, DB_TXN *));
*/
int
__bam_reclaim(dbp, txn)
DB *dbp;
DB_TXN *txn;
{
DBC *dbc;
int ret, t_ret;
/* Acquire a cursor. */
if ((ret = __db_cursor(dbp, txn, &dbc, 0)) != 0)
return (ret);
/* Walk the tree, freeing pages. */
ret = __bam_traverse(dbc,
DB_LOCK_WRITE, dbc->internal->root, __db_reclaim_callback, dbc);
/* Discard the cursor. */
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
/*
* __bam_truncate --
* Truncate a database.
*
* PUBLIC: int __bam_truncate __P((DBC *, u_int32_t *));
*/
int
__bam_truncate(dbc, countp)
DBC *dbc;
u_int32_t *countp;
{
db_trunc_param trunc;
int ret;
trunc.count = 0;
trunc.dbc = dbc;
/* Walk the tree, freeing pages. */
ret = __bam_traverse(dbc,
DB_LOCK_WRITE, dbc->internal->root, __db_truncate_callback, &trunc);
if (countp != NULL)
*countp = trunc.count;
return (ret);
}

File diff suppressed because it is too large Load diff

View file

@ -1,431 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* 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. 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.
*
* $Id: bt_rsearch.c,v 12.5 2005/08/08 03:37:05 ubell Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/btree.h"
#include "dbinc/db_shash.h"
#include "dbinc/lock.h"
#include "dbinc/mp.h"
/*
* __bam_rsearch --
* Search a btree for a record number.
*
* PUBLIC: int __bam_rsearch __P((DBC *, db_recno_t *, u_int32_t, int, int *));
*/
int
__bam_rsearch(dbc, recnop, flags, stop, exactp)
DBC *dbc;
db_recno_t *recnop;
u_int32_t flags;
int stop, *exactp;
{
BINTERNAL *bi;
BTREE_CURSOR *cp;
DB *dbp;
DB_LOCK lock;
DB_MPOOLFILE *mpf;
PAGE *h;
RINTERNAL *ri;
db_indx_t adjust, deloffset, indx, top;
db_lockmode_t lock_mode;
db_pgno_t pg;
db_recno_t recno, t_recno, total;
int ret, stack, t_ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
h = NULL;
BT_STK_CLR(cp);
/*
* 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. In addition, if we're adding or deleting
* an item, we have to lock the entire tree, regardless. 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.
*/
if ((ret = __bam_get_root(dbc, cp->root, stop, flags, &stack)) != 0)
return (ret);
lock_mode = cp->csp->lock_mode;
lock = cp->csp->lock;
h = cp->csp->page;
BT_STK_CLR(cp);
/*
* 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.
*/
total = RE_NREC(h);
if (LF_ISSET(S_APPEND)) {
*exactp = 0;
*recnop = recno = total + 1;
} else {
recno = *recnop;
if (recno <= total)
*exactp = 1;
else {
*exactp = 0;
if (!LF_ISSET(S_PAST_EOF) || recno > total + 1) {
/*
* Keep the page locked for serializability.
*
* XXX
* This leaves the root page locked, which will
* eliminate any concurrency. A possible fix
* would be to lock the last leaf page instead.
*/
ret = __memp_fput(mpf, h, 0);
if ((t_ret =
__TLPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
return (ret == 0 ? DB_NOTFOUND : ret);
}
}
}
/*
* !!!
* 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:
case P_LDUP:
recno -= total;
/*
* There may be logically deleted records on the page.
* If there are enough, the record may not exist.
*/
if (TYPE(h) == P_LBTREE) {
adjust = P_INDX;
deloffset = O_INDX;
} else {
adjust = O_INDX;
deloffset = 0;
}
for (t_recno = 0, indx = 0;; indx += adjust) {
if (indx >= NUM_ENT(h)) {
*exactp = 0;
if (!LF_ISSET(S_PAST_EOF) ||
recno > t_recno + 1) {
ret = __memp_fput(mpf, h, 0);
h = NULL;
if ((t_ret = __TLPUT(dbc,
lock)) != 0 && ret == 0)
ret = t_ret;
if (ret == 0)
ret = DB_NOTFOUND;
goto err;
}
}
if (!B_DISSET(GET_BKEYDATA(dbp, h,
indx + deloffset)->type) &&
++t_recno == recno)
break;
}
/* Correct from 1-based to 0-based for a page offset. */
BT_STK_ENTER(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
return (0);
case P_IBTREE:
for (indx = 0, top = NUM_ENT(h);;) {
bi = GET_BINTERNAL(dbp, 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(dbp->dbenv,
cp, h, recno, lock, lock_mode, ret);
if (ret != 0)
goto err;
return (0);
case P_IRECNO:
for (indx = 0, top = NUM_ENT(h);;) {
ri = GET_RINTERNAL(dbp, h, indx);
if (++indx == top || total + ri->nrecs >= recno)
break;
total += ri->nrecs;
}
pg = ri->pgno;
break;
default:
return (__db_pgfmt(dbp->dbenv, h->pgno));
}
--indx;
/* Return if this is the lowest page wanted. */
if (stop == LEVEL(h)) {
BT_STK_ENTER(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
return (0);
}
if (stack) {
BT_STK_PUSH(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
h = NULL;
lock_mode = DB_LOCK_WRITE;
if ((ret =
__db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
goto err;
} else {
/*
* 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)(LEVEL(h) - 1)) ||
(LEVEL(h) - 1) == LEAFLEVEL)
stack = 1;
if ((ret = __memp_fput(mpf, h, 0)) != 0)
goto err;
h = NULL;
lock_mode = stack &&
LF_ISSET(S_WRITE) ? DB_LOCK_WRITE : DB_LOCK_READ;
if ((ret = __db_lget(dbc,
LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) {
/*
* If we fail, discard the lock we held. This
* is OK because this only happens when we are
* descending the tree holding read-locks.
*/
(void)__LPUT(dbc, lock);
goto err;
}
}
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0)
goto err;
}
/* NOTREACHED */
err: if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret;
BT_STK_POP(cp);
__bam_stkrel(dbc, 0);
return (ret);
}
/*
* __bam_adjust --
* Adjust the tree after adding or deleting a record.
*
* PUBLIC: int __bam_adjust __P((DBC *, int32_t));
*/
int
__bam_adjust(dbc, adjust)
DBC *dbc;
int32_t adjust;
{
BTREE_CURSOR *cp;
DB *dbp;
DB_MPOOLFILE *mpf;
EPG *epg;
PAGE *h;
db_pgno_t root_pgno;
int ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
root_pgno = cp->root;
/* Update the record counts for the tree. */
for (epg = cp->sp; epg <= cp->csp; ++epg) {
h = epg->page;
if (TYPE(h) == P_IBTREE || TYPE(h) == P_IRECNO) {
if (DBC_LOGGING(dbc)) {
if ((ret = __bam_cadjust_log(dbp, dbc->txn,
&LSN(h), 0, PGNO(h), &LSN(h),
(u_int32_t)epg->indx, adjust,
PGNO(h) == root_pgno ?
CAD_UPDATEROOT : 0)) != 0)
return (ret);
} else
LSN_NOT_LOGGED(LSN(h));
if (TYPE(h) == P_IBTREE)
GET_BINTERNAL(dbp, h, epg->indx)->nrecs +=
adjust;
else
GET_RINTERNAL(dbp, h, epg->indx)->nrecs +=
adjust;
if (PGNO(h) == root_pgno)
RE_NREC_ADJ(h, adjust);
if ((ret = __memp_fset(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((DBC *, db_recno_t *));
*/
int
__bam_nrecs(dbc, rep)
DBC *dbc;
db_recno_t *rep;
{
DB *dbp;
DB_LOCK lock;
DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t pgno;
int ret, t_ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
pgno = dbc->internal->root;
if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
return (ret);
*rep = RE_NREC(h);
ret = __memp_fput(mpf, h, 0);
if ((t_ret = __TLPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
/*
* __bam_total --
* Return the number of records below a page.
*
* PUBLIC: db_recno_t __bam_total __P((DB *, PAGE *));
*/
db_recno_t
__bam_total(dbp, h)
DB *dbp;
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(dbp, h, indx + O_INDX)->type))
++nrecs;
break;
case P_LDUP:
/* Check for logically deleted records. */
for (indx = 0; indx < top; indx += O_INDX)
if (!B_DISSET(GET_BKEYDATA(dbp, h, indx)->type))
++nrecs;
break;
case P_IBTREE:
for (indx = 0; indx < top; indx += O_INDX)
nrecs += GET_BINTERNAL(dbp, 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(dbp, h, indx)->nrecs;
break;
}
return (nrecs);
}

View file

@ -1,706 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* 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. 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.
*
* $Id: bt_search.c,v 12.17 2005/11/10 21:17:13 ubell Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/btree.h"
#include "dbinc/lock.h"
#include "dbinc/mp.h"
/*
* __bam_get_root --
* Fetch the root of a tree and see if we want to keep
* it in the stack.
*
* PUBLIC: int __bam_get_root __P((DBC *, db_pgno_t, int, u_int32_t, int *));
*/
int
__bam_get_root(dbc, pg, slevel, flags, stack)
DBC *dbc;
db_pgno_t pg;
int slevel;
u_int32_t flags;
int *stack;
{
BTREE_CURSOR *cp;
DB *dbp;
DB_LOCK lock;
DB_MPOOLFILE *mpf;
PAGE *h;
db_lockmode_t lock_mode;
int ret, t_ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
/*
* 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.
*/
try_again:
*stack = LF_ISSET(S_STACK) &&
(dbc->dbtype == DB_RECNO || F_ISSET(cp, C_RECNUM));
lock_mode = DB_LOCK_READ;
if (*stack ||
LF_ISSET(S_DEL) || (LF_ISSET(S_NEXT) && LF_ISSET(S_WRITE)))
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, 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)(slevel + 1) >= LEVEL(h)) ||
(LF_ISSET(S_WRITE) && LEVEL(h) == LEAFLEVEL) ||
(LF_ISSET(S_START) && slevel == LEVEL(h)))) {
if (!STD_LOCKING(dbc))
goto no_relock;
ret = __memp_fput(mpf, h, 0);
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
if (!((LF_ISSET(S_PARENT) &&
(u_int8_t)(slevel + 1) >= LEVEL(h)) ||
(LF_ISSET(S_WRITE) && LEVEL(h) == LEAFLEVEL) ||
(LF_ISSET(S_START) && slevel == LEVEL(h)))) {
/* Someone else split the root, start over. */
ret = __memp_fput(mpf, h, 0);
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
goto try_again;
}
no_relock: *stack = 1;
}
BT_STK_ENTER(dbp->dbenv, cp, h, 0, lock, lock_mode, ret);
return (ret);
}
/*
* __bam_search --
* Search a btree for a key.
*
* PUBLIC: int __bam_search __P((DBC *, db_pgno_t,
* PUBLIC: const DBT *, u_int32_t, int, db_recno_t *, int *));
*/
int
__bam_search(dbc, root_pgno, key, flags, slevel, recnop, exactp)
DBC *dbc;
db_pgno_t root_pgno;
const DBT *key;
u_int32_t flags;
int slevel, *exactp;
db_recno_t *recnop;
{
BTREE *t;
BTREE_CURSOR *cp;
DB *dbp;
DB_LOCK lock;
DB_MPOOLFILE *mpf;
PAGE *h;
db_indx_t base, i, indx, *inp, lim;
db_lockmode_t lock_mode;
db_pgno_t pg;
db_recno_t recno;
int adjust, cmp, deloffset, ret, stack, t_ret;
int (*func) __P((DB *, const DBT *, const DBT *));
dbp = dbc->dbp;
mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
h = NULL;
t = dbp->bt_internal;
recno = 0;
BT_STK_CLR(cp);
/*
* 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. In addition,
* if we're modifying record numbers, we have to lock the entire tree
* regardless. See btree.h for more details.
*/
if (root_pgno == PGNO_INVALID)
root_pgno = cp->root;
if ((ret = __bam_get_root(dbc, root_pgno, slevel, flags, &stack)) != 0)
return (ret);
lock_mode = cp->csp->lock_mode;
lock = cp->csp->lock;
h = cp->csp->page;
BT_STK_CLR(cp);
/* Choose a comparison function. */
func = F_ISSET(dbc, DBC_OPD) ?
(dbp->dup_compare == NULL ? __bam_defcmp : dbp->dup_compare) :
t->bt_compare;
for (;;) {
inp = P_INP(dbp, h);
adjust = TYPE(h) == P_LBTREE ? P_INDX : O_INDX;
if (LF_ISSET(S_MIN | S_MAX)) {
if (LF_ISSET(S_MIN) || NUM_ENT(h) == 0)
indx = 0;
else if (TYPE(h) == P_LBTREE)
indx = NUM_ENT(h) - 2;
else
indx = NUM_ENT(h) - 1;
if (LEVEL(h) == LEAFLEVEL ||
(!LF_ISSET(S_START) && LEVEL(h) == slevel)) {
if (LF_ISSET(S_NEXT))
goto get_next;
goto found;
}
goto next;
}
/*
* Do a binary search on the current page. If we're searching
* a Btree leaf page, we have to walk the indices in groups of
* two. If we're searching an internal page or a off-page dup
* page, they're an index per page item. If we find an exact
* match on a leaf page, we're done.
*/
for (base = 0,
lim = NUM_ENT(h) / (db_indx_t)adjust; lim != 0; lim >>= 1) {
indx = base + ((lim >> 1) * adjust);
if ((ret =
__bam_cmp(dbp, key, h, indx, func, &cmp)) != 0)
goto err;
if (cmp == 0) {
if (LEVEL(h) == LEAFLEVEL ||
(!LF_ISSET(S_START) &&
LEVEL(h) == slevel)) {
if (LF_ISSET(S_NEXT))
goto get_next;
goto found;
}
goto next;
}
if (cmp > 0) {
base = indx + adjust;
--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 or the stopping point,
* return base as the "found" value.
* Delete only deletes exact matches.
*/
if (LEVEL(h) == LEAFLEVEL ||
(!LF_ISSET(S_START) && LEVEL(h) == slevel)) {
*exactp = 0;
if (LF_ISSET(S_EXACT)) {
ret = DB_NOTFOUND;
goto err;
}
if (LF_ISSET(S_STK_ONLY)) {
BT_STK_NUM(dbp->dbenv, cp, h, base, ret);
if ((t_ret =
__LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if ((t_ret =
__memp_fput(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
if (LF_ISSET(S_NEXT)) {
get_next: /*
* The caller could have asked for a NEXT
* at the root if the tree recently collapsed.
*/
if (PGNO(h) == root_pgno) {
ret = DB_NOTFOUND;
goto err;
}
/*
* Save the root of the subtree
* and drop the rest of the subtree
* and search down again starting at
* the next child.
*/
if ((ret = __LPUT(dbc, lock)) != 0)
goto err;
if ((ret = __memp_fput(mpf, h, 0)) != 0)
goto err;
h = NULL;
LF_SET(S_MIN);
LF_CLR(S_NEXT);
indx = cp->sp->indx + 1;
if (indx == NUM_ENT(cp->sp->page)) {
ret = DB_NOTFOUND;
cp->csp++;
goto err;
}
h = cp->sp->page;
cp->sp->page = NULL;
lock = cp->sp->lock;
LOCK_INIT(cp->sp->lock);
if ((ret = __bam_stkrel(dbc, STK_NOLOCK)) != 0)
goto err;
stack = 1;
goto next;
}
/*
* !!!
* 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 by the
* calling routine.
*/
if (LF_ISSET(S_DEL) && cp->csp == cp->sp)
cp->csp++;
BT_STK_ENTER(dbp->dbenv,
cp, h, base, lock, lock_mode, ret);
if (ret != 0)
goto err;
return (0);
}
/*
* 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.
*/
next: if (recnop != NULL)
for (i = 0; i < indx; ++i)
recno += GET_BINTERNAL(dbp, h, i)->nrecs;
pg = GET_BINTERNAL(dbp, h, indx)->pgno;
/* See if we are at the level to start stacking. */
if (LF_ISSET(S_START) && slevel == LEVEL(h))
stack = 1;
if (LF_ISSET(S_STK_ONLY)) {
if (slevel == LEVEL(h)) {
BT_STK_NUM(dbp->dbenv, cp, h, indx, ret);
if ((t_ret =
__LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if ((t_ret =
__memp_fput(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
BT_STK_NUMPUSH(dbp->dbenv, cp, h, indx, ret);
(void)__memp_fput(mpf, h, 0);
h = NULL;
if ((ret = __db_lget(dbc,
LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) {
/*
* Discard our lock and return on failure. This
* is OK because it only happens when descending
* the tree holding read-locks.
*/
(void)__LPUT(dbc, lock);
return (ret);
}
} else if (stack) {
/* Return if this is the lowest page wanted. */
if (LF_ISSET(S_PARENT) && slevel == LEVEL(h)) {
BT_STK_ENTER(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
return (0);
}
if (LF_ISSET(S_DEL) && NUM_ENT(h) > 1) {
/*
* There was a page with a singleton pointer
* to a non-empty subtree.
*/
cp->csp--;
if ((ret = __bam_stkrel(dbc, STK_NOLOCK)) != 0)
goto err;
stack = 0;
goto do_del;
}
BT_STK_PUSH(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
h = NULL;
lock_mode = DB_LOCK_WRITE;
if ((ret =
__db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
goto err;
} else {
/*
* Decide if we want to return a reference to the next
* page in the return stack. If so, lock it and never
* unlock it.
*/
if ((LF_ISSET(S_PARENT) &&
(u_int8_t)(slevel + 1) >= (LEVEL(h) - 1)) ||
(LEVEL(h) - 1) == LEAFLEVEL)
stack = 1;
/*
* Returning a subtree. See if we have hit the start
* point if so save the parent and set stack.
* Otherwise free the parent and temporarily
* save this one.
* For S_DEL we need to find a page with 1 entry.
* For S_NEXT we want find the minimal subtree
* that contains the key and the next page.
* We save pages as long as we are at the right
* edge of the subtree. When we leave the right
* edge, then drop the subtree.
*/
if (!LF_ISSET(S_DEL | S_NEXT)) {
if ((ret = __memp_fput(mpf, h, 0)) != 0)
goto err;
goto lock_next;
}
if ((LF_ISSET(S_DEL) && NUM_ENT(h) == 1)) {
stack = 1;
LF_SET(S_WRITE);
/* Push the parent. */
cp->csp++;
/* Push this node. */
BT_STK_PUSH(dbp->dbenv, cp, h,
indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
LOCK_INIT(lock);
} else {
/*
* See if we want to save the tree so far.
* If we are looking for the next key,
* then we must save this node if we are
* at the end of the page. If not then
* discard anything we have saved so far.
* For delete only keep one node until
* we find a singleton.
*/
do_del: if (cp->csp->page != NULL) {
if (LF_ISSET(S_NEXT) &&
indx == NUM_ENT(h) - 1)
cp->csp++;
else if ((ret =
__bam_stkrel(dbc, STK_NOLOCK)) != 0)
goto err;
}
/* Save this node. */
BT_STK_ENTER(dbp->dbenv, cp,
h, indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
LOCK_INIT(lock);
}
lock_next: h = NULL;
if (stack && LF_ISSET(S_WRITE))
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc,
LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) {
/*
* If we fail, discard the lock we held. This
* is OK because this only happens when we are
* descending the tree holding read-locks.
*/
(void)__LPUT(dbc, lock);
if (LF_ISSET(S_DEL | S_NEXT))
cp->csp++;
goto err;
}
}
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0)
goto err;
}
/* NOTREACHED */
found: *exactp = 1;
/*
* If we got here, we know that we have a Btree leaf or off-page
* duplicates page. If it's a Btree leaf page, we have to handle
* on-page duplicates.
*
* 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 (TYPE(h) == P_LBTREE && NUM_ENT(h) > P_INDX) {
if (LF_ISSET(S_DUPLAST))
while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
inp[indx] == inp[indx + P_INDX])
indx += P_INDX;
else if (LF_ISSET(S_DUPFIRST))
while (indx > 0 &&
inp[indx] == inp[indx - P_INDX])
indx -= P_INDX;
}
/*
* Now check if we are allowed to return deleted items; if not, then
* find the next (or previous) non-deleted duplicate entry. (We do
* not move from the original found key on the basis of the S_DELNO
* flag.)
*/
DB_ASSERT(recnop == NULL || LF_ISSET(S_DELNO));
if (LF_ISSET(S_DELNO)) {
deloffset = TYPE(h) == P_LBTREE ? O_INDX : 0;
if (LF_ISSET(S_DUPLAST))
while (B_DISSET(GET_BKEYDATA(dbp,
h, indx + deloffset)->type) && indx > 0 &&
inp[indx] == inp[indx - adjust])
indx -= adjust;
else
while (B_DISSET(GET_BKEYDATA(dbp,
h, indx + deloffset)->type) &&
indx < (db_indx_t)(NUM_ENT(h) - adjust) &&
inp[indx] == inp[indx + adjust])
indx += adjust;
/*
* If we weren't able to find a non-deleted duplicate, return
* DB_NOTFOUND.
*/
if (B_DISSET(GET_BKEYDATA(dbp, h, indx + deloffset)->type)) {
ret = DB_NOTFOUND;
goto err;
}
/*
* Increment the record counter to point to the found element.
* Ignore any deleted key/data pairs. There doesn't need to
* be any correction for duplicates, as Btree doesn't support
* duplicates and record numbers in the same tree.
*/
if (recnop != NULL) {
DB_ASSERT(TYPE(h) == P_LBTREE);
for (i = 0; i < indx; i += P_INDX)
if (!B_DISSET(
GET_BKEYDATA(dbp, h, i + O_INDX)->type))
++recno;
/* Correct the number for a 0-base. */
*recnop = recno + 1;
}
}
if (LF_ISSET(S_STK_ONLY)) {
BT_STK_NUM(dbp->dbenv, cp, h, indx, ret);
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret;
} else {
if (LF_ISSET(S_DEL) && cp->csp == cp->sp)
cp->csp++;
BT_STK_ENTER(dbp->dbenv, cp, h, indx, lock, lock_mode, ret);
}
if (ret != 0)
goto err;
return (0);
err: if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret;
/* Keep any not-found page locked for serializability. */
if ((t_ret = __TLPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
BT_STK_POP(cp);
__bam_stkrel(dbc, 0);
return (ret);
}
/*
* __bam_stkrel --
* Release all pages currently held in the stack.
*
* PUBLIC: int __bam_stkrel __P((DBC *, u_int32_t));
*/
int
__bam_stkrel(dbc, flags)
DBC *dbc;
u_int32_t flags;
{
BTREE_CURSOR *cp;
DB *dbp;
DB_MPOOLFILE *mpf;
EPG *epg;
int ret, t_ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
/*
* Release inner pages first.
*
* The caller must be sure that setting STK_NOLOCK will not effect
* either serializability or recoverability.
*/
for (ret = 0, epg = cp->sp; epg <= cp->csp; ++epg) {
if (epg->page != NULL) {
if (LF_ISSET(STK_CLRDBC) && cp->page == epg->page) {
cp->page = NULL;
LOCK_INIT(cp->lock);
}
if ((t_ret =
__memp_fput(mpf, epg->page, 0)) != 0 && ret == 0)
ret = t_ret;
/*
* XXX
* Temporary fix for #3243 -- under certain deadlock
* conditions we call here again and re-free the page.
* The correct fix is to never release a stack that
* doesn't hold items.
*/
epg->page = NULL;
}
/*
* We set this if we need to release our pins,
* but are not logically ready to have the pages
* visible.
*/
if (LF_ISSET(STK_PGONLY))
continue;
if (LF_ISSET(STK_NOLOCK)) {
if ((t_ret = __LPUT(dbc, epg->lock)) != 0 && ret == 0)
ret = t_ret;
} else
if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
ret = t_ret;
}
/* Clear the stack, all pages have been released. */
if (!LF_ISSET(STK_PGONLY))
BT_STK_CLR(cp);
return (ret);
}
/*
* __bam_stkgrow --
* Grow the stack.
*
* PUBLIC: int __bam_stkgrow __P((DB_ENV *, BTREE_CURSOR *));
*/
int
__bam_stkgrow(dbenv, cp)
DB_ENV *dbenv;
BTREE_CURSOR *cp;
{
EPG *p;
size_t entries;
int ret;
entries = cp->esp - cp->sp;
if ((ret = __os_calloc(dbenv, entries * 2, sizeof(EPG), &p)) != 0)
return (ret);
memcpy(p, cp->sp, entries * sizeof(EPG));
if (cp->sp != cp->stack)
__os_free(dbenv, cp->sp);
cp->sp = p;
cp->csp = p + entries;
cp->esp = p + entries * 2;
return (0);
}

File diff suppressed because it is too large Load diff

View file

@ -1,638 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_stat.c,v 12.3 2005/06/16 20:20:23 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <ctype.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/btree.h"
#include "dbinc/lock.h"
#include "dbinc/mp.h"
#ifdef HAVE_STATISTICS
/*
* __bam_stat --
* Gather/print the btree statistics
*
* PUBLIC: int __bam_stat __P((DBC *, void *, u_int32_t));
*/
int
__bam_stat(dbc, spp, flags)
DBC *dbc;
void *spp;
u_int32_t flags;
{
BTMETA *meta;
BTREE *t;
BTREE_CURSOR *cp;
DB *dbp;
DB_BTREE_STAT *sp;
DB_ENV *dbenv;
DB_LOCK lock, metalock;
DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t pgno;
int ret, t_ret, write_meta;
dbp = dbc->dbp;
dbenv = dbp->dbenv;
meta = NULL;
t = dbp->bt_internal;
sp = NULL;
LOCK_INIT(metalock);
LOCK_INIT(lock);
mpf = dbp->mpf;
h = NULL;
ret = write_meta = 0;
cp = (BTREE_CURSOR *)dbc->internal;
/* Allocate and clear the structure. */
if ((ret = __os_umalloc(dbenv, sizeof(*sp), &sp)) != 0)
goto err;
memset(sp, 0, sizeof(*sp));
/* Get the metadata page for the entire database. */
pgno = PGNO_BASE_MD;
if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &metalock)) != 0)
goto err;
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0)
goto err;
if (flags == DB_RECORDCOUNT || flags == DB_CACHED_COUNTS)
flags = DB_FAST_STAT;
if (flags == DB_FAST_STAT)
goto meta_only;
/* Walk the metadata free list, counting pages. */
for (sp->bt_free = 0, pgno = meta->dbmeta.free; pgno != PGNO_INVALID;) {
++sp->bt_free;
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
goto err;
pgno = h->next_pgno;
if ((ret = __memp_fput(mpf, h, 0)) != 0)
goto err;
h = NULL;
}
/* Get the root page. */
pgno = cp->root;
if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lock)) != 0)
goto err;
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
goto err;
/* Get the levels from the root page. */
sp->bt_levels = h->level;
/* Discard the root page. */
ret = __memp_fput(mpf, h, 0);
h = NULL;
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
goto err;
/* Walk the tree. */
if ((ret = __bam_traverse(dbc,
DB_LOCK_READ, cp->root, __bam_stat_callback, sp)) != 0)
goto err;
/*
* Get the subdatabase metadata page if it's not the same as the
* one we already have.
*/
write_meta = !F_ISSET(dbp, DB_AM_RDONLY);
meta_only:
if (t->bt_meta != PGNO_BASE_MD || write_meta != 0) {
ret = __memp_fput(mpf, meta, 0);
meta = NULL;
if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
goto err;
if ((ret = __db_lget(dbc,
0, t->bt_meta, write_meta == 0 ?
DB_LOCK_READ : DB_LOCK_WRITE, 0, &metalock)) != 0)
goto err;
if ((ret = __memp_fget(mpf, &t->bt_meta, 0, &meta)) != 0)
goto err;
}
if (flags == DB_FAST_STAT) {
if (dbp->type == DB_RECNO ||
(dbp->type == DB_BTREE && F_ISSET(dbp, DB_AM_RECNUM))) {
if ((ret = __db_lget(dbc, 0,
cp->root, DB_LOCK_READ, 0, &lock)) != 0)
goto err;
if ((ret = __memp_fget(mpf, &cp->root, 0, &h)) != 0)
goto err;
sp->bt_nkeys = RE_NREC(h);
} else
sp->bt_nkeys = meta->dbmeta.key_count;
sp->bt_ndata = dbp->type == DB_RECNO ?
sp->bt_nkeys : meta->dbmeta.record_count;
}
/* Get metadata page statistics. */
sp->bt_metaflags = meta->dbmeta.flags;
sp->bt_minkey = meta->minkey;
sp->bt_re_len = meta->re_len;
sp->bt_re_pad = meta->re_pad;
sp->bt_pagesize = meta->dbmeta.pagesize;
sp->bt_magic = meta->dbmeta.magic;
sp->bt_version = meta->dbmeta.version;
if (write_meta != 0) {
meta->dbmeta.key_count = sp->bt_nkeys;
meta->dbmeta.record_count = sp->bt_ndata;
}
*(DB_BTREE_STAT **)spp = sp;
err: /* Discard the second page. */
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret;
/* Discard the metadata page. */
if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
ret = t_ret;
if (meta != NULL && (t_ret = __memp_fput(
mpf, meta, write_meta == 0 ? 0 : DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0 && sp != NULL) {
__os_ufree(dbenv, sp);
*(DB_BTREE_STAT **)spp = NULL;
}
return (ret);
}
/*
* __bam_stat_print --
* Display btree/recno statistics.
*
* PUBLIC: int __bam_stat_print __P((DBC *, u_int32_t));
*/
int
__bam_stat_print(dbc, flags)
DBC *dbc;
u_int32_t flags;
{
static const FN fn[] = {
{ BTM_DUP, "duplicates" },
{ BTM_RECNO, "recno" },
{ BTM_RECNUM, "record-numbers" },
{ BTM_FIXEDLEN, "fixed-length" },
{ BTM_RENUMBER, "renumber" },
{ BTM_SUBDB, "multiple-databases" },
{ BTM_DUPSORT, "sorted duplicates" },
{ 0, NULL }
};
DB *dbp;
DB_BTREE_STAT *sp;
DB_ENV *dbenv;
int lorder, ret;
const char *s;
dbp = dbc->dbp;
dbenv = dbp->dbenv;
if ((ret = __bam_stat(dbc, &sp, 0)) != 0)
return (ret);
if (LF_ISSET(DB_STAT_ALL)) {
__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
__db_msg(dbenv, "Default Btree/Recno database information:");
}
__db_msg(dbenv, "%lx\tBtree magic number", (u_long)sp->bt_magic);
__db_msg(dbenv, "%lu\tBtree version number", (u_long)sp->bt_version);
(void)__db_get_lorder(dbp, &lorder);
switch (lorder) {
case 1234:
s = "Little-endian";
break;
case 4321:
s = "Big-endian";
break;
default:
s = "Unrecognized byte order";
break;
}
__db_msg(dbenv, "%s\tByte order", s);
__db_prflags(dbenv, NULL, sp->bt_metaflags, fn, NULL, "\tFlags");
if (dbp->type == DB_BTREE)
__db_dl(dbenv, "Minimum keys per-page", (u_long)sp->bt_minkey);
if (dbp->type == DB_RECNO) {
__db_dl(dbenv,
"Fixed-length record size", (u_long)sp->bt_re_len);
__db_msg(dbenv,
"%#x\tFixed-length record pad", (u_int)sp->bt_re_pad);
}
__db_dl(dbenv,
"Underlying database page size", (u_long)sp->bt_pagesize);
__db_dl(dbenv, "Number of levels in the tree", (u_long)sp->bt_levels);
__db_dl(dbenv, dbp->type == DB_BTREE ?
"Number of unique keys in the tree" :
"Number of records in the tree", (u_long)sp->bt_nkeys);
__db_dl(dbenv,
"Number of data items in the tree", (u_long)sp->bt_ndata);
__db_dl(dbenv,
"Number of tree internal pages", (u_long)sp->bt_int_pg);
__db_dl_pct(dbenv,
"Number of bytes free in tree internal pages",
(u_long)sp->bt_int_pgfree,
DB_PCT_PG(sp->bt_int_pgfree, sp->bt_int_pg, sp->bt_pagesize), "ff");
__db_dl(dbenv,
"Number of tree leaf pages", (u_long)sp->bt_leaf_pg);
__db_dl_pct(dbenv, "Number of bytes free in tree leaf pages",
(u_long)sp->bt_leaf_pgfree, DB_PCT_PG(
sp->bt_leaf_pgfree, sp->bt_leaf_pg, sp->bt_pagesize), "ff");
__db_dl(dbenv,
"Number of tree duplicate pages", (u_long)sp->bt_dup_pg);
__db_dl_pct(dbenv,
"Number of bytes free in tree duplicate pages",
(u_long)sp->bt_dup_pgfree,
DB_PCT_PG(sp->bt_dup_pgfree, sp->bt_dup_pg, sp->bt_pagesize), "ff");
__db_dl(dbenv,
"Number of tree overflow pages", (u_long)sp->bt_over_pg);
__db_dl_pct(dbenv, "Number of bytes free in tree overflow pages",
(u_long)sp->bt_over_pgfree, DB_PCT_PG(
sp->bt_over_pgfree, sp->bt_over_pg, sp->bt_pagesize), "ff");
__db_dl(dbenv, "Number of empty pages", (u_long)sp->bt_empty_pg);
__db_dl(dbenv, "Number of pages on the free list", (u_long)sp->bt_free);
__os_ufree(dbenv, sp);
return (0);
}
/*
* __bam_stat_callback --
* Statistics callback.
*
* PUBLIC: int __bam_stat_callback __P((DB *, PAGE *, void *, int *));
*/
int
__bam_stat_callback(dbp, h, cookie, putp)
DB *dbp;
PAGE *h;
void *cookie;
int *putp;
{
DB_BTREE_STAT *sp;
db_indx_t indx, *inp, top;
u_int8_t type;
sp = cookie;
*putp = 0;
top = NUM_ENT(h);
inp = P_INP(dbp, h);
switch (TYPE(h)) {
case P_IBTREE:
case P_IRECNO:
++sp->bt_int_pg;
sp->bt_int_pgfree += P_FREESPACE(dbp, h);
break;
case P_LBTREE:
if (top == 0)
++sp->bt_empty_pg;
/* Correct for on-page duplicates and deleted items. */
for (indx = 0; indx < top; indx += P_INDX) {
type = GET_BKEYDATA(dbp, h, indx + O_INDX)->type;
/* Ignore deleted items. */
if (B_DISSET(type))
continue;
/* Ignore duplicate keys. */
if (indx + P_INDX >= top ||
inp[indx] != inp[indx + P_INDX])
++sp->bt_nkeys;
/* Ignore off-page duplicates. */
if (B_TYPE(type) != B_DUPLICATE)
++sp->bt_ndata;
}
++sp->bt_leaf_pg;
sp->bt_leaf_pgfree += P_FREESPACE(dbp, h);
break;
case P_LRECNO:
if (top == 0)
++sp->bt_empty_pg;
/*
* If walking a recno tree, then each of these items is a key.
* Otherwise, we're walking an off-page duplicate set.
*/
if (dbp->type == DB_RECNO) {
/*
* Correct for deleted items in non-renumbering Recno
* databases.
*/
if (F_ISSET(dbp, DB_AM_RENUMBER)) {
sp->bt_nkeys += top;
sp->bt_ndata += top;
} else
for (indx = 0; indx < top; indx += O_INDX) {
type = GET_BKEYDATA(dbp, h, indx)->type;
if (!B_DISSET(type)) {
++sp->bt_ndata;
++sp->bt_nkeys;
}
}
++sp->bt_leaf_pg;
sp->bt_leaf_pgfree += P_FREESPACE(dbp, h);
} else {
sp->bt_ndata += top;
++sp->bt_dup_pg;
sp->bt_dup_pgfree += P_FREESPACE(dbp, h);
}
break;
case P_LDUP:
if (top == 0)
++sp->bt_empty_pg;
/* Correct for deleted items. */
for (indx = 0; indx < top; indx += O_INDX)
if (!B_DISSET(GET_BKEYDATA(dbp, h, indx)->type))
++sp->bt_ndata;
++sp->bt_dup_pg;
sp->bt_dup_pgfree += P_FREESPACE(dbp, h);
break;
case P_OVERFLOW:
++sp->bt_over_pg;
sp->bt_over_pgfree += P_OVFLSPACE(dbp, dbp->pgsize, h);
break;
default:
return (__db_pgfmt(dbp->dbenv, h->pgno));
}
return (0);
}
/*
* __bam_print_cursor --
* Display the current internal cursor.
*
* PUBLIC: void __bam_print_cursor __P((DBC *));
*/
void
__bam_print_cursor(dbc)
DBC *dbc;
{
static const FN fn[] = {
{ C_DELETED, "C_DELETED" },
{ C_RECNUM, "C_RECNUM" },
{ C_RENUMBER, "C_RENUMBER" },
{ 0, NULL }
};
DB_ENV *dbenv;
BTREE_CURSOR *cp;
dbenv = dbc->dbp->dbenv;
cp = (BTREE_CURSOR *)dbc->internal;
STAT_ULONG("Overflow size", cp->ovflsize);
if (dbc->dbtype == DB_RECNO)
STAT_ULONG("Recno", cp->recno);
STAT_ULONG("Order", cp->order);
__db_prflags(dbenv, NULL, cp->flags, fn, NULL, "\tInternal Flags");
}
#else /* !HAVE_STATISTICS */
int
__bam_stat(dbc, spp, flags)
DBC *dbc;
void *spp;
u_int32_t flags;
{
COMPQUIET(spp, NULL);
COMPQUIET(flags, 0);
return (__db_stat_not_built(dbc->dbp->dbenv));
}
int
__bam_stat_print(dbc, flags)
DBC *dbc;
u_int32_t flags;
{
COMPQUIET(flags, 0);
return (__db_stat_not_built(dbc->dbp->dbenv));
}
#endif
/*
* __bam_key_range --
* Return proportion of keys relative to given key. The numbers are
* slightly skewed due to on page duplicates.
*
* PUBLIC: int __bam_key_range __P((DBC *, DBT *, DB_KEY_RANGE *, u_int32_t));
*/
int
__bam_key_range(dbc, dbt, kp, flags)
DBC *dbc;
DBT *dbt;
DB_KEY_RANGE *kp;
u_int32_t flags;
{
BTREE_CURSOR *cp;
EPG *sp;
double factor;
int exact, ret;
COMPQUIET(flags, 0);
if ((ret = __bam_search(dbc, PGNO_INVALID,
dbt, S_STK_ONLY, 1, NULL, &exact)) != 0)
return (ret);
cp = (BTREE_CURSOR *)dbc->internal;
kp->less = kp->greater = 0.0;
factor = 1.0;
/* Correct the leaf page. */
cp->csp->entries /= 2;
cp->csp->indx /= 2;
for (sp = cp->sp; sp <= cp->csp; ++sp) {
/*
* At each level we know that pages greater than indx contain
* keys greater than what we are looking for and those less
* than indx are less than. The one pointed to by indx may
* have some less, some greater or even equal. If indx is
* equal to the number of entries, then the key is out of range
* and everything is less.
*/
if (sp->indx == 0)
kp->greater += factor * (sp->entries - 1)/sp->entries;
else if (sp->indx == sp->entries)
kp->less += factor;
else {
kp->less += factor * sp->indx / sp->entries;
kp->greater += factor *
((sp->entries - sp->indx) - 1) / sp->entries;
}
factor *= 1.0/sp->entries;
}
/*
* If there was an exact match then assign 1 n'th to the key itself.
* Otherwise that factor belongs to those greater than the key, unless
* the key was out of range.
*/
if (exact)
kp->equal = factor;
else {
if (kp->less != 1)
kp->greater += factor;
kp->equal = 0;
}
BT_STK_CLR(cp);
return (0);
}
/*
* __bam_traverse --
* Walk a Btree database.
*
* PUBLIC: int __bam_traverse __P((DBC *, db_lockmode_t,
* PUBLIC: db_pgno_t, int (*)(DB *, PAGE *, void *, int *), void *));
*/
int
__bam_traverse(dbc, mode, root_pgno, callback, cookie)
DBC *dbc;
db_lockmode_t mode;
db_pgno_t root_pgno;
int (*callback)__P((DB *, PAGE *, void *, int *));
void *cookie;
{
BINTERNAL *bi;
BKEYDATA *bk;
DB *dbp;
DB_LOCK lock;
DB_MPOOLFILE *mpf;
PAGE *h;
RINTERNAL *ri;
db_indx_t indx, *inp;
int already_put, ret, t_ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
already_put = 0;
if ((ret = __db_lget(dbc, 0, root_pgno, mode, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &root_pgno, 0, &h)) != 0) {
(void)__TLPUT(dbc, lock);
return (ret);
}
switch (TYPE(h)) {
case P_IBTREE:
for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
bi = GET_BINTERNAL(dbp, h, indx);
if (B_TYPE(bi->type) == B_OVERFLOW &&
(ret = __db_traverse_big(dbp,
((BOVERFLOW *)bi->data)->pgno,
callback, cookie)) != 0)
goto err;
if ((ret = __bam_traverse(
dbc, mode, bi->pgno, callback, cookie)) != 0)
goto err;
}
break;
case P_IRECNO:
for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
ri = GET_RINTERNAL(dbp, h, indx);
if ((ret = __bam_traverse(
dbc, mode, ri->pgno, callback, cookie)) != 0)
goto err;
}
break;
case P_LBTREE:
inp = P_INP(dbp, h);
for (indx = 0; indx < NUM_ENT(h); indx += P_INDX) {
bk = GET_BKEYDATA(dbp, h, indx);
if (B_TYPE(bk->type) == B_OVERFLOW &&
(indx + P_INDX >= NUM_ENT(h) ||
inp[indx] != inp[indx + P_INDX])) {
if ((ret = __db_traverse_big(dbp,
GET_BOVERFLOW(dbp, h, indx)->pgno,
callback, cookie)) != 0)
goto err;
}
bk = GET_BKEYDATA(dbp, h, indx + O_INDX);
if (B_TYPE(bk->type) == B_DUPLICATE &&
(ret = __bam_traverse(dbc, mode,
GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno,
callback, cookie)) != 0)
goto err;
if (B_TYPE(bk->type) == B_OVERFLOW &&
(ret = __db_traverse_big(dbp,
GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno,
callback, cookie)) != 0)
goto err;
}
break;
case P_LDUP:
case P_LRECNO:
for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
bk = GET_BKEYDATA(dbp, h, indx);
if (B_TYPE(bk->type) == B_OVERFLOW &&
(ret = __db_traverse_big(dbp,
GET_BOVERFLOW(dbp, h, indx)->pgno,
callback, cookie)) != 0)
goto err;
}
break;
default:
return (__db_pgfmt(dbp->dbenv, h->pgno));
}
ret = callback(dbp, h, cookie, &already_put);
err: if (!already_put && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret;
if ((t_ret = __TLPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}

View file

@ -1,159 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_upgrade.c,v 12.1 2005/06/16 20:20:23 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_upgrade.h"
#include "dbinc/btree.h"
/*
* __bam_30_btreemeta --
* Upgrade the metadata pages from version 6 to version 7.
*
* PUBLIC: int __bam_30_btreemeta __P((DB *, char *, u_int8_t *));
*/
int
__bam_30_btreemeta(dbp, real_name, buf)
DB *dbp;
char *real_name;
u_int8_t *buf;
{
BTMETA30 *newmeta;
BTMETA2X *oldmeta;
DB_ENV *dbenv;
int ret;
dbenv = dbp->dbenv;
newmeta = (BTMETA30 *)buf;
oldmeta = (BTMETA2X *)buf;
/*
* Move things from the end up, so we do not overwrite things.
* We are going to create a new uid, so we can move the stuff
* at the end of the structure first, overwriting the uid.
*/
newmeta->re_pad = oldmeta->re_pad;
newmeta->re_len = oldmeta->re_len;
newmeta->minkey = oldmeta->minkey;
newmeta->maxkey = oldmeta->maxkey;
newmeta->dbmeta.free = oldmeta->free;
newmeta->dbmeta.flags = oldmeta->flags;
newmeta->dbmeta.type = P_BTREEMETA;
newmeta->dbmeta.version = 7;
/* Replace the unique ID. */
if ((ret = __os_fileid(dbenv, real_name, 1, buf + 36)) != 0)
return (ret);
newmeta->root = 1;
return (0);
}
/*
* __bam_31_btreemeta --
* Upgrade the database from version 7 to version 8.
*
* PUBLIC: int __bam_31_btreemeta
* PUBLIC: __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
*/
int
__bam_31_btreemeta(dbp, real_name, flags, fhp, h, dirtyp)
DB *dbp;
char *real_name;
u_int32_t flags;
DB_FH *fhp;
PAGE *h;
int *dirtyp;
{
BTMETA31 *newmeta;
BTMETA30 *oldmeta;
COMPQUIET(dbp, NULL);
COMPQUIET(real_name, NULL);
COMPQUIET(fhp, NULL);
newmeta = (BTMETA31 *)h;
oldmeta = (BTMETA30 *)h;
/*
* Copy the effected fields down the page.
* The fields may overlap each other so we
* start at the bottom and use memmove.
*/
newmeta->root = oldmeta->root;
newmeta->re_pad = oldmeta->re_pad;
newmeta->re_len = oldmeta->re_len;
newmeta->minkey = oldmeta->minkey;
newmeta->maxkey = oldmeta->maxkey;
memmove(newmeta->dbmeta.uid,
oldmeta->dbmeta.uid, sizeof(oldmeta->dbmeta.uid));
newmeta->dbmeta.flags = oldmeta->dbmeta.flags;
newmeta->dbmeta.record_count = 0;
newmeta->dbmeta.key_count = 0;
ZERO_LSN(newmeta->dbmeta.unused3);
/* Set the version number. */
newmeta->dbmeta.version = 8;
/* Upgrade the flags. */
if (LF_ISSET(DB_DUPSORT))
F_SET(&newmeta->dbmeta, BTM_DUPSORT);
*dirtyp = 1;
return (0);
}
/*
* __bam_31_lbtree --
* Upgrade the database btree leaf pages.
*
* PUBLIC: int __bam_31_lbtree
* PUBLIC: __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *));
*/
int
__bam_31_lbtree(dbp, real_name, flags, fhp, h, dirtyp)
DB *dbp;
char *real_name;
u_int32_t flags;
DB_FH *fhp;
PAGE *h;
int *dirtyp;
{
BKEYDATA *bk;
db_pgno_t pgno;
db_indx_t indx;
int ret;
ret = 0;
for (indx = O_INDX; indx < NUM_ENT(h); indx += P_INDX) {
bk = GET_BKEYDATA(dbp, h, indx);
if (B_TYPE(bk->type) == B_DUPLICATE) {
pgno = GET_BOVERFLOW(dbp, h, indx)->pgno;
if ((ret = __db_31_offdup(dbp, real_name, fhp,
LF_ISSET(DB_DUPSORT) ? 1 : 0, &pgno)) != 0)
break;
if (pgno != GET_BOVERFLOW(dbp, h, indx)->pgno) {
*dirtyp = 1;
GET_BOVERFLOW(dbp, h, indx)->pgno = pgno;
}
}
}
return (ret);
}

File diff suppressed because it is too large Load diff

View file

@ -1,252 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: btree.src,v 12.3 2005/08/08 03:37:05 ubell Exp $
*/
PREFIX __bam
DBPRIVATE
INCLUDE #ifndef NO_SYSTEM_INCLUDES
INCLUDE #include <sys/types.h>
INCLUDE
INCLUDE #include <ctype.h>
INCLUDE #include <string.h>
INCLUDE #endif
INCLUDE
INCLUDE #include "db_int.h"
INCLUDE #include "dbinc/crypto.h"
INCLUDE #include "dbinc/db_page.h"
INCLUDE #include "dbinc/db_dispatch.h"
INCLUDE #include "dbinc/db_am.h"
INCLUDE #include "dbinc/btree.h"
INCLUDE #include "dbinc/log.h"
INCLUDE #include "dbinc/txn.h"
INCLUDE
/*
* 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).
* root_pgno: the root page number
* pg: the split page's contents before the split.
* opflags: SPL_NRECS: if splitting a tree that maintains a record count.
*/
BEGIN split 62
DB fileid int32_t ld
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
ARG root_pgno db_pgno_t lu
PGDBT pg DBT s
ARG opflags u_int32_t lu
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.
* root_pgno: the root page number.
* nrec: the tree's record count.
* rootent: last entry on the root page.
* rootlsn: the root page's original lsn.
*/
BEGIN rsplit 63
DB fileid int32_t ld
ARG pgno db_pgno_t lu
PGDBT pgdbt DBT s
ARG root_pgno db_pgno_t lu
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 55
DB fileid int32_t ld
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.
* opflags: CAD_UPDATEROOT: if root page count was adjusted.
*/
BEGIN cadjust 56
DB fileid int32_t ld
ARG pgno db_pgno_t lu
POINTER lsn DB_LSN * lu
ARG indx u_int32_t lu
ARG adjust int32_t ld
ARG opflags u_int32_t lu
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 57
DB fileid int32_t ld
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.
* indx: the index to be replaced.
* isdeleted: set if the record was previously deleted.
* orig: the original data.
* repl: the replacement data.
* prefix: the prefix of the replacement that matches the original.
* suffix: the suffix of the replacement that matches the original.
*/
BEGIN repl 58
DB fileid int32_t ld
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
/*
* BTREE-root: log the assignment of a root btree page.
*/
BEGIN root 59
DB fileid int32_t ld
ARG meta_pgno db_pgno_t lu
ARG root_pgno db_pgno_t lu
POINTER meta_lsn DB_LSN * lu
END
/*
* BTREE-curadj: undo cursor adjustments on txn abort.
* Should only be processed during DB_TXN_ABORT.
* NOTE: the first_indx field gets used to hold
* signed index adjustment in one case.
* care should be taken if its size is changed.
*/
BEGIN curadj 64
/* Fileid of db affected. */
DB fileid int32_t ld
/* Which adjustment. */
ARG mode db_ca_mode ld
/* Page entry is from. */
ARG from_pgno db_pgno_t lu
/* Page entry went to. */
ARG to_pgno db_pgno_t lu
/* Left page of root split. */
ARG left_pgno db_pgno_t lu
/* First index of dup set. Also used as adjustment. */
ARG first_indx u_int32_t lu
/* Index entry is from. */
ARG from_indx u_int32_t lu
/* Index where entry went. */
ARG to_indx u_int32_t lu
END
/*
* BTREE-rcuradj: undo cursor adjustments on txn abort in
* renumbering recno trees.
* Should only be processed during DB_TXN_ABORT.
*/
BEGIN rcuradj 65
/* Fileid of db affected. */
DB fileid int32_t ld
/* Which adjustment. */
ARG mode ca_recno_arg ld
/* Root page number. */
ARG root db_pgno_t ld
/* Recno of the adjustment. */
ARG recno db_recno_t ld
/* Order number of the adjustment. */
ARG order u_int32_t ld
END
/*
* BTREE-relink -- Handles relinking around a deleted leaf page.
*
*/
BEGIN relink 147
/* Fileid of db affected. */
DB fileid int32_t ld
/* The page being removed. */
ARG pgno db_pgno_t lu
/* The new page number, if any. */
ARG new_pgno db_pgno_t lu
/* The previous page. */
ARG prev db_pgno_t lu
/* The previous page's original lsn. */
POINTER lsn_prev DB_LSN * lu
/* The next page. */
ARG next db_pgno_t lu
/* The previous page's original lsn. */
POINTER lsn_next DB_LSN * lu
END
/*
* BTREE-merge -- Handles merging of pages during a compaction.
*/
BEGIN merge 148
DB fileid int32_t ld
ARG pgno db_pgno_t lu
POINTER lsn DB_LSN * lu
ARG npgno db_pgno_t lu
POINTER nlsn DB_LSN * lu
DBT hdr DBT s
DBT data DBT s
DBT ind DBT s
END
/*
* BTREE-pgno -- Handles replacing a page number in the record
* refernece on pgno by indx.
*/
BEGIN pgno 149
DB fileid int32_t ld
ARG pgno db_pgno_t lu
POINTER lsn DB_LSN * lu
ARG indx u_int32_t lu
ARG opgno db_pgno_t lu
ARG npgno db_pgno_t lu
END

View file

@ -1,3 +0,0 @@
Some combinations of the gzip and tar archive exploders found
on Linux systems ignore directories that don't have any files
(other than symbolic links) in them. So, here's a file.

View file

@ -1,782 +0,0 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "build_all"=.\build_all.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_hotbackup
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_upgrade
End Project Dependency
Begin Project Dependency
Project_Dep_Name db_verify
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_btrec
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_env
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_sequence
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_tpcb
End Project Dependency
Begin Project Dependency
Project_Dep_Name example_database_load
End Project Dependency
Begin Project Dependency
Project_Dep_Name example_database_read
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_access
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_btrec
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_env
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_sequence
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_tpcb
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_example_database_load
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_example_database_read
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_repquote
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_txnguide
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_txnguide_inmem
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_txnguide
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_txnguide_inmem
End Project Dependency
}}}
###############################################################################
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_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_dll"=.\db_dll.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
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_hotbackup"=.\db_hotbackup.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "db_java"=.\db_java.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_small"=.\db_small.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
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: "db_static"=.\db_static.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "db_tcl"=.\db_tcl.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "db_test"=.\db_test.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name build_all
End Project Dependency
Begin Project Dependency
Project_Dep_Name db_tcl
End Project Dependency
}}}
###############################################################################
Project: "db_upgrade"=.\db_upgrade.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "db_verify"=.\db_verify.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
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_btrec"=.\ex_btrec.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_csvcode"=.\ex_csvcode.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_csvload"=.\ex_csvload.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_csvcode
End Project Dependency
}}}
###############################################################################
Project: "ex_csvquery"=.\ex_csvquery.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_csvcode
End Project Dependency
}}}
###############################################################################
Project: "ex_env"=.\ex_env.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_repquote"=.\ex_repquote.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_sequence"=.\ex_sequence.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: "ex_txnguide"=.\ex_txnguide.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_txnguide_inmem"=.\ex_txnguide_inmem.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "example_database_load"=.\example_database_load.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "example_database_read"=.\example_database_read.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_btrec"=.\excxx_btrec.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_env"=.\excxx_env.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_example_database_load"=.\excxx_example_database_load.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_example_database_read"=.\excxx_example_database_read.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_sequence"=.\excxx_sequence.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
}}}
###############################################################################
Project: "excxx_txnguide"=.\excxx_txnguide.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_txnguide_inmem"=.\excxx_txnguide_inmem.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View file

@ -1,261 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=@project_name@ - 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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 ASCII Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 ASCII Release" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win64 Debug AMD64" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win64 Release AMD64" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win64 Debug IA64" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win64 Release IA64" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@bin_rel_dest@"
# PROP BASE Intermediate_Dir "Release/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@bin_rel_dest@"
# PROP Intermediate_Dir "Release/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /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 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcmt" /libpath:"@lib_rel_dest@"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@bin_debug_dest@"
# PROP BASE Intermediate_Dir "Debug/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@bin_debug_dest@"
# PROP Intermediate_Dir "Debug/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /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 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"libcmtd" /fixed:no /libpath:"@lib_debug_dest@"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@bin_debug_dest@_ASCII"
# PROP BASE Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@bin_debug_dest@_ASCII"
# PROP Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /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 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"libcmtd" /fixed:no
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"libcmtd" /fixed:no /libpath:"@lib_debug_dest@_ASCII"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@bin_rel_dest@_ASCII"
# PROP BASE Intermediate_Dir "Release_ASCII/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@bin_rel_dest@_ASCII"
# PROP Intermediate_Dir "Release_ASCII/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /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 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcmt"
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcmt" /libpath:"@lib_rel_dest@_ASCII"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@bin_debug_dest@_AMD64"
# PROP BASE Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@bin_debug_dest@_AMD64"
# PROP Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /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 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:AMD64 /nodefaultlib:"libcmtd" /fixed:no
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:AMD64 /nodefaultlib:"libcmtd" /fixed:no /libpath:"@lib_debug_dest@_AMD64"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@bin_rel_dest@_AMD64"
# PROP BASE Intermediate_Dir "Release_AMD64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@bin_rel_dest@_AMD64"
# PROP Intermediate_Dir "Release_AMD64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /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 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:AMD64 /nodefaultlib:"libcmt"
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:AMD64 /nodefaultlib:"libcmt" /libpath:"@lib_rel_dest@_AMD64"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@bin_debug_dest@_IA64"
# PROP BASE Intermediate_Dir "Debug_IA64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@bin_debug_dest@_IA64"
# PROP Intermediate_Dir "Debug_IA64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /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 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:IA64 /nodefaultlib:"libcmtd" /fixed:no
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:IA64 /nodefaultlib:"libcmtd" /fixed:no /libpath:"@lib_debug_dest@_IA64"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@bin_rel_dest@_IA64"
# PROP BASE Intermediate_Dir "Release_IA64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@bin_rel_dest@_IA64"
# PROP Intermediate_Dir "Release_IA64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /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 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:IA64 /nodefaultlib:"libcmt"
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:IA64 /nodefaultlib:"libcmt" /libpath:"@lib_rel_dest@_IA64"
@POST_BUILD@
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
# Name "@project_name@ - Win32 ASCII Debug"
# Name "@project_name@ - Win32 ASCII Release"
# Name "@project_name@ - Win64 Debug AMD64"
# Name "@project_name@ - Win64 Release AMD64"
# Name "@project_name@ - Win64 Debug IA64"
# Name "@project_name@ - Win64 Release IA64"
@SOURCE_FILES@
# Begin Source File
SOURCE=..\clib\getopt.c
# End Source File
# End Target
# End Project

View file

@ -1,21 +0,0 @@
JAVA_XADIR=../java/src/com/sleepycat/db/xa
JAVA_XASRCS=\
$(JAVA_XADIR)/DbXAResource.java \
$(JAVA_XADIR)/DbXid.java
Release/dbxa.jar : $(JAVA_XASRCS)
@echo compiling Berkeley DB XA classes
@javac -g -d ./Release/classes -classpath "$(CLASSPATH);./Release/classes" $(JAVA_XASRCS)
@echo creating jar file
@cd .\Release\classes
@jar cf ../dbxa.jar com\sleepycat\db\xa\*.class
@echo Java XA build finished
Debug/dbxa.jar : $(JAVA_XASRCS)
@echo compiling Berkeley DB XA classes
@javac -g -d ./Debug/classes -classpath "$(CLASSPATH);./Debug/classes" $(JAVA_XASRCS)
@echo creating jar file
@cd .\Debug\classes
@jar cf ../dbxa.jar com\sleepycat\db\xa\*.class
@echo Java XA build finished

View file

@ -1,97 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=@project_name@ - 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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - 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 ".." /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@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib /nologo /subsystem:console /machine:I386
# Begin Special Build Tool
SOURCE="$(InputPath)"
PostBuild_Desc=Copy built executable files.
PostBuild_Cmds=copy Release\*.exe .
# End Special Build Tool
!ELSEIF "$(CFG)" == "@project_name@ - 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 /MDd /W3 /GX /Z7 /Od /I "." /I ".." /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@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.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 /out:"Debug/dbkill.exe" /fixed:no
# Begin Special Build Tool
SOURCE="$(InputPath)"
PostBuild_Desc=Copy built executable files.
PostBuild_Cmds=copy Debug\*.exe .
# End Special Build Tool
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -1,131 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1999-2005
* Sleepycat Software. All rights reserved.
*
* $Id: dbkill.cpp,v 12.1 2005/06/16 20:20:43 bostic Exp $
*/
/*
* Kill -
* Simulate Unix kill on Windows/NT and Windows/9X.
* This good enough to support the Berkeley DB test suite,
* but may be missing some favorite features.
*
* Would have used MKS kill, but it didn't seem to work well
* on Win/9X. Cygnus kill works within the Gnu/Cygnus environment
* (where processes are given small pids, with presumably a translation
* table between small pids and actual process handles), but our test
* environment, via Tcl, does not use the Cygnus environment.
*
* Compile this and install it as c:/tools/kill.exe (or as indicated
* by build_win32/include.tcl ).
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
/*
* Like atol, with specified base. Would use stdlib, but
* strtol("0xFFFF1234", NULL, 16) returns 0x7FFFFFFF and
* strtol("4294712487", NULL, 16) returns 0x7FFFFFFF w/ VC++
*/
long
myatol(char *s, int base)
{
long result = 0;
char ch;
int sign = 1; /* + */
if (base == 0)
base = 10;
if (base != 10 && base != 16)
return LONG_MAX;
while ((ch = *s++) != '\0') {
if (ch == '-') {
sign = -sign;
}
else if (ch >= '0' && ch <= '9') {
result = result * base + (ch - '0');
}
else if (ch == 'x' || ch == 'X') {
/* Allow leading 0x..., and switch to base 16 */
base = 16;
}
else if (base == 16 && ch >= 'a' && ch <= 'f') {
result = result * base + (ch - 'a' + 10);
}
else if (base == 16 && ch >= 'A' && ch <= 'F') {
result = result * base + (ch - 'A' + 10);
}
else {
if (sign > 1)
return LONG_MAX;
else
return LONG_MIN;
}
}
return sign * result;
}
void
usage_exit()
{
fprintf(stderr, "Usage: kill [ -sig ] pid\n");
fprintf(stderr, " for win32, sig must be or 0, 15 (TERM)\n");
exit(EXIT_FAILURE);
}
int
main(int argc, char **argv)
{
HANDLE hProcess ;
DWORD accessflag;
long pid;
int sig = 15;
if (argc > 2) {
if (argv[1][0] != '-')
usage_exit();
if (strcmp(argv[1], "-TERM") == 0)
sig = 15;
else {
/* currently sig is more or less ignored,
* we only care if it is zero or not
*/
sig = atoi(&argv[1][1]);
if (sig < 0)
usage_exit();
}
argc--;
argv++;
}
if (argc < 2)
usage_exit();
pid = myatol(argv[1], 10);
/*printf("pid = %ld (0x%lx) (command line %s)\n", pid, pid, argv[1]);*/
if (pid == LONG_MAX || pid == LONG_MIN)
usage_exit();
if (sig == 0)
accessflag = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
else
accessflag = STANDARD_RIGHTS_REQUIRED | PROCESS_TERMINATE;
hProcess = OpenProcess(accessflag, FALSE, pid);
if (hProcess == NULL) {
fprintf(stderr, "dbkill: %s: no such process\n", argv[1]);
exit(EXIT_FAILURE);
}
if (sig == 0)
exit(EXIT_SUCCESS);
if (!TerminateProcess(hProcess, 99)) {
DWORD err = GetLastError();
fprintf(stderr,
"dbkill: cannot kill process: error %d (0x%lx)\n", err, err);
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}

View file

@ -1,97 +0,0 @@
/*
* --------------------------------------------------------------------------
* Copyright (C) 1997 Netscape Communications Corporation
* --------------------------------------------------------------------------
*
* dllmain.c
*
* $Id: dllmain.c,v 1.3 2000/10/26 21:58:48 bostic Exp $
*/
#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;
}

View file

@ -1,281 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=@project_name@ - 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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 ASCII Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 ASCII Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win64 Debug AMD64" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win64 Release AMD64" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win64 Debug IA64" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win64 Release IA64" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@"
# PROP BASE Intermediate_Dir "Release/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@"
# PROP Intermediate_Dir "Release/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /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 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"@bin_rel_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll" /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@"
# PROP BASE Intermediate_Dir "Debug/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@"
# PROP Intermediate_Dir "Debug/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /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 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /export:__db_assert /pdb:none /debug /machine:I386 /out:"@bin_debug_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_ASCII"
# PROP BASE Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_ASCII"
# PROP Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# SUBTRACT BASE CPP /Fr
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /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 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"@bin_debug_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
# ADD LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /export:__db_assert /pdb:none /debug /machine:I386 /out:"@bin_debug_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_ASCII"
# PROP BASE Intermediate_Dir "Release_ASCII/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_ASCII"
# PROP Intermediate_Dir "Release_ASCII/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /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 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"@bin_rel_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
# ADD LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"@bin_rel_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll" /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_AMD64"
# PROP BASE Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_AMD64"
# PROP Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# SUBTRACT BASE CPP /Fr
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /Wp64 /c
# 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 @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /debug /machine:AMD64 /out:"@bin_debug_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
# ADD LINK32 @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /export:__db_assert /debug /machine:AMD64 /out:"@bin_debug_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_AMD64"
# PROP BASE Intermediate_Dir "Release_AMD64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_AMD64"
# PROP Intermediate_Dir "Release_AMD64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /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 @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:AMD64 /out:"@bin_rel_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
# ADD LINK32 @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:AMD64 /out:"@bin_rel_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll" /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_IA64"
# PROP BASE Intermediate_Dir "Debug_IA64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_IA64"
# PROP Intermediate_Dir "Debug_IA64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# SUBTRACT BASE CPP /Fr
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /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 @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /debug /machine:IA64 /out:"@bin_debug_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
# ADD LINK32 @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /export:__db_assert /debug /machine:IA64 /out:"@bin_debug_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_IA64"
# PROP BASE Intermediate_Dir "Release_IA64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_IA64"
# PROP Intermediate_Dir "Release_IA64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /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 @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:IA64 /out:"@bin_rel_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
# ADD LINK32 @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:IA64 /out:"@bin_rel_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll" /libpath:"$(OUTDIR)"
@POST_BUILD@
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
# Name "@project_name@ - Win32 ASCII Debug"
# Name "@project_name@ - Win32 ASCII Release"
# Name "@project_name@ - Win64 Debug AMD64"
# Name "@project_name@ - Win64 Release AMD64"
# Name "@project_name@ - Win64 Debug IA64"
# Name "@project_name@ - Win64 Release IA64"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -1,129 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=@project_name@ - 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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - 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 ".." /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 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
# Begin Custom Build - Compiling java files using javac
ProjDir=.
InputPath=.\Release\libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll
SOURCE="$(InputPath)"
"force_compilation.txt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
echo compiling Berkeley DB classes
mkdir "$(OUTDIR)\classes"
javac -O -d "$(OUTDIR)\classes" -classpath "$(OUTDIR)/classes" ..\java\src\com\sleepycat\db\*.java ..\java\src\com\sleepycat\db\internal\*.java ..\java\src\com\sleepycat\bind\*.java ..\java\src\com\sleepycat\bind\serial\*.java ..\java\src\com\sleepycat\bind\tuple\*.java ..\java\src\com\sleepycat\collections\*.java ..\java\src\com\sleepycat\compat\*.java ..\java\src\com\sleepycat\util\*.java
echo compiling examples
mkdir "$(OUTDIR)\classes.ex"
javac -O -d "$(OUTDIR)\classes.ex" -classpath "$(OUTDIR)\classes;$(OUTDIR)\classes.ex" ..\examples_java\src\com\sleepycat\examples\db\*.java ..\examples_java\src\com\sleepycat\examples\db\GettingStarted\*.java ..\examples_java\src\com\sleepycat\examples\collections\access\*.java ..\examples_java\src\com\sleepycat\examples\collections\hello\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\basic\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\entity\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\tuple\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\sentity\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\marshal\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\factory\*.java
echo creating jar files
jar cf "$(OUTDIR)\db.jar" -C "$(OUTDIR)\classes" .
jar cf "$(OUTDIR)\dbexamples.jar" -C "$(OUTDIR)\classes.ex" .
echo Java build finished
# End Custom Build
!ELSEIF "$(CFG)" == "@project_name@ - 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 2
# 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 ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /D "_WINDLL" /D "_AFXDLL" /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" /d "_AFXDLL"
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 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
# Begin Custom Build - Compiling java files using javac
ProjDir=.
InputPath=.\Debug\libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll
SOURCE="$(InputPath)"
"force_compilation.txt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
echo compiling Berkeley DB classes
mkdir "$(OUTDIR)\classes"
javac -g -d "$(OUTDIR)\classes" -classpath "$(OUTDIR)/classes" ..\java\src\com\sleepycat\db\*.java ..\java\src\com\sleepycat\db\internal\*.java ..\java\src\com\sleepycat\bind\*.java ..\java\src\com\sleepycat\bind\serial\*.java ..\java\src\com\sleepycat\bind\tuple\*.java ..\java\src\com\sleepycat\collections\*.java ..\java\src\com\sleepycat\compat\*.java ..\java\src\com\sleepycat\util\*.java
echo compiling examples
mkdir "$(OUTDIR)\classes.ex"
javac -g -d "$(OUTDIR)\classes.ex" -classpath "$(OUTDIR)\classes;$(OUTDIR)\classes.ex" ..\examples_java\src\com\sleepycat\examples\db\*.java ..\examples_java\src\com\sleepycat\examples\db\GettingStarted\*.java ..\examples_java\src\com\sleepycat\examples\collections\access\*.java ..\examples_java\src\com\sleepycat\examples\collections\hello\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\basic\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\entity\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\tuple\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\sentity\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\marshal\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\factory\*.java
echo creating jar files
jar cf "$(OUTDIR)\db.jar" -C "$(OUTDIR)\classes" .
jar cf "$(OUTDIR)\dbexamples.jar" -C "$(OUTDIR)\classes.ex" .
echo Java build finished
# End Custom Build
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -1,7 +0,0 @@
; $Id: libdb_tcl.def,v 12.0 2004/11/17 03:48:15 bostic Exp $
DESCRIPTION 'Berkeley DB TCL interface Library'
EXPORTS
Db_tcl_Init
_NameToPtr

View file

@ -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 %MAJOR%.%MINOR% DLL\0"
VALUE "FileVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
VALUE "InternalName", "libdb%MAJOR%%MINOR%.dll\0"
VALUE "LegalCopyright", "Copyright © Sleepycat Software Inc. 1997-2005\0"
VALUE "OriginalFilename", "libdb%MAJOR%%MINOR%.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

View file

@ -1,85 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=@project_name@ - Win32 Debug Static
!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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug Static"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release Static" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win32 Debug Static" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - Win32 Release Static"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release_small"
# PROP BASE Intermediate_Dir "Release_small"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_small"
# PROP Intermediate_Dir "Release_small"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /D "HAVE_SMALLBUILD" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /D "HAVE_SMALLBUILD" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"Release_small/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
# ADD LIB32 /nologo /out:"Release_small/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug Static"
# PROP BASE Use_MFC 1
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug_small"
# PROP BASE Intermediate_Dir "Debug_small"
# PROP BASE Target_Dir ""
# PROP Use_MFC 1
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_small"
# PROP Intermediate_Dir "Debug_small"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "HAVE_SMALLBUILD" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "HAVE_SMALLBUILD" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"Debug_small/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
# ADD LIB32 /nologo /out:"Debug_small/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release Static"
# Name "@project_name@ - Win32 Debug Static"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -1,4 +0,0 @@
# Begin Source File
SOURCE=@srcdir@\@srcfile@
# End Source File

View file

@ -1,235 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=@project_name@ - 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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win32 ASCII Release" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win32 ASCII Debug" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win64 Debug AMD64" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win64 Release AMD64" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win64 Debug IA64" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win64 Release IA64" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@"
# PROP BASE Intermediate_Dir "Release/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@"
# PROP Intermediate_Dir "Release/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_rel_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
# ADD LIB32 /nologo /out:"@lib_rel_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@"
# PROP BASE Intermediate_Dir "Debug/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@"
# PROP Intermediate_Dir "Debug/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_debug_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
# ADD LIB32 /nologo /out:"@lib_debug_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_ASCII"
# PROP BASE Intermediate_Dir "Release_ASCII/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_ASCII"
# PROP Intermediate_Dir "Release_ASCII/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_rel_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
# ADD LIB32 /nologo /out:"@lib_rel_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_ASCII"
# PROP BASE Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_ASCII"
# PROP Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_debug_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
# ADD LIB32 /nologo /out:"@lib_debug_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_AMD64"
# PROP BASE Intermediate_Dir "Debug/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_AMD64"
# PROP Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /Wp64 /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_debug_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
# ADD LIB32 /nologo /out:"@lib_debug_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_AMD64"
# PROP BASE Intermediate_Dir "Release_AMD64/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_AMD64"
# PROP Intermediate_Dir "Release_AMD64/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_rel_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
# ADD LIB32 /nologo /out:"@lib_rel_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_IA64"
# PROP BASE Intermediate_Dir "Debug_IA64/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_IA64"
# PROP Intermediate_Dir "Debug_IA64/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_debug_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
# ADD LIB32 /nologo /out:"@lib_debug_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_IA64"
# PROP BASE Intermediate_Dir "Release_IA64/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_IA64"
# PROP Intermediate_Dir "Release_IA64/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_rel_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
# ADD LIB32 /nologo /out:"@lib_rel_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
# Name "@project_name@ - Win32 ASCII Release"
# Name "@project_name@ - Win32 ASCII Debug"
# Name "@project_name@ - Win64 Debug AMD64"
# Name "@project_name@ - Win64 Release AMD64"
# Name "@project_name@ - Win64 Debug IA64"
# Name "@project_name@ - Win64 Release IA64"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -1,93 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=@project_name@ - 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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - 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 ".." /D "DB_TCL_SUPPORT" /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 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib tcl84.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb_tcl@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
!ELSEIF "$(CFG)" == "@project_name@ - 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 2
# 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 ".." /D "DB_TCL_SUPPORT" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /D "_WINDLL" /D "_AFXDLL" /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" /d "_AFXDLL"
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 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib tcl84g.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb_tcl@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -1,145 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=@project_name@ - Win32 Debug Static
!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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug Static"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Release Static" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Debug Static" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - 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 ".." /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 /nologo /subsystem:console /machine:IA64
# ADD LINK32 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib /nologo /subsystem:console /machine:IA64 /nodefaultlib:"libcmt"
!ELSEIF "$(CFG)" == "@project_name@ - 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 /MDd /W3 /GX /Z7 /Od /I "." /I ".." /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 /nologo /subsystem:console /debug /machine:IA64 /pdbtype:sept
# ADD LINK32 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib /nologo /subsystem:console /debug /machine:IA64 /nodefaultlib:"libcmtd" /fixed:no
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Release Static"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_static"
# PROP Intermediate_Dir "Release_static"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /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 Release_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib /nologo /subsystem:console /machine:IA64
# ADD LINK32 Release_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib /nologo /subsystem:console /machine:IA64
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug Static"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_static"
# PROP Intermediate_Dir "Debug_static"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /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 Debug_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:IA64 /fixed:no
# ADD LINK32 Debug_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:IA64 /fixed:no
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
# Name "@project_name@ - Win32 Release Static"
# Name "@project_name@ - Win32 Debug Static"
@SOURCE_FILES@
# Begin Source File
SOURCE=..\clib\getopt.c
# End Source File
# End Target
# End Project

View file

@ -1,97 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=@project_name@ - 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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - 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 ".." /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 /nologo /subsystem:console /machine:IA64
# ADD LINK32 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib /nologo /subsystem:console /machine:IA64
# Begin Special Build Tool
SOURCE="$(InputPath)"
PostBuild_Desc=Copy built executable files.
PostBuild_Cmds=copy Release\*.exe .
# End Special Build Tool
!ELSEIF "$(CFG)" == "@project_name@ - 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 /MDd /W3 /GX /Z7 /Od /I "." /I ".." /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 /nologo /subsystem:console /debug /machine:IA64 /pdbtype:sept
# ADD LINK32 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:IA64 /out:"Debug/dbkill.exe" /fixed:no
# Begin Special Build Tool
SOURCE="$(InputPath)"
PostBuild_Desc=Copy built executable files.
PostBuild_Cmds=copy Debug\*.exe .
# End Special Build Tool
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -1,93 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=@project_name@ - 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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - 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 ".." /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /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 /nologo /subsystem:windows /dll /machine:IA64
# ADD LINK32 /nologo /base:"0x13000000" /subsystem:windows /dll /machine:IA64 /out:"Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
!ELSEIF "$(CFG)" == "@project_name@ - 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 2
# 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 ".." /D "DB_CREATE_DLL" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /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 /nologo /subsystem:windows /dll /debug /machine:IA64 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /base:"0x13000000" /subsystem:windows /dll /debug /machine:IA64 /out:"Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -1,145 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=@project_name@ - Win32 Debug Static
!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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug Static"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Release Static" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Debug Static" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - 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 ".." /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 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /machine:IA64
# ADD LINK32 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib ws2_32.lib /nologo /subsystem:console /machine:IA64 /nodefaultlib:"libcmt"
!ELSEIF "$(CFG)" == "@project_name@ - 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 /MDd /W3 /GX /Z7 /Od /I "." /I ".." /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 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:IA64 /pdbtype:sept
# ADD LINK32 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib ws2_32.lib /nologo /subsystem:console /debug /machine:IA64 /nodefaultlib:"libcmtd" /fixed:no
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Release Static"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_static"
# PROP Intermediate_Dir "Release_static"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /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 Release_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib ws2_32.lib /nologo /subsystem:console /machine:IA64
# ADD LINK32 Release_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib ws2_32.lib /nologo /subsystem:console /machine:IA64
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug Static"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_static"
# PROP Intermediate_Dir "Debug_static"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /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 Debug_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:IA64 /fixed:no
# ADD LINK32 Debug_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:IA64 /fixed:no
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
# Name "@project_name@ - Win32 Release Static"
# Name "@project_name@ - Win32 Debug Static"
@SOURCE_FILES@
# Begin Source File
SOURCE=..\clib\getopt.c
# End Source File
# End Target
# End Project

View file

@ -1,129 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=@project_name@ - 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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - 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 ".." /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 /nologo /subsystem:windows /dll /machine:IA64
# ADD LINK32 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:IA64 /out:"Release/libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
# Begin Custom Build - Compiling java files using javac
ProjDir=.
InputPath=.\Release\libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll
SOURCE="$(InputPath)"
"force_compilation.txt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
echo compiling Berkeley DB classes
mkdir "$(OUTDIR)\classes"
javac -O -d "$(OUTDIR)\classes" -classpath "$(OUTDIR)/classes" ..\java\src\com\sleepycat\db\*.java ..\java\src\com\sleepycat\db\internal\*.java ..\java\src\com\sleepycat\bind\*.java ..\java\src\com\sleepycat\bind\serial\*.java ..\java\src\com\sleepycat\bind\tuple\*.java ..\java\src\com\sleepycat\collections\*.java ..\java\src\com\sleepycat\compat\*.java ..\java\src\com\sleepycat\util\*.java
echo compiling examples
mkdir "$(OUTDIR)\classes.ex"
javac -O -d "$(OUTDIR)\classes.ex" -classpath "$(OUTDIR)\classes;$(OUTDIR)\classes.ex" ..\examples_java\src\com\sleepycat\examples\db\*.java ..\examples_java\src\com\sleepycat\examples\db\GettingStarted\*.java ..\examples_java\src\com\sleepycat\examples\collections\access\*.java ..\examples_java\src\com\sleepycat\examples\collections\hello\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\basic\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\entity\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\tuple\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\sentity\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\marshal\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\factory\*.java
echo creating jar files
jar cf "$(OUTDIR)\db.jar" -C "$(OUTDIR)\classes" .
jar cf "$(OUTDIR)\dbexamples.jar" -C "$(OUTDIR)\classes.ex" .
echo Java build finished
# End Custom Build
!ELSEIF "$(CFG)" == "@project_name@ - 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 2
# 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 ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /D "_WINDLL" /D "_AFXDLL" /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" /d "_AFXDLL"
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 /nologo /subsystem:windows /dll /debug /machine:IA64 /pdbtype:sept
# ADD LINK32 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib /nologo /base:"0x13000000" /subsystem:windows /dll /debug /machine:IA64 /out:"Debug/libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
# Begin Custom Build - Compiling java files using javac
ProjDir=.
InputPath=.\Debug\libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll
SOURCE="$(InputPath)"
"force_compilation.txt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
echo compiling Berkeley DB classes
mkdir "$(OUTDIR)\classes"
javac -g -d "$(OUTDIR)\classes" -classpath "$(OUTDIR)/classes" ..\java\src\com\sleepycat\db\*.java ..\java\src\com\sleepycat\db\internal\*.java ..\java\src\com\sleepycat\bind\*.java ..\java\src\com\sleepycat\bind\serial\*.java ..\java\src\com\sleepycat\bind\tuple\*.java ..\java\src\com\sleepycat\collections\*.java ..\java\src\com\sleepycat\compat\*.java ..\java\src\com\sleepycat\util\*.java
echo compiling examples
mkdir "$(OUTDIR)\classes.ex"
javac -g -d "$(OUTDIR)\classes.ex" -classpath "$(OUTDIR)\classes;$(OUTDIR)\classes.ex" ..\examples_java\src\com\sleepycat\examples\db\*.java ..\examples_java\src\com\sleepycat\examples\db\GettingStarted\*.java ..\examples_java\src\com\sleepycat\examples\collections\access\*.java ..\examples_java\src\com\sleepycat\examples\collections\hello\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\basic\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\entity\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\tuple\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\sentity\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\marshal\*.java ..\examples_java\src\com\sleepycat\examples\collections\ship\factory\*.java
echo creating jar files
jar cf "$(OUTDIR)\db.jar" -C "$(OUTDIR)\classes" .
jar cf "$(OUTDIR)\dbexamples.jar" -C "$(OUTDIR)\classes.ex" .
echo Java build finished
# End Custom Build
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -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 3.0 DLL\0"
VALUE "FileVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
VALUE "InternalName", "libdb.dll\0"
VALUE "LegalCopyright", "Copyright © Sleepycat Software Inc. 1997-2004\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

View file

@ -1,85 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=@project_name@ - Win32 Debug Static
!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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug Static"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release Static" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win32 Debug Static" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - Win32 Release Static"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release_small"
# PROP BASE Intermediate_Dir "Release_small"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_small"
# PROP Intermediate_Dir "Release_small"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /D "HAVE_SMALLBUILD" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /D "HAVE_SMALLBUILD" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"Release_small/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
# ADD LIB32 /nologo /out:"Release_small/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug Static"
# PROP BASE Use_MFC 1
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug_small"
# PROP BASE Intermediate_Dir "Debug_small"
# PROP BASE Target_Dir ""
# PROP Use_MFC 1
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_small"
# PROP Intermediate_Dir "Debug_small"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "HAVE_SMALLBUILD" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "HAVE_SMALLBUILD" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"Debug_small/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
# ADD LIB32 /nologo /out:"Debug_small/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release Static"
# Name "@project_name@ - Win32 Debug Static"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -1,4 +0,0 @@
# Begin Source File
SOURCE=@srcdir@\@srcfile@
# End Source File

View file

@ -1,85 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=@project_name@ - Win32 Debug Static
!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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug Static"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release Static" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win32 Debug Static" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - Win32 Release Static"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release_static"
# PROP BASE Intermediate_Dir "Release_static"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_static"
# PROP Intermediate_Dir "Release_static"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
# ADD LIB32 /nologo /out:"Release_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug Static"
# PROP BASE Use_MFC 1
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug_static"
# PROP BASE Intermediate_Dir "Debug_static"
# PROP BASE Target_Dir ""
# PROP Use_MFC 1
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_static"
# PROP Intermediate_Dir "Debug_static"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
# ADD LIB32 /nologo /out:"Debug_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release Static"
# Name "@project_name@ - Win32 Debug Static"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -1,93 +0,0 @@
# Microsoft Developer Studio Project File - Name="@project_name@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=@project_name@ - 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 "@project_name@.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 "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - 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 ".." /D "DB_TCL_SUPPORT" /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 /nologo /subsystem:windows /dll /machine:IA64
# ADD LINK32 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib tcl84.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:IA64 /out:"Release/libdb_tcl@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
!ELSEIF "$(CFG)" == "@project_name@ - 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 2
# 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 ".." /D "DB_TCL_SUPPORT" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /D "_WINDLL" /D "_AFXDLL" /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" /d "_AFXDLL"
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 /nologo /subsystem:windows /dll /debug /machine:IA64 /pdbtype:sept
# ADD LINK32 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib tcl84g.lib /nologo /base:"0x13000000" /subsystem:windows /dll /debug /machine:IA64 /out:"Debug/libdb_tcl@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -1,270 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* 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. 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.
*
* $Id: getcwd.c,v 12.1 2005/06/16 20:20:48 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#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 ret, 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) {
__os_set_errno(EINVAL);
return (NULL);
}
if (size == 1) {
__os_set_errno(ERANGE);
return (NULL);
}
ept = pt + size;
} else {
if ((ret =
__os_malloc(NULL, ptsize = 1024 - 4, &pt)) != 0) {
__os_set_errno(ret);
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 ((ret = __os_malloc(NULL, upsize = 1024 - 4, &up)) != 0)
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;
__os_set_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);
__os_free(NULL, 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 (__os_realloc(NULL, upsize *= 2, &up) != 0)
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 == 0)
save_errno = __os_get_errno();
__os_set_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) {
__os_set_errno(ERANGE);
goto err;
}
off = bpt - pt;
len = ept - bpt;
if (__os_realloc(NULL, ptsize *= 2, &pt) != 0)
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 (__os_get_errno_ret_zero() == 0)
__os_set_errno(save_errno == 0 ? ENOENT : save_errno);
/* FALLTHROUGH */
err:
if (ptsize)
__os_free(NULL, pt);
__os_free(NULL, up);
return (NULL);
}

View file

@ -1,152 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* 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. 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.
*
* $Id: getopt.c,v 12.1 2005/06/16 20:20:48 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "db_int.h"
int __db_getopt_reset; /* global reset for VxWorks. */
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 */
/*
* VxWorks needs to be able to repeatedly call getopt from multiple
* programs within its global name space.
*/
if (__db_getopt_reset) {
__db_getopt_reset = 0;
opterr = optind = 1;
optopt = optreset = 0;
optarg = NULL;
progname = NULL;
place = EMSG;
}
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 */
}

View file

@ -1,65 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* 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. 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.
*
* $Id: memcmp.c,v 12.1 2005/06/16 20:20:48 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#endif
/*
* 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);
}

View file

@ -1,153 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* 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. 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.
*
* $Id: memmove.c,v 12.1 2005/06/16 20:20:49 bostic Exp $
*/
#include "db_config.h"
#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
}

View file

@ -1,30 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: raise.c,v 12.2 2005/06/16 20:20:50 bostic Exp $
*/
#include "db_config.h"
#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));
}

View file

@ -1,159 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: snprintf.c,v 12.1 2005/06/16 20:20:50 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /* Declare STDERR_FILENO. */
#endif
#include "db_int.h"
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
static void sprintf_overflow __P((void));
static int sprintf_retcharpnt __P((void));
#endif
/*
* snprintf --
* Bounded version of sprintf.
*
* PUBLIC: #ifndef HAVE_SNPRINTF
* PUBLIC: int snprintf __P((char *, size_t, const char *, ...));
* PUBLIC: #endif
*/
#ifndef HAVE_SNPRINTF
int
#ifdef STDC_HEADERS
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
{
static int ret_charpnt = -1;
va_list ap;
size_t len;
if (ret_charpnt == -1)
ret_charpnt = sprintf_retcharpnt();
#ifdef STDC_HEADERS
va_start(ap, fmt);
#else
va_start(ap);
#endif
len = (size_t)vsprintf(str, fmt, ap);
if (ret_charpnt)
len = strlen(str);
va_end(ap);
if (len >= n) {
sprintf_overflow();
/* NOTREACHED */
}
return ((int)len);
}
#endif
/*
* vsnprintf --
* Bounded version of vsprintf.
*
* PUBLIC: #ifndef HAVE_VSNPRINTF
* PUBLIC: int vsnprintf __P((char *, size_t, const char *, va_list));
* PUBLIC: #endif
*/
#ifndef HAVE_VSNPRINTF
int
vsnprintf(str, n, fmt, ap)
char *str;
size_t n;
const char *fmt;
va_list ap;
{
static int ret_charpnt = -1;
size_t len;
if (ret_charpnt == -1)
ret_charpnt = sprintf_retcharpnt();
len = (size_t)vsprintf(str, fmt, ap);
if (ret_charpnt)
len = strlen(str);
if (len >= n) {
sprintf_overflow();
/* NOTREACHED */
}
return ((int)len);
}
#endif
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
static void
sprintf_overflow()
{
/*
* !!!
* We're potentially manipulating strings handed us by the application,
* and on systems without a real snprintf() the sprintf() calls could
* have overflowed the buffer. We can't do anything about it now, but
* we don't want to return control to the application, we might have
* overwritten the stack with a Trojan horse. We're not trying to do
* anything recoverable here because systems without snprintf support
* are pretty rare anymore.
*/
#define OVERFLOW_ERROR "internal buffer overflow, process ended\n"
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
(void)write(STDERR_FILENO, OVERFLOW_ERROR, sizeof(OVERFLOW_ERROR) - 1);
/* Be polite. */
exit(1);
/* But firm. */
abort();
/* NOTREACHED */
}
static int
sprintf_retcharpnt()
{
int ret_charpnt;
char buf[10];
/*
* Some old versions of sprintf return a pointer to the first argument
* instead of a character count. Assume the return value of snprintf,
* vsprintf, etc. will be the same as sprintf, and check the easy one.
*
* We do this test at run-time because it's not a test we can do in a
* cross-compilation environment.
*/
ret_charpnt =
(int)sprintf(buf, "123") != 3 ||
(int)sprintf(buf, "123456789") != 9 ||
(int)sprintf(buf, "1234") != 4;
return (ret_charpnt);
}
#endif

View file

@ -1,130 +0,0 @@
/*
* Copyright (c) 1987, 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.
*
* $Id: strcasecmp.c,v 12.0 2004/11/17 03:43:15 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <string.h>
#endif
/*
* This array is designed for mapping upper and lower case letter
* together for a case independent comparison. The mappings are
* based upon ascii character sequences.
*/
static const unsigned char charmap[] = {
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
'\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
'\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
'\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
'\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377'
};
/*
* strcasecmp --
* Do strcmp(3) in a case-insensitive manner.
*
* PUBLIC: #ifndef HAVE_STRCASECMP
* PUBLIC: int strcasecmp __P((const char *, const char *));
* PUBLIC: #endif
*/
int
strcasecmp(s1, s2)
const char *s1, *s2;
{
register const unsigned char *cm = charmap,
*us1 = (const unsigned char *)s1,
*us2 = (const unsigned char *)s2;
while (cm[*us1] == cm[*us2++])
if (*us1++ == '\0')
return (0);
return (cm[*us1] - cm[*--us2]);
}
/*
* strncasecmp --
* Do strncmp(3) in a case-insensitive manner.
*
* PUBLIC: #ifndef HAVE_STRCASECMP
* PUBLIC: int strncasecmp __P((const char *, const char *, size_t));
* PUBLIC: #endif
*/
int
strncasecmp(s1, s2, n)
const char *s1, *s2;
register size_t n;
{
if (n != 0) {
register const unsigned char *cm = charmap,
*us1 = (const unsigned char *)s1,
*us2 = (const unsigned char *)s2;
do {
if (cm[*us1] != cm[*us2++])
return (cm[*us1] - cm[*--us2]);
if (*us1++ == '\0')
break;
} while (--n != 0);
}
return (0);
}

View file

@ -1,65 +0,0 @@
/*
* 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.
*
* $Id: strdup.c,v 12.0 2004/11/17 03:43:15 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#endif
/*
* strdup --
*
* PUBLIC: #ifndef HAVE_STRDUP
* PUBLIC: char *strdup __P((const char *));
* PUBLIC: #endif
*/
char *
strdup(str)
const char *str;
{
size_t len;
char *copy;
len = strlen(str) + 1;
if (!(copy = malloc((u_int)len)))
return (NULL);
memcpy(copy, str, len);
return (copy);
}

View file

@ -1,75 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2005
* 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. 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.
*
* $Id: strerror.c,v 12.1 2005/06/16 20:20:51 bostic Exp $
*/
#include "db_config.h"
/*
* 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);
}

View file

@ -1,144 +0,0 @@
/*-
* 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.
*
* $Id: strtol.c,v 12.0 2004/11/17 03:43:15 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#endif
/*
* Convert a string to a long integer.
*
* Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long
strtol(nptr, endptr, base)
const char * nptr;
char ** endptr;
int base;
{
const char *s;
unsigned long acc;
char c;
unsigned long cutoff;
int neg, any, cutlim;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
s = nptr;
do {
c = *s++;
} while (isspace((unsigned char)c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
acc = any = 0;
if (base < 2 || base > 36)
goto noconv;
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for longs is
* [-2147483648..2147483647] and the input base is 10,
* cutoff will be set to 214748364 and cutlim to either
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
* a value > 214748364, or equal but the next digit is > 7 (or 8),
* the number is too big, and we will return a range error.
*
* Set 'any' if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX
: LONG_MAX;
cutlim = cutoff % base;
cutoff /= base;
for ( ; ; c = *s++) {
if (c >= '0' && c <= '9')
c -= '0';
else if (c >= 'A' && c <= 'Z')
c -= 'A' - 10;
else if (c >= 'a' && c <= 'z')
c -= 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
errno = ERANGE;
} else if (!any) {
noconv:
errno = EINVAL;
} else if (neg)
acc = -acc;
if (endptr != NULL)
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}

View file

@ -1,123 +0,0 @@
/*
* 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.
*
* $Id: strtoul.c,v 12.0 2004/11/17 03:43:15 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#endif
/*
* Convert a string to an unsigned long integer.
*
* Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
unsigned long
strtoul(nptr, endptr, base)
const char * nptr;
char ** endptr;
int base;
{
const char *s;
unsigned long acc;
char c;
unsigned long cutoff;
int neg, any, cutlim;
/*
* See strtol for comments as to the logic used.
*/
s = nptr;
do {
c = *s++;
} while (isspace((unsigned char)c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
acc = any = 0;
if (base < 2 || base > 36)
goto noconv;
cutoff = ULONG_MAX / base;
cutlim = ULONG_MAX % base;
for ( ; ; c = *s++) {
if (c >= '0' && c <= '9')
c -= '0';
else if (c >= 'A' && c <= 'Z')
c -= 'A' - 10;
else if (c >= 'a' && c <= 'z')
c -= 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = ULONG_MAX;
errno = ERANGE;
} else if (!any) {
noconv:
errno = EINVAL;
} else if (neg)
acc = -acc;
if (endptr != NULL)
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}

View file

@ -1,47 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
static const char revid[] = "$Id: vsnprintf.c,v 11.7 2002/01/11 15:51:29 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdio.h>
#endif
#include "db_int.h"
/*
* vsnprintf --
* Bounded version of vsprintf.
*
* PUBLIC: #ifndef HAVE_VSNPRINTF
* PUBLIC: int vsnprintf __P((char *, size_t, const char *, va_list));
* PUBLIC: #endif
*/
#ifndef HAVE_VSNPRINTF
int
vsnprintf(str, n, fmt, ap)
char *str;
size_t n;
const char *fmt;
va_list ap;
{
COMPQUIET(n, 0);
#ifdef SPRINTF_RET_CHARPNT
(void)vsprintf(str, fmt, ap);
return (strlen(str));
#else
return (vsprintf(str, fmt, ap));
#endif
}
#endif

View file

@ -1,45 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: crypto_stub.c,v 12.2 2005/07/20 16:50:55 bostic Exp $
*/
#include "db_config.h"
#include "db_int.h"
/*
* __crypto_region_init --
* Initialize crypto.
*
*
* !!!
* We don't put this stub file in the crypto/ directory of the distribution
* because that entire directory is removed for non-crypto distributions.
*
* PUBLIC: int __crypto_region_init __P((DB_ENV *));
*/
int
__crypto_region_init(dbenv)
DB_ENV *dbenv;
{
REGENV *renv;
REGINFO *infop;
int ret;
infop = dbenv->reginfo;
renv = infop->primary;
MUTEX_LOCK(dbenv, renv->mtx_regenv);
ret = !(renv->cipher_off == INVALID_ROFF);
MUTEX_UNLOCK(dbenv, renv->mtx_regenv);
if (ret == 0)
return (0);
__db_err(dbenv,
"Encrypted environment: library build did not include cryptography support");
return (DB_OPNOTSUP);
}

View file

@ -1,72 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_byteorder.c,v 12.1 2005/06/16 20:20:52 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#endif
#include "db_int.h"
/*
* __db_isbigendian --
* Return 1 if big-endian (Motorola and Sparc), not little-endian
* (Intel and Vax). We do this work at run-time, rather than at
* configuration time so cross-compilation and general embedded
* system support is simpler.
*
* PUBLIC: int __db_isbigendian __P((void));
*/
int
__db_isbigendian()
{
union { /* From Harbison & Steele. */
long l;
char c[sizeof(long)];
} u;
u.l = 1;
return (u.c[sizeof(long) - 1] == 1);
}
/*
* __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;
{
int is_bigendian;
is_bigendian = __db_isbigendian();
switch (lorder) {
case 0:
break;
case 1234:
if (is_bigendian)
return (DB_SWAPBYTES);
break;
case 4321:
if (!is_bigendian)
return (DB_SWAPBYTES);
break;
default:
__db_err(dbenv,
"unsupported byte order, only big and little-endian supported");
return (EINVAL);
}
return (0);
}

View file

@ -1,30 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_clock.c,v 1.2 2005/08/08 14:39:52 bostic Exp $
*/
#include "db_config.h"
#include "db_int.h"
/*
* __db_difftime --
*
* Compute the difference in seconds and microseconds of two timers.
*
* PUBLIC: void __db_difftime __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t,
* PUBLIC: u_int32_t *, u_int32_t *));
*/
void
__db_difftime(ssec, esec, susec, eusec, secp, usecp)
u_int32_t ssec, esec, susec, eusec, *secp, *usecp;
{
if ((*secp = esec - ssec) != 0 && eusec < susec) {
(*secp)--;
eusec += 1000000;
}
*usecp = eusec - susec;
}

View file

@ -1,840 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_err.c,v 12.19 2005/10/19 19:06:29 sue Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_am.h"
#include "dbinc/db_shash.h"
#include "dbinc/lock.h"
#include "dbinc/log.h"
#include "dbinc/mp.h"
#include "dbinc/txn.h"
static void __db_msgcall __P((const DB_ENV *, const char *, va_list));
static void __db_msgfile __P((const DB_ENV *, const char *, va_list));
/*
* __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;
{
return (LF_ISSET(~ok_flags) ? __db_ferr(dbenv, name, 0) : 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;
{
return (LF_ISSET(flag1) &&
LF_ISSET(flag2) ? __db_ferr(dbenv, name, 1) : 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_fnl --
* Common flag-needs-locking message.
*
* PUBLIC: int __db_fnl __P((const DB_ENV *, const char *));
*/
int
__db_fnl(dbenv, name)
const DB_ENV *dbenv;
const char *name;
{
__db_err(dbenv,
"%s: DB_READ_COMMITTED, DB_READ_UNCOMMITTED and DB_RMW require locking",
name);
return (EINVAL);
}
/*
* __db_pgerr --
* Error when unable to retrieve a specified page.
*
* PUBLIC: int __db_pgerr __P((DB *, db_pgno_t, int));
*/
int
__db_pgerr(dbp, pgno, errval)
DB *dbp;
db_pgno_t pgno;
int errval;
{
/*
* 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->dbenv, errval));
}
/*
* __db_pgfmt --
* Error when a page has the wrong format.
*
* PUBLIC: int __db_pgfmt __P((DB_ENV *, db_pgno_t));
*/
int
__db_pgfmt(dbenv, pgno)
DB_ENV *dbenv;
db_pgno_t pgno;
{
__db_err(dbenv, "page %lu: illegal page type or format", (u_long)pgno);
return (__db_panic(dbenv, EINVAL));
}
#ifdef DIAGNOSTIC
/*
* __db_assert --
* Error when an assertion fails. Only checked if #DIAGNOSTIC defined.
*
* PUBLIC: #ifdef DIAGNOSTIC
* PUBLIC: void __db_assert __P((const char *, const char *, int));
* PUBLIC: #endif
*/
void
__db_assert(failedexpr, file, line)
const char *failedexpr, *file;
int line;
{
(void)fprintf(stderr,
"__db_assert: \"%s\" failed: file \"%s\", line %d\n",
failedexpr, file, line);
(void)fflush(stderr);
/* We want a stack trace of how this could possibly happen. */
abort();
/* NOTREACHED */
}
#endif
/*
* __db_panic_msg --
* Just report that someone else paniced.
*
* PUBLIC: int __db_panic_msg __P((DB_ENV *));
*/
int
__db_panic_msg(dbenv)
DB_ENV *dbenv;
{
__db_err(dbenv, "PANIC: fatal region error detected; run recovery");
if (dbenv->db_paniccall != NULL)
dbenv->db_paniccall(dbenv, DB_RUNRECOVERY);
return (DB_RUNRECOVERY);
}
/*
* __db_panic --
* Lock out the tree due to unrecoverable error.
*
* PUBLIC: int __db_panic __P((DB_ENV *, int));
*/
int
__db_panic(dbenv, errval)
DB_ENV *dbenv;
int errval;
{
if (dbenv != NULL) {
__db_panic_set(dbenv, 1);
__db_err(dbenv, "PANIC: %s", db_strerror(errval));
if (dbenv->db_paniccall != NULL)
dbenv->db_paniccall(dbenv, errval);
}
#if defined(DIAGNOSTIC) && !defined(CONFIG_TEST)
/*
* We want a stack trace of how this could possibly happen.
*
* Don't drop core if it's the test suite -- it's reasonable for the
* test suite to check to make sure that DB_RUNRECOVERY is returned
* under certain conditions.
*/
abort();
#endif
/*
* Chaos reigns within.
* Reflect, repent, and reboot.
* Order shall return.
*/
return (DB_RUNRECOVERY);
}
/*
* __db_panic_set --
* Set/clear unrecoverable error.
*
* PUBLIC: void __db_panic_set __P((DB_ENV *, int));
*/
void
__db_panic_set(dbenv, on)
DB_ENV *dbenv;
int on;
{
if (dbenv != NULL && dbenv->reginfo != NULL)
((REGENV *)
((REGINFO *)dbenv->reginfo)->primary)->panic = on ? 1 : 0;
}
/*
* db_strerror --
* ANSI C strerror(3) for DB.
*
* EXTERN: char *db_strerror __P((int));
*/
char *
db_strerror(error)
int error;
{
char *p;
if (error == 0)
return ("Successful return: 0");
if (error > 0) {
if ((p = strerror(error)) != NULL)
return (p);
goto unknown_err;
}
/*
* !!!
* The Tcl API requires that some of these return strings be compared
* against strings stored in application scripts. So, any of these
* errors that do not invariably result in a Tcl exception may not be
* altered.
*/
switch (error) {
case DB_BUFFER_SMALL:
return
("DB_BUFFER_SMALL: User memory too small for return value");
case DB_DONOTINDEX:
return ("DB_DONOTINDEX: Secondary index callback returns null");
case DB_KEYEMPTY:
return ("DB_KEYEMPTY: Non-existent key/data pair");
case DB_KEYEXIST:
return ("DB_KEYEXIST: Key/data pair already exists");
case DB_LOCK_DEADLOCK:
return
("DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock");
case DB_LOCK_NOTGRANTED:
return ("DB_LOCK_NOTGRANTED: Lock not granted");
case DB_LOG_BUFFER_FULL:
return ("DB_LOG_BUFFER_FULL: In-memory log buffer is full");
case DB_NOSERVER:
return ("DB_NOSERVER: Fatal error, no RPC server");
case DB_NOSERVER_HOME:
return ("DB_NOSERVER_HOME: Home unrecognized at server");
case DB_NOSERVER_ID:
return ("DB_NOSERVER_ID: Identifier unrecognized at server");
case DB_NOTFOUND:
return ("DB_NOTFOUND: No matching key/data pair found");
case DB_OLD_VERSION:
return ("DB_OLDVERSION: Database requires a version upgrade");
case DB_PAGE_NOTFOUND:
return ("DB_PAGE_NOTFOUND: Requested page not found");
case DB_REP_DUPMASTER:
return ("DB_REP_DUPMASTER: A second master site appeared");
case DB_REP_HANDLE_DEAD:
return ("DB_REP_HANDLE_DEAD: Handle is no longer valid");
case DB_REP_HOLDELECTION:
return ("DB_REP_HOLDELECTION: Need to hold an election");
case DB_REP_IGNORE:
return ("DB_REP_IGNORE: Replication record ignored");
case DB_REP_ISPERM:
return ("DB_REP_ISPERM: Permanent record written");
case DB_REP_JOIN_FAILURE:
return
("DB_REP_JOIN_FAILURE: Unable to join replication group");
case DB_REP_LOCKOUT:
return
("DB_REP_LOCKOUT: Waiting for replication recovery to complete");
case DB_REP_NEWMASTER:
return ("DB_REP_NEWMASTER: A new master has declared itself");
case DB_REP_NEWSITE:
return ("DB_REP_NEWSITE: A new site has entered the system");
case DB_REP_NOTPERM:
return ("DB_REP_NOTPERM: Permanent log record not written");
case DB_REP_STARTUPDONE:
return
("DB_REP_STARTUPDONE: Client completed startup synchronization.");
case DB_REP_UNAVAIL:
return ("DB_REP_UNAVAIL: Unable to elect a master");
case DB_RUNRECOVERY:
return ("DB_RUNRECOVERY: Fatal error, run database recovery");
case DB_SECONDARY_BAD:
return
("DB_SECONDARY_BAD: Secondary index inconsistent with primary");
case DB_VERIFY_BAD:
return ("DB_VERIFY_BAD: Database verification failed");
case DB_VERSION_MISMATCH:
return
("DB_VERSION_MISMATCH: Database environment version mismatch");
default:
break;
}
unknown_err: {
/*
* !!!
* Room for a 64-bit number + slop. This buffer is only used
* if we're given an unknown error, which should never happen.
* Note, however, we're no longer thread-safe if it does.
*/
static char ebuf[40];
(void)snprintf(ebuf, sizeof(ebuf), "Unknown error: %d", error);
return (ebuf);
}
}
/*
* __db_err --
* Standard DB error routine. The same as errx, except we don't write
* to stderr if no output mechanism was specified.
*
* PUBLIC: void __db_err __P((const DB_ENV *, const char *, ...))
* PUBLIC: __attribute__ ((__format__ (__printf__, 2, 3)));
*/
void
#ifdef STDC_HEADERS
__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
{
DB_REAL_ERR(dbenv, 0, 0, 0, fmt);
}
/*
* __db_errcall --
* Do the error message work for callback functions.
*
* PUBLIC: void __db_errcall
* PUBLIC: __P((const DB_ENV *, int, int, const char *, va_list));
*/
void
__db_errcall(dbenv, error, error_set, fmt, ap)
const DB_ENV *dbenv;
int error, error_set;
const char *fmt;
va_list ap;
{
char *p;
char buf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
p = buf;
if (fmt != NULL)
p += vsnprintf(buf, sizeof(buf), fmt, ap);
if (error_set)
p += snprintf(p,
sizeof(buf) - (size_t)(p - buf), ": %s",
db_strerror(error));
dbenv->db_errcall(dbenv, dbenv->db_errpfx, buf);
}
/*
* __db_errfile --
* Do the error message work for FILE *s.
*
* PUBLIC: void __db_errfile
* PUBLIC: __P((const DB_ENV *, int, int, const char *, va_list));
*/
void
__db_errfile(dbenv, error, error_set, fmt, ap)
const DB_ENV *dbenv;
int error, error_set;
const char *fmt;
va_list ap;
{
FILE *fp;
fp = dbenv == NULL ||
dbenv->db_errfile == NULL ? stderr : dbenv->db_errfile;
if (dbenv != NULL && dbenv->db_errpfx != NULL)
(void)fprintf(fp, "%s: ", dbenv->db_errpfx);
if (fmt != NULL) {
(void)vfprintf(fp, fmt, ap);
if (error_set)
(void)fprintf(fp, ": ");
}
if (error_set)
(void)fprintf(fp, "%s", db_strerror(error));
(void)fprintf(fp, "\n");
(void)fflush(fp);
}
/*
* __db_msgadd --
* Aggregate a set of strings into a buffer for the callback API.
*
* PUBLIC: void __db_msgadd __P((DB_ENV *, DB_MSGBUF *, const char *, ...))
* PUBLIC: __attribute__ ((__format__ (__printf__, 3, 4)));
*/
void
#ifdef STDC_HEADERS
__db_msgadd(DB_ENV *dbenv, DB_MSGBUF *mbp, const char *fmt, ...)
#else
__db_msgadd(dbenv, mbp, fmt, va_alist)
DB_ENV *dbenv;
DB_MSGBUF *mbp;
const char *fmt;
va_dcl
#endif
{
va_list ap;
size_t len, olen;
char buf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
#ifdef STDC_HEADERS
va_start(ap, fmt);
#else
va_start(ap);
#endif
len = (size_t)vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
/*
* There's a heap buffer in the DB_ENV handle we use to aggregate the
* message chunks. We maintain a pointer to the buffer, the next slot
* to be filled in in the buffer, and a total buffer length.
*/
olen = (size_t)(mbp->cur - mbp->buf);
if (olen + len >= mbp->len) {
if (__os_realloc(dbenv, mbp->len + len + 256, &mbp->buf))
return;
mbp->len += (len + 256);
mbp->cur = mbp->buf + olen;
}
memcpy(mbp->cur, buf, len + 1);
mbp->cur += len;
}
/*
* __db_msg --
* Standard DB stat message routine.
*
* PUBLIC: void __db_msg __P((const DB_ENV *, const char *, ...))
* PUBLIC: __attribute__ ((__format__ (__printf__, 2, 3)));
*/
void
#ifdef STDC_HEADERS
__db_msg(const DB_ENV *dbenv, const char *fmt, ...)
#else
__db_msg(dbenv, fmt, va_alist)
const DB_ENV *dbenv;
const char *fmt;
va_dcl
#endif
{
DB_REAL_MSG(dbenv, fmt);
}
/*
* __db_msgcall --
* Do the message work for callback functions.
*/
static void
__db_msgcall(dbenv, fmt, ap)
const DB_ENV *dbenv;
const char *fmt;
va_list ap;
{
char buf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
(void)vsnprintf(buf, sizeof(buf), fmt, ap);
dbenv->db_msgcall(dbenv, buf);
}
/*
* __db_msgfile --
* Do the message work for FILE *s.
*/
static void
__db_msgfile(dbenv, fmt, ap)
const DB_ENV *dbenv;
const char *fmt;
va_list ap;
{
FILE *fp;
fp = dbenv == NULL ||
dbenv->db_msgfile == NULL ? stdout : dbenv->db_msgfile;
(void)vfprintf(fp, fmt, ap);
(void)fprintf(fp, "\n");
(void)fflush(fp);
}
/*
* __db_unknown_flag -- report internal error
*
* PUBLIC: int __db_unknown_flag __P((DB_ENV *, char *, u_int32_t));
*/
int
__db_unknown_flag(dbenv, routine, flag)
DB_ENV *dbenv;
char *routine;
u_int32_t flag;
{
__db_err(dbenv, "%s: Unknown flag: %#x", routine, (u_int)flag);
DB_ASSERT(0);
return (EINVAL);
}
/*
* __db_unknown_type -- report internal error
*
* PUBLIC: int __db_unknown_type __P((DB_ENV *, char *, DBTYPE));
*/
int
__db_unknown_type(dbenv, routine, type)
DB_ENV *dbenv;
char *routine;
DBTYPE type;
{
__db_err(dbenv,
"%s: Unexpected DB type: %s", routine, __db_dbtype_to_string(type));
DB_ASSERT(0);
return (EINVAL);
}
/*
* __db_check_txn --
* Check for common transaction errors.
*
* PUBLIC: int __db_check_txn __P((DB *, DB_TXN *, u_int32_t, int));
*/
int
__db_check_txn(dbp, txn, assoc_lid, read_op)
DB *dbp;
DB_TXN *txn;
u_int32_t assoc_lid;
int read_op;
{
DB_ENV *dbenv;
int isp, ret;
dbenv = dbp->dbenv;
/*
* If we are in recovery or aborting a transaction, then we
* don't need to enforce the rules about dbp's not allowing
* transactional operations in non-transactional dbps and
* vica-versa. This happens all the time as the dbp during
* an abort may be transactional, but we undo operations
* outside a transaction since we're aborting.
*/
if (IS_RECOVERING(dbenv) || F_ISSET(dbp, DB_AM_RECOVER))
return (0);
/*
* Check for common transaction errors:
* an operation on a handle whose open commit hasn't completed.
* a transaction handle in a non-transactional environment
* a transaction handle for a non-transactional database
*/
if (txn == NULL) {
if (dbp->cur_lid >= TXN_MINIMUM)
goto open_err;
} else {
if (!TXN_ON(dbenv))
return (__db_not_txn_env(dbenv));
if (!F_ISSET(dbp, DB_AM_TXN)) {
__db_err(dbenv,
"Transaction specified for a DB handle opened outside a transaction");
return (EINVAL);
}
if (F_ISSET(txn, TXN_DEADLOCK)) {
__db_err(dbenv,
"Previous deadlock return not resolved");
return (EINVAL);
}
if (dbp->cur_lid >= TXN_MINIMUM && dbp->cur_lid != txn->txnid) {
if ((ret = __lock_locker_is_parent(dbenv,
dbp->cur_lid, txn->txnid, &isp)) != 0)
return (ret);
if (!isp)
goto open_err;
}
}
/*
* If dbp->associate_lid is not DB_LOCK_INVALIDID, that means we're in
* the middle of a DB->associate with DB_CREATE (i.e., a secondary index
* creation).
*
* In addition to the usual transaction rules, we need to lock out
* non-transactional updates that aren't part of the associate (and
* thus are using some other locker ID).
*
* Transactional updates should simply block; from the time we
* decide to build the secondary until commit, we'll hold a write
* lock on all of its pages, so it should be safe to attempt to update
* the secondary in another transaction (presumably by updating the
* primary).
*/
if (!read_op && dbp->associate_lid != DB_LOCK_INVALIDID &&
txn != NULL && dbp->associate_lid != assoc_lid) {
__db_err(dbenv,
"Operation forbidden while secondary index is being created");
return (EINVAL);
}
/*
* Check the txn and dbp are from the same env.
*/
if (txn != NULL && dbenv != txn->mgrp->dbenv) {
__db_err(dbenv,
"Transaction and database from different environments");
return (EINVAL);
}
return (0);
open_err:
__db_err(dbenv,
"Transaction that opened the DB handle is still active");
return (EINVAL);
}
/*
* __db_not_txn_env --
* DB handle must be in an environment that supports transactions.
*
* PUBLIC: int __db_not_txn_env __P((DB_ENV *));
*/
int
__db_not_txn_env(dbenv)
DB_ENV *dbenv;
{
__db_err(dbenv, "DB environment not configured for transactions");
return (EINVAL);
}
/*
* __db_rec_toobig --
* Fixed record length exceeded error message.
*
* PUBLIC: int __db_rec_toobig __P((DB_ENV *, u_int32_t, u_int32_t));
*/
int
__db_rec_toobig(dbenv, data_len, fixed_rec_len)
DB_ENV *dbenv;
u_int32_t data_len, fixed_rec_len;
{
__db_err(dbenv, "%s: length of %lu larger than database's value of %lu",
"Record length error", (u_long)data_len, (u_long)fixed_rec_len);
return (EINVAL);
}
/*
* __db_rec_repl --
* Fixed record replacement length error message.
*
* PUBLIC: int __db_rec_repl __P((DB_ENV *, u_int32_t, u_int32_t));
*/
int
__db_rec_repl(dbenv, data_size, data_dlen)
DB_ENV *dbenv;
u_int32_t data_size, data_dlen;
{
__db_err(dbenv,
"%s: replacement length %lu differs from replaced length %lu",
"Record length error", (u_long)data_size, (u_long)data_dlen);
return (EINVAL);
}
#if defined(DIAGNOSTIC) || defined(DEBUG_ROP) || defined(DEBUG_WOP)
/*
* __dbc_logging --
* In DIAGNOSTIC mode, check for bad replication combinations.
*
* PUBLIC: int __dbc_logging __P((DBC *));
*/
int
__dbc_logging(dbc)
DBC *dbc;
{
DB_ENV *dbenv;
DB_REP *db_rep;
int ret;
dbenv = dbc->dbp->dbenv;
db_rep = dbenv->rep_handle;
ret = LOGGING_ON(dbenv) &&
!F_ISSET(dbc, DBC_RECOVER) && !IS_REP_CLIENT(dbenv);
/*
* If we're not using replication or running recovery, return.
*/
if (db_rep == NULL || F_ISSET(dbc, DBC_RECOVER))
return (ret);
#ifndef DEBUG_ROP
/*
* Only check when DEBUG_ROP is not configured. People often do
* non-transactional reads, and debug_rop is going to write
* a log record.
*/
{
REP *rep;
rep = db_rep->region;
/*
* If we're a client and not running recovery or internally, error.
*/
if (IS_REP_CLIENT(dbenv) && !F_ISSET(dbc->dbp, DB_AM_CL_WRITER)) {
__db_err(dbenv, "Dbc_logging: Client update");
goto err;
}
if (IS_REP_MASTER(dbenv) && dbc->txn == NULL) {
__db_err(dbenv, "Dbc_logging: Master non-txn update");
goto err;
}
if (0) {
err: __db_err(dbenv, "Rep: flags 0x%lx msg_th %lu, start_th %d",
(u_long)rep->flags, (u_long)rep->msg_th, rep->start_th);
__db_err(dbenv, "Rep: handle %lu, opcnt %lu, in_rec %d",
(u_long)rep->handle_cnt, (u_long)rep->op_cnt,
rep->in_recovery);
abort();
}
}
#endif
return (ret);
}
#endif
/*
* __db_check_lsn --
* Display the log sequence error message.
*
* PUBLIC: int __db_check_lsn __P((DB_ENV *, DB_LSN *, DB_LSN *));
*/
int
__db_check_lsn(dbenv, lsn, prev)
DB_ENV *dbenv;
DB_LSN *lsn, *prev;
{
__db_err(dbenv,
"Log sequence error: page LSN %lu %lu; previous LSN %lu %lu",
(u_long)(lsn)->file, (u_long)(lsn)->offset,
(u_long)(prev)->file, (u_long)(prev)->offset);
return (EINVAL);
}
/*
* __db_rdonly --
* Common readonly message.
* PUBLIC: int __db_rdonly __P((const DB_ENV *, const char *));
*/
int
__db_rdonly(dbenv, name)
const DB_ENV *dbenv;
const char *name;
{
__db_err(dbenv, "%s: attempt to modify a read-only database", name);
return (EACCES);
}
/*
* __db_space_err --
* Common out of space message.
* PUBLIC: int __db_space_err __P((const DB *));
*/
int
__db_space_err(dbp)
const DB *dbp;
{
__db_err(dbp->dbenv,
"%s: file limited to %lu pages",
dbp->fname, (u_long)dbp->mpf->mfp->maxpgno);
return (ENOSPC);
}
/*
* __db_failed --
* Common failed thread message.
*
* PUBLIC: int __db_failed __P((const DB_ENV *,
* PUBLIC: const char *, pid_t, db_threadid_t));
*/
int
__db_failed(dbenv, msg, pid, tid)
const DB_ENV *dbenv;
const char *msg;
pid_t pid;
db_threadid_t tid;
{
char buf[DB_THREADID_STRLEN];
__db_err(dbenv, "Thread/process %s failed: %s",
dbenv->thread_id_string((DB_ENV*)dbenv, pid, tid, buf), msg);
return (DB_RUNRECOVERY);
}

View file

@ -1,146 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_getlong.c,v 12.1 2005/06/16 20:20:53 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "db_int.h"
/*
* __db_getlong --
* Return a long value inside of basic parameters.
*
* PUBLIC: int __db_getlong
* PUBLIC: __P((DB_ENV *, const char *, char *, long, long, long *));
*/
int
__db_getlong(dbenv, progname, p, min, max, storep)
DB_ENV *dbenv;
const char *progname;
char *p;
long min, max, *storep;
{
long val;
char *end;
__os_set_errno(0);
val = strtol(p, &end, 10);
if ((val == LONG_MIN || val == LONG_MAX) &&
__os_get_errno() == ERANGE) {
if (dbenv == NULL)
fprintf(stderr,
"%s: %s: %s\n", progname, p, strerror(ERANGE));
else
dbenv->err(dbenv, ERANGE, "%s", p);
return (1);
}
if (p[0] == '\0' || (end[0] != '\0' && end[0] != '\n')) {
if (dbenv == NULL)
fprintf(stderr,
"%s: %s: Invalid numeric argument\n", progname, p);
else
dbenv->errx(dbenv, "%s: Invalid numeric argument", p);
return (1);
}
if (val < min) {
if (dbenv == NULL)
fprintf(stderr,
"%s: %s: Less than minimum value (%ld)\n",
progname, p, min);
else
dbenv->errx(dbenv,
"%s: Less than minimum value (%ld)", p, min);
return (1);
}
if (val > max) {
if (dbenv == NULL)
fprintf(stderr,
"%s: %s: Greater than maximum value (%ld)\n",
progname, p, max);
else
dbenv->errx(dbenv,
"%s: Greater than maximum value (%ld)", p, max);
return (1);
}
*storep = val;
return (0);
}
/*
* __db_getulong --
* Return an unsigned long value inside of basic parameters.
*
* PUBLIC: int __db_getulong
* PUBLIC: __P((DB_ENV *, const char *, char *, u_long, u_long, u_long *));
*/
int
__db_getulong(dbenv, progname, p, min, max, storep)
DB_ENV *dbenv;
const char *progname;
char *p;
u_long min, max, *storep;
{
u_long val;
char *end;
__os_set_errno(0);
val = strtoul(p, &end, 10);
if (val == ULONG_MAX && __os_get_errno() == ERANGE) {
if (dbenv == NULL)
fprintf(stderr,
"%s: %s: %s\n", progname, p, strerror(ERANGE));
else
dbenv->err(dbenv, ERANGE, "%s", p);
return (1);
}
if (p[0] == '\0' || (end[0] != '\0' && end[0] != '\n')) {
if (dbenv == NULL)
fprintf(stderr,
"%s: %s: Invalid numeric argument\n", progname, p);
else
dbenv->errx(dbenv, "%s: Invalid numeric argument", p);
return (1);
}
if (val < min) {
if (dbenv == NULL)
fprintf(stderr,
"%s: %s: Less than minimum value (%lu)\n",
progname, p, min);
else
dbenv->errx(dbenv,
"%s: Less than minimum value (%lu)", p, min);
return (1);
}
/*
* We allow a 0 to substitute as a max value for ULONG_MAX because
* 1) accepting only a 0 value is unlikely to be necessary, and 2)
* we don't want callers to have to use ULONG_MAX explicitly, as it
* may not exist on all platforms.
*/
if (max != 0 && val > max) {
if (dbenv == NULL)
fprintf(stderr,
"%s: %s: Greater than maximum value (%lu)\n",
progname, p, max);
else
dbenv->errx(dbenv,
"%s: Greater than maximum value (%lu)", p, max);
return (1);
}
*storep = val;
return (0);
}

View file

@ -1,92 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_idspace.c,v 12.1 2005/06/16 20:20:53 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdlib.h>
#endif
#include "db_int.h"
static int __db_idcmp __P((const void *, const void *));
static int
__db_idcmp(a, b)
const void *a;
const void *b;
{
u_int32_t i, j;
i = *(u_int32_t *)a;
j = *(u_int32_t *)b;
if (i < j)
return (-1);
else if (i > j)
return (1);
else
return (0);
}
/*
* __db_idspace --
*
* On input, minp and maxp contain the minimum and maximum valid values for
* the name space and on return, they contain the minimum and maximum ids
* available (by finding the biggest gap). The minimum can be an inuse
* value, but the maximum cannot be.
*
* PUBLIC: void __db_idspace __P((u_int32_t *, int, u_int32_t *, u_int32_t *));
*/
void
__db_idspace(inuse, n, minp, maxp)
u_int32_t *inuse;
int n;
u_int32_t *minp, *maxp;
{
int i, low;
u_int32_t gap, t;
/* A single locker ID is a special case. */
if (n == 1) {
/*
* If the single item in use is the last one in the range,
* then we've got to perform wrap which means that we set
* the min to the minimum ID, which is what we came in with,
* so we don't do anything.
*/
if (inuse[0] != *maxp)
*minp = inuse[0];
*maxp = inuse[0] - 1;
return;
}
gap = 0;
low = 0;
qsort(inuse, (size_t)n, sizeof(u_int32_t), __db_idcmp);
for (i = 0; i < n - 1; i++)
if ((t = (inuse[i + 1] - inuse[i])) > gap) {
gap = t;
low = i;
}
/* Check for largest gap at the end of the space. */
if ((*maxp - inuse[n - 1]) + (inuse[0] - *minp) > gap) {
/* Do same check as we do in the n == 1 case. */
if (inuse[n - 1] != *maxp)
*minp = inuse[n - 1];
*maxp = inuse[0] - 1;
} else {
*minp = inuse[low];
*maxp = inuse[low + 1] - 1;
}
}

View file

@ -1,62 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* 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. 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.
*
* $Id: db_log2.c,v 12.1 2005/06/16 20:20:53 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#endif
#include "db_int.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);
}

View file

@ -1,124 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved.
*
* $Id: util_arg.c,v 12.1 2005/06/16 20:20:53 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#endif
#include "db_int.h"
static char *__db_strsep __P((char **, const char *));
/*
* __db_util_arg --
* Convert a string into an argc/argv pair.
*
* PUBLIC: int __db_util_arg __P((char *, char *, int *, char ***));
*/
int
__db_util_arg(arg0, str, argcp, argvp)
char *arg0, *str, ***argvp;
int *argcp;
{
int n, ret;
char **ap, **argv;
#define MAXARGS 25
if ((ret =
__os_malloc(NULL, (MAXARGS + 1) * sizeof(char **), &argv)) != 0)
return (ret);
ap = argv;
*ap++ = arg0;
for (n = 1; (*ap = __db_strsep(&str, " \t")) != NULL;)
if (**ap != '\0') {
++ap;
if (++n == MAXARGS)
break;
}
*ap = NULL;
*argcp = ap - argv;
*argvp = argv;
return (0);
}
/*-
* 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.
*/
/*
* 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.
*/
static char *
__db_strsep(stringp, delim)
char **stringp;
const char *delim;
{
const char *spanp;
int c, sc;
char *s, *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 */
}

View file

@ -1,56 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved.
*
* $Id: util_cache.c,v 12.1 2005/06/16 20:20:54 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "db_int.h"
/*
* __db_util_cache --
* Compute if we have enough cache.
*
* PUBLIC: int __db_util_cache __P((DB *, u_int32_t *, int *));
*/
int
__db_util_cache(dbp, cachep, resizep)
DB *dbp;
u_int32_t *cachep;
int *resizep;
{
u_int32_t pgsize;
int ret;
/* Get the current page size. */
if ((ret = dbp->get_pagesize(dbp, &pgsize)) != 0)
return (ret);
/*
* The current cache size is in cachep. If it's insufficient, set the
* the memory referenced by resizep to 1 and set cachep to the minimum
* size needed.
*
* Make sure our current cache is big enough. We want at least
* DB_MINPAGECACHE pages in the cache.
*/
if ((*cachep / pgsize) < DB_MINPAGECACHE) {
*resizep = 1;
*cachep = pgsize * DB_MINPAGECACHE;
} else
*resizep = 0;
return (0);
}

View file

@ -1,63 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved.
*
* $Id: util_log.c,v 12.4 2005/10/12 17:47:17 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdlib.h>
#if TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#endif
#include <string.h>
#endif
#include "db_int.h"
/*
* __db_util_logset --
* Log that we're running.
*
* PUBLIC: int __db_util_logset __P((const char *, char *));
*/
int
__db_util_logset(progname, fname)
const char *progname;
char *fname;
{
pid_t pid;
db_threadid_t tid;
FILE *fp;
time_t now;
if ((fp = fopen(fname, "w")) == NULL)
goto err;
(void)time(&now);
__os_id(NULL, &pid, &tid);
fprintf(fp, "%s: %lu %s", progname, (u_long)pid, ctime(&now));
if (fclose(fp) == EOF)
goto err;
return (0);
err: fprintf(stderr, "%s: %s: %s\n", progname, fname, strerror(errno));
return (1);
}

View file

@ -1,84 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved.
*
* $Id: util_sig.c,v 12.1 2005/06/16 20:20:55 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <signal.h>
#endif
#include "db_int.h"
static int interrupt;
static void onint __P((int));
/*
* onint --
* Interrupt signal handler.
*/
static void
onint(signo)
int signo;
{
if ((interrupt = signo) == 0)
interrupt = SIGINT;
}
/*
* __db_util_siginit --
*
* PUBLIC: void __db_util_siginit __P((void));
*/
void
__db_util_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.
*/
#ifdef SIGHUP
(void)signal(SIGHUP, onint);
#endif
(void)signal(SIGINT, onint);
#ifdef SIGPIPE
(void)signal(SIGPIPE, onint);
#endif
(void)signal(SIGTERM, onint);
}
/*
* __db_util_interrupted --
* Return if interrupted.
*
* PUBLIC: int __db_util_interrupted __P((void));
*/
int
__db_util_interrupted()
{
return (interrupt != 0);
}
/*
* __db_util_sigresend --
*
* PUBLIC: void __db_util_sigresend __P((void));
*/
void
__db_util_sigresend()
{
/* Resend any caught signal. */
if (interrupt != 0) {
(void)signal(interrupt, SIG_DFL);
(void)raise(interrupt);
/* NOTREACHED */
}
}

View file

@ -1,273 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved.
*
* Some parts of this code originally written by Adam Stubblefield,
* -- astubble@rice.edu.
*
* $Id: aes_method.c,v 12.1 2005/06/16 20:20:55 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/crypto.h"
#include "dbinc/hmac.h"
static void __aes_err __P((DB_ENV *, int));
static int __aes_derivekeys __P((DB_ENV *, DB_CIPHER *, u_int8_t *, size_t));
/*
* __aes_setup --
* Setup AES functions.
*
* PUBLIC: int __aes_setup __P((DB_ENV *, DB_CIPHER *));
*/
int
__aes_setup(dbenv, db_cipher)
DB_ENV *dbenv;
DB_CIPHER *db_cipher;
{
AES_CIPHER *aes_cipher;
int ret;
db_cipher->adj_size = __aes_adj_size;
db_cipher->close = __aes_close;
db_cipher->decrypt = __aes_decrypt;
db_cipher->encrypt = __aes_encrypt;
db_cipher->init = __aes_init;
if ((ret = __os_calloc(dbenv, 1, sizeof(AES_CIPHER), &aes_cipher)) != 0)
return (ret);
db_cipher->data = aes_cipher;
return (0);
}
/*
* __aes_adj_size --
* Given a size, return an addition amount needed to meet the
* "chunk" needs of the algorithm.
*
* PUBLIC: u_int __aes_adj_size __P((size_t));
*/
u_int
__aes_adj_size(len)
size_t len;
{
if (len % DB_AES_CHUNK == 0)
return (0);
return (DB_AES_CHUNK - (u_int)(len % DB_AES_CHUNK));
}
/*
* __aes_close --
* Destroy the AES encryption instantiation.
*
* PUBLIC: int __aes_close __P((DB_ENV *, void *));
*/
int
__aes_close(dbenv, data)
DB_ENV *dbenv;
void *data;
{
__os_free(dbenv, data);
return (0);
}
/*
* __aes_decrypt --
* Decrypt data with AES.
*
* PUBLIC: int __aes_decrypt __P((DB_ENV *, void *, void *,
* PUBLIC: u_int8_t *, size_t));
*/
int
__aes_decrypt(dbenv, aes_data, iv, cipher, cipher_len)
DB_ENV *dbenv;
void *aes_data;
void *iv;
u_int8_t *cipher;
size_t cipher_len;
{
AES_CIPHER *aes;
cipherInstance c;
int ret;
aes = (AES_CIPHER *)aes_data;
if (iv == NULL || cipher == NULL)
return (EINVAL);
if ((cipher_len % DB_AES_CHUNK) != 0)
return (EINVAL);
/*
* Initialize the cipher
*/
if ((ret = __db_cipherInit(&c, MODE_CBC, iv)) < 0) {
__aes_err(dbenv, ret);
return (EAGAIN);
}
/* Do the decryption */
if ((ret = __db_blockDecrypt(&c, &aes->decrypt_ki, cipher,
cipher_len * 8, cipher)) < 0) {
__aes_err(dbenv, ret);
return (EAGAIN);
}
return (0);
}
/*
* __aes_encrypt --
* Encrypt data with AES.
*
* PUBLIC: int __aes_encrypt __P((DB_ENV *, void *, void *,
* PUBLIC: u_int8_t *, size_t));
*/
int
__aes_encrypt(dbenv, aes_data, iv, data, data_len)
DB_ENV *dbenv;
void *aes_data;
void *iv;
u_int8_t *data;
size_t data_len;
{
AES_CIPHER *aes;
cipherInstance c;
u_int32_t tmp_iv[DB_IV_BYTES/4];
int ret;
aes = (AES_CIPHER *)aes_data;
if (aes == NULL || data == NULL)
return (EINVAL);
if ((data_len % DB_AES_CHUNK) != 0)
return (EINVAL);
/*
* Generate the IV here. We store it in a tmp IV because
* the IV might be stored within the data we are encrypting
* and so we will copy it over to the given location after
* encryption is done.
* We don't do this outside of there because some encryption
* algorithms someone might add may not use IV's and we always
* want on here.
*/
if ((ret = __db_generate_iv(dbenv, tmp_iv)) != 0)
return (ret);
/*
* Initialize the cipher
*/
if ((ret = __db_cipherInit(&c, MODE_CBC, (char *)tmp_iv)) < 0) {
__aes_err(dbenv, ret);
return (EAGAIN);
}
/* Do the encryption */
if ((ret = __db_blockEncrypt(&c, &aes->encrypt_ki, data, data_len * 8,
data)) < 0) {
__aes_err(dbenv, ret);
return (EAGAIN);
}
memcpy(iv, tmp_iv, DB_IV_BYTES);
return (0);
}
/*
* __aes_init --
* Initialize the AES encryption instantiation.
*
* PUBLIC: int __aes_init __P((DB_ENV *, DB_CIPHER *));
*/
int
__aes_init(dbenv, db_cipher)
DB_ENV *dbenv;
DB_CIPHER *db_cipher;
{
return (__aes_derivekeys(dbenv, db_cipher, (u_int8_t *)dbenv->passwd,
dbenv->passwd_len));
}
static int
__aes_derivekeys(dbenv, db_cipher, passwd, plen)
DB_ENV *dbenv;
DB_CIPHER *db_cipher;
u_int8_t *passwd;
size_t plen;
{
SHA1_CTX ctx;
AES_CIPHER *aes;
int ret;
u_int32_t temp[DB_MAC_KEY/4];
if (passwd == NULL)
return (EINVAL);
aes = (AES_CIPHER *)db_cipher->data;
/* Derive the crypto keys */
__db_SHA1Init(&ctx);
__db_SHA1Update(&ctx, passwd, plen);
__db_SHA1Update(&ctx, (u_int8_t *)DB_ENC_MAGIC, strlen(DB_ENC_MAGIC));
__db_SHA1Update(&ctx, passwd, plen);
__db_SHA1Final((u_int8_t *)temp, &ctx);
if ((ret = __db_makeKey(&aes->encrypt_ki, DIR_ENCRYPT,
DB_AES_KEYLEN, (char *)temp)) != TRUE) {
__aes_err(dbenv, ret);
return (EAGAIN);
}
if ((ret = __db_makeKey(&aes->decrypt_ki, DIR_DECRYPT,
DB_AES_KEYLEN, (char *)temp)) != TRUE) {
__aes_err(dbenv, ret);
return (EAGAIN);
}
return (0);
}
/*
* __aes_err --
* Handle AES-specific errors. Codes and messages derived from
* rijndael/rijndael-api-fst.h.
*/
static void
__aes_err(dbenv, err)
DB_ENV *dbenv;
int err;
{
char *errstr;
switch (err) {
case BAD_KEY_DIR:
errstr = "AES key direction is invalid";
break;
case BAD_KEY_MAT:
errstr = "AES key material not of correct length";
break;
case BAD_KEY_INSTANCE:
errstr = "AES key passwd not valid";
break;
case BAD_CIPHER_MODE:
errstr = "AES cipher in wrong state (not initialized)";
break;
case BAD_BLOCK_LENGTH:
errstr = "AES bad block length";
break;
case BAD_CIPHER_INSTANCE:
errstr = "AES cipher instance is invalid";
break;
case BAD_DATA:
errstr = "AES data contents are invalid";
break;
case BAD_OTHER:
errstr = "AES unknown error";
break;
default:
errstr = "AES error unrecognized";
break;
}
__db_err(dbenv, errstr);
return;
}

View file

@ -1,394 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* Some parts of this code originally written by Adam Stubblefield
* -- astubble@rice.edu
*
* $Id: crypto.c,v 12.5 2005/07/20 16:50:56 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/crypto.h"
/*
* __crypto_region_init --
* Initialize crypto.
*/
int
__crypto_region_init(dbenv)
DB_ENV *dbenv;
{
REGENV *renv;
REGINFO *infop;
CIPHER *cipher;
DB_CIPHER *db_cipher;
char *sh_passwd;
int ret;
db_cipher = dbenv->crypto_handle;
ret = 0;
infop = dbenv->reginfo;
renv = infop->primary;
if (renv->cipher_off == INVALID_ROFF) {
if (!CRYPTO_ON(dbenv))
return (0);
if (!F_ISSET(infop, REGION_CREATE)) {
__db_err(dbenv,
"Joining non-encrypted environment with encryption key");
return (EINVAL);
}
if (F_ISSET(db_cipher, CIPHER_ANY)) {
__db_err(dbenv, "Encryption algorithm not supplied");
return (EINVAL);
}
/*
* Must create the shared information. We need: Shared cipher
* information that contains the passwd. After we copy the
* passwd, we smash and free the one in the dbenv.
*/
if ((ret =
__db_shalloc(infop, sizeof(CIPHER), 0, &cipher)) != 0)
return (ret);
memset(cipher, 0, sizeof(*cipher));
if ((ret = __db_shalloc(
infop, dbenv->passwd_len, 0, &sh_passwd)) != 0) {
__db_shalloc_free(infop, cipher);
return (ret);
}
memset(sh_passwd, 0, dbenv->passwd_len);
cipher->passwd = R_OFFSET(infop, sh_passwd);
cipher->passwd_len = dbenv->passwd_len;
cipher->flags = db_cipher->alg;
memcpy(sh_passwd, dbenv->passwd, cipher->passwd_len);
renv->cipher_off = R_OFFSET(infop, cipher);
} else {
if (!CRYPTO_ON(dbenv)) {
__db_err(dbenv,
"Encrypted environment: no encryption key supplied");
return (EINVAL);
}
cipher = R_ADDR(infop, renv->cipher_off);
sh_passwd = R_ADDR(infop, cipher->passwd);
if ((cipher->passwd_len != dbenv->passwd_len) ||
memcmp(dbenv->passwd, sh_passwd, cipher->passwd_len) != 0) {
__db_err(dbenv, "Invalid password");
return (EPERM);
}
if (!F_ISSET(db_cipher, CIPHER_ANY) &&
db_cipher->alg != cipher->flags) {
__db_err(dbenv,
"Environment encrypted using a different algorithm");
return (EINVAL);
}
if (F_ISSET(db_cipher, CIPHER_ANY))
/*
* We have CIPHER_ANY and we are joining the existing
* env. Setup our cipher structure for whatever
* algorithm this env has.
*/
if ((ret = __crypto_algsetup(dbenv, db_cipher,
cipher->flags, 0)) != 0)
return (ret);
}
ret = db_cipher->init(dbenv, db_cipher);
/*
* On success, no matter if we allocated it or are using the already
* existing one, we are done with the passwd in the dbenv. We smash
* N-1 bytes so that we don't overwrite the nul.
*/
memset(dbenv->passwd, 0xff, dbenv->passwd_len-1);
__os_free(dbenv, dbenv->passwd);
dbenv->passwd = NULL;
dbenv->passwd_len = 0;
return (ret);
}
/*
* __crypto_dbenv_close --
* Crypto-specific destruction of DB_ENV structure.
*
* PUBLIC: int __crypto_dbenv_close __P((DB_ENV *));
*/
int
__crypto_dbenv_close(dbenv)
DB_ENV *dbenv;
{
DB_CIPHER *db_cipher;
int ret;
ret = 0;
db_cipher = dbenv->crypto_handle;
if (dbenv->passwd != NULL) {
memset(dbenv->passwd, 0xff, dbenv->passwd_len-1);
__os_free(dbenv, dbenv->passwd);
dbenv->passwd = NULL;
}
if (!CRYPTO_ON(dbenv))
return (0);
if (!F_ISSET(db_cipher, CIPHER_ANY))
ret = db_cipher->close(dbenv, db_cipher->data);
__os_free(dbenv, db_cipher);
return (ret);
}
/*
* __crypto_region_destroy --
* Destroy any system resources allocated in the primary region.
*
* PUBLIC: int __crypto_region_destroy __P((DB_ENV *));
*/
int
__crypto_region_destroy(dbenv)
DB_ENV *dbenv;
{
CIPHER *cipher;
REGENV *renv;
REGINFO *infop;
infop = dbenv->reginfo;
renv = infop->primary;
if (renv->cipher_off != INVALID_ROFF) {
cipher = R_ADDR(infop, renv->cipher_off);
__db_shalloc_free(infop, R_ADDR(infop, cipher->passwd));
__db_shalloc_free(infop, cipher);
}
return (0);
}
/*
* __crypto_algsetup --
* Given a db_cipher structure and a valid algorithm flag, call
* the specific algorithm setup function.
*
* PUBLIC: int __crypto_algsetup __P((DB_ENV *, DB_CIPHER *, u_int32_t, int));
*/
int
__crypto_algsetup(dbenv, db_cipher, alg, do_init)
DB_ENV *dbenv;
DB_CIPHER *db_cipher;
u_int32_t alg;
int do_init;
{
int ret;
ret = 0;
if (!CRYPTO_ON(dbenv)) {
__db_err(dbenv, "No cipher structure given");
return (EINVAL);
}
F_CLR(db_cipher, CIPHER_ANY);
switch (alg) {
case CIPHER_AES:
db_cipher->alg = CIPHER_AES;
ret = __aes_setup(dbenv, db_cipher);
break;
default:
__db_panic(dbenv, EINVAL);
/* NOTREACHED */
}
if (do_init)
ret = db_cipher->init(dbenv, db_cipher);
return (ret);
}
/*
* __crypto_decrypt_meta --
* Perform decryption on a metapage if needed.
*
* PUBLIC: int __crypto_decrypt_meta __P((DB_ENV *, DB *, u_int8_t *, int));
*/
int
__crypto_decrypt_meta(dbenv, dbp, mbuf, do_metachk)
DB_ENV *dbenv;
DB *dbp;
u_int8_t *mbuf;
int do_metachk;
{
DB_CIPHER *db_cipher;
DB dummydb;
DBMETA *meta;
size_t pg_off;
int ret;
u_int8_t *iv;
/*
* If we weren't given a dbp, we just want to decrypt the page on
* behalf of some internal subsystem, not on behalf of a user with
* a dbp. Therefore, set up a dummy dbp so that the call to
* P_OVERHEAD below works.
*/
if (dbp == NULL) {
memset(&dummydb, 0, sizeof(DB));
dbp = &dummydb;
}
ret = 0;
meta = (DBMETA *)mbuf;
/*
* !!!
* We used an "unused" field in the meta-data page to flag whether or
* not the database is encrypted. Unfortunately, that unused field
* was used in Berkeley DB releases before 3.0 (for example, 2.7.7).
* It would have been OK, except encryption doesn't follow the usual
* rules of "upgrade before doing anything else", we check encryption
* before checking for old versions of the database.
*
* We don't have to check Btree databases -- before 3.0, the field of
* interest was the bt_maxkey field (which was never supported and has
* since been removed).
*
* Ugly check to jump out if this format is older than what we support.
* It assumes no encrypted page will have an unencrypted magic number,
* but that seems relatively safe. [#10920]
*/
if (meta->magic == DB_HASHMAGIC && meta->version <= 5)
return (0);
/*
* Meta-pages may be encrypted for DBMETASIZE bytes. If we have a
* non-zero IV (that is written after encryption) then we decrypt (or
* error if the user isn't set up for security). We guarantee that
* the IV space on non-encrypted pages will be zero and a zero-IV is
* illegal for encryption. Therefore any non-zero IV means an
* encrypted database. This basically checks the passwd on the file
* if we cannot find a good magic number. We walk through all the
* algorithms we know about attempting to decrypt (and possibly
* byteswap).
*
* !!!
* All method meta pages have the IV and checksum at the exact same
* location, but not in DBMETA, use BTMETA.
*/
if (meta->encrypt_alg != 0) {
db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
if (!F_ISSET(dbp, DB_AM_ENCRYPT)) {
if (!CRYPTO_ON(dbenv)) {
__db_err(dbenv,
"Encrypted database: no encryption flag specified");
return (EINVAL);
}
/*
* User has a correct, secure env, but has encountered
* a database in that env that is secure, but user
* didn't dbp->set_flags. Since it is existing, use
* encryption if it is that way already.
*/
F_SET(dbp, DB_AM_ENCRYPT|DB_AM_CHKSUM);
}
/*
* This was checked in set_flags when DB_AM_ENCRYPT was set.
* So it better still be true here.
*/
DB_ASSERT(CRYPTO_ON(dbenv));
if (!F_ISSET(db_cipher, CIPHER_ANY) &&
meta->encrypt_alg != db_cipher->alg) {
__db_err(dbenv,
"Database encrypted using a different algorithm");
return (EINVAL);
}
DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM));
iv = ((BTMETA *)mbuf)->iv;
/*
* For ALL pages, we do not encrypt the beginning of the page
* that contains overhead information. This is true of meta
* and all other pages.
*/
pg_off = P_OVERHEAD(dbp);
alg_retry:
/*
* If they asked for a specific algorithm, then
* use it. Otherwise walk through those we know.
*/
if (!F_ISSET(db_cipher, CIPHER_ANY)) {
if (do_metachk && (ret = db_cipher->decrypt(dbenv,
db_cipher->data, iv, mbuf + pg_off,
DBMETASIZE - pg_off)))
return (ret);
if (((BTMETA *)meta)->crypto_magic !=
meta->magic) {
__db_err(dbenv, "Invalid password");
return (EINVAL);
}
/*
* Success here. The algorithm asked for and the one
* on the file match. We've just decrypted the meta
* page and checked the magic numbers. They match,
* indicating the password is right. All is right
* with the world.
*/
return (0);
}
/*
* If we get here, CIPHER_ANY must be set.
*/
ret = __crypto_algsetup(dbenv, db_cipher, meta->encrypt_alg, 1);
goto alg_retry;
} else if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
/*
* They gave us a passwd, but the database is not encrypted.
* This is an error. We do NOT want to silently allow them
* to write data in the clear when the user set up and expects
* encrypted data.
*
* This covers at least the following scenario.
* 1. User creates and sets up an encrypted database.
* 2. Attacker cannot read the actual data in the database
* because it is encrypted, but can remove/replace the file
* with an empty, unencrypted database file.
* 3. User sets encryption and we get to this code now.
* If we allowed the file to be used in the clear since
* it is that way on disk, the user would unsuspectingly
* write sensitive data in the clear.
* 4. Attacker reads data that user thought was encrypted.
*
* Therefore, asking for encryption with a database that
* was not encrypted is an error.
*/
__db_err(dbenv,
"Unencrypted database with a supplied encryption key");
return (EINVAL);
}
return (ret);
}
/*
* __crypto_set_passwd --
* Get the password from the shared region; and set it in a new
* environment handle. Use this to duplicate environment handles.
*
* PUBLIC: int __crypto_set_passwd __P((DB_ENV *, DB_ENV *));
*/
int
__crypto_set_passwd(dbenv_src, dbenv_dest)
DB_ENV *dbenv_src, *dbenv_dest;
{
CIPHER *cipher;
REGENV *renv;
REGINFO *infop;
char *sh_passwd;
int ret;
ret = 0;
infop = dbenv_src->reginfo;
renv = infop->primary;
DB_ASSERT(CRYPTO_ON(dbenv_src));
cipher = R_ADDR(infop, renv->cipher_off);
sh_passwd = R_ADDR(infop, cipher->passwd);
return (__env_set_encrypt(dbenv_dest, sh_passwd, DB_ENCRYPT_AES));
}

View file

@ -1,639 +0,0 @@
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Mozilla/4.76 [en] (X11; U; FreeBSD 4.3-RELEASE i386) [Netscape]">
</head>
<body>
<center>
<h1>
&nbsp;Security Interface for Berkeley DB</h1></center>
<center><i>Susan LoVerso</i>
<br><i>sue@sleepycat.com</i>
<br><i>Rev 1.6</i>
<br><i>2002 Feb 26</i></center>
<p>We provide an interface allowing secure access to Berkeley DB.&nbsp;&nbsp;
Our goal is to allow users to have encrypted secure databases.&nbsp; In
this document, the term <i>ciphering</i> means the act of encryption or
decryption.&nbsp; They are equal but opposite actions and the same issues
apply to both just in the opposite direction.
<h3>
Requirements</h3>
The overriding requirement is to provide a simple mechanism to allow users
to have a secure database.&nbsp; A secure database means that all of the
pages of a database will be encrypted, and all of the log files will be
encrypted.
<p>Falling out from this work will be a simple mechanism to allow users
to request that we checksum their data for additional error detection (without
encryption/decryption).
<p>We expect that data in process memory or stored in shared memory, potentially
backed by disk, is not encrypted or secure.
<h2>
<a NAME="DB Modifications"></a>DB Method Interface Modifications</h2>
With a logging environment, all database changes are recorded in the log
files.&nbsp; Therefore, users requiring secure databases in such environments
also require secure log files.
<p>A prior thought had been to allow different passwords on the environment
and the databases within.&nbsp; However, such a scheme, then requires that
the password be logged in order for recovery to be able to restore the
database.&nbsp; Therefore, any application having the password for the
log could get the password for any databases by reading the log.&nbsp;
So having a different password on a database does not gain any additional
security and it makes certain things harder and more complex.&nbsp; Some
of those more complex things include the need to handle database and env
passwords differently since they'd need to be stored and accessed from
different places.&nbsp; Also resolving the issue of how <i>db_checkpoint</i>
or <i>db_sync</i>, which flush database pages to disk, would find the passwords
of various databases without any dbps was unsolved.&nbsp; The feature didn't
gain anything and caused significant pain.&nbsp; Therefore the decision
is that there will be a single password protecting an environment and all
the logs and some databases within that environment.&nbsp; We do allow
users to have a secure environment and clear databases.&nbsp; Users that
want secure databases within a secure environment must set a flag.
<p>Users wishing to enable encryption on a database in a secure environment
or enable just checksumming on their database pages will use new flags
to <a href="../docs/api_c/db_set_flags.html">DB->set_flags()</a>.&nbsp;
Providing ciphering over an entire environment is accomplished by adding
a single environment method: <a href="../docs/api_c/env_set_encrypt.html">DBENV->set_encrypt()</a>.&nbsp;
Providing encryption for a database (not part of an environment) is accomplished
by adding a new database method: <a href="../docs/api_c/db_set_encrypt.html">DB->set_encrypt()</a>.
<p>Both of the <i>set_encrypt</i> methods must be called before their respective
<i>open</i> calls.&nbsp; The environment method must be before the environment
open because we must know about security before there is any possibility
of writing any log records out.&nbsp; The database method must be before
the database open in order to read the root page.&nbsp; The planned interfaces
for these methods are:
<pre>DBENV->set_encrypt(DBENV *dbenv,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* DB_ENV structure */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *passwd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Password */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int32_t flags);&nbsp;&nbsp;&nbsp;&nbsp; /* Flags */</pre>
<pre>DB->set_encrypt(DB *dbp,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* DB structure */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *passwd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Password */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int32_t flags);&nbsp;&nbsp;&nbsp;&nbsp; /* Flags */</pre>
The flags accepted by these functions are:
<pre>#define DB_ENCRYPT_AES&nbsp; 0x00000001&nbsp; /* Use the AES encryption algorithm */</pre>
Passwords are NULL-terminated strings.&nbsp; NULL or zero length strings
are illegal.&nbsp; These flags enable the checksumming and encryption using
the particular algorithms we have chosen for this implementation.&nbsp;
The flags are named such that there is a logical naming pattern if additional
checksum or encryption algorithms are used. If a user gives a flag of zero,
it will behave in a manner similar to DB_UNKNOWN. It will be illegal if
they are creating the environment or database, as an algorithm must be
specified. If they are joining an existing environment or opening an existing
database, they will use whatever algorithm is in force at the time.&nbsp;
Using DB_ENCRYPT_AES automatically implies SHA1 checksumming.
<p>These functions will perform several initialization steps.&nbsp; We
will allocate crypto_handle for our env handle and set up our function
pointers.&nbsp; We will allocate space and copy the password into our env
handle password area.&nbsp; Similar to <i>DB->set_cachesize</i>, calling
<i>DB->set_encrypt</i>
will actually reflect back into the local environment created by DB.
<p>Lastly, we will add a new flag, DB_OVERWRITE, to the <a href="../docs/api_c/env_remove.html">DBENV->remove</a>
method.&nbsp; The purpose of this flag is to force all of the memory used
by the shared regions to be overwritten before removal.&nbsp; We will use
<i>rm_overwrite</i>,
a function that overwrites and syncs a file 3 times with varying bit patterns
to really remove a file.&nbsp; Additionally, this flag will force a sync
of the overwritten regions to disk, if the regions are backed by the file
system.&nbsp; That way there is no residual information left in the clear
in memory or freed disk blocks.&nbsp; Although we expect that this flag
will be used by customers using security, primarily, its action is not
dependent on passwords or a secure setup, and so can be used by anyone.
<h4>
Initialization of the Environment</h4>
The setup of the security subsystem will be similar to replication initialization
since it is a sort of subsystem, but it does not have its own region.&nbsp;
When the environment handle is created via <i>db_env_create</i>, we initialize
our <i>set_encrypt</i> method to be the RPC or local version.&nbsp; Therefore
the <i>DB_ENV</i> structure needs a new pointer:
<pre>&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp; *crypto_handle;&nbsp;&nbsp; /* Security handle */</pre>
The crypto handle will really point to a new <i>__db_cipher</i> structure
that will contain a set of functions and a pointer to the in-memory information
needed by the specific encryption algorithm.&nbsp; It will look like:
<pre>typedef struct __db_cipher {
&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (*init)__P((...));&nbsp;&nbsp;&nbsp; /* Alg-specific initialization function */
&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (*encrypt)__P((...)); /* Alg-specific encryption algorithm */
&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (*decrypt)__P((...)); /* Alg-specific decryption function */
&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *data;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Pointer to alg-specific information (AES_CIPHER) */
&nbsp;&nbsp;&nbsp; u_int32_t flags;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Cipher flags */
} DB_CIPHER;</pre>
<pre>#define DB_MAC_KEY&nbsp;&nbsp;&nbsp; 20&nbsp;&nbsp;&nbsp; /* Size of the MAC key */
typedef struct __aes_cipher {
&nbsp;&nbsp;&nbsp; keyInstance&nbsp;&nbsp;&nbsp; encrypt_ki;&nbsp;&nbsp; /* Encrypt keyInstance temp. */
&nbsp;&nbsp;&nbsp; keyInstance&nbsp;&nbsp;&nbsp; decrypt_ki;&nbsp;&nbsp; /* Decrypt keyInstance temp. */
&nbsp;&nbsp;&nbsp; u_int8_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mac_key[DB_MAC_KEY]; /* MAC key */
&nbsp;&nbsp;&nbsp; u_int32_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flags;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* AES-specific flags */
} AES_CIPHER;</pre>
It should be noted that none of these structures have their own mutex.&nbsp;
We hold the environment region locked while we are creating this, but once
this is set up, it is read-only forever.
<p>During <a href="../docs/api_c/env_set_encrypt.html">dbenv->set_encrypt</a>,
we set the encryption, decryption and checksumming methods to the appropriate
functions based on the flags.&nbsp; This function will allocate us a crypto
handle that we store in the <i>DB_ENV</i> structure just like all the
other subsystems.&nbsp; For now, only AES ciphering functions and SHA1
checksumming functions are supported.&nbsp; Also we will copy the password
into the <i>DB_ENV</i> structure.&nbsp; We ultimately need to keep the
password in the environment's shared memory region or compare this one
against the one that is there, if we are joining an existing environment,
but we do not have it yet because open has not yet been called.&nbsp; We
will allocate a structure that will be used in initialization and set up
the function pointers to point to the algorithm-specific functions.
<p>In the&nbsp; <i>__env_open</i> path, in <i>__db_e_attach</i>, if we
are creating the region and the <i>dbenv->passwd</i> field is set, we need
to use the length of the password in the initial computation of the environment's
size.&nbsp; This guarantees sufficient space for storing the password in
shared memory.&nbsp; Then we will call a new function to initialize the
security region, <i>__crypto_region_init</i> in <i>__env_open</i>.&nbsp;
If we are the creator, we will allocate space in the shared region to store
the password and copy the password into that space.&nbsp; Or, if we are
not the creator we will compare the password stored in the dbenv with the
one in shared memory.&nbsp;&nbsp; Additionally, we will compare the ciphering
algorithm to the one stored in the shared region.We'll smash the dbenv
password and free it.&nbsp; If they do not match, we return an error.&nbsp;
If we are the creator we store the offset into the REGENV structure.&nbsp;
Then <i>__crypto_region_init&nbsp;</i> will call the initialization function
set up earlier based on the ciphering algorithm specified.&nbsp; For now
we will call <i>__aes_init</i>.&nbsp; Additionally this function will allocate
and set up the per-process state vector for this encryption's IVs.&nbsp;
See <a href="#Generating the Initialization Vector">Generating the Initialization
Vector</a> for a detailed description of the IV and state vector.
<p>In the AES-specific initialization function, <i>__aes_init</i>,&nbsp;
we will initialize it by calling
<i>__aes_derivekeys</i> in order to fill
in the keyInstance and mac_key fields in that structure.&nbsp; The REGENV
structure will have one additional item
<pre>&nbsp;&nbsp; roff_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; passwd_off;&nbsp;&nbsp; /* Offset of passwd */</pre>
<h4>
Initializing a Database</h4>
During <a href="../docs/api_c/db_set_encrypt.html">db->set_encrypt</a>,
we set the encryption, decryption and checksumming methods to the appropriate
functions based on the flags.&nbsp; Basically, we test that we are not
in an existing environment and we haven't called open.&nbsp; Then we just
call through the environment handle to set the password.
<p>Also, we will need to add a flag in the database meta-data page that
indicates that the database is encrypted and what its algorithm is.&nbsp;
This will be used when the meta-page is read after reopening a file. We
need this information on the meta-page in order to detect a user opening
a secure database without a password.&nbsp; I propose using the first unused1
byte (renaming it too) in the meta page for this purpose.
<p>All pages will not be encrypted for the first 64 bytes of data.&nbsp;
Database meta-pages will be encrypted on the first 512 bytes only.&nbsp;
All meta-page types will have an IV and checksum added within the first
512 bytes as well as a crypto magic number.&nbsp; This will expand the
size of the meta-page from 256 bytes to 512 bytes. The page in/out routines,
<i>__db_pgin</i> and <i>__db_pgout</i> know the page type of the page and
will apply the 512 bytes ciphering to meta pages.&nbsp; In <i>__db_pgout</i>,
if we have a crypto handle in our (private) environment, we will apply
ciphering to either the entire page, or the first 512 bytes if it is a
meta-page.&nbsp; In <i>__db_pgin</i>, we will decrypt if the page we have
a crypto handle.
<p>When multiple processes share a database, all must use the same password
as the database creator. Using an existing database requires several conditions
to be true.&nbsp; First, if the creator of the database did not create
with security, then opening later with security is an error.&nbsp; Second,
if the creator did create it with security, then opening later without
security is an error.&nbsp; Third, we need to be able to test and check
that when another process opens a secure database that the password they
provided is the same as the one in use by the creator.
<p>When reading the meta-page, in <i>__db_file_setup</i>, we do not go
through the paging functions, but directly read via <i>__os_read</i>.&nbsp;
It is at this point that we will determine if the user is configured correctly.&nbsp;
If the meta-page we read has an IV and checksum, they better have a crypto
handle.&nbsp; If they have a crypto handle, then the meta-page must have
an IV and checksum.&nbsp; If both of those are true, we test the password.&nbsp;
We compare the unencrypted magic number to the newly-decrypted crypto magic
number and if they are not the same, then we report that the user gave
us a bad password.
<p>On a mostly unrelated topic, even when we go to very large pagesizes,
the meta information will still be within a disk sector.&nbsp; So, after
talking it over with Keith and Margo, we determined that unencrypted meta-pages
still will not need a checksum.
<h3>
Encryption and Checksum Routines</h3>
These routines are provided to us by Adam Stubblefield at Rice University
(astubble@rice.edu).&nbsp; The functional interfaces are:
<pre>__aes_derivekeys(DB_ENV *dbenv,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* dbenv */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *passwd,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Password */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t passwd_len,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Length of passwd */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *mac_key,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 20 byte array to store MAC key */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keyInstance *encrypt_key,&nbsp;&nbsp; /* Encryption key of passwd */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keyInstance *decrypt_key);&nbsp; /* Decryption key of passwd */</pre>
This is the only function requiring the textual user password.&nbsp; From
the password, this function generates a key used in the checksum function,
<i>__db_chksum</i>.&nbsp;
It also fills in <i>keyInstance</i> structures which are then used in the
encryption and decryption routines.&nbsp; The keyInstance structures must
already be allocated.&nbsp; These will be stored in the AES_CIPHER structure.
<pre>&nbsp;__db_chksum(u_int8_t *data,&nbsp;&nbsp;&nbsp; /* Data to checksum */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t data_len,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Length of data */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *mac_key,&nbsp;&nbsp;&nbsp; /* 20 byte array from __db_derive_keys */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *checksum);&nbsp; /* 20 byte array to store checksum */</pre>
This function generates a checksum on the data given.&nbsp; This function
will do double-duty for users that simply want error detection on their
pages.&nbsp; When users are using encryption, the <i>mac_key </i>will contain
the 20-byte key set up in <i>__aes_derivekeys</i>.&nbsp; If they just want
checksumming, then <i>mac_key</i> will be NULL.&nbsp; According to Adam,
we can safely use the first N-bytes of the checksum.&nbsp; So for seeding
the generator for initialization vectors, we'll hash the time and then
send in the first 4 bytes for the seed.&nbsp; I believe we can probably
do the same thing for checksumming log records.&nbsp; We can only use 4
bytes for the checksum in the non-secure case.&nbsp; So when we want to
verify the log checksum we can compute the mac but just compare the first
4 bytes to the one we read.&nbsp; All locations where we generate or check
log record checksums that currently call <i>__ham_func4</i> will now call
<i>__db_chksum</i>.&nbsp;
I believe there are 5 such locations,
<i>__log_put, __log_putr, __log_newfile,
__log_rep_put
</i>and<i> __txn_force_abort.</i>
<pre>__aes_encrypt(DB_ENV *dbenv,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* dbenv */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keyInstance *key,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Password key instance from __db_derive_keys */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *iv,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Initialization vector */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *data,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Data to encrypt */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t data_len);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Length of data to encrypt - 16 byte multiple */</pre>
This is the function to encrypt data.&nbsp; It will be called to encrypt
pages and log records.&nbsp; The <i>key</i> instance is initialized in
<i>__aes_derivekeys</i>.&nbsp;
The initialization vector, <i>iv</i>, is the 16 byte random value set up
by the Mersenne Twister pseudo-random generator.&nbsp; Lastly, we pass
in a pointer to the <i>data</i> to encrypt and its length in <i>data_len</i>.&nbsp;
The <i>data_len</i> must be a multiple of 16 bytes. The encryption is done
in-place so that when the encryption code returns our encrypted data is
in the same location as the original data.
<pre>__aes_decrypt(DB_ENV *dbenv,&nbsp;&nbsp;&nbsp; /* dbenv */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keyInstance *key,&nbsp; /* Password key instance from __db_derive_keys */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *iv,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Initialization vector */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_int8_t *data,&nbsp;&nbsp;&nbsp; /* Data to decrypt */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t data_len);&nbsp; /* Length of data to decrypt - 16 byte multiple */</pre>
This is the function to decrypt the data.&nbsp; It is exactly the same
as the encryption function except for the action it performs.&nbsp; All
of the args and issues are the same.&nbsp; It also decrypts in place.
<h3>
<a NAME="Generating the Initialization Vector"></a>Generating the Initialization
Vector</h3>
Internally, we need to provide a unique initialization vector (IV) of 16
bytes every time we encrypt any data with the same password.&nbsp; For
the IV we are planning on using mt19937, the Mersenne Twister, a random
number generator that has a period of 2**19937-1. This package can be found
at <a href="http://www.math.keio.ac.jp/~matumoto/emt.html">http://www.math.keio.ac.jp/~matumoto/emt.html</a>.&nbsp;
Tests show that although it repeats a single integer every once in a while,
that after several million iterations, it doesn't repeat any 4 integers
that we'd be stuffing into our 16-byte IV.&nbsp; We plan on seeding this
generator with the time (tv_sec) hashed through SHA1 when we create the
environment.&nbsp; This package uses a global state vector that contains
624 unsigned long integers.&nbsp; We do not allow a 16-byte IV of zero.&nbsp;
It is simpler just to reject any 4-byte value of 0 and if we get one, just
call the generator again and get a different number.&nbsp; We need to detect
holes in files and if we read an IV of zero that is a simple indication
that we need to check for an entire page of zero.&nbsp; The IVs are stored
on the page after encryption and are not encrypted themselves so it is
not possible for an entire encrypted page to be read as all zeroes, unless
it was a hole in a file.&nbsp; See <a href="#Holes in Files">Holes in Files</a>
for more details.
<p>We will not be holding any locks when we need to generate our IV but
we need to protect access to the state vector and the index.&nbsp; Calls
to the MT code will come while encrypting some data in <i>__aes_encrypt.</i>&nbsp;&nbsp;
The MT code will assume that all necessary locks are held in the caller.&nbsp;
We will have per-process state vectors that are set up when a process begins.&nbsp;
That way we minimize the contention and only multi-threaded processes need
acquire locks for the IV.&nbsp; We will have the state vector in the environment
handle in heap memory, as well as the index and there will be a mutex protecting
it for threaded access.&nbsp; This will be added to the <i>DB_ENV</i>
structure:
<pre>&nbsp;&nbsp;&nbsp; DB_MUTEX&nbsp;&nbsp;&nbsp; *mt_mutexp;&nbsp;&nbsp; /* Mersenne Twister mutex */
&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *mti;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* MT index */
&nbsp;&nbsp;&nbsp; u_long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *mt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* MT state vector */</pre>
This portion of the environment will be initialized at the end of _<i>_dbenv_open</i>,
right after we initialize the other mutex for the <i>dblist</i>. When we
allocate the space, we will generate our initial state vector. If we are
multi-threaded we'll allocate and initialize our mutex also.
<p>We need to make changes to the MT code to make it work in our namespace
and&nbsp; to take&nbsp; a pointer to the location of the state vector and
the index.&nbsp;&nbsp; There will be a wrapper function <i>__db_generate_iv</i>
that DB will call and it will call the appropriate MT function.&nbsp; I
am also going to change the default seed to use a hashed time instead of
a hard coded value.&nbsp; I have looked at other implementations of the
MT code available on the web site.&nbsp; The C++ version does a hash on
the current time.&nbsp; I will modify our MT code to seed with the hashed
time as well.&nbsp; That way the code to seed is contained within the MT
code and we can just write the wrapper to get an IV.&nbsp; We will not
be changing the core computational code of MT.
<h2>
DB Internal Issues</h2>
<h4>
When do we Cipher?</h4>
All of the page ciphering is done in the <i>__db_pgin/__db_pgout</i> functions.&nbsp;
We will encrypt after the method-specific function on page-out and decrypt
before the method-specfic function on page-in.&nbsp; We do not hold any
locks when entering these functions.&nbsp; We determine that we need to
cipher based on the existence of the encryption flag in the dbp.
<p>For ciphering log records, the encryption will be done as the first
thing (or a new wrapper) in <i>__log_put.&nbsp; </i>See <a href="#Log Record Encryption">Log
Record Encryption</a> for those details.
<br>&nbsp;
<h4>
Page Changes</h4>
The checksum and IV values will be stored prior to the first index of the
page.&nbsp; We have a new P_INP macro that replaces use of inp[X] in the
code. &nbsp;This macro takes a dbp as an argument and determines where
our first index is based on whether we have DB_AM_CHKSUM and DB_AM_ENCRYPT
set.&nbsp; If neither is set, then our first index is where it always was.
&nbsp;If just checksumming is set, then we reserve a 4-byte checksum.&nbsp;
If encryption is set, then we reserve 36 bytes for our checksum/IV as well
as some space to get proper alignment to encrypt on a 16-byte boundary.
<p>Since several paging macros use inp[X] in them, those macros must now
take a dbp.&nbsp; There are a lot of changes to make all the necessary
paging macros take a dbp, although these changes are trivial in nature.
<p>Also, there is a new function <i>__db_chk_meta</i> to perform checksumming
and decryption checking on meta pages specifically.&nbsp; This function
is where we check that the database algorithm matches what the user gave
(or if they set DB_CIPHER_ANY then we set it), and other encryption related
testing for bad combinations of what is in the file versus what is in the
user structures.
<h4>
Verification</h4>
The verification code will also need to be updated to deal with secure
pages.&nbsp; Basically when the verification code reads in the meta page
it will call <i>__db_chk_meta</i> to perform any checksumming and decryption.
<h4>
<a NAME="Holes in Files"></a>Holes in Files</h4>
Holes in files will be dealt with rather simply.&nbsp; We need to be able
to distinguish reading a hole in a file from an encrypted page that happened
to encrypt to all zero's.&nbsp; If we read a hole in a file, we do not
want to send that empty page through the decryption routine.&nbsp; This
can be determined simply without incurring the performance penalty of comparing
every byte on a page on every read until we get a non-zero byte.
<br>The __db_pgin function is only given an invalid page P_INVALID in this
case.&nbsp;&nbsp;So, if the page type, which is always unencrypted, is
P_INVALID, then we do not perform any checksum verification or decryption.
<h4>
Errors and Recovery</h4>
Dealing with a checksum error is tricky.&nbsp; Ultimately, if a checksum
error occurs it is extremely likely that the user must do catastrophic
recovery.&nbsp; There is no other failure return other than&nbsp; DB_RUNRECOVERY
for indicating that the user should run catastrophic recovery.&nbsp; We
do not want to add a new error return for applications to check because
a lot of applications already look for and deal with DB_RUNRECOVERY as
an error condition and we want to fit ourselves into that application model.&nbsp;
We already indicate to the user that when they get that error, then they
need to run recovery.&nbsp; If recovery fails, then they need to run catastrophic
recovery.&nbsp; We need to get ourselves to the point where users will
run catastrophic recovery.
<p>If we get a checksum error, then we need to log a message stating a
checksum error occurred on page N.&nbsp; In <i>__db_pgin</i>, we can check
if logging is on in the environment.&nbsp; If so, we want to log the message.
<p>When the application gets the DB_RUNRECOVERY error, they'll have to
shut down their application and run recovery.&nbsp; When the recovery encounters
the record indicating checksum failure, then normal recovery will fail
and the user will have to perform catastrophic recovery.&nbsp; When catastrophic
recovery encounters that record, it will simply ignore it.
<h4>
<a NAME="Log Record Encryption"></a>Log Record Encryption</h4>
Log records will be ciphered.&nbsp; It might make sense to wrap <i>__log_put</i>
to encrypt the DBT we send down.&nbsp; The <i>__log_put </i>function is
where the checksum is computed before acquiring the region lock.&nbsp;
But also this function is where we call <i>__rep_send_message</i> to send
the DBT to the replication clients.&nbsp; Therefore, we need the DBT to
be encrypted prior to there.&nbsp; We also need it encrypted before checksumming.
I think <i>__log_put </i>will become <i>__log_put_internal</i>, and the
new <i>__log_put</i> will encrypt if needed and then call <i>__log_put_internal
</i>(the
function formerly known as <i>__log_put</i>).&nbsp; Log records are kept
in a shared memory region buffer prior to going out to disk.&nbsp; Records
in the buffer will be encrypted.&nbsp; No locks are held at the time we
will need to encrypt.
<p>On reading the log, via log cursors, the log code stores log records
in the log buffer.&nbsp; Records in that buffer will be encrypted, so decryption
will occur no matter whether we are returning records from the buffer or
if we are returning log records directly from the disk. Current checksum
checking is done in
<i>__log_get_c_int.</i>&nbsp; Decryption will be done
after the checksum is checked.
<p>There are currently two nasty issues with encrypted log records.&nbsp;
The first is that <i>__txn_force_abort</i> overwrites a commit record in
the log buffer with an abort record.&nbsp; Well, our log buffer will be
encrypted.&nbsp; Therefore, <i>__txn_force_abort</i> is going to need to
do encryption of its new record.&nbsp; This can be accomplished by sending
in the dbenv handle to the function.&nbsp; It is available to us in <i>__log_flush_commit</i>
and we can just pass it in.&nbsp; I don't like putting log encryption in
the txn code, but the layering violation is already there.
<p>The second issue is that the encryption code requires data that is a
multiple of 16 bytes and log record lengths are variable.&nbsp; We will
need to pad log records to meet the requirement.&nbsp; Since the callers
of <i>__log_put</i> set up the given DBT it is a logical place to pad if
necessary. We will modify the gen_rec.awk script to have all of the generated
logging functions pad for us if we have a crypto handle. This padding will
also expand the size of log files. Anyone calling <i>log_put</i> and using
security from the application will have to pad on their own or it will
return an error.
<p>When ciphering the log file, we will need a different header than the
current one.&nbsp; The current header only has space for a 4 byte checksum.&nbsp;
Our secure header will need space for the 16 byte IV and 20 byte checksum.&nbsp;
This will blow up our log files when running securely since every single
log record header will now consume 32 additional bytes.&nbsp; I believe
that the log header does not need to be encrypted.&nbsp; It contains an
offset, a length and our IV and checksum.&nbsp; Our IV and checksum are
never encrypted.&nbsp; I don't believe there to be any risk in having the
offset and length in the clear.
<p>I would prefer not to have two types of log headers that are incompatible
with each other.&nbsp; It is not acceptable to increase the log headers
of all users from 12 bytes to 44 bytes.&nbsp; Such a change would also
make log files incompatible with earlier releases.&nbsp; Worse even, is
that the <i>cksum</i> field of the header is in between the offset and
len.&nbsp; It would be really convenient if we could have just made a bigger
cksum portion without affecting the location of the other fields.&nbsp;
Oh well.&nbsp; Most customers will not be using encryption and we won't
make them pay the price of the expanded header.&nbsp; Keith indicates that
the log file format is changing with the next release so I will move the
cksum field so it can at least be overlaid.
<p>One method around this would be to have a single internal header that
contains all the information both mechanisms need, but when we write out
the header we choose which pieces to write.&nbsp; By appending the security
information to the end of the existing structure, and adding a size field,
we can modify a few places to use the size field to write out only the
current first 12 bytes, or the entire security header needed.
<h4>
Replication</h4>
Replication clients are going to need to start all of their individual
environment handles with the same password.&nbsp; The log records are going
to be sent to the clients decrypted and the clients will have to encrypt
them on their way to the client log files.&nbsp; We cannot send encrypted
log records to clients. &nbsp;The reason is that the checksum and IV&nbsp;are
stored in the log header and the master only sends the log record itself
to the client. &nbsp;Therefore, the client has no way to decrypt a log
record from the master. &nbsp;Therefore, anyone wanting to use truly secure
replication is going to have to have a secure transport mechanism.&nbsp;
By not encrypting records, clients can theoretically have different passwords
and DB won't care.
<p>On the master side we must copy the DBT sent in.&nbsp; We encrypt the
original and send to clients the clear record.&nbsp; On the client side,
support for encryption is added into <i>__log_rep_put</i>.
<h4>
Sharing the Environment</h4>
When multiple processes join the environment, all must use the same password
as the creator.
<p>Joining an existing environment requires several conditions to be true.&nbsp;
First, if the creator of the environment did not create with security,
then joining later with security is an error.&nbsp; Second, if the creator
did create it with security, then joining later without security is an
error.&nbsp; Third, we need to be able to test and check that when another
process joins a secure environment that the password they provided is the
same as the one in use by the creator.
<p>The first two scenarios should be fairly trivial to determine, if we
aren't creating the environment, we can compare what is there with what
we have.&nbsp; In the third case, the <i>__crypto_region_init</i> function
will see that the environment region has a valid passwd_off and we'll then
compare that password to the one we have in our dbenv handle.&nbsp; In
any case we'll smash the dbenv handle's passwd and free that memory before
returning whether we have a password match or not.
<p>We need to store the passwords themselves in the region because multiple
calls to the <i>__aes_derivekeys </i>function with the same password yields
different keyInstance contents.&nbsp; Therefore we don't have any way to
check passwords other than retaining and comparing the actual passwords.
<h4>
Other APIs</h4>
All of the other APIs will need interface enhancements to support the new
security methods.&nbsp; The Java and C++ interfaces will likely be done
by Michael Cahill and Sue will implement the Tcl and RPC changes.&nbsp;
Tcl will need the changes for testing purposes but the interface should
be public, not test-only.&nbsp; RPC should fully support security.&nbsp;
The biggest risk that I can see is that the client will send the password
to the server in the clear.&nbsp; Anyone sniffing the wires or running
tcpdump or other packet grabbing code could grab that.&nbsp; Someone really
interested in using security over RPC probably ought to add authentication
and other measures to the RPC server as well.
<h4>
<a NAME="Utilities"></a>Utilities</h4>
All should take a -P flag to specify a password for the environment or
password.&nbsp; Those that take an env and a database might need something
more to distinguish between env passwds and db passwds. Here is what we
do for each utility:
<ul>
<li>
berkeley_db_svc - Needs -P after each -h specified.</li>
<li>
db_archive - Needs -P if the env is encrypted.</li>
<li>
db_checkpoint - Needs -P if the env is encrypted.</li>
<li>
db_deadlock - No changes</li>
<li>
db_dump - Needs -P if the env or database is encrypted.</li>
<li>
db_load - Needs -P if the env or database is encrypted.</li>
<li>
db_printlog - Needs -P if the env is encrypted.</li>
<li>
db_recover - Needs -P if the env is encrypted.</li>
<li>
db_stat - Needs -P if the env or database is encrypted.</li>
<li>
db_upgrade - Needs -P if the env or database is encrypted.</li>
<li>
db_verify - Needs -P if the env or database is encrypted.</li>
</ul>
<h2>
Testing</h2>
All testing should be able to be accomplished via Tcl.&nbsp; The following
tests (and probably others I haven't thought of yet) should be performed:
<ul>
<li>
Basic functionality - basically a test001 but encrypted without an env</li>
<li>
Basic functionality, w/ env - like the previous test but with an env.</li>
<li>
Basic functionality, multiple processes - like first test, but make sure
others can correctly join.</li>
<li>
Basic functionality, mult. processes - like above test, but initialize/close
environment/database first so that the next test processes are all joiners
of an existing env, but creator no longer exists and the shared region
must be opened.</li>
<li>
Recovery test - Run recovery over an encrypted environment.</li>
<li>
Subdb test - Run with subdbs that are encrypted.</li>
<li>
Utility test - Verify the new options to all the utilities.</li>
<li>
Error handling - Test the basic setup errors for both env's and databases
with multiple processes.&nbsp; They are:</li>
<ol>
<li>
Attempt to set a NULL or zero-length passwd.</li>
<li>
Create Env w/ security and attempt to create database w/ its own password.</li>
<li>
Env/DB creates with security.&nbsp; Proc2 joins without - should get an
error.</li>
<li>
Env/DB creates without security.&nbsp; Proc2 joins with - should get an
error.</li>
<li>
Env/DB creates with security.&nbsp; Proc2 joins with different password
- should get an error.</li>
<li>
Env/DB creates with security.&nbsp; Closes.&nbsp; Proc2 reopens with different
password - should get an error.</li>
<li>
Env/DB creates with security.&nbsp; Closes.&nbsp; Tcl overwrites a page
of the database with garbage.&nbsp; Proc2 reopens with the correct password.&nbsp;
Code should detect checksum error.</li>
<li>
Env/DB creates with security.&nbsp; Open a 2nd identical DB with a different
password.&nbsp; Put the exact same data into both databases.&nbsp; Close.&nbsp;
Overwrite the identical page of DB1 with the one from DB2.&nbsp; Reopen
the database with correct DB1 password.&nbsp; Code should detect an encryption
error on that page.</li>
</ol>
</ul>
<h2>
Risks</h2>
There are several holes in this design.&nbsp; It is important to document
them clearly.
<p>The first is that all of the pages are stored in memory and possibly
the file system in the clear.&nbsp; The password is stored in the shared
data regions in the clear.&nbsp; Therefore if an attacker can read the
process memory, they can do whatever they want.&nbsp; If the attacker can
read system memory or swap they can access the data as well.&nbsp; Since
everything in the shared data regions (with the exception of the buffered
log) will be in the clear, it is important to realize that file backed
regions will be written in the clear, including the portion of the regions
containing passwords.&nbsp; We recommend to users that they use system
memory instead of file backed shared memory.
</body>
</html>

View file

@ -1,186 +0,0 @@
/*
* $Id: mt19937db.c,v 12.1 2005/07/20 16:50:57 bostic Exp $
*/
#include "db_config.h"
#include "db_int.h"
#include "dbinc/crypto.h"
#include "dbinc/hmac.h"
/* A C-program for MT19937: Integer version (1999/10/28) */
/* genrand() generates one pseudorandom unsigned integer (32bit) */
/* which is uniformly distributed among 0 to 2^32-1 for each */
/* call. sgenrand(seed) sets initial values to the working area */
/* of 624 words. Before genrand(), sgenrand(seed) must be */
/* called once. (seed is any 32-bit integer.) */
/* Coded by Takuji Nishimura, considering the suggestions by */
/* Topher Cooper and Marc Rieffel in July-Aug. 1997. */
/* This library is free software under the Artistic license: */
/* see the file COPYING distributed together with this code. */
/* For the verification of the code, its output sequence file */
/* mt19937int.out is attached (2001/4/2) */
/* Copyright (C) 1997, 1999 Makoto Matsumoto and Takuji Nishimura. */
/* Any feedback is very welcome. For any question, comments, */
/* see http://www.math.keio.ac.jp/matumoto/emt.html or email */
/* matumoto@math.keio.ac.jp */
/* REFERENCE */
/* M. Matsumoto and T. Nishimura, */
/* "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform */
/* Pseudo-Random Number Generator", */
/* ACM Transactions on Modeling and Computer Simulation, */
/* Vol. 8, No. 1, January 1998, pp 3--30. */
/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0df /* constant vector a */
#define UPPER_MASK 0x80000000 /* most significant w-r bits */
#define LOWER_MASK 0x7fffffff /* least significant r bits */
/* Tempering parameters */
#define TEMPERING_MASK_B 0x9d2c5680
#define TEMPERING_MASK_C 0xefc60000
#define TEMPERING_SHIFT_U(y) (y >> 11)
#define TEMPERING_SHIFT_S(y) (y << 7)
#define TEMPERING_SHIFT_T(y) (y << 15)
#define TEMPERING_SHIFT_L(y) (y >> 18)
static void __db_sgenrand __P((unsigned long, unsigned long *, int *));
#ifdef NOT_USED
static void __db_lsgenrand __P((unsigned long *, unsigned long *, int *));
#endif
static unsigned long __db_genrand __P((DB_ENV *));
/*
* __db_generate_iv --
* Generate an initialization vector (IV)
*
* PUBLIC: int __db_generate_iv __P((DB_ENV *, u_int32_t *));
*/
int
__db_generate_iv(dbenv, iv)
DB_ENV *dbenv;
u_int32_t *iv;
{
int i, n, ret;
ret = 0;
n = DB_IV_BYTES / sizeof(u_int32_t);
MUTEX_LOCK(dbenv, dbenv->mtx_mt);
if (dbenv->mt == NULL) {
if ((ret = __os_calloc(dbenv, 1, N*sizeof(unsigned long),
&dbenv->mt)) != 0)
return (ret);
/* mti==N+1 means mt[N] is not initialized */
dbenv->mti = N + 1;
}
for (i = 0; i < n; i++) {
/*
* We do not allow 0. If we get one just try again.
*/
do {
iv[i] = (u_int32_t)__db_genrand(dbenv);
} while (iv[i] == 0);
}
MUTEX_UNLOCK(dbenv, dbenv->mtx_mt);
return (0);
}
/* Initializing the array with a seed */
static void
__db_sgenrand(seed, mt, mtip)
unsigned long seed;
unsigned long mt[];
int *mtip;
{
int i;
DB_ASSERT(seed != 0);
for (i=0;i<N;i++) {
mt[i] = seed & 0xffff0000;
seed = 69069 * seed + 1;
mt[i] |= (seed & 0xffff0000) >> 16;
seed = 69069 * seed + 1;
}
*mtip = N;
}
#ifdef NOT_USED
/* Initialization by "sgenrand()" is an example. Theoretically, */
/* there are 2^19937-1 possible states as an intial state. */
/* This function allows to choose any of 2^19937-1 ones. */
/* Essential bits in "seed_array[]" is following 19937 bits: */
/* (seed_array[0]&UPPER_MASK), seed_array[1], ..., seed_array[N-1]. */
/* (seed_array[0]&LOWER_MASK) is discarded. */
/* Theoretically, */
/* (seed_array[0]&UPPER_MASK), seed_array[1], ..., seed_array[N-1] */
/* can take any values except all zeros. */
static void
__db_lsgenrand(seed_array, mt, mtip)
unsigned long seed_array[];
unsigned long mt[];
int *mtip;
/* the length of seed_array[] must be at least N */
{
int i;
for (i=0;i<N;i++)
mt[i] = seed_array[i];
*mtip=N;
}
#endif
static unsigned long
__db_genrand(dbenv)
DB_ENV *dbenv;
{
unsigned long y;
static unsigned long mag01[2]={0x0, MATRIX_A};
/* mag01[x] = x * MATRIX_A for x=0,1 */
u_int32_t secs, seed, usecs;
/*
* We are called with DB_ENV->mtx_mt locked.
*/
if (dbenv->mti >= N) { /* generate N words at one time */
int kk;
if (dbenv->mti == N+1) { /* if sgenrand() has not been called, */
/*
* Seed the generator with the hashed time. The __db_mac
* function will return 4 bytes if we don't send in a key.
*/
do {
__os_clock(dbenv, &secs, &usecs);
__db_chksum((u_int8_t *)&secs, sizeof(secs), NULL,
(u_int8_t *)&seed);
} while (seed == 0);
__db_sgenrand((long)seed, dbenv->mt, &dbenv->mti);
}
for (kk=0;kk<N-M;kk++) {
y = (dbenv->mt[kk]&UPPER_MASK)|(dbenv->mt[kk+1]&LOWER_MASK);
dbenv->mt[kk] = dbenv->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
}
for (;kk<N-1;kk++) {
y = (dbenv->mt[kk]&UPPER_MASK)|(dbenv->mt[kk+1]&LOWER_MASK);
dbenv->mt[kk] = dbenv->mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
}
y = (dbenv->mt[N-1]&UPPER_MASK)|(dbenv->mt[0]&LOWER_MASK);
dbenv->mt[N-1] = dbenv->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
dbenv->mti = 0;
}
y = dbenv->mt[dbenv->mti++];
y ^= TEMPERING_SHIFT_U(y);
y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
y ^= TEMPERING_SHIFT_L(y);
return y;
}

File diff suppressed because it is too large Load diff

View file

@ -1,40 +0,0 @@
/*
* $Id: rijndael-alg-fst.h,v 12.0 2004/11/17 03:43:17 bostic Exp $
*/
/**
* rijndael-alg-fst.h
*
* @version 3.0 (December 2000)
*
* Optimised ANSI C code for the Rijndael cipher (now AES)
*
* @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
* @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
* @author Paulo Barreto <paulo.barreto@terra.com.br>
*
* This code is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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.
*/
#ifndef __RIJNDAEL_ALG_FST_H
#define __RIJNDAEL_ALG_FST_H
#define MAXKC (256/32)
#define MAXKB (256/8)
#define MAXNR 14
typedef u_int8_t u8;
typedef u_int16_t u16;
typedef u_int32_t u32;
#endif /* __RIJNDAEL_ALG_FST_H */

View file

@ -1,496 +0,0 @@
/**
* rijndael-api-fst.c
*
* @version 2.9 (December 2000)
*
* Optimised ANSI C code for the Rijndael cipher (now AES)
*
* @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
* @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
* @author Paulo Barreto <paulo.barreto@terra.com.br>
*
* This code is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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.
*
* Acknowledgements:
*
* We are deeply indebted to the following people for their bug reports,
* fixes, and improvement suggestions to this implementation. Though we
* tried to list all contributions, we apologise in advance for any
* missing reference.
*
* Andrew Bales <Andrew.Bales@Honeywell.com>
* Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
* John Skodon <skodonj@webquill.com>
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/crypto.h"
#include "crypto/rijndael/rijndael-alg-fst.h"
#include "crypto/rijndael/rijndael-api-fst.h"
/*
* __db_makeKey --
*
* PUBLIC: int __db_makeKey __P((keyInstance *, int, int, char *));
*/
int
__db_makeKey(key, direction, keyLen, keyMaterial)
keyInstance *key;
int direction;
int keyLen;
char *keyMaterial;
{
u8 cipherKey[MAXKB];
if (key == NULL) {
return BAD_KEY_INSTANCE;
}
if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
key->direction = direction;
} else {
return BAD_KEY_DIR;
}
if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
key->keyLen = keyLen;
} else {
return BAD_KEY_MAT;
}
if (keyMaterial != NULL) {
memcpy(cipherKey, keyMaterial, key->keyLen/8);
}
if (direction == DIR_ENCRYPT) {
key->Nr = __db_rijndaelKeySetupEnc(key->rk, cipherKey, keyLen);
} else {
key->Nr = __db_rijndaelKeySetupDec(key->rk, cipherKey, keyLen);
}
__db_rijndaelKeySetupEnc(key->ek, cipherKey, keyLen);
return TRUE;
}
/*
* __db_cipherInit --
*
* PUBLIC: int __db_cipherInit __P((cipherInstance *, int, char *));
*/
int
__db_cipherInit(cipher, mode, IV)
cipherInstance *cipher;
int mode;
char *IV;
{
if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
cipher->mode = mode;
} else {
return BAD_CIPHER_MODE;
}
if (IV != NULL) {
memcpy(cipher->IV, IV, MAX_IV_SIZE);
}
return TRUE;
}
/*
* __db_blockEncrypt --
*
* PUBLIC: int __db_blockEncrypt __P((cipherInstance *, keyInstance *, u_int8_t *,
* PUBLIC: size_t, u_int8_t *));
*/
int
__db_blockEncrypt(cipher, key, input, inputLen, outBuffer)
cipherInstance *cipher;
keyInstance *key;
u_int8_t *input;
size_t inputLen;
u_int8_t *outBuffer;
{
int i, k, t, numBlocks;
u8 block[16], *iv;
u32 tmpiv[4];
if (cipher == NULL ||
key == NULL ||
key->direction == DIR_DECRYPT) {
return BAD_CIPHER_STATE;
}
if (input == NULL || inputLen <= 0) {
return 0; /* nothing to do */
}
numBlocks = (int)(inputLen/128);
switch (cipher->mode) {
case MODE_ECB:
for (i = numBlocks; i > 0; i--) {
__db_rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
input += 16;
outBuffer += 16;
}
break;
case MODE_CBC:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
memcpy(tmpiv, iv, MAX_IV_SIZE);
((u32*)block)[0] = ((u32*)input)[0] ^ tmpiv[0];
((u32*)block)[1] = ((u32*)input)[1] ^ tmpiv[1];
((u32*)block)[2] = ((u32*)input)[2] ^ tmpiv[2];
((u32*)block)[3] = ((u32*)input)[3] ^ tmpiv[3];
__db_rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
iv = outBuffer;
input += 16;
outBuffer += 16;
}
break;
case MODE_CFB1:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
memcpy(outBuffer, input, 16);
for (k = 0; k < 128; k++) {
__db_rijndaelEncrypt(key->ek, key->Nr, iv, block);
outBuffer[k >> 3] ^= (block[0] & (u_int)0x80) >> (k & 7);
for (t = 0; t < 15; t++) {
iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
}
iv[15] = (iv[15] << 1) | ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
}
outBuffer += 16;
input += 16;
}
break;
default:
return BAD_CIPHER_STATE;
}
return 128*numBlocks;
}
/**
* Encrypt data partitioned in octets, using RFC 2040-like padding.
*
* @param input data to be encrypted (octet sequence)
* @param inputOctets input length in octets (not bits)
* @param outBuffer encrypted output data
*
* @return length in octets (not bits) of the encrypted output buffer.
*/
/*
* __db_padEncrypt --
*
* PUBLIC: int __db_padEncrypt __P((cipherInstance *, keyInstance *, u_int8_t *,
* PUBLIC: int, u_int8_t *));
*/
int
__db_padEncrypt(cipher, key, input, inputOctets, outBuffer)
cipherInstance *cipher;
keyInstance *key;
u_int8_t *input;
int inputOctets;
u_int8_t *outBuffer;
{
int i, numBlocks, padLen;
u8 block[16], *iv;
u32 tmpiv[4];
if (cipher == NULL ||
key == NULL ||
key->direction == DIR_DECRYPT) {
return BAD_CIPHER_STATE;
}
if (input == NULL || inputOctets <= 0) {
return 0; /* nothing to do */
}
numBlocks = inputOctets/16;
switch (cipher->mode) {
case MODE_ECB:
for (i = numBlocks; i > 0; i--) {
__db_rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
input += 16;
outBuffer += 16;
}
padLen = 16 - (inputOctets - 16*numBlocks);
DB_ASSERT(padLen > 0 && padLen <= 16);
memcpy(block, input, 16 - padLen);
memset(block + 16 - padLen, padLen, padLen);
__db_rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
break;
case MODE_CBC:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
memcpy(tmpiv, iv, MAX_IV_SIZE);
((u32*)block)[0] = ((u32*)input)[0] ^ tmpiv[0];
((u32*)block)[1] = ((u32*)input)[1] ^ tmpiv[1];
((u32*)block)[2] = ((u32*)input)[2] ^ tmpiv[2];
((u32*)block)[3] = ((u32*)input)[3] ^ tmpiv[3];
__db_rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
iv = outBuffer;
input += 16;
outBuffer += 16;
}
padLen = 16 - (inputOctets - 16*numBlocks);
DB_ASSERT(padLen > 0 && padLen <= 16);
for (i = 0; i < 16 - padLen; i++) {
block[i] = input[i] ^ iv[i];
}
for (i = 16 - padLen; i < 16; i++) {
block[i] = (u_int8_t)padLen ^ iv[i];
}
__db_rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
break;
default:
return BAD_CIPHER_STATE;
}
return 16*(numBlocks + 1);
}
/*
* __db_blockDecrypt --
*
* PUBLIC: int __db_blockDecrypt __P((cipherInstance *, keyInstance *, u_int8_t *,
* PUBLIC: size_t, u_int8_t *));
*/
int
__db_blockDecrypt(cipher, key, input, inputLen, outBuffer)
cipherInstance *cipher;
keyInstance *key;
u_int8_t *input;
size_t inputLen;
u_int8_t *outBuffer;
{
int i, k, t, numBlocks;
u8 block[16], *iv;
u32 tmpiv[4];
if (cipher == NULL ||
key == NULL ||
(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
return BAD_CIPHER_STATE;
}
if (input == NULL || inputLen <= 0) {
return 0; /* nothing to do */
}
numBlocks = (int)(inputLen/128);
switch (cipher->mode) {
case MODE_ECB:
for (i = numBlocks; i > 0; i--) {
__db_rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
input += 16;
outBuffer += 16;
}
break;
case MODE_CBC:
memcpy(tmpiv, cipher->IV, MAX_IV_SIZE);
for (i = numBlocks; i > 0; i--) {
__db_rijndaelDecrypt(key->rk, key->Nr, input, block);
((u32*)block)[0] ^= tmpiv[0];
((u32*)block)[1] ^= tmpiv[1];
((u32*)block)[2] ^= tmpiv[2];
((u32*)block)[3] ^= tmpiv[3];
memcpy(tmpiv, input, 16);
memcpy(outBuffer, block, 16);
input += 16;
outBuffer += 16;
}
break;
case MODE_CFB1:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
memcpy(outBuffer, input, 16);
for (k = 0; k < 128; k++) {
__db_rijndaelEncrypt(key->ek, key->Nr, iv, block);
for (t = 0; t < 15; t++) {
iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
}
iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1);
outBuffer[k >> 3] ^= (block[0] & (u_int)0x80) >> (k & 7);
}
outBuffer += 16;
input += 16;
}
break;
default:
return BAD_CIPHER_STATE;
}
return 128*numBlocks;
}
/*
* __db_padDecrypt --
*
* PUBLIC: int __db_padDecrypt __P((cipherInstance *, keyInstance *, u_int8_t *,
* PUBLIC: int, u_int8_t *));
*/
int
__db_padDecrypt(cipher, key, input, inputOctets, outBuffer)
cipherInstance *cipher;
keyInstance *key;
u_int8_t *input;
int inputOctets;
u_int8_t *outBuffer;
{
int i, numBlocks, padLen;
u8 block[16];
u32 tmpiv[4];
if (cipher == NULL ||
key == NULL ||
key->direction == DIR_ENCRYPT) {
return BAD_CIPHER_STATE;
}
if (input == NULL || inputOctets <= 0) {
return 0; /* nothing to do */
}
if (inputOctets % 16 != 0) {
return BAD_DATA;
}
numBlocks = inputOctets/16;
switch (cipher->mode) {
case MODE_ECB:
/* all blocks but last */
for (i = numBlocks - 1; i > 0; i--) {
__db_rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
input += 16;
outBuffer += 16;
}
/* last block */
__db_rijndaelDecrypt(key->rk, key->Nr, input, block);
padLen = block[15];
if (padLen >= 16) {
return BAD_DATA;
}
for (i = 16 - padLen; i < 16; i++) {
if (block[i] != padLen) {
return BAD_DATA;
}
}
memcpy(outBuffer, block, 16 - padLen);
break;
case MODE_CBC:
/* all blocks but last */
memcpy(tmpiv, cipher->IV, MAX_IV_SIZE);
for (i = numBlocks - 1; i > 0; i--) {
__db_rijndaelDecrypt(key->rk, key->Nr, input, block);
((u32*)block)[0] ^= tmpiv[0];
((u32*)block)[1] ^= tmpiv[1];
((u32*)block)[2] ^= tmpiv[2];
((u32*)block)[3] ^= tmpiv[3];
memcpy(tmpiv, input, 16);
memcpy(outBuffer, block, 16);
input += 16;
outBuffer += 16;
}
/* last block */
__db_rijndaelDecrypt(key->rk, key->Nr, input, block);
((u32*)block)[0] ^= tmpiv[0];
((u32*)block)[1] ^= tmpiv[1];
((u32*)block)[2] ^= tmpiv[2];
((u32*)block)[3] ^= tmpiv[3];
padLen = block[15];
if (padLen <= 0 || padLen > 16) {
return BAD_DATA;
}
for (i = 16 - padLen; i < 16; i++) {
if (block[i] != padLen) {
return BAD_DATA;
}
}
memcpy(outBuffer, block, 16 - padLen);
break;
default:
return BAD_CIPHER_STATE;
}
return 16*numBlocks - padLen;
}
#ifdef INTERMEDIATE_VALUE_KAT
/**
* cipherUpdateRounds:
*
* Encrypts/Decrypts exactly one full block a specified number of rounds.
* Only used in the Intermediate Value Known Answer Test.
*
* Returns:
* TRUE - on success
* BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
*/
/*
* __db_cipherUpdateRounds --
*
* PUBLIC: int __db_cipherUpdateRounds __P((cipherInstance *, keyInstance *,
* PUBLIC: u_int8_t *, int, u_int8_t *, int));
*/
int
__db_cipherUpdateRounds(cipher, key, input, inputLen, outBuffer, rounds)
cipherInstance *cipher;
keyInstance *key;
u_int8_t *input;
size_t inputLen;
u_int8_t *outBuffer;
int rounds;
{
u8 block[16];
if (cipher == NULL || key == NULL) {
return BAD_CIPHER_STATE;
}
memcpy(block, input, 16);
switch (key->direction) {
case DIR_ENCRYPT:
__db_rijndaelEncryptRound(key->rk, key->Nr, block, rounds);
break;
case DIR_DECRYPT:
__db_rijndaelDecryptRound(key->rk, key->Nr, block, rounds);
break;
default:
return BAD_KEY_DIR;
}
memcpy(outBuffer, block, 16);
return TRUE;
}
#endif /* INTERMEDIATE_VALUE_KAT */

View file

@ -1,91 +0,0 @@
/*
* $Id: rijndael-api-fst.h,v 12.0 2004/11/17 03:43:17 bostic Exp $
*/
/**
* rijndael-api-fst.h
*
* @version 2.9 (December 2000)
*
* Optimised ANSI C code for the Rijndael cipher (now AES)
*
* @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
* @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
* @author Paulo Barreto <paulo.barreto@terra.com.br>
*
* This code is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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.
*
* Acknowledgements:
*
* We are deeply indebted to the following people for their bug reports,
* fixes, and improvement suggestions to this implementation. Though we
* tried to list all contributions, we apologise in advance for any
* missing reference.
*
* Andrew Bales <Andrew.Bales@Honeywell.com>
* Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
* John Skodon <skodonj@webquill.com>
*/
#ifndef __RIJNDAEL_API_FST_H
#define __RIJNDAEL_API_FST_H
#include "crypto/rijndael/rijndael-alg-fst.h"
/* Generic Defines */
#define DIR_ENCRYPT 0 /* Are we encrpyting? */
#define DIR_DECRYPT 1 /* Are we decrpyting? */
#define MODE_ECB 1 /* Are we ciphering in ECB mode? */
#define MODE_CBC 2 /* Are we ciphering in CBC mode? */
#define MODE_CFB1 3 /* Are we ciphering in 1-bit CFB mode? */
#undef TRUE
#define TRUE 1
#undef FALSE
#define FALSE 0
#define BITSPERBLOCK 128 /* Default number of bits in a cipher block */
/* Error Codes */
#define BAD_KEY_DIR -1 /* Key direction is invalid, e.g., unknown value */
#define BAD_KEY_MAT -2 /* Key material not of correct length */
#define BAD_KEY_INSTANCE -3 /* Key passed is not valid */
#define BAD_CIPHER_MODE -4 /* Params struct passed to cipherInit invalid */
#define BAD_CIPHER_STATE -5 /* Cipher in wrong state (e.g., not initialized) */
#define BAD_BLOCK_LENGTH -6
#define BAD_CIPHER_INSTANCE -7
#define BAD_DATA -8 /* Data contents are invalid, e.g., invalid padding */
#define BAD_OTHER -9 /* Unknown error */
/* Algorithm-specific Defines */
#define MAX_KEY_SIZE 64 /* # of ASCII char's needed to represent a key */
#define MAX_IV_SIZE 16 /* # bytes needed to represent an IV */
/* Typedefs */
/* The structure for key information */
typedef struct {
u_int8_t direction; /* Key used for encrypting or decrypting? */
int keyLen; /* Length of the key */
char keyMaterial[MAX_KEY_SIZE+1]; /* Raw key data in ASCII, e.g., user input or KAT values */
int Nr; /* key-length-dependent number of rounds */
u32 rk[4*(MAXNR + 1)]; /* key schedule */
u32 ek[4*(MAXNR + 1)]; /* CFB1 key schedule (encryption only) */
} keyInstance;
/* The structure for cipher information */
typedef struct { /* changed order of the components */
u_int8_t mode; /* MODE_ECB, MODE_CBC, or MODE_CFB1 */
u_int8_t IV[MAX_IV_SIZE]; /* A possible Initialization Vector for ciphering */
} cipherInstance;
#endif /* __RIJNDAEL_API_FST_H */

View file

@ -1,657 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_db.cpp,v 12.4 2005/10/18 14:25:53 mjc Exp $
*/
#include "db_config.h"
#include <errno.h>
#include <string.h>
#include "db_cxx.h"
#include "dbinc/cxx_int.h"
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc_auto/db_auto.h"
#include "dbinc_auto/crdel_auto.h"
#include "dbinc/db_dispatch.h"
#include "dbinc_auto/db_ext.h"
#include "dbinc_auto/common_ext.h"
// Helper macros for simple methods that pass through to the
// underlying C method. It may return an error or raise an exception.
// Note this macro expects that input _argspec is an argument
// list element (e.g., "char *arg") and that _arglist is the arguments
// that should be passed through to the C method (e.g., "(db, arg)")
//
#define DB_METHOD(_name, _argspec, _arglist, _retok) \
int Db::_name _argspec \
{ \
int ret; \
DB *db = unwrap(this); \
\
ret = db->_name _arglist; \
if (!_retok(ret)) \
DB_ERROR(env_, "Db::" # _name, ret, error_policy()); \
return (ret); \
}
#define DB_DESTRUCTOR(_name, _argspec, _arglist, _retok) \
int Db::_name _argspec \
{ \
int ret; \
DB *db = unwrap(this); \
\
if (!db) { \
DB_ERROR(env_, "Db::" # _name, EINVAL, error_policy()); \
return (EINVAL); \
} \
cleanup(); \
ret = db->_name _arglist; \
if (!_retok(ret)) \
DB_ERROR(env_, "Db::" # _name, ret, error_policy()); \
return (ret); \
}
#define DB_METHOD_QUIET(_name, _argspec, _arglist) \
int Db::_name _argspec \
{ \
DB *db = unwrap(this); \
\
return (db->_name _arglist); \
}
#define DB_METHOD_VOID(_name, _argspec, _arglist) \
void Db::_name _argspec \
{ \
DB *db = unwrap(this); \
\
db->_name _arglist; \
}
// A truism for the Db object is that there is a valid
// DB handle from the constructor until close().
// After the close, the DB handle is invalid and
// no operations are permitted on the Db (other than
// destructor). Leaving the Db handle open and not
// doing a close is generally considered an error.
//
// We used to allow Db objects to be closed and reopened.
// This implied always keeping a valid DB object, and
// coordinating the open objects between Db/DbEnv turned
// out to be overly complicated. Now we do not allow this.
Db::Db(DbEnv *env, u_int32_t flags)
: imp_(0)
, env_(env)
, mpf_(0)
, construct_error_(0)
, flags_(0)
, construct_flags_(flags)
, append_recno_callback_(0)
, associate_callback_(0)
, bt_compare_callback_(0)
, bt_prefix_callback_(0)
, dup_compare_callback_(0)
, feedback_callback_(0)
, h_hash_callback_(0)
{
if (env_ == 0)
flags_ |= DB_CXX_PRIVATE_ENV;
if ((construct_error_ = initialize()) != 0)
DB_ERROR(env_, "Db::Db", construct_error_, error_policy());
}
// If the DB handle is still open, we close it. This is to make stack
// allocation of Db objects easier so that they are cleaned up in the error
// path. If the environment was closed prior to this, it may cause a trap, but
// an error message is generated during the environment close. Applications
// should call close explicitly in normal (non-exceptional) cases to check the
// return value.
//
Db::~Db()
{
DB *db;
db = unwrap(this);
if (db != NULL) {
cleanup();
(void)db->close(db, 0);
}
}
// private method to initialize during constructor.
// initialize must create a backing DB object,
// and if that creates a new DB_ENV, it must be tied to a new DbEnv.
//
int Db::initialize()
{
DB *db;
DB_ENV *cenv = unwrap(env_);
int ret;
u_int32_t cxx_flags;
cxx_flags = construct_flags_ & DB_CXX_NO_EXCEPTIONS;
// Create a new underlying DB object.
// We rely on the fact that if a NULL DB_ENV* is given,
// one is allocated by DB.
//
if ((ret = db_create(&db, cenv,
construct_flags_ & ~cxx_flags)) != 0)
return (ret);
// Associate the DB with this object
imp_ = db;
db->api_internal = this;
// Create a new DbEnv from a DB_ENV* if it was created locally.
// It is deleted in Db::close().
//
if ((flags_ & DB_CXX_PRIVATE_ENV) != 0)
env_ = new DbEnv(db->dbenv, cxx_flags);
// Create a DbMpoolFile from the DB_MPOOLFILE* in the DB handle.
mpf_ = new DbMpoolFile();
mpf_->imp_ = db->mpf;
return (0);
}
// private method to cleanup after destructor or during close.
// If the environment was created by this Db object, we optionally
// delete it, or return it so the caller can delete it after
// last use.
//
void Db::cleanup()
{
DB *db = unwrap(this);
if (db != NULL) {
// extra safety
imp_ = 0;
// we must dispose of the DbEnv object if
// we created it. This will be the case
// if a NULL DbEnv was passed into the constructor.
// The underlying DB_ENV object will be inaccessible
// after the close, so we must clean it up now.
//
if ((flags_ & DB_CXX_PRIVATE_ENV) != 0) {
env_->cleanup();
delete env_;
env_ = 0;
}
delete mpf_;
}
}
// Return a tristate value corresponding to whether we should
// throw exceptions on errors:
// ON_ERROR_RETURN
// ON_ERROR_THROW
// ON_ERROR_UNKNOWN
//
int Db::error_policy()
{
if (env_ != NULL)
return (env_->error_policy());
else {
// If the env_ is null, that means that the user
// did not attach an environment, so the correct error
// policy can be deduced from constructor flags
// for this Db.
//
if ((construct_flags_ & DB_CXX_NO_EXCEPTIONS) != 0) {
return (ON_ERROR_RETURN);
}
else {
return (ON_ERROR_THROW);
}
}
}
DB_DESTRUCTOR(close, (u_int32_t flags), (db, flags), DB_RETOK_STD)
DB_METHOD(compact, (DbTxn *txnid, Dbt *start, Dbt *stop,
DB_COMPACT *c_data, u_int32_t flags, Dbt *end),
(db, unwrap(txnid), start, stop, c_data, flags, end), DB_RETOK_STD)
// The following cast implies that Dbc can be no larger than DBC
DB_METHOD(cursor, (DbTxn *txnid, Dbc **cursorp, u_int32_t flags),
(db, unwrap(txnid), (DBC **)cursorp, flags),
DB_RETOK_STD)
DB_METHOD(del, (DbTxn *txnid, Dbt *key, u_int32_t flags),
(db, unwrap(txnid), key, flags),
DB_RETOK_DBDEL)
void Db::err(int error, const char *format, ...)
{
DB *db = unwrap(this);
DB_REAL_ERR(db->dbenv, error, 1, 1, format);
}
void Db::errx(const char *format, ...)
{
DB *db = unwrap(this);
DB_REAL_ERR(db->dbenv, 0, 0, 1, format);
}
DB_METHOD(fd, (int *fdp), (db, fdp), DB_RETOK_STD)
int Db::get(DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags)
{
DB *db = unwrap(this);
int ret;
ret = db->get(db, unwrap(txnid), key, value, flags);
if (!DB_RETOK_DBGET(ret)) {
if (ret == DB_BUFFER_SMALL)
DB_ERROR_DBT(env_, "Db::get", value, error_policy());
else
DB_ERROR(env_, "Db::get", ret, error_policy());
}
return (ret);
}
int Db::get_byteswapped(int *isswapped)
{
DB *db = (DB *)unwrapConst(this);
return (db->get_byteswapped(db, isswapped));
}
DbEnv *Db::get_env()
{
DB *db = (DB *)unwrapConst(this);
DB_ENV *dbenv = db->get_env(db);
return (dbenv != NULL ? DbEnv::get_DbEnv(dbenv) : NULL);
}
DbMpoolFile *Db::get_mpf()
{
return (mpf_);
}
DB_METHOD(get_dbname, (const char **filenamep, const char **dbnamep),
(db, filenamep, dbnamep), DB_RETOK_STD)
DB_METHOD(get_open_flags, (u_int32_t *flagsp), (db, flagsp), DB_RETOK_STD)
int Db::get_type(DBTYPE *dbtype)
{
DB *db = (DB *)unwrapConst(this);
return (db->get_type(db, dbtype));
}
// Dbc is a "compatible" subclass of DBC - that is, no virtual functions
// or even extra data members, so these casts, although technically
// non-portable, "should" always be okay.
DB_METHOD(join, (Dbc **curslist, Dbc **cursorp, u_int32_t flags),
(db, (DBC **)curslist, (DBC **)cursorp, flags), DB_RETOK_STD)
DB_METHOD(key_range,
(DbTxn *txnid, Dbt *key, DB_KEY_RANGE *results, u_int32_t flags),
(db, unwrap(txnid), key, results, flags), DB_RETOK_STD)
// If an error occurred during the constructor, report it now.
// Otherwise, call the underlying DB->open method.
//
int Db::open(DbTxn *txnid, const char *file, const char *database,
DBTYPE type, u_int32_t flags, int mode)
{
int ret;
DB *db = unwrap(this);
if (construct_error_ != 0)
ret = construct_error_;
else
ret = db->open(db, unwrap(txnid), file, database, type, flags,
mode);
if (!DB_RETOK_STD(ret))
DB_ERROR(env_, "Db::open", ret, error_policy());
return (ret);
}
int Db::pget(DbTxn *txnid, Dbt *key, Dbt *pkey, Dbt *value, u_int32_t flags)
{
DB *db = unwrap(this);
int ret;
ret = db->pget(db, unwrap(txnid), key, pkey, value, flags);
/* The logic here is identical to Db::get - reuse the macro. */
if (!DB_RETOK_DBGET(ret)) {
if (ret == DB_BUFFER_SMALL && DB_OVERFLOWED_DBT(value))
DB_ERROR_DBT(env_, "Db::pget", value, error_policy());
else
DB_ERROR(env_, "Db::pget", ret, error_policy());
}
return (ret);
}
DB_METHOD(put, (DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags),
(db, unwrap(txnid), key, value, flags), DB_RETOK_DBPUT)
DB_DESTRUCTOR(rename,
(const char *file, const char *database, const char *newname,
u_int32_t flags),
(db, file, database, newname, flags), DB_RETOK_STD)
DB_DESTRUCTOR(remove, (const char *file, const char *database, u_int32_t flags),
(db, file, database, flags), DB_RETOK_STD)
DB_METHOD(truncate, (DbTxn *txnid, u_int32_t *countp, u_int32_t flags),
(db, unwrap(txnid), countp, flags), DB_RETOK_STD)
DB_METHOD(stat, (DbTxn *txnid, void *sp, u_int32_t flags),
(db, unwrap(txnid), sp, flags), DB_RETOK_STD)
DB_METHOD(stat_print, (u_int32_t flags), (db, flags), DB_RETOK_STD)
DB_METHOD(sync, (u_int32_t flags), (db, flags), DB_RETOK_STD)
DB_METHOD(upgrade,
(const char *name, u_int32_t flags), (db, name, flags), DB_RETOK_STD)
////////////////////////////////////////////////////////////////////////
//
// callbacks
//
// *_intercept_c are 'glue' functions that must be declared
// as extern "C" so to be typesafe. Using a C++ method, even
// a static class method with 'correct' arguments, will not pass
// the test; some picky compilers do not allow mixing of function
// pointers to 'C' functions with function pointers to C++ functions.
//
// One wart with this scheme is that the *_callback_ method pointer
// must be declared public to be accessible by the C intercept.
// It's possible to accomplish the goal without this, and with
// another public transfer method, but it's just too much overhead.
// These callbacks are supposed to be *fast*.
//
// The DBTs we receive in these callbacks from the C layer may be
// manufactured there, but we want to treat them as a Dbts.
// Technically speaking, these DBTs were not constructed as a Dbts,
// but it should be safe to cast them as such given that Dbt is a
// *very* thin extension of the DBT. That is, Dbt has no additional
// data elements, does not use virtual functions, virtual inheritance,
// multiple inheritance, RTI, or any other language feature that
// causes the structure to grow or be displaced. Although this may
// sound risky, a design goal of C++ is complete structure
// compatibility with C, and has the philosophy 'if you don't use it,
// you shouldn't incur the overhead'. If the C/C++ compilers you're
// using on a given machine do not have matching struct layouts, then
// a lot more things will be broken than just this.
//
// The alternative, creating a Dbt here in the callback, and populating
// it from the DBT, is just too slow and cumbersome to be very useful.
// These macros avoid a lot of boilerplate code for callbacks
#define DB_CALLBACK_C_INTERCEPT(_name, _rettype, _cargspec, \
_return, _cxxargs) \
extern "C" _rettype _db_##_name##_intercept_c _cargspec \
{ \
Db *cxxthis; \
\
DB_ASSERT(cthis != NULL); \
cxxthis = Db::get_Db(cthis); \
DB_ASSERT(cxxthis != NULL); \
DB_ASSERT(cxxthis->_name##_callback_ != 0); \
\
_return (*cxxthis->_name##_callback_) _cxxargs; \
}
#define DB_SET_CALLBACK(_cxxname, _name, _cxxargspec, _cb) \
int Db::_cxxname _cxxargspec \
{ \
DB *cthis = unwrap(this); \
\
_name##_callback_ = _cb; \
return ((*(cthis->_cxxname))(cthis, \
(_cb) ? _db_##_name##_intercept_c : NULL)); \
}
/* associate callback - doesn't quite fit the pattern because of the flags */
DB_CALLBACK_C_INTERCEPT(associate,
int, (DB *cthis, const DBT *key, const DBT *data, DBT *retval),
return, (cxxthis, Dbt::get_const_Dbt(key), Dbt::get_const_Dbt(data),
Dbt::get_Dbt(retval)))
int Db::associate(DbTxn *txn, Db *secondary, int (*callback)(Db *, const Dbt *,
const Dbt *, Dbt *), u_int32_t flags)
{
DB *cthis = unwrap(this);
/* Since the secondary Db is used as the first argument
* to the callback, we store the C++ callback on it
* rather than on 'this'.
*/
secondary->associate_callback_ = callback;
return ((*(cthis->associate))(cthis, unwrap(txn), unwrap(secondary),
(callback) ? _db_associate_intercept_c : NULL, flags));
}
DB_CALLBACK_C_INTERCEPT(feedback,
void, (DB *cthis, int opcode, int pct),
/* no return */ (void), (cxxthis, opcode, pct))
DB_SET_CALLBACK(set_feedback, feedback,
(void (*arg)(Db *cxxthis, int opcode, int pct)), arg)
DB_CALLBACK_C_INTERCEPT(append_recno,
int, (DB *cthis, DBT *data, db_recno_t recno),
return, (cxxthis, Dbt::get_Dbt(data), recno))
DB_SET_CALLBACK(set_append_recno, append_recno,
(int (*arg)(Db *cxxthis, Dbt *data, db_recno_t recno)), arg)
DB_CALLBACK_C_INTERCEPT(bt_compare,
int, (DB *cthis, const DBT *data1, const DBT *data2),
return,
(cxxthis, Dbt::get_const_Dbt(data1), Dbt::get_const_Dbt(data2)))
DB_SET_CALLBACK(set_bt_compare, bt_compare,
(int (*arg)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), arg)
DB_CALLBACK_C_INTERCEPT(bt_prefix,
size_t, (DB *cthis, const DBT *data1, const DBT *data2),
return,
(cxxthis, Dbt::get_const_Dbt(data1), Dbt::get_const_Dbt(data2)))
DB_SET_CALLBACK(set_bt_prefix, bt_prefix,
(size_t (*arg)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), arg)
DB_CALLBACK_C_INTERCEPT(dup_compare,
int, (DB *cthis, const DBT *data1, const DBT *data2),
return,
(cxxthis, Dbt::get_const_Dbt(data1), Dbt::get_const_Dbt(data2)))
DB_SET_CALLBACK(set_dup_compare, dup_compare,
(int (*arg)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), arg)
DB_CALLBACK_C_INTERCEPT(h_hash,
u_int32_t, (DB *cthis, const void *data, u_int32_t len),
return, (cxxthis, data, len))
DB_SET_CALLBACK(set_h_hash, h_hash,
(u_int32_t (*arg)(Db *cxxthis, const void *data, u_int32_t len)), arg)
// This is a 'glue' function declared as extern "C" so it will
// be compatible with picky compilers that do not allow mixing
// of function pointers to 'C' functions with function pointers
// to C++ functions.
//
extern "C"
int _verify_callback_c(void *handle, const void *str_arg)
{
char *str;
__DB_STD(ostream) *out;
str = (char *)str_arg;
out = (__DB_STD(ostream) *)handle;
(*out) << str;
if (out->fail())
return (EIO);
return (0);
}
int Db::verify(const char *name, const char *subdb,
__DB_STD(ostream) *ostr, u_int32_t flags)
{
DB *db = unwrap(this);
int ret;
if (!db)
ret = EINVAL;
else {
// after a DB->verify (no matter if success or failure),
// the underlying DB object must not be accessed,
// so we clean up in advance.
//
cleanup();
ret = __db_verify_internal(db, name, subdb, ostr,
_verify_callback_c, flags);
}
if (!DB_RETOK_STD(ret))
DB_ERROR(env_, "Db::verify", ret, error_policy());
return (ret);
}
DB_METHOD(set_bt_compare, (bt_compare_fcn_type func),
(db, func), DB_RETOK_STD)
DB_METHOD(get_bt_minkey, (u_int32_t *bt_minkeyp),
(db, bt_minkeyp), DB_RETOK_STD)
DB_METHOD(set_bt_minkey, (u_int32_t bt_minkey),
(db, bt_minkey), DB_RETOK_STD)
DB_METHOD(set_bt_prefix, (bt_prefix_fcn_type func),
(db, func), DB_RETOK_STD)
DB_METHOD(set_dup_compare, (dup_compare_fcn_type func),
(db, func), DB_RETOK_STD)
DB_METHOD(get_encrypt_flags, (u_int32_t *flagsp),
(db, flagsp), DB_RETOK_STD)
DB_METHOD(set_encrypt, (const char *passwd, u_int32_t flags),
(db, passwd, flags), DB_RETOK_STD)
DB_METHOD_VOID(get_errfile, (FILE **errfilep), (db, errfilep))
DB_METHOD_VOID(set_errfile, (FILE *errfile), (db, errfile))
DB_METHOD_VOID(get_errpfx, (const char **errpfx), (db, errpfx))
DB_METHOD_VOID(set_errpfx, (const char *errpfx), (db, errpfx))
DB_METHOD(get_flags, (u_int32_t *flagsp), (db, flagsp),
DB_RETOK_STD)
DB_METHOD(set_flags, (u_int32_t flags), (db, flags),
DB_RETOK_STD)
DB_METHOD(get_h_ffactor, (u_int32_t *h_ffactorp),
(db, h_ffactorp), DB_RETOK_STD)
DB_METHOD(set_h_ffactor, (u_int32_t h_ffactor),
(db, h_ffactor), DB_RETOK_STD)
DB_METHOD(set_h_hash, (h_hash_fcn_type func),
(db, func), DB_RETOK_STD)
DB_METHOD(get_h_nelem, (u_int32_t *h_nelemp),
(db, h_nelemp), DB_RETOK_STD)
DB_METHOD(set_h_nelem, (u_int32_t h_nelem),
(db, h_nelem), DB_RETOK_STD)
DB_METHOD(get_lorder, (int *db_lorderp), (db, db_lorderp),
DB_RETOK_STD)
DB_METHOD(set_lorder, (int db_lorder), (db, db_lorder),
DB_RETOK_STD)
DB_METHOD_VOID(get_msgfile, (FILE **msgfilep), (db, msgfilep))
DB_METHOD_VOID(set_msgfile, (FILE *msgfile), (db, msgfile))
DB_METHOD(get_pagesize, (u_int32_t *db_pagesizep),
(db, db_pagesizep), DB_RETOK_STD)
DB_METHOD(set_pagesize, (u_int32_t db_pagesize),
(db, db_pagesize), DB_RETOK_STD)
DB_METHOD(get_re_delim, (int *re_delimp),
(db, re_delimp), DB_RETOK_STD)
DB_METHOD(set_re_delim, (int re_delim),
(db, re_delim), DB_RETOK_STD)
DB_METHOD(get_re_len, (u_int32_t *re_lenp),
(db, re_lenp), DB_RETOK_STD)
DB_METHOD(set_re_len, (u_int32_t re_len),
(db, re_len), DB_RETOK_STD)
DB_METHOD(get_re_pad, (int *re_padp),
(db, re_padp), DB_RETOK_STD)
DB_METHOD(set_re_pad, (int re_pad),
(db, re_pad), DB_RETOK_STD)
DB_METHOD(get_re_source, (const char **re_source),
(db, re_source), DB_RETOK_STD)
DB_METHOD(set_re_source, (const char *re_source),
(db, re_source), DB_RETOK_STD)
DB_METHOD(get_q_extentsize, (u_int32_t *extentsizep),
(db, extentsizep), DB_RETOK_STD)
DB_METHOD(set_q_extentsize, (u_int32_t extentsize),
(db, extentsize), DB_RETOK_STD)
DB_METHOD_QUIET(set_alloc, (db_malloc_fcn_type malloc_fcn,
db_realloc_fcn_type realloc_fcn, db_free_fcn_type free_fcn),
(db, malloc_fcn, realloc_fcn, free_fcn))
void Db::set_errcall(void (*arg)(const DbEnv *, const char *, const char *))
{
env_->set_errcall(arg);
}
void Db::set_msgcall(void (*arg)(const DbEnv *, const char *))
{
env_->set_msgcall(arg);
}
void *Db::get_app_private() const
{
return unwrapConst(this)->app_private;
}
void Db::set_app_private(void *value)
{
unwrap(this)->app_private = value;
}
DB_METHOD(get_cachesize, (u_int32_t *gbytesp, u_int32_t *bytesp, int *ncachep),
(db, gbytesp, bytesp, ncachep), DB_RETOK_STD)
DB_METHOD(set_cachesize, (u_int32_t gbytes, u_int32_t bytes, int ncache),
(db, gbytes, bytes, ncache), DB_RETOK_STD)
int Db::set_paniccall(void (*callback)(DbEnv *, int))
{
return (env_->set_paniccall(callback));
}
__DB_STD(ostream) *Db::get_error_stream()
{
return env_->get_error_stream();
}
void Db::set_error_stream(__DB_STD(ostream) *error_stream)
{
env_->set_error_stream(error_stream);
}
__DB_STD(ostream) *Db::get_message_stream()
{
return env_->get_message_stream();
}
void Db::set_message_stream(__DB_STD(ostream) *message_stream)
{
env_->set_message_stream(message_stream);
}
DB_METHOD_QUIET(get_transactional, (), (db))

View file

@ -1,121 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_dbc.cpp,v 12.2 2005/09/30 07:38:25 mjc Exp $
*/
#include "db_config.h"
#include <errno.h>
#include <string.h>
#include "db_cxx.h"
#include "dbinc/cxx_int.h"
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc_auto/db_auto.h"
#include "dbinc_auto/crdel_auto.h"
#include "dbinc/db_dispatch.h"
#include "dbinc_auto/db_ext.h"
#include "dbinc_auto/common_ext.h"
// Helper macro for simple methods that pass through to the
// underlying C method. It may return an error or raise an exception.
// Note this macro expects that input _argspec is an argument
// list element (e.g., "char *arg") and that _arglist is the arguments
// that should be passed through to the C method (e.g., "(db, arg)")
//
#define DBC_METHOD(_name, _argspec, _arglist, _retok) \
int Dbc::_name _argspec \
{ \
int ret; \
DBC *dbc = this; \
\
ret = dbc->c_##_name _arglist; \
if (!_retok(ret)) \
DB_ERROR(DbEnv::get_DbEnv(dbc->dbp->dbenv), \
"Dbc::" # _name, ret, ON_ERROR_UNKNOWN); \
return (ret); \
}
// It's private, and should never be called, but VC4.0 needs it resolved
//
Dbc::~Dbc()
{
}
DBC_METHOD(close, (void), (dbc), DB_RETOK_STD)
DBC_METHOD(count, (db_recno_t *countp, u_int32_t _flags),
(dbc, countp, _flags), DB_RETOK_STD)
DBC_METHOD(del, (u_int32_t _flags),
(dbc, _flags), DB_RETOK_DBCDEL)
int Dbc::dup(Dbc** cursorp, u_int32_t _flags)
{
int ret;
DBC *dbc = this;
DBC *new_cursor = 0;
ret = dbc->c_dup(dbc, &new_cursor, _flags);
if (DB_RETOK_STD(ret))
// The following cast implies that Dbc can be no larger than DBC
*cursorp = (Dbc*)new_cursor;
else
DB_ERROR(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::dup", ret, ON_ERROR_UNKNOWN);
return (ret);
}
int Dbc::get(Dbt* key, Dbt *data, u_int32_t _flags)
{
int ret;
DBC *dbc = this;
ret = dbc->c_get(dbc, key, data, _flags);
if (!DB_RETOK_DBCGET(ret)) {
if (ret == DB_BUFFER_SMALL && DB_OVERFLOWED_DBT(key))
DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::get", key, ON_ERROR_UNKNOWN);
else if (ret == DB_BUFFER_SMALL && DB_OVERFLOWED_DBT(data))
DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::get", data, ON_ERROR_UNKNOWN);
else
DB_ERROR(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::get", ret, ON_ERROR_UNKNOWN);
}
return (ret);
}
int Dbc::pget(Dbt* key, Dbt *pkey, Dbt *data, u_int32_t _flags)
{
int ret;
DBC *dbc = this;
ret = dbc->c_pget(dbc, key, pkey, data, _flags);
/* Logic is the same as for Dbc::get - reusing macro. */
if (!DB_RETOK_DBCGET(ret)) {
if (ret == DB_BUFFER_SMALL && DB_OVERFLOWED_DBT(key))
DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::pget", key, ON_ERROR_UNKNOWN);
else if (ret == DB_BUFFER_SMALL && DB_OVERFLOWED_DBT(data))
DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::pget", data, ON_ERROR_UNKNOWN);
else
DB_ERROR(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::pget", ret, ON_ERROR_UNKNOWN);
}
return (ret);
}
DBC_METHOD(put, (Dbt* key, Dbt *data, u_int32_t _flags),
(dbc, key, data, _flags), DB_RETOK_DBCPUT)

View file

@ -1,59 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_dbt.cpp,v 12.1 2005/06/16 20:20:58 bostic Exp $
*/
#include "db_config.h"
#include <errno.h>
#include <string.h>
#include "db_cxx.h"
#include "dbinc/cxx_int.h"
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc_auto/db_auto.h"
#include "dbinc_auto/crdel_auto.h"
#include "dbinc/db_dispatch.h"
#include "dbinc_auto/db_ext.h"
#include "dbinc_auto/common_ext.h"
Dbt::Dbt()
{
DBT *dbt = this;
memset(dbt, 0, sizeof(DBT));
}
Dbt::Dbt(void *data_arg, u_int32_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)
{
if (this != &that) {
const DBT *from = &that;
DBT *to = this;
memcpy(to, from, sizeof(DBT));
}
return (*this);
}

File diff suppressed because it is too large Load diff

View file

@ -1,354 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_except.cpp,v 12.2 2005/10/14 12:20:04 mjc Exp $
*/
#include "db_config.h"
#include <string.h>
#include <errno.h>
#include "db_cxx.h"
#include "dbinc/cxx_int.h"
// 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() throw()
{
delete [] what_;
}
DbException::DbException(int err)
: err_(err)
, env_(0)
{
describe(0, 0);
}
DbException::DbException(const char *description)
: err_(0)
, env_(0)
{
describe(0, description);
}
DbException::DbException(const char *description, int err)
: err_(err)
, env_(0)
{
describe(0, description);
}
DbException::DbException(const char *prefix, const char *description, int err)
: err_(err)
, env_(0)
{
describe(prefix, description);
}
DbException::DbException(const DbException &that)
: __DB_STD(exception)()
, what_(dupString(that.what_))
, err_(that.err_)
, env_(0)
{
}
DbException &DbException::operator = (const DbException &that)
{
if (this != &that) {
err_ = that.err_;
delete [] what_;
what_ = dupString(that.what_);
}
return (*this);
}
void DbException::describe(const char *prefix, const char *description)
{
char msgbuf[1024], *p, *end;
p = msgbuf;
end = msgbuf + sizeof(msgbuf) - 1;
if (prefix != NULL) {
strncpy(p, prefix, (p < end) ? end - p: 0);
p += strlen(prefix);
strncpy(p, ": ", (p < end) ? end - p: 0);
p += 2;
}
if (description != NULL) {
strncpy(p, description, (p < end) ? end - p: 0);
p += strlen(description);
if (err_ != 0) {
strncpy(p, ": ", (p < end) ? end - p: 0);
p += 2;
}
}
if (err_ != 0) {
strncpy(p, db_strerror(err_), (p < end) ? end - p: 0);
p += strlen(db_strerror(err_));
}
/*
* If the result was too long, the buffer will not be null-terminated,
* so we need to fix that here before duplicating it.
*/
if (p >= end)
*end = '\0';
what_ = dupString(msgbuf);
}
int DbException::get_errno() const
{
return (err_);
}
const char *DbException::what() const throw()
{
return (what_);
}
DbEnv *DbException::get_env() const
{
return env_;
}
void DbException::set_env(DbEnv *env)
{
env_= env;
}
////////////////////////////////////////////////////////////////////////
// //
// DbMemoryException //
// //
////////////////////////////////////////////////////////////////////////
static const char *memory_err_desc = "Dbt not large enough for available data";
DbMemoryException::~DbMemoryException() throw()
{
}
DbMemoryException::DbMemoryException(Dbt *dbt)
: DbException(memory_err_desc, ENOMEM)
, dbt_(dbt)
{
}
DbMemoryException::DbMemoryException(const char *prefix, Dbt *dbt)
: DbException(prefix, memory_err_desc, ENOMEM)
, dbt_(dbt)
{
}
DbMemoryException::DbMemoryException(const DbMemoryException &that)
: DbException(that)
, dbt_(that.dbt_)
{
}
DbMemoryException
&DbMemoryException::operator =(const DbMemoryException &that)
{
if (this != &that) {
DbException::operator=(that);
dbt_ = that.dbt_;
}
return (*this);
}
Dbt *DbMemoryException::get_dbt() const
{
return (dbt_);
}
////////////////////////////////////////////////////////////////////////
// //
// DbDeadlockException //
// //
////////////////////////////////////////////////////////////////////////
DbDeadlockException::~DbDeadlockException() throw()
{
}
DbDeadlockException::DbDeadlockException(const char *description)
: DbException(description, DB_LOCK_DEADLOCK)
{
}
DbDeadlockException::DbDeadlockException(const DbDeadlockException &that)
: DbException(that)
{
}
DbDeadlockException
&DbDeadlockException::operator =(const DbDeadlockException &that)
{
if (this != &that)
DbException::operator=(that);
return (*this);
}
////////////////////////////////////////////////////////////////////////
// //
// DbLockNotGrantedException //
// //
////////////////////////////////////////////////////////////////////////
DbLockNotGrantedException::~DbLockNotGrantedException() throw()
{
delete lock_;
}
DbLockNotGrantedException::DbLockNotGrantedException(const char *prefix,
db_lockop_t op, db_lockmode_t mode, const Dbt *obj, const DbLock lock,
int index)
: DbException(prefix, DbEnv::strerror(DB_LOCK_NOTGRANTED),
DB_LOCK_NOTGRANTED)
, op_(op)
, mode_(mode)
, obj_(obj)
, lock_(new DbLock(lock))
, index_(index)
{
}
DbLockNotGrantedException::DbLockNotGrantedException(const char *description)
: DbException(description, DB_LOCK_NOTGRANTED)
, op_(DB_LOCK_GET)
, mode_(DB_LOCK_NG)
, obj_(NULL)
, lock_(NULL)
, index_(0)
{
}
DbLockNotGrantedException::DbLockNotGrantedException
(const DbLockNotGrantedException &that)
: DbException(that)
{
op_ = that.op_;
mode_ = that.mode_;
obj_ = that.obj_;
lock_ = (that.lock_ != NULL) ? new DbLock(*that.lock_) : NULL;
index_ = that.index_;
}
DbLockNotGrantedException
&DbLockNotGrantedException::operator =(const DbLockNotGrantedException &that)
{
if (this != &that) {
DbException::operator=(that);
op_ = that.op_;
mode_ = that.mode_;
obj_ = that.obj_;
lock_ = (that.lock_ != NULL) ? new DbLock(*that.lock_) : NULL;
index_ = that.index_;
}
return (*this);
}
db_lockop_t DbLockNotGrantedException::get_op() const
{
return op_;
}
db_lockmode_t DbLockNotGrantedException::get_mode() const
{
return mode_;
}
const Dbt* DbLockNotGrantedException::get_obj() const
{
return obj_;
}
DbLock* DbLockNotGrantedException::get_lock() const
{
return lock_;
}
int DbLockNotGrantedException::get_index() const
{
return index_;
}
////////////////////////////////////////////////////////////////////////
// //
// DbRepHandleDeadException //
// //
////////////////////////////////////////////////////////////////////////
DbRepHandleDeadException::~DbRepHandleDeadException() throw()
{
}
DbRepHandleDeadException::DbRepHandleDeadException(const char *description)
: DbException(description, DB_REP_HANDLE_DEAD)
{
}
DbRepHandleDeadException::DbRepHandleDeadException
(const DbRepHandleDeadException &that)
: DbException(that)
{
}
DbRepHandleDeadException
&DbRepHandleDeadException::operator =(const DbRepHandleDeadException &that)
{
if (this != &that)
DbException::operator=(that);
return (*this);
}
////////////////////////////////////////////////////////////////////////
// //
// DbRunRecoveryException //
// //
////////////////////////////////////////////////////////////////////////
DbRunRecoveryException::~DbRunRecoveryException() throw()
{
}
DbRunRecoveryException::DbRunRecoveryException(const char *description)
: DbException(description, DB_RUNRECOVERY)
{
}
DbRunRecoveryException::DbRunRecoveryException
(const DbRunRecoveryException &that)
: DbException(that)
{
}
DbRunRecoveryException
&DbRunRecoveryException::operator =(const DbRunRecoveryException &that)
{
if (this != &that)
DbException::operator=(that);
return (*this);
}

View file

@ -1,43 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_lock.cpp,v 12.1 2005/06/16 20:20:59 bostic Exp $
*/
#include "db_config.h"
#include <errno.h>
#include <string.h>
#include "db_cxx.h"
#include "dbinc/cxx_int.h"
////////////////////////////////////////////////////////////////////////
// //
// DbLock //
// //
////////////////////////////////////////////////////////////////////////
DbLock::DbLock(DB_LOCK value)
: lock_(value)
{
}
DbLock::DbLock()
{
memset(&lock_, 0, sizeof(DB_LOCK));
}
DbLock::DbLock(const DbLock &that)
: lock_(that.lock_)
{
}
DbLock &DbLock::operator = (const DbLock &that)
{
lock_ = that.lock_;
return (*this);
}

View file

@ -1,66 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_logc.cpp,v 12.1 2005/06/16 20:21:00 bostic Exp $
*/
#include "db_config.h"
#include <errno.h>
#include <string.h>
#include "db_cxx.h"
#include "dbinc/cxx_int.h"
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc_auto/db_auto.h"
#include "dbinc_auto/crdel_auto.h"
#include "dbinc/db_dispatch.h"
#include "dbinc_auto/db_ext.h"
#include "dbinc_auto/common_ext.h"
// It's private, and should never be called,
// but some compilers need it resolved
//
DbLogc::~DbLogc()
{
}
// The name _flags prevents a name clash with __db_log_cursor::flags
int DbLogc::close(u_int32_t _flags)
{
DB_LOGC *logc = this;
int ret;
DbEnv *dbenv2 = DbEnv::get_DbEnv(logc->dbenv);
ret = logc->close(logc, _flags);
if (!DB_RETOK_STD(ret))
DB_ERROR(dbenv2, "DbLogc::close", ret, ON_ERROR_UNKNOWN);
return (ret);
}
// The name _flags prevents a name clash with __db_log_cursor::flags
int DbLogc::get(DbLsn *lsn, Dbt *data, u_int32_t _flags)
{
DB_LOGC *logc = this;
int ret;
ret = logc->get(logc, lsn, data, _flags);
if (!DB_RETOK_LGGET(ret)) {
if (ret == DB_BUFFER_SMALL)
DB_ERROR_DBT(DbEnv::get_DbEnv(logc->dbenv),
"DbLogc::get", data, ON_ERROR_UNKNOWN);
else
DB_ERROR(DbEnv::get_DbEnv(logc->dbenv),
"DbLogc::get", ret, ON_ERROR_UNKNOWN);
}
return (ret);
}

View file

@ -1,129 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_mpool.cpp,v 12.1 2005/06/16 20:21:02 bostic Exp $
*/
#include "db_config.h"
#include <errno.h>
#include "db_cxx.h"
#include "dbinc/cxx_int.h"
#include "db_int.h"
// Helper macros for simple methods that pass through to the
// underlying C method. It may return an error or raise an exception.
// Note this macro expects that input _argspec is an argument
// list element (e.g., "char *arg") and that _arglist is the arguments
// that should be passed through to the C method (e.g., "(mpf, arg)")
//
#define DB_MPOOLFILE_METHOD(_name, _argspec, _arglist, _retok) \
int DbMpoolFile::_name _argspec \
{ \
int ret; \
DB_MPOOLFILE *mpf = unwrap(this); \
\
if (mpf == NULL) \
ret = EINVAL; \
else \
ret = mpf->_name _arglist; \
if (!_retok(ret)) \
DB_ERROR(DbEnv::get_DbEnv(mpf->dbenv), \
"DbMpoolFile::"#_name, ret, ON_ERROR_UNKNOWN); \
return (ret); \
}
#define DB_MPOOLFILE_METHOD_VOID(_name, _argspec, _arglist) \
void DbMpoolFile::_name _argspec \
{ \
DB_MPOOLFILE *mpf = unwrap(this); \
\
mpf->_name _arglist; \
}
////////////////////////////////////////////////////////////////////////
// //
// DbMpoolFile //
// //
////////////////////////////////////////////////////////////////////////
DbMpoolFile::DbMpoolFile()
: imp_(0)
{
}
DbMpoolFile::~DbMpoolFile()
{
}
int DbMpoolFile::close(u_int32_t flags)
{
DB_MPOOLFILE *mpf = unwrap(this);
int ret;
DbEnv *dbenv = DbEnv::get_DbEnv(mpf->dbenv);
if (mpf == NULL)
ret = EINVAL;
else
ret = mpf->close(mpf, flags);
imp_ = 0; // extra safety
// This may seem weird, but is legal as long as we don't access
// any data before returning.
delete this;
if (!DB_RETOK_STD(ret))
DB_ERROR(dbenv, "DbMpoolFile::close", ret, ON_ERROR_UNKNOWN);
return (ret);
}
DB_MPOOLFILE_METHOD(get, (db_pgno_t *pgnoaddr, u_int32_t flags, void *pagep),
(mpf, pgnoaddr, flags, pagep), DB_RETOK_MPGET)
DB_MPOOLFILE_METHOD(open,
(const char *file, u_int32_t flags, int mode, size_t pagesize),
(mpf, file, flags, mode, pagesize), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(put, (void *pgaddr, u_int32_t flags),
(mpf, pgaddr, flags), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(set, (void *pgaddr, u_int32_t flags),
(mpf, pgaddr, flags), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(get_clear_len, (u_int32_t *lenp),
(mpf, lenp), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(set_clear_len, (u_int32_t len),
(mpf, len), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(get_fileid, (u_int8_t *fileid),
(mpf, fileid), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(set_fileid, (u_int8_t *fileid),
(mpf, fileid), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(get_flags, (u_int32_t *flagsp),
(mpf, flagsp), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(set_flags, (u_int32_t flags, int onoff),
(mpf, flags, onoff), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(get_ftype, (int *ftypep),
(mpf, ftypep), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(set_ftype, (int ftype),
(mpf, ftype), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(get_lsn_offset, (int32_t *offsetp),
(mpf, offsetp), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(set_lsn_offset, (int32_t offset),
(mpf, offset), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(get_maxsize, (u_int32_t *gbytesp, u_int32_t *bytesp),
(mpf, gbytesp, bytesp), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(set_maxsize, (u_int32_t gbytes, u_int32_t bytes),
(mpf, gbytes, bytes), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(get_pgcookie, (DBT *dbt),
(mpf, dbt), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(set_pgcookie, (DBT *dbt),
(mpf, dbt), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(get_priority, (DB_CACHE_PRIORITY *priorityp),
(mpf, priorityp), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(set_priority, (DB_CACHE_PRIORITY priority),
(mpf, priority), DB_RETOK_STD)
DB_MPOOLFILE_METHOD(sync, (),
(mpf), DB_RETOK_STD)

View file

@ -1,65 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_multi.cpp,v 12.3 2005/09/30 07:40:20 mjc Exp $
*/
#include "db_config.h"
#include "db_cxx.h"
DbMultipleIterator::DbMultipleIterator(const Dbt &dbt)
: data_((u_int8_t*)dbt.get_data()),
p_((u_int32_t*)(data_ + dbt.get_size() - sizeof(u_int32_t)))
{
}
bool DbMultipleDataIterator::next(Dbt &data)
{
if (*p_ == (u_int32_t)-1) {
data.set_data(0);
data.set_size(0);
p_ = 0;
} else {
data.set_data(data_ + *p_--);
data.set_size(*p_--);
if (data.get_size() == 0 && data.get_data() == data_)
data.set_data(0);
}
return (p_ != 0);
}
bool DbMultipleKeyDataIterator::next(Dbt &key, Dbt &data)
{
if (*p_ == (u_int32_t)-1) {
key.set_data(0);
key.set_size(0);
data.set_data(0);
data.set_size(0);
p_ = 0;
} else {
key.set_data(data_ + *p_--);
key.set_size(*p_--);
data.set_data(data_ + *p_--);
data.set_size(*p_--);
}
return (p_ != 0);
}
bool DbMultipleRecnoDataIterator::next(db_recno_t &recno, Dbt &data)
{
if (*p_ == (u_int32_t)0) {
recno = 0;
data.set_data(0);
data.set_size(0);
p_ = 0;
} else {
recno = *p_--;
data.set_data(data_ + *p_--);
data.set_size(*p_--);
}
return (p_ != 0);
}

View file

@ -1,113 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_seq.cpp,v 12.2 2005/10/13 20:49:47 bostic Exp $
*/
#include "db_config.h"
#include <errno.h>
#include <string.h>
#include "db_cxx.h"
#include "dbinc/cxx_int.h"
#include "db_int.h"
// Helper macro for simple methods that pass through to the
// underlying C method. It may return an error or raise an exception.
// Note this macro expects that input _argspec is an argument
// list element (e.g., "char *arg") and that _arglist is the arguments
// that should be passed through to the C method (e.g., "(db, arg)")
//
#define DBSEQ_METHOD(_name, _argspec, _arglist, _destructor) \
int DbSequence::_name _argspec \
{ \
int ret; \
DB_SEQUENCE *seq = unwrap(this); \
DbEnv *dbenv = DbEnv::get_DbEnv(seq->seq_dbp->dbenv); \
\
ret = seq->_name _arglist; \
if (_destructor) \
imp_ = 0; \
if (!DB_RETOK_STD(ret)) \
DB_ERROR(dbenv, \
"DbSequence::" # _name, ret, ON_ERROR_UNKNOWN); \
return (ret); \
}
DbSequence::DbSequence(Db *db, u_int32_t flags)
: imp_(0)
{
DB_SEQUENCE *seq;
int ret;
if ((ret = db_sequence_create(&seq, unwrap(db), flags)) != 0)
DB_ERROR(db->get_env(), "DbSequence::DbSequence", ret,
ON_ERROR_UNKNOWN);
else {
imp_ = seq;
seq->api_internal = this;
}
}
DbSequence::DbSequence(DB_SEQUENCE *seq)
: imp_(seq)
{
seq->api_internal = this;
}
DbSequence::~DbSequence()
{
DB_SEQUENCE *seq;
seq = unwrap(this);
if (seq != NULL)
(void)seq->close(seq, 0);
}
DBSEQ_METHOD(open, (DbTxn *txnid, Dbt *key, u_int32_t flags),
(seq, unwrap(txnid), key, flags), 0)
DBSEQ_METHOD(initial_value, (db_seq_t value), (seq, value), 0)
DBSEQ_METHOD(close, (u_int32_t flags), (seq, flags), 1)
DBSEQ_METHOD(remove, (DbTxn *txnid, u_int32_t flags),
(seq, unwrap(txnid), flags), 1)
DBSEQ_METHOD(stat, (DB_SEQUENCE_STAT **sp, u_int32_t flags),
(seq, sp, flags), 0)
DBSEQ_METHOD(stat_print, (u_int32_t flags), (seq, flags), 0)
DBSEQ_METHOD(get,
(DbTxn *txnid, int32_t delta, db_seq_t *retp, u_int32_t flags),
(seq, unwrap(txnid), delta, retp, flags), 0)
DBSEQ_METHOD(get_cachesize, (int32_t *sizep), (seq, sizep), 0)
DBSEQ_METHOD(set_cachesize, (int32_t size), (seq, size), 0)
DBSEQ_METHOD(get_flags, (u_int32_t *flagsp), (seq, flagsp), 0)
DBSEQ_METHOD(set_flags, (u_int32_t flags), (seq, flags), 0)
DBSEQ_METHOD(get_range, (db_seq_t *minp, db_seq_t *maxp), (seq, minp, maxp), 0)
DBSEQ_METHOD(set_range, (db_seq_t min, db_seq_t max), (seq, min, max), 0)
Db *DbSequence::get_db()
{
DB_SEQUENCE *seq = unwrap(this);
DB *db;
(void)seq->get_db(seq, &db);
return Db::get_Db(db);
}
Dbt *DbSequence::get_key()
{
DB_SEQUENCE *seq = unwrap(this);
memset(&key_, 0, sizeof (DBT));
(void)seq->get_key(seq, &key_);
return Dbt::get_Dbt(&key_);
}
// static method
DbSequence *DbSequence::wrap_DB_SEQUENCE(DB_SEQUENCE *seq)
{
DbSequence *wrapped_seq = get_DbSequence(seq);
return (wrapped_seq != NULL) ? wrapped_seq : new DbSequence(seq);
}

View file

@ -1,81 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_txn.cpp,v 12.2 2005/06/16 20:21:03 bostic Exp $
*/
#include "db_config.h"
#include <errno.h>
#include "db_cxx.h"
#include "dbinc/cxx_int.h"
#include "db_int.h"
#include "dbinc/txn.h"
// Helper macro for simple methods that pass through to the
// underlying C method. It may return an error or raise an exception.
// Note this macro expects that input _argspec is an argument
// list element (e.g., "char *arg") and that _arglist is the arguments
// that should be passed through to the C method (e.g., "(db, arg)")
//
#define DBTXN_METHOD(_name, _delete, _argspec, _arglist) \
int DbTxn::_name _argspec \
{ \
int ret; \
DB_TXN *txn = unwrap(this); \
DbEnv *dbenv = DbEnv::get_DbEnv(txn->mgrp->dbenv); \
\
ret = txn->_name _arglist; \
/* Weird, but safe if we don't access this again. */ \
if (_delete) \
delete this; \
if (!DB_RETOK_STD(ret)) \
DB_ERROR(dbenv, "DbTxn::" # _name, ret, ON_ERROR_UNKNOWN); \
return (ret); \
}
// private constructor, never called but needed by some C++ linkers
DbTxn::DbTxn()
: imp_(0)
{
}
DbTxn::DbTxn(DB_TXN *txn)
: imp_(txn)
{
txn->api_internal = this;
}
DbTxn::~DbTxn()
{
}
DBTXN_METHOD(abort, 1, (), (txn))
DBTXN_METHOD(commit, 1, (u_int32_t flags), (txn, flags))
DBTXN_METHOD(discard, 1, (u_int32_t flags), (txn, flags))
u_int32_t DbTxn::id()
{
DB_TXN *txn;
txn = unwrap(this);
return (txn->id(txn)); // no error
}
DBTXN_METHOD(get_name, 0, (const char **namep), (txn, namep))
DBTXN_METHOD(prepare, 0, (u_int8_t *gid), (txn, gid))
DBTXN_METHOD(set_name, 0, (const char *name), (txn, name))
DBTXN_METHOD(set_timeout, 0, (db_timeout_t timeout, u_int32_t flags),
(txn, timeout, flags))
// static method
DbTxn *DbTxn::wrap_DB_TXN(DB_TXN *txn)
{
DbTxn *wrapped_txn = get_DbTxn(txn);
return (wrapped_txn != NULL) ? wrapped_txn : new DbTxn(txn);
}

View file

@ -1,80 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: crdel.src,v 12.2 2005/09/28 17:44:18 margo Exp $
*/
PREFIX __crdel
DBPRIVATE
INCLUDE #ifndef NO_SYSTEM_INCLUDES
INCLUDE #include <sys/types.h>
INCLUDE
INCLUDE #include <ctype.h>
INCLUDE #include <string.h>
INCLUDE #endif
INCLUDE
INCLUDE #include "db_int.h"
INCLUDE #include "dbinc/crypto.h"
INCLUDE #include "dbinc/db_page.h"
INCLUDE #include "dbinc/db_dispatch.h"
INCLUDE #include "dbinc/db_am.h"
INCLUDE #include "dbinc/log.h"
INCLUDE #include "dbinc/txn.h"
INCLUDE
/*
* Metasub: log the creation of a subdatabase meta data page.
*
* fileid: identifies the file being acted upon.
* pgno: page number on which to write this meta-data page
* page: the actual meta-data page
* lsn: lsn of the page.
*/
BEGIN metasub 142
DB fileid int32_t ld
ARG pgno db_pgno_t lu
PGDBT page DBT s
POINTER lsn DB_LSN * lu
END
/*
* Inmem_create: Log the creation of an in-memory database.
*
* name: Name of the database
* fid: File id of the database
*/
BEGIN inmem_create 138
ARG fileid int32_t ld
DBT name DBT s
DBT fid DBT s
ARG pgsize u_int32_t lu
END
/*
* Inmem_rename: Log the renaming of an in-memory only database.
*
* oldname: database's starting name
* newname: database's ending name
* fid: fileid
*/
BEGIN inmem_rename 139
DBT oldname DBT s
DBT newname DBT s
DBT fid DBT s
END
/*
* Inmem_remove: Log the removal of an in-memory only database.
*
* name: database's ending name
* fid: fileid
*/
BEGIN inmem_remove 140
DBT name DBT s
DBT fid DBT s
END

View file

@ -1,294 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: crdel_rec.c,v 12.6 2005/10/20 18:57:04 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/fop.h"
#include "dbinc/hash.h"
#include "dbinc/log.h"
#include "dbinc/mp.h"
#include "dbinc/txn.h"
/*
* __crdel_metasub_recover --
* Recovery function for metasub.
*
* PUBLIC: int __crdel_metasub_recover
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
int
__crdel_metasub_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__crdel_metasub_args *argp;
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
int cmp_p, modified, ret;
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__crdel_metasub_print);
REC_INTRO(__crdel_metasub_read, 0, 0);
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
/* If this is an in-memory file, this might be OK. */
if (F_ISSET(file_dbp, DB_AM_INMEM) && (ret = __memp_fget(mpf,
&argp->pgno, DB_MPOOL_CREATE, &pagep)) == 0)
LSN_NOT_LOGGED(LSN(pagep));
else {
*lsnp = argp->prev_lsn;
ret = 0;
goto out;
}
}
modified = 0;
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) {
memcpy(pagep, argp->page.data, argp->page.size);
LSN(pagep) = *lsnp;
modified = 1;
/*
* If this was an in-memory database and we are re-creating
* and this is the meta-data page, then we need to set up a
* bunch of fields in the dbo as well.
*/
if (F_ISSET(file_dbp, DB_AM_INMEM) &&
argp->pgno == PGNO_BASE_MD &&
(ret = __db_meta_setup(file_dbp->dbenv,
file_dbp, file_dbp->dname, (DBMETA *)pagep, 0, 1)) != 0)
goto out;
} else if (DB_UNDO(op)) {
/*
* We want to undo this page creation. The page creation
* happened in two parts. First, we called __bam_new which
* was logged separately. Then we wrote the meta-data onto
* the page. So long as we restore the LSN, then the recovery
* for __bam_new will do everything else.
*
* Don't bother checking the lsn on the page. If we are
* rolling back the next thing is that this page will get
* freed. Opening the subdb will have reinitialized the
* page, but not the lsn.
*/
LSN(pagep) = argp->lsn;
modified = 1;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
out: if (pagep != NULL)
(void)__memp_fput(mpf, pagep, 0);
REC_CLOSE;
}
/*
* __crdel_inmem_create_recover --
* Recovery function for inmem_create.
*
* PUBLIC: int __crdel_inmem_create_recover
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
int
__crdel_inmem_create_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
DB *dbp;
__crdel_inmem_create_args *argp;
int do_close, ret, t_ret;
COMPQUIET(info, NULL);
dbp = NULL;
do_close = 0;
REC_PRINT(__crdel_inmem_create_print);
REC_NOOP_INTRO(__crdel_inmem_create_read);
/* First, see if the DB handle already exists. */
if (argp->fileid == DB_LOGFILEID_INVALID) {
if (DB_REDO(op))
ret = ENOENT;
else
ret = 0;
} else
ret = __dbreg_id_to_db_int(dbenv,
argp->txnid, &dbp, argp->fileid, 0, 0);
if (DB_REDO(op)) {
/*
* If the dbreg failed, that means that we're creating a
* tmp file.
*/
if (ret != 0) {
if ((ret = db_create(&dbp, dbenv, 0)) != 0)
goto out;
F_SET(dbp, DB_AM_RECOVER | DB_AM_INMEM);
memcpy(dbp->fileid, argp->fid.data, DB_FILE_ID_LEN);
if (((ret = __os_strdup(dbenv,
argp->name.data, &dbp->dname)) != 0))
goto out;
/*
* This DBP is never going to be entered into the
* dbentry table, so if we leave it open here,
* then we're going to lose it.
*/
do_close = 1;
}
/* Now, set the fileid. */
memcpy(dbp->fileid, argp->fid.data, argp->fid.size);
if ((ret = __memp_set_fileid(dbp->mpf, dbp->fileid)) != 0)
goto out;
dbp->preserve_fid = 1;
MAKE_INMEM(dbp);
if ((ret = __db_dbenv_setup(dbp,
NULL, NULL, argp->name.data, TXN_INVALID, 0)) != 0)
goto out;
ret = __db_dbenv_mpool(dbp, argp->name.data, 0);
if (ret == ENOENT) {
dbp->pgsize = argp->pgsize;
if ((ret = __db_dbenv_mpool(dbp,
argp->name.data, DB_CREATE)) != 0)
goto out;
} else if (ret != 0)
goto out;
}
if (DB_UNDO(op)) {
if (ret == 0)
ret = __memp_nameop(dbenv, argp->fid.data, NULL,
(const char *)argp->name.data, NULL, 1);
if (ret == ENOENT || ret == DB_DELETED)
ret = 0;
else
goto out;
}
*lsnp = argp->prev_lsn;
out: if (dbp != NULL) {
t_ret = 0;
if (DB_UNDO(op))
t_ret = __db_refresh(dbp, NULL, DB_NOSYNC, NULL, 0);
else if (do_close || ret != 0)
t_ret = __db_close(dbp, NULL, DB_NOSYNC);
if (t_ret != 0 && ret == 0)
ret = t_ret;
}
REC_NOOP_CLOSE;
}
/*
* __crdel_inmem_rename_recover --
* Recovery function for inmem_rename.
*
* PUBLIC: int __crdel_inmem_rename_recover
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
int
__crdel_inmem_rename_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__crdel_inmem_rename_args *argp;
u_int8_t *fileid;
int ret;
COMPQUIET(info, NULL);
REC_PRINT(__crdel_inmem_rename_print);
REC_NOOP_INTRO(__crdel_inmem_rename_read);
fileid = argp->fid.data;
/* Void out errors because the files may or may not still exist. */
if (DB_REDO(op))
(void)__memp_nameop(dbenv, fileid,
(const char *)argp->newname.data,
(const char *)argp->oldname.data,
(const char *)argp->newname.data, 1);
if (DB_UNDO(op))
(void)__memp_nameop(dbenv, fileid,
(const char *)argp->oldname.data,
(const char *)argp->newname.data,
(const char *)argp->oldname.data, 1);
*lsnp = argp->prev_lsn;
ret = 0;
REC_NOOP_CLOSE;
}
/*
* __crdel_inmem_remove_recover --
* Recovery function for inmem_remove.
*
* PUBLIC: int __crdel_inmem_remove_recover
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
int
__crdel_inmem_remove_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__crdel_inmem_remove_args *argp;
int ret;
COMPQUIET(info, NULL);
REC_PRINT(__crdel_inmem_remove_print);
REC_NOOP_INTRO(__crdel_inmem_remove_read);
/*
* Since removes are delayed; there is no undo for a remove; only redo.
* The remove may fail, which is OK.
*/
if (DB_REDO(op)) {
(void)__memp_nameop(dbenv,
argp->fid.data, NULL, argp->name.data, NULL, 1);
}
*lsnp = argp->prev_lsn;
ret = 0;
REC_NOOP_CLOSE;
}

File diff suppressed because it is too large Load diff

View file

@ -1,259 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db.src,v 12.2 2005/08/08 03:37:06 ubell Exp $
*/
PREFIX __db
DBPRIVATE
INCLUDE #ifndef NO_SYSTEM_INCLUDES
INCLUDE #include <sys/types.h>
INCLUDE
INCLUDE #include <ctype.h>
INCLUDE #include <string.h>
INCLUDE #endif
INCLUDE
INCLUDE #include "db_int.h"
INCLUDE #include "dbinc/crypto.h"
INCLUDE #include "dbinc/db_page.h"
INCLUDE #include "dbinc/db_dispatch.h"
INCLUDE #include "dbinc/db_am.h"
INCLUDE #include "dbinc/log.h"
INCLUDE #include "dbinc/txn.h"
INCLUDE
/*
* 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 41
ARG opcode u_int32_t lu
DB fileid int32_t ld
ARG pgno db_pgno_t lu
ARG indx u_int32_t lu
ARG nbytes u_int32_t lu
PGDBT hdr DBT s
DBT dbt 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 43
ARG opcode u_int32_t lu
DB fileid int32_t ld
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 44
DB fileid int32_t ld
ARG pgno db_pgno_t lu
ARG adjust int32_t ld
POINTER lsn 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 47
DBT op DBT s
ARG fileid int32_t ld
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 48
DB fileid int32_t ld
ARG pgno db_pgno_t lu
POINTER prevlsn DB_LSN * lu
END
/*
* pg_alloc: used to record allocating a new page.
*
* meta_lsn: the meta-data page's original lsn.
* meta_pgno the meta-data page number.
* page_lsn: the allocated page's original lsn.
* pgno: the page allocated.
* ptype: the type of the page allocated.
* next: the next page on the free list.
* last_pgno: the last page in the file after this op.
*/
BEGIN pg_alloc 49
DB fileid int32_t ld
POINTER meta_lsn DB_LSN * lu
ARG meta_pgno db_pgno_t 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
ARG last_pgno db_pgno_t lu
END
/*
* pg_free: used to record freeing a page.
*
* pgno: the page being freed.
* meta_lsn: the meta-data page's original lsn.
* meta_pgno: the meta-data page number.
* header: the header from the free'd page.
* next: the previous next pointer on the metadata page.
* last_pgno: the last page in the file before this op.
*/
BEGIN pg_free 50
DB fileid int32_t ld
ARG pgno db_pgno_t lu
POINTER meta_lsn DB_LSN * lu
ARG meta_pgno db_pgno_t lu
PGDBT header DBT s
ARG next db_pgno_t lu
ARG last_pgno db_pgno_t lu
END
/*
* cksum --
* This log record is written when we're unable to checksum a page,
* before returning DB_RUNRECOVERY. This log record causes normal
* recovery to itself return DB_RUNRECOVERY, as only catastrophic
* recovery can fix things.
*/
BEGIN cksum 51
END
/*
* pg_freedata: used to record freeing a page with data on it.
*
* pgno: the page being freed.
* meta_lsn: the meta-data page's original lsn.
* meta_pgno: the meta-data page number.
* header: the header and index entries from the free'd page.
* data: the data from the free'd page.
* next: the previous next pointer on the metadata page.
* last_pgno: the last page in the file before this op.
*/
BEGIN pg_freedata 52
DB fileid int32_t ld
ARG pgno db_pgno_t lu
POINTER meta_lsn DB_LSN * lu
ARG meta_pgno db_pgno_t lu
PGDBT header DBT s
ARG next db_pgno_t lu
ARG last_pgno db_pgno_t lu
PGDBT data DBT s
END
/*
* pg_prepare: used to record an aborted page in a prepared transaction.
*
* pgno: the page being freed.
*/
BEGIN pg_prepare 53
DB fileid int32_t ld
ARG pgno db_pgno_t lu
END
/*
* pg_new: used to record a new page put on the free list.
*
* pgno: the page being freed.
* meta_lsn: the meta-data page's original lsn.
* meta_pgno: the meta-data page number.
* header: the header from the free'd page.
* next: the previous next pointer on the metadata page.
*/
BEGIN pg_new 54
DB fileid int32_t ld
ARG pgno db_pgno_t lu
POINTER meta_lsn DB_LSN * lu
ARG meta_pgno db_pgno_t lu
PGDBT header DBT s
ARG next db_pgno_t lu
END
/*
* pg_init: used to reinitialize a page during truncate.
*
* pgno: the page being initialized.
* header: the header from the page.
* data: data that used to be on the page.
*/
BEGIN pg_init 60
DB fileid int32_t ld
ARG pgno db_pgno_t lu
PGDBT header DBT s
PGDBT data DBT s
END
/*
* pg_sort: sort the free list
*
* meta: meta page number
* meta_lsn: lsn on meta page.
* last_free: page number of new last free page.
* last_lsn; lsn of last free page.
* last_pgno: current last page number.
* list: list of pages and lsns to sort.
*/
BEGIN pg_sort 61
DB fileid int32_t ld
ARG meta db_pgno_t lu
POINTER meta_lsn DB_LSN * lu
ARG last_free db_pgno_t lu
POINTER last_lsn DB_LSN * lu
ARG last_pgno db_pgno_t lu
DBT list DBT s
END

View file

@ -1,904 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1998-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_am.c,v 12.12 2005/11/01 00:44:09 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/btree.h"
#include "dbinc/hash.h"
#include "dbinc/lock.h"
#include "dbinc/log.h"
#include "dbinc/mp.h"
#include "dbinc/qam.h"
static int __db_append_primary __P((DBC *, DBT *, DBT *));
static int __db_secondary_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
/*
* __db_cursor_int --
* Internal routine to create a cursor.
*
* PUBLIC: int __db_cursor_int
* PUBLIC: __P((DB *, DB_TXN *, DBTYPE, db_pgno_t, int, u_int32_t, DBC **));
*/
int
__db_cursor_int(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
DB *dbp;
DB_TXN *txn;
DBTYPE dbtype;
db_pgno_t root;
int is_opd;
u_int32_t lockerid;
DBC **dbcp;
{
DBC *dbc;
DBC_INTERNAL *cp;
DB_ENV *dbenv;
db_threadid_t tid;
int allocated, ret;
pid_t pid;
dbenv = dbp->dbenv;
allocated = 0;
/*
* If dbcp is non-NULL it is assumed to point to an area to initialize
* as a cursor.
*
* Take one from the free list if it's available. Take only the
* right type. With off page dups we may have different kinds
* of cursors on the queue for a single database.
*/
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&dbp->free_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
if (dbtype == dbc->dbtype) {
TAILQ_REMOVE(&dbp->free_queue, dbc, links);
F_CLR(dbc, ~DBC_OWN_LID);
break;
}
MUTEX_UNLOCK(dbenv, dbp->mutex);
if (dbc == NULL) {
if ((ret = __os_calloc(dbenv, 1, sizeof(DBC), &dbc)) != 0)
return (ret);
allocated = 1;
dbc->flags = 0;
dbc->dbp = dbp;
/* Set up locking information. */
if (LOCKING_ON(dbenv)) {
/*
* If we are not threaded, we share a locker ID among
* all cursors opened in the environment handle,
* allocating one if this is the first cursor.
*
* This relies on the fact that non-threaded DB handles
* always have non-threaded environment handles, since
* we set DB_THREAD on DB handles created with threaded
* environment handles.
*/
if (!DB_IS_THREADED(dbp)) {
if (dbp->dbenv->env_lref == NULL &&
(ret = __lock_id(dbenv, NULL,
(DB_LOCKER **)&dbp->dbenv->env_lref)) != 0)
goto err;
dbc->lref = dbp->dbenv->env_lref;
} else {
if ((ret = __lock_id(dbenv, NULL,
(DB_LOCKER **)&dbc->lref)) != 0)
goto err;
F_SET(dbc, DBC_OWN_LID);
}
/*
* In CDB, secondary indices should share a lock file
* ID with the primary; otherwise we're susceptible
* to deadlocks. We also use __db_cursor_int rather
* than __db_cursor to create secondary update cursors
* in c_put and c_del; these won't acquire a new lock.
*
* !!!
* Since this is in the one-time cursor allocation
* code, we need to be sure to destroy, not just
* close, all cursors in the secondary when we
* associate.
*/
if (CDB_LOCKING(dbenv) &&
F_ISSET(dbp, DB_AM_SECONDARY))
memcpy(dbc->lock.fileid,
dbp->s_primary->fileid, DB_FILE_ID_LEN);
else
memcpy(dbc->lock.fileid,
dbp->fileid, DB_FILE_ID_LEN);
if (CDB_LOCKING(dbenv)) {
if (F_ISSET(dbenv, DB_ENV_CDB_ALLDB)) {
/*
* If we are doing a single lock per
* environment, set up the global
* lock object just like we do to
* single thread creates.
*/
DB_ASSERT(sizeof(db_pgno_t) ==
sizeof(u_int32_t));
dbc->lock_dbt.size = sizeof(u_int32_t);
dbc->lock_dbt.data = &dbc->lock.pgno;
dbc->lock.pgno = 0;
} else {
dbc->lock_dbt.size = DB_FILE_ID_LEN;
dbc->lock_dbt.data = dbc->lock.fileid;
}
} else {
dbc->lock.type = DB_PAGE_LOCK;
dbc->lock_dbt.size = sizeof(dbc->lock);
dbc->lock_dbt.data = &dbc->lock;
}
}
/* Init the DBC internal structure. */
switch (dbtype) {
case DB_BTREE:
case DB_RECNO:
if ((ret = __bam_c_init(dbc, dbtype)) != 0)
goto err;
break;
case DB_HASH:
if ((ret = __ham_c_init(dbc)) != 0)
goto err;
break;
case DB_QUEUE:
if ((ret = __qam_c_init(dbc)) != 0)
goto err;
break;
case DB_UNKNOWN:
default:
ret = __db_unknown_type(dbenv, "DB->cursor", dbtype);
goto err;
}
cp = dbc->internal;
}
/* Refresh the DBC structure. */
dbc->dbtype = dbtype;
RESET_RET_MEM(dbc);
if ((dbc->txn = txn) != NULL)
dbc->locker = txn->txnid;
else if (LOCKING_ON(dbenv)) {
/*
* There are certain cases in which we want to create a
* new cursor with a particular locker ID that is known
* to be the same as (and thus not conflict with) an
* open cursor.
*
* The most obvious case is cursor duplication; when we
* call DBC->c_dup or __db_c_idup, we want to use the original
* cursor's locker ID.
*
* Another case is when updating secondary indices. Standard
* CDB locking would mean that we might block ourself: we need
* to open an update cursor in the secondary while an update
* cursor in the primary is open, and when the secondary and
* primary are subdatabases or we're using env-wide locking,
* this is disastrous.
*
* In these cases, our caller will pass a nonzero locker
* ID into this function. Use this locker ID instead of
* the default as the locker ID for our new cursor.
*/
if (lockerid != DB_LOCK_INVALIDID)
dbc->locker = lockerid;
else {
/*
* If we are threaded then we need to set the
* proper thread id into the locker.
*/
if (DB_IS_THREADED(dbp)) {
dbenv->thread_id(dbenv, &pid, &tid);
__lock_set_thread_id(
(DB_LOCKER *)dbc->lref, pid, tid);
}
dbc->locker = ((DB_LOCKER *)dbc->lref)->id;
}
}
/*
* These fields change when we are used as a secondary index, so
* if the DB is a secondary, make sure they're set properly just
* in case we opened some cursors before we were associated.
*
* __db_c_get is used by all access methods, so this should be safe.
*/
if (F_ISSET(dbp, DB_AM_SECONDARY))
dbc->c_get = __db_c_secondary_get_pp;
if (is_opd)
F_SET(dbc, DBC_OPD);
if (F_ISSET(dbp, DB_AM_RECOVER))
F_SET(dbc, DBC_RECOVER);
if (F_ISSET(dbp, DB_AM_COMPENSATE))
F_SET(dbc, DBC_COMPENSATE);
/* Refresh the DBC internal structure. */
cp = dbc->internal;
cp->opd = NULL;
cp->indx = 0;
cp->page = NULL;
cp->pgno = PGNO_INVALID;
cp->root = root;
switch (dbtype) {
case DB_BTREE:
case DB_RECNO:
if ((ret = __bam_c_refresh(dbc)) != 0)
goto err;
break;
case DB_HASH:
case DB_QUEUE:
break;
case DB_UNKNOWN:
default:
ret = __db_unknown_type(dbenv, "DB->cursor", dbp->type);
goto err;
}
/*
* The transaction keeps track of how many cursors were opened within
* it to catch application errors where the cursor isn't closed when
* the transaction is resolved.
*/
if (txn != NULL)
++txn->cursors;
MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_INSERT_TAIL(&dbp->active_queue, dbc, links);
F_SET(dbc, DBC_ACTIVE);
MUTEX_UNLOCK(dbenv, dbp->mutex);
*dbcp = dbc;
return (0);
err: if (allocated)
__os_free(dbenv, dbc);
return (ret);
}
/*
* __db_put --
* Store a key/data pair.
*
* PUBLIC: int __db_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
*/
int
__db_put(dbp, txn, key, data, flags)
DB *dbp;
DB_TXN *txn;
DBT *key, *data;
u_int32_t flags;
{
DBC *dbc;
DBT tdata;
DB_ENV *dbenv;
int ret, t_ret;
dbenv = dbp->dbenv;
if ((ret = __db_cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
return (ret);
DEBUG_LWRITE(dbc, txn, "DB->put", key, data, flags);
SET_RET_MEM(dbc, dbp);
/*
* See the comment in __db_get().
*
* Note that the c_get in the DB_NOOVERWRITE case is safe to
* do with this flag set; if it errors in any way other than
* DB_NOTFOUND, we're going to close the cursor without doing
* anything else, and if it returns DB_NOTFOUND then it's safe
* to do a c_put(DB_KEYLAST) even if an access method moved the
* cursor, since that's not position-dependent.
*/
F_SET(dbc, DBC_TRANSIENT);
switch (flags) {
case DB_APPEND:
/*
* If there is an append callback, the value stored in
* data->data may be replaced and then freed. To avoid
* passing a freed pointer back to the user, just operate
* on a copy of the data DBT.
*/
tdata = *data;
/*
* Append isn't a normal put operation; call the appropriate
* access method's append function.
*/
switch (dbp->type) {
case DB_QUEUE:
if ((ret = __qam_append(dbc, key, &tdata)) != 0)
goto err;
break;
case DB_RECNO:
if ((ret = __ram_append(dbc, key, &tdata)) != 0)
goto err;
break;
case DB_BTREE:
case DB_HASH:
case DB_UNKNOWN:
default:
/* The interface should prevent this. */
DB_ASSERT(
dbp->type == DB_QUEUE || dbp->type == DB_RECNO);
ret = __db_ferr(dbenv, "DB->put", 0);
goto err;
}
/*
* Secondary indices: since we've returned zero from
* an append function, we've just put a record, and done
* so outside __db_c_put. We know we're not a secondary--
* the interface prevents puts on them--but we may be a
* primary. If so, update our secondary indices
* appropriately.
*/
DB_ASSERT(!F_ISSET(dbp, DB_AM_SECONDARY));
if (LIST_FIRST(&dbp->s_secondaries) != NULL)
ret = __db_append_primary(dbc, key, &tdata);
/*
* The append callback, if one exists, may have allocated
* a new tdata.data buffer. If so, free it.
*/
FREE_IF_NEEDED(dbp, &tdata);
/* No need for a cursor put; we're done. */
goto done;
case DB_NOOVERWRITE:
flags = 0;
/*
* Set DB_DBT_USERMEM, this might be a threaded application and
* the flags checking will catch us. We don't want the actual
* data, so request a partial of length 0.
*/
memset(&tdata, 0, sizeof(tdata));
F_SET(&tdata, DB_DBT_USERMEM | DB_DBT_PARTIAL);
/*
* If we're doing page-level locking, set the read-modify-write
* flag, we're going to overwrite immediately.
*/
if ((ret = __db_c_get(dbc, key, &tdata,
DB_SET | (STD_LOCKING(dbc) ? DB_RMW : 0))) == 0)
ret = DB_KEYEXIST;
else if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY)
ret = 0;
break;
default:
/* Fall through to normal cursor put. */
break;
}
if (ret == 0)
ret = __db_c_put(dbc,
key, data, flags == 0 ? DB_KEYLAST : flags);
err:
done: /* Close the cursor. */
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
/*
* __db_del --
* Delete the items referenced by a key.
*
* PUBLIC: int __db_del __P((DB *, DB_TXN *, DBT *, u_int32_t));
*/
int
__db_del(dbp, txn, key, flags)
DB *dbp;
DB_TXN *txn;
DBT *key;
u_int32_t flags;
{
DBC *dbc;
DBT data, lkey;
u_int32_t f_init, f_next;
int ret, t_ret;
/* Allocate a cursor. */
if ((ret = __db_cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
goto err;
DEBUG_LWRITE(dbc, txn, "DB->del", key, NULL, flags);
COMPQUIET(flags, 0);
/*
* Walk a cursor through the key/data pairs, deleting as we go. Set
* the DB_DBT_USERMEM flag, as this might be a threaded application
* and the flags checking will catch us. We don't actually want the
* keys or data, so request a partial of length 0.
*/
memset(&lkey, 0, sizeof(lkey));
F_SET(&lkey, DB_DBT_USERMEM | DB_DBT_PARTIAL);
memset(&data, 0, sizeof(data));
F_SET(&data, DB_DBT_USERMEM | DB_DBT_PARTIAL);
/*
* If locking (and we haven't already acquired CDB locks), set the
* read-modify-write flag.
*/
f_init = DB_SET;
f_next = DB_NEXT_DUP;
if (STD_LOCKING(dbc)) {
f_init |= DB_RMW;
f_next |= DB_RMW;
}
/*
* Optimize the simple cases. For all AMs if we don't have secondaries
* and are not a secondary and there are no dups then we can avoid a
* bunch of overhead. For queue we don't need to fetch the record since
* we delete by direct calculation from the record number.
*
* Hash permits an optimization in DB->del: since on-page duplicates are
* stored in a single HKEYDATA structure, it's possible to delete an
* entire set of them at once, and as the HKEYDATA has to be rebuilt
* and re-put each time it changes, this is much faster than deleting
* the duplicates one by one. Thus, if not pointing at an off-page
* duplicate set, and we're not using secondary indices (in which case
* we'd have to examine the items one by one anyway), let hash do this
* "quick delete".
*
* !!!
* Note that this is the only application-executed delete call in
* Berkeley DB that does not go through the __db_c_del function.
* If anything other than the delete itself (like a secondary index
* update) has to happen there in a particular situation, the
* conditions here should be modified not to use these optimizations.
* The ordinary AM-independent alternative will work just fine;
* it'll just be slower.
*/
if (!F_ISSET(dbp, DB_AM_SECONDARY) &&
LIST_FIRST(&dbp->s_secondaries) == NULL) {
#ifdef HAVE_QUEUE
if (dbp->type == DB_QUEUE) {
ret = __qam_delete(dbc, key);
goto done;
}
#endif
/* Fetch the first record. */
if ((ret = __db_c_get(dbc, key, &data, f_init)) != 0)
goto err;
#ifdef HAVE_HASH
if (dbp->type == DB_HASH && dbc->internal->opd == NULL) {
ret = __ham_quick_delete(dbc);
goto done;
}
#endif
if ((dbp->type == DB_BTREE || dbp->type == DB_RECNO) &&
!F_ISSET(dbp, DB_AM_DUP)) {
ret = dbc->c_am_del(dbc);
goto done;
}
} else if ((ret = __db_c_get(dbc, key, &data, f_init)) != 0)
goto err;
/* Walk through the set of key/data pairs, deleting as we go. */
for (;;) {
if ((ret = __db_c_del(dbc, 0)) != 0)
break;
if ((ret = __db_c_get(dbc, &lkey, &data, f_next)) != 0) {
if (ret == DB_NOTFOUND)
ret = 0;
break;
}
}
done:
err: /* Discard the cursor. */
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
/*
* __db_sync --
* Flush the database cache.
*
* PUBLIC: int __db_sync __P((DB *));
*/
int
__db_sync(dbp)
DB *dbp;
{
int ret, t_ret;
ret = 0;
/* If the database was read-only, we're done. */
if (F_ISSET(dbp, DB_AM_RDONLY))
return (0);
/* If it's a Recno tree, write the backing source text file. */
if (dbp->type == DB_RECNO)
ret = __ram_writeback(dbp);
/* If the database was never backed by a database file, we're done. */
if (F_ISSET(dbp, DB_AM_INMEM))
return (ret);
if (dbp->type == DB_QUEUE)
ret = __qam_sync(dbp);
else
/* Flush any dirty pages from the cache to the backing file. */
if ((t_ret = __memp_fsync(dbp->mpf)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
/*
* __db_associate --
* Associate another database as a secondary index to this one.
*
* PUBLIC: int __db_associate __P((DB *, DB_TXN *, DB *,
* PUBLIC: int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t));
*/
int
__db_associate(dbp, txn, sdbp, callback, flags)
DB *dbp, *sdbp;
DB_TXN *txn;
int (*callback) __P((DB *, const DBT *, const DBT *, DBT *));
u_int32_t flags;
{
DB_ENV *dbenv;
DBC *pdbc, *sdbc;
DBT skey, key, data;
int build, ret, t_ret;
dbenv = dbp->dbenv;
pdbc = sdbc = NULL;
ret = 0;
/*
* Check to see if the secondary is empty -- and thus if we should
* build it -- before we link it in and risk making it show up in other
* threads. Do this first so that the databases remain unassociated on
* error.
*/
build = 0;
if (LF_ISSET(DB_CREATE)) {
if ((ret = __db_cursor(sdbp, txn, &sdbc, 0)) != 0)
goto err;
/*
* We don't care about key or data; we're just doing
* an existence check.
*/
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
F_SET(&key, DB_DBT_PARTIAL | DB_DBT_USERMEM);
F_SET(&data, DB_DBT_PARTIAL | DB_DBT_USERMEM);
if ((ret = __db_c_get(sdbc, &key, &data,
(STD_LOCKING(sdbc) ? DB_RMW : 0) |
DB_FIRST)) == DB_NOTFOUND) {
build = 1;
ret = 0;
}
if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
ret = t_ret;
/* Reset for later error check. */
sdbc = NULL;
if (ret != 0)
goto err;
}
/*
* Set up the database handle as a secondary.
*/
sdbp->s_callback = callback;
sdbp->s_primary = dbp;
sdbp->stored_get = sdbp->get;
sdbp->get = __db_secondary_get;
sdbp->stored_close = sdbp->close;
sdbp->close = __db_secondary_close_pp;
F_SET(sdbp, DB_AM_SECONDARY);
if (LF_ISSET(DB_IMMUTABLE_KEY))
FLD_SET(sdbp->s_assoc_flags, DB_ASSOC_IMMUTABLE_KEY);
/*
* Add the secondary to the list on the primary. Do it here
* so that we see any updates that occur while we're walking
* the primary.
*/
MUTEX_LOCK(dbenv, dbp->mutex);
/* See __db_s_next for an explanation of secondary refcounting. */
DB_ASSERT(sdbp->s_refcnt == 0);
sdbp->s_refcnt = 1;
LIST_INSERT_HEAD(&dbp->s_secondaries, sdbp, s_links);
MUTEX_UNLOCK(dbenv, dbp->mutex);
if (build) {
/*
* We loop through the primary, putting each item we
* find into the new secondary.
*
* If we're using CDB, opening these two cursors puts us
* in a bit of a locking tangle: CDB locks are done on the
* primary, so that we stay deadlock-free, but that means
* that updating the secondary while we have a read cursor
* open on the primary will self-block. To get around this,
* we force the primary cursor to use the same locker ID
* as the secondary, so they won't conflict. This should
* be harmless even if we're not using CDB.
*/
if ((ret = __db_cursor(sdbp, txn, &sdbc,
CDB_LOCKING(sdbp->dbenv) ? DB_WRITECURSOR : 0)) != 0)
goto err;
if ((ret = __db_cursor_int(dbp,
txn, dbp->type, PGNO_INVALID, 0, sdbc->locker, &pdbc)) != 0)
goto err;
/* Lock out other threads, now that we have a locker ID. */
dbp->associate_lid = sdbc->locker;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
while ((ret = __db_c_get(pdbc, &key, &data, DB_NEXT)) == 0) {
memset(&skey, 0, sizeof(DBT));
if ((ret = callback(sdbp, &key, &data, &skey)) != 0) {
if (ret == DB_DONOTINDEX)
continue;
goto err;
}
SWAP_IF_NEEDED(dbp, sdbp, &key);
if ((ret = __db_c_put(sdbc,
&skey, &key, DB_UPDATE_SECONDARY)) != 0) {
FREE_IF_NEEDED(sdbp, &skey);
goto err;
}
SWAP_IF_NEEDED(dbp, sdbp, &key);
FREE_IF_NEEDED(sdbp, &skey);
}
if (ret == DB_NOTFOUND)
ret = 0;
}
err: if (sdbc != NULL && (t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
ret = t_ret;
if (pdbc != NULL && (t_ret = __db_c_close(pdbc)) != 0 && ret == 0)
ret = t_ret;
dbp->associate_lid = DB_LOCK_INVALIDID;
return (ret);
}
/*
* __db_secondary_get --
* This wrapper function for DB->pget() is the DB->get() function
* on a database which has been made into a secondary index.
*/
static int
__db_secondary_get(sdbp, txn, skey, data, flags)
DB *sdbp;
DB_TXN *txn;
DBT *skey, *data;
u_int32_t flags;
{
DB_ASSERT(F_ISSET(sdbp, DB_AM_SECONDARY));
return (__db_pget_pp(sdbp, txn, skey, NULL, data, flags));
}
/*
* __db_secondary_close --
* Wrapper function for DB->close() which we use on secondaries to
* manage refcounting and make sure we don't close them underneath
* a primary that is updating.
*
* PUBLIC: int __db_secondary_close __P((DB *, u_int32_t));
*/
int
__db_secondary_close(sdbp, flags)
DB *sdbp;
u_int32_t flags;
{
DB *primary;
int doclose;
doclose = 0;
primary = sdbp->s_primary;
MUTEX_LOCK(primary->dbenv, primary->mutex);
/*
* Check the refcount--if it was at 1 when we were called, no
* thread is currently updating this secondary through the primary,
* so it's safe to close it for real.
*
* If it's not safe to do the close now, we do nothing; the
* database will actually be closed when the refcount is decremented,
* which can happen in either __db_s_next or __db_s_done.
*/
DB_ASSERT(sdbp->s_refcnt != 0);
if (--sdbp->s_refcnt == 0) {
LIST_REMOVE(sdbp, s_links);
/* We don't want to call close while the mutex is held. */
doclose = 1;
}
MUTEX_UNLOCK(primary->dbenv, primary->mutex);
/*
* sdbp->close is this function; call the real one explicitly if
* need be.
*/
return (doclose ? __db_close(sdbp, NULL, flags) : 0);
}
/*
* __db_append_primary --
* Perform the secondary index updates necessary to put(DB_APPEND)
* a record to a primary database.
*/
static int
__db_append_primary(dbc, key, data)
DBC *dbc;
DBT *key, *data;
{
DB *dbp, *sdbp;
DBC *sdbc, *pdbc;
DBT oldpkey, pkey, pdata, skey;
int cmp, ret, t_ret;
dbp = dbc->dbp;
sdbp = NULL;
ret = 0;
/*
* Worrying about partial appends seems a little like worrying
* about Linear A character encodings. But we support those
* too if your application understands them.
*/
pdbc = NULL;
if (F_ISSET(data, DB_DBT_PARTIAL) || F_ISSET(key, DB_DBT_PARTIAL)) {
/*
* The dbc we were passed is all set to pass things
* back to the user; we can't safely do a call on it.
* Dup the cursor, grab the real data item (we don't
* care what the key is--we've been passed it directly),
* and use that instead of the data DBT we were passed.
*
* Note that we can get away with this simple get because
* an appended item is by definition new, and the
* correctly-constructed full data item from this partial
* put is on the page waiting for us.
*/
if ((ret = __db_c_idup(dbc, &pdbc, DB_POSITION)) != 0)
return (ret);
memset(&pkey, 0, sizeof(DBT));
memset(&pdata, 0, sizeof(DBT));
if ((ret = __db_c_get(pdbc, &pkey, &pdata, DB_CURRENT)) != 0)
goto err;
key = &pkey;
data = &pdata;
}
/*
* Loop through the secondary indices, putting a new item in
* each that points to the appended item.
*
* This is much like the loop in "step 3" in __db_c_put, so
* I'm not commenting heavily here; it was unclean to excerpt
* just that section into a common function, but the basic
* overview is the same here.
*/
if ((ret = __db_s_first(dbp, &sdbp)) != 0)
goto err;
for (; sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
memset(&skey, 0, sizeof(DBT));
if ((ret = sdbp->s_callback(sdbp, key, data, &skey)) != 0) {
if (ret == DB_DONOTINDEX)
continue;
goto err;
}
if ((ret = __db_cursor_int(sdbp, dbc->txn, sdbp->type,
PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0) {
FREE_IF_NEEDED(sdbp, &skey);
goto err;
}
if (CDB_LOCKING(sdbp->dbenv)) {
DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
F_SET(sdbc, DBC_WRITER);
}
/*
* Since we know we have a new primary key, it can't be a
* duplicate duplicate in the secondary. It can be a
* duplicate in a secondary that doesn't support duplicates,
* however, so we need to be careful to avoid an overwrite
* (which would corrupt our index).
*/
if (!F_ISSET(sdbp, DB_AM_DUP)) {
memset(&oldpkey, 0, sizeof(DBT));
F_SET(&oldpkey, DB_DBT_MALLOC);
ret = __db_c_get(sdbc, &skey, &oldpkey,
DB_SET | (STD_LOCKING(dbc) ? DB_RMW : 0));
if (ret == 0) {
cmp = __bam_defcmp(sdbp, &oldpkey, key);
/*
* XXX
* This needs to use the right free function
* as soon as this is possible.
*/
__os_ufree(sdbp->dbenv,
oldpkey.data);
if (cmp != 0) {
__db_err(sdbp->dbenv, "%s%s",
"Append results in a non-unique secondary key in",
" an index not configured to support duplicates");
ret = EINVAL;
goto err1;
}
} else if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY)
goto err1;
}
ret = __db_c_put(sdbc, &skey, key, DB_UPDATE_SECONDARY);
err1: FREE_IF_NEEDED(sdbp, &skey);
if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
goto err;
}
err: if (pdbc != NULL && (t_ret = __db_c_close(pdbc)) != 0 && ret == 0)
ret = t_ret;
if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}

File diff suppressed because it is too large Load diff

View file

@ -1,561 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* 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. 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.
*
* $Id: db_conv.c,v 12.1 2005/06/16 20:21:09 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/crypto.h"
#include "dbinc/hmac.h"
#include "dbinc/db_page.h"
#include "dbinc/db_swap.h"
#include "dbinc/btree.h"
#include "dbinc/hash.h"
#include "dbinc/log.h"
#include "dbinc/qam.h"
/*
* __db_pgin --
* Primary page-swap routine.
*
* PUBLIC: int __db_pgin __P((DB_ENV *, db_pgno_t, void *, DBT *));
*/
int
__db_pgin(dbenv, pg, pp, cookie)
DB_ENV *dbenv;
db_pgno_t pg;
void *pp;
DBT *cookie;
{
DB dummydb, *dbp;
DB_PGINFO *pginfo;
DB_CIPHER *db_cipher;
DB_LSN not_used;
PAGE *pagep;
size_t pg_off, pg_len, sum_len;
int is_hmac, ret;
u_int8_t *chksum, *iv;
pginfo = (DB_PGINFO *)cookie->data;
pagep = (PAGE *)pp;
ret = is_hmac = 0;
chksum = iv = NULL;
memset(&dummydb, 0, sizeof(DB));
dbp = &dummydb;
dummydb.flags = pginfo->flags;
db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
switch (pagep->type) {
case P_HASHMETA:
case P_BTREEMETA:
case P_QAMMETA:
/*
* If checksumming is set on the meta-page, we must set
* it in the dbp.
*/
if (FLD_ISSET(((DBMETA *)pp)->metaflags, DBMETA_CHKSUM))
F_SET(dbp, DB_AM_CHKSUM);
else
F_CLR(dbp, DB_AM_CHKSUM);
if (((DBMETA *)pp)->encrypt_alg != 0 ||
F_ISSET(dbp, DB_AM_ENCRYPT))
is_hmac = 1;
/*
* !!!
* For all meta pages it is required that the chksum
* be at the same location. Use BTMETA to get to it
* for any meta type.
*/
chksum = ((BTMETA *)pp)->chksum;
sum_len = DBMETASIZE;
break;
case P_INVALID:
/*
* We assume that we've read a file hole if we have
* a zero LSN, zero page number and P_INVALID. Otherwise
* we have an invalid page that might contain real data.
*/
if (IS_ZERO_LSN(LSN(pagep)) && pagep->pgno == PGNO_INVALID) {
sum_len = 0;
break;
}
/* FALLTHROUGH */
default:
chksum = P_CHKSUM(dbp, pagep);
sum_len = pginfo->db_pagesize;
/*
* If we are reading in a non-meta page, then if we have
* a db_cipher then we are using hmac.
*/
is_hmac = CRYPTO_ON(dbenv) ? 1 : 0;
break;
}
/*
* We expect a checksum error if there was a configuration problem.
* If there is no configuration problem and we don't get a match,
* it's fatal: panic the system.
*/
if (F_ISSET(dbp, DB_AM_CHKSUM) && sum_len != 0) {
if (F_ISSET(dbp, DB_AM_SWAP) && is_hmac == 0)
P_32_SWAP(chksum);
switch (ret = __db_check_chksum(
dbenv, db_cipher, chksum, pp, sum_len, is_hmac)) {
case 0:
break;
case -1:
if (DBENV_LOGGING(dbenv))
(void)__db_cksum_log(
dbenv, NULL, &not_used, DB_FLUSH);
__db_err(dbenv,
"checksum error: page %lu: catastrophic recovery required",
(u_long)pg);
return (__db_panic(dbenv, DB_RUNRECOVERY));
default:
return (ret);
}
}
if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
DB_ASSERT(db_cipher != NULL);
DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM));
pg_off = P_OVERHEAD(dbp);
DB_ASSERT(db_cipher->adj_size(pg_off) == 0);
switch (pagep->type) {
case P_HASHMETA:
case P_BTREEMETA:
case P_QAMMETA:
/*
* !!!
* For all meta pages it is required that the iv
* be at the same location. Use BTMETA to get to it
* for any meta type.
*/
iv = ((BTMETA *)pp)->iv;
pg_len = DBMETASIZE;
break;
case P_INVALID:
if (IS_ZERO_LSN(LSN(pagep)) &&
pagep->pgno == PGNO_INVALID) {
pg_len = 0;
break;
}
/* FALLTHROUGH */
default:
iv = P_IV(dbp, pagep);
pg_len = pginfo->db_pagesize;
break;
}
if (pg_len != 0 && (ret = db_cipher->decrypt(dbenv,
db_cipher->data, iv, ((u_int8_t *)pagep) + pg_off,
pg_len - pg_off)) != 0)
return (ret);
}
switch (pagep->type) {
case P_INVALID:
if (pginfo->type == DB_QUEUE)
return (__qam_pgin_out(dbenv, pg, pp, cookie));
else
return (__ham_pgin(dbenv, dbp, pg, pp, cookie));
case P_HASH:
case P_HASHMETA:
return (__ham_pgin(dbenv, dbp, pg, pp, cookie));
case P_BTREEMETA:
case P_IBTREE:
case P_IRECNO:
case P_LBTREE:
case P_LDUP:
case P_LRECNO:
case P_OVERFLOW:
return (__bam_pgin(dbenv, dbp, pg, pp, cookie));
case P_QAMMETA:
case P_QAMDATA:
return (__qam_pgin_out(dbenv, pg, pp, cookie));
default:
break;
}
return (__db_pgfmt(dbenv, pg));
}
/*
* __db_pgout --
* Primary page-swap routine.
*
* PUBLIC: int __db_pgout __P((DB_ENV *, db_pgno_t, void *, DBT *));
*/
int
__db_pgout(dbenv, pg, pp, cookie)
DB_ENV *dbenv;
db_pgno_t pg;
void *pp;
DBT *cookie;
{
DB dummydb, *dbp;
DB_CIPHER *db_cipher;
DB_PGINFO *pginfo;
PAGE *pagep;
size_t pg_off, pg_len, sum_len;
int ret;
u_int8_t *chksum, *iv, *key;
pginfo = (DB_PGINFO *)cookie->data;
pagep = (PAGE *)pp;
chksum = iv = key = NULL;
memset(&dummydb, 0, sizeof(DB));
dbp = &dummydb;
dummydb.flags = pginfo->flags;
ret = 0;
switch (pagep->type) {
case P_INVALID:
if (pginfo->type == DB_QUEUE)
ret = __qam_pgin_out(dbenv, pg, pp, cookie);
else
ret = __ham_pgout(dbenv, dbp, pg, pp, cookie);
break;
case P_HASH:
case P_HASHMETA:
ret = __ham_pgout(dbenv, dbp, pg, pp, cookie);
break;
case P_BTREEMETA:
case P_IBTREE:
case P_IRECNO:
case P_LBTREE:
case P_LDUP:
case P_LRECNO:
case P_OVERFLOW:
ret = __bam_pgout(dbenv, dbp, pg, pp, cookie);
break;
case P_QAMMETA:
case P_QAMDATA:
ret = __qam_pgin_out(dbenv, pg, pp, cookie);
break;
default:
return (__db_pgfmt(dbenv, pg));
}
if (ret)
return (ret);
db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
DB_ASSERT(db_cipher != NULL);
DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM));
pg_off = P_OVERHEAD(dbp);
DB_ASSERT(db_cipher->adj_size(pg_off) == 0);
key = db_cipher->mac_key;
switch (pagep->type) {
case P_HASHMETA:
case P_BTREEMETA:
case P_QAMMETA:
/*
* !!!
* For all meta pages it is required that the iv
* be at the same location. Use BTMETA to get to it
* for any meta type.
*/
iv = ((BTMETA *)pp)->iv;
pg_len = DBMETASIZE;
break;
default:
iv = P_IV(dbp, pagep);
pg_len = pginfo->db_pagesize;
break;
}
if ((ret = db_cipher->encrypt(dbenv, db_cipher->data,
iv, ((u_int8_t *)pagep) + pg_off, pg_len - pg_off)) != 0)
return (ret);
}
if (F_ISSET(dbp, DB_AM_CHKSUM)) {
switch (pagep->type) {
case P_HASHMETA:
case P_BTREEMETA:
case P_QAMMETA:
/*
* !!!
* For all meta pages it is required that the chksum
* be at the same location. Use BTMETA to get to it
* for any meta type.
*/
chksum = ((BTMETA *)pp)->chksum;
sum_len = DBMETASIZE;
break;
default:
chksum = P_CHKSUM(dbp, pagep);
sum_len = pginfo->db_pagesize;
break;
}
__db_chksum(pp, sum_len, key, chksum);
if (F_ISSET(dbp, DB_AM_SWAP) && !F_ISSET(dbp, DB_AM_ENCRYPT))
P_32_SWAP(chksum);
}
return (0);
}
/*
* __db_metaswap --
* Byteswap the common part of the meta-data page.
*
* PUBLIC: void __db_metaswap __P((PAGE *));
*/
void
__db_metaswap(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 */
p += 4; /* unused, page type, unused, unused */
SWAP32(p); /* free */
SWAP32(p); /* alloc_lsn part 1 */
SWAP32(p); /* alloc_lsn part 2 */
SWAP32(p); /* cached key count */
SWAP32(p); /* cached record count */
SWAP32(p); /* flags */
}
/*
* __db_byteswap --
* Byteswap a page.
*
* PUBLIC: int __db_byteswap
* PUBLIC: __P((DB_ENV *, DB *, db_pgno_t, PAGE *, size_t, int));
*/
int
__db_byteswap(dbenv, dbp, pg, h, pagesize, pgin)
DB_ENV *dbenv;
DB *dbp;
db_pgno_t pg;
PAGE *h;
size_t pagesize;
int pgin;
{
BINTERNAL *bi;
BKEYDATA *bk;
BOVERFLOW *bo;
RINTERNAL *ri;
db_indx_t i, *inp, len, tmp;
u_int8_t *p, *end;
COMPQUIET(pg, 0);
inp = P_INP(dbp, h);
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(inp[i]);
switch (HPAGE_TYPE(dbp, h, i)) {
case H_KEYDATA:
break;
case H_DUPLICATE:
len = LEN_HKEYDATA(dbp, h, pagesize, i);
p = HKEYDATA_DATA(P_ENTRY(dbp, 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(dbp, h, i));
SWAP32(p); /* pgno */
break;
case H_OFFPAGE:
p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
SWAP32(p); /* pgno */
SWAP32(p); /* tlen */
break;
default:
return (__db_pgfmt(dbenv, pg));
}
}
/*
* 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(inp[i]);
break;
case P_LBTREE:
case P_LDUP:
case P_LRECNO:
for (i = 0; i < NUM_ENT(h); i++) {
if (pgin)
M_16_SWAP(inp[i]);
/*
* In the case of on-page duplicates, key information
* should only be swapped once.
*/
if (h->type == P_LBTREE && i > 1) {
if (pgin) {
if (inp[i] == inp[i - 2])
continue;
} else {
M_16_SWAP(inp[i]);
if (inp[i] == inp[i - 2])
continue;
M_16_SWAP(inp[i]);
}
}
bk = GET_BKEYDATA(dbp, 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;
default:
return (__db_pgfmt(dbenv, pg));
}
if (!pgin)
M_16_SWAP(inp[i]);
}
break;
case P_IBTREE:
for (i = 0; i < NUM_ENT(h); i++) {
if (pgin)
M_16_SWAP(inp[i]);
bi = GET_BINTERNAL(dbp, 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;
default:
return (__db_pgfmt(dbenv, pg));
}
if (!pgin)
M_16_SWAP(inp[i]);
}
break;
case P_IRECNO:
for (i = 0; i < NUM_ENT(h); i++) {
if (pgin)
M_16_SWAP(inp[i]);
ri = GET_RINTERNAL(dbp, h, i);
M_32_SWAP(ri->pgno);
M_32_SWAP(ri->nrecs);
if (!pgin)
M_16_SWAP(inp[i]);
}
break;
case P_OVERFLOW:
case P_INVALID:
/* Nothing to do. */
break;
default:
return (__db_pgfmt(dbenv, pg));
}
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);
}

File diff suppressed because it is too large Load diff

View file

@ -1,164 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_dup.c,v 12.2 2005/06/16 20:21:10 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/mp.h"
#include "dbinc/db_am.h"
/*
* __db_ditem --
* Remove an item from a page.
*
* PUBLIC: int __db_ditem __P((DBC *, PAGE *, u_int32_t, u_int32_t));
*/
int
__db_ditem(dbc, pagep, indx, nbytes)
DBC *dbc;
PAGE *pagep;
u_int32_t indx, nbytes;
{
DB *dbp;
DBT ldbt;
db_indx_t cnt, *inp, offset;
int ret;
u_int8_t *from;
dbp = dbc->dbp;
if (DBC_LOGGING(dbc)) {
ldbt.data = P_ENTRY(dbp, pagep, indx);
ldbt.size = nbytes;
if ((ret = __db_addrem_log(dbp, dbc->txn,
&LSN(pagep), 0, DB_REM_DUP, PGNO(pagep),
(u_int32_t)indx, nbytes, &ldbt, NULL, &LSN(pagep))) != 0)
return (ret);
} else
LSN_NOT_LOGGED(LSN(pagep));
/*
* 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);
}
inp = P_INP(dbp, pagep);
/*
* 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);
DB_ASSERT(inp[indx] >= HOFFSET(pagep));
memmove(from + nbytes, from, inp[indx] - HOFFSET(pagep));
HOFFSET(pagep) += nbytes;
/* Adjust the indices' offsets. */
offset = inp[indx];
for (cnt = 0; cnt < NUM_ENT(pagep); ++cnt)
if (inp[cnt] < offset)
inp[cnt] += nbytes;
/* Shift the indices down. */
--NUM_ENT(pagep);
if (indx != NUM_ENT(pagep))
memmove(&inp[indx], &inp[indx + 1],
sizeof(db_indx_t) * (NUM_ENT(pagep) - indx));
return (0);
}
/*
* __db_pitem --
* Put an item on a page.
*
* PUBLIC: int __db_pitem
* PUBLIC: __P((DBC *, PAGE *, u_int32_t, u_int32_t, DBT *, DBT *));
*/
int
__db_pitem(dbc, pagep, indx, nbytes, hdr, data)
DBC *dbc;
PAGE *pagep;
u_int32_t indx;
u_int32_t nbytes;
DBT *hdr, *data;
{
DB *dbp;
BKEYDATA bk;
DBT thdr;
db_indx_t *inp;
int ret;
u_int8_t *p;
dbp = dbc->dbp;
if (nbytes > P_FREESPACE(dbp, pagep)) {
DB_ASSERT(nbytes <= P_FREESPACE(dbp, pagep));
return (EINVAL);
}
/*
* 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 (DBC_LOGGING(dbc)) {
if ((ret = __db_addrem_log(dbp, dbc->txn,
&LSN(pagep), 0, DB_ADD_DUP, PGNO(pagep),
(u_int32_t)indx, nbytes, hdr, data, &LSN(pagep))) != 0)
return (ret);
} else
LSN_NOT_LOGGED(LSN(pagep));
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;
}
inp = P_INP(dbp, pagep);
/* Adjust the index table, then put the item on the page. */
if (indx != NUM_ENT(pagep))
memmove(&inp[indx + 1], &inp[indx],
sizeof(db_indx_t) * (NUM_ENT(pagep) - indx));
HOFFSET(pagep) -= nbytes;
inp[indx] = HOFFSET(pagep);
++NUM_ENT(pagep);
p = P_ENTRY(dbp, pagep, indx);
memcpy(p, hdr->data, hdr->size);
if (data != NULL)
memcpy(p + hdr->size, data->data, data->size);
return (0);
}

File diff suppressed because it is too large Load diff

View file

@ -1,942 +0,0 @@
/*
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1998-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_join.c,v 12.6 2005/10/07 20:21:22 ubell Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_join.h"
#include "dbinc/btree.h"
static int __db_join_close_pp __P((DBC *));
static int __db_join_cmp __P((const void *, const void *));
static int __db_join_del __P((DBC *, u_int32_t));
static int __db_join_get __P((DBC *, DBT *, DBT *, u_int32_t));
static int __db_join_get_pp __P((DBC *, DBT *, DBT *, u_int32_t));
static int __db_join_getnext __P((DBC *, DBT *, DBT *, u_int32_t, u_int32_t));
static int __db_join_primget __P((DB *,
DB_TXN *, u_int32_t, DBT *, DBT *, u_int32_t));
static int __db_join_put __P((DBC *, DBT *, DBT *, u_int32_t));
/*
* Check to see if the Nth secondary cursor of join cursor jc is pointing
* to a sorted duplicate set.
*/
#define SORTED_SET(jc, n) ((jc)->j_curslist[(n)]->dbp->dup_compare != NULL)
/*
* This is the duplicate-assisted join functionality. Right now we're
* going to write it such that we return one item at a time, although
* I think we may need to optimize it to return them all at once.
* It should be easier to get it working this way, and I believe that
* changing it should be fairly straightforward.
*
* We optimize the join by sorting cursors from smallest to largest
* cardinality. In most cases, this is indeed optimal. However, if
* a cursor with large cardinality has very few data in common with the
* first cursor, it is possible that the join will be made faster by
* putting it earlier in the cursor list. Since we have no way to detect
* cases like this, we simply provide a flag, DB_JOIN_NOSORT, which retains
* the sort order specified by the caller, who may know more about the
* structure of the data.
*
* The first cursor moves sequentially through the duplicate set while
* the others search explicitly for the duplicate in question.
*
*/
/*
* __db_join --
* This is the interface to the duplicate-assisted join functionality.
* In the same way that cursors mark a position in a database, a cursor
* can mark a position in a join. While most cursors are created by the
* cursor method of a DB, join cursors are created through an explicit
* call to DB->join.
*
* The curslist is an array of existing, initialized cursors and primary
* is the DB of the primary file. The data item that joins all the
* cursors in the curslist is used as the key into the primary and that
* key and data are returned. When no more items are left in the join
* set, the c_next operation off the join cursor will return DB_NOTFOUND.
*
* PUBLIC: int __db_join __P((DB *, DBC **, DBC **, u_int32_t));
*/
int
__db_join(primary, curslist, dbcp, flags)
DB *primary;
DBC **curslist, **dbcp;
u_int32_t flags;
{
DB_ENV *dbenv;
DBC *dbc;
JOIN_CURSOR *jc;
size_t ncurs, nslots;
u_int32_t i;
int ret;
dbenv = primary->dbenv;
dbc = NULL;
jc = NULL;
if ((ret = __os_calloc(dbenv, 1, sizeof(DBC), &dbc)) != 0)
goto err;
if ((ret = __os_calloc(dbenv, 1, sizeof(JOIN_CURSOR), &jc)) != 0)
goto err;
if ((ret = __os_malloc(dbenv, 256, &jc->j_key.data)) != 0)
goto err;
jc->j_key.ulen = 256;
F_SET(&jc->j_key, DB_DBT_USERMEM);
F_SET(&jc->j_rdata, DB_DBT_REALLOC);
for (jc->j_curslist = curslist;
*jc->j_curslist != NULL; jc->j_curslist++)
;
/*
* The number of cursor slots we allocate is one greater than
* the number of cursors involved in the join, because the
* list is NULL-terminated.
*/
ncurs = (size_t)(jc->j_curslist - curslist);
nslots = ncurs + 1;
/*
* !!! -- A note on the various lists hanging off jc.
*
* j_curslist is the initial NULL-terminated list of cursors passed
* into __db_join. The original cursors are not modified; pristine
* copies are required because, in databases with unsorted dups, we
* must reset all of the secondary cursors after the first each
* time the first one is incremented, or else we will lose data
* which happen to be sorted differently in two different cursors.
*
* j_workcurs is where we put those copies that we're planning to
* work with. They're lazily c_dup'ed from j_curslist as we need
* them, and closed when the join cursor is closed or when we need
* to reset them to their original values (in which case we just
* c_dup afresh).
*
* j_fdupcurs is an array of cursors which point to the first
* duplicate in the duplicate set that contains the data value
* we're currently interested in. We need this to make
* __db_join_get correctly return duplicate duplicates; i.e., if a
* given data value occurs twice in the set belonging to cursor #2,
* and thrice in the set belonging to cursor #3, and once in all
* the other cursors, successive calls to __db_join_get need to
* return that data item six times. To make this happen, each time
* cursor N is allowed to advance to a new datum, all cursors M
* such that M > N have to be reset to the first duplicate with
* that datum, so __db_join_get will return all the dup-dups again.
* We could just reset them to the original cursor from j_curslist,
* but that would be a bit slower in the unsorted case and a LOT
* slower in the sorted one.
*
* j_exhausted is a list of boolean values which represent
* whether or not their corresponding cursors are "exhausted",
* i.e. whether the datum under the corresponding cursor has
* been found not to exist in any unreturned combinations of
* later secondary cursors, in which case they are ready to be
* incremented.
*/
/* We don't want to free regions whose callocs have failed. */
jc->j_curslist = NULL;
jc->j_workcurs = NULL;
jc->j_fdupcurs = NULL;
jc->j_exhausted = NULL;
if ((ret = __os_calloc(dbenv, nslots, sizeof(DBC *),
&jc->j_curslist)) != 0)
goto err;
if ((ret = __os_calloc(dbenv, nslots, sizeof(DBC *),
&jc->j_workcurs)) != 0)
goto err;
if ((ret = __os_calloc(dbenv, nslots, sizeof(DBC *),
&jc->j_fdupcurs)) != 0)
goto err;
if ((ret = __os_calloc(dbenv, nslots, sizeof(u_int8_t),
&jc->j_exhausted)) != 0)
goto err;
for (i = 0; curslist[i] != NULL; i++) {
jc->j_curslist[i] = curslist[i];
jc->j_workcurs[i] = NULL;
jc->j_fdupcurs[i] = NULL;
jc->j_exhausted[i] = 0;
}
jc->j_ncurs = (u_int32_t)ncurs;
/*
* If DB_JOIN_NOSORT is not set, optimize secondary cursors by
* sorting in order of increasing cardinality.
*/
if (!LF_ISSET(DB_JOIN_NOSORT))
qsort(jc->j_curslist, ncurs, sizeof(DBC *), __db_join_cmp);
/*
* We never need to reset the 0th cursor, so there's no
* solid reason to use workcurs[0] rather than curslist[0] in
* join_get. Nonetheless, it feels cleaner to do it for symmetry,
* and this is the most logical place to copy it.
*
* !!!
* There's no need to close the new cursor if we goto err only
* because this is the last thing that can fail. Modifier of this
* function beware!
*/
if ((ret =
__db_c_dup(jc->j_curslist[0], jc->j_workcurs, DB_POSITION)) != 0)
goto err;
dbc->c_close = __db_join_close_pp;
dbc->c_del = __db_join_del;
dbc->c_get = __db_join_get_pp;
dbc->c_put = __db_join_put;
dbc->internal = (DBC_INTERNAL *)jc;
dbc->dbp = primary;
jc->j_primary = primary;
/* Stash the first cursor's transaction here for easy access. */
dbc->txn = curslist[0]->txn;
*dbcp = dbc;
MUTEX_LOCK(dbenv, primary->mutex);
TAILQ_INSERT_TAIL(&primary->join_queue, dbc, links);
MUTEX_UNLOCK(dbenv, primary->mutex);
return (0);
err: if (jc != NULL) {
if (jc->j_curslist != NULL)
__os_free(dbenv, jc->j_curslist);
if (jc->j_workcurs != NULL) {
if (jc->j_workcurs[0] != NULL)
(void)__db_c_close(jc->j_workcurs[0]);
__os_free(dbenv, jc->j_workcurs);
}
if (jc->j_fdupcurs != NULL)
__os_free(dbenv, jc->j_fdupcurs);
if (jc->j_exhausted != NULL)
__os_free(dbenv, jc->j_exhausted);
__os_free(dbenv, jc);
}
if (dbc != NULL)
__os_free(dbenv, dbc);
return (ret);
}
/*
* __db_join_close_pp --
* DBC->c_close pre/post processing for join cursors.
*/
static int
__db_join_close_pp(dbc)
DBC *dbc;
{
DB_ENV *dbenv;
DB_THREAD_INFO *ip;
DB *dbp;
int handle_check, ret, t_ret;
dbp = dbc->dbp;
dbenv = dbp->dbenv;
PANIC_CHECK(dbenv);
ENV_ENTER(dbenv, ip);
handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check &&
(ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0) {
handle_check = 0;
goto err;
}
ret = __db_join_close(dbc);
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret);
}
static int
__db_join_put(dbc, key, data, flags)
DBC *dbc;
DBT *key;
DBT *data;
u_int32_t flags;
{
PANIC_CHECK(dbc->dbp->dbenv);
COMPQUIET(key, NULL);
COMPQUIET(data, NULL);
COMPQUIET(flags, 0);
return (EINVAL);
}
static int
__db_join_del(dbc, flags)
DBC *dbc;
u_int32_t flags;
{
PANIC_CHECK(dbc->dbp->dbenv);
COMPQUIET(flags, 0);
return (EINVAL);
}
/*
* __db_join_get_pp --
* DBjoin->get pre/post processing.
*/
static int
__db_join_get_pp(dbc, key, data, flags)
DBC *dbc;
DBT *key, *data;
u_int32_t flags;
{
DB *dbp;
DB_ENV *dbenv;
DB_THREAD_INFO *ip;
u_int32_t handle_check, save_flags;
int ret, t_ret;
dbp = dbc->dbp;
dbenv = dbp->dbenv;
/* Save the original flags value. */
save_flags = flags;
PANIC_CHECK(dbenv);
if (LF_ISSET(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW)) {
if (!LOCKING_ON(dbp->dbenv))
return (__db_fnl(dbp->dbenv, "DBcursor->c_get"));
LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW);
}
switch (flags) {
case 0:
case DB_JOIN_ITEM:
break;
default:
return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 0));
}
/*
* A partial get of the key of a join cursor don't make much sense;
* the entire key is necessary to query the primary database
* and find the datum, and so regardless of the size of the key
* it would not be a performance improvement. Since it would require
* special handling, we simply disallow it.
*
* A partial get of the data, however, potentially makes sense (if
* all possible data are a predictable large structure, for instance)
* and causes us no headaches, so we permit it.
*/
if (F_ISSET(key, DB_DBT_PARTIAL)) {
__db_err(dbp->dbenv,
"DB_DBT_PARTIAL may not be set on key during join_get");
return (EINVAL);
}
ENV_ENTER(dbenv, ip);
handle_check = IS_ENV_REPLICATED(dbp->dbenv);
if (handle_check &&
(ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0) {
handle_check = 0;
goto err;
}
/* Restore the original flags value. */
flags = save_flags;
ret = __db_join_get(dbc, key, data, flags);
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret);
}
static int
__db_join_get(dbc, key_arg, data_arg, flags)
DBC *dbc;
DBT *key_arg, *data_arg;
u_int32_t flags;
{
DBT *key_n, key_n_mem;
DB *dbp;
DBC *cp;
JOIN_CURSOR *jc;
int db_manage_data, ret;
u_int32_t i, j, operation, opmods;
dbp = dbc->dbp;
jc = (JOIN_CURSOR *)dbc->internal;
operation = LF_ISSET(DB_OPFLAGS_MASK);
/* !!!
* If the set of flags here changes, check that __db_join_primget
* is updated to handle them properly.
*/
opmods = LF_ISSET(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW);
/*
* Since we are fetching the key as a datum in the secondary indices,
* we must be careful of caller-specified DB_DBT_* memory
* management flags. If necessary, use a stack-allocated DBT;
* we'll appropriately copy and/or allocate the data later.
*/
if (F_ISSET(key_arg, DB_DBT_USERMEM) ||
F_ISSET(key_arg, DB_DBT_MALLOC)) {
/* We just use the default buffer; no need to go malloc. */
key_n = &key_n_mem;
memset(key_n, 0, sizeof(DBT));
} else {
/*
* Either DB_DBT_REALLOC or the default buffer will work
* fine if we have to reuse it, as we do.
*/
key_n = key_arg;
}
/*
* If our last attempt to do a get on the primary key failed,
* short-circuit the join and try again with the same key.
*/
if (F_ISSET(jc, JOIN_RETRY))
goto samekey;
F_CLR(jc, JOIN_RETRY);
retry: ret = __db_c_get(jc->j_workcurs[0], &jc->j_key, key_n,
opmods | (jc->j_exhausted[0] ? DB_NEXT_DUP : DB_CURRENT));
if (ret == DB_BUFFER_SMALL) {
jc->j_key.ulen <<= 1;
if ((ret = __os_realloc(dbp->dbenv,
jc->j_key.ulen, &jc->j_key.data)) != 0)
goto mem_err;
goto retry;
}
/*
* If ret == DB_NOTFOUND, we're out of elements of the first
* secondary cursor. This is how we finally finish the join
* if all goes well.
*/
if (ret != 0)
goto err;
/*
* If jc->j_exhausted[0] == 1, we've just advanced the first cursor,
* and we're going to want to advance all the cursors that point to
* the first member of a duplicate duplicate set (j_fdupcurs[1..N]).
* Close all the cursors in j_fdupcurs; we'll reopen them the
* first time through the upcoming loop.
*/
for (i = 1; i < jc->j_ncurs; i++) {
if (jc->j_fdupcurs[i] != NULL &&
(ret = __db_c_close(jc->j_fdupcurs[i])) != 0)
goto err;
jc->j_fdupcurs[i] = NULL;
}
/*
* If jc->j_curslist[1] == NULL, we have only one cursor in the join.
* Thus, we can safely increment that one cursor on each call
* to __db_join_get, and we signal this by setting jc->j_exhausted[0]
* right away.
*
* Otherwise, reset jc->j_exhausted[0] to 0, so that we don't
* increment it until we know we're ready to.
*/
if (jc->j_curslist[1] == NULL)
jc->j_exhausted[0] = 1;
else
jc->j_exhausted[0] = 0;
/* We have the first element; now look for it in the other cursors. */
for (i = 1; i < jc->j_ncurs; i++) {
DB_ASSERT(jc->j_curslist[i] != NULL);
if (jc->j_workcurs[i] == NULL)
/* If this is NULL, we need to dup curslist into it. */
if ((ret = __db_c_dup(jc->j_curslist[i],
&jc->j_workcurs[i], DB_POSITION)) != 0)
goto err;
retry2: cp = jc->j_workcurs[i];
if ((ret = __db_join_getnext(cp, &jc->j_key, key_n,
jc->j_exhausted[i], opmods)) == DB_NOTFOUND) {
/*
* jc->j_workcurs[i] has no more of the datum we're
* interested in. Go back one cursor and get
* a new dup. We can't just move to a new
* element of the outer relation, because that way
* we might miss duplicate duplicates in cursor i-1.
*
* If this takes us back to the first cursor,
* -then- we can move to a new element of the outer
* relation.
*/
--i;
jc->j_exhausted[i] = 1;
if (i == 0) {
for (j = 1; jc->j_workcurs[j] != NULL; j++) {
/*
* We're moving to a new element of
* the first secondary cursor. If
* that cursor is sorted, then any
* other sorted cursors can be safely
* reset to the first duplicate
* duplicate in the current set if we
* have a pointer to it (we can't just
* leave them be, or we'll miss
* duplicate duplicates in the outer
* relation).
*
* If the first cursor is unsorted, or
* if cursor j is unsorted, we can
* make no assumptions about what
* we're looking for next or where it
* will be, so we reset to the very
* beginning (setting workcurs NULL
* will achieve this next go-round).
*
* XXX: This is likely to break
* horribly if any two cursors are
* both sorted, but have different
* specified sort functions. For,
* now, we dismiss this as pathology
* and let strange things happen--we
* can't make rope childproof.
*/
if ((ret = __db_c_close(
jc->j_workcurs[j])) != 0)
goto err;
if (!SORTED_SET(jc, 0) ||
!SORTED_SET(jc, j) ||
jc->j_fdupcurs[j] == NULL)
/*
* Unsafe conditions;
* reset fully.
*/
jc->j_workcurs[j] = NULL;
else
/* Partial reset suffices. */
if ((__db_c_dup(
jc->j_fdupcurs[j],
&jc->j_workcurs[j],
DB_POSITION)) != 0)
goto err;
jc->j_exhausted[j] = 0;
}
goto retry;
/* NOTREACHED */
}
/*
* We're about to advance the cursor and need to
* reset all of the workcurs[j] where j>i, so that
* we don't miss any duplicate duplicates.
*/
for (j = i + 1;
jc->j_workcurs[j] != NULL;
j++) {
if ((ret =
__db_c_close(jc->j_workcurs[j])) != 0)
goto err;
jc->j_exhausted[j] = 0;
if (jc->j_fdupcurs[j] == NULL)
jc->j_workcurs[j] = NULL;
else if ((ret = __db_c_dup(jc->j_fdupcurs[j],
&jc->j_workcurs[j], DB_POSITION)) != 0)
goto err;
}
goto retry2;
/* NOTREACHED */
}
if (ret == DB_BUFFER_SMALL) {
jc->j_key.ulen <<= 1;
if ((ret = __os_realloc(dbp->dbenv, jc->j_key.ulen,
&jc->j_key.data)) != 0) {
mem_err: __db_err(dbp->dbenv,
"Allocation failed for join key, len = %lu",
(u_long)jc->j_key.ulen);
goto err;
}
goto retry2;
}
if (ret != 0)
goto err;
/*
* If we made it this far, we've found a matching
* datum in cursor i. Mark the current cursor
* unexhausted, so we don't miss any duplicate
* duplicates the next go-round--unless this is the
* very last cursor, in which case there are none to
* miss, and we'll need that exhausted flag to finally
* get a DB_NOTFOUND and move on to the next datum in
* the outermost cursor.
*/
if (i + 1 != jc->j_ncurs)
jc->j_exhausted[i] = 0;
else
jc->j_exhausted[i] = 1;
/*
* If jc->j_fdupcurs[i] is NULL and the ith cursor's dups are
* sorted, then we're here for the first time since advancing
* cursor 0, and we have a new datum of interest.
* jc->j_workcurs[i] points to the beginning of a set of
* duplicate duplicates; store this into jc->j_fdupcurs[i].
*/
if (SORTED_SET(jc, i) && jc->j_fdupcurs[i] == NULL && (ret =
__db_c_dup(cp, &jc->j_fdupcurs[i], DB_POSITION)) != 0)
goto err;
}
err: if (ret != 0)
return (ret);
if (0) {
samekey: /*
* Get the key we tried and failed to return last time;
* it should be the current datum of all the secondary cursors.
*/
if ((ret = __db_c_get(jc->j_workcurs[0],
&jc->j_key, key_n, DB_CURRENT | opmods)) != 0)
return (ret);
F_CLR(jc, JOIN_RETRY);
}
/*
* ret == 0; we have a key to return.
*
* If DB_DBT_USERMEM or DB_DBT_MALLOC is set, we need to copy the key
* back into the dbt we were given for the key; call __db_retcopy.
* Otherwise, assert that we do not need to copy anything and proceed.
*/
DB_ASSERT(F_ISSET(
key_arg, DB_DBT_USERMEM | DB_DBT_MALLOC) || key_n == key_arg);
if (F_ISSET(key_arg, DB_DBT_USERMEM | DB_DBT_MALLOC) &&
(ret = __db_retcopy(dbp->dbenv,
key_arg, key_n->data, key_n->size, NULL, NULL)) != 0) {
/*
* The retcopy failed, most commonly because we have a user
* buffer for the key which is too small. Set things up to
* retry next time, and return.
*/
F_SET(jc, JOIN_RETRY);
return (ret);
}
/*
* If DB_JOIN_ITEM is set, we return it; otherwise we do the lookup
* in the primary and then return.
*
* Note that we use key_arg here; it is safe (and appropriate)
* to do so.
*/
if (operation == DB_JOIN_ITEM)
return (0);
/*
* If data_arg->flags == 0--that is, if DB is managing the
* data DBT's memory--it's not safe to just pass the DBT
* through to the primary get call, since we don't want that
* memory to belong to the primary DB handle (and if the primary
* is free-threaded, it can't anyway).
*
* Instead, use memory that is managed by the join cursor, in
* jc->j_rdata.
*/
if (!F_ISSET(data_arg, DB_DBT_MALLOC | DB_DBT_REALLOC | DB_DBT_USERMEM))
db_manage_data = 1;
else
db_manage_data = 0;
if ((ret = __db_join_primget(jc->j_primary,
jc->j_curslist[0]->txn, jc->j_curslist[0]->locker, key_arg,
db_manage_data ? &jc->j_rdata : data_arg, opmods)) != 0) {
if (ret == DB_NOTFOUND)
/*
* If ret == DB_NOTFOUND, the primary and secondary
* are out of sync; every item in each secondary
* should correspond to something in the primary,
* or we shouldn't have done the join this way.
* Wail.
*/
ret = __db_secondary_corrupt(jc->j_primary);
else
/*
* The get on the primary failed for some other
* reason, most commonly because we're using a user
* buffer that's not big enough. Flag our failure
* so we can return the same key next time.
*/
F_SET(jc, JOIN_RETRY);
}
if (db_manage_data && ret == 0) {
data_arg->data = jc->j_rdata.data;
data_arg->size = jc->j_rdata.size;
}
return (ret);
}
/*
* __db_join_close --
* DBC->c_close for join cursors.
*
* PUBLIC: int __db_join_close __P((DBC *));
*/
int
__db_join_close(dbc)
DBC *dbc;
{
DB *dbp;
DB_ENV *dbenv;
JOIN_CURSOR *jc;
int ret, t_ret;
u_int32_t i;
jc = (JOIN_CURSOR *)dbc->internal;
dbp = dbc->dbp;
dbenv = dbp->dbenv;
ret = t_ret = 0;
/*
* Remove from active list of join cursors. Note that this
* must happen before any action that can fail and return, or else
* __db_close may loop indefinitely.
*/
MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_REMOVE(&dbp->join_queue, dbc, links);
MUTEX_UNLOCK(dbenv, dbp->mutex);
PANIC_CHECK(dbenv);
/*
* Close any open scratch cursors. In each case, there may
* not be as many outstanding as there are cursors in
* curslist, but we want to close whatever's there.
*
* If any close fails, there's no reason not to close everything else;
* we'll just return the error code of the last one to fail. There's
* not much the caller can do anyway, since these cursors only exist
* hanging off a db-internal data structure that they shouldn't be
* mucking with.
*/
for (i = 0; i < jc->j_ncurs; i++) {
if (jc->j_workcurs[i] != NULL &&
(t_ret = __db_c_close(jc->j_workcurs[i])) != 0)
ret = t_ret;
if (jc->j_fdupcurs[i] != NULL &&
(t_ret = __db_c_close(jc->j_fdupcurs[i])) != 0)
ret = t_ret;
}
__os_free(dbenv, jc->j_exhausted);
__os_free(dbenv, jc->j_curslist);
__os_free(dbenv, jc->j_workcurs);
__os_free(dbenv, jc->j_fdupcurs);
__os_free(dbenv, jc->j_key.data);
if (jc->j_rdata.data != NULL)
__os_ufree(dbenv, jc->j_rdata.data);
__os_free(dbenv, jc);
__os_free(dbenv, dbc);
return (ret);
}
/*
* __db_join_getnext --
* This function replaces the DBC_CONTINUE and DBC_KEYSET
* functionality inside the various cursor get routines.
*
* If exhausted == 0, we're not done with the current datum;
* return it if it matches "matching", otherwise search
* using DB_GET_BOTHC (which is faster than iteratively doing
* DB_NEXT_DUP) forward until we find one that does.
*
* If exhausted == 1, we are done with the current datum, so just
* leap forward to searching NEXT_DUPs.
*
* If no matching datum exists, returns DB_NOTFOUND, else 0.
*/
static int
__db_join_getnext(dbc, key, data, exhausted, opmods)
DBC *dbc;
DBT *key, *data;
u_int32_t exhausted, opmods;
{
int ret, cmp;
DB *dbp;
DBT ldata;
int (*func) __P((DB *, const DBT *, const DBT *));
dbp = dbc->dbp;
func = (dbp->dup_compare == NULL) ? __bam_defcmp : dbp->dup_compare;
switch (exhausted) {
case 0:
/*
* We don't want to step on data->data; use a new
* DBT and malloc so we don't step on dbc's rdata memory.
*/
memset(&ldata, 0, sizeof(DBT));
F_SET(&ldata, DB_DBT_MALLOC);
if ((ret = __db_c_get(dbc,
key, &ldata, opmods | DB_CURRENT)) != 0)
break;
cmp = func(dbp, data, &ldata);
if (cmp == 0) {
/*
* We have to return the real data value. Copy
* it into data, then free the buffer we malloc'ed
* above.
*/
if ((ret = __db_retcopy(dbp->dbenv, data, ldata.data,
ldata.size, &data->data, &data->size)) != 0)
return (ret);
__os_ufree(dbp->dbenv, ldata.data);
return (0);
}
/*
* Didn't match--we want to fall through and search future
* dups. We just forget about ldata and free
* its buffer--data contains the value we're searching for.
*/
__os_ufree(dbp->dbenv, ldata.data);
/* FALLTHROUGH */
case 1:
ret = __db_c_get(dbc, key, data, opmods | DB_GET_BOTHC);
break;
default:
ret = EINVAL;
break;
}
return (ret);
}
/*
* __db_join_cmp --
* Comparison function for sorting DBCs in cardinality order.
*/
static int
__db_join_cmp(a, b)
const void *a, *b;
{
DBC *dbca, *dbcb;
db_recno_t counta, countb;
dbca = *((DBC * const *)a);
dbcb = *((DBC * const *)b);
if (__db_c_count(dbca, &counta) != 0 ||
__db_c_count(dbcb, &countb) != 0)
return (0);
return ((long)counta - (long)countb);
}
/*
* __db_join_primget --
* Perform a DB->get in the primary, being careful not to use a new
* locker ID if we're doing CDB locking.
*/
static int
__db_join_primget(dbp, txn, lockerid, key, data, flags)
DB *dbp;
DB_TXN *txn;
u_int32_t lockerid;
DBT *key, *data;
u_int32_t flags;
{
DBC *dbc;
u_int32_t rmw;
int ret, t_ret;
if ((ret = __db_cursor_int(dbp,
txn, dbp->type, PGNO_INVALID, 0, lockerid, &dbc)) != 0)
return (ret);
/*
* The only allowable flags here are the two flags copied into "opmods"
* in __db_join_get, DB_RMW and DB_READ_UNCOMMITTED. The former is an
* op on the c_get call, the latter on the cursor call. It's a DB bug
* if we allow any other flags down in here.
*/
rmw = LF_ISSET(DB_RMW);
if (LF_ISSET(DB_READ_UNCOMMITTED) ||
(txn != NULL && F_ISSET(txn, TXN_READ_UNCOMMITTED)))
F_SET(dbc, DBC_READ_UNCOMMITTED);
if (LF_ISSET(DB_READ_COMMITTED) ||
(txn != NULL && F_ISSET(txn, TXN_READ_COMMITTED)))
F_SET(dbc, DBC_READ_COMMITTED);
LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW);
DB_ASSERT(flags == 0);
F_SET(dbc, DBC_TRANSIENT);
/*
* This shouldn't be necessary, thanks to the fact that join cursors
* swap in their own DB_DBT_REALLOC'ed buffers, but just for form's
* sake, we mirror what __db_get does.
*/
SET_RET_MEM(dbc, dbp);
ret = __db_c_get(dbc, key, data, DB_SET | rmw);
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
/*
* __db_secondary_corrupt --
* Report that a secondary index appears corrupt, as it has a record
* that does not correspond to a record in the primary or vice versa.
*
* PUBLIC: int __db_secondary_corrupt __P((DB *));
*/
int
__db_secondary_corrupt(dbp)
DB *dbp;
{
__db_err(dbp->dbenv,
"Secondary index corrupt: not consistent with primary");
return (DB_SECONDARY_BAD);
}

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more