mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
Merge mysql.com:/home/jimw/my/mysql-5.1-bdb
into mysql.com:/home/jimw/my/mysql-5.1-clean VC++Files/storage/bdb/bdb.dsp: Auto merged sql/ha_berkeley.cc: Auto merged
This commit is contained in:
@@ -158,6 +158,26 @@ SOURCE=.\btree\btree_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\crypto\aes_method.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\crypto\crypto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\crypto\mersenne\mt19937db.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\crypto\rijndael\rijndael-alg-fst.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\crypto\rijndael\rijndael-api-fst.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\db\crdel_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -238,6 +258,10 @@ SOURCE=.\db\db_overflow.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\db\db_ovfl_vrfy.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\db\db_pr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -262,6 +286,18 @@ SOURCE=.\db\db_ret.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\db\db_setid.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\db\db_setlsn.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\db\db_stati.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\env\db_salloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -306,6 +342,10 @@ SOURCE=.\dbreg\dbreg_rec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dbreg\dbreg_stat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dbreg\dbreg_util.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -330,6 +370,10 @@ SOURCE=.\env\env_region.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\env\env_stat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fileops\fileops_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -418,6 +462,14 @@ SOURCE=.\lock\lock_deadlock.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lock\lock_id.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lock\lock_list.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lock\lock_method.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -430,6 +482,10 @@ SOURCE=.\lock\lock_stat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lock\lock_timer.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lock\lock_util.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -458,6 +514,10 @@ SOURCE=.\log\log_put.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\log\log_stat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mp\mp_alloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -470,6 +530,10 @@ SOURCE=.\mp\mp_fget.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mp\mp_fmethod.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mp\mp_fopen.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -614,6 +678,10 @@ SOURCE=.\os\os_tmpdir.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\os_win32\os_truncate.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\os_win32\os_type.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -662,6 +730,14 @@ SOURCE=.\qam\qam_verify.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rep\rep_auto.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rep\rep_backup.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rep\rep_method.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -674,6 +750,10 @@ SOURCE=.\rep\rep_region.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rep\rep_stat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rep\rep_util.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -93,7 +93,8 @@ u_int32_t berkeley_lock_types[]=
|
||||
TYPELIB berkeley_lock_typelib= {array_elements(berkeley_lock_names)-1,"",
|
||||
berkeley_lock_names, NULL};
|
||||
|
||||
static void berkeley_print_error(const char *db_errpfx, char *buffer);
|
||||
static void berkeley_print_error(const DB_ENV *db_env, const char *db_errpfx,
|
||||
const char *buffer);
|
||||
static byte* bdb_get_key(BDB_SHARE *share,uint *length,
|
||||
my_bool not_used __attribute__((unused)));
|
||||
static BDB_SHARE *get_share(const char *table_name, TABLE *table);
|
||||
@@ -176,7 +177,7 @@ handlerton *berkeley_init(void)
|
||||
|
||||
if (opt_endinfo)
|
||||
db_env->set_verbose(db_env,
|
||||
DB_VERB_CHKPOINT | DB_VERB_DEADLOCK | DB_VERB_RECOVERY,
|
||||
DB_VERB_DEADLOCK | DB_VERB_RECOVERY,
|
||||
1);
|
||||
|
||||
db_env->set_cachesize(db_env, 0, berkeley_cache_size, 0);
|
||||
@@ -248,7 +249,7 @@ static int berkeley_commit(THD *thd, bool all)
|
||||
DBUG_PRINT("trans",("ending transaction %s", all ? "all" : "stmt"));
|
||||
berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
|
||||
DB_TXN **txn= all ? &trx->all : &trx->stmt;
|
||||
int error=txn_commit(*txn,0);
|
||||
int error= (*txn)->commit(*txn,0);
|
||||
*txn=0;
|
||||
#ifndef DBUG_OFF
|
||||
if (error)
|
||||
@@ -263,7 +264,7 @@ static int berkeley_rollback(THD *thd, bool all)
|
||||
DBUG_PRINT("trans",("aborting transaction %s", all ? "all" : "stmt"));
|
||||
berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
|
||||
DB_TXN **txn= all ? &trx->all : &trx->stmt;
|
||||
int error=txn_abort(*txn);
|
||||
int error= (*txn)->abort(*txn);
|
||||
*txn=0;
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
@@ -321,7 +322,8 @@ err:
|
||||
}
|
||||
|
||||
|
||||
static void berkeley_print_error(const char *db_errpfx, char *buffer)
|
||||
static void berkeley_print_error(const DB_ENV *db_env, const char *db_errpfx,
|
||||
const char *buffer)
|
||||
{
|
||||
sql_print_error("%s: %s",db_errpfx,buffer); /* purecov: tested */
|
||||
}
|
||||
@@ -612,7 +614,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
|
||||
berkeley_cmp_packed_key));
|
||||
if (!hidden_primary_key)
|
||||
file->app_private= (void*) (table->key_info + table_share->primary_key);
|
||||
if ((error= txn_begin(db_env, 0, (DB_TXN**) &transaction, 0)) ||
|
||||
if ((error= db_env->txn_begin(db_env, NULL, (DB_TXN**) &transaction, 0)) ||
|
||||
(error= (file->open(file, transaction,
|
||||
fn_format(name_buff, name, "", ha_berkeley_ext,
|
||||
2 | 4),
|
||||
@@ -651,7 +653,8 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
|
||||
DBUG_PRINT("bdb",("Setting DB_DUP for key %u", i));
|
||||
(*ptr)->set_flags(*ptr, DB_DUP);
|
||||
}
|
||||
if ((error= txn_begin(db_env, 0, (DB_TXN**) &transaction, 0)) ||
|
||||
if ((error= db_env->txn_begin(db_env, NULL, (DB_TXN**) &transaction,
|
||||
0)) ||
|
||||
(error=((*ptr)->open(*ptr, transaction, name_buff, part, DB_BTREE,
|
||||
open_mode, 0))) ||
|
||||
(error= transaction->commit(transaction, 0)))
|
||||
@@ -1844,7 +1847,7 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
|
||||
/* We have to start a master transaction */
|
||||
DBUG_PRINT("trans",("starting transaction all: options: 0x%lx",
|
||||
(ulong) thd->options));
|
||||
if ((error=txn_begin(db_env, 0, &trx->all, 0)))
|
||||
if ((error= db_env->txn_begin(db_env, NULL, &trx->all, 0)))
|
||||
{
|
||||
trx->bdb_lock_count--; // We didn't get the lock
|
||||
DBUG_RETURN(error);
|
||||
@@ -1854,7 +1857,7 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
|
||||
DBUG_RETURN(0); // Don't create stmt trans
|
||||
}
|
||||
DBUG_PRINT("trans",("starting transaction stmt"));
|
||||
if ((error=txn_begin(db_env, trx->all, &trx->stmt, 0)))
|
||||
if ((error= db_env->txn_begin(db_env, trx->all, &trx->stmt, 0)))
|
||||
{
|
||||
/* We leave the possible master transaction open */
|
||||
trx->bdb_lock_count--; // We didn't get the lock
|
||||
@@ -1879,7 +1882,7 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
|
||||
We must in this case commit the work to keep the row locks
|
||||
*/
|
||||
DBUG_PRINT("trans",("commiting non-updating transaction"));
|
||||
error= txn_commit(trx->stmt,0);
|
||||
error= trx->stmt->commit(trx->stmt,0);
|
||||
trx->stmt= transaction= 0;
|
||||
}
|
||||
}
|
||||
@@ -1908,7 +1911,7 @@ int ha_berkeley::start_stmt(THD *thd)
|
||||
if (!trx->stmt)
|
||||
{
|
||||
DBUG_PRINT("trans",("starting transaction stmt"));
|
||||
error=txn_begin(db_env, trx->all, &trx->stmt, 0);
|
||||
error= db_env->txn_begin(db_env, trx->all, &trx->stmt, 0);
|
||||
trans_register_ha(thd, FALSE, &berkeley_hton);
|
||||
}
|
||||
transaction= trx->stmt;
|
||||
@@ -2289,7 +2292,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
|
||||
free(stat);
|
||||
stat=0;
|
||||
}
|
||||
if ((key_file[i]->stat)(key_file[i], (void*) &stat, 0))
|
||||
if ((key_file[i]->stat)(key_file[i], NULL, (void*) &stat, 0))
|
||||
goto err; /* purecov: inspected */
|
||||
share->rec_per_key[i]= (stat->bt_ndata /
|
||||
(stat->bt_nkeys ? stat->bt_nkeys : 1));
|
||||
@@ -2302,7 +2305,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
|
||||
free(stat);
|
||||
stat=0;
|
||||
}
|
||||
if ((file->stat)(file, (void*) &stat, 0))
|
||||
if ((file->stat)(file, NULL, (void*) &stat, 0))
|
||||
goto err; /* purecov: inspected */
|
||||
}
|
||||
pthread_mutex_lock(&share->mutex);
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
/*-
|
||||
* $Id: LICENSE,v 11.9 2002/01/11 15:51:10 bostic Exp $
|
||||
* $Id: LICENSE,v 11.12 2004/03/30 20:49:44 bostic Exp $
|
||||
*/
|
||||
|
||||
The following is the license that applies to this copy of the Berkeley DB
|
||||
software. For a license to use the Berkeley DB software under conditions
|
||||
other than those described here, or to purchase support for this software,
|
||||
please contact Sleepycat Software by email at db@sleepycat.com, or on the
|
||||
Web at http://www.sleepycat.com.
|
||||
please contact Sleepycat Software by email at info@sleepycat.com, or on
|
||||
the Web at http://www.sleepycat.com.
|
||||
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
/*
|
||||
* Copyright (c) 1990-2002
|
||||
* Copyright (c) 1990-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -38,14 +38,12 @@
|
||||
* 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 11.20 2004/02/21 15:54:44 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_compare.c,v 11.17 2002/03/27 04:30:42 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -204,8 +202,12 @@ __bam_defpfx(dbp, a, b)
|
||||
return (cnt);
|
||||
|
||||
/*
|
||||
* We know that a->size must be <= b->size, or they wouldn't be
|
||||
* in this order.
|
||||
* They match up to the smaller of the two sizes.
|
||||
* Collate the longer after the shorter.
|
||||
*/
|
||||
return (a->size < b->size ? a->size + 1 : a->size);
|
||||
if (a->size < b->size)
|
||||
return (a->size + 1);
|
||||
if (b->size < a->size)
|
||||
return (b->size + 1);
|
||||
return (b->size);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: bt_conv.c,v 11.15 2004/01/28 03:35:48 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_conv.c,v 11.13 2002/08/06 06:11:12 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: bt_curadj.c,v 11.37 2004/03/13 14:11:33 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_curadj.c,v 11.30 2002/07/03 19:03:48 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -21,30 +19,6 @@ static const char revid[] = "$Id: bt_curadj.c,v 11.30 2002/07/03 19:03:48 bostic
|
||||
|
||||
static int __bam_opd_cursor __P((DB *, DBC *, db_pgno_t, u_int32_t, u_int32_t));
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* __bam_cprint --
|
||||
* Display the current internal cursor.
|
||||
*
|
||||
* PUBLIC: void __bam_cprint __P((DBC *));
|
||||
*/
|
||||
void
|
||||
__bam_cprint(dbc)
|
||||
DBC *dbc;
|
||||
{
|
||||
BTREE_CURSOR *cp;
|
||||
|
||||
cp = (BTREE_CURSOR *)dbc->internal;
|
||||
|
||||
fprintf(stderr, "\tinternal: ovflsize: %lu", (u_long)cp->ovflsize);
|
||||
if (dbc->dbtype == DB_RECNO)
|
||||
fprintf(stderr, " recno: %lu", (u_long)cp->recno);
|
||||
if (F_ISSET(cp, C_DELETED))
|
||||
fprintf(stderr, " (deleted)");
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Cursor adjustments are logged if they are for subtransactions. This is
|
||||
* because it's possible for a subtransaction to adjust cursors which will
|
||||
@@ -98,6 +72,19 @@ __bam_ca_delete(dbp, pgno, indx, delete)
|
||||
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
|
||||
@@ -192,7 +179,10 @@ __bam_ca_di(my_dbc, pgno, indx, adjust)
|
||||
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;
|
||||
@@ -203,8 +193,8 @@ __bam_ca_di(my_dbc, pgno, indx, adjust)
|
||||
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
|
||||
|
||||
if (found != 0 && DBC_LOGGING(my_dbc)) {
|
||||
if ((ret = __bam_curadj_log(dbp, my_dbc->txn,
|
||||
&lsn, 0, DB_CA_DI, pgno, 0, 0, adjust, indx, 0)) != 0)
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -319,6 +309,10 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
|
||||
continue;
|
||||
|
||||
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
|
||||
/* [#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);
|
||||
@@ -388,7 +382,7 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
|
||||
!= ti)
|
||||
continue;
|
||||
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
|
||||
if ((ret = orig_cp->opd->c_close(orig_cp->opd)) != 0)
|
||||
if ((ret = __db_c_close(orig_cp->opd)) != 0)
|
||||
return (ret);
|
||||
orig_cp->opd = NULL;
|
||||
orig_cp->indx = fi;
|
||||
@@ -442,6 +436,10 @@ __bam_ca_rsplit(my_dbc, fpgno, tpgno)
|
||||
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;
|
||||
}
|
||||
@@ -506,6 +504,10 @@ __bam_ca_split(my_dbc, ppgno, lpgno, rpgno, split_indx, cleft)
|
||||
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) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -38,14 +38,12 @@
|
||||
* 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 11.49 2004/02/27 12:38:28 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_delete.c,v 11.44 2002/07/03 19:03:49 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -57,6 +55,7 @@ static const char revid[] = "$Id: bt_delete.c,v 11.44 2002/07/03 19:03:49 bostic
|
||||
#include "dbinc/db_shash.h"
|
||||
#include "dbinc/btree.h"
|
||||
#include "dbinc/lock.h"
|
||||
#include "dbinc/mp.h"
|
||||
|
||||
/*
|
||||
* __bam_ditem --
|
||||
@@ -161,7 +160,7 @@ __bam_ditem(dbc, h, indx)
|
||||
/* Delete the item and mark the page dirty. */
|
||||
if ((ret = __db_ditem(dbc, h, indx, nbytes)) != 0)
|
||||
return (ret);
|
||||
if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0)
|
||||
if ((ret = __memp_fset(mpf, h, DB_MPOOL_DIRTY)) != 0)
|
||||
return (ret);
|
||||
|
||||
return (0);
|
||||
@@ -211,7 +210,7 @@ __bam_adjindx(dbc, h, indx, indx_copy, is_insert)
|
||||
memmove(&inp[indx], &inp[indx + O_INDX],
|
||||
sizeof(db_indx_t) * (NUM_ENT(h) - indx));
|
||||
}
|
||||
if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0)
|
||||
if ((ret = __memp_fset(mpf, h, DB_MPOOL_DIRTY)) != 0)
|
||||
return (ret);
|
||||
|
||||
return (0);
|
||||
@@ -260,9 +259,10 @@ __bam_dpages(dbc, stack_epg)
|
||||
*/
|
||||
ret = 0;
|
||||
for (epg = cp->sp; epg < stack_epg; ++epg) {
|
||||
if ((t_ret = mpf->put(mpf, epg->page, 0)) != 0 && ret == 0)
|
||||
if ((t_ret = __memp_fput(mpf, epg->page, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
(void)__TLPUT(dbc, epg->lock);
|
||||
}
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
@@ -276,7 +276,7 @@ __bam_dpages(dbc, stack_epg)
|
||||
* It will deadlock here. Before we unlink the subtree, we relink the
|
||||
* leaf page chain.
|
||||
*/
|
||||
if ((ret = __db_relink(dbc, DB_REM_PAGE, cp->csp->page, NULL, 1)) != 0)
|
||||
if ((ret = __bam_relink(dbc, cp->csp->page, NULL)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
@@ -295,9 +295,11 @@ __bam_dpages(dbc, stack_epg)
|
||||
pgno = PGNO(epg->page);
|
||||
nitems = NUM_ENT(epg->page);
|
||||
|
||||
if ((ret = mpf->put(mpf, epg->page, 0)) != 0)
|
||||
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;
|
||||
(void)__TLPUT(dbc, epg->lock);
|
||||
|
||||
/* Free the rest of the pages in the stack. */
|
||||
while (++epg <= cp->csp) {
|
||||
@@ -314,18 +316,19 @@ __bam_dpages(dbc, stack_epg)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((ret = __db_free(dbc, epg->page)) != 0) {
|
||||
epg->page = NULL;
|
||||
ret = __db_free(dbc, epg->page);
|
||||
epg->page = NULL;
|
||||
if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if (ret != 0)
|
||||
goto err_inc;
|
||||
}
|
||||
(void)__TLPUT(dbc, epg->lock);
|
||||
}
|
||||
|
||||
if (0) {
|
||||
err_inc: ++epg;
|
||||
err: for (; epg <= cp->csp; ++epg) {
|
||||
if (epg->page != NULL)
|
||||
(void)mpf->put(mpf, epg->page, 0);
|
||||
(void)__memp_fput(mpf, epg->page, 0);
|
||||
(void)__TLPUT(dbc, epg->lock);
|
||||
}
|
||||
BT_STK_CLR(cp);
|
||||
@@ -354,7 +357,7 @@ err: for (; epg <= cp->csp; ++epg) {
|
||||
if ((ret =
|
||||
__db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &p_lock)) != 0)
|
||||
goto stop;
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &parent)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &parent)) != 0)
|
||||
goto stop;
|
||||
|
||||
if (NUM_ENT(parent) != 1)
|
||||
@@ -384,7 +387,7 @@ err: for (; epg <= cp->csp; ++epg) {
|
||||
if ((ret =
|
||||
__db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &c_lock)) != 0)
|
||||
goto stop;
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &child)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &child)) != 0)
|
||||
goto stop;
|
||||
|
||||
/* Log the change. */
|
||||
@@ -423,9 +426,9 @@ err: for (; epg <= cp->csp; ++epg) {
|
||||
RE_NREC_SET(parent, rcnt);
|
||||
|
||||
/* Mark the pages dirty. */
|
||||
if ((ret = mpf->set(mpf, parent, DB_MPOOL_DIRTY)) != 0)
|
||||
if ((ret = __memp_fset(mpf, parent, DB_MPOOL_DIRTY)) != 0)
|
||||
goto stop;
|
||||
if ((ret = mpf->set(mpf, child, DB_MPOOL_DIRTY)) != 0)
|
||||
if ((ret = __memp_fset(mpf, child, DB_MPOOL_DIRTY)) != 0)
|
||||
goto stop;
|
||||
|
||||
/* Adjust the cursors. */
|
||||
@@ -446,15 +449,125 @@ err: for (; epg <= cp->csp; ++epg) {
|
||||
if (0) {
|
||||
stop: done = 1;
|
||||
}
|
||||
(void)__TLPUT(dbc, p_lock);
|
||||
if (parent != NULL &&
|
||||
(t_ret = mpf->put(mpf, parent, 0)) != 0 && ret == 0)
|
||||
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;
|
||||
(void)__TLPUT(dbc, c_lock);
|
||||
if (child != NULL &&
|
||||
(t_ret = mpf->put(mpf, child, 0)) != 0 && ret == 0)
|
||||
(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 *, PAGE **));
|
||||
*/
|
||||
int
|
||||
__bam_relink(dbc, pagep, new_next)
|
||||
DBC *dbc;
|
||||
PAGE *pagep, **new_next;
|
||||
{
|
||||
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, &pagep->lsn, 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;
|
||||
pagep->lsn = ret_lsn;
|
||||
|
||||
/*
|
||||
* Modify and release the two pages.
|
||||
*
|
||||
* !!!
|
||||
* The parameter new_next gets set to the page following the page we
|
||||
* are removing. If there is no following page, then new_next gets
|
||||
* set to NULL.
|
||||
*/
|
||||
if (np != NULL) {
|
||||
np->prev_pgno = pagep->prev_pgno;
|
||||
if (new_next == NULL)
|
||||
ret = __memp_fput(mpf, np, DB_MPOOL_DIRTY);
|
||||
else {
|
||||
*new_next = np;
|
||||
ret = __memp_fset(mpf, np, DB_MPOOL_DIRTY);
|
||||
}
|
||||
if ((t_ret = __TLPUT(dbc, npl)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
} else if (new_next != NULL)
|
||||
*new_next = NULL;
|
||||
|
||||
if (pp != NULL) {
|
||||
pp->next_pgno = pagep->next_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);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1999-2002
|
||||
* Copyright (c) 1999-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: bt_method.c,v 11.38 2004/09/22 03:31:26 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_method.c,v 11.29 2002/04/21 13:17:04 margo Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -20,15 +18,15 @@ static const char revid[] = "$Id: bt_method.c,v 11.29 2002/04/21 13:17:04 margo
|
||||
#include "dbinc/btree.h"
|
||||
#include "dbinc/qam.h"
|
||||
|
||||
static int __bam_set_bt_compare
|
||||
__P((DB *, int (*)(DB *, const DBT *, const DBT *)));
|
||||
static int __bam_set_bt_maxkey __P((DB *, u_int32_t));
|
||||
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 *));
|
||||
|
||||
/*
|
||||
@@ -55,6 +53,7 @@ __bam_db_create(dbp)
|
||||
|
||||
dbp->set_bt_compare = __bam_set_bt_compare;
|
||||
dbp->set_bt_maxkey = __bam_set_bt_maxkey;
|
||||
dbp->get_bt_minkey = __bam_get_bt_minkey;
|
||||
dbp->set_bt_minkey = __bam_set_bt_minkey;
|
||||
dbp->set_bt_prefix = __bam_set_bt_prefix;
|
||||
|
||||
@@ -62,9 +61,13 @@ __bam_db_create(dbp)
|
||||
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);
|
||||
@@ -99,6 +102,37 @@ __bam_db_close(dbp)
|
||||
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.
|
||||
@@ -113,50 +147,31 @@ __bam_set_flags(dbp, flagsp)
|
||||
u_int32_t flags;
|
||||
|
||||
flags = *flagsp;
|
||||
if (LF_ISSET(DB_DUP | DB_DUPSORT | DB_RECNUM | DB_REVSPLITOFF)) {
|
||||
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);
|
||||
/*
|
||||
* 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);
|
||||
if (LF_ISSET(DB_RECNUM | DB_REVSPLITOFF))
|
||||
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
|
||||
|
||||
if (LF_ISSET(DB_DUP | DB_DUPSORT)) {
|
||||
/* DB_DUP/DB_DUPSORT is incompatible with DB_RECNUM. */
|
||||
if (F_ISSET(dbp, DB_AM_RECNUM))
|
||||
goto incompat;
|
||||
/* DB_DUP/DB_DUPSORT is incompatible with DB_RECNUM. */
|
||||
if (LF_ISSET(DB_DUP | DB_DUPSORT) && F_ISSET(dbp, DB_AM_RECNUM))
|
||||
goto incompat;
|
||||
|
||||
if (LF_ISSET(DB_DUPSORT)) {
|
||||
if (dbp->dup_compare == NULL)
|
||||
dbp->dup_compare = __bam_defcmp;
|
||||
F_SET(dbp, DB_AM_DUPSORT);
|
||||
}
|
||||
/* DB_RECNUM is incompatible with DB_DUP/DB_DUPSORT. */
|
||||
if (LF_ISSET(DB_RECNUM) && F_ISSET(dbp, DB_AM_DUP))
|
||||
goto incompat;
|
||||
|
||||
F_SET(dbp, DB_AM_DUP);
|
||||
LF_CLR(DB_DUP | DB_DUPSORT);
|
||||
}
|
||||
if (LF_ISSET(DB_DUPSORT) && dbp->dup_compare == NULL)
|
||||
dbp->dup_compare = __bam_defcmp;
|
||||
|
||||
if (LF_ISSET(DB_RECNUM)) {
|
||||
/* DB_RECNUM is incompatible with DB_DUP/DB_DUPSORT. */
|
||||
if (F_ISSET(dbp, DB_AM_DUP))
|
||||
goto incompat;
|
||||
|
||||
F_SET(dbp, DB_AM_RECNUM);
|
||||
LF_CLR(DB_RECNUM);
|
||||
}
|
||||
|
||||
if (LF_ISSET(DB_REVSPLITOFF)) {
|
||||
F_SET(dbp, DB_AM_REVSPLITOFF);
|
||||
LF_CLR(DB_REVSPLITOFF);
|
||||
}
|
||||
|
||||
*flagsp = flags;
|
||||
}
|
||||
__bam_map_flags(dbp, flagsp, &dbp->flags);
|
||||
return (0);
|
||||
|
||||
incompat:
|
||||
@@ -166,15 +181,18 @@ incompat:
|
||||
/*
|
||||
* __bam_set_bt_compare --
|
||||
* Set the comparison function.
|
||||
*
|
||||
* PUBLIC: int __bam_set_bt_compare
|
||||
* PUBLIC: __P((DB *, int (*)(DB *, const DBT *, const DBT *)));
|
||||
*/
|
||||
static int
|
||||
int
|
||||
__bam_set_bt_compare(dbp, func)
|
||||
DB *dbp;
|
||||
int (*func) __P((DB *, const DBT *, const DBT *));
|
||||
{
|
||||
BTREE *t;
|
||||
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_bt_compare");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_compare");
|
||||
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
|
||||
|
||||
t = dbp->bt_internal;
|
||||
@@ -201,7 +219,7 @@ __bam_set_bt_maxkey(dbp, bt_maxkey)
|
||||
{
|
||||
BTREE *t;
|
||||
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_bt_maxkey");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_maxkey");
|
||||
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
|
||||
|
||||
t = dbp->bt_internal;
|
||||
@@ -215,6 +233,26 @@ __bam_set_bt_maxkey(dbp, bt_maxkey)
|
||||
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.
|
||||
@@ -226,7 +264,7 @@ __bam_set_bt_minkey(dbp, bt_minkey)
|
||||
{
|
||||
BTREE *t;
|
||||
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_bt_minkey");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_minkey");
|
||||
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
|
||||
|
||||
t = dbp->bt_internal;
|
||||
@@ -251,7 +289,7 @@ __bam_set_bt_prefix(dbp, func)
|
||||
{
|
||||
BTREE *t;
|
||||
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_bt_prefix");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_prefix");
|
||||
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
|
||||
|
||||
t = dbp->bt_internal;
|
||||
@@ -260,6 +298,29 @@ __bam_set_bt_prefix(dbp, 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.
|
||||
@@ -276,21 +337,27 @@ __ram_set_flags(dbp, flagsp)
|
||||
flags = *flagsp;
|
||||
if (LF_ISSET(DB_RENUMBER | DB_SNAPSHOT)) {
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_flags");
|
||||
|
||||
DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
|
||||
|
||||
if (LF_ISSET(DB_RENUMBER)) {
|
||||
F_SET(dbp, DB_AM_RENUMBER);
|
||||
LF_CLR(DB_RENUMBER);
|
||||
}
|
||||
|
||||
if (LF_ISSET(DB_SNAPSHOT)) {
|
||||
F_SET(dbp, DB_AM_SNAPSHOT);
|
||||
LF_CLR(DB_SNAPSHOT);
|
||||
}
|
||||
|
||||
*flagsp = flags;
|
||||
}
|
||||
|
||||
__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);
|
||||
}
|
||||
|
||||
@@ -305,7 +372,7 @@ __ram_set_re_delim(dbp, re_delim)
|
||||
{
|
||||
BTREE *t;
|
||||
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_re_delim");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_delim");
|
||||
DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
|
||||
|
||||
t = dbp->bt_internal;
|
||||
@@ -316,6 +383,40 @@ __ram_set_re_delim(dbp, re_delim)
|
||||
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.
|
||||
@@ -328,7 +429,7 @@ __ram_set_re_len(dbp, re_len)
|
||||
BTREE *t;
|
||||
QUEUE *q;
|
||||
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_re_len");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_len");
|
||||
DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
|
||||
|
||||
t = dbp->bt_internal;
|
||||
@@ -342,6 +443,40 @@ __ram_set_re_len(dbp, re_len)
|
||||
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.
|
||||
@@ -354,7 +489,7 @@ __ram_set_re_pad(dbp, re_pad)
|
||||
BTREE *t;
|
||||
QUEUE *q;
|
||||
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_re_pad");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_pad");
|
||||
DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
|
||||
|
||||
t = dbp->bt_internal;
|
||||
@@ -368,6 +503,24 @@ __ram_set_re_pad(dbp, re_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.
|
||||
@@ -379,7 +532,7 @@ __ram_set_re_source(dbp, re_source)
|
||||
{
|
||||
BTREE *t;
|
||||
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_re_source");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_source");
|
||||
DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
|
||||
|
||||
t = dbp->bt_internal;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -38,18 +38,15 @@
|
||||
* 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 11.92 2004/04/29 14:39:47 ubell Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_open.c,v 11.76 2002/09/04 19:06:42 margo Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
@@ -61,6 +58,7 @@ static const char revid[] = "$Id: bt_open.c,v 11.76 2002/09/04 19:06:42 margo Ex
|
||||
#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 *));
|
||||
@@ -85,10 +83,6 @@ __bam_open(dbp, txn, name, base_pgno, flags)
|
||||
COMPQUIET(name, NULL);
|
||||
t = dbp->bt_internal;
|
||||
|
||||
/* Initialize the remaining fields/methods of the DB. */
|
||||
dbp->key_range = __bam_key_range;
|
||||
dbp->stat = __bam_stat;
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -290,6 +284,7 @@ __bam_read_root(dbp, txn, base_pgno, flags)
|
||||
DB_MPOOLFILE *mpf;
|
||||
int ret, t_ret;
|
||||
|
||||
COMPQUIET(flags, 0);
|
||||
meta = NULL;
|
||||
t = dbp->bt_internal;
|
||||
LOCK_INIT(metalock);
|
||||
@@ -297,14 +292,14 @@ __bam_read_root(dbp, txn, base_pgno, flags)
|
||||
ret = 0;
|
||||
|
||||
/* Get a cursor. */
|
||||
if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
|
||||
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 = mpf->get(mpf, &base_pgno, 0, (PAGE **)&meta)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &base_pgno, 0, &meta)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
@@ -315,16 +310,18 @@ __bam_read_root(dbp, txn, base_pgno, flags)
|
||||
* Otherwise, we'd better be in recovery or abort, in which case the
|
||||
* metadata page will be created/initialized elsewhere.
|
||||
*/
|
||||
DB_ASSERT(meta->dbmeta.magic != 0 ||
|
||||
IS_RECOVERING(dbp->dbenv) || F_ISSET(dbp, DB_AM_RECOVER));
|
||||
if (meta->dbmeta.magic == DB_BTREEMAGIC) {
|
||||
t->bt_maxkey = meta->maxkey;
|
||||
t->bt_minkey = meta->minkey;
|
||||
t->re_pad = (int)meta->re_pad;
|
||||
t->re_len = meta->re_len;
|
||||
|
||||
t->bt_maxkey = meta->maxkey;
|
||||
t->bt_minkey = meta->minkey;
|
||||
t->re_pad = meta->re_pad;
|
||||
t->re_len = meta->re_len;
|
||||
|
||||
t->bt_meta = base_pgno;
|
||||
t->bt_root = meta->root;
|
||||
t->bt_meta = base_pgno;
|
||||
t->bt_root = meta->root;
|
||||
} else {
|
||||
DB_ASSERT(IS_RECOVERING(dbp->dbenv) ||
|
||||
F_ISSET(dbp, DB_AM_RECOVER));
|
||||
}
|
||||
|
||||
/*
|
||||
* !!!
|
||||
@@ -337,21 +334,14 @@ __bam_read_root(dbp, txn, base_pgno, flags)
|
||||
*/
|
||||
t->bt_lpgno = PGNO_INVALID;
|
||||
|
||||
/* We must initialize last_pgno, it could be stale. */
|
||||
if (!LF_ISSET(DB_RDONLY) && dbp->meta_pgno == PGNO_BASE_MD) {
|
||||
mpf->last_pgno(mpf, &meta->dbmeta.last_pgno);
|
||||
ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY);
|
||||
} else
|
||||
ret = mpf->put(mpf, meta, 0);
|
||||
meta = NULL;
|
||||
|
||||
err: /* Put the metadata page back. */
|
||||
if (meta != NULL && (t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
|
||||
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 = dbc->c_close(dbc)) != 0 && ret == 0)
|
||||
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
return (ret);
|
||||
}
|
||||
@@ -408,7 +398,7 @@ __bam_init_meta(dbp, meta, pgno, lsnp)
|
||||
meta->maxkey = t->bt_maxkey;
|
||||
meta->minkey = t->bt_minkey;
|
||||
meta->re_len = t->re_len;
|
||||
meta->re_pad = t->re_pad;
|
||||
meta->re_pad = (u_int32_t)t->re_pad;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -418,8 +408,8 @@ __bam_init_meta(dbp, meta, pgno, lsnp)
|
||||
* 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 mpf->get), 2) the initialization, and 3) the "put page"
|
||||
* chunk which either does a fop write or an mpf->put.
|
||||
* 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 *));
|
||||
*/
|
||||
@@ -445,78 +435,84 @@ __bam_new_file(dbp, txn, fhp, name)
|
||||
mpf = dbp->mpf;
|
||||
root = NULL;
|
||||
meta = NULL;
|
||||
memset(&pdbt, 0, sizeof(pdbt));
|
||||
|
||||
/* Build meta-data page. */
|
||||
buf = NULL;
|
||||
|
||||
if (name == NULL) {
|
||||
/* Build the meta-data page. */
|
||||
pgno = PGNO_BASE_MD;
|
||||
ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &meta);
|
||||
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;
|
||||
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);
|
||||
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);
|
||||
ret = __os_calloc(dbp->dbenv, 1, dbp->pgsize, &buf);
|
||||
if ((ret = __os_calloc(dbenv, 1, dbp->pgsize, &buf)) != 0)
|
||||
return (ret);
|
||||
meta = (BTMETA *)buf;
|
||||
}
|
||||
if (ret != 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 (name == NULL)
|
||||
ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY);
|
||||
else {
|
||||
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;
|
||||
ret = __fop_write(dbenv,
|
||||
txn, name, DB_APP_DATA, fhp, 0, buf, dbp->pgsize, 1);
|
||||
}
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
meta = NULL;
|
||||
|
||||
/* Now build root page. */
|
||||
if (name == NULL) {
|
||||
pgno = 1;
|
||||
if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &root)) != 0)
|
||||
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;
|
||||
} else {
|
||||
meta = NULL;
|
||||
|
||||
/* Build the root page. */
|
||||
#ifdef DIAGNOSTIC
|
||||
memset(buf, 0, dbp->pgsize);
|
||||
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 (name == NULL)
|
||||
ret = mpf->put(mpf, root, DB_MPOOL_DIRTY);
|
||||
else {
|
||||
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;
|
||||
ret = __fop_write(dbenv, txn,
|
||||
name, DB_APP_DATA, fhp, dbp->pgsize, buf, dbp->pgsize, 1);
|
||||
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;
|
||||
}
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
root = NULL;
|
||||
|
||||
err: if (name != NULL)
|
||||
err: if (buf != NULL)
|
||||
__os_free(dbenv, buf);
|
||||
else {
|
||||
if (meta != NULL)
|
||||
(void)mpf->put(mpf, meta, 0);
|
||||
(void)__memp_fput(mpf, meta, 0);
|
||||
if (root != NULL)
|
||||
(void)mpf->put(mpf, root, 0);
|
||||
(void)__memp_fput(mpf, root, 0);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
@@ -547,7 +543,7 @@ __bam_new_subdb(mdbp, dbp, txn)
|
||||
meta = NULL;
|
||||
root = NULL;
|
||||
|
||||
if ((ret = mdbp->cursor(mdbp, txn,
|
||||
if ((ret = __db_cursor(mdbp, txn,
|
||||
&dbc, CDB_LOCKING(dbenv) ? DB_WRITECURSOR : 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
@@ -555,7 +551,8 @@ __bam_new_subdb(mdbp, dbp, txn)
|
||||
if ((ret = __db_lget(dbc,
|
||||
0, dbp->meta_pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
|
||||
goto err;
|
||||
if ((ret = mpf->get(mpf, &dbp->meta_pgno, DB_MPOOL_CREATE, &meta)) != 0)
|
||||
if ((ret =
|
||||
__memp_fget(mpf, &dbp->meta_pgno, DB_MPOOL_CREATE, &meta)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Build meta-data page. */
|
||||
@@ -582,24 +579,23 @@ __bam_new_subdb(mdbp, dbp, txn)
|
||||
goto err;
|
||||
|
||||
/* Release the metadata and root pages. */
|
||||
if ((ret = mpf->put(mpf, meta, DB_MPOOL_DIRTY)) != 0)
|
||||
if ((ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY)) != 0)
|
||||
goto err;
|
||||
meta = NULL;
|
||||
if ((ret = mpf->put(mpf, root, DB_MPOOL_DIRTY)) != 0)
|
||||
if ((ret = __memp_fput(mpf, root, DB_MPOOL_DIRTY)) != 0)
|
||||
goto err;
|
||||
root = NULL;
|
||||
err:
|
||||
if (meta != NULL)
|
||||
if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
|
||||
if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if (root != NULL)
|
||||
if ((t_ret = mpf->put(mpf, root, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if (LOCK_ISSET(metalock))
|
||||
if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
|
||||
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 = dbc->c_close(dbc)) != 0 && ret == 0)
|
||||
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -38,14 +38,12 @@
|
||||
* 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 11.80 2004/10/29 17:33:25 ubell Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_put.c,v 11.69 2002/08/06 06:11:12 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -54,7 +52,9 @@ static const char revid[] = "$Id: bt_put.c,v 11.69 2002/08/06 06:11:12 bostic Ex
|
||||
|
||||
#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));
|
||||
@@ -76,6 +76,7 @@ __bam_iitem(dbc, key, data, op, flags)
|
||||
DBT *key, *data;
|
||||
u_int32_t op, flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
BKEYDATA *bk, bk_tmp;
|
||||
BTREE *t;
|
||||
BTREE_CURSOR *cp;
|
||||
@@ -90,6 +91,7 @@ __bam_iitem(dbc, key, data, op, flags)
|
||||
COMPQUIET(bk, NULL);
|
||||
|
||||
dbp = dbc->dbp;
|
||||
dbenv = dbp->dbenv;
|
||||
mpf = dbp->mpf;
|
||||
cp = (BTREE_CURSOR *)dbc->internal;
|
||||
t = dbp->bt_internal;
|
||||
@@ -102,10 +104,8 @@ __bam_iitem(dbc, key, data, op, flags)
|
||||
* anything other simple overwrite.
|
||||
*/
|
||||
if (F_ISSET(dbp, DB_AM_FIXEDLEN) &&
|
||||
F_ISSET(data, DB_DBT_PARTIAL) && data->dlen != data->size) {
|
||||
data_size = data->size;
|
||||
goto len_err;
|
||||
}
|
||||
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
|
||||
@@ -119,12 +119,8 @@ __bam_iitem(dbc, key, data, op, flags)
|
||||
__bam_partsize(dbp, op, data, h, indx) : data->size;
|
||||
padrec = 0;
|
||||
if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
|
||||
if (data_size > t->re_len) {
|
||||
len_err: __db_err(dbp->dbenv,
|
||||
"Length improper for fixed length record %lu",
|
||||
(u_long)data_size);
|
||||
return (EINVAL);
|
||||
}
|
||||
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) {
|
||||
@@ -158,8 +154,8 @@ len_err: __db_err(dbp->dbenv,
|
||||
dbp->dup_compare, &cmp)) != 0)
|
||||
return (ret);
|
||||
if (cmp != 0) {
|
||||
__db_err(dbp->dbenv,
|
||||
"Current data differs from put data");
|
||||
__db_err(dbenv,
|
||||
"Existing data sorts differently from put data");
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
@@ -218,19 +214,14 @@ len_err: __db_err(dbp->dbenv,
|
||||
needed += need_bytes - have_bytes;
|
||||
break;
|
||||
default:
|
||||
return (__db_unknown_flag(dbp->dbenv, "__bam_iitem", op));
|
||||
return (__db_unknown_flag(dbenv, "DB->put", op));
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's not enough room, or the user has put a ceiling on the
|
||||
* number of keys permitted in the page, split the page.
|
||||
*
|
||||
* XXX
|
||||
* The t->bt_maxkey test here may be insufficient -- do we have to
|
||||
* check in the btree split code, so we don't undo it there!?!?
|
||||
*/
|
||||
if (P_FREESPACE(dbp, h) < needed ||
|
||||
(t->bt_maxkey != 0 && NUM_ENT(h) > t->bt_maxkey))
|
||||
if (P_FREESPACE(dbp, h) < needed)
|
||||
return (DB_NEEDSPLIT);
|
||||
|
||||
/*
|
||||
@@ -294,24 +285,25 @@ len_err: __db_err(dbp->dbenv,
|
||||
* 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
|
||||
* flag is set.
|
||||
*/
|
||||
(void)__bam_ca_delete(dbp, PGNO(h), indx, 0);
|
||||
|
||||
if (TYPE(h) == P_LBTREE) {
|
||||
++indx;
|
||||
dupadjust = 1;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
was_deleted = B_DISSET(bk->type);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
@@ -331,7 +323,7 @@ len_err: __db_err(dbp->dbenv,
|
||||
replace = 1;
|
||||
break;
|
||||
default:
|
||||
return (__db_unknown_flag(dbp->dbenv, "__bam_iitem", op));
|
||||
return (__db_unknown_flag(dbenv, "DB->put", op));
|
||||
}
|
||||
|
||||
/* Add the data. */
|
||||
@@ -360,7 +352,7 @@ len_err: __db_err(dbp->dbenv,
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
}
|
||||
if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0)
|
||||
if ((ret = __memp_fset(mpf, h, DB_MPOOL_DIRTY)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
@@ -648,7 +640,7 @@ __bam_ritem(dbc, h, indx, data)
|
||||
if (p == t) /* First index is fast. */
|
||||
inp[indx] += nbytes;
|
||||
else { /* Else, shift the page. */
|
||||
memmove(p + nbytes, p, t - p);
|
||||
memmove(p + nbytes, p, (size_t)(t - p));
|
||||
|
||||
/* Adjust the indices' offsets. */
|
||||
off = inp[indx];
|
||||
@@ -700,12 +692,16 @@ __bam_dup_convert(dbc, h, indx)
|
||||
*/
|
||||
while (indx > 0 && inp[indx] == inp[indx - P_INDX])
|
||||
indx -= P_INDX;
|
||||
for (cnt = 0, sz = 0, first = indx;; ++cnt, indx += P_INDX) {
|
||||
if (indx >= NUM_ENT(h) || inp[first] != inp[indx])
|
||||
break;
|
||||
bk = GET_BKEYDATA(dbp, h, indx);
|
||||
sz += B_TYPE(bk->type) == B_KEYDATA ?
|
||||
BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE;
|
||||
|
||||
/* 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. */
|
||||
for (cnt = 0, 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;
|
||||
@@ -800,14 +796,14 @@ __bam_dup_convert(dbc, h, indx)
|
||||
B_DUPLICATE, dp->pgno, h, first + 1, NULL)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Adjust cursors for all the above movments. */
|
||||
/* Adjust cursors for all the above movements. */
|
||||
if ((ret = __bam_ca_di(dbc,
|
||||
PGNO(h), first + P_INDX, first + P_INDX - indx)) != 0)
|
||||
PGNO(h), first + P_INDX, (int)(first + P_INDX - indx))) != 0)
|
||||
goto err;
|
||||
|
||||
return (mpf->put(mpf, dp, DB_MPOOL_DIRTY));
|
||||
return (__memp_fput(mpf, dp, DB_MPOOL_DIRTY));
|
||||
|
||||
err: (void)mpf->put(mpf, dp, 0);
|
||||
err: (void)__memp_fput(mpf, dp, 0);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: bt_rec.c,v 11.70 2004/09/24 00:43:12 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_rec.c,v 11.57 2002/08/06 16:53:53 ubell Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -23,6 +21,7 @@ static const char revid[] = "$Id: bt_rec.c,v 11.57 2002/08/06 16:53:53 ubell Exp
|
||||
#include "dbinc/btree.h"
|
||||
#include "dbinc/lock.h"
|
||||
#include "dbinc/log.h"
|
||||
#include "dbinc/mp.h"
|
||||
|
||||
#define IS_BTREE_PAGE(pagep) \
|
||||
(TYPE(pagep) == P_IBTREE || \
|
||||
@@ -50,7 +49,7 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
|
||||
PAGE *_lp, *lp, *np, *pp, *_rp, *rp, *sp;
|
||||
db_pgno_t pgno, root_pgno;
|
||||
u_int32_t ptype;
|
||||
int cmp, l_update, p_update, r_update, rc, ret, ret_l, rootsplit, t_ret;
|
||||
int cmp, l_update, p_update, r_update, rc, ret, rootsplit, t_ret;
|
||||
|
||||
COMPQUIET(info, NULL);
|
||||
REC_PRINT(__bam_split_print);
|
||||
@@ -82,50 +81,40 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
|
||||
pgno = PGNO(sp);
|
||||
root_pgno = argp->root_pgno;
|
||||
rootsplit = root_pgno != PGNO_INVALID;
|
||||
if ((ret_l = mpf->get(mpf, &argp->left, 0, &lp)) != 0)
|
||||
lp = NULL;
|
||||
if (mpf->get(mpf, &argp->right, 0, &rp) != 0)
|
||||
rp = NULL;
|
||||
REC_FGET(mpf, argp->left, &lp, right);
|
||||
right: REC_FGET(mpf, argp->right, &rp, redo);
|
||||
|
||||
if (DB_REDO(op)) {
|
||||
redo: if (DB_REDO(op)) {
|
||||
l_update = r_update = p_update = 0;
|
||||
/*
|
||||
* Decide if we need to resplit the page.
|
||||
*
|
||||
* If this is a root split, then the root has to exist, it's
|
||||
* the page we're splitting and it gets modified. If this is
|
||||
* not a root split, then the left page has to exist, for the
|
||||
* same reason.
|
||||
* If this is a root split, then the root has to exist unless
|
||||
* we have truncated it due to a future deallocation.
|
||||
*/
|
||||
if (rootsplit) {
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &pp)) != 0) {
|
||||
__db_pgerr(file_dbp, pgno, ret);
|
||||
pp = NULL;
|
||||
goto out;
|
||||
}
|
||||
cmp = log_compare(&LSN(pp), &LSN(argp->pg.data));
|
||||
CHECK_LSN(op, cmp, &LSN(pp), &LSN(argp->pg.data));
|
||||
REC_FGET(mpf, root_pgno, &pp, do_left);
|
||||
cmp =
|
||||
log_compare(&LSN(pp), &LSN(argp->pg.data));
|
||||
CHECK_LSN(op,
|
||||
cmp, &LSN(pp), &LSN(argp->pg.data));
|
||||
p_update = cmp == 0;
|
||||
} else if (lp == NULL) {
|
||||
__db_pgerr(file_dbp, argp->left, ret_l);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lp != NULL) {
|
||||
do_left: if (lp != NULL) {
|
||||
cmp = log_compare(&LSN(lp), &argp->llsn);
|
||||
CHECK_LSN(op, cmp, &LSN(lp), &argp->llsn);
|
||||
if (cmp == 0)
|
||||
l_update = 1;
|
||||
} else
|
||||
l_update = 1;
|
||||
}
|
||||
|
||||
if (rp != NULL) {
|
||||
cmp = log_compare(&LSN(rp), &argp->rlsn);
|
||||
CHECK_LSN(op, cmp, &LSN(rp), &argp->rlsn);
|
||||
if (cmp == 0)
|
||||
r_update = 1;
|
||||
} else
|
||||
r_update = 1;
|
||||
}
|
||||
|
||||
if (!p_update && !l_update && !r_update)
|
||||
goto check_next;
|
||||
|
||||
@@ -158,32 +147,18 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
|
||||
NUM_ENT(sp))) != 0)
|
||||
goto out;
|
||||
|
||||
/* If the left child is wrong, update it. */
|
||||
if (lp == NULL && (ret = mpf->get(
|
||||
mpf, &argp->left, DB_MPOOL_CREATE, &lp)) != 0) {
|
||||
__db_pgerr(file_dbp, argp->left, ret);
|
||||
lp = NULL;
|
||||
goto out;
|
||||
}
|
||||
if (l_update) {
|
||||
memcpy(lp, _lp, file_dbp->pgsize);
|
||||
lp->lsn = *lsnp;
|
||||
if ((ret = mpf->put(mpf, lp, DB_MPOOL_DIRTY)) != 0)
|
||||
if ((ret = __memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto out;
|
||||
lp = NULL;
|
||||
}
|
||||
|
||||
/* If the right child is wrong, update it. */
|
||||
if (rp == NULL && (ret = mpf->get(
|
||||
mpf, &argp->right, DB_MPOOL_CREATE, &rp)) != 0) {
|
||||
__db_pgerr(file_dbp, argp->right, ret);
|
||||
rp = NULL;
|
||||
goto out;
|
||||
}
|
||||
if (r_update) {
|
||||
memcpy(rp, _rp, file_dbp->pgsize);
|
||||
rp->lsn = *lsnp;
|
||||
if ((ret = mpf->put(mpf, rp, DB_MPOOL_DIRTY)) != 0)
|
||||
if ((ret = __memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto out;
|
||||
rp = NULL;
|
||||
}
|
||||
@@ -205,11 +180,11 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
|
||||
|
||||
P_INIT(pp, file_dbp->pgsize, root_pgno,
|
||||
PGNO_INVALID, PGNO_INVALID, _lp->level + 1, ptype);
|
||||
RE_NREC_SET(pp, rc ? __bam_total(file_dbp, _lp) +
|
||||
RE_NREC_SET(pp, rc ? __bam_total(file_dbp, _lp) +
|
||||
__bam_total(file_dbp, _rp) : 0);
|
||||
|
||||
pp->lsn = *lsnp;
|
||||
if ((ret = mpf->put(mpf, pp, DB_MPOOL_DIRTY)) != 0)
|
||||
if ((ret = __memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto out;
|
||||
pp = NULL;
|
||||
}
|
||||
@@ -221,11 +196,19 @@ check_next: /*
|
||||
* previous-page pointer updated to our new page. The next
|
||||
* page must exist because we're redoing the operation.
|
||||
*/
|
||||
if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) {
|
||||
if ((ret = mpf->get(mpf, &argp->npgno, 0, &np)) != 0) {
|
||||
__db_pgerr(file_dbp, argp->npgno, ret);
|
||||
np = NULL;
|
||||
goto out;
|
||||
if (!rootsplit && argp->npgno != PGNO_INVALID) {
|
||||
if ((ret =
|
||||
__memp_fget(mpf, &argp->npgno, 0, &np)) != 0) {
|
||||
if (ret != DB_PAGE_NOTFOUND
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
|| DB_REDO(op)
|
||||
#endif
|
||||
) {
|
||||
ret = __db_pgerr(
|
||||
file_dbp, argp->npgno, ret);
|
||||
goto out;
|
||||
} else
|
||||
goto done;
|
||||
}
|
||||
cmp = log_compare(&LSN(np), &argp->nlsn);
|
||||
CHECK_LSN(op, cmp, &LSN(np), &argp->nlsn);
|
||||
@@ -233,7 +216,7 @@ check_next: /*
|
||||
PREV_PGNO(np) = argp->right;
|
||||
np->lsn = *lsnp;
|
||||
if ((ret =
|
||||
mpf->put(mpf, np, DB_MPOOL_DIRTY)) != 0)
|
||||
__memp_fput(mpf, np, DB_MPOOL_DIRTY)) != 0)
|
||||
goto out;
|
||||
np = NULL;
|
||||
}
|
||||
@@ -246,13 +229,13 @@ check_next: /*
|
||||
* the adds onto the page that caused the split, and there's
|
||||
* really no undo-ing to be done.
|
||||
*/
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &pp)) != 0) {
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &pp)) != 0) {
|
||||
pp = NULL;
|
||||
goto lrundo;
|
||||
}
|
||||
if (log_compare(lsnp, &LSN(pp)) == 0) {
|
||||
memcpy(pp, argp->pg.data, argp->pg.size);
|
||||
if ((ret = mpf->put(mpf, pp, DB_MPOOL_DIRTY)) != 0)
|
||||
if ((ret = __memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto out;
|
||||
pp = NULL;
|
||||
}
|
||||
@@ -270,7 +253,7 @@ lrundo: if ((rootsplit && lp != NULL) || rp != NULL) {
|
||||
log_compare(lsnp, &LSN(lp)) == 0) {
|
||||
lp->lsn = argp->llsn;
|
||||
if ((ret =
|
||||
mpf->put(mpf, lp, DB_MPOOL_DIRTY)) != 0)
|
||||
__memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto out;
|
||||
lp = NULL;
|
||||
}
|
||||
@@ -278,7 +261,7 @@ lrundo: if ((rootsplit && lp != NULL) || rp != NULL) {
|
||||
log_compare(lsnp, &LSN(rp)) == 0) {
|
||||
rp->lsn = argp->rlsn;
|
||||
if ((ret =
|
||||
mpf->put(mpf, rp, DB_MPOOL_DIRTY)) != 0)
|
||||
__memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto out;
|
||||
rp = NULL;
|
||||
}
|
||||
@@ -292,15 +275,16 @@ lrundo: if ((rootsplit && lp != NULL) || rp != NULL) {
|
||||
* possible that the next-page never existed, we ignore it as
|
||||
* if there's nothing to undo.
|
||||
*/
|
||||
if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) {
|
||||
if ((ret = mpf->get(mpf, &argp->npgno, 0, &np)) != 0) {
|
||||
if (!rootsplit && argp->npgno != PGNO_INVALID) {
|
||||
if ((ret =
|
||||
__memp_fget(mpf, &argp->npgno, 0, &np)) != 0) {
|
||||
np = NULL;
|
||||
goto done;
|
||||
}
|
||||
if (log_compare(lsnp, &LSN(np)) == 0) {
|
||||
PREV_PGNO(np) = argp->left;
|
||||
np->lsn = argp->nlsn;
|
||||
if (mpf->put(mpf, np, DB_MPOOL_DIRTY))
|
||||
if (__memp_fput(mpf, np, DB_MPOOL_DIRTY))
|
||||
goto out;
|
||||
np = NULL;
|
||||
}
|
||||
@@ -311,13 +295,13 @@ done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: /* Free any pages that weren't dirtied. */
|
||||
if (pp != NULL && (t_ret = mpf->put(mpf, pp, 0)) != 0 && ret == 0)
|
||||
if (pp != NULL && (t_ret = __memp_fput(mpf, pp, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if (lp != NULL && (t_ret = mpf->put(mpf, lp, 0)) != 0 && ret == 0)
|
||||
if (lp != NULL && (t_ret = __memp_fput(mpf, lp, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if (np != NULL && (t_ret = mpf->put(mpf, np, 0)) != 0 && ret == 0)
|
||||
if (np != NULL && (t_ret = __memp_fput(mpf, np, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if (rp != NULL && (t_ret = mpf->put(mpf, rp, 0)) != 0 && ret == 0)
|
||||
if (rp != NULL && (t_ret = __memp_fput(mpf, rp, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/* Free any allocated space. */
|
||||
@@ -362,18 +346,18 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
|
||||
|
||||
/* Fix the root page. */
|
||||
pgno = root_pgno = argp->root_pgno;
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0) {
|
||||
/* The root page must always exist if we are going forward. */
|
||||
if (DB_REDO(op)) {
|
||||
__db_pgerr(file_dbp, pgno, ret);
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0) {
|
||||
if (ret != DB_PAGE_NOTFOUND
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
|| DB_REDO(op)
|
||||
#endif
|
||||
) {
|
||||
ret = __db_pgerr(file_dbp, pgno, ret);
|
||||
goto out;
|
||||
}
|
||||
/* This must be the root of an OPD tree. */
|
||||
DB_ASSERT(root_pgno !=
|
||||
((BTREE *)file_dbp->bt_internal)->bt_root);
|
||||
ret = 0;
|
||||
goto do_page;
|
||||
} else
|
||||
goto do_page;
|
||||
}
|
||||
|
||||
modified = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->rootlsn);
|
||||
@@ -395,7 +379,7 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
|
||||
pagep->lsn = argp->rootlsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
|
||||
do_page:
|
||||
@@ -404,11 +388,16 @@ do_page:
|
||||
* page never made it to disk, so if we're undo-ing and the page
|
||||
* doesn't exist, it's okay and there's nothing further to do.
|
||||
*/
|
||||
if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (DB_UNDO(op))
|
||||
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (ret != DB_PAGE_NOTFOUND
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
|| DB_REDO(op)
|
||||
#endif
|
||||
) {
|
||||
ret = __db_pgerr(file_dbp, argp->pgno, ret);
|
||||
goto out;
|
||||
} else
|
||||
goto done;
|
||||
__db_pgerr(file_dbp, argp->pgno, ret);
|
||||
goto out;
|
||||
}
|
||||
modified = 0;
|
||||
(void)__ua_memcpy(©_lsn, &LSN(argp->pgdbt.data), sizeof(DB_LSN));
|
||||
@@ -424,7 +413,7 @@ do_page:
|
||||
memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size);
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
pagep = NULL;
|
||||
|
||||
@@ -432,7 +421,7 @@ done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: if (pagep != NULL)
|
||||
(void)mpf->put(mpf, pagep, 0);
|
||||
(void)__memp_fput(mpf, pagep, 0);
|
||||
REC_CLOSE;
|
||||
}
|
||||
|
||||
@@ -464,11 +453,16 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
|
||||
REC_INTRO(__bam_adj_read, 1);
|
||||
|
||||
/* Get the page; if it never existed and we're undoing, we're done. */
|
||||
if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (DB_UNDO(op))
|
||||
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (ret != DB_PAGE_NOTFOUND
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
|| DB_REDO(op)
|
||||
#endif
|
||||
) {
|
||||
ret = __db_pgerr(file_dbp, argp->pgno, ret);
|
||||
goto out;
|
||||
} else
|
||||
goto done;
|
||||
__db_pgerr(file_dbp, argp->pgno, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
modified = 0;
|
||||
@@ -492,7 +486,7 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
|
||||
LSN(pagep) = argp->lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
pagep = NULL;
|
||||
|
||||
@@ -500,7 +494,7 @@ done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: if (pagep != NULL)
|
||||
(void)mpf->put(mpf, pagep, 0);
|
||||
(void)__memp_fput(mpf, pagep, 0);
|
||||
REC_CLOSE;
|
||||
}
|
||||
|
||||
@@ -533,11 +527,16 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
|
||||
REC_INTRO(__bam_cadjust_read, 1);
|
||||
|
||||
/* Get the page; if it never existed and we're undoing, we're done. */
|
||||
if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (DB_UNDO(op))
|
||||
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (ret != DB_PAGE_NOTFOUND
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
|| DB_REDO(op)
|
||||
#endif
|
||||
) {
|
||||
ret = __db_pgerr(file_dbp, argp->pgno, ret);
|
||||
goto out;
|
||||
} else
|
||||
goto done;
|
||||
__db_pgerr(file_dbp, argp->pgno, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
modified = 0;
|
||||
@@ -576,7 +575,7 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
|
||||
LSN(pagep) = argp->lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
pagep = NULL;
|
||||
|
||||
@@ -584,7 +583,7 @@ done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: if (pagep != NULL)
|
||||
(void)mpf->put(mpf, pagep, 0);
|
||||
(void)__memp_fput(mpf, pagep, 0);
|
||||
REC_CLOSE;
|
||||
}
|
||||
|
||||
@@ -617,11 +616,16 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
|
||||
REC_INTRO(__bam_cdel_read, 1);
|
||||
|
||||
/* Get the page; if it never existed and we're undoing, we're done. */
|
||||
if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (DB_UNDO(op))
|
||||
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (ret != DB_PAGE_NOTFOUND
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
|| DB_REDO(op)
|
||||
#endif
|
||||
) {
|
||||
ret = __db_pgerr(file_dbp, argp->pgno, ret);
|
||||
goto out;
|
||||
} else
|
||||
goto done;
|
||||
__db_pgerr(file_dbp, argp->pgno, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
modified = 0;
|
||||
@@ -645,7 +649,7 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
|
||||
LSN(pagep) = argp->lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
pagep = NULL;
|
||||
|
||||
@@ -653,7 +657,7 @@ done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: if (pagep != NULL)
|
||||
(void)mpf->put(mpf, pagep, 0);
|
||||
(void)__memp_fput(mpf, pagep, 0);
|
||||
REC_CLOSE;
|
||||
}
|
||||
|
||||
@@ -688,11 +692,16 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
|
||||
REC_INTRO(__bam_repl_read, 1);
|
||||
|
||||
/* Get the page; if it never existed and we're undoing, we're done. */
|
||||
if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (DB_UNDO(op))
|
||||
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (ret != DB_PAGE_NOTFOUND
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
|| DB_REDO(op)
|
||||
#endif
|
||||
) {
|
||||
ret = __db_pgerr(file_dbp, argp->pgno, ret);
|
||||
goto out;
|
||||
} else
|
||||
goto done;
|
||||
__db_pgerr(file_dbp, argp->pgno, ret);
|
||||
goto out;
|
||||
}
|
||||
bk = GET_BKEYDATA(file_dbp, pagep, argp->indx);
|
||||
|
||||
@@ -753,7 +762,7 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
|
||||
LSN(pagep) = argp->lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
pagep = NULL;
|
||||
|
||||
@@ -761,7 +770,7 @@ done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: if (pagep != NULL)
|
||||
(void)mpf->put(mpf, pagep, 0);
|
||||
(void)__memp_fput(mpf, pagep, 0);
|
||||
REC_CLOSE;
|
||||
}
|
||||
|
||||
@@ -792,10 +801,13 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info)
|
||||
REC_PRINT(__bam_root_print);
|
||||
REC_INTRO(__bam_root_read, 0);
|
||||
|
||||
if ((ret = mpf->get(mpf, &argp->meta_pgno, 0, &meta)) != 0) {
|
||||
/* The metadata page must always exist on redo. */
|
||||
if (DB_REDO(op)) {
|
||||
__db_pgerr(file_dbp, argp->meta_pgno, ret);
|
||||
if ((ret = __memp_fget(mpf, &argp->meta_pgno, 0, &meta)) != 0) {
|
||||
if (ret != DB_PAGE_NOTFOUND
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
|| DB_REDO(op)
|
||||
#endif
|
||||
) {
|
||||
ret = __db_pgerr(file_dbp, argp->meta_pgno, ret);
|
||||
goto out;
|
||||
} else
|
||||
goto done;
|
||||
@@ -816,7 +828,7 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info)
|
||||
meta->dbmeta.lsn = argp->meta_lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
if ((ret = __memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
meta = NULL;
|
||||
|
||||
@@ -824,7 +836,7 @@ done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: if (meta != NULL)
|
||||
(void)mpf->put(mpf, meta, 0);
|
||||
(void)__memp_fput(mpf, meta, 0);
|
||||
REC_CLOSE;
|
||||
}
|
||||
|
||||
@@ -851,6 +863,7 @@ __bam_curadj_recover(dbenv, dbtp, lsnp, op, info)
|
||||
int ret;
|
||||
|
||||
COMPQUIET(info, NULL);
|
||||
COMPQUIET(mpf, NULL);
|
||||
|
||||
REC_PRINT(__bam_curadj_print);
|
||||
REC_INTRO(__bam_curadj_read, 0);
|
||||
@@ -859,7 +872,7 @@ __bam_curadj_recover(dbenv, dbtp, lsnp, op, info)
|
||||
if (op != DB_TXN_ABORT)
|
||||
goto done;
|
||||
|
||||
switch(argp->mode) {
|
||||
switch (argp->mode) {
|
||||
case DB_CA_DI:
|
||||
if ((ret = __bam_ca_di(dbc, argp->from_pgno,
|
||||
argp->from_indx, -(int)argp->first_indx)) != 0)
|
||||
@@ -911,6 +924,7 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
|
||||
int ret, t_ret;
|
||||
|
||||
COMPQUIET(info, NULL);
|
||||
COMPQUIET(mpf, NULL);
|
||||
rdbc = NULL;
|
||||
|
||||
REC_PRINT(__bam_rcuradj_print);
|
||||
@@ -931,8 +945,7 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
|
||||
* state into __ram_ca, and this way we don't need to make
|
||||
* this function know anything about how offpage dups work.
|
||||
*/
|
||||
if ((ret =
|
||||
__db_icursor(file_dbp,
|
||||
if ((ret = __db_cursor_int(file_dbp,
|
||||
NULL, DB_RECNO, argp->root, 0, DB_LOCK_INVALIDID, &rdbc)) != 0)
|
||||
goto out;
|
||||
|
||||
@@ -940,7 +953,7 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
|
||||
F_SET(cp, C_RENUMBER);
|
||||
cp->recno = argp->recno;
|
||||
|
||||
switch(argp->mode) {
|
||||
switch (argp->mode) {
|
||||
case CA_DELETE:
|
||||
/*
|
||||
* The way to undo a delete is with an insert. Since
|
||||
@@ -949,7 +962,7 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
|
||||
F_SET(cp, C_DELETED);
|
||||
F_SET(cp, C_RENUMBER); /* Just in case. */
|
||||
cp->order = argp->order;
|
||||
__ram_ca(rdbc, CA_ICURRENT);
|
||||
(void)__ram_ca(rdbc, CA_ICURRENT);
|
||||
break;
|
||||
case CA_IAFTER:
|
||||
case CA_IBEFORE:
|
||||
@@ -960,12 +973,157 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
|
||||
*/
|
||||
F_CLR(cp, C_DELETED);
|
||||
cp->order = INVALID_ORDER;
|
||||
__ram_ca(rdbc, CA_DELETE);
|
||||
(void)__ram_ca(rdbc, CA_DELETE);
|
||||
break;
|
||||
}
|
||||
|
||||
done: *lsnp = argp->prev_lsn;
|
||||
out: if (rdbc != NULL && (t_ret = rdbc->c_close(rdbc)) != 0 && ret == 0)
|
||||
out: if (rdbc != NULL && (t_ret = __db_c_close(rdbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
REC_CLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_relink_recover --
|
||||
* Recovery function for relink.
|
||||
*
|
||||
* PUBLIC: int __bam_relink_recover
|
||||
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
|
||||
*/
|
||||
int
|
||||
__bam_relink_recover(dbenv, dbtp, lsnp, op, info)
|
||||
DB_ENV *dbenv;
|
||||
DBT *dbtp;
|
||||
DB_LSN *lsnp;
|
||||
db_recops op;
|
||||
void *info;
|
||||
{
|
||||
__bam_relink_args *argp;
|
||||
DB *file_dbp;
|
||||
DBC *dbc;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
int cmp_n, cmp_p, modified, ret;
|
||||
|
||||
pagep = NULL;
|
||||
COMPQUIET(info, NULL);
|
||||
REC_PRINT(__bam_relink_print);
|
||||
REC_INTRO(__bam_relink_read, 1);
|
||||
|
||||
/*
|
||||
* There are up to three pages we need to check -- the page, and the
|
||||
* previous and next pages, if they existed. For a page add operation,
|
||||
* the current page is the result of a split and is being recovered
|
||||
* elsewhere, so all we need do is recover the next page.
|
||||
*/
|
||||
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (ret != DB_PAGE_NOTFOUND
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
|| DB_REDO(op)
|
||||
#endif
|
||||
) {
|
||||
ret = __db_pgerr(file_dbp, argp->pgno, ret);
|
||||
goto out;
|
||||
} else
|
||||
goto next2;
|
||||
}
|
||||
modified = 0;
|
||||
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
|
||||
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
|
||||
if (cmp_p == 0 && DB_REDO(op)) {
|
||||
/* Redo the relink. */
|
||||
pagep->lsn = *lsnp;
|
||||
modified = 1;
|
||||
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
|
||||
/* Undo the relink. */
|
||||
pagep->next_pgno = argp->next;
|
||||
pagep->prev_pgno = argp->prev;
|
||||
|
||||
pagep->lsn = argp->lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
pagep = NULL;
|
||||
|
||||
next2: if ((ret = __memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
|
||||
if (ret != DB_PAGE_NOTFOUND
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
|| DB_REDO(op)
|
||||
#endif
|
||||
) {
|
||||
ret = __db_pgerr(file_dbp, argp->next, ret);
|
||||
goto out;
|
||||
} else
|
||||
goto prev;
|
||||
}
|
||||
|
||||
modified = 0;
|
||||
cmp_n = log_compare(lsnp, &LSN(pagep));
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->lsn_next);
|
||||
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_next);
|
||||
if (cmp_p == 0 && DB_REDO(op)) {
|
||||
/* Redo the remove or undo the add. */
|
||||
pagep->prev_pgno = argp->prev;
|
||||
|
||||
modified = 1;
|
||||
} else if (cmp_n == 0 && DB_UNDO(op)) {
|
||||
/* Undo the remove or redo the add. */
|
||||
pagep->prev_pgno = argp->pgno;
|
||||
|
||||
modified = 1;
|
||||
}
|
||||
if (modified == 1) {
|
||||
if (DB_UNDO(op))
|
||||
pagep->lsn = argp->lsn_next;
|
||||
else
|
||||
pagep->lsn = *lsnp;
|
||||
}
|
||||
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
pagep = NULL;
|
||||
|
||||
prev: if ((ret = __memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) {
|
||||
if (ret != DB_PAGE_NOTFOUND
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
|| DB_REDO(op)
|
||||
#endif
|
||||
) {
|
||||
ret = __db_pgerr(file_dbp, argp->prev, ret);
|
||||
goto out;
|
||||
} else
|
||||
goto done;
|
||||
}
|
||||
|
||||
modified = 0;
|
||||
cmp_p = log_compare(&LSN(pagep), &argp->lsn_prev);
|
||||
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_prev);
|
||||
if (cmp_p == 0 && DB_REDO(op)) {
|
||||
/* Redo the relink. */
|
||||
pagep->next_pgno = argp->next;
|
||||
|
||||
modified = 1;
|
||||
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
|
||||
/* Undo the relink. */
|
||||
pagep->next_pgno = argp->pgno;
|
||||
|
||||
modified = 1;
|
||||
}
|
||||
if (modified == 1) {
|
||||
if (DB_UNDO(op))
|
||||
pagep->lsn = argp->lsn_prev;
|
||||
else
|
||||
pagep->lsn = *lsnp;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1998-2002
|
||||
* Copyright (c) 1998-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: bt_reclaim.c,v 11.15 2004/01/28 03:35:49 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_reclaim.c,v 11.11 2002/03/29 20:46:26 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -36,7 +34,7 @@ __bam_reclaim(dbp, txn)
|
||||
int ret, t_ret;
|
||||
|
||||
/* Acquire a cursor. */
|
||||
if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
|
||||
if ((ret = __db_cursor(dbp, txn, &dbc, 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Walk the tree, freeing pages. */
|
||||
@@ -44,7 +42,7 @@ __bam_reclaim(dbp, txn)
|
||||
DB_LOCK_WRITE, dbc->internal->root, __db_reclaim_callback, dbc);
|
||||
|
||||
/* Discard the cursor. */
|
||||
if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
|
||||
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (ret);
|
||||
@@ -54,32 +52,23 @@ __bam_reclaim(dbp, txn)
|
||||
* __bam_truncate --
|
||||
* Truncate a database.
|
||||
*
|
||||
* PUBLIC: int __bam_truncate __P((DB *, DB_TXN *, u_int32_t *));
|
||||
* PUBLIC: int __bam_truncate __P((DBC *, u_int32_t *));
|
||||
*/
|
||||
int
|
||||
__bam_truncate(dbp, txn, countp)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
__bam_truncate(dbc, countp)
|
||||
DBC *dbc;
|
||||
u_int32_t *countp;
|
||||
{
|
||||
DBC *dbc;
|
||||
db_trunc_param trunc;
|
||||
int ret, t_ret;
|
||||
|
||||
/* Acquire a cursor. */
|
||||
if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
|
||||
return (ret);
|
||||
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);
|
||||
|
||||
/* Discard the cursor. */
|
||||
if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
*countp = trunc.count;
|
||||
|
||||
return (ret);
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2002
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: bt_recno.c,v 11.117 2004/03/28 17:01:01 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_recno.c,v 11.106 2002/08/16 04:56:30 ubell Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
@@ -58,7 +54,7 @@ static int __ram_update __P((DBC *, db_recno_t, int));
|
||||
} \
|
||||
}
|
||||
#define CD_ISSET(cp) \
|
||||
(F_ISSET(cp, C_RENUMBER) && F_ISSET(cp, C_DELETED))
|
||||
(F_ISSET(cp, C_RENUMBER) && F_ISSET(cp, C_DELETED) ? 1 : 0)
|
||||
|
||||
/*
|
||||
* Macros for comparing the ordering of two cursors.
|
||||
@@ -91,11 +87,13 @@ static int __ram_update __P((DBC *, db_recno_t, int));
|
||||
* After a search, copy the found page into the cursor, discarding any
|
||||
* currently held lock.
|
||||
*/
|
||||
#define STACK_TO_CURSOR(cp) { \
|
||||
#define STACK_TO_CURSOR(cp, ret) { \
|
||||
int __t_ret; \
|
||||
(cp)->page = (cp)->csp->page; \
|
||||
(cp)->pgno = (cp)->csp->page->pgno; \
|
||||
(cp)->indx = (cp)->csp->indx; \
|
||||
(void)__TLPUT(dbc, (cp)->lock); \
|
||||
if ((__t_ret = __TLPUT(dbc, (cp)->lock)) != 0 && (ret) == 0) \
|
||||
ret = __t_ret; \
|
||||
(cp)->lock = (cp)->csp->lock; \
|
||||
(cp)->lock_mode = (cp)->csp->lock_mode; \
|
||||
}
|
||||
@@ -122,9 +120,6 @@ __ram_open(dbp, txn, name, base_pgno, flags)
|
||||
COMPQUIET(name, NULL);
|
||||
t = dbp->bt_internal;
|
||||
|
||||
/* Initialize the remaining fields/methods of the DB. */
|
||||
dbp->stat = __bam_stat;
|
||||
|
||||
/* Start up the tree. */
|
||||
if ((ret = __bam_read_root(dbp, txn, base_pgno, flags)) != 0)
|
||||
return (ret);
|
||||
@@ -143,7 +138,7 @@ __ram_open(dbp, txn, name, base_pgno, flags)
|
||||
/* If we're snapshotting an underlying source file, do it now. */
|
||||
if (F_ISSET(dbp, DB_AM_SNAPSHOT)) {
|
||||
/* Allocate a cursor. */
|
||||
if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
|
||||
if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Do the snapshot. */
|
||||
@@ -152,7 +147,7 @@ __ram_open(dbp, txn, name, base_pgno, flags)
|
||||
ret = 0;
|
||||
|
||||
/* Discard the cursor. */
|
||||
if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
|
||||
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
}
|
||||
|
||||
@@ -209,7 +204,7 @@ __ram_c_del(dbc)
|
||||
DB_LSN lsn;
|
||||
DBT hdr, data;
|
||||
EPG *epg;
|
||||
int exact, ret, stack;
|
||||
int exact, ret, stack, t_ret;
|
||||
|
||||
dbp = dbc->dbp;
|
||||
cp = (BTREE_CURSOR *)dbc->internal;
|
||||
@@ -240,7 +235,9 @@ __ram_c_del(dbc)
|
||||
stack = 1;
|
||||
|
||||
/* Copy the page into the cursor. */
|
||||
STACK_TO_CURSOR(cp);
|
||||
STACK_TO_CURSOR(cp, ret);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* If re-numbering records, the on-page deleted flag can only mean
|
||||
@@ -262,7 +259,8 @@ __ram_c_del(dbc)
|
||||
/* Delete the item, adjust the counts, adjust the cursors. */
|
||||
if ((ret = __bam_ditem(dbc, cp->page, cp->indx)) != 0)
|
||||
goto err;
|
||||
__bam_adjust(dbc, -1);
|
||||
if ((ret = __bam_adjust(dbc, -1)) != 0)
|
||||
goto err;
|
||||
if (__ram_ca(dbc, CA_DELETE) > 0 &&
|
||||
CURADJ_LOG(dbc) && (ret = __bam_rcuradj_log(dbp, dbc->txn,
|
||||
&lsn, 0, CA_DELETE, cp->root, cp->recno, cp->order)) != 0)
|
||||
@@ -325,8 +323,8 @@ __ram_c_del(dbc)
|
||||
|
||||
t->re_modified = 1;
|
||||
|
||||
err: if (stack)
|
||||
__bam_stkrel(dbc, STK_CLRDBC);
|
||||
err: if (stack && (t_ret = __bam_stkrel(dbc, STK_CLRDBC)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -388,8 +386,13 @@ retry: switch (flags) {
|
||||
* we have to avoid incrementing the record number so that we
|
||||
* return the right record by virtue of renumbering the tree.
|
||||
*/
|
||||
if (CD_ISSET(cp))
|
||||
if (CD_ISSET(cp)) {
|
||||
/*
|
||||
* Clear the flag, we've moved off the deleted record.
|
||||
*/
|
||||
CD_CLR(cp);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cp->recno != RECNO_OOB) {
|
||||
++cp->recno;
|
||||
@@ -494,7 +497,9 @@ retry: switch (flags) {
|
||||
}
|
||||
|
||||
/* Copy the page into the cursor. */
|
||||
STACK_TO_CURSOR(cp);
|
||||
STACK_TO_CURSOR(cp, ret);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* If re-numbering records, the on-page deleted flag means this
|
||||
@@ -607,9 +612,11 @@ __ram_c_put(dbc, key, data, flags, pgnop)
|
||||
return (ret);
|
||||
if (CURADJ_LOG(dbc) &&
|
||||
(ret = __bam_rcuradj_log(dbp, dbc->txn, &lsn, 0,
|
||||
CA_ICURRENT, cp->root, cp->recno, cp->order)))
|
||||
CA_ICURRENT, cp->root, cp->recno, cp->order)) != 0)
|
||||
return (ret);
|
||||
return (0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -650,7 +657,9 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
|
||||
DB_ASSERT(exact || CD_ISSET(cp));
|
||||
|
||||
/* Copy the page into the cursor. */
|
||||
STACK_TO_CURSOR(cp);
|
||||
STACK_TO_CURSOR(cp, ret);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
ret = __bam_iitem(dbc, key, data, iiflags, 0);
|
||||
t_ret = __bam_stkrel(dbc, STK_CLRDBC);
|
||||
@@ -708,6 +717,8 @@ split: if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
|
||||
CA_ICURRENT, cp->root, cp->recno, cp->order)) != 0)
|
||||
goto err;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return the key if we've created a new record. */
|
||||
@@ -983,7 +994,7 @@ __ram_source(dbp)
|
||||
* when it comes time to write the database back to the source.
|
||||
*/
|
||||
if ((t->re_fp = fopen(t->re_source, "r")) == NULL) {
|
||||
ret = errno;
|
||||
ret = __os_get_errno();
|
||||
__db_err(dbp->dbenv, "%s: %s", t->re_source, db_strerror(ret));
|
||||
return (ret);
|
||||
}
|
||||
@@ -1027,7 +1038,7 @@ __ram_writeback(dbp)
|
||||
}
|
||||
|
||||
/* Allocate a cursor. */
|
||||
if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
|
||||
if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
@@ -1060,13 +1071,13 @@ __ram_writeback(dbp)
|
||||
*/
|
||||
if (t->re_fp != NULL) {
|
||||
if (fclose(t->re_fp) != 0) {
|
||||
ret = errno;
|
||||
ret = __os_get_errno();
|
||||
goto err;
|
||||
}
|
||||
t->re_fp = NULL;
|
||||
}
|
||||
if ((fp = fopen(t->re_source, "w")) == NULL) {
|
||||
ret = errno;
|
||||
ret = __os_get_errno();
|
||||
__db_err(dbenv, "%s: %s", t->re_source, db_strerror(ret));
|
||||
goto err;
|
||||
}
|
||||
@@ -1088,23 +1099,24 @@ __ram_writeback(dbp)
|
||||
* and the pad character if we're doing fixed-length records.
|
||||
*/
|
||||
delim = t->re_delim;
|
||||
if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
|
||||
if ((ret = __os_malloc(dbenv, t->re_len, &pad)) != 0)
|
||||
goto err;
|
||||
memset(pad, t->re_pad, t->re_len);
|
||||
}
|
||||
for (keyno = 1;; ++keyno) {
|
||||
switch (ret = dbp->get(dbp, NULL, &key, &data, 0)) {
|
||||
switch (ret = __db_get(dbp, NULL, &key, &data, 0)) {
|
||||
case 0:
|
||||
if (data.size != 0 && (u_int32_t)fwrite(
|
||||
data.data, 1, data.size, fp) != data.size)
|
||||
if (data.size != 0 &&
|
||||
fwrite(data.data, 1, data.size, fp) != data.size)
|
||||
goto write_err;
|
||||
break;
|
||||
case DB_KEYEMPTY:
|
||||
if (F_ISSET(dbp, DB_AM_FIXEDLEN) &&
|
||||
(u_int32_t)fwrite(pad, 1, t->re_len, fp) !=
|
||||
t->re_len)
|
||||
goto write_err;
|
||||
if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
|
||||
if (pad == NULL) {
|
||||
if ((ret = __os_malloc(
|
||||
dbenv, t->re_len, &pad)) != 0)
|
||||
goto err;
|
||||
memset(pad, t->re_pad, t->re_len);
|
||||
}
|
||||
if (fwrite(pad, 1, t->re_len, fp) != t->re_len)
|
||||
goto write_err;
|
||||
}
|
||||
break;
|
||||
case DB_NOTFOUND:
|
||||
ret = 0;
|
||||
@@ -1114,8 +1126,8 @@ __ram_writeback(dbp)
|
||||
}
|
||||
if (!F_ISSET(dbp, DB_AM_FIXEDLEN) &&
|
||||
fwrite(&delim, 1, 1, fp) != 1) {
|
||||
write_err: ret = errno;
|
||||
__db_err(dbp->dbenv,
|
||||
write_err: ret = __os_get_errno();
|
||||
__db_err(dbenv,
|
||||
"%s: write failed to backing file: %s",
|
||||
t->re_source, strerror(ret));
|
||||
goto err;
|
||||
@@ -1125,13 +1137,14 @@ write_err: ret = errno;
|
||||
err:
|
||||
done: /* Close the file descriptor. */
|
||||
if (fp != NULL && fclose(fp) != 0) {
|
||||
t_ret = __os_get_errno();
|
||||
if (ret == 0)
|
||||
ret = errno;
|
||||
__db_err(dbenv, "%s: %s", t->re_source, db_strerror(errno));
|
||||
ret = t_ret;
|
||||
__db_err(dbenv, "%s: %s", t->re_source, db_strerror(t_ret));
|
||||
}
|
||||
|
||||
/* Discard the cursor. */
|
||||
if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
|
||||
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/* Discard memory allocated to hold the data items. */
|
||||
@@ -1259,7 +1272,7 @@ __ram_add(dbc, recnop, data, flags, bi_flags)
|
||||
u_int32_t flags, bi_flags;
|
||||
{
|
||||
BTREE_CURSOR *cp;
|
||||
int exact, ret, stack;
|
||||
int exact, ret, stack, t_ret;
|
||||
|
||||
cp = (BTREE_CURSOR *)dbc->internal;
|
||||
|
||||
@@ -1270,7 +1283,9 @@ retry: /* Find the slot for insertion. */
|
||||
stack = 1;
|
||||
|
||||
/* Copy the page into the cursor. */
|
||||
STACK_TO_CURSOR(cp);
|
||||
STACK_TO_CURSOR(cp, ret);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* The application may modify the data based on the selected record
|
||||
@@ -1320,8 +1335,8 @@ retry: /* Find the slot for insertion. */
|
||||
goto err;
|
||||
}
|
||||
|
||||
err: if (stack)
|
||||
__bam_stkrel(dbc, STK_CLRDBC);
|
||||
err: if (stack && (t_ret = __bam_stkrel(dbc, STK_CLRDBC)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -35,14 +35,12 @@
|
||||
* 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 11.40 2004/07/23 17:21:09 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_rsearch.c,v 11.34 2002/07/03 19:03:50 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -52,6 +50,7 @@ static const char revid[] = "$Id: bt_rsearch.c,v 11.34 2002/07/03 19:03:50 bosti
|
||||
#include "dbinc/btree.h"
|
||||
#include "dbinc/db_shash.h"
|
||||
#include "dbinc/lock.h"
|
||||
#include "dbinc/mp.h"
|
||||
|
||||
/*
|
||||
* __bam_rsearch --
|
||||
@@ -77,11 +76,12 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
|
||||
db_lockmode_t lock_mode;
|
||||
db_pgno_t pg;
|
||||
db_recno_t recno, t_recno, total;
|
||||
int ret, stack;
|
||||
int ret, stack, t_ret;
|
||||
|
||||
dbp = dbc->dbp;
|
||||
mpf = dbp->mpf;
|
||||
cp = (BTREE_CURSOR *)dbc->internal;
|
||||
h = NULL;
|
||||
|
||||
BT_STK_CLR(cp);
|
||||
|
||||
@@ -105,7 +105,7 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
|
||||
lock_mode = stack ? DB_LOCK_WRITE : DB_LOCK_READ;
|
||||
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
|
||||
return (ret);
|
||||
if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0) {
|
||||
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);
|
||||
@@ -122,12 +122,15 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
|
||||
if (!stack &&
|
||||
((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) ||
|
||||
(LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
(void)__LPUT(dbc, lock);
|
||||
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 = mpf->get(mpf, &pg, 0, &h)) != 0) {
|
||||
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);
|
||||
@@ -166,9 +169,11 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
|
||||
* eliminate any concurrency. A possible fix
|
||||
* would be to lock the last leaf page instead.
|
||||
*/
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
(void)__TLPUT(dbc, lock);
|
||||
return (DB_NOTFOUND);
|
||||
ret = __memp_fput(mpf, h, 0);
|
||||
if ((t_ret =
|
||||
__TLPUT(dbc, lock)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
return (ret == 0 ? DB_NOTFOUND : ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,7 +205,13 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
|
||||
*exactp = 0;
|
||||
if (!LF_ISSET(S_PAST_EOF) ||
|
||||
recno > t_recno + 1) {
|
||||
ret = DB_NOTFOUND;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -262,6 +273,7 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
|
||||
cp, h, indx, lock, lock_mode, ret);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
h = NULL;
|
||||
|
||||
lock_mode = DB_LOCK_WRITE;
|
||||
if ((ret =
|
||||
@@ -278,7 +290,9 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
|
||||
(h->level - 1) == LEAFLEVEL)
|
||||
stack = 1;
|
||||
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
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;
|
||||
@@ -289,18 +303,22 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
|
||||
* is OK because this only happens when we are
|
||||
* descending the tree holding read-locks.
|
||||
*/
|
||||
__LPUT(dbc, lock);
|
||||
(void)__LPUT(dbc, lock);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0)
|
||||
goto err;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
|
||||
err: BT_STK_POP(cp);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -352,7 +370,7 @@ __bam_adjust(dbc, adjust)
|
||||
if (PGNO(h) == root_pgno)
|
||||
RE_NREC_ADJ(h, adjust);
|
||||
|
||||
if ((ret = mpf->set(mpf, h, DB_MPOOL_DIRTY)) != 0)
|
||||
if ((ret = __memp_fset(mpf, h, DB_MPOOL_DIRTY)) != 0)
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
@@ -375,7 +393,7 @@ __bam_nrecs(dbc, rep)
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *h;
|
||||
db_pgno_t pgno;
|
||||
int ret;
|
||||
int ret, t_ret;
|
||||
|
||||
dbp = dbc->dbp;
|
||||
mpf = dbp->mpf;
|
||||
@@ -383,15 +401,16 @@ __bam_nrecs(dbc, rep)
|
||||
pgno = dbc->internal->root;
|
||||
if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lock)) != 0)
|
||||
return (ret);
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
|
||||
return (ret);
|
||||
|
||||
*rep = RE_NREC(h);
|
||||
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
(void)__TLPUT(dbc, lock);
|
||||
ret = __memp_fput(mpf, h, 0);
|
||||
if ((t_ret = __TLPUT(dbc, lock)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (0);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -38,14 +38,12 @@
|
||||
* 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 11.50 2004/07/23 17:21:09 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_search.c,v 11.43 2002/07/03 19:03:50 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -57,6 +55,7 @@ static const char revid[] = "$Id: bt_search.c,v 11.43 2002/07/03 19:03:50 bostic
|
||||
#include "dbinc/db_shash.h"
|
||||
#include "dbinc/btree.h"
|
||||
#include "dbinc/lock.h"
|
||||
#include "dbinc/mp.h"
|
||||
|
||||
/*
|
||||
* __bam_search --
|
||||
@@ -84,12 +83,13 @@ __bam_search(dbc, root_pgno, key, flags, stop, recnop, exactp)
|
||||
db_lockmode_t lock_mode;
|
||||
db_pgno_t pg;
|
||||
db_recno_t recno;
|
||||
int adjust, cmp, deloffset, ret, stack;
|
||||
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;
|
||||
|
||||
@@ -117,7 +117,7 @@ try_again:
|
||||
lock_mode = stack ? DB_LOCK_WRITE : DB_LOCK_READ;
|
||||
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
|
||||
return (ret);
|
||||
if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0) {
|
||||
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);
|
||||
@@ -134,12 +134,15 @@ try_again:
|
||||
if (!stack &&
|
||||
((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) ||
|
||||
(LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
(void)__LPUT(dbc, lock);
|
||||
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 = mpf->get(mpf, &pg, 0, &h)) != 0) {
|
||||
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);
|
||||
@@ -148,8 +151,11 @@ try_again:
|
||||
(u_int8_t)(stop + 1) >= h->level) ||
|
||||
(LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
|
||||
/* Someone else split the root, start over. */
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
(void)__LPUT(dbc, lock);
|
||||
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;
|
||||
}
|
||||
stack = 1;
|
||||
@@ -197,13 +203,19 @@ try_again:
|
||||
if (TYPE(h) == P_LBTREE || TYPE(h) == P_LDUP) {
|
||||
*exactp = 0;
|
||||
|
||||
if (LF_ISSET(S_EXACT))
|
||||
goto notfound;
|
||||
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);
|
||||
__LPUT(dbc, lock);
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -243,12 +255,17 @@ next: if (recnop != NULL)
|
||||
if (LF_ISSET(S_STK_ONLY)) {
|
||||
if (stop == h->level) {
|
||||
BT_STK_NUM(dbp->dbenv, cp, h, indx, ret);
|
||||
__LPUT(dbc, lock);
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
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)mpf->put(mpf, h, 0);
|
||||
(void)__memp_fput(mpf, h, 0);
|
||||
h = NULL;
|
||||
if ((ret = __db_lget(dbc,
|
||||
LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) {
|
||||
/*
|
||||
@@ -256,7 +273,7 @@ next: if (recnop != NULL)
|
||||
* is OK because it only happens when descending
|
||||
* the tree holding read-locks.
|
||||
*/
|
||||
__LPUT(dbc, lock);
|
||||
(void)__LPUT(dbc, lock);
|
||||
return (ret);
|
||||
}
|
||||
} else if (stack) {
|
||||
@@ -272,6 +289,7 @@ next: if (recnop != NULL)
|
||||
cp, h, indx, lock, lock_mode, ret);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
h = NULL;
|
||||
|
||||
lock_mode = DB_LOCK_WRITE;
|
||||
if ((ret =
|
||||
@@ -288,7 +306,9 @@ next: if (recnop != NULL)
|
||||
(h->level - 1) == LEAFLEVEL)
|
||||
stack = 1;
|
||||
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
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;
|
||||
@@ -299,25 +319,17 @@ next: if (recnop != NULL)
|
||||
* is OK because this only happens when we are
|
||||
* descending the tree holding read-locks.
|
||||
*/
|
||||
__LPUT(dbc, lock);
|
||||
(void)__LPUT(dbc, lock);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if ((ret = mpf->get(mpf, &pg, 0, &h)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0)
|
||||
goto err;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
|
||||
found: *exactp = 1;
|
||||
|
||||
/*
|
||||
* If we're trying to calculate the record number, add in the
|
||||
* offset on this page and correct for the fact that records
|
||||
* in the tree are 0-based.
|
||||
*/
|
||||
if (recnop != NULL)
|
||||
*recnop = recno + (indx / P_INDX) + 1;
|
||||
|
||||
/*
|
||||
* If we got here, we know that we have a Btree leaf or off-page
|
||||
* duplicates page. If it's a Btree leaf page, we have to handle
|
||||
@@ -345,6 +357,7 @@ found: *exactp = 1;
|
||||
* 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))
|
||||
@@ -363,29 +376,53 @@ found: *exactp = 1;
|
||||
* If we weren't able to find a non-deleted duplicate, return
|
||||
* DB_NOTFOUND.
|
||||
*/
|
||||
if (B_DISSET(GET_BKEYDATA(dbp, h, indx + deloffset)->type))
|
||||
goto 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);
|
||||
__LPUT(dbc, lock);
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
} else {
|
||||
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
|
||||
BT_STK_ENTER(dbp->dbenv, cp, h, indx, lock, lock_mode, ret);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
}
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
return (0);
|
||||
|
||||
notfound:
|
||||
/* Keep the page locked for serializability. */
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
(void)__TLPUT(dbc, lock);
|
||||
ret = DB_NOTFOUND;
|
||||
err: if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
err: BT_STK_POP(cp);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
@@ -423,7 +460,7 @@ __bam_stkrel(dbc, flags)
|
||||
LOCK_INIT(cp->lock);
|
||||
}
|
||||
if ((t_ret =
|
||||
mpf->put(mpf, epg->page, 0)) != 0 && ret == 0)
|
||||
__memp_fput(mpf, epg->page, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
/*
|
||||
* XXX
|
||||
@@ -434,10 +471,12 @@ __bam_stkrel(dbc, flags)
|
||||
*/
|
||||
epg->page = NULL;
|
||||
}
|
||||
if (LF_ISSET(STK_NOLOCK))
|
||||
(void)__LPUT(dbc, epg->lock);
|
||||
else
|
||||
(void)__TLPUT(dbc, epg->lock);
|
||||
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. */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -35,18 +35,15 @@
|
||||
* 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_split.c,v 11.66 2004/10/01 13:00:21 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_split.c,v 11.58 2002/07/03 19:03:50 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
@@ -54,6 +51,7 @@ static const char revid[] = "$Id: bt_split.c,v 11.58 2002/07/03 19:03:50 bostic
|
||||
#include "dbinc/db_page.h"
|
||||
#include "dbinc/db_shash.h"
|
||||
#include "dbinc/lock.h"
|
||||
#include "dbinc/mp.h"
|
||||
#include "dbinc/btree.h"
|
||||
|
||||
static int __bam_broot __P((DBC *, PAGE *, PAGE *, PAGE *));
|
||||
@@ -119,7 +117,7 @@ __bam_split(dbc, arg, root_pgnop)
|
||||
arg, S_WRPAIR, level, NULL, &exact) :
|
||||
__bam_rsearch(dbc,
|
||||
(db_recno_t *)arg, S_WRPAIR, level, &exact))) != 0)
|
||||
return (ret);
|
||||
break;
|
||||
|
||||
if (root_pgnop != NULL)
|
||||
*root_pgnop = cp->csp[0].page->pgno == root_pgno ?
|
||||
@@ -133,7 +131,7 @@ __bam_split(dbc, arg, root_pgnop)
|
||||
if (2 * B_MAXSIZEONPAGE(cp->ovflsize)
|
||||
<= (db_indx_t)P_FREESPACE(dbc->dbp, cp->csp[0].page)) {
|
||||
__bam_stkrel(dbc, STK_NOLOCK);
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
ret = cp->csp[0].page->pgno == root_pgno ?
|
||||
__bam_root(dbc, &cp->csp[0]) :
|
||||
@@ -161,10 +159,13 @@ __bam_split(dbc, arg, root_pgnop)
|
||||
dir = UP;
|
||||
break;
|
||||
default:
|
||||
return (ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
|
||||
err: if (root_pgnop != NULL)
|
||||
*root_pgnop = cp->root;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -183,10 +184,11 @@ __bam_root(dbc, cp)
|
||||
PAGE *lp, *rp;
|
||||
db_indx_t split;
|
||||
u_int32_t opflags;
|
||||
int ret;
|
||||
int ret, t_ret;
|
||||
|
||||
dbp = dbc->dbp;
|
||||
mpf = dbp->mpf;
|
||||
lp = rp = NULL;
|
||||
|
||||
/* Yeah, right. */
|
||||
if (cp->page->level >= MAXBTREELEVEL) {
|
||||
@@ -197,7 +199,6 @@ __bam_root(dbc, cp)
|
||||
}
|
||||
|
||||
/* Create new left and right pages for the split. */
|
||||
lp = rp = NULL;
|
||||
if ((ret = __db_new(dbc, TYPE(cp->page), &lp)) != 0 ||
|
||||
(ret = __db_new(dbc, TYPE(cp->page), &rp)) != 0)
|
||||
goto err;
|
||||
@@ -237,24 +238,21 @@ __bam_root(dbc, cp)
|
||||
goto err;
|
||||
|
||||
/* Adjust any cursors. */
|
||||
if ((ret = __bam_ca_split(dbc,
|
||||
cp->page->pgno, lp->pgno, rp->pgno, split, 1)) != 0)
|
||||
goto err;
|
||||
ret = __bam_ca_split(dbc, cp->page->pgno, lp->pgno, rp->pgno, split, 1);
|
||||
|
||||
/* Success -- write the real pages back to the store. */
|
||||
(void)mpf->put(mpf, cp->page, DB_MPOOL_DIRTY);
|
||||
(void)__TLPUT(dbc, cp->lock);
|
||||
(void)mpf->put(mpf, lp, DB_MPOOL_DIRTY);
|
||||
(void)mpf->put(mpf, rp, DB_MPOOL_DIRTY);
|
||||
/* Success or error: release pages and locks. */
|
||||
err: if ((t_ret =
|
||||
__memp_fput(mpf, cp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if ((t_ret = __TLPUT(dbc, cp->lock)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if (lp != NULL &&
|
||||
(t_ret = __memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if (rp != NULL &&
|
||||
(t_ret = __memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (0);
|
||||
|
||||
err: if (lp != NULL)
|
||||
(void)mpf->put(mpf, lp, 0);
|
||||
if (rp != NULL)
|
||||
(void)mpf->put(mpf, rp, 0);
|
||||
(void)mpf->put(mpf, cp->page, 0);
|
||||
(void)__TLPUT(dbc, cp->lock);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -358,7 +356,7 @@ __bam_page(dbc, pp, cp)
|
||||
if ((ret = __db_lget(dbc,
|
||||
0, NEXT_PGNO(cp->page), DB_LOCK_WRITE, 0, &tplock)) != 0)
|
||||
goto err;
|
||||
if ((ret = mpf->get(mpf, &NEXT_PGNO(cp->page), 0, &tp)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &NEXT_PGNO(cp->page), 0, &tp)) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -370,9 +368,13 @@ __bam_page(dbc, pp, cp)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Lock the new page. We need to do this because someone
|
||||
* could get here through bt_lpgno if this page was recently
|
||||
* dealocated. They can't look at it before we commit.
|
||||
* Lock the new page. We need to do this for two reasons: first, the
|
||||
* fast-lookup code might have a reference to this page in bt_lpgno if
|
||||
* the page was recently deleted from the tree, and that code doesn't
|
||||
* walk the tree and so won't encounter the parent's page lock.
|
||||
* Second, a dirty reader could get to this page via the parent or old
|
||||
* page after the split is done but before the transaction is committed
|
||||
* or aborted.
|
||||
*/
|
||||
if ((ret = __db_lget(dbc,
|
||||
0, PGNO(alloc_rp), DB_LOCK_WRITE, 0, &rplock)) != 0)
|
||||
@@ -456,20 +458,27 @@ __bam_page(dbc, pp, cp)
|
||||
* releasing locks on the pages that reference it. We're finished
|
||||
* modifying the page so it's not really necessary, but it's neater.
|
||||
*/
|
||||
if ((t_ret = mpf->put(mpf, alloc_rp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
if ((t_ret =
|
||||
__memp_fput(mpf, alloc_rp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
(void)__TLPUT(dbc, rplock);
|
||||
if ((t_ret = mpf->put(mpf, pp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
if ((t_ret = __TLPUT(dbc, rplock)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
(void)__TLPUT(dbc, pp->lock);
|
||||
if ((t_ret = mpf->put(mpf, cp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
if ((t_ret =
|
||||
__memp_fput(mpf, pp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if ((t_ret = __TLPUT(dbc, pp->lock)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if ((t_ret =
|
||||
__memp_fput(mpf, cp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if ((t_ret = __TLPUT(dbc, cp->lock)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
(void)__TLPUT(dbc, cp->lock);
|
||||
if (tp != NULL) {
|
||||
if ((t_ret =
|
||||
mpf->put(mpf, tp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
__memp_fput(mpf, tp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if ((t_ret = __TLPUT(dbc, tplock)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
(void)__TLPUT(dbc, tplock);
|
||||
}
|
||||
return (ret);
|
||||
|
||||
@@ -478,21 +487,21 @@ err: if (lp != NULL)
|
||||
if (rp != NULL)
|
||||
__os_free(dbp->dbenv, rp);
|
||||
if (alloc_rp != NULL)
|
||||
(void)mpf->put(mpf, alloc_rp, 0);
|
||||
(void)__memp_fput(mpf, alloc_rp, 0);
|
||||
if (tp != NULL)
|
||||
(void)mpf->put(mpf, tp, 0);
|
||||
(void)__memp_fput(mpf, tp, 0);
|
||||
|
||||
/* We never updated the new or next pages, we can release them. */
|
||||
(void)__LPUT(dbc, rplock);
|
||||
(void)__LPUT(dbc, tplock);
|
||||
|
||||
(void)mpf->put(mpf, pp->page, 0);
|
||||
(void)__memp_fput(mpf, pp->page, 0);
|
||||
if (ret == DB_NEEDSPLIT)
|
||||
(void)__LPUT(dbc, pp->lock);
|
||||
else
|
||||
(void)__TLPUT(dbc, pp->lock);
|
||||
|
||||
(void)mpf->put(mpf, cp->page, 0);
|
||||
(void)__memp_fput(mpf, cp->page, 0);
|
||||
if (ret == DB_NEEDSPLIT)
|
||||
(void)__LPUT(dbc, cp->lock);
|
||||
else
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: bt_stat.c,v 11.78 2004/09/22 03:31:26 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_stat.c,v 11.52 2002/05/30 15:40:27 krinsky Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
@@ -22,33 +21,35 @@ static const char revid[] = "$Id: bt_stat.c,v 11.52 2002/05/30 15:40:27 krinsky
|
||||
#include "dbinc/db_shash.h"
|
||||
#include "dbinc/btree.h"
|
||||
#include "dbinc/lock.h"
|
||||
#include "dbinc/log.h"
|
||||
#include "dbinc/mp.h"
|
||||
|
||||
#ifdef HAVE_STATISTICS
|
||||
/*
|
||||
* __bam_stat --
|
||||
* Gather/print the btree statistics
|
||||
*
|
||||
* PUBLIC: int __bam_stat __P((DB *, void *, u_int32_t));
|
||||
* PUBLIC: int __bam_stat __P((DBC *, void *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__bam_stat(dbp, spp, flags)
|
||||
DB *dbp;
|
||||
__bam_stat(dbc, spp, flags)
|
||||
DBC *dbc;
|
||||
void *spp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
BTMETA *meta;
|
||||
BTREE *t;
|
||||
BTREE_CURSOR *cp;
|
||||
DBC *dbc;
|
||||
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;
|
||||
|
||||
PANIC_CHECK(dbp->dbenv);
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
|
||||
dbp = dbc->dbp;
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
meta = NULL;
|
||||
t = dbp->bt_internal;
|
||||
@@ -57,22 +58,12 @@ __bam_stat(dbp, spp, flags)
|
||||
LOCK_INIT(lock);
|
||||
mpf = dbp->mpf;
|
||||
h = NULL;
|
||||
ret = 0;
|
||||
write_meta = 0;
|
||||
ret = write_meta = 0;
|
||||
|
||||
/* Check for invalid flags. */
|
||||
if ((ret = __db_statchk(dbp, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Acquire a cursor. */
|
||||
if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
|
||||
return (ret);
|
||||
cp = (BTREE_CURSOR *)dbc->internal;
|
||||
|
||||
DEBUG_LWRITE(dbc, NULL, "bam_stat", NULL, NULL, flags);
|
||||
|
||||
/* Allocate and clear the structure. */
|
||||
if ((ret = __os_umalloc(dbp->dbenv, sizeof(*sp), &sp)) != 0)
|
||||
if ((ret = __os_umalloc(dbenv, sizeof(*sp), &sp)) != 0)
|
||||
goto err;
|
||||
memset(sp, 0, sizeof(*sp));
|
||||
|
||||
@@ -80,7 +71,7 @@ __bam_stat(dbp, spp, flags)
|
||||
pgno = PGNO_BASE_MD;
|
||||
if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &metalock)) != 0)
|
||||
goto err;
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0)
|
||||
goto err;
|
||||
|
||||
if (flags == DB_RECORDCOUNT || flags == DB_CACHED_COUNTS)
|
||||
@@ -92,11 +83,11 @@ __bam_stat(dbp, spp, flags)
|
||||
for (sp->bt_free = 0, pgno = meta->dbmeta.free; pgno != PGNO_INVALID;) {
|
||||
++sp->bt_free;
|
||||
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
|
||||
goto err;
|
||||
|
||||
pgno = h->next_pgno;
|
||||
if ((ret = mpf->put(mpf, h, 0)) != 0)
|
||||
if ((ret = __memp_fput(mpf, h, 0)) != 0)
|
||||
goto err;
|
||||
h = NULL;
|
||||
}
|
||||
@@ -105,17 +96,19 @@ __bam_stat(dbp, spp, flags)
|
||||
pgno = cp->root;
|
||||
if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lock)) != 0)
|
||||
goto err;
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
|
||||
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. */
|
||||
if ((ret = mpf->put(mpf, h, 0)) != 0)
|
||||
goto err;
|
||||
ret = __memp_fput(mpf, h, 0);
|
||||
h = NULL;
|
||||
__LPUT(dbc, lock);
|
||||
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,
|
||||
@@ -129,16 +122,18 @@ __bam_stat(dbp, spp, flags)
|
||||
write_meta = !F_ISSET(dbp, DB_AM_RDONLY);
|
||||
meta_only:
|
||||
if (t->bt_meta != PGNO_BASE_MD || write_meta != 0) {
|
||||
if ((ret = mpf->put(mpf, meta, 0)) != 0)
|
||||
goto err;
|
||||
ret = __memp_fput(mpf, meta, 0);
|
||||
meta = NULL;
|
||||
__LPUT(dbc, metalock);
|
||||
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 = mpf->get(mpf, &t->bt_meta, 0, (PAGE **)&meta)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &t->bt_meta, 0, &meta)) != 0)
|
||||
goto err;
|
||||
}
|
||||
if (flags == DB_FAST_STAT) {
|
||||
@@ -147,14 +142,15 @@ meta_only:
|
||||
if ((ret = __db_lget(dbc, 0,
|
||||
cp->root, DB_LOCK_READ, 0, &lock)) != 0)
|
||||
goto err;
|
||||
if ((ret =
|
||||
mpf->get(mpf, &cp->root, 0, (PAGE **)&h)) != 0)
|
||||
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 = meta->dbmeta.record_count;
|
||||
|
||||
sp->bt_ndata = dbp->type == DB_RECNO ?
|
||||
sp->bt_nkeys : meta->dbmeta.record_count;
|
||||
}
|
||||
|
||||
/* Get metadata page statistics. */
|
||||
@@ -175,21 +171,20 @@ meta_only:
|
||||
*(DB_BTREE_STAT **)spp = sp;
|
||||
|
||||
err: /* Discard the second page. */
|
||||
__LPUT(dbc, lock);
|
||||
if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
|
||||
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. */
|
||||
__LPUT(dbc, metalock);
|
||||
if (meta != NULL && (t_ret = mpf->put(
|
||||
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 ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
if (ret != 0 && sp != NULL) {
|
||||
__os_ufree(dbp->dbenv, sp);
|
||||
__os_ufree(dbenv, sp);
|
||||
*(DB_BTREE_STAT **)spp = NULL;
|
||||
}
|
||||
|
||||
@@ -197,104 +192,113 @@ err: /* Discard the second page. */
|
||||
}
|
||||
|
||||
/*
|
||||
* __bam_traverse --
|
||||
* Walk a Btree database.
|
||||
* __bam_stat_print --
|
||||
* Display btree/recno statistics.
|
||||
*
|
||||
* PUBLIC: int __bam_traverse __P((DBC *, db_lockmode_t,
|
||||
* PUBLIC: db_pgno_t, int (*)(DB *, PAGE *, void *, int *), void *));
|
||||
* PUBLIC: int __bam_stat_print __P((DBC *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__bam_traverse(dbc, mode, root_pgno, callback, cookie)
|
||||
__bam_stat_print(dbc, flags)
|
||||
DBC *dbc;
|
||||
db_lockmode_t mode;
|
||||
db_pgno_t root_pgno;
|
||||
int (*callback)__P((DB *, PAGE *, void *, int *));
|
||||
void *cookie;
|
||||
u_int32_t flags;
|
||||
{
|
||||
BINTERNAL *bi;
|
||||
BKEYDATA *bk;
|
||||
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_LOCK lock;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *h;
|
||||
RINTERNAL *ri;
|
||||
db_indx_t indx;
|
||||
int already_put, ret, t_ret;
|
||||
DB_BTREE_STAT *sp;
|
||||
DB_ENV *dbenv;
|
||||
int lorder, ret;
|
||||
const char *s;
|
||||
|
||||
dbp = dbc->dbp;
|
||||
mpf = dbp->mpf;
|
||||
already_put = 0;
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
if ((ret = __db_lget(dbc, 0, root_pgno, mode, 0, &lock)) != 0)
|
||||
return (ret);
|
||||
if ((ret = mpf->get(mpf, &root_pgno, 0, &h)) != 0) {
|
||||
__LPUT(dbc, lock);
|
||||
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:");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
__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 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;
|
||||
}
|
||||
case 4321:
|
||||
s = "Big-endian";
|
||||
break;
|
||||
case P_LBTREE:
|
||||
for (indx = 0; indx < NUM_ENT(h); indx += P_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;
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
#ifdef NOT_IMPLEMENTED
|
||||
__db_dl(dbenv, "Maximum keys per-page", (u_long)sp->bt_maxkey);
|
||||
#endif
|
||||
__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_dl(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);
|
||||
|
||||
ret = callback(dbp, h, cookie, &already_put);
|
||||
__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");
|
||||
|
||||
err: if (!already_put && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret != 0)
|
||||
ret = t_ret;
|
||||
__LPUT(dbc, lock);
|
||||
__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");
|
||||
|
||||
return (ret);
|
||||
__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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -326,14 +330,23 @@ __bam_stat_callback(dbp, h, cookie, putp)
|
||||
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;
|
||||
|
||||
type = GET_BKEYDATA(dbp, h, indx + O_INDX)->type;
|
||||
if (!B_DISSET(type) && B_TYPE(type) != B_DUPLICATE)
|
||||
/* Ignore off-page duplicates. */
|
||||
if (B_TYPE(type) != B_DUPLICATE)
|
||||
++sp->bt_ndata;
|
||||
}
|
||||
|
||||
@@ -341,24 +354,28 @@ __bam_stat_callback(dbp, h, cookie, putp)
|
||||
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) {
|
||||
sp->bt_nkeys += top;
|
||||
|
||||
/*
|
||||
* Correct for deleted items in non-renumbering
|
||||
* Recno databases.
|
||||
* Correct for deleted items in non-renumbering Recno
|
||||
* databases.
|
||||
*/
|
||||
if (F_ISSET(dbp, DB_AM_RENUMBER))
|
||||
if (F_ISSET(dbp, DB_AM_RENUMBER)) {
|
||||
sp->bt_nkeys += top;
|
||||
sp->bt_ndata += top;
|
||||
else
|
||||
} else
|
||||
for (indx = 0; indx < top; indx += O_INDX) {
|
||||
type = GET_BKEYDATA(dbp, h, indx)->type;
|
||||
if (!B_DISSET(type))
|
||||
if (!B_DISSET(type)) {
|
||||
++sp->bt_ndata;
|
||||
++sp->bt_nkeys;
|
||||
}
|
||||
}
|
||||
|
||||
++sp->bt_leaf_pg;
|
||||
@@ -371,6 +388,9 @@ __bam_stat_callback(dbp, h, cookie, putp)
|
||||
}
|
||||
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))
|
||||
@@ -389,47 +409,84 @@ __bam_stat_callback(dbp, h, cookie, putp)
|
||||
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((DB *,
|
||||
* PUBLIC: DB_TXN *, DBT *, DB_KEY_RANGE *, u_int32_t));
|
||||
* PUBLIC: int __bam_key_range __P((DBC *, DBT *, DB_KEY_RANGE *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__bam_key_range(dbp, txn, dbt, kp, flags)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
__bam_key_range(dbc, dbt, kp, flags)
|
||||
DBC *dbc;
|
||||
DBT *dbt;
|
||||
DB_KEY_RANGE *kp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
BTREE_CURSOR *cp;
|
||||
DBC *dbc;
|
||||
EPG *sp;
|
||||
double factor;
|
||||
int exact, ret, t_ret;
|
||||
int exact, ret;
|
||||
|
||||
PANIC_CHECK(dbp->dbenv);
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->key_range");
|
||||
|
||||
if (flags != 0)
|
||||
return (__db_ferr(dbp->dbenv, "DB->key_range", 0));
|
||||
|
||||
/* Check for consistent transaction usage. */
|
||||
if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Acquire a cursor. */
|
||||
if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
DEBUG_LWRITE(dbc, NULL, "bam_key_range", NULL, NULL, 0);
|
||||
COMPQUIET(flags, 0);
|
||||
|
||||
if ((ret = __bam_search(dbc, PGNO_INVALID,
|
||||
dbt, S_STK_ONLY, 1, NULL, &exact)) != 0)
|
||||
goto err;
|
||||
return (ret);
|
||||
|
||||
cp = (BTREE_CURSOR *)dbc->internal;
|
||||
kp->less = kp->greater = 0.0;
|
||||
@@ -454,7 +511,7 @@ __bam_key_range(dbp, txn, dbt, kp, flags)
|
||||
else {
|
||||
kp->less += factor * sp->indx / sp->entries;
|
||||
kp->greater += factor *
|
||||
(sp->entries - sp->indx - 1) / sp->entries;
|
||||
((sp->entries - sp->indx) - 1) / sp->entries;
|
||||
}
|
||||
factor *= 1.0/sp->entries;
|
||||
}
|
||||
@@ -474,7 +531,112 @@ __bam_key_range(dbp, txn, dbt, kp, flags)
|
||||
|
||||
BT_STK_CLR(cp);
|
||||
|
||||
err: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
|
||||
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);
|
||||
|
||||
@@ -1,26 +1,23 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: bt_upgrade.c,v 11.30 2004/01/28 03:35:49 bostic Exp $
|
||||
*/
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: bt_upgrade.c,v 11.25 2002/08/06 06:11:13 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "dbinc/db_page.h"
|
||||
#include "dbinc/db_am.h"
|
||||
#include "dbinc/db_upgrade.h"
|
||||
#include "dbinc/btree.h"
|
||||
|
||||
/*
|
||||
* __bam_30_btreemeta --
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,15 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: btree.src,v 10.35 2002/04/17 19:02:56 krinsky Exp $
|
||||
* $Id: btree.src,v 10.42 2004/06/17 17:35:12 bostic Exp $
|
||||
*/
|
||||
|
||||
PREFIX __bam
|
||||
DBPRIVATE
|
||||
|
||||
INCLUDE #include "db_config.h"
|
||||
INCLUDE
|
||||
INCLUDE #ifndef NO_SYSTEM_INCLUDES
|
||||
INCLUDE #include <sys/types.h>
|
||||
INCLUDE
|
||||
@@ -26,14 +24,9 @@ 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/rep.h"
|
||||
INCLUDE #include "dbinc/txn.h"
|
||||
INCLUDE
|
||||
|
||||
/*
|
||||
* NOTE: pg_alloc and pg_free have been moved to db.src, where they belong.
|
||||
*/
|
||||
|
||||
/*
|
||||
* BTREE-split: used to log a page split.
|
||||
*
|
||||
@@ -50,14 +43,14 @@ INCLUDE
|
||||
*/
|
||||
BEGIN split 62
|
||||
DB fileid int32_t ld
|
||||
WRLOCK left db_pgno_t lu
|
||||
ARG left db_pgno_t lu
|
||||
POINTER llsn DB_LSN * lu
|
||||
WRLOCK right db_pgno_t 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
|
||||
WRLOCKNZ root_pgno db_pgno_t lu
|
||||
ARG root_pgno db_pgno_t lu
|
||||
PGDBT pg DBT s
|
||||
ARG opflags u_int32_t lu
|
||||
END
|
||||
@@ -74,9 +67,9 @@ END
|
||||
*/
|
||||
BEGIN rsplit 63
|
||||
DB fileid int32_t ld
|
||||
WRLOCK pgno db_pgno_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
PGDBT pgdbt DBT s
|
||||
WRLOCK root_pgno db_pgno_t lu
|
||||
ARG root_pgno db_pgno_t lu
|
||||
ARG nrec db_pgno_t lu
|
||||
DBT rootent DBT s
|
||||
POINTER rootlsn DB_LSN * lu
|
||||
@@ -93,7 +86,7 @@ END
|
||||
*/
|
||||
BEGIN adj 55
|
||||
DB fileid int32_t ld
|
||||
WRLOCK pgno db_pgno_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER lsn DB_LSN * lu
|
||||
ARG indx u_int32_t lu
|
||||
ARG indx_copy u_int32_t lu
|
||||
@@ -111,7 +104,7 @@ END
|
||||
*/
|
||||
BEGIN cadjust 56
|
||||
DB fileid int32_t ld
|
||||
WRLOCK pgno db_pgno_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER lsn DB_LSN * lu
|
||||
ARG indx u_int32_t lu
|
||||
ARG adjust int32_t ld
|
||||
@@ -127,7 +120,7 @@ END
|
||||
*/
|
||||
BEGIN cdel 57
|
||||
DB fileid int32_t ld
|
||||
WRLOCK pgno db_pgno_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER lsn DB_LSN * lu
|
||||
ARG indx u_int32_t lu
|
||||
END
|
||||
@@ -137,13 +130,16 @@ END
|
||||
*
|
||||
* 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.
|
||||
* new: the replacement data.
|
||||
* duplicate: the prefix of the replacement that matches the original.
|
||||
* 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
|
||||
WRLOCK pgno db_pgno_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER lsn DB_LSN * lu
|
||||
ARG indx u_int32_t lu
|
||||
ARG isdeleted u_int32_t lu
|
||||
@@ -158,8 +154,8 @@ END
|
||||
*/
|
||||
BEGIN root 59
|
||||
DB fileid int32_t ld
|
||||
WRLOCK meta_pgno db_pgno_t lu
|
||||
WRLOCK root_pgno db_pgno_t lu
|
||||
ARG meta_pgno db_pgno_t lu
|
||||
ARG root_pgno db_pgno_t lu
|
||||
POINTER meta_lsn DB_LSN * lu
|
||||
END
|
||||
|
||||
@@ -206,3 +202,24 @@ 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 changed. */
|
||||
ARG pgno db_pgno_t lu
|
||||
/* The page's original lsn. */
|
||||
POINTER lsn DB_LSN * 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
|
||||
|
||||
251
storage/bdb/build_vxworks/db_deadlock/db_deadlock.c
Normal file
251
storage/bdb/build_vxworks/db_deadlock/db_deadlock.c
Normal file
@@ -0,0 +1,251 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_deadlock.c,v 11.45 2004/03/24 15:13:12 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"Copyright (c) 1996-2004\nSleepycat Software Inc. All rights reserved.\n";
|
||||
#endif
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.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 <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
|
||||
int db_deadlock_main __P((int, char *[]));
|
||||
int db_deadlock_usage __P((void));
|
||||
int db_deadlock_version_check __P((const char *));
|
||||
|
||||
int
|
||||
db_deadlock(args)
|
||||
char *args;
|
||||
{
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
__db_util_arg("db_deadlock", args, &argc, &argv);
|
||||
return (db_deadlock_main(argc, argv) ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
#define ERROR_RETURN ERROR
|
||||
|
||||
int
|
||||
db_deadlock_main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind, __db_getopt_reset;
|
||||
const char *progname = "db_deadlock";
|
||||
DB_ENV *dbenv;
|
||||
u_int32_t atype;
|
||||
time_t now;
|
||||
u_long secs, usecs;
|
||||
int ch, exitval, ret, verbose;
|
||||
char *home, *logfile, *str;
|
||||
|
||||
if ((ret = db_deadlock_version_check(progname)) != 0)
|
||||
return (ret);
|
||||
|
||||
dbenv = NULL;
|
||||
atype = DB_LOCK_DEFAULT;
|
||||
home = logfile = NULL;
|
||||
secs = usecs = 0;
|
||||
exitval = verbose = 0;
|
||||
__db_getopt_reset = 1;
|
||||
while ((ch = getopt(argc, argv, "a:h:L:t:Vvw")) != EOF)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
switch (optarg[0]) {
|
||||
case 'e':
|
||||
atype = DB_LOCK_EXPIRE;
|
||||
break;
|
||||
case 'm':
|
||||
atype = DB_LOCK_MAXLOCKS;
|
||||
break;
|
||||
case 'n':
|
||||
atype = DB_LOCK_MINLOCKS;
|
||||
break;
|
||||
case 'o':
|
||||
atype = DB_LOCK_OLDEST;
|
||||
break;
|
||||
case 'W':
|
||||
atype = DB_LOCK_MAXWRITE;
|
||||
break;
|
||||
case 'w':
|
||||
atype = DB_LOCK_MINWRITE;
|
||||
break;
|
||||
case 'y':
|
||||
atype = DB_LOCK_YOUNGEST;
|
||||
break;
|
||||
default:
|
||||
return (db_deadlock_usage());
|
||||
/* NOTREACHED */
|
||||
}
|
||||
if (optarg[1] != '\0')
|
||||
return (db_deadlock_usage());
|
||||
break;
|
||||
case 'h':
|
||||
home = optarg;
|
||||
break;
|
||||
case 'L':
|
||||
logfile = optarg;
|
||||
break;
|
||||
case 't':
|
||||
if ((str = strchr(optarg, '.')) != NULL) {
|
||||
*str++ = '\0';
|
||||
if (*str != '\0' && __db_getulong(
|
||||
NULL, progname, str, 0, LONG_MAX, &usecs))
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
if (*optarg != '\0' && __db_getulong(
|
||||
NULL, progname, optarg, 0, LONG_MAX, &secs))
|
||||
return (EXIT_FAILURE);
|
||||
if (secs == 0 && usecs == 0)
|
||||
return (db_deadlock_usage());
|
||||
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
printf("%s\n", db_version(NULL, NULL, NULL));
|
||||
return (EXIT_SUCCESS);
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'w': /* Undocumented. */
|
||||
/* Detect every 100ms (100000 us) when polling. */
|
||||
secs = 0;
|
||||
usecs = 100000;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
return (db_deadlock_usage());
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 0)
|
||||
return (db_deadlock_usage());
|
||||
|
||||
/* Handle possible interruptions. */
|
||||
__db_util_siginit();
|
||||
|
||||
/* Log our process ID. */
|
||||
if (logfile != NULL && __db_util_logset(progname, logfile))
|
||||
goto shutdown;
|
||||
|
||||
/*
|
||||
* Create an environment object and initialize it for error
|
||||
* reporting.
|
||||
*/
|
||||
if ((ret = db_env_create(&dbenv, 0)) != 0) {
|
||||
fprintf(stderr,
|
||||
"%s: db_env_create: %s\n", progname, db_strerror(ret));
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
dbenv->set_errfile(dbenv, stderr);
|
||||
dbenv->set_errpfx(dbenv, progname);
|
||||
|
||||
if (verbose) {
|
||||
(void)dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK, 1);
|
||||
(void)dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR, 1);
|
||||
}
|
||||
|
||||
/* An environment is required. */
|
||||
if ((ret =
|
||||
dbenv->open(dbenv, home, DB_INIT_LOCK | DB_USE_ENVIRON, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "open");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
while (!__db_util_interrupted()) {
|
||||
if (verbose) {
|
||||
(void)time(&now);
|
||||
dbenv->errx(dbenv, "running at %.24s", ctime(&now));
|
||||
}
|
||||
|
||||
if ((ret = dbenv->lock_detect(dbenv, 0, atype, NULL)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB_ENV->lock_detect");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
/* Make a pass every "secs" secs and "usecs" usecs. */
|
||||
if (secs == 0 && usecs == 0)
|
||||
break;
|
||||
__os_sleep(dbenv, secs, usecs);
|
||||
}
|
||||
|
||||
if (0) {
|
||||
shutdown: exitval = 1;
|
||||
}
|
||||
|
||||
/* Clean up the logfile. */
|
||||
if (logfile != NULL)
|
||||
(void)remove(logfile);
|
||||
|
||||
/* Clean up the environment. */
|
||||
if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
|
||||
exitval = 1;
|
||||
fprintf(stderr,
|
||||
"%s: dbenv->close: %s\n", progname, db_strerror(ret));
|
||||
}
|
||||
|
||||
/* Resend any caught signal. */
|
||||
__db_util_sigresend();
|
||||
|
||||
return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int
|
||||
db_deadlock_usage()
|
||||
{
|
||||
(void)fprintf(stderr, "%s\n\t%s\n",
|
||||
"usage: db_deadlock [-Vv]",
|
||||
"[-a e | m | n | o | W | w | y] [-h home] [-L file] [-t sec.usec]");
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int
|
||||
db_deadlock_version_check(progname)
|
||||
const char *progname;
|
||||
{
|
||||
int v_major, v_minor, v_patch;
|
||||
|
||||
/* Make sure we're loaded with the right version of the DB library. */
|
||||
(void)db_version(&v_major, &v_minor, &v_patch);
|
||||
if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
|
||||
fprintf(stderr,
|
||||
"%s: version %d.%d doesn't match library version %d.%d\n",
|
||||
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
|
||||
v_major, v_minor);
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -1,51 +1,9 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 5.00
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "DB_DLL"=.\db_dll.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "DB_Static"=.\db_static.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_archive"=.\db_archive.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_buildall"=.\db_buildall.dsp - Package Owner=<4>
|
||||
Project: "build_all"=.\build_all.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
@@ -125,6 +83,24 @@ Package=<4>
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name excxx_tpcb
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_archive"=.\db_archive.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
@@ -138,10 +114,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -158,9 +131,18 @@ Package=<4>
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_dll"=.\db_dll.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
@@ -174,10 +156,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -198,6 +177,24 @@ Package=<4>
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_lib"=.\db_lib.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 db_static
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "db_load"=.\db_load.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
@@ -207,10 +204,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -225,10 +219,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -243,10 +234,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -261,15 +249,24 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
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>
|
||||
@@ -294,7 +291,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name db_buildall
|
||||
Project_Dep_Name build_all
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name db_tcl
|
||||
@@ -312,10 +309,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -330,10 +324,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -348,10 +339,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -366,10 +354,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -384,10 +369,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -402,10 +384,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -420,10 +399,22 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "ex_repquote"=.\ex_repquote.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -438,10 +429,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -456,10 +444,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -474,10 +459,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -492,10 +474,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -510,10 +489,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -528,10 +504,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -546,10 +519,7 @@ Package=<5>
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_DLL
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name DB_Static
|
||||
Project_Dep_Name db_lib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
@@ -566,3 +536,4 @@ Package=<3>
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ RSC=rc.exe
|
||||
# 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 ".." /I "../dbinc" /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
|
||||
@@ -68,7 +68,7 @@ LINK32=link.exe
|
||||
# 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 ".." /I "../dbinc" /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
|
||||
@@ -92,8 +92,8 @@ LINK32=link.exe
|
||||
# PROP Intermediate_Dir "Release_static"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# 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
|
||||
@@ -117,8 +117,8 @@ LINK32=link.exe
|
||||
# PROP Intermediate_Dir "Debug_static"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# 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
|
||||
|
||||
@@ -42,7 +42,7 @@ RSC=rc.exe
|
||||
# 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 ".." /I "../dbinc" /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
|
||||
@@ -71,7 +71,7 @@ PostBuild_Cmds=copy Release\*.exe .
|
||||
# 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 ".." /I "../dbinc" /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
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1999-2002
|
||||
* Copyright (c) 1999-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: dbkill.cpp,v 11.7 2002/01/11 15:51:27 bostic Exp $
|
||||
* $Id: dbkill.cpp,v 11.9 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
/*
|
||||
* Kill -
|
||||
|
||||
@@ -43,7 +43,7 @@ RSC=rc.exe
|
||||
# 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 ".." /I "../dbinc" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /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"
|
||||
@@ -69,7 +69,7 @@ LINK32=link.exe
|
||||
# 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 ".." /I "../dbinc" /D "DB_CREATE_DLL" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /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
|
||||
|
||||
@@ -43,7 +43,7 @@ RSC=rc.exe
|
||||
# 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 ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /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"
|
||||
@@ -60,15 +60,15 @@ InputPath=.\Release\libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll
|
||||
SOURCE="$(InputPath)"
|
||||
|
||||
"force_compilation.txt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
mkdir $(ProjDir)\Release\classes
|
||||
echo compiling Berkeley DB classes
|
||||
javac -g -d $(ProjDir)/Release/classes -classpath "$(CLASSPATH);$(ProjDir)/Release/classes" ..\java\src\com\sleepycat\db\*.java
|
||||
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
|
||||
javac -g -d $(ProjDir)/Release/classes -classpath "$(CLASSPATH);$(ProjDir)/Release/classes" ..\java\src\com\sleepycat\examples\*.java
|
||||
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
|
||||
cd $(ProjDir)\Release\classes
|
||||
jar cf ../db.jar com\sleepycat\db\*.class
|
||||
jar cf ../dbexamples.jar com\sleepycat\examples\*.class
|
||||
jar cf "$(OUTDIR)\db.jar" -C "$(OUTDIR)\classes" .
|
||||
jar cf "$(OUTDIR)\dbexamples.jar" -C "$(OUTDIR)\classes.ex" .
|
||||
echo Java build finished
|
||||
|
||||
# End Custom Build
|
||||
@@ -87,7 +87,7 @@ SOURCE="$(InputPath)"
|
||||
# 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 ".." /I "../dbinc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /D "_WINDLL" /D "_AFXDLL" /YX"config.h" /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
|
||||
@@ -105,17 +105,17 @@ InputPath=.\Debug\libdb_java@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll
|
||||
SOURCE="$(InputPath)"
|
||||
|
||||
"force_compilation.txt" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
mkdir $(ProjDir)\Debug\classes
|
||||
echo compiling Berkeley DB classes
|
||||
javac -g -d $(ProjDir)/Debug/classes -classpath "$(CLASSPATH);$(ProjDir)/Debug/classes" ..\java\src\com\sleepycat\db\*.java
|
||||
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
|
||||
javac -g -d $(ProjDir)/Debug/classes -classpath "$(CLASSPATH);$(ProjDir)/Debug/classes" ..\java\src\com\sleepycat\examples\*.java
|
||||
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
|
||||
cd $(ProjDir)\Debug\classes
|
||||
jar cf ../db.jar com\sleepycat\db\*.class
|
||||
jar cf ../dbexamples.jar com\sleepycat\examples\*.class
|
||||
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
|
||||
|
||||
@@ -1,27 +1,7 @@
|
||||
; $Id: libdb_tcl.def,v 11.5 2002/04/03 12:01:27 mjc Exp $
|
||||
; $Id: libdb_tcl.def,v 11.7 2002/10/14 23:44:20 mjc Exp $
|
||||
|
||||
DESCRIPTION 'Berkeley DB TCL interface Library'
|
||||
EXPORTS
|
||||
Db_tcl_Init
|
||||
db_Cmd
|
||||
dbc_Cmd
|
||||
env_Cmd
|
||||
tcl_EnvRemove
|
||||
tcl_LockDetect
|
||||
tcl_LockGet
|
||||
tcl_LockStat
|
||||
tcl_LockVec
|
||||
tcl_LogArchive
|
||||
tcl_LogCompare
|
||||
tcl_LogFile
|
||||
tcl_LogFlush
|
||||
tcl_LogGet
|
||||
tcl_LogPut
|
||||
tcl_LogStat
|
||||
tcl_Mp
|
||||
tcl_MpStat
|
||||
tcl_MpSync
|
||||
tcl_MpTrickle
|
||||
tcl_Txn
|
||||
tcl_TxnCheckpoint
|
||||
tcl_TxnStat
|
||||
_NameToPtr
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ BEGIN
|
||||
VALUE "FileDescription", "Berkeley DB 3.0 DLL\0"
|
||||
VALUE "FileVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
|
||||
VALUE "InternalName", "libdb.dll\0"
|
||||
VALUE "LegalCopyright", "Copyright <20> Sleepycat Software Inc. 1997-2002\0"
|
||||
VALUE "LegalCopyright", "Copyright <20> Sleepycat Software Inc. 1997-2004\0"
|
||||
VALUE "OriginalFilename", "libdb.dll\0"
|
||||
VALUE "ProductName", "Sleepycat Software libdb\0"
|
||||
VALUE "ProductVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
|
||||
|
||||
@@ -40,8 +40,8 @@ RSC=rc.exe
|
||||
# PROP Output_Dir "Release_static"
|
||||
# PROP Intermediate_Dir "Release_static"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /I "../dbinc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
|
||||
# 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
|
||||
@@ -63,8 +63,8 @@ LIB32=link.exe -lib
|
||||
# PROP Output_Dir "Debug_static"
|
||||
# PROP Intermediate_Dir "Debug_static"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
|
||||
# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /I "../dbinc" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
|
||||
# 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
|
||||
|
||||
@@ -43,7 +43,7 @@ RSC=rc.exe
|
||||
# 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 ".." /I "../dbinc" /D "DB_TCL_SUPPORT" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "DB_CREATE_DLL" /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"
|
||||
@@ -53,7 +53,7 @@ BSC32=bscmake.exe
|
||||
# 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 tcl83.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb_tcl@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
|
||||
# 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"
|
||||
|
||||
@@ -69,7 +69,7 @@ LINK32=link.exe
|
||||
# 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 ".." /I "../dbinc" /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
|
||||
# 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
|
||||
@@ -80,7 +80,7 @@ BSC32=bscmake.exe
|
||||
# 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 tcl83d.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
|
||||
# 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
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -31,14 +31,12 @@
|
||||
* 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 11.15 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: getcwd.c,v 11.13 2002/02/28 21:27:18 ubell Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -31,14 +31,12 @@
|
||||
* 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 11.9 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: getopt.c,v 11.7 2002/01/11 15:51:28 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -31,14 +31,12 @@
|
||||
* 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 11.9 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: memcmp.c,v 11.7 2002/01/11 15:51:28 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -31,14 +31,12 @@
|
||||
* 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 11.8 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: memmove.c,v 11.6 2002/01/11 15:51:28 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2002
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: raise.c,v 11.8 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: raise.c,v 11.6 2002/01/11 15:51:28 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: snprintf.c,v 11.18 2004/09/22 03:32:43 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: snprintf.c,v 11.10 2002/01/11 15:51:28 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#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.
|
||||
@@ -29,7 +35,7 @@ static const char revid[] = "$Id: snprintf.c,v 11.10 2002/01/11 15:51:28 bostic
|
||||
*/
|
||||
#ifndef HAVE_SNPRINTF
|
||||
int
|
||||
#ifdef __STDC__
|
||||
#ifdef STDC_HEADERS
|
||||
snprintf(char *str, size_t n, const char *fmt, ...)
|
||||
#else
|
||||
snprintf(str, n, fmt, va_alist)
|
||||
@@ -41,9 +47,98 @@ snprintf(str, n, fmt, va_alist)
|
||||
{
|
||||
static int ret_charpnt = -1;
|
||||
va_list ap;
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
COMPQUIET(n, 0);
|
||||
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
|
||||
@@ -53,22 +148,12 @@ snprintf(str, n, fmt, va_alist)
|
||||
* We do this test at run-time because it's not a test we can do in a
|
||||
* cross-compilation environment.
|
||||
*/
|
||||
if (ret_charpnt == -1) {
|
||||
char buf[10];
|
||||
|
||||
ret_charpnt =
|
||||
sprintf(buf, "123") != 3 ||
|
||||
sprintf(buf, "123456789") != 9 ||
|
||||
sprintf(buf, "1234") != 4;
|
||||
}
|
||||
ret_charpnt =
|
||||
(int)sprintf(buf, "123") != 3 ||
|
||||
(int)sprintf(buf, "123456789") != 9 ||
|
||||
(int)sprintf(buf, "1234") != 4;
|
||||
|
||||
#ifdef __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
len = vsprintf(str, fmt, ap);
|
||||
va_end(ap);
|
||||
return (ret_charpnt ? (int)strlen(str) : len);
|
||||
return (ret_charpnt);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -29,14 +29,12 @@
|
||||
* 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 1.8 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: strcasecmp.c,v 1.7 2001/11/15 17:51:38 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
@@ -29,14 +29,12 @@
|
||||
* 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 1.6 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: strdup.c,v 1.5 2002/05/01 18:40:05 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2002
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -31,14 +31,12 @@
|
||||
* 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 11.8 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: strerror.c,v 11.6 2002/01/11 15:51:29 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* strerror --
|
||||
* Return the string associated with an errno.
|
||||
|
||||
144
storage/bdb/clib/strtol.c
Normal file
144
storage/bdb/clib/strtol.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/*-
|
||||
* 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 1.3 2004/10/28 19:27:19 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);
|
||||
}
|
||||
123
storage/bdb/clib/strtoul.c
Normal file
123
storage/bdb/clib/strtoul.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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 1.3 2004/10/28 19:27:19 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);
|
||||
}
|
||||
45
storage/bdb/common/crypto_stub.c
Normal file
45
storage/bdb/common/crypto_stub.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: crypto_stub.c,v 1.4 2004/01/28 03:35:52 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->mutex);
|
||||
ret = !(renv->cipher_off == INVALID_ROFF);
|
||||
MUTEX_UNLOCK(dbenv, &renv->mutex);
|
||||
|
||||
if (ret == 0)
|
||||
return (0);
|
||||
|
||||
__db_err(dbenv,
|
||||
"Encrypted environment: library build did not include cryptography support");
|
||||
return (DB_OPNOTSUP);
|
||||
}
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_byteorder.c,v 11.10 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_byteorder.c,v 11.8 2002/02/01 18:15:29 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_err.c,v 11.123 2004/09/22 03:07:50 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_err.c,v 11.80 2002/07/30 01:21:53 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
@@ -27,6 +24,9 @@ static const char revid[] = "$Id: db_err.c,v 11.80 2002/07/30 01:21:53 bostic Ex
|
||||
#include "dbinc/log.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.
|
||||
@@ -76,13 +76,30 @@ __db_ferr(dbenv, name, iscombo)
|
||||
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: the DB_DIRTY_READ, DB_DEGREE_2 and DB_RMW flags require locking",
|
||||
name);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_pgerr --
|
||||
* Error when unable to retrieve a specified page.
|
||||
*
|
||||
* PUBLIC: void __db_pgerr __P((DB *, db_pgno_t, int));
|
||||
* PUBLIC: int __db_pgerr __P((DB *, db_pgno_t, int));
|
||||
*/
|
||||
void
|
||||
int
|
||||
__db_pgerr(dbp, pgno, errval)
|
||||
DB *dbp;
|
||||
db_pgno_t pgno;
|
||||
@@ -95,7 +112,7 @@ __db_pgerr(dbp, pgno, errval)
|
||||
*/
|
||||
__db_err(dbp->dbenv,
|
||||
"unable to create/retrieve page %lu", (u_long)pgno);
|
||||
(void)__db_panic(dbp->dbenv, errval);
|
||||
return (__db_panic(dbp->dbenv, errval));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -113,24 +130,6 @@ __db_pgfmt(dbenv, pgno)
|
||||
return (__db_panic(dbenv, EINVAL));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_eopnotsup --
|
||||
* Common operation not supported message.
|
||||
*
|
||||
* PUBLIC: int __db_eopnotsup __P((const DB_ENV *));
|
||||
*/
|
||||
int
|
||||
__db_eopnotsup(dbenv)
|
||||
const DB_ENV *dbenv;
|
||||
{
|
||||
__db_err(dbenv, "operation not supported");
|
||||
#ifdef EOPNOTSUPP
|
||||
return (EOPNOTSUPP);
|
||||
#else
|
||||
return (EINVAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
/*
|
||||
* __db_assert --
|
||||
@@ -167,7 +166,11 @@ int
|
||||
__db_panic_msg(dbenv)
|
||||
DB_ENV *dbenv;
|
||||
{
|
||||
__db_err(dbenv, "fatal region error detected; run recovery");
|
||||
__db_err(dbenv, "PANIC: fatal region error detected; run recovery");
|
||||
|
||||
if (dbenv->db_paniccall != NULL)
|
||||
dbenv->db_paniccall(dbenv, DB_RUNRECOVERY);
|
||||
|
||||
return (DB_RUNRECOVERY);
|
||||
}
|
||||
|
||||
@@ -185,8 +188,6 @@ __db_panic(dbenv, errval)
|
||||
if (dbenv != NULL) {
|
||||
PANIC_SET(dbenv, 1);
|
||||
|
||||
dbenv->panic_errval = errval;
|
||||
|
||||
__db_err(dbenv, "PANIC: %s", db_strerror(errval));
|
||||
|
||||
if (dbenv->db_paniccall != NULL)
|
||||
@@ -222,10 +223,15 @@ char *
|
||||
db_strerror(error)
|
||||
int error;
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (error == 0)
|
||||
return ("Successful return: 0");
|
||||
if (error > 0)
|
||||
return (strerror(error));
|
||||
if (error > 0) {
|
||||
if ((p = strerror(error)) != NULL)
|
||||
return (p);
|
||||
goto unknown_err;
|
||||
}
|
||||
|
||||
/*
|
||||
* !!!
|
||||
@@ -235,6 +241,9 @@ db_strerror(error)
|
||||
* 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:
|
||||
@@ -246,8 +255,10 @@ db_strerror(error)
|
||||
("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 server");
|
||||
return ("DB_NOSERVER: Fatal error, no RPC server");
|
||||
case DB_NOSERVER_HOME:
|
||||
return ("DB_NOSERVER_HOME: Home unrecognized at server");
|
||||
case DB_NOSERVER_ID:
|
||||
@@ -260,25 +271,38 @@ db_strerror(error)
|
||||
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_ISPERM:
|
||||
return ("DB_REP_ISPERM: Permanent record written");
|
||||
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_OUTDATED:
|
||||
case DB_REP_NOTPERM:
|
||||
return ("DB_REP_NOTPERM: Permanent log record not written");
|
||||
case DB_REP_STARTUPDONE:
|
||||
return
|
||||
("DB_REP_OUTDATED: Insufficient logs on master to recover");
|
||||
("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 item missing from primary");
|
||||
("DB_SECONDARY_BAD: Secondary index inconsistent with primary");
|
||||
case DB_VERIFY_BAD:
|
||||
return ("DB_VERIFY_BAD: Database verification failed");
|
||||
default: {
|
||||
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
|
||||
@@ -290,7 +314,6 @@ db_strerror(error)
|
||||
(void)snprintf(ebuf, sizeof(ebuf), "Unknown error: %d", error);
|
||||
return (ebuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -298,10 +321,11 @@ db_strerror(error)
|
||||
* 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: void __db_err __P((const DB_ENV *, const char *, ...))
|
||||
* PUBLIC: __attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
*/
|
||||
void
|
||||
#ifdef __STDC__
|
||||
#ifdef STDC_HEADERS
|
||||
__db_err(const DB_ENV *dbenv, const char *fmt, ...)
|
||||
#else
|
||||
__db_err(dbenv, fmt, va_alist)
|
||||
@@ -328,34 +352,17 @@ __db_errcall(dbenv, error, error_set, fmt, ap)
|
||||
va_list ap;
|
||||
{
|
||||
char *p;
|
||||
char errbuf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
|
||||
char buf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
|
||||
|
||||
p = errbuf;
|
||||
p = buf;
|
||||
if (fmt != NULL)
|
||||
p += vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
|
||||
p += vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
if (error_set)
|
||||
p += snprintf(p,
|
||||
sizeof(errbuf) - (p - errbuf), ": %s", db_strerror(error));
|
||||
/*
|
||||
* !!!
|
||||
* 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.
|
||||
*/
|
||||
if ((size_t)(p - errbuf) > sizeof(errbuf)) {
|
||||
(void)fprintf(stderr,
|
||||
"Berkeley DB: error callback interface buffer overflow\n");
|
||||
(void)fflush(stderr);
|
||||
sizeof(buf) - (size_t)(p - buf), ": %s",
|
||||
db_strerror(error));
|
||||
|
||||
abort();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
dbenv->db_errcall(dbenv->db_errpfx, errbuf);
|
||||
dbenv->db_errcall(dbenv, dbenv->db_errpfx, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -390,15 +397,121 @@ __db_errfile(dbenv, error, error_set, fmt, ap)
|
||||
(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_logmsg --
|
||||
* Write information into the DB log.
|
||||
*
|
||||
* PUBLIC: void __db_logmsg __P((const DB_ENV *,
|
||||
* PUBLIC: DB_TXN *, const char *, u_int32_t, const char *, ...));
|
||||
* PUBLIC: DB_TXN *, const char *, u_int32_t, const char *, ...))
|
||||
* PUBLIC: __attribute__ ((__format__ (__printf__, 5, 6)));
|
||||
*/
|
||||
void
|
||||
#ifdef __STDC__
|
||||
#ifdef STDC_HEADERS
|
||||
__db_logmsg(const DB_ENV *dbenv,
|
||||
DB_TXN *txnid, const char *opname, u_int32_t flags, const char *fmt, ...)
|
||||
#else
|
||||
@@ -418,7 +531,7 @@ __db_logmsg(dbenv, txnid, opname, flags, fmt, va_alist)
|
||||
if (!LOGGING_ON(dbenv))
|
||||
return;
|
||||
|
||||
#ifdef __STDC__
|
||||
#ifdef STDC_HEADERS
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
@@ -429,17 +542,17 @@ __db_logmsg(dbenv, txnid, opname, flags, fmt, va_alist)
|
||||
|
||||
memset(&msgdbt, 0, sizeof(msgdbt));
|
||||
msgdbt.data = __logbuf;
|
||||
msgdbt.size = vsnprintf(__logbuf, sizeof(__logbuf), fmt, ap);
|
||||
msgdbt.size = (u_int32_t)vsnprintf(__logbuf, sizeof(__logbuf), fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Explicitly discard the const. Otherwise, we have to const DB_ENV
|
||||
* references throughout the logging subsystem.
|
||||
*/
|
||||
__db_debug_log(
|
||||
(void)__db_debug_log(
|
||||
(DB_ENV *)dbenv, txnid, &lsn, flags, &opdbt, -1, &msgdbt, NULL, 0);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -453,7 +566,7 @@ __db_unknown_flag(dbenv, routine, flag)
|
||||
char *routine;
|
||||
u_int32_t flag;
|
||||
{
|
||||
__db_err(dbenv, "%s: Unknown flag: 0x%x", routine, flag);
|
||||
__db_err(dbenv, "%s: Unknown flag: %#x", routine, (u_int)flag);
|
||||
DB_ASSERT(0);
|
||||
return (EINVAL);
|
||||
}
|
||||
@@ -469,7 +582,9 @@ __db_unknown_type(dbenv, routine, type)
|
||||
char *routine;
|
||||
DBTYPE type;
|
||||
{
|
||||
__db_err(dbenv, "%s: Unknown db type: 0x%x", routine, type);
|
||||
__db_err(dbenv,
|
||||
"%s: Unexpected DB type: %s", routine, __db_dbtype_to_string(type));
|
||||
|
||||
DB_ASSERT(0);
|
||||
return (EINVAL);
|
||||
}
|
||||
@@ -488,6 +603,7 @@ __db_check_txn(dbp, txn, assoc_lid, read_op)
|
||||
int read_op;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int isp, ret;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
@@ -522,8 +638,19 @@ __db_check_txn(dbp, txn, assoc_lid, read_op)
|
||||
if (dbp->cur_lid >= TXN_MINIMUM)
|
||||
goto open_err;
|
||||
} else {
|
||||
if (dbp->cur_lid >= TXN_MINIMUM && dbp->cur_lid != txn->txnid)
|
||||
goto open_err;
|
||||
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 (!TXN_ON(dbenv))
|
||||
return (__db_not_txn_env(dbenv));
|
||||
@@ -577,3 +704,54 @@ __db_not_txn_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);
|
||||
}
|
||||
|
||||
/*
|
||||
* __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);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_getlong.c,v 11.22 2004/10/28 14:43:26 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_getlong.c,v 11.18 2002/03/28 20:13:33 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -26,11 +24,11 @@ static const char revid[] = "$Id: db_getlong.c,v 11.18 2002/03/28 20:13:33 bosti
|
||||
* Return a long value inside of basic parameters.
|
||||
*
|
||||
* PUBLIC: int __db_getlong
|
||||
* PUBLIC: __P((DB *, const char *, char *, long, long, long *));
|
||||
* PUBLIC: __P((DB_ENV *, const char *, char *, long, long, long *));
|
||||
*/
|
||||
int
|
||||
__db_getlong(dbp, progname, p, min, max, storep)
|
||||
DB *dbp;
|
||||
__db_getlong(dbenv, progname, p, min, max, storep)
|
||||
DB_ENV *dbenv;
|
||||
const char *progname;
|
||||
char *p;
|
||||
long min, max, *storep;
|
||||
@@ -42,38 +40,38 @@ __db_getlong(dbp, progname, p, min, max, storep)
|
||||
val = strtol(p, &end, 10);
|
||||
if ((val == LONG_MIN || val == LONG_MAX) &&
|
||||
__os_get_errno() == ERANGE) {
|
||||
if (dbp == NULL)
|
||||
if (dbenv == NULL)
|
||||
fprintf(stderr,
|
||||
"%s: %s: %s\n", progname, p, strerror(ERANGE));
|
||||
else
|
||||
dbp->err(dbp, ERANGE, "%s", p);
|
||||
dbenv->err(dbenv, ERANGE, "%s", p);
|
||||
return (1);
|
||||
}
|
||||
if (p[0] == '\0' || (end[0] != '\0' && end[0] != '\n')) {
|
||||
if (dbp == NULL)
|
||||
if (dbenv == NULL)
|
||||
fprintf(stderr,
|
||||
"%s: %s: Invalid numeric argument\n", progname, p);
|
||||
else
|
||||
dbp->errx(dbp, "%s: Invalid numeric argument", p);
|
||||
dbenv->errx(dbenv, "%s: Invalid numeric argument", p);
|
||||
return (1);
|
||||
}
|
||||
if (val < min) {
|
||||
if (dbp == NULL)
|
||||
if (dbenv == NULL)
|
||||
fprintf(stderr,
|
||||
"%s: %s: Less than minimum value (%ld)\n",
|
||||
progname, p, min);
|
||||
else
|
||||
dbp->errx(dbp,
|
||||
dbenv->errx(dbenv,
|
||||
"%s: Less than minimum value (%ld)", p, min);
|
||||
return (1);
|
||||
}
|
||||
if (val > max) {
|
||||
if (dbp == NULL)
|
||||
if (dbenv == NULL)
|
||||
fprintf(stderr,
|
||||
"%s: %s: Greater than maximum value (%ld)\n",
|
||||
progname, p, max);
|
||||
else
|
||||
dbp->errx(dbp,
|
||||
dbenv->errx(dbenv,
|
||||
"%s: Greater than maximum value (%ld)", p, max);
|
||||
return (1);
|
||||
}
|
||||
@@ -86,48 +84,43 @@ __db_getlong(dbp, progname, p, min, max, storep)
|
||||
* Return an unsigned long value inside of basic parameters.
|
||||
*
|
||||
* PUBLIC: int __db_getulong
|
||||
* PUBLIC: __P((DB *, const char *, char *, u_long, u_long, u_long *));
|
||||
* PUBLIC: __P((DB_ENV *, const char *, char *, u_long, u_long, u_long *));
|
||||
*/
|
||||
int
|
||||
__db_getulong(dbp, progname, p, min, max, storep)
|
||||
DB *dbp;
|
||||
__db_getulong(dbenv, progname, p, min, max, storep)
|
||||
DB_ENV *dbenv;
|
||||
const char *progname;
|
||||
char *p;
|
||||
u_long min, max, *storep;
|
||||
{
|
||||
#if !defined(HAVE_STRTOUL)
|
||||
COMPQUIET(min, 0);
|
||||
|
||||
return (__db_getlong(dbp, progname, p, 0, max, (long *)storep));
|
||||
#else
|
||||
u_long val;
|
||||
char *end;
|
||||
|
||||
__os_set_errno(0);
|
||||
val = strtoul(p, &end, 10);
|
||||
if (val == ULONG_MAX && __os_get_errno() == ERANGE) {
|
||||
if (dbp == NULL)
|
||||
if (dbenv == NULL)
|
||||
fprintf(stderr,
|
||||
"%s: %s: %s\n", progname, p, strerror(ERANGE));
|
||||
else
|
||||
dbp->err(dbp, ERANGE, "%s", p);
|
||||
dbenv->err(dbenv, ERANGE, "%s", p);
|
||||
return (1);
|
||||
}
|
||||
if (p[0] == '\0' || (end[0] != '\0' && end[0] != '\n')) {
|
||||
if (dbp == NULL)
|
||||
if (dbenv == NULL)
|
||||
fprintf(stderr,
|
||||
"%s: %s: Invalid numeric argument\n", progname, p);
|
||||
else
|
||||
dbp->errx(dbp, "%s: Invalid numeric argument", p);
|
||||
dbenv->errx(dbenv, "%s: Invalid numeric argument", p);
|
||||
return (1);
|
||||
}
|
||||
if (val < min) {
|
||||
if (dbp == NULL)
|
||||
if (dbenv == NULL)
|
||||
fprintf(stderr,
|
||||
"%s: %s: Less than minimum value (%lu)\n",
|
||||
progname, p, min);
|
||||
else
|
||||
dbp->errx(dbp,
|
||||
dbenv->errx(dbenv,
|
||||
"%s: Less than minimum value (%lu)", p, min);
|
||||
return (1);
|
||||
}
|
||||
@@ -139,16 +132,15 @@ __db_getulong(dbp, progname, p, min, max, storep)
|
||||
* may not exist on all platforms.
|
||||
*/
|
||||
if (max != 0 && val > max) {
|
||||
if (dbp == NULL)
|
||||
if (dbenv == NULL)
|
||||
fprintf(stderr,
|
||||
"%s: %s: Greater than maximum value (%lu)\n",
|
||||
progname, p, max);
|
||||
else
|
||||
dbp->errx(dbp,
|
||||
dbenv->errx(dbenv,
|
||||
"%s: Greater than maximum value (%lu)", p, max);
|
||||
return (1);
|
||||
}
|
||||
*storep = val;
|
||||
return (0);
|
||||
#endif /* !defined(HAVE_STRTOUL) */
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 2001-2002
|
||||
* Copyright (c) 2001-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_idspace.c,v 1.9 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_idspace.c,v 1.5 2002/02/01 18:15:29 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -44,7 +42,8 @@ __db_idcmp(a, b)
|
||||
*
|
||||
* 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).
|
||||
* 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 *));
|
||||
*/
|
||||
@@ -73,7 +72,7 @@ __db_idspace(inuse, n, minp, maxp)
|
||||
|
||||
gap = 0;
|
||||
low = 0;
|
||||
qsort(inuse, n, sizeof(u_int32_t), __db_idcmp);
|
||||
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;
|
||||
@@ -85,9 +84,9 @@ __db_idspace(inuse, n, minp, maxp)
|
||||
/* Do same check as we do in the n == 1 case. */
|
||||
if (inuse[n - 1] != *maxp)
|
||||
*minp = inuse[n - 1];
|
||||
*maxp = inuse[0];
|
||||
*maxp = inuse[0] - 1;
|
||||
} else {
|
||||
*minp = inuse[low];
|
||||
*maxp = inuse[low + 1];
|
||||
*maxp = inuse[low + 1] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -34,14 +34,12 @@
|
||||
* 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 11.9 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_log2.c,v 11.7 2002/02/01 18:15:30 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 2001-2002
|
||||
* Copyright (c) 2001-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: util_arg.c,v 1.6 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: util_arg.c,v 1.4 2002/02/01 18:15:30 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 2000-2002
|
||||
* Copyright (c) 2000-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: util_cache.c,v 1.8 2004/02/17 16:03:05 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: util_cache.c,v 1.3 2002/04/04 18:50:10 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
@@ -26,59 +23,26 @@ static const char revid[] = "$Id: util_cache.c,v 1.3 2002/04/04 18:50:10 bostic
|
||||
* __db_util_cache --
|
||||
* Compute if we have enough cache.
|
||||
*
|
||||
* PUBLIC: int __db_util_cache __P((DB_ENV *, DB *, u_int32_t *, int *));
|
||||
* PUBLIC: int __db_util_cache __P((DB *, u_int32_t *, int *));
|
||||
*/
|
||||
int
|
||||
__db_util_cache(dbenv, dbp, cachep, resizep)
|
||||
DB_ENV *dbenv;
|
||||
__db_util_cache(dbp, cachep, resizep)
|
||||
DB *dbp;
|
||||
u_int32_t *cachep;
|
||||
int *resizep;
|
||||
{
|
||||
DBTYPE type;
|
||||
DB_BTREE_STAT *bsp;
|
||||
DB_HASH_STAT *hsp;
|
||||
DB_QUEUE_STAT *qsp;
|
||||
u_int32_t pgsize;
|
||||
int ret;
|
||||
void *sp;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
if ((ret = dbp->get_type(dbp, &type)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB->get_type");
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if ((ret = dbp->stat(dbp, &sp, DB_FAST_STAT)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB->stat");
|
||||
return (ret);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case DB_QUEUE:
|
||||
qsp = (DB_QUEUE_STAT *)sp;
|
||||
pgsize = qsp->qs_pagesize;
|
||||
break;
|
||||
case DB_HASH:
|
||||
hsp = (DB_HASH_STAT *)sp;
|
||||
pgsize = hsp->hash_pagesize;
|
||||
break;
|
||||
case DB_BTREE:
|
||||
case DB_RECNO:
|
||||
bsp = (DB_BTREE_STAT *)sp;
|
||||
pgsize = bsp->bt_pagesize;
|
||||
break;
|
||||
default:
|
||||
dbenv->err(dbenv, ret, "unknown database type: %d", type);
|
||||
return (EINVAL);
|
||||
}
|
||||
free(sp);
|
||||
|
||||
/*
|
||||
*
|
||||
* Make sure our current cache is big enough. We want at least
|
||||
* DB_MINPAGECACHE pages in the cache.
|
||||
*/
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 2000-2002
|
||||
* Copyright (c) 2000-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: util_log.c,v 1.14 2004/01/28 03:35:52 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: util_log.c,v 1.11 2002/02/01 18:15:30 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -27,7 +25,6 @@ static const char revid[] = "$Id: util_log.c,v 1.11 2002/02/01 18:15:30 bostic E
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 2000-2002
|
||||
* Copyright (c) 2000-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: util_sig.c,v 1.9 2004/01/28 03:35:54 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: util_sig.c,v 1.7 2002/02/02 17:04:42 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
273
storage/bdb/crypto/aes_method.c
Normal file
273
storage/bdb/crypto/aes_method.c
Normal file
@@ -0,0 +1,273 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 2001-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* Some parts of this code originally written by Adam Stubblefield,
|
||||
* -- astubble@rice.edu.
|
||||
*
|
||||
* $Id: aes_method.c,v 1.20 2004/09/17 22:00:25 mjc 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;
|
||||
}
|
||||
385
storage/bdb/crypto/crypto.c
Normal file
385
storage/bdb/crypto/crypto.c
Normal file
@@ -0,0 +1,385 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* Some parts of this code originally written by Adam Stubblefield
|
||||
* -- astubble@rice.edu
|
||||
*
|
||||
* $Id: crypto.c,v 1.31 2004/10/15 16:59:38 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;
|
||||
MUTEX_LOCK(dbenv, &renv->mutex);
|
||||
if (renv->cipher_off == INVALID_ROFF) {
|
||||
if (!CRYPTO_ON(dbenv))
|
||||
goto err;
|
||||
if (!F_ISSET(infop, REGION_CREATE)) {
|
||||
__db_err(dbenv,
|
||||
"Joining non-encrypted environment with encryption key");
|
||||
ret = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
if (F_ISSET(db_cipher, CIPHER_ANY)) {
|
||||
__db_err(dbenv, "Encryption algorithm not supplied");
|
||||
ret = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* 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), MUTEX_ALIGN, &cipher)) != 0)
|
||||
goto err;
|
||||
memset(cipher, 0, sizeof(*cipher));
|
||||
if ((ret = __db_shalloc(
|
||||
infop, dbenv->passwd_len, 0, &sh_passwd)) != 0) {
|
||||
__db_shalloc_free(infop, cipher);
|
||||
goto err;
|
||||
}
|
||||
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");
|
||||
ret = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
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");
|
||||
ret = EPERM;
|
||||
goto err;
|
||||
}
|
||||
if (!F_ISSET(db_cipher, CIPHER_ANY) &&
|
||||
db_cipher->alg != cipher->flags) {
|
||||
__db_err(dbenv,
|
||||
"Environment encrypted using a different algorithm");
|
||||
ret = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
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)
|
||||
goto err;
|
||||
}
|
||||
MUTEX_UNLOCK(dbenv, &renv->mutex);
|
||||
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;
|
||||
|
||||
if (0) {
|
||||
err: MUTEX_UNLOCK(dbenv, &renv->mutex);
|
||||
}
|
||||
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;
|
||||
}
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
ret = 0;
|
||||
meta = (DBMETA *)mbuf;
|
||||
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 (__dbenv_set_encrypt(dbenv_dest, sh_passwd, DB_ENCRYPT_AES));
|
||||
}
|
||||
639
storage/bdb/crypto/crypto.html
Normal file
639
storage/bdb/crypto/crypto.html
Normal file
@@ -0,0 +1,639 @@
|
||||
<!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>
|
||||
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.
|
||||
Our goal is to allow users to have encrypted secure databases. In
|
||||
this document, the term <i>ciphering</i> means the act of encryption or
|
||||
decryption. 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. 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. 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. However, such a scheme, then requires that
|
||||
the password be logged in order for recovery to be able to restore the
|
||||
database. Therefore, any application having the password for the
|
||||
log could get the password for any databases by reading the log.
|
||||
So having a different password on a database does not gain any additional
|
||||
security and it makes certain things harder and more complex. 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. 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. The feature didn't
|
||||
gain anything and caused significant pain. Therefore the decision
|
||||
is that there will be a single password protecting an environment and all
|
||||
the logs and some databases within that environment. We do allow
|
||||
users to have a secure environment and clear databases. 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>.
|
||||
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>.
|
||||
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. 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. The database method must be before
|
||||
the database open in order to read the root page. The planned interfaces
|
||||
for these methods are:
|
||||
<pre>DBENV->set_encrypt(DBENV *dbenv, /* DB_ENV structure */
|
||||
char *passwd /* Password */
|
||||
u_int32_t flags); /* Flags */</pre>
|
||||
|
||||
<pre>DB->set_encrypt(DB *dbp, /* DB structure */
|
||||
char *passwd /* Password */
|
||||
u_int32_t flags); /* Flags */</pre>
|
||||
The flags accepted by these functions are:
|
||||
<pre>#define DB_ENCRYPT_AES 0x00000001 /* Use the AES encryption algorithm */</pre>
|
||||
Passwords are NULL-terminated strings. NULL or zero length strings
|
||||
are illegal. These flags enable the checksumming and encryption using
|
||||
the particular algorithms we have chosen for this implementation.
|
||||
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.
|
||||
Using DB_ENCRYPT_AES automatically implies SHA1 checksumming.
|
||||
<p>These functions will perform several initialization steps. We
|
||||
will allocate crypto_handle for our env handle and set up our function
|
||||
pointers. We will allocate space and copy the password into our env
|
||||
handle password area. 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. The purpose of this flag is to force all of the memory used
|
||||
by the shared regions to be overwritten before removal. 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. Additionally, this flag will force a sync
|
||||
of the overwritten regions to disk, if the regions are backed by the file
|
||||
system. That way there is no residual information left in the clear
|
||||
in memory or freed disk blocks. 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.
|
||||
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. Therefore
|
||||
the <i>__dbenv</i> structure needs a new pointer:
|
||||
<pre> void *crypto_handle; /* 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. It will look like:
|
||||
<pre>typedef struct __db_cipher {
|
||||
int (*init)__P((...)); /* Alg-specific initialization function */
|
||||
int (*encrypt)__P((...)); /* Alg-specific encryption algorithm */
|
||||
int (*decrypt)__P((...)); /* Alg-specific decryption function */
|
||||
void *data; /* Pointer to alg-specific information (AES_CIPHER) */
|
||||
u_int32_t flags; /* Cipher flags */
|
||||
} DB_CIPHER;</pre>
|
||||
|
||||
<pre>#define DB_MAC_KEY 20 /* Size of the MAC key */
|
||||
typedef struct __aes_cipher {
|
||||
keyInstance encrypt_ki; /* Encrypt keyInstance temp. */
|
||||
keyInstance decrypt_ki; /* Decrypt keyInstance temp. */
|
||||
u_int8_t mac_key[DB_MAC_KEY]; /* MAC key */
|
||||
u_int32_t flags; /* AES-specific flags */
|
||||
} AES_CIPHER;</pre>
|
||||
It should be noted that none of these structures have their own mutex.
|
||||
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. This function will allocate us a crypto
|
||||
handle that we store in the <i>__dbenv</i> structure just like all the
|
||||
other subsystems. For now, only AES ciphering functions and SHA1
|
||||
checksumming functions are supported. Also we will copy the password
|
||||
into the <i>__dbenv</i> structure. 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. 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 <i>__dbenv_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. This guarantees sufficient space for storing the password in
|
||||
shared memory. Then we will call a new function to initialize the
|
||||
security region, <i>__crypto_region_init</i> in <i>__dbenv_open</i>.
|
||||
If we are the creator, we will allocate space in the shared region to store
|
||||
the password and copy the password into that space. Or, if we are
|
||||
not the creator we will compare the password stored in the dbenv with the
|
||||
one in shared memory. Additionally, we will compare the ciphering
|
||||
algorithm to the one stored in the shared region.We'll smash the dbenv
|
||||
password and free it. If they do not match, we return an error.
|
||||
If we are the creator we store the offset into the REGENV structure.
|
||||
Then <i>__crypto_region_init </i> will call the initialization function
|
||||
set up earlier based on the ciphering algorithm specified. For now
|
||||
we will call <i>__aes_init</i>. Additionally this function will allocate
|
||||
and set up the per-process state vector for this encryption's IVs.
|
||||
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>,
|
||||
we will initialize it by calling
|
||||
<i>__aes_derivekeys</i> in order to fill
|
||||
in the keyInstance and mac_key fields in that structure. The REGENV
|
||||
structure will have one additional item
|
||||
<pre> roff_t passwd_off; /* 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. Basically, we test that we are not
|
||||
in an existing environment and we haven't called open. 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.
|
||||
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. 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.
|
||||
Database meta-pages will be encrypted on the first 512 bytes only.
|
||||
All meta-page types will have an IV and checksum added within the first
|
||||
512 bytes as well as a crypto magic number. 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. 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. 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. First, if the creator of the database did not create
|
||||
with security, then opening later with security is an error. Second,
|
||||
if the creator did create it with security, then opening later without
|
||||
security is an error. 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>.
|
||||
It is at this point that we will determine if the user is configured correctly.
|
||||
If the meta-page we read has an IV and checksum, they better have a crypto
|
||||
handle. If they have a crypto handle, then the meta-page must have
|
||||
an IV and checksum. If both of those are true, we test the password.
|
||||
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. 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). The functional interfaces are:
|
||||
<pre>__aes_derivekeys(DB_ENV *dbenv, /* dbenv */
|
||||
u_int8_t *passwd, /* Password */
|
||||
size_t passwd_len, /* Length of passwd */
|
||||
u_int8_t *mac_key, /* 20 byte array to store MAC key */
|
||||
keyInstance *encrypt_key, /* Encryption key of passwd */
|
||||
keyInstance *decrypt_key); /* Decryption key of passwd */</pre>
|
||||
This is the only function requiring the textual user password. From
|
||||
the password, this function generates a key used in the checksum function,
|
||||
<i>__db_chksum</i>.
|
||||
It also fills in <i>keyInstance</i> structures which are then used in the
|
||||
encryption and decryption routines. The keyInstance structures must
|
||||
already be allocated. These will be stored in the AES_CIPHER structure.
|
||||
<pre> __db_chksum(u_int8_t *data, /* Data to checksum */
|
||||
size_t data_len, /* Length of data */
|
||||
u_int8_t *mac_key, /* 20 byte array from __db_derive_keys */
|
||||
u_int8_t *checksum); /* 20 byte array to store checksum */</pre>
|
||||
This function generates a checksum on the data given. This function
|
||||
will do double-duty for users that simply want error detection on their
|
||||
pages. When users are using encryption, the <i>mac_key </i>will contain
|
||||
the 20-byte key set up in <i>__aes_derivekeys</i>. If they just want
|
||||
checksumming, then <i>mac_key</i> will be NULL. According to Adam,
|
||||
we can safely use the first N-bytes of the checksum. So for seeding
|
||||
the generator for initialization vectors, we'll hash the time and then
|
||||
send in the first 4 bytes for the seed. I believe we can probably
|
||||
do the same thing for checksumming log records. We can only use 4
|
||||
bytes for the checksum in the non-secure case. 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. All locations where we generate or check
|
||||
log record checksums that currently call <i>__ham_func4</i> will now call
|
||||
<i>__db_chksum</i>.
|
||||
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, /* dbenv */
|
||||
keyInstance *key, /* Password key instance from __db_derive_keys */
|
||||
u_int8_t *iv, /* Initialization vector */
|
||||
u_int8_t *data, /* Data to encrypt */
|
||||
size_t data_len); /* Length of data to encrypt - 16 byte multiple */</pre>
|
||||
This is the function to encrypt data. It will be called to encrypt
|
||||
pages and log records. The <i>key</i> instance is initialized in
|
||||
<i>__aes_derivekeys</i>.
|
||||
The initialization vector, <i>iv</i>, is the 16 byte random value set up
|
||||
by the Mersenne Twister pseudo-random generator. Lastly, we pass
|
||||
in a pointer to the <i>data</i> to encrypt and its length in <i>data_len</i>.
|
||||
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, /* dbenv */
|
||||
keyInstance *key, /* Password key instance from __db_derive_keys */
|
||||
u_int8_t *iv, /* Initialization vector */
|
||||
u_int8_t *data, /* Data to decrypt */
|
||||
size_t data_len); /* Length of data to decrypt - 16 byte multiple */</pre>
|
||||
This is the function to decrypt the data. It is exactly the same
|
||||
as the encryption function except for the action it performs. All
|
||||
of the args and issues are the same. 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. 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>.
|
||||
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. We plan on seeding this
|
||||
generator with the time (tv_sec) hashed through SHA1 when we create the
|
||||
environment. This package uses a global state vector that contains
|
||||
624 unsigned long integers. We do not allow a 16-byte IV of zero.
|
||||
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. 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. 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. 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. Calls
|
||||
to the MT code will come while encrypting some data in <i>__aes_encrypt.</i>
|
||||
The MT code will assume that all necessary locks are held in the caller.
|
||||
We will have per-process state vectors that are set up when a process begins.
|
||||
That way we minimize the contention and only multi-threaded processes need
|
||||
acquire locks for the IV. 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. This will be added to the <i>__dbenv</i>
|
||||
structure:
|
||||
<pre> DB_MUTEX *mt_mutexp; /* Mersenne Twister mutex */
|
||||
int *mti; /* MT index */
|
||||
u_long *mt; /* 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 to take a pointer to the location of the state vector and
|
||||
the index. There will be a wrapper function <i>__db_generate_iv</i>
|
||||
that DB will call and it will call the appropriate MT function. I
|
||||
am also going to change the default seed to use a hashed time instead of
|
||||
a hard coded value. I have looked at other implementations of the
|
||||
MT code available on the web site. The C++ version does a hash on
|
||||
the current time. I will modify our MT code to seed with the hashed
|
||||
time as well. That way the code to seed is contained within the MT
|
||||
code and we can just write the wrapper to get an IV. 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.
|
||||
We will encrypt after the method-specific function on page-out and decrypt
|
||||
before the method-specfic function on page-in. We do not hold any
|
||||
locks when entering these functions. 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. </i>See <a href="#Log Record Encryption">Log
|
||||
Record Encryption</a> for those details.
|
||||
<br>
|
||||
<h4>
|
||||
Page Changes</h4>
|
||||
The checksum and IV values will be stored prior to the first index of the
|
||||
page. We have a new P_INP macro that replaces use of inp[X] in the
|
||||
code. 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. If neither is set, then our first index is where it always was.
|
||||
If just checksumming is set, then we reserve a 4-byte checksum.
|
||||
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. 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. 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. 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. 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. If we read a hole in a file, we do not
|
||||
want to send that empty page through the decryption routine. 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. 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. Ultimately, if a checksum
|
||||
error occurs it is extremely likely that the user must do catastrophic
|
||||
recovery. There is no other failure return other than DB_RUNRECOVERY
|
||||
for indicating that the user should run catastrophic recovery. 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.
|
||||
We already indicate to the user that when they get that error, then they
|
||||
need to run recovery. If recovery fails, then they need to run catastrophic
|
||||
recovery. 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. In <i>__db_pgin</i>, we can check
|
||||
if logging is on in the environment. 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. When the recovery encounters
|
||||
the record indicating checksum failure, then normal recovery will fail
|
||||
and the user will have to perform catastrophic recovery. 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. It might make sense to wrap <i>__log_put</i>
|
||||
to encrypt the DBT we send down. The <i>__log_put </i>function is
|
||||
where the checksum is computed before acquiring the region lock.
|
||||
But also this function is where we call <i>__rep_send_message</i> to send
|
||||
the DBT to the replication clients. Therefore, we need the DBT to
|
||||
be encrypted prior to there. 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>). Log records are kept
|
||||
in a shared memory region buffer prior to going out to disk. Records
|
||||
in the buffer will be encrypted. 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. 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> Decryption will be done
|
||||
after the checksum is checked.
|
||||
<p>There are currently two nasty issues with encrypted log records.
|
||||
The first is that <i>__txn_force_abort</i> overwrites a commit record in
|
||||
the log buffer with an abort record. Well, our log buffer will be
|
||||
encrypted. Therefore, <i>__txn_force_abort</i> is going to need to
|
||||
do encryption of its new record. This can be accomplished by sending
|
||||
in the dbenv handle to the function. It is available to us in <i>__log_flush_commit</i>
|
||||
and we can just pass it in. 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. We will
|
||||
need to pad log records to meet the requirement. 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. The current header only has space for a 4 byte checksum.
|
||||
Our secure header will need space for the 16 byte IV and 20 byte checksum.
|
||||
This will blow up our log files when running securely since every single
|
||||
log record header will now consume 32 additional bytes. I believe
|
||||
that the log header does not need to be encrypted. It contains an
|
||||
offset, a length and our IV and checksum. Our IV and checksum are
|
||||
never encrypted. 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. It is not acceptable to increase the log headers
|
||||
of all users from 12 bytes to 44 bytes. Such a change would also
|
||||
make log files incompatible with earlier releases. Worse even, is
|
||||
that the <i>cksum</i> field of the header is in between the offset and
|
||||
len. It would be really convenient if we could have just made a bigger
|
||||
cksum portion without affecting the location of the other fields.
|
||||
Oh well. Most customers will not be using encryption and we won't
|
||||
make them pay the price of the expanded header. 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. 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. 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. We cannot send encrypted
|
||||
log records to clients. The reason is that the checksum and IV are
|
||||
stored in the log header and the master only sends the log record itself
|
||||
to the client. Therefore, the client has no way to decrypt a log
|
||||
record from the master. Therefore, anyone wanting to use truly secure
|
||||
replication is going to have to have a secure transport mechanism.
|
||||
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. We encrypt the
|
||||
original and send to clients the clear record. 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.
|
||||
First, if the creator of the environment did not create with security,
|
||||
then joining later with security is an error. Second, if the creator
|
||||
did create it with security, then joining later without security is an
|
||||
error. 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. 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. 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. 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. The Java and C++ interfaces will likely be done
|
||||
by Michael Cahill and Sue will implement the Tcl and RPC changes.
|
||||
Tcl will need the changes for testing purposes but the interface should
|
||||
be public, not test-only. RPC should fully support security.
|
||||
The biggest risk that I can see is that the client will send the password
|
||||
to the server in the clear. Anyone sniffing the wires or running
|
||||
tcpdump or other packet grabbing code could grab that. 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. 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. 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. 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. Proc2 joins without - should get an
|
||||
error.</li>
|
||||
|
||||
<li>
|
||||
Env/DB creates without security. Proc2 joins with - should get an
|
||||
error.</li>
|
||||
|
||||
<li>
|
||||
Env/DB creates with security. Proc2 joins with different password
|
||||
- should get an error.</li>
|
||||
|
||||
<li>
|
||||
Env/DB creates with security. Closes. Proc2 reopens with different
|
||||
password - should get an error.</li>
|
||||
|
||||
<li>
|
||||
Env/DB creates with security. Closes. Tcl overwrites a page
|
||||
of the database with garbage. Proc2 reopens with the correct password.
|
||||
Code should detect checksum error.</li>
|
||||
|
||||
<li>
|
||||
Env/DB creates with security. Open a 2nd identical DB with a different
|
||||
password. Put the exact same data into both databases. Close.
|
||||
Overwrite the identical page of DB1 with the one from DB2. Reopen
|
||||
the database with correct DB1 password. Code should detect an encryption
|
||||
error on that page.</li>
|
||||
</ol>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
Risks</h2>
|
||||
There are several holes in this design. 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. The password is stored in the shared
|
||||
data regions in the clear. Therefore if an attacker can read the
|
||||
process memory, they can do whatever they want. If the attacker can
|
||||
read system memory or swap they can access the data as well. 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. We recommend to users that they use system
|
||||
memory instead of file backed shared memory.
|
||||
</body>
|
||||
</html>
|
||||
187
storage/bdb/crypto/mersenne/mt19937db.c
Normal file
187
storage/bdb/crypto/mersenne/mt19937db.c
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* $Id: mt19937db.c,v 1.12 2004/06/14 16:54:27 mjc 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_THREAD_LOCK(dbenv, dbenv->mt_mutexp);
|
||||
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_THREAD_UNLOCK(dbenv, dbenv->mt_mutexp);
|
||||
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 the mt_mutexp 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;
|
||||
}
|
||||
1466
storage/bdb/crypto/rijndael/rijndael-alg-fst.c
Normal file
1466
storage/bdb/crypto/rijndael/rijndael-alg-fst.c
Normal file
File diff suppressed because it is too large
Load Diff
40
storage/bdb/crypto/rijndael/rijndael-alg-fst.h
Normal file
40
storage/bdb/crypto/rijndael/rijndael-alg-fst.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* $Id: rijndael-alg-fst.h,v 1.2 2002/01/08 18:53:37 sue 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 */
|
||||
496
storage/bdb/crypto/rijndael/rijndael-api-fst.c
Normal file
496
storage/bdb/crypto/rijndael/rijndael-api-fst.c
Normal file
@@ -0,0 +1,496 @@
|
||||
/**
|
||||
* 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 */
|
||||
91
storage/bdb/crypto/rijndael/rijndael-api-fst.h
Normal file
91
storage/bdb/crypto/rijndael/rijndael-api-fst.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* $Id: rijndael-api-fst.h,v 1.5 2003/03/17 19:42:18 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 */
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2002
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: cxx_db.cpp,v 11.87 2004/07/15 18:26:48 ubell Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: cxx_db.cpp,v 11.71 2002/08/26 22:13:36 mjc Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -39,25 +37,24 @@ int Db::_name _argspec \
|
||||
\
|
||||
ret = db->_name _arglist; \
|
||||
if (!_retok(ret)) \
|
||||
DB_ERROR("Db::" # _name, ret, error_policy()); \
|
||||
DB_ERROR(env_, "Db::" # _name, ret, error_policy()); \
|
||||
return (ret); \
|
||||
}
|
||||
|
||||
#define DB_METHOD_CHECKED(_name, _cleanup, _argspec, _arglist, _retok) \
|
||||
#define DB_DESTRUCTOR(_name, _argspec, _arglist, _retok) \
|
||||
int Db::_name _argspec \
|
||||
{ \
|
||||
int ret; \
|
||||
DB *db = unwrap(this); \
|
||||
\
|
||||
if (!db) { \
|
||||
DB_ERROR("Db::" # _name, EINVAL, error_policy()); \
|
||||
DB_ERROR(env_, "Db::" # _name, EINVAL, error_policy()); \
|
||||
return (EINVAL); \
|
||||
} \
|
||||
if (_cleanup) \
|
||||
cleanup(); \
|
||||
cleanup(); \
|
||||
ret = db->_name _arglist; \
|
||||
if (!_retok(ret)) \
|
||||
DB_ERROR("Db::" # _name, ret, error_policy()); \
|
||||
DB_ERROR(env_, "Db::" # _name, ret, error_policy()); \
|
||||
return (ret); \
|
||||
}
|
||||
|
||||
@@ -92,6 +89,7 @@ void Db::_name _argspec \
|
||||
Db::Db(DbEnv *env, u_int32_t flags)
|
||||
: imp_(0)
|
||||
, env_(env)
|
||||
, mpf_(0)
|
||||
, construct_error_(0)
|
||||
, flags_(0)
|
||||
, construct_flags_(flags)
|
||||
@@ -107,7 +105,7 @@ Db::Db(DbEnv *env, u_int32_t flags)
|
||||
flags_ |= DB_CXX_PRIVATE_ENV;
|
||||
|
||||
if ((construct_error_ = initialize()) != 0)
|
||||
DB_ERROR("Db::Db", construct_error_, error_policy());
|
||||
DB_ERROR(env_, "Db::Db", construct_error_, error_policy());
|
||||
}
|
||||
|
||||
// If the DB handle is still open, we close it. This is to make stack
|
||||
@@ -150,7 +148,7 @@ int Db::initialize()
|
||||
return (ret);
|
||||
|
||||
// Associate the DB with this object
|
||||
imp_ = wrap(db);
|
||||
imp_ = db;
|
||||
db->api_internal = this;
|
||||
|
||||
// Create a new DbEnv from a DB_ENV* if it was created locally.
|
||||
@@ -159,6 +157,10 @@ int Db::initialize()
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -173,7 +175,6 @@ void Db::cleanup()
|
||||
|
||||
if (db != NULL) {
|
||||
// extra safety
|
||||
db->api_internal = 0;
|
||||
imp_ = 0;
|
||||
|
||||
// we must dispose of the DbEnv object if
|
||||
@@ -187,6 +188,8 @@ void Db::cleanup()
|
||||
delete env_;
|
||||
env_ = 0;
|
||||
}
|
||||
|
||||
delete mpf_;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,26 +218,7 @@ int Db::error_policy()
|
||||
}
|
||||
}
|
||||
|
||||
int Db::close(u_int32_t flags)
|
||||
{
|
||||
DB *db = unwrap(this);
|
||||
int ret;
|
||||
|
||||
// after a DB->close (no matter if success or failure),
|
||||
// the underlying DB object must not be accessed,
|
||||
// so we clean up in advance.
|
||||
//
|
||||
cleanup();
|
||||
|
||||
// It's safe to throw an error after the close,
|
||||
// since our error mechanism does not peer into
|
||||
// the DB* structures.
|
||||
//
|
||||
if ((ret = db->close(db, flags)) != 0)
|
||||
DB_ERROR("Db::close", ret, error_policy());
|
||||
|
||||
return (ret);
|
||||
}
|
||||
DB_DESTRUCTOR(close, (u_int32_t flags), (db, flags), 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),
|
||||
@@ -259,9 +243,7 @@ void Db::errx(const char *format, ...)
|
||||
DB_REAL_ERR(db->dbenv, 0, 0, 1, format);
|
||||
}
|
||||
|
||||
DB_METHOD(fd, (int *fdp),
|
||||
(db, fdp),
|
||||
DB_RETOK_STD)
|
||||
DB_METHOD(fd, (int *fdp), (db, fdp), DB_RETOK_STD)
|
||||
|
||||
int Db::get(DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags)
|
||||
{
|
||||
@@ -271,10 +253,10 @@ int Db::get(DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags)
|
||||
ret = db->get(db, unwrap(txnid), key, value, flags);
|
||||
|
||||
if (!DB_RETOK_DBGET(ret)) {
|
||||
if (ret == ENOMEM && DB_OVERFLOWED_DBT(value))
|
||||
DB_ERROR_DBT("Db::get", value, error_policy());
|
||||
if (ret == DB_BUFFER_SMALL)
|
||||
DB_ERROR_DBT(env_, "Db::get", value, error_policy());
|
||||
else
|
||||
DB_ERROR("Db::get", ret, error_policy());
|
||||
DB_ERROR(env_, "Db::get", ret, error_policy());
|
||||
}
|
||||
|
||||
return (ret);
|
||||
@@ -286,6 +268,23 @@ int Db::get_byteswapped(int *isswapped)
|
||||
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);
|
||||
@@ -296,13 +295,11 @@ int Db::get_type(DBTYPE *dbtype)
|
||||
// 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, (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)
|
||||
(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.
|
||||
@@ -320,7 +317,7 @@ int Db::open(DbTxn *txnid, const char *file, const char *database,
|
||||
mode);
|
||||
|
||||
if (!DB_RETOK_STD(ret))
|
||||
DB_ERROR("Db::open", ret, error_policy());
|
||||
DB_ERROR(env_, "Db::open", ret, error_policy());
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -335,39 +332,36 @@ int Db::pget(DbTxn *txnid, Dbt *key, Dbt *pkey, Dbt *value, u_int32_t flags)
|
||||
/* The logic here is identical to Db::get - reuse the macro. */
|
||||
if (!DB_RETOK_DBGET(ret)) {
|
||||
if (ret == ENOMEM && DB_OVERFLOWED_DBT(value))
|
||||
DB_ERROR_DBT("Db::pget", value, error_policy());
|
||||
DB_ERROR_DBT(env_, "Db::pget", value, error_policy());
|
||||
else
|
||||
DB_ERROR("Db::pget", ret, error_policy());
|
||||
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_METHOD(put, (DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags),
|
||||
(db, unwrap(txnid), key, value, flags), DB_RETOK_DBPUT)
|
||||
|
||||
DB_METHOD_CHECKED(rename, 1,
|
||||
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_METHOD_CHECKED(remove, 1,
|
||||
(const char *file, const char *database, u_int32_t flags),
|
||||
DB_DESTRUCTOR(remove, (const char *file, const char *database, u_int32_t flags),
|
||||
(db, file, database, flags), DB_RETOK_STD)
|
||||
|
||||
DB_METHOD_CHECKED(truncate, 0,
|
||||
(DbTxn *txnid, u_int32_t *countp, u_int32_t flags),
|
||||
DB_METHOD(truncate, (DbTxn *txnid, u_int32_t *countp, u_int32_t flags),
|
||||
(db, unwrap(txnid), countp, flags), DB_RETOK_STD)
|
||||
|
||||
DB_METHOD_CHECKED(stat, 0,
|
||||
(void *sp, u_int32_t flags), (db, sp, 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_CHECKED(sync, 0,
|
||||
(u_int32_t flags), (db, flags), DB_RETOK_STD)
|
||||
DB_METHOD(stat_print, (u_int32_t flags), (db, flags), DB_RETOK_STD)
|
||||
|
||||
DB_METHOD_CHECKED(upgrade, 0,
|
||||
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)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -412,7 +406,7 @@ extern "C" _rettype _db_##_name##_intercept_c _cargspec \
|
||||
Db *cxxthis; \
|
||||
\
|
||||
DB_ASSERT(cthis != NULL); \
|
||||
cxxthis = (Db *)cthis->api_internal; \
|
||||
cxxthis = Db::get_Db(cthis); \
|
||||
DB_ASSERT(cxxthis != NULL); \
|
||||
DB_ASSERT(cxxthis->_name##_callback_ != 0); \
|
||||
\
|
||||
@@ -503,10 +497,10 @@ extern "C"
|
||||
int _verify_callback_c(void *handle, const void *str_arg)
|
||||
{
|
||||
char *str;
|
||||
__DB_OSTREAMCLASS *out;
|
||||
__DB_STD(ostream) *out;
|
||||
|
||||
str = (char *)str_arg;
|
||||
out = (__DB_OSTREAMCLASS *)handle;
|
||||
out = (__DB_STD(ostream) *)handle;
|
||||
|
||||
(*out) << str;
|
||||
if (out->fail())
|
||||
@@ -516,19 +510,26 @@ int _verify_callback_c(void *handle, const void *str_arg)
|
||||
}
|
||||
|
||||
int Db::verify(const char *name, const char *subdb,
|
||||
__DB_OSTREAMCLASS *ostr, u_int32_t flags)
|
||||
__DB_STD(ostream) *ostr, u_int32_t flags)
|
||||
{
|
||||
DB *db = unwrap(this);
|
||||
int ret;
|
||||
|
||||
if (!db)
|
||||
ret = EINVAL;
|
||||
else
|
||||
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("Db::verify", ret, error_policy());
|
||||
DB_ERROR(env_, "Db::verify", ret, error_policy());
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -537,36 +538,64 @@ DB_METHOD(set_bt_compare, (bt_compare_fcn_type func),
|
||||
(db, func), DB_RETOK_STD)
|
||||
DB_METHOD(set_bt_maxkey, (u_int32_t bt_maxkey),
|
||||
(db, bt_maxkey), 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(set_encrypt, (const char *passwd, int flags),
|
||||
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(set_re_source, (char *re_source),
|
||||
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)
|
||||
|
||||
@@ -574,11 +603,16 @@ 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 char *, char *))
|
||||
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;
|
||||
@@ -589,17 +623,34 @@ 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)
|
||||
DB_METHOD(set_cache_priority, (DB_CACHE_PRIORITY priority),
|
||||
(db, priority), DB_RETOK_STD)
|
||||
|
||||
int Db::set_paniccall(void (*callback)(DbEnv *, int))
|
||||
{
|
||||
return (env_->set_paniccall(callback));
|
||||
}
|
||||
|
||||
void Db::set_error_stream(__DB_OSTREAMCLASS *error_stream)
|
||||
__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))
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2002
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: cxx_dbc.cpp,v 11.59 2004/01/28 03:35:56 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: cxx_dbc.cpp,v 11.55 2002/07/03 21:03:52 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -39,7 +37,8 @@ int Dbc::_name _argspec \
|
||||
\
|
||||
ret = dbc->c_##_name _arglist; \
|
||||
if (!_retok(ret)) \
|
||||
DB_ERROR("Dbc::" # _name, ret, ON_ERROR_UNKNOWN); \
|
||||
DB_ERROR(DbEnv::get_DbEnv(dbc->dbp->dbenv), \
|
||||
"Dbc::" # _name, ret, ON_ERROR_UNKNOWN); \
|
||||
return (ret); \
|
||||
}
|
||||
|
||||
@@ -67,7 +66,8 @@ int Dbc::dup(Dbc** cursorp, u_int32_t _flags)
|
||||
// The following cast implies that Dbc can be no larger than DBC
|
||||
*cursorp = (Dbc*)new_cursor;
|
||||
else
|
||||
DB_ERROR("Dbc::dup", ret, ON_ERROR_UNKNOWN);
|
||||
DB_ERROR(DbEnv::get_DbEnv(dbc->dbp->dbenv),
|
||||
"Dbc::dup", ret, ON_ERROR_UNKNOWN);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -81,11 +81,14 @@ int Dbc::get(Dbt* key, Dbt *data, u_int32_t _flags)
|
||||
|
||||
if (!DB_RETOK_DBCGET(ret)) {
|
||||
if (ret == ENOMEM && DB_OVERFLOWED_DBT(key))
|
||||
DB_ERROR_DBT("Dbc::get", key, ON_ERROR_UNKNOWN);
|
||||
DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
|
||||
"Dbc::get", key, ON_ERROR_UNKNOWN);
|
||||
else if (ret == ENOMEM && DB_OVERFLOWED_DBT(data))
|
||||
DB_ERROR_DBT("Dbc::get", data, ON_ERROR_UNKNOWN);
|
||||
DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
|
||||
"Dbc::get", data, ON_ERROR_UNKNOWN);
|
||||
else
|
||||
DB_ERROR("Dbc::get", ret, ON_ERROR_UNKNOWN);
|
||||
DB_ERROR(DbEnv::get_DbEnv(dbc->dbp->dbenv),
|
||||
"Dbc::get", ret, ON_ERROR_UNKNOWN);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
@@ -101,11 +104,14 @@ int Dbc::pget(Dbt* key, Dbt *pkey, Dbt *data, u_int32_t _flags)
|
||||
/* Logic is the same as for Dbc::get - reusing macro. */
|
||||
if (!DB_RETOK_DBCGET(ret)) {
|
||||
if (ret == ENOMEM && DB_OVERFLOWED_DBT(key))
|
||||
DB_ERROR_DBT("Dbc::pget", key, ON_ERROR_UNKNOWN);
|
||||
DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
|
||||
"Dbc::pget", key, ON_ERROR_UNKNOWN);
|
||||
else if (ret == ENOMEM && DB_OVERFLOWED_DBT(data))
|
||||
DB_ERROR_DBT("Dbc::pget", data, ON_ERROR_UNKNOWN);
|
||||
DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
|
||||
"Dbc::pget", data, ON_ERROR_UNKNOWN);
|
||||
else
|
||||
DB_ERROR("Dbc::pget", ret, ON_ERROR_UNKNOWN);
|
||||
DB_ERROR(DbEnv::get_DbEnv(dbc->dbp->dbenv),
|
||||
"Dbc::pget", ret, ON_ERROR_UNKNOWN);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2002
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: cxx_dbt.cpp,v 11.55 2004/01/28 03:35:56 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: cxx_dbt.cpp,v 11.53 2002/03/27 04:31:14 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2002
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: cxx_env.cpp,v 11.105 2004/09/22 22:20:31 mjc Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: cxx_env.cpp,v 11.88 2002/08/26 22:13:36 mjc Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h> // needed for set_error_stream
|
||||
#include <string.h>
|
||||
@@ -45,7 +43,7 @@ int DbEnv::_name _argspec \
|
||||
|
||||
#define DBENV_METHOD(_name, _argspec, _arglist) \
|
||||
DBENV_METHOD_ERR(_name, _argspec, _arglist, \
|
||||
DB_ERROR("DbEnv::" # _name, ret, error_policy()))
|
||||
DB_ERROR(this, "DbEnv::" # _name, ret, error_policy()))
|
||||
|
||||
#define DBENV_METHOD_QUIET(_name, _argspec, _arglist) \
|
||||
int DbEnv::_name _argspec \
|
||||
@@ -63,13 +61,6 @@ void DbEnv::_name _argspec \
|
||||
dbenv->_name _arglist; \
|
||||
}
|
||||
|
||||
// This datatype is needed for picky compilers.
|
||||
//
|
||||
extern "C" {
|
||||
typedef void (*db_errcall_fcn_type)
|
||||
(const char *, char *);
|
||||
};
|
||||
|
||||
// The reason for a static variable is that some structures
|
||||
// (like Dbts) have no connection to any Db or DbEnv, so when
|
||||
// errors occur in their methods, we must have some reasonable
|
||||
@@ -81,8 +72,6 @@ extern "C" {
|
||||
//
|
||||
static int last_known_error_policy = ON_ERROR_UNKNOWN;
|
||||
|
||||
__DB_OSTREAMCLASS *DbEnv::error_stream_ = 0;
|
||||
|
||||
// These 'glue' function are declared as extern "C" so they will
|
||||
// be compatible with picky compilers that do not allow mixing
|
||||
// of function pointers to 'C' functions with function pointers
|
||||
@@ -101,40 +90,45 @@ void _paniccall_intercept_c(DB_ENV *env, int errval)
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void _stream_error_function_c(const char *prefix, char *message)
|
||||
void _stream_error_function_c(const DB_ENV *env,
|
||||
const char *prefix, const char *message)
|
||||
{
|
||||
DbEnv::_stream_error_function(prefix, message);
|
||||
DbEnv::_stream_error_function(env, prefix, message);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void _stream_message_function_c(const DB_ENV *env, const char *message)
|
||||
{
|
||||
DbEnv::_stream_message_function(env, message);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int _app_dispatch_intercept_c(DB_ENV *env, DBT *dbt,
|
||||
DB_LSN *lsn, db_recops op)
|
||||
DB_LSN *lsn, db_recops op)
|
||||
{
|
||||
return (DbEnv::_app_dispatch_intercept(env, dbt, lsn, op));
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int _rep_send_intercept_c(DB_ENV *env, const DBT *cntrl,
|
||||
const DBT *data, int id, u_int32_t flags)
|
||||
const DBT *data, const DB_LSN *lsn, int id,
|
||||
u_int32_t flags)
|
||||
{
|
||||
return (DbEnv::_rep_send_intercept(env,
|
||||
cntrl, data, id, flags));
|
||||
cntrl, data, lsn, id, flags));
|
||||
}
|
||||
|
||||
void DbEnv::_feedback_intercept(DB_ENV *env, int opcode, int pct)
|
||||
{
|
||||
if (env == 0) {
|
||||
DB_ERROR("DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
DbEnv *cxxenv = (DbEnv *)env->api1_internal;
|
||||
DbEnv *cxxenv = DbEnv::get_DbEnv(env);
|
||||
if (cxxenv == 0) {
|
||||
DB_ERROR("DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
|
||||
DB_ERROR(0,
|
||||
"DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
if (cxxenv->feedback_callback_ == 0) {
|
||||
DB_ERROR("DbEnv::feedback_callback", EINVAL,
|
||||
cxxenv->error_policy());
|
||||
DB_ERROR(DbEnv::get_DbEnv(env),
|
||||
"DbEnv::feedback_callback", EINVAL, cxxenv->error_policy());
|
||||
return;
|
||||
}
|
||||
(*cxxenv->feedback_callback_)(cxxenv, opcode, pct);
|
||||
@@ -142,39 +136,33 @@ void DbEnv::_feedback_intercept(DB_ENV *env, int opcode, int pct)
|
||||
|
||||
void DbEnv::_paniccall_intercept(DB_ENV *env, int errval)
|
||||
{
|
||||
if (env == 0) {
|
||||
DB_ERROR("DbEnv::paniccall_callback", EINVAL,
|
||||
ON_ERROR_UNKNOWN);
|
||||
}
|
||||
DbEnv *cxxenv = (DbEnv *)env->api1_internal;
|
||||
DbEnv *cxxenv = DbEnv::get_DbEnv(env);
|
||||
if (cxxenv == 0) {
|
||||
DB_ERROR("DbEnv::paniccall_callback", EINVAL,
|
||||
ON_ERROR_UNKNOWN);
|
||||
DB_ERROR(0,
|
||||
"DbEnv::paniccall_callback", EINVAL, ON_ERROR_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
if (cxxenv->paniccall_callback_ == 0) {
|
||||
DB_ERROR("DbEnv::paniccall_callback", EINVAL,
|
||||
DB_ERROR(cxxenv, "DbEnv::paniccall_callback", EINVAL,
|
||||
cxxenv->error_policy());
|
||||
return;
|
||||
}
|
||||
(*cxxenv->paniccall_callback_)(cxxenv, errval);
|
||||
}
|
||||
|
||||
int DbEnv::_app_dispatch_intercept(DB_ENV *env, DBT *dbt,
|
||||
DB_LSN *lsn, db_recops op)
|
||||
DB_LSN *lsn, db_recops op)
|
||||
{
|
||||
if (env == 0) {
|
||||
DB_ERROR("DbEnv::app_dispatch_callback",
|
||||
EINVAL, ON_ERROR_UNKNOWN);
|
||||
return (EINVAL);
|
||||
}
|
||||
DbEnv *cxxenv = (DbEnv *)env->api1_internal;
|
||||
DbEnv *cxxenv = DbEnv::get_DbEnv(env);
|
||||
if (cxxenv == 0) {
|
||||
DB_ERROR("DbEnv::app_dispatch_callback",
|
||||
EINVAL, ON_ERROR_UNKNOWN);
|
||||
DB_ERROR(DbEnv::get_DbEnv(env),
|
||||
"DbEnv::app_dispatch_callback", EINVAL, ON_ERROR_UNKNOWN);
|
||||
return (EINVAL);
|
||||
}
|
||||
if (cxxenv->app_dispatch_callback_ == 0) {
|
||||
DB_ERROR("DbEnv::app_dispatch_callback",
|
||||
EINVAL, cxxenv->error_policy());
|
||||
DB_ERROR(DbEnv::get_DbEnv(env),
|
||||
"DbEnv::app_dispatch_callback", EINVAL,
|
||||
cxxenv->error_policy());
|
||||
return (EINVAL);
|
||||
}
|
||||
Dbt *cxxdbt = (Dbt *)dbt;
|
||||
@@ -183,22 +171,20 @@ int DbEnv::_app_dispatch_intercept(DB_ENV *env, DBT *dbt,
|
||||
}
|
||||
|
||||
int DbEnv::_rep_send_intercept(DB_ENV *env, const DBT *cntrl,
|
||||
const DBT *data, int id, u_int32_t flags)
|
||||
const DBT *data, const DB_LSN *lsn,
|
||||
int id, u_int32_t flags)
|
||||
{
|
||||
|
||||
if (env == 0) {
|
||||
DB_ERROR("DbEnv::rep_send_callback", EINVAL, ON_ERROR_UNKNOWN);
|
||||
return (EINVAL);
|
||||
}
|
||||
DbEnv *cxxenv = (DbEnv *)env->api1_internal;
|
||||
DbEnv *cxxenv = DbEnv::get_DbEnv(env);
|
||||
if (cxxenv == 0) {
|
||||
DB_ERROR("DbEnv::rep_send_callback", EINVAL, ON_ERROR_UNKNOWN);
|
||||
DB_ERROR(DbEnv::get_DbEnv(env),
|
||||
"DbEnv::rep_send_callback", EINVAL, ON_ERROR_UNKNOWN);
|
||||
return (EINVAL);
|
||||
}
|
||||
const Dbt *cxxcntrl = (const Dbt *)cntrl;
|
||||
const DbLsn *cxxlsn = (const DbLsn *)lsn;
|
||||
Dbt *cxxdata = (Dbt *)data;
|
||||
return ((*cxxenv->rep_send_callback_)(cxxenv,
|
||||
cxxcntrl, cxxdata, id, flags));
|
||||
cxxcntrl, cxxdata, cxxlsn, id, flags));
|
||||
}
|
||||
|
||||
// A truism for the DbEnv object is that there is a valid
|
||||
@@ -217,6 +203,8 @@ DbEnv::DbEnv(u_int32_t flags)
|
||||
: imp_(0)
|
||||
, construct_error_(0)
|
||||
, construct_flags_(flags)
|
||||
, error_stream_(0)
|
||||
, message_stream_(0)
|
||||
, app_dispatch_callback_(0)
|
||||
, feedback_callback_(0)
|
||||
, paniccall_callback_(0)
|
||||
@@ -225,13 +213,16 @@ DbEnv::DbEnv(u_int32_t flags)
|
||||
, rep_send_callback_(0)
|
||||
{
|
||||
if ((construct_error_ = initialize(0)) != 0)
|
||||
DB_ERROR("DbEnv::DbEnv", construct_error_, error_policy());
|
||||
DB_ERROR(this, "DbEnv::DbEnv", construct_error_,
|
||||
error_policy());
|
||||
}
|
||||
|
||||
DbEnv::DbEnv(DB_ENV *env, u_int32_t flags)
|
||||
: imp_(0)
|
||||
, construct_error_(0)
|
||||
, construct_flags_(flags)
|
||||
, error_stream_(0)
|
||||
, message_stream_(0)
|
||||
, app_dispatch_callback_(0)
|
||||
, feedback_callback_(0)
|
||||
, paniccall_callback_(0)
|
||||
@@ -240,7 +231,8 @@ DbEnv::DbEnv(DB_ENV *env, u_int32_t flags)
|
||||
, rep_send_callback_(0)
|
||||
{
|
||||
if ((construct_error_ = initialize(env)) != 0)
|
||||
DB_ERROR("DbEnv::DbEnv", construct_error_, error_policy());
|
||||
DB_ERROR(this, "DbEnv::DbEnv", construct_error_,
|
||||
error_policy());
|
||||
}
|
||||
|
||||
// If the DB_ENV handle is still open, we close it. This is to make stack
|
||||
@@ -287,7 +279,7 @@ int DbEnv::close(u_int32_t flags)
|
||||
// the DB* structures.
|
||||
//
|
||||
if ((ret = env->close(env, flags)) != 0)
|
||||
DB_ERROR("DbEnv::close", ret, error_policy());
|
||||
DB_ERROR(this, "DbEnv::close", ret, error_policy());
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -334,6 +326,10 @@ void *DbEnv::get_app_private() const
|
||||
return unwrapConst(this)->app_private;
|
||||
}
|
||||
|
||||
DBENV_METHOD(get_home, (const char **homep), (dbenv, homep))
|
||||
DBENV_METHOD(get_open_flags, (u_int32_t *flagsp), (dbenv, flagsp))
|
||||
DBENV_METHOD(get_data_dirs, (const char ***dirspp), (dbenv, dirspp))
|
||||
|
||||
// used internally during constructor
|
||||
// to associate an existing DB_ENV with this DbEnv,
|
||||
// or create a new one.
|
||||
@@ -350,7 +346,7 @@ int DbEnv::initialize(DB_ENV *env)
|
||||
construct_flags_ & ~DB_CXX_NO_EXCEPTIONS)) != 0)
|
||||
return (ret);
|
||||
}
|
||||
imp_ = wrap(env);
|
||||
imp_ = env;
|
||||
env->api1_internal = this; // for DB_ENV* to DbEnv* conversion
|
||||
return (0);
|
||||
}
|
||||
@@ -362,7 +358,7 @@ DBENV_METHOD_ERR(lock_get,
|
||||
(u_int32_t locker, u_int32_t flags, const Dbt *obj,
|
||||
db_lockmode_t lock_mode, DbLock *lock),
|
||||
(dbenv, locker, flags, obj, lock_mode, &lock->lock_),
|
||||
DbEnv::runtime_error_lock_get("DbEnv::lock_get", ret,
|
||||
DbEnv::runtime_error_lock_get(this, "DbEnv::lock_get", ret,
|
||||
DB_LOCK_GET, lock_mode, obj, *lock,
|
||||
-1, error_policy()))
|
||||
DBENV_METHOD(lock_id, (u_int32_t *idp), (dbenv, idp))
|
||||
@@ -370,11 +366,12 @@ DBENV_METHOD(lock_id_free, (u_int32_t id), (dbenv, id))
|
||||
DBENV_METHOD(lock_put, (DbLock *lock), (dbenv, &lock->lock_))
|
||||
DBENV_METHOD(lock_stat, (DB_LOCK_STAT **statp, u_int32_t flags),
|
||||
(dbenv, statp, flags))
|
||||
DBENV_METHOD(lock_stat_print, (u_int32_t flags), (dbenv, flags))
|
||||
DBENV_METHOD_ERR(lock_vec,
|
||||
(u_int32_t locker, u_int32_t flags, DB_LOCKREQ list[],
|
||||
int nlist, DB_LOCKREQ **elist_returned),
|
||||
(dbenv, locker, flags, list, nlist, elist_returned),
|
||||
DbEnv::runtime_error_lock_get("DbEnv::lock_vec", ret,
|
||||
DbEnv::runtime_error_lock_get(this, "DbEnv::lock_vec", ret,
|
||||
(*elist_returned)->op, (*elist_returned)->mode,
|
||||
Dbt::get_Dbt((*elist_returned)->obj), DbLock((*elist_returned)->lock),
|
||||
(*elist_returned) - list, error_policy()))
|
||||
@@ -397,6 +394,7 @@ DBENV_METHOD(log_put, (DbLsn *lsn, const Dbt *data, u_int32_t flags),
|
||||
(dbenv, lsn, data, flags))
|
||||
DBENV_METHOD(log_stat, (DB_LOG_STAT **spp, u_int32_t flags),
|
||||
(dbenv, spp, flags))
|
||||
DBENV_METHOD(log_stat_print, (u_int32_t flags), (dbenv, flags))
|
||||
|
||||
int DbEnv::memp_fcreate(DbMpoolFile **dbmfp, u_int32_t flags)
|
||||
{
|
||||
@@ -411,9 +409,9 @@ int DbEnv::memp_fcreate(DbMpoolFile **dbmfp, u_int32_t flags)
|
||||
|
||||
if (DB_RETOK_STD(ret)) {
|
||||
*dbmfp = new DbMpoolFile();
|
||||
(*dbmfp)->imp_ = wrap(mpf);
|
||||
(*dbmfp)->imp_ = mpf;
|
||||
} else
|
||||
DB_ERROR("DbMpoolFile::f_create", ret, ON_ERROR_UNKNOWN);
|
||||
DB_ERROR(this, "DbMpoolFile::f_create", ret, ON_ERROR_UNKNOWN);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -426,9 +424,8 @@ DBENV_METHOD(memp_register,
|
||||
DBENV_METHOD(memp_stat,
|
||||
(DB_MPOOL_STAT **gsp, DB_MPOOL_FSTAT ***fsp, u_int32_t flags),
|
||||
(dbenv, gsp, fsp, flags))
|
||||
|
||||
DBENV_METHOD(memp_stat_print, (u_int32_t flags), (dbenv, flags))
|
||||
DBENV_METHOD(memp_sync, (DbLsn *sn), (dbenv, sn))
|
||||
|
||||
DBENV_METHOD(memp_trickle, (int pct, int *nwrotep), (dbenv, pct, nwrotep))
|
||||
|
||||
// If an error occurred during the constructor, report it now.
|
||||
@@ -445,7 +442,7 @@ int DbEnv::open(const char *db_home, u_int32_t flags, int mode)
|
||||
ret = env->open(env, db_home, flags, mode);
|
||||
|
||||
if (!DB_RETOK_STD(ret))
|
||||
DB_ERROR("DbEnv::open", ret, error_policy());
|
||||
DB_ERROR(this, "DbEnv::open", ret, error_policy());
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -462,7 +459,7 @@ int DbEnv::remove(const char *db_home, u_int32_t flags)
|
||||
cleanup();
|
||||
|
||||
if ((ret = env->remove(env, db_home, flags)) != 0)
|
||||
DB_ERROR("DbEnv::remove", ret, error_policy());
|
||||
DB_ERROR(this, "DbEnv::remove", ret, error_policy());
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -473,7 +470,8 @@ int DbEnv::remove(const char *db_home, u_int32_t flags)
|
||||
// ON_ERROR_RETURN do nothing here, the caller will return an error
|
||||
// ON_ERROR_UNKNOWN defer the policy to policy saved in DbEnv::DbEnv
|
||||
//
|
||||
void DbEnv::runtime_error(const char *caller, int error, int error_policy)
|
||||
void DbEnv::runtime_error(DbEnv *env,
|
||||
const char *caller, int error, int error_policy)
|
||||
{
|
||||
if (error_policy == ON_ERROR_UNKNOWN)
|
||||
error_policy = last_known_error_policy;
|
||||
@@ -484,18 +482,28 @@ void DbEnv::runtime_error(const char *caller, int error, int error_policy)
|
||||
case DB_LOCK_DEADLOCK:
|
||||
{
|
||||
DbDeadlockException dl_except(caller);
|
||||
dl_except.set_env(env);
|
||||
throw dl_except;
|
||||
}
|
||||
break;
|
||||
case DB_RUNRECOVERY:
|
||||
{
|
||||
DbRunRecoveryException rr_except(caller);
|
||||
rr_except.set_env(env);
|
||||
throw rr_except;
|
||||
}
|
||||
break;
|
||||
case DB_LOCK_NOTGRANTED:
|
||||
{
|
||||
DbLockNotGrantedException lng_except(caller);
|
||||
lng_except.set_env(env);
|
||||
throw lng_except;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
DbException except(caller, error);
|
||||
except.set_env(env);
|
||||
throw except;
|
||||
}
|
||||
break;
|
||||
@@ -505,7 +513,8 @@ void DbEnv::runtime_error(const char *caller, int error, int error_policy)
|
||||
|
||||
// Like DbEnv::runtime_error, but issue a DbMemoryException
|
||||
// based on the fact that this Dbt is not large enough.
|
||||
void DbEnv::runtime_error_dbt(const char *caller, Dbt *dbt, int error_policy)
|
||||
void DbEnv::runtime_error_dbt(DbEnv *env,
|
||||
const char *caller, Dbt *dbt, int error_policy)
|
||||
{
|
||||
if (error_policy == ON_ERROR_UNKNOWN)
|
||||
error_policy = last_known_error_policy;
|
||||
@@ -513,6 +522,7 @@ void DbEnv::runtime_error_dbt(const char *caller, Dbt *dbt, int error_policy)
|
||||
// Creating and throwing the object in two separate
|
||||
// statements seems to be necessary for HP compilers.
|
||||
DbMemoryException except(caller, dbt);
|
||||
except.set_env(env);
|
||||
throw except;
|
||||
}
|
||||
}
|
||||
@@ -520,12 +530,13 @@ void DbEnv::runtime_error_dbt(const char *caller, Dbt *dbt, int error_policy)
|
||||
// Like DbEnv::runtime_error, but issue a DbLockNotGrantedException,
|
||||
// or a regular runtime error.
|
||||
// call regular runtime_error if it
|
||||
void DbEnv::runtime_error_lock_get(const char *caller, int error,
|
||||
void DbEnv::runtime_error_lock_get(DbEnv *env,
|
||||
const char *caller, int error,
|
||||
db_lockop_t op, db_lockmode_t mode, const Dbt *obj,
|
||||
DbLock lock, int index, int error_policy)
|
||||
{
|
||||
if (error != DB_LOCK_NOTGRANTED) {
|
||||
runtime_error(caller, error, error_policy);
|
||||
runtime_error(env, caller, error, error_policy);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -536,52 +547,101 @@ void DbEnv::runtime_error_lock_get(const char *caller, int error,
|
||||
// statements seems to be necessary for HP compilers.
|
||||
DbLockNotGrantedException except(caller, op, mode,
|
||||
obj, lock, index);
|
||||
except.set_env(env);
|
||||
throw except;
|
||||
}
|
||||
}
|
||||
|
||||
void DbEnv::_stream_error_function(
|
||||
const DB_ENV *env, const char *prefix, const char *message)
|
||||
{
|
||||
const DbEnv *cxxenv = DbEnv::get_const_DbEnv(env);
|
||||
if (cxxenv == 0) {
|
||||
DB_ERROR(0,
|
||||
"DbEnv::stream_error", EINVAL, ON_ERROR_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cxxenv->error_callback_)
|
||||
cxxenv->error_callback_(cxxenv, prefix, message);
|
||||
else if (cxxenv->error_stream_) {
|
||||
// HP compilers need the extra casts, we don't know why.
|
||||
if (prefix) {
|
||||
(*cxxenv->error_stream_) << prefix;
|
||||
(*cxxenv->error_stream_) << (const char *)": ";
|
||||
}
|
||||
if (message)
|
||||
(*cxxenv->error_stream_) << (const char *)message;
|
||||
(*cxxenv->error_stream_) << (const char *)"\n";
|
||||
}
|
||||
}
|
||||
|
||||
void DbEnv::_stream_message_function(const DB_ENV *env, const char *message)
|
||||
{
|
||||
const DbEnv *cxxenv = DbEnv::get_const_DbEnv(env);
|
||||
if (cxxenv == 0) {
|
||||
DB_ERROR(0,
|
||||
"DbEnv::stream_message", EINVAL, ON_ERROR_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cxxenv->message_callback_)
|
||||
cxxenv->message_callback_(cxxenv, message);
|
||||
else if (cxxenv->message_stream_) {
|
||||
// HP compilers need the extra casts, we don't know why.
|
||||
(*cxxenv->message_stream_) << (const char *)message;
|
||||
(*cxxenv->message_stream_) << (const char *)"\n";
|
||||
}
|
||||
}
|
||||
|
||||
// static method
|
||||
char *DbEnv::strerror(int error)
|
||||
{
|
||||
return (db_strerror(error));
|
||||
}
|
||||
|
||||
void DbEnv::_stream_error_function(const char *prefix, char *message)
|
||||
{
|
||||
// HP compilers need the extra casts, we don't know why.
|
||||
if (error_stream_) {
|
||||
if (prefix) {
|
||||
(*error_stream_) << prefix << (const char *)": ";
|
||||
}
|
||||
if (message) {
|
||||
(*error_stream_) << (const char *)message;
|
||||
}
|
||||
(*error_stream_) << (const char *)"\n";
|
||||
}
|
||||
}
|
||||
|
||||
// set methods
|
||||
|
||||
DBENV_METHOD_VOID(set_errfile, (FILE *errfile), (dbenv, errfile))
|
||||
DBENV_METHOD_VOID(set_errpfx, (const char *errpfx), (dbenv, errpfx))
|
||||
|
||||
// We keep these alphabetical by field name,
|
||||
// for comparison with Java's list.
|
||||
//
|
||||
DBENV_METHOD(set_data_dir, (const char *dir), (dbenv, dir))
|
||||
DBENV_METHOD(set_encrypt, (const char *passwd, int flags),
|
||||
DBENV_METHOD(get_encrypt_flags, (u_int32_t *flagsp),
|
||||
(dbenv, flagsp))
|
||||
DBENV_METHOD(set_encrypt, (const char *passwd, u_int32_t flags),
|
||||
(dbenv, passwd, flags))
|
||||
DBENV_METHOD_VOID(get_errfile, (FILE **errfilep), (dbenv, errfilep))
|
||||
DBENV_METHOD_VOID(set_errfile, (FILE *errfile), (dbenv, errfile))
|
||||
DBENV_METHOD_VOID(get_errpfx, (const char **errpfxp), (dbenv, errpfxp))
|
||||
DBENV_METHOD_VOID(set_errpfx, (const char *errpfx), (dbenv, errpfx))
|
||||
DBENV_METHOD(get_lg_bsize, (u_int32_t *bsizep), (dbenv, bsizep))
|
||||
DBENV_METHOD(set_lg_bsize, (u_int32_t bsize), (dbenv, bsize))
|
||||
DBENV_METHOD(get_lg_dir, (const char **dirp), (dbenv, dirp))
|
||||
DBENV_METHOD(set_lg_dir, (const char *dir), (dbenv, dir))
|
||||
DBENV_METHOD(get_lg_max, (u_int32_t *maxp), (dbenv, maxp))
|
||||
DBENV_METHOD(set_lg_max, (u_int32_t max), (dbenv, max))
|
||||
DBENV_METHOD(get_lg_regionmax, (u_int32_t *regionmaxp), (dbenv, regionmaxp))
|
||||
DBENV_METHOD(set_lg_regionmax, (u_int32_t regionmax), (dbenv, regionmax))
|
||||
DBENV_METHOD(get_lk_conflicts, (const u_int8_t **lk_conflictsp, int *lk_maxp),
|
||||
(dbenv, lk_conflictsp, lk_maxp))
|
||||
DBENV_METHOD(set_lk_conflicts, (u_int8_t *lk_conflicts, int lk_max),
|
||||
(dbenv, lk_conflicts, lk_max))
|
||||
DBENV_METHOD(get_lk_detect, (u_int32_t *detectp), (dbenv, detectp))
|
||||
DBENV_METHOD(set_lk_detect, (u_int32_t detect), (dbenv, detect))
|
||||
DBENV_METHOD(set_lk_max, (u_int32_t max), (dbenv, max))
|
||||
DBENV_METHOD(get_lk_max_lockers, (u_int32_t *max_lockersp),
|
||||
(dbenv, max_lockersp))
|
||||
DBENV_METHOD(set_lk_max_lockers, (u_int32_t max_lockers), (dbenv, max_lockers))
|
||||
DBENV_METHOD(get_lk_max_locks, (u_int32_t *max_locksp), (dbenv, max_locksp))
|
||||
DBENV_METHOD(set_lk_max_locks, (u_int32_t max_locks), (dbenv, max_locks))
|
||||
DBENV_METHOD(get_lk_max_objects, (u_int32_t *max_objectsp),
|
||||
(dbenv, max_objectsp))
|
||||
DBENV_METHOD(set_lk_max_objects, (u_int32_t max_objects), (dbenv, max_objects))
|
||||
DBENV_METHOD(get_mp_mmapsize, (size_t *mmapsizep), (dbenv, mmapsizep))
|
||||
DBENV_METHOD(set_mp_mmapsize, (size_t mmapsize), (dbenv, mmapsize))
|
||||
DBENV_METHOD_VOID(get_msgfile, (FILE **msgfilep), (dbenv, msgfilep))
|
||||
DBENV_METHOD_VOID(set_msgfile, (FILE *msgfile), (dbenv, msgfile))
|
||||
DBENV_METHOD(get_tmp_dir, (const char **tmp_dirp), (dbenv, tmp_dirp))
|
||||
DBENV_METHOD(set_tmp_dir, (const char *tmp_dir), (dbenv, tmp_dir))
|
||||
DBENV_METHOD(get_tx_max, (u_int32_t *tx_maxp), (dbenv, tx_maxp))
|
||||
DBENV_METHOD(set_tx_max, (u_int32_t tx_max), (dbenv, tx_max))
|
||||
|
||||
DBENV_METHOD_QUIET(set_alloc,
|
||||
@@ -594,40 +654,36 @@ void DbEnv::set_app_private(void *value)
|
||||
unwrap(this)->app_private = value;
|
||||
}
|
||||
|
||||
DBENV_METHOD(get_cachesize,
|
||||
(u_int32_t *gbytesp, u_int32_t *bytesp, int *ncachep),
|
||||
(dbenv, gbytesp, bytesp, ncachep))
|
||||
DBENV_METHOD(set_cachesize,
|
||||
(u_int32_t gbytes, u_int32_t bytes, int ncache),
|
||||
(dbenv, gbytes, bytes, ncache))
|
||||
|
||||
void DbEnv::set_errcall(void (*arg)(const char *, char *))
|
||||
void DbEnv::set_errcall(void (*arg)(const DbEnv *, const char *, const char *))
|
||||
{
|
||||
DB_ENV *dbenv = unwrap(this);
|
||||
|
||||
// XXX
|
||||
// We are casting from a function ptr declared with C++
|
||||
// linkage to one (same arg types) declared with C
|
||||
// linkage. It's hard to imagine a pair of C/C++
|
||||
// compilers from the same vendor for which this
|
||||
// won't work. Unfortunately, we can't use a
|
||||
// intercept function like the others since the
|
||||
// function does not have a (DbEnv*) as one of
|
||||
// the args. If this causes trouble, we can pull
|
||||
// the same trick we use in Java, namely stuffing
|
||||
// a (DbEnv*) pointer into the prefix. We're
|
||||
// avoiding this for the moment because it obfuscates.
|
||||
//
|
||||
(*(dbenv->set_errcall))(dbenv, (db_errcall_fcn_type)arg);
|
||||
error_callback_ = arg;
|
||||
error_stream_ = 0;
|
||||
|
||||
dbenv->set_errcall(dbenv, (arg == 0) ? 0 :
|
||||
_stream_error_function_c);
|
||||
}
|
||||
|
||||
// Note: This actually behaves a bit like a static function,
|
||||
// since DB_ENV.db_errcall has no information about which
|
||||
// db_env triggered the call. A user that has multiple DB_ENVs
|
||||
// will simply not be able to have different streams for each one.
|
||||
//
|
||||
void DbEnv::set_error_stream(__DB_OSTREAMCLASS *stream)
|
||||
__DB_STD(ostream) *DbEnv::get_error_stream()
|
||||
{
|
||||
return (error_stream_);
|
||||
}
|
||||
|
||||
void DbEnv::set_error_stream(__DB_STD(ostream) *stream)
|
||||
{
|
||||
DB_ENV *dbenv = unwrap(this);
|
||||
|
||||
error_stream_ = stream;
|
||||
error_callback_ = 0;
|
||||
|
||||
dbenv->set_errcall(dbenv, (stream == 0) ? 0 :
|
||||
_stream_error_function_c);
|
||||
}
|
||||
@@ -638,12 +694,38 @@ int DbEnv::set_feedback(void (*arg)(DbEnv *, int, int))
|
||||
|
||||
feedback_callback_ = arg;
|
||||
|
||||
return ((*(dbenv->set_feedback))(dbenv, _feedback_intercept_c));
|
||||
return (dbenv->set_feedback(dbenv, _feedback_intercept_c));
|
||||
}
|
||||
|
||||
DBENV_METHOD(get_flags, (u_int32_t *flagsp), (dbenv, flagsp))
|
||||
DBENV_METHOD(set_flags, (u_int32_t flags, int onoff), (dbenv, flags, onoff))
|
||||
DBENV_METHOD(set_lk_conflicts, (u_int8_t *lk_conflicts, int lk_max),
|
||||
(dbenv, lk_conflicts, lk_max))
|
||||
|
||||
void DbEnv::set_msgcall(void (*arg)(const DbEnv *, const char *))
|
||||
{
|
||||
DB_ENV *dbenv = unwrap(this);
|
||||
|
||||
message_callback_ = arg;
|
||||
message_stream_ = 0;
|
||||
|
||||
dbenv->set_msgcall(dbenv, (arg == 0) ? 0 :
|
||||
_stream_message_function_c);
|
||||
}
|
||||
|
||||
__DB_STD(ostream) *DbEnv::get_message_stream()
|
||||
{
|
||||
return (message_stream_);
|
||||
}
|
||||
|
||||
void DbEnv::set_message_stream(__DB_STD(ostream) *stream)
|
||||
{
|
||||
DB_ENV *dbenv = unwrap(this);
|
||||
|
||||
message_stream_ = stream;
|
||||
message_callback_ = 0;
|
||||
|
||||
dbenv->set_msgcall(dbenv, (stream == 0) ? 0 :
|
||||
_stream_message_function_c);
|
||||
}
|
||||
|
||||
int DbEnv::set_paniccall(void (*arg)(DbEnv *, int))
|
||||
{
|
||||
@@ -651,14 +733,16 @@ int DbEnv::set_paniccall(void (*arg)(DbEnv *, int))
|
||||
|
||||
paniccall_callback_ = arg;
|
||||
|
||||
return ((*(dbenv->set_paniccall))(dbenv, _paniccall_intercept_c));
|
||||
return (dbenv->set_paniccall(dbenv, _paniccall_intercept_c));
|
||||
}
|
||||
|
||||
DBENV_METHOD(set_rpc_server,
|
||||
(void *cl, char *host, long tsec, long ssec, u_int32_t flags),
|
||||
(dbenv, cl, host, tsec, ssec, flags))
|
||||
DBENV_METHOD(get_shm_key, (long *shm_keyp), (dbenv, shm_keyp))
|
||||
DBENV_METHOD(set_shm_key, (long shm_key), (dbenv, shm_key))
|
||||
// Note: this changes from last_known_error_policy to error_policy()
|
||||
DBENV_METHOD(get_tas_spins, (u_int32_t *argp), (dbenv, argp))
|
||||
DBENV_METHOD(set_tas_spins, (u_int32_t arg), (dbenv, arg))
|
||||
|
||||
int DbEnv::set_app_dispatch
|
||||
@@ -668,14 +752,17 @@ int DbEnv::set_app_dispatch
|
||||
int ret;
|
||||
|
||||
app_dispatch_callback_ = arg;
|
||||
if ((ret = (*(dbenv->set_app_dispatch))(dbenv,
|
||||
if ((ret = dbenv->set_app_dispatch(dbenv,
|
||||
_app_dispatch_intercept_c)) != 0)
|
||||
DB_ERROR("DbEnv::set_app_dispatch", ret, error_policy());
|
||||
DB_ERROR(this, "DbEnv::set_app_dispatch", ret, error_policy());
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
DBENV_METHOD(get_tx_timestamp, (time_t *timestamp), (dbenv, timestamp))
|
||||
DBENV_METHOD(set_tx_timestamp, (time_t *timestamp), (dbenv, timestamp))
|
||||
DBENV_METHOD(get_verbose, (u_int32_t which, int *onoffp),
|
||||
(dbenv, which, onoffp))
|
||||
DBENV_METHOD(set_verbose, (u_int32_t which, int onoff), (dbenv, which, onoff))
|
||||
|
||||
int DbEnv::txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags)
|
||||
@@ -688,7 +775,7 @@ int DbEnv::txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags)
|
||||
if (DB_RETOK_STD(ret))
|
||||
*tid = new DbTxn(txn);
|
||||
else
|
||||
DB_ERROR("DbEnv::txn_begin", ret, error_policy());
|
||||
DB_ERROR(this, "DbEnv::txn_begin", ret, error_policy());
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -716,20 +803,20 @@ int DbEnv::txn_recover(DbPreplist *preplist, long count,
|
||||
&c_preplist);
|
||||
|
||||
if (ret != 0) {
|
||||
DB_ERROR("DbEnv::txn_recover", ret, error_policy());
|
||||
DB_ERROR(this, "DbEnv::txn_recover", ret, error_policy());
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if ((ret =
|
||||
dbenv->txn_recover(dbenv, c_preplist, count, retp, flags)) != 0) {
|
||||
__os_free(dbenv, c_preplist);
|
||||
DB_ERROR("DbEnv::txn_recover", ret, error_policy());
|
||||
DB_ERROR(this, "DbEnv::txn_recover", ret, error_policy());
|
||||
return (ret);
|
||||
}
|
||||
|
||||
for (i = 0; i < *retp; i++) {
|
||||
preplist[i].txn = new DbTxn();
|
||||
preplist[i].txn->imp_ = wrap(c_preplist[i].txn);
|
||||
preplist[i].txn->imp_ = c_preplist[i].txn;
|
||||
memcpy(preplist[i].gid, c_preplist[i].gid,
|
||||
sizeof(preplist[i].gid));
|
||||
}
|
||||
@@ -741,9 +828,11 @@ int DbEnv::txn_recover(DbPreplist *preplist, long count,
|
||||
|
||||
DBENV_METHOD(txn_stat, (DB_TXN_STAT **statp, u_int32_t flags),
|
||||
(dbenv, statp, flags))
|
||||
DBENV_METHOD(txn_stat_print, (u_int32_t flags), (dbenv, flags))
|
||||
|
||||
int DbEnv::set_rep_transport(u_int32_t myid,
|
||||
int (*f_send)(DbEnv *, const Dbt *, const Dbt *, int, u_int32_t))
|
||||
int DbEnv::set_rep_transport(int myid,
|
||||
int (*f_send)(DbEnv *, const Dbt *, const Dbt *, const DbLsn *, int,
|
||||
u_int32_t))
|
||||
{
|
||||
DB_ENV *dbenv = unwrap(this);
|
||||
int ret;
|
||||
@@ -751,23 +840,26 @@ int DbEnv::set_rep_transport(u_int32_t myid,
|
||||
rep_send_callback_ = f_send;
|
||||
if ((ret = dbenv->set_rep_transport(dbenv,
|
||||
myid, _rep_send_intercept_c)) != 0)
|
||||
DB_ERROR("DbEnv::set_rep_transport", ret, error_policy());
|
||||
DB_ERROR(this, "DbEnv::set_rep_transport", ret, error_policy());
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
DBENV_METHOD(rep_elect,
|
||||
(int nsites, int pri, u_int32_t timeout, int *idp),
|
||||
(dbenv, nsites, pri, timeout, idp))
|
||||
(int nsites,
|
||||
int nvotes, int priority, u_int32_t timeout, int *eidp, u_int32_t flags),
|
||||
(dbenv, nsites, nvotes, priority, timeout, eidp, flags))
|
||||
|
||||
int DbEnv::rep_process_message(Dbt *control, Dbt *rec, int *idp)
|
||||
int DbEnv::rep_process_message(Dbt *control,
|
||||
Dbt *rec, int *idp, DbLsn *ret_lsnp)
|
||||
{
|
||||
DB_ENV *dbenv = unwrap(this);
|
||||
int ret;
|
||||
|
||||
ret = dbenv->rep_process_message(dbenv, control, rec, idp);
|
||||
ret = dbenv->rep_process_message(dbenv, control, rec, idp, ret_lsnp);
|
||||
if (!DB_RETOK_REPPMSG(ret))
|
||||
DB_ERROR("DbEnv::rep_process_message", ret, error_policy());
|
||||
DB_ERROR(this, "DbEnv::rep_process_message", ret,
|
||||
error_policy());
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -778,10 +870,16 @@ DBENV_METHOD(rep_start,
|
||||
|
||||
DBENV_METHOD(rep_stat, (DB_REP_STAT **statp, u_int32_t flags),
|
||||
(dbenv, statp, flags))
|
||||
DBENV_METHOD(rep_stat_print, (u_int32_t flags), (dbenv, flags))
|
||||
|
||||
DBENV_METHOD(get_rep_limit, (u_int32_t *gbytesp, u_int32_t *bytesp),
|
||||
(dbenv, gbytesp, bytesp))
|
||||
DBENV_METHOD(set_rep_limit, (u_int32_t gbytes, u_int32_t bytes),
|
||||
(dbenv, gbytes, bytes))
|
||||
|
||||
DBENV_METHOD(get_timeout,
|
||||
(db_timeout_t *timeoutp, u_int32_t flags),
|
||||
(dbenv, timeoutp, flags))
|
||||
DBENV_METHOD(set_timeout,
|
||||
(db_timeout_t timeout, u_int32_t flags),
|
||||
(dbenv, timeout, flags))
|
||||
@@ -796,7 +894,5 @@ char *DbEnv::version(int *major, int *minor, int *patch)
|
||||
DbEnv *DbEnv::wrap_DB_ENV(DB_ENV *dbenv)
|
||||
{
|
||||
DbEnv *wrapped_env = get_DbEnv(dbenv);
|
||||
if (wrapped_env == NULL)
|
||||
wrapped_env = new DbEnv(dbenv, 0);
|
||||
return wrapped_env;
|
||||
return (wrapped_env != NULL) ? wrapped_env : new DbEnv(dbenv, 0);
|
||||
}
|
||||
|
||||
@@ -1,68 +1,20 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2002
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: cxx_except.cpp,v 11.28 2004/09/22 03:34:48 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: cxx_except.cpp,v 11.17 2002/08/23 01:07:27 mjc Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "db_cxx.h"
|
||||
#include "dbinc/cxx_int.h"
|
||||
|
||||
// tmpString is used to create strings on the stack
|
||||
//
|
||||
class tmpString
|
||||
{
|
||||
public:
|
||||
tmpString(const char *str1,
|
||||
const char *str2 = 0,
|
||||
const char *str3 = 0,
|
||||
const char *str4 = 0,
|
||||
const char *str5 = 0);
|
||||
~tmpString() { delete [] s_; }
|
||||
operator const char *() { return (s_); }
|
||||
|
||||
private:
|
||||
char *s_;
|
||||
};
|
||||
|
||||
tmpString::tmpString(const char *str1,
|
||||
const char *str2,
|
||||
const char *str3,
|
||||
const char *str4,
|
||||
const char *str5)
|
||||
{
|
||||
size_t len = strlen(str1);
|
||||
if (str2)
|
||||
len += strlen(str2);
|
||||
if (str3)
|
||||
len += strlen(str3);
|
||||
if (str4)
|
||||
len += strlen(str4);
|
||||
if (str5)
|
||||
len += strlen(str5);
|
||||
|
||||
s_ = new char[len+1];
|
||||
|
||||
strcpy(s_, str1);
|
||||
if (str2)
|
||||
strcat(s_, str2);
|
||||
if (str3)
|
||||
strcat(s_, str3);
|
||||
if (str4)
|
||||
strcat(s_, str4);
|
||||
if (str5)
|
||||
strcat(s_, str5);
|
||||
}
|
||||
|
||||
// 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).
|
||||
@@ -80,65 +32,113 @@ static char *dupString(const char *s)
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbException::~DbException()
|
||||
DbException::~DbException() throw()
|
||||
{
|
||||
if (what_)
|
||||
delete [] what_;
|
||||
delete [] what_;
|
||||
}
|
||||
|
||||
DbException::DbException(int err)
|
||||
: err_(err)
|
||||
, env_(0)
|
||||
{
|
||||
what_ = dupString(db_strerror(err));
|
||||
describe(0, 0);
|
||||
}
|
||||
|
||||
DbException::DbException(const char *description)
|
||||
: err_(0)
|
||||
, env_(0)
|
||||
{
|
||||
what_ = dupString(tmpString(description));
|
||||
describe(0, description);
|
||||
}
|
||||
|
||||
DbException::DbException(const char *prefix, int err)
|
||||
DbException::DbException(const char *description, int err)
|
||||
: err_(err)
|
||||
, env_(0)
|
||||
{
|
||||
what_ = dupString(tmpString(prefix, ": ", db_strerror(err)));
|
||||
describe(0, description);
|
||||
}
|
||||
|
||||
DbException::DbException(const char *prefix1, const char *prefix2, int err)
|
||||
DbException::DbException(const char *prefix, const char *description, int err)
|
||||
: err_(err)
|
||||
, env_(0)
|
||||
{
|
||||
what_ = dupString(tmpString(prefix1, ": ", prefix2, ": ",
|
||||
db_strerror(err)));
|
||||
describe(prefix, description);
|
||||
}
|
||||
|
||||
DbException::DbException(const DbException &that)
|
||||
: err_(that.err_)
|
||||
: __DB_STD(exception)()
|
||||
, what_(dupString(that.what_))
|
||||
, err_(that.err_)
|
||||
, env_(0)
|
||||
{
|
||||
what_ = dupString(that.what_);
|
||||
}
|
||||
|
||||
DbException &DbException::operator = (const DbException &that)
|
||||
{
|
||||
if (this != &that) {
|
||||
err_ = that.err_;
|
||||
if (what_)
|
||||
delete [] what_;
|
||||
what_ = 0; // in case new throws exception
|
||||
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
|
||||
const char *DbException::what() const throw()
|
||||
{
|
||||
return (what_);
|
||||
}
|
||||
|
||||
DbEnv *DbException::get_env() const
|
||||
{
|
||||
return env_;
|
||||
}
|
||||
|
||||
void DbException::set_env(DbEnv *env)
|
||||
{
|
||||
env_= env;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DbMemoryException //
|
||||
@@ -146,7 +146,7 @@ const char *DbException::what() const
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const char *memory_err_desc = "Dbt not large enough for available data";
|
||||
DbMemoryException::~DbMemoryException()
|
||||
DbMemoryException::~DbMemoryException() throw()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -156,25 +156,12 @@ DbMemoryException::DbMemoryException(Dbt *dbt)
|
||||
{
|
||||
}
|
||||
|
||||
DbMemoryException::DbMemoryException(const char *description)
|
||||
: DbException(description, ENOMEM)
|
||||
, dbt_(0)
|
||||
{
|
||||
}
|
||||
|
||||
DbMemoryException::DbMemoryException(const char *prefix, Dbt *dbt)
|
||||
: DbException(prefix, memory_err_desc, ENOMEM)
|
||||
, dbt_(dbt)
|
||||
{
|
||||
}
|
||||
|
||||
DbMemoryException::DbMemoryException(const char *prefix1, const char *prefix2,
|
||||
Dbt *dbt)
|
||||
: DbException(prefix1, prefix2, ENOMEM)
|
||||
, dbt_(dbt)
|
||||
{
|
||||
}
|
||||
|
||||
DbMemoryException::DbMemoryException(const DbMemoryException &that)
|
||||
: DbException(that)
|
||||
, dbt_(that.dbt_)
|
||||
@@ -202,7 +189,7 @@ Dbt *DbMemoryException::get_dbt() const
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbDeadlockException::~DbDeadlockException()
|
||||
DbDeadlockException::~DbDeadlockException() throw()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -230,7 +217,7 @@ DbDeadlockException
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbLockNotGrantedException::~DbLockNotGrantedException()
|
||||
DbLockNotGrantedException::~DbLockNotGrantedException() throw()
|
||||
{
|
||||
delete lock_;
|
||||
}
|
||||
@@ -243,9 +230,19 @@ DbLockNotGrantedException::DbLockNotGrantedException(const char *prefix,
|
||||
, op_(op)
|
||||
, mode_(mode)
|
||||
, obj_(obj)
|
||||
, lock_(new DbLock(lock))
|
||||
, index_(index)
|
||||
{
|
||||
lock_ = new DbLock(lock);
|
||||
}
|
||||
|
||||
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
|
||||
@@ -255,7 +252,7 @@ DbLockNotGrantedException::DbLockNotGrantedException
|
||||
op_ = that.op_;
|
||||
mode_ = that.mode_;
|
||||
obj_ = that.obj_;
|
||||
lock_ = new DbLock(*that.lock_);
|
||||
lock_ = (that.lock_ != NULL) ? new DbLock(*that.lock_) : NULL;
|
||||
index_ = that.index_;
|
||||
}
|
||||
|
||||
@@ -267,7 +264,7 @@ DbLockNotGrantedException
|
||||
op_ = that.op_;
|
||||
mode_ = that.mode_;
|
||||
obj_ = that.obj_;
|
||||
lock_ = new DbLock(*that.lock_);
|
||||
lock_ = (that.lock_ != NULL) ? new DbLock(*that.lock_) : NULL;
|
||||
index_ = that.index_;
|
||||
}
|
||||
return (*this);
|
||||
@@ -298,15 +295,13 @@ int DbLockNotGrantedException::get_index() const
|
||||
return index_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DbRunRecoveryException //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbRunRecoveryException::~DbRunRecoveryException()
|
||||
DbRunRecoveryException::~DbRunRecoveryException() throw()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2002
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: cxx_lock.cpp,v 11.19 2004/01/28 03:35:56 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: cxx_lock.cpp,v 11.17 2002/03/27 04:31:16 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2002
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: cxx_logc.cpp,v 11.13 2004/02/05 02:25:12 mjc Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: cxx_logc.cpp,v 11.8 2002/07/03 21:03:53 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -37,11 +35,12 @@ 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("DbLogc::close", ret, ON_ERROR_UNKNOWN);
|
||||
DB_ERROR(dbenv2, "DbLogc::close", ret, ON_ERROR_UNKNOWN);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -55,10 +54,12 @@ int DbLogc::get(DbLsn *lsn, Dbt *data, u_int32_t _flags)
|
||||
ret = logc->get(logc, lsn, data, _flags);
|
||||
|
||||
if (!DB_RETOK_LGGET(ret)) {
|
||||
if (ret == ENOMEM && DB_OVERFLOWED_DBT(data))
|
||||
DB_ERROR_DBT("DbLogc::get", data, ON_ERROR_UNKNOWN);
|
||||
if (ret == DB_BUFFER_SMALL)
|
||||
DB_ERROR_DBT(DbEnv::get_DbEnv(logc->dbenv),
|
||||
"DbLogc::get", data, ON_ERROR_UNKNOWN);
|
||||
else
|
||||
DB_ERROR("DbLogc::get", ret, ON_ERROR_UNKNOWN);
|
||||
DB_ERROR(DbEnv::get_DbEnv(logc->dbenv),
|
||||
"DbLogc::get", ret, ON_ERROR_UNKNOWN);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2002
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: cxx_mpool.cpp,v 11.28 2004/01/28 03:35:56 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: cxx_mpool.cpp,v 11.20 2002/07/03 21:03:53 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "db_cxx.h"
|
||||
@@ -35,7 +33,8 @@ int DbMpoolFile::_name _argspec \
|
||||
else \
|
||||
ret = mpf->_name _arglist; \
|
||||
if (!_retok(ret)) \
|
||||
DB_ERROR("DbMpoolFile::"#_name, ret, ON_ERROR_UNKNOWN); \
|
||||
DB_ERROR(DbEnv::get_DbEnv(mpf->dbenv), \
|
||||
"DbMpoolFile::"#_name, ret, ON_ERROR_UNKNOWN); \
|
||||
return (ret); \
|
||||
}
|
||||
|
||||
@@ -66,6 +65,7 @@ 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;
|
||||
@@ -79,32 +79,51 @@ int DbMpoolFile::close(u_int32_t flags)
|
||||
delete this;
|
||||
|
||||
if (!DB_RETOK_STD(ret))
|
||||
DB_ERROR("DbMpoolFile::close", ret, ON_ERROR_UNKNOWN);
|
||||
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_VOID(last_pgno, (db_pgno_t *pgnoaddr), (mpf, pgnoaddr))
|
||||
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_VOID(refcnt, (db_pgno_t *pgnoaddr), (mpf, pgnoaddr))
|
||||
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_VOID(set_unlink, (int ul), (mpf, ul))
|
||||
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)
|
||||
|
||||
65
storage/bdb/cxx/cxx_multi.cpp
Normal file
65
storage/bdb/cxx/cxx_multi.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: cxx_multi.cpp,v 1.4 2004/01/28 03:35:56 bostic 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 (data.get_data() != 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 (data.get_data() != 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 (recno != 0);
|
||||
}
|
||||
113
storage/bdb/cxx/cxx_seq.cpp
Normal file
113
storage/bdb/cxx/cxx_seq.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: cxx_seq.cpp,v 11.3 2004/09/23 20:05:08 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"
|
||||
|
||||
// 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);
|
||||
}
|
||||
@@ -1,22 +1,21 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1997-2002
|
||||
* Copyright (c) 1997-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: cxx_txn.cpp,v 11.33 2004/09/22 22:20:31 mjc Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: cxx_txn.cpp,v 11.27 2002/07/20 13:50:11 dda Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#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.
|
||||
@@ -24,19 +23,20 @@ static const char revid[] = "$Id: cxx_txn.cpp,v 11.27 2002/07/20 13:50:11 dda Ex
|
||||
// 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); \
|
||||
\
|
||||
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("DbTxn::" # _name, ret, ON_ERROR_UNKNOWN); \
|
||||
return (ret); \
|
||||
#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
|
||||
@@ -46,7 +46,7 @@ DbTxn::DbTxn()
|
||||
}
|
||||
|
||||
DbTxn::DbTxn(DB_TXN *txn)
|
||||
: imp_(wrap(txn))
|
||||
: imp_(txn)
|
||||
{
|
||||
txn->api_internal = this;
|
||||
}
|
||||
@@ -75,7 +75,5 @@ DBTXN_METHOD(set_timeout, 0, (db_timeout_t timeout, u_int32_t flags),
|
||||
DbTxn *DbTxn::wrap_DB_TXN(DB_TXN *txn)
|
||||
{
|
||||
DbTxn *wrapped_txn = get_DbTxn(txn);
|
||||
if (wrapped_txn == NULL)
|
||||
wrapped_txn = new DbTxn(txn);
|
||||
return wrapped_txn;
|
||||
return (wrapped_txn != NULL) ? wrapped_txn : new DbTxn(txn);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: crdel.src,v 11.24 2002/04/17 19:02:57 krinsky Exp $
|
||||
* $Id: crdel.src,v 11.29 2004/06/17 17:35:15 bostic Exp $
|
||||
*/
|
||||
|
||||
PREFIX __crdel
|
||||
DBPRIVATE
|
||||
|
||||
INCLUDE #include "db_config.h"
|
||||
INCLUDE
|
||||
INCLUDE #ifndef NO_SYSTEM_INCLUDES
|
||||
INCLUDE #include <sys/types.h>
|
||||
INCLUDE
|
||||
@@ -25,7 +23,6 @@ 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/rep.h"
|
||||
INCLUDE #include "dbinc/txn.h"
|
||||
INCLUDE
|
||||
|
||||
@@ -39,7 +36,7 @@ INCLUDE
|
||||
*/
|
||||
BEGIN metasub 142
|
||||
DB fileid int32_t ld
|
||||
WRLOCK pgno db_pgno_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
PGDBT page DBT s
|
||||
POINTER lsn DB_LSN * lu
|
||||
END
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: crdel_rec.c,v 11.68 2004/04/29 00:07:55 ubell Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: crdel_rec.c,v 11.64 2002/08/14 20:27:34 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -19,8 +17,10 @@ static const char revid[] = "$Id: crdel_rec.c,v 11.64 2002/08/14 20:27:34 bostic
|
||||
|
||||
#include "db_int.h"
|
||||
#include "dbinc/db_page.h"
|
||||
#include "dbinc/db_shash.h"
|
||||
#include "dbinc/hash.h"
|
||||
#include "dbinc/log.h"
|
||||
#include "dbinc/mp.h"
|
||||
|
||||
/*
|
||||
* __crdel_metasub_recover --
|
||||
@@ -49,16 +49,10 @@ __crdel_metasub_recover(dbenv, dbtp, lsnp, op, info)
|
||||
REC_PRINT(__crdel_metasub_print);
|
||||
REC_INTRO(__crdel_metasub_read, 0);
|
||||
|
||||
if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
if (DB_REDO(op)) {
|
||||
if ((ret = mpf->get(mpf,
|
||||
&argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
|
||||
goto out;
|
||||
} else {
|
||||
*lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
|
||||
*lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
modified = 0;
|
||||
@@ -84,7 +78,7 @@ __crdel_metasub_recover(dbenv, dbtp, lsnp, op, info)
|
||||
LSN(pagep) = argp->lsn;
|
||||
modified = 1;
|
||||
}
|
||||
if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
|
||||
goto out;
|
||||
pagep = NULL;
|
||||
|
||||
@@ -92,6 +86,6 @@ done: *lsnp = argp->prev_lsn;
|
||||
ret = 0;
|
||||
|
||||
out: if (pagep != NULL)
|
||||
(void)mpf->put(mpf, pagep, 0);
|
||||
(void)__memp_fput(mpf, pagep, 0);
|
||||
REC_CLOSE;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,15 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db.src,v 11.18 2002/04/17 19:02:58 krinsky Exp $
|
||||
* $Id: db.src,v 11.28 2004/06/17 17:35:15 bostic Exp $
|
||||
*/
|
||||
|
||||
PREFIX __db
|
||||
DBPRIVATE
|
||||
|
||||
INCLUDE #include "db_config.h"
|
||||
INCLUDE
|
||||
INCLUDE #ifndef NO_SYSTEM_INCLUDES
|
||||
INCLUDE #include <sys/types.h>
|
||||
INCLUDE
|
||||
@@ -25,7 +23,6 @@ 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/rep.h"
|
||||
INCLUDE #include "dbinc/txn.h"
|
||||
INCLUDE
|
||||
|
||||
@@ -48,7 +45,7 @@ INCLUDE
|
||||
BEGIN addrem 41
|
||||
ARG opcode u_int32_t lu
|
||||
DB fileid int32_t ld
|
||||
WRLOCK pgno db_pgno_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
ARG indx u_int32_t lu
|
||||
ARG nbytes u_int32_t lu
|
||||
PGDBT hdr DBT s
|
||||
@@ -74,9 +71,9 @@ END
|
||||
BEGIN big 43
|
||||
ARG opcode u_int32_t lu
|
||||
DB fileid int32_t ld
|
||||
WRLOCK pgno db_pgno_t lu
|
||||
WRLOCKNZ prev_pgno db_pgno_t lu
|
||||
WRLOCKNZ next_pgno db_pgno_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
ARG prev_pgno db_pgno_t lu
|
||||
ARG next_pgno db_pgno_t lu
|
||||
DBT dbt DBT s
|
||||
POINTER pagelsn DB_LSN * lu
|
||||
POINTER prevlsn DB_LSN * lu
|
||||
@@ -93,33 +90,11 @@ END
|
||||
*/
|
||||
BEGIN ovref 44
|
||||
DB fileid int32_t ld
|
||||
WRLOCK pgno db_pgno_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
ARG adjust int32_t ld
|
||||
POINTER lsn DB_LSN * lu
|
||||
END
|
||||
|
||||
/*
|
||||
* relink -- Handles relinking around a page.
|
||||
*
|
||||
* opcode: indicates if this is an addpage or delete page
|
||||
* pgno: the page being changed.
|
||||
* lsn the page's original lsn.
|
||||
* prev: the previous page.
|
||||
* lsn_prev: the previous page's original lsn.
|
||||
* next: the next page.
|
||||
* lsn_next: the previous page's original lsn.
|
||||
*/
|
||||
BEGIN relink 45
|
||||
ARG opcode u_int32_t lu
|
||||
DB fileid int32_t ld
|
||||
WRLOCK pgno db_pgno_t lu
|
||||
POINTER lsn DB_LSN * lu
|
||||
WRLOCKNZ prev db_pgno_t lu
|
||||
POINTER lsn_prev DB_LSN * lu
|
||||
WRLOCKNZ next db_pgno_t lu
|
||||
POINTER lsn_next DB_LSN * lu
|
||||
END
|
||||
|
||||
/*
|
||||
* Debug -- log an operation upon entering an access method.
|
||||
* op: Operation (cursor, c_close, c_get, c_put, c_del,
|
||||
@@ -142,7 +117,7 @@ END
|
||||
*/
|
||||
BEGIN noop 48
|
||||
DB fileid int32_t ld
|
||||
WRLOCK pgno db_pgno_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER prevlsn DB_LSN * lu
|
||||
END
|
||||
|
||||
@@ -155,15 +130,17 @@ END
|
||||
* 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
|
||||
WRLOCK meta_pgno db_pgno_t lu
|
||||
ARG meta_pgno db_pgno_t lu
|
||||
POINTER page_lsn DB_LSN * lu
|
||||
WRLOCK pgno db_pgno_t 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
|
||||
|
||||
/*
|
||||
@@ -174,14 +151,16 @@ END
|
||||
* 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
|
||||
WRLOCK pgno db_pgno_t lu
|
||||
ARG pgno db_pgno_t lu
|
||||
POINTER meta_lsn DB_LSN * lu
|
||||
WRLOCK meta_pgno db_pgno_t 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
|
||||
|
||||
/*
|
||||
@@ -193,3 +172,67 @@ END
|
||||
*/
|
||||
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
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1998-2002
|
||||
* Copyright (c) 1998-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_am.c,v 11.120 2004/10/07 17:33:32 sue Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_am.c,v 11.96 2002/08/27 15:17:32 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -29,91 +27,16 @@ static const char revid[] = "$Id: db_am.c,v 11.96 2002/08/27 15:17:32 bostic Exp
|
||||
|
||||
static int __db_append_primary __P((DBC *, DBT *, DBT *));
|
||||
static int __db_secondary_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
|
||||
static int __db_secondary_close __P((DB *, u_int32_t));
|
||||
|
||||
#ifdef DEBUG
|
||||
static int __db_cprint_item __P((DBC *));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* __db_cursor --
|
||||
* Allocate and return a cursor.
|
||||
* __db_cursor_int --
|
||||
* Internal routine to create a cursor.
|
||||
*
|
||||
* PUBLIC: int __db_cursor __P((DB *, DB_TXN *, DBC **, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_cursor(dbp, txn, dbcp, flags)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
DBC **dbcp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
DBC *dbc;
|
||||
db_lockmode_t mode;
|
||||
u_int32_t op;
|
||||
int ret;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
PANIC_CHECK(dbenv);
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->cursor");
|
||||
|
||||
/* Validate arguments. */
|
||||
if ((ret = __db_cursorchk(dbp, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* Check for consistent transaction usage. For now, assume that
|
||||
* this cursor might be used for read operations only (in which
|
||||
* case it may not require a txn). We'll check more stringently
|
||||
* in c_del and c_put. (Note that this all means that the
|
||||
* read-op txn tests have to be a subset of the write-op ones.)
|
||||
*/
|
||||
if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)
|
||||
return (ret);
|
||||
|
||||
if ((ret = __db_icursor(dbp,
|
||||
txn, dbp->type, PGNO_INVALID, 0, DB_LOCK_INVALIDID, dbcp)) != 0)
|
||||
return (ret);
|
||||
dbc = *dbcp;
|
||||
|
||||
/*
|
||||
* If this is CDB, do all the locking in the interface, which is
|
||||
* right here.
|
||||
*/
|
||||
if (CDB_LOCKING(dbenv)) {
|
||||
op = LF_ISSET(DB_OPFLAGS_MASK);
|
||||
mode = (op == DB_WRITELOCK) ? DB_LOCK_WRITE :
|
||||
((op == DB_WRITECURSOR) ? DB_LOCK_IWRITE : DB_LOCK_READ);
|
||||
if ((ret = dbenv->lock_get(dbenv, dbc->locker, 0,
|
||||
&dbc->lock_dbt, mode, &dbc->mylock)) != 0) {
|
||||
(void)__db_c_close(dbc);
|
||||
return (ret);
|
||||
}
|
||||
if (op == DB_WRITECURSOR)
|
||||
F_SET(dbc, DBC_WRITECURSOR);
|
||||
if (op == DB_WRITELOCK)
|
||||
F_SET(dbc, DBC_WRITER);
|
||||
}
|
||||
|
||||
if (LF_ISSET(DB_DIRTY_READ) ||
|
||||
(txn != NULL && F_ISSET(txn, TXN_DIRTY_READ)))
|
||||
F_SET(dbc, DBC_DIRTY_READ);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_icursor --
|
||||
* Internal version of __db_cursor. If dbcp is
|
||||
* non-NULL it is assumed to point to an area to
|
||||
* initialize as a cursor.
|
||||
*
|
||||
* PUBLIC: int __db_icursor
|
||||
* PUBLIC: int __db_cursor_int
|
||||
* PUBLIC: __P((DB *, DB_TXN *, DBTYPE, db_pgno_t, int, u_int32_t, DBC **));
|
||||
*/
|
||||
int
|
||||
__db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
|
||||
__db_cursor_int(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
DBTYPE dbtype;
|
||||
@@ -122,7 +45,7 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
|
||||
u_int32_t lockerid;
|
||||
DBC **dbcp;
|
||||
{
|
||||
DBC *dbc, *adbc;
|
||||
DBC *dbc;
|
||||
DBC_INTERNAL *cp;
|
||||
DB_ENV *dbenv;
|
||||
int allocated, ret;
|
||||
@@ -131,6 +54,9 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
|
||||
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.
|
||||
@@ -146,7 +72,7 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
|
||||
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
|
||||
|
||||
if (dbc == NULL) {
|
||||
if ((ret = __os_calloc(dbp->dbenv, 1, sizeof(DBC), &dbc)) != 0)
|
||||
if ((ret = __os_calloc(dbenv, 1, sizeof(DBC), &dbc)) != 0)
|
||||
return (ret);
|
||||
allocated = 1;
|
||||
dbc->flags = 0;
|
||||
@@ -156,28 +82,33 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
|
||||
/* Set up locking information. */
|
||||
if (LOCKING_ON(dbenv)) {
|
||||
/*
|
||||
* If we are not threaded, then there is no need to
|
||||
* create new locker ids. We know that no one else
|
||||
* is running concurrently using this DB, so we can
|
||||
* take a peek at any cursors on the active queue.
|
||||
* 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) &&
|
||||
(adbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
|
||||
dbc->lid = adbc->lid;
|
||||
else {
|
||||
if ((ret =
|
||||
dbenv->lock_id(dbenv, &dbc->lid)) != 0)
|
||||
if (!DB_IS_THREADED(dbp)) {
|
||||
if (dbp->dbenv->env_lid == DB_LOCK_INVALIDID &&
|
||||
(ret =
|
||||
__lock_id(dbenv,&dbp->dbenv->env_lid)) != 0)
|
||||
goto err;
|
||||
dbc->lid = dbp->dbenv->env_lid;
|
||||
} else {
|
||||
if ((ret = __lock_id(dbenv, &dbc->lid)) != 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_icursor rather
|
||||
* than sdbp->cursor to create secondary update
|
||||
* cursors in c_put and c_del; these won't
|
||||
* acquire a new lock.
|
||||
* 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
|
||||
@@ -185,7 +116,7 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
|
||||
* close, all cursors in the secondary when we
|
||||
* associate.
|
||||
*/
|
||||
if (CDB_LOCKING(dbp->dbenv) &&
|
||||
if (CDB_LOCKING(dbenv) &&
|
||||
F_ISSET(dbp, DB_AM_SECONDARY))
|
||||
memcpy(dbc->lock.fileid,
|
||||
dbp->s_primary->fileid, DB_FILE_ID_LEN);
|
||||
@@ -231,9 +162,9 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
|
||||
if ((ret = __qam_c_init(dbc)) != 0)
|
||||
goto err;
|
||||
break;
|
||||
case DB_UNKNOWN:
|
||||
default:
|
||||
ret = __db_unknown_type(dbp->dbenv,
|
||||
"__db_icursor", dbtype);
|
||||
ret = __db_unknown_type(dbenv, "DB->cursor", dbtype);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -270,10 +201,8 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
|
||||
dbc->locker = lockerid;
|
||||
else
|
||||
dbc->locker = dbc->lid;
|
||||
} else {
|
||||
} else
|
||||
dbc->locker = txn->txnid;
|
||||
txn->cursors++;
|
||||
}
|
||||
|
||||
/*
|
||||
* These fields change when we are used as a secondary index, so
|
||||
@@ -283,7 +212,7 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
|
||||
* __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;
|
||||
dbc->c_get = __db_c_secondary_get_pp;
|
||||
|
||||
if (is_opd)
|
||||
F_SET(dbc, DBC_OPD);
|
||||
@@ -310,11 +239,20 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
|
||||
case DB_HASH:
|
||||
case DB_QUEUE:
|
||||
break;
|
||||
case DB_UNKNOWN:
|
||||
default:
|
||||
ret = __db_unknown_type(dbp->dbenv, "__db_icursor", dbp->type);
|
||||
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_THREAD_LOCK(dbenv, dbp->mutexp);
|
||||
TAILQ_INSERT_TAIL(&dbp->active_queue, dbc, links);
|
||||
F_SET(dbc, DBC_ACTIVE);
|
||||
@@ -324,189 +262,7 @@ __db_icursor(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
|
||||
return (0);
|
||||
|
||||
err: if (allocated)
|
||||
__os_free(dbp->dbenv, dbc);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* __db_cprint --
|
||||
* Display the cursor active and free queues.
|
||||
*
|
||||
* PUBLIC: int __db_cprint __P((DB *));
|
||||
*/
|
||||
int
|
||||
__db_cprint(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
DBC *dbc;
|
||||
int ret, t_ret;
|
||||
|
||||
ret = 0;
|
||||
MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
|
||||
fprintf(stderr, "Active queue:\n");
|
||||
for (dbc = TAILQ_FIRST(&dbp->active_queue);
|
||||
dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
|
||||
if ((t_ret = __db_cprint_item(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
fprintf(stderr, "Free queue:\n");
|
||||
for (dbc = TAILQ_FIRST(&dbp->free_queue);
|
||||
dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
|
||||
if ((t_ret = __db_cprint_item(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static
|
||||
int __db_cprint_item(dbc)
|
||||
DBC *dbc;
|
||||
{
|
||||
static const FN fn[] = {
|
||||
{ DBC_ACTIVE, "active" },
|
||||
{ DBC_COMPENSATE, "compensate" },
|
||||
{ DBC_OPD, "off-page-dup" },
|
||||
{ DBC_RECOVER, "recover" },
|
||||
{ DBC_RMW, "read-modify-write" },
|
||||
{ DBC_TRANSIENT, "transient" },
|
||||
{ DBC_WRITECURSOR, "write cursor" },
|
||||
{ DBC_WRITEDUP, "internally dup'ed write cursor" },
|
||||
{ DBC_WRITER, "short-term write cursor" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
DB *dbp;
|
||||
DBC_INTERNAL *cp;
|
||||
const char *s;
|
||||
|
||||
dbp = dbc->dbp;
|
||||
cp = dbc->internal;
|
||||
|
||||
s = __db_dbtype_to_string(dbc->dbtype);
|
||||
if (strcmp(s, "UNKNOWN TYPE") == 0) {
|
||||
DB_ASSERT(0);
|
||||
return (1);
|
||||
}
|
||||
fprintf(stderr, "%s/%#0lx: opd: %#0lx\n",
|
||||
s, P_TO_ULONG(dbc), P_TO_ULONG(cp->opd));
|
||||
|
||||
fprintf(stderr, "\ttxn: %#0lx lid: %lu locker: %lu\n",
|
||||
P_TO_ULONG(dbc->txn), (u_long)dbc->lid, (u_long)dbc->locker);
|
||||
|
||||
fprintf(stderr, "\troot: %lu page/index: %lu/%lu",
|
||||
(u_long)cp->root, (u_long)cp->pgno, (u_long)cp->indx);
|
||||
|
||||
__db_prflags(dbc->flags, fn, stderr);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
switch (dbp->type) {
|
||||
case DB_BTREE:
|
||||
__bam_cprint(dbc);
|
||||
break;
|
||||
case DB_HASH:
|
||||
__ham_cprint(dbc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* db_fd --
|
||||
* Return a file descriptor for flock'ing.
|
||||
*
|
||||
* PUBLIC: int __db_fd __P((DB *, int *));
|
||||
*/
|
||||
int
|
||||
__db_fd(dbp, fdp)
|
||||
DB *dbp;
|
||||
int *fdp;
|
||||
{
|
||||
DB_FH *fhp;
|
||||
int ret;
|
||||
|
||||
PANIC_CHECK(dbp->dbenv);
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->fd");
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Truly spectacular layering violation.
|
||||
*/
|
||||
if ((ret = __mp_xxx_fh(dbp->mpf, &fhp)) != 0)
|
||||
return (ret);
|
||||
|
||||
if (F_ISSET(fhp, DB_FH_VALID)) {
|
||||
*fdp = fhp->fd;
|
||||
return (0);
|
||||
} else {
|
||||
*fdp = -1;
|
||||
__db_err(dbp->dbenv, "DB does not have a valid file handle");
|
||||
return (ENOENT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_get --
|
||||
* Return a key/data pair.
|
||||
*
|
||||
* PUBLIC: int __db_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_get(dbp, txn, key, data, flags)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
DBT *key, *data;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DBC *dbc;
|
||||
int mode, ret, t_ret;
|
||||
|
||||
PANIC_CHECK(dbp->dbenv);
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get");
|
||||
|
||||
if ((ret = __db_getchk(dbp, key, data, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Check for consistent transaction usage. */
|
||||
if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)
|
||||
return (ret);
|
||||
|
||||
mode = 0;
|
||||
if (LF_ISSET(DB_DIRTY_READ)) {
|
||||
mode = DB_DIRTY_READ;
|
||||
LF_CLR(DB_DIRTY_READ);
|
||||
}
|
||||
else if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT)
|
||||
mode = DB_WRITELOCK;
|
||||
if ((ret = dbp->cursor(dbp, txn, &dbc, mode)) != 0)
|
||||
return (ret);
|
||||
|
||||
DEBUG_LREAD(dbc, txn, "__db_get", key, NULL, flags);
|
||||
|
||||
/*
|
||||
* The DBC_TRANSIENT flag indicates that we're just doing a
|
||||
* single operation with this cursor, and that in case of
|
||||
* error we don't need to restore it to its old position--we're
|
||||
* going to close it right away. Thus, we can perform the get
|
||||
* without duplicating the cursor, saving some cycles in this
|
||||
* common case.
|
||||
*
|
||||
* SET_RET_MEM indicates that if key and/or data have no DBT
|
||||
* flags set and DB manages the returned-data memory, that memory
|
||||
* will belong to this handle, not to the underlying cursor.
|
||||
*/
|
||||
F_SET(dbc, DBC_TRANSIENT);
|
||||
SET_RET_MEM(dbc, dbp);
|
||||
|
||||
if (LF_ISSET(~(DB_RMW | DB_MULTIPLE)) == 0)
|
||||
LF_SET(DB_SET);
|
||||
ret = dbc->c_get(dbc, key, data, flags);
|
||||
|
||||
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
__os_free(dbenv, dbc);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -526,36 +282,14 @@ __db_put(dbp, txn, key, data, flags)
|
||||
DBC *dbc;
|
||||
DBT tdata;
|
||||
DB_ENV *dbenv;
|
||||
int ret, t_ret, txn_local;
|
||||
int ret, t_ret;
|
||||
|
||||
dbc = NULL;
|
||||
dbenv = dbp->dbenv;
|
||||
txn_local = 0;
|
||||
|
||||
PANIC_CHECK(dbenv);
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->put");
|
||||
|
||||
/* Validate arguments. */
|
||||
if ((ret = __db_putchk(dbp, key, data,
|
||||
flags, F_ISSET(dbp, DB_AM_DUP) || F_ISSET(key, DB_DBT_DUPOK))) != 0)
|
||||
if ((ret = __db_cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Create local transaction as necessary. */
|
||||
if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
|
||||
if ((ret = __db_txn_auto(dbp, &txn)) != 0)
|
||||
return (ret);
|
||||
txn_local = 1;
|
||||
LF_CLR(DB_AUTO_COMMIT);
|
||||
}
|
||||
|
||||
/* Check for consistent transaction usage. */
|
||||
if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
|
||||
goto err;
|
||||
|
||||
if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
|
||||
goto err;
|
||||
|
||||
DEBUG_LWRITE(dbc, txn, "db_put", key, data, flags);
|
||||
DEBUG_LWRITE(dbc, txn, "DB->put", key, data, flags);
|
||||
|
||||
SET_RET_MEM(dbc, dbp);
|
||||
|
||||
@@ -594,10 +328,15 @@ __db_put(dbp, txn, key, data, flags)
|
||||
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(0);
|
||||
ret = __db_ferr(dbenv, "__db_put", flags);
|
||||
DB_ASSERT(
|
||||
dbp->type == DB_QUEUE || dbp->type == DB_RECNO);
|
||||
|
||||
ret = __db_ferr(dbenv, "DB->put", 0);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -621,7 +360,7 @@ __db_put(dbp, txn, key, data, flags)
|
||||
FREE_IF_NEEDED(dbp, &tdata);
|
||||
|
||||
/* No need for a cursor put; we're done. */
|
||||
goto err;
|
||||
goto done;
|
||||
case DB_NOOVERWRITE:
|
||||
flags = 0;
|
||||
/*
|
||||
@@ -636,7 +375,7 @@ __db_put(dbp, txn, key, data, flags)
|
||||
* If we're doing page-level locking, set the read-modify-write
|
||||
* flag, we're going to overwrite immediately.
|
||||
*/
|
||||
if ((ret = dbc->c_get(dbc, key, &tdata,
|
||||
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)
|
||||
@@ -646,34 +385,27 @@ __db_put(dbp, txn, key, data, flags)
|
||||
/* Fall through to normal cursor put. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
ret = dbc->c_put(dbc,
|
||||
ret = __db_c_put(dbc,
|
||||
key, data, flags == 0 ? DB_KEYLAST : flags);
|
||||
|
||||
err: /* Close the cursor. */
|
||||
if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
|
||||
err:
|
||||
done: /* Close the cursor. */
|
||||
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/* Commit for DB_AUTO_COMMIT. */
|
||||
if (txn_local) {
|
||||
if (ret == 0)
|
||||
ret = txn->commit(txn, 0);
|
||||
else
|
||||
if ((t_ret = txn->abort(txn)) != 0)
|
||||
ret = __db_panic(dbenv, t_ret);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_delete --
|
||||
* __db_del --
|
||||
* Delete the items referenced by a key.
|
||||
*
|
||||
* PUBLIC: int __db_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
|
||||
* PUBLIC: int __db_del __P((DB *, DB_TXN *, DBT *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_delete(dbp, txn, key, flags)
|
||||
__db_del(dbp, txn, key, flags)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
DBT *key;
|
||||
@@ -681,38 +413,15 @@ __db_delete(dbp, txn, key, flags)
|
||||
{
|
||||
DBC *dbc;
|
||||
DBT data, lkey;
|
||||
DB_ENV *dbenv;
|
||||
u_int32_t f_init, f_next;
|
||||
int ret, t_ret, txn_local;
|
||||
|
||||
dbc = NULL;
|
||||
dbenv = dbp->dbenv;
|
||||
txn_local = 0;
|
||||
|
||||
PANIC_CHECK(dbenv);
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->del");
|
||||
|
||||
/* Check for invalid flags. */
|
||||
if ((ret = __db_delchk(dbp, key, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Create local transaction as necessary. */
|
||||
if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
|
||||
if ((ret = __db_txn_auto(dbp, &txn)) != 0)
|
||||
return (ret);
|
||||
txn_local = 1;
|
||||
LF_CLR(DB_AUTO_COMMIT);
|
||||
}
|
||||
|
||||
/* Check for consistent transaction usage. */
|
||||
if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
|
||||
goto err;
|
||||
int ret, t_ret;
|
||||
|
||||
/* Allocate a cursor. */
|
||||
if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
|
||||
if ((ret = __db_cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
|
||||
goto err;
|
||||
|
||||
DEBUG_LWRITE(dbc, txn, "db_delete", key, NULL, flags);
|
||||
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
|
||||
@@ -737,7 +446,7 @@ __db_delete(dbp, txn, key, flags)
|
||||
}
|
||||
|
||||
/* Walk through the set of key/data pairs, deleting as we go. */
|
||||
if ((ret = dbc->c_get(dbc, key, &data, f_init)) != 0)
|
||||
if ((ret = __db_c_get(dbc, key, &data, f_init)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
@@ -760,40 +469,29 @@ __db_delete(dbp, txn, key, flags)
|
||||
* The ordinary AM-independent alternative will work just fine with
|
||||
* a hash; it'll just be slower.
|
||||
*/
|
||||
if (dbp->type == DB_HASH) {
|
||||
if (dbp->type == DB_HASH)
|
||||
if (LIST_FIRST(&dbp->s_secondaries) == NULL &&
|
||||
!F_ISSET(dbp, DB_AM_SECONDARY) &&
|
||||
dbc->internal->opd == NULL) {
|
||||
ret = __ham_quick_delete(dbc);
|
||||
goto err;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if ((ret = dbc->c_del(dbc, 0)) != 0)
|
||||
goto err;
|
||||
if ((ret = dbc->c_get(dbc, &lkey, &data, f_next)) != 0) {
|
||||
if (ret == DB_NOTFOUND) {
|
||||
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;
|
||||
}
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
err: /* Discard the cursor. */
|
||||
if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
|
||||
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/* Commit for DB_AUTO_COMMIT. */
|
||||
if (txn_local) {
|
||||
if (ret == 0)
|
||||
ret = txn->commit(txn, 0);
|
||||
else
|
||||
if ((t_ret = txn->abort(txn)) != 0)
|
||||
ret = __db_panic(dbenv, t_ret);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -801,22 +499,17 @@ err: /* Discard the cursor. */
|
||||
* __db_sync --
|
||||
* Flush the database cache.
|
||||
*
|
||||
* PUBLIC: int __db_sync __P((DB *, u_int32_t));
|
||||
* PUBLIC: int __db_sync __P((DB *));
|
||||
*/
|
||||
int
|
||||
__db_sync(dbp, flags)
|
||||
__db_sync(dbp)
|
||||
DB *dbp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
int ret, t_ret;
|
||||
|
||||
PANIC_CHECK(dbp->dbenv);
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->sync");
|
||||
ret = 0;
|
||||
|
||||
if ((ret = __db_syncchk(dbp, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Read-only trees never need to be sync'd. */
|
||||
/* If the database was read-only, we're done. */
|
||||
if (F_ISSET(dbp, DB_AM_RDONLY))
|
||||
return (0);
|
||||
|
||||
@@ -824,13 +517,17 @@ __db_sync(dbp, flags)
|
||||
if (dbp->type == DB_RECNO)
|
||||
ret = __ram_writeback(dbp);
|
||||
|
||||
/* If the tree was never backed by a database file, we're done. */
|
||||
/* If the database was never backed by a database file, we're done. */
|
||||
if (F_ISSET(dbp, DB_AM_INMEM))
|
||||
return (0);
|
||||
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;
|
||||
|
||||
/* Flush any dirty pages from the cache to the backing file. */
|
||||
if ((t_ret = dbp->mpf->sync(dbp->mpf)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -851,40 +548,11 @@ __db_associate(dbp, txn, sdbp, callback, flags)
|
||||
DB_ENV *dbenv;
|
||||
DBC *pdbc, *sdbc;
|
||||
DBT skey, key, data;
|
||||
int build, ret, t_ret, txn_local;
|
||||
int build, ret, t_ret;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
PANIC_CHECK(dbenv);
|
||||
|
||||
txn_local = 0;
|
||||
pdbc = NULL;
|
||||
|
||||
memset(&key, 0, sizeof(DBT));
|
||||
memset(&data, 0, sizeof(DBT));
|
||||
memset(&skey, 0, sizeof(DBT));
|
||||
|
||||
if ((ret = __db_associatechk(dbp, sdbp, callback, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* Create a local transaction as necessary, check for consistent
|
||||
* transaction usage, and, if we have no transaction but do have
|
||||
* locking on, acquire a locker id for the handle lock acquisition.
|
||||
*/
|
||||
if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
|
||||
if ((ret = __db_txn_auto(dbp, &txn)) != 0)
|
||||
return (ret);
|
||||
txn_local = 1;
|
||||
} else if (txn != NULL && !TXN_ON(dbenv))
|
||||
return (__db_not_txn_env(dbenv));
|
||||
|
||||
/*
|
||||
* Check that if an open transaction is in progress, we're in it,
|
||||
* for other common transaction errors, and for concurrent associates.
|
||||
*/
|
||||
if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
|
||||
return (ret);
|
||||
pdbc = sdbc = NULL;
|
||||
ret = 0;
|
||||
|
||||
sdbp->s_callback = callback;
|
||||
sdbp->s_primary = dbp;
|
||||
@@ -893,23 +561,7 @@ __db_associate(dbp, txn, sdbp, callback, flags)
|
||||
sdbp->get = __db_secondary_get;
|
||||
|
||||
sdbp->stored_close = sdbp->close;
|
||||
sdbp->close = __db_secondary_close;
|
||||
|
||||
/*
|
||||
* Secondary cursors may have the primary's lock file ID, so we
|
||||
* need to make sure that no older cursors are lying around
|
||||
* when we make the transition.
|
||||
*/
|
||||
if (TAILQ_FIRST(&sdbp->active_queue) != NULL ||
|
||||
TAILQ_FIRST(&sdbp->join_queue) != NULL) {
|
||||
__db_err(dbenv,
|
||||
"Databases may not become secondary indices while cursors are open");
|
||||
ret = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
while ((sdbc = TAILQ_FIRST(&sdbp->free_queue)) != NULL)
|
||||
if ((ret = __db_c_destroy(sdbc)) != 0)
|
||||
goto err;
|
||||
sdbp->close = __db_secondary_close_pp;
|
||||
|
||||
F_SET(sdbp, DB_AM_SECONDARY);
|
||||
|
||||
@@ -920,19 +572,18 @@ __db_associate(dbp, txn, sdbp, callback, flags)
|
||||
*/
|
||||
build = 0;
|
||||
if (LF_ISSET(DB_CREATE)) {
|
||||
if ((ret = sdbp->cursor(sdbp, txn, &sdbc, 0)) != 0)
|
||||
if ((ret = __db_cursor(sdbp, txn, &sdbc, 0)) != 0)
|
||||
goto err;
|
||||
|
||||
memset(&key, 0, sizeof(DBT));
|
||||
memset(&data, 0, sizeof(DBT));
|
||||
|
||||
/*
|
||||
* 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 = sdbc->c_real_get(sdbc, &key, &data,
|
||||
if ((ret = __db_c_get(sdbc, &key, &data,
|
||||
(STD_LOCKING(sdbc) ? DB_RMW : 0) |
|
||||
DB_FIRST)) == DB_NOTFOUND) {
|
||||
build = 1;
|
||||
@@ -943,8 +594,12 @@ __db_associate(dbp, txn, sdbp, callback, flags)
|
||||
* Secondary cursors have special refcounting close
|
||||
* methods. Be careful.
|
||||
*/
|
||||
if ((t_ret = __db_c_close(sdbc)) != 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;
|
||||
}
|
||||
@@ -976,10 +631,10 @@ __db_associate(dbp, txn, sdbp, callback, flags)
|
||||
* as the secondary, so they won't conflict. This should
|
||||
* be harmless even if we're not using CDB.
|
||||
*/
|
||||
if ((ret = sdbp->cursor(sdbp, txn, &sdbc,
|
||||
if ((ret = __db_cursor(sdbp, txn, &sdbc,
|
||||
CDB_LOCKING(sdbp->dbenv) ? DB_WRITECURSOR : 0)) != 0)
|
||||
goto err;
|
||||
if ((ret = __db_icursor(dbp,
|
||||
if ((ret = __db_cursor_int(dbp,
|
||||
txn, dbp->type, PGNO_INVALID, 0, sdbc->locker, &pdbc)) != 0)
|
||||
goto err;
|
||||
|
||||
@@ -988,15 +643,14 @@ __db_associate(dbp, txn, sdbp, callback, flags)
|
||||
|
||||
memset(&key, 0, sizeof(DBT));
|
||||
memset(&data, 0, sizeof(DBT));
|
||||
while ((ret = pdbc->c_get(pdbc, &key, &data, DB_NEXT)) == 0) {
|
||||
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;
|
||||
else
|
||||
goto err;
|
||||
goto err;
|
||||
}
|
||||
if ((ret = sdbc->c_put(sdbc,
|
||||
if ((ret = __db_c_put(sdbc,
|
||||
&skey, &key, DB_UPDATE_SECONDARY)) != 0) {
|
||||
FREE_IF_NEEDED(sdbp, &skey);
|
||||
goto err;
|
||||
@@ -1006,79 +660,16 @@ __db_associate(dbp, txn, sdbp, callback, flags)
|
||||
}
|
||||
if (ret == DB_NOTFOUND)
|
||||
ret = 0;
|
||||
|
||||
if ((ret = sdbc->c_close(sdbc)) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
err: if (pdbc != NULL && (t_ret = pdbc->c_close(pdbc)) != 0 && 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;
|
||||
|
||||
if (txn_local) {
|
||||
if (ret == 0)
|
||||
ret = txn->commit(txn, 0);
|
||||
else
|
||||
if ((t_ret = txn->abort(txn)) != 0)
|
||||
ret = __db_panic(dbenv, t_ret);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_pget --
|
||||
* Return a primary key/data pair given a secondary key.
|
||||
*
|
||||
* PUBLIC: int __db_pget __P((DB *, DB_TXN *, DBT *, DBT *, DBT *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_pget(dbp, txn, skey, pkey, data, flags)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
DBT *skey, *pkey, *data;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DBC *dbc;
|
||||
int ret, t_ret;
|
||||
|
||||
PANIC_CHECK(dbp->dbenv);
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->pget");
|
||||
|
||||
if ((ret = __db_pgetchk(dbp, skey, pkey, data, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
|
||||
return (ret);
|
||||
SET_RET_MEM(dbc, dbp);
|
||||
|
||||
/*
|
||||
* The underlying cursor pget will fill in a default DBT for null
|
||||
* pkeys, and use the cursor's returned-key memory internally to
|
||||
* store any intermediate primary keys. However, we've just set
|
||||
* the returned-key memory to the DB handle's key memory, which
|
||||
* is unsafe to use if the DB handle is threaded. If the pkey
|
||||
* argument is NULL, use the DBC-owned returned-key memory
|
||||
* instead; it'll go away when we close the cursor before we
|
||||
* return, but in this case that's just fine, as we're not
|
||||
* returning the primary key.
|
||||
*/
|
||||
if (pkey == NULL)
|
||||
dbc->rkey = &dbc->my_rkey;
|
||||
|
||||
DEBUG_LREAD(dbc, txn, "__db_pget", skey, NULL, flags);
|
||||
|
||||
/*
|
||||
* The cursor is just a perfectly ordinary secondary database
|
||||
* cursor. Call its c_pget() method to do the dirty work.
|
||||
*/
|
||||
if (flags == 0 || flags == DB_RMW)
|
||||
flags |= DB_SET;
|
||||
ret = dbc->c_pget(dbc, skey, pkey, data, flags);
|
||||
|
||||
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -1096,7 +687,7 @@ __db_secondary_get(sdbp, txn, skey, data, flags)
|
||||
{
|
||||
|
||||
DB_ASSERT(F_ISSET(sdbp, DB_AM_SECONDARY));
|
||||
return (sdbp->pget(sdbp, txn, skey, NULL, data, flags));
|
||||
return (__db_pget_pp(sdbp, txn, skey, NULL, data, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1104,8 +695,10 @@ __db_secondary_get(sdbp, txn, skey, data, flags)
|
||||
* 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));
|
||||
*/
|
||||
static int
|
||||
int
|
||||
__db_secondary_close(sdbp, flags)
|
||||
DB *sdbp;
|
||||
u_int32_t flags;
|
||||
@@ -1138,7 +731,7 @@ __db_secondary_close(sdbp, flags)
|
||||
* sdbp->close is this function; call the real one explicitly if
|
||||
* need be.
|
||||
*/
|
||||
return (doclose ? __db_close(sdbp, flags) : 0);
|
||||
return (doclose ? __db_close(sdbp, NULL, flags) : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1179,12 +772,12 @@ __db_append_primary(dbc, key, data)
|
||||
* correctly-constructed full data item from this partial
|
||||
* put is on the page waiting for us.
|
||||
*/
|
||||
if ((ret = __db_c_idup(dbc, &pdbc, DB_POSITIONI)) != 0)
|
||||
if ((ret = __db_c_idup(dbc, &pdbc, DB_POSITION)) != 0)
|
||||
return (ret);
|
||||
memset(&pkey, 0, sizeof(DBT));
|
||||
memset(&pdata, 0, sizeof(DBT));
|
||||
|
||||
if ((ret = pdbc->c_get(pdbc, &pkey, &pdata, DB_CURRENT)) != 0)
|
||||
if ((ret = __db_c_get(pdbc, &pkey, &pdata, DB_CURRENT)) != 0)
|
||||
goto err;
|
||||
|
||||
key = &pkey;
|
||||
@@ -1210,7 +803,7 @@ __db_append_primary(dbc, key, data)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((ret = __db_icursor(sdbp, dbc->txn, sdbp->type,
|
||||
if ((ret = __db_cursor_int(sdbp, dbc->txn, sdbp->type,
|
||||
PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0) {
|
||||
FREE_IF_NEEDED(sdbp, &skey);
|
||||
goto err;
|
||||
@@ -1230,7 +823,7 @@ __db_append_primary(dbc, key, data)
|
||||
if (!F_ISSET(sdbp, DB_AM_DUP)) {
|
||||
memset(&oldpkey, 0, sizeof(DBT));
|
||||
F_SET(&oldpkey, DB_DBT_MALLOC);
|
||||
ret = sdbc->c_real_get(sdbc, &skey, &oldpkey,
|
||||
ret = __db_c_get(sdbc, &skey, &oldpkey,
|
||||
DB_SET | (STD_LOCKING(dbc) ? DB_RMW : 0));
|
||||
if (ret == 0) {
|
||||
cmp = __bam_defcmp(sdbp, &oldpkey, key);
|
||||
@@ -1252,18 +845,18 @@ __db_append_primary(dbc, key, data)
|
||||
goto err1;
|
||||
}
|
||||
|
||||
ret = sdbc->c_put(sdbc, &skey, key, DB_UPDATE_SECONDARY);
|
||||
ret = __db_c_put(sdbc, &skey, key, DB_UPDATE_SECONDARY);
|
||||
|
||||
err1: FREE_IF_NEEDED(sdbp, &skey);
|
||||
|
||||
if ((t_ret = sdbc->c_close(sdbc)) != 0 && ret == 0)
|
||||
if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
err: if (pdbc != NULL && (t_ret = pdbc->c_close(pdbc)) != 0 && ret == 0)
|
||||
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;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -35,14 +35,12 @@
|
||||
* 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 11.45 2004/01/28 03:35:57 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_conv.c,v 11.38 2002/08/15 03:00:13 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -100,6 +98,8 @@ __db_pgin(dbenv, pg, pp, cookie)
|
||||
*/
|
||||
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;
|
||||
@@ -139,22 +139,25 @@ __db_pgin(dbenv, pg, pp, cookie)
|
||||
* 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_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))
|
||||
__db_cksum_log(
|
||||
(void)__db_cksum_log(
|
||||
dbenv, NULL, ¬_used, DB_FLUSH);
|
||||
__db_err(dbenv,
|
||||
"checksum error: catastrophic recovery required");
|
||||
"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));
|
||||
@@ -330,6 +333,8 @@ __db_pgout(dbenv, pg, pp, cookie)
|
||||
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);
|
||||
}
|
||||
@@ -436,6 +441,8 @@ __db_byteswap(dbenv, dbp, pg, h, pagesize, pgin)
|
||||
SWAP32(p); /* pgno */
|
||||
SWAP32(p); /* tlen */
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbenv, pg));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -484,6 +491,8 @@ __db_byteswap(dbenv, dbp, pg, h, pagesize, pgin)
|
||||
M_32_SWAP(bo->pgno);
|
||||
M_32_SWAP(bo->tlen);
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbenv, pg));
|
||||
}
|
||||
|
||||
if (!pgin)
|
||||
@@ -509,6 +518,8 @@ __db_byteswap(dbenv, dbp, pg, h, pagesize, pgin)
|
||||
M_32_SWAP(bo->pgno);
|
||||
M_32_SWAP(bo->tlen);
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbenv, pg));
|
||||
}
|
||||
|
||||
if (!pgin)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_dup.c,v 11.39 2004/02/18 21:34:37 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_dup.c,v 11.32 2002/08/08 03:57:47 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -20,7 +18,7 @@ static const char revid[] = "$Id: db_dup.c,v 11.32 2002/08/08 03:57:47 bostic Ex
|
||||
#include "db_int.h"
|
||||
#include "dbinc/db_page.h"
|
||||
#include "dbinc/db_shash.h"
|
||||
#include "dbinc/lock.h"
|
||||
#include "dbinc/mp.h"
|
||||
#include "dbinc/db_am.h"
|
||||
|
||||
/*
|
||||
@@ -164,118 +162,3 @@ __db_pitem(dbc, pagep, indx, nbytes, hdr, data)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_relink --
|
||||
* Relink around a deleted page.
|
||||
*
|
||||
* PUBLIC: int __db_relink __P((DBC *, u_int32_t, PAGE *, PAGE **, int));
|
||||
*/
|
||||
int
|
||||
__db_relink(dbc, add_rem, pagep, new_next, needlock)
|
||||
DBC *dbc;
|
||||
u_int32_t add_rem;
|
||||
PAGE *pagep, **new_next;
|
||||
int needlock;
|
||||
{
|
||||
DB *dbp;
|
||||
PAGE *np, *pp;
|
||||
DB_LOCK npl, ppl;
|
||||
DB_LSN *nlsnp, *plsnp, ret_lsn;
|
||||
DB_MPOOLFILE *mpf;
|
||||
int 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 (needlock && (ret = __db_lget(dbc,
|
||||
0, pagep->next_pgno, DB_LOCK_WRITE, 0, &npl)) != 0)
|
||||
goto err;
|
||||
if ((ret = mpf->get(mpf, &pagep->next_pgno, 0, &np)) != 0) {
|
||||
__db_pgerr(dbp, pagep->next_pgno, ret);
|
||||
goto err;
|
||||
}
|
||||
nlsnp = &np->lsn;
|
||||
}
|
||||
if (add_rem == DB_REM_PAGE && pagep->prev_pgno != PGNO_INVALID) {
|
||||
if (needlock && (ret = __db_lget(dbc,
|
||||
0, pagep->prev_pgno, DB_LOCK_WRITE, 0, &ppl)) != 0)
|
||||
goto err;
|
||||
if ((ret = mpf->get(mpf, &pagep->prev_pgno, 0, &pp)) != 0) {
|
||||
__db_pgerr(dbp, pagep->next_pgno, ret);
|
||||
goto err;
|
||||
}
|
||||
plsnp = &pp->lsn;
|
||||
}
|
||||
|
||||
/* Log the change. */
|
||||
if (DBC_LOGGING(dbc)) {
|
||||
if ((ret = __db_relink_log(dbp, dbc->txn, &ret_lsn, 0, add_rem,
|
||||
pagep->pgno, &pagep->lsn, 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;
|
||||
if (add_rem == DB_REM_PAGE)
|
||||
pagep->lsn = ret_lsn;
|
||||
|
||||
/*
|
||||
* Modify and release the two pages.
|
||||
*
|
||||
* !!!
|
||||
* The parameter new_next gets set to the page following the page we
|
||||
* are removing. If there is no following page, then new_next gets
|
||||
* set to NULL.
|
||||
*/
|
||||
if (np != NULL) {
|
||||
if (add_rem == DB_ADD_PAGE)
|
||||
np->prev_pgno = pagep->pgno;
|
||||
else
|
||||
np->prev_pgno = pagep->prev_pgno;
|
||||
if (new_next == NULL)
|
||||
ret = mpf->put(mpf, np, DB_MPOOL_DIRTY);
|
||||
else {
|
||||
*new_next = np;
|
||||
ret = mpf->set(mpf, np, DB_MPOOL_DIRTY);
|
||||
}
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
if (needlock)
|
||||
(void)__TLPUT(dbc, npl);
|
||||
} else if (new_next != NULL)
|
||||
*new_next = NULL;
|
||||
|
||||
if (pp != NULL) {
|
||||
pp->next_pgno = pagep->next_pgno;
|
||||
if ((ret = mpf->put(mpf, pp, DB_MPOOL_DIRTY)) != 0)
|
||||
goto err;
|
||||
if (needlock)
|
||||
(void)__TLPUT(dbc, ppl);
|
||||
}
|
||||
return (0);
|
||||
|
||||
err: if (np != NULL)
|
||||
(void)mpf->put(mpf, np, 0);
|
||||
if (needlock)
|
||||
(void)__TLPUT(dbc, npl);
|
||||
if (pp != NULL)
|
||||
(void)mpf->put(mpf, pp, 0);
|
||||
if (needlock)
|
||||
(void)__TLPUT(dbc, ppl);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,14 @@
|
||||
/*
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1998-2002
|
||||
* Copyright (c) 1998-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_join.c,v 11.75 2004/09/22 03:30:23 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_join.c,v 11.55 2002/08/08 03:57:47 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -23,10 +21,11 @@ static const char revid[] = "$Id: db_join.c,v 11.55 2002/08/08 03:57:47 bostic E
|
||||
#include "dbinc/db_join.h"
|
||||
#include "dbinc/btree.h"
|
||||
|
||||
static int __db_join_close __P((DBC *));
|
||||
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));
|
||||
@@ -67,7 +66,7 @@ static int __db_join_put __P((DBC *, DBT *, DBT *, u_int32_t));
|
||||
* cursor method of a DB, join cursors are created through an explicit
|
||||
* call to DB->join.
|
||||
*
|
||||
* The curslist is an array of existing, intialized cursors and primary
|
||||
* 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
|
||||
@@ -84,26 +83,18 @@ __db_join(primary, curslist, dbcp, flags)
|
||||
DB_ENV *dbenv;
|
||||
DBC *dbc;
|
||||
JOIN_CURSOR *jc;
|
||||
int ret;
|
||||
u_int32_t i;
|
||||
size_t ncurs, nslots;
|
||||
u_int32_t i;
|
||||
int ret;
|
||||
|
||||
COMPQUIET(nslots, 0);
|
||||
|
||||
PANIC_CHECK(primary->dbenv);
|
||||
|
||||
if ((ret = __db_joinchk(primary, curslist, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
dbenv = primary->dbenv;
|
||||
dbc = NULL;
|
||||
jc = NULL;
|
||||
dbenv = primary->dbenv;
|
||||
|
||||
if ((ret = __os_calloc(dbenv, 1, sizeof(DBC), &dbc)) != 0)
|
||||
goto err;
|
||||
|
||||
if ((ret = __os_calloc(dbenv,
|
||||
1, sizeof(JOIN_CURSOR), &jc)) != 0)
|
||||
if ((ret = __os_calloc(dbenv, 1, sizeof(JOIN_CURSOR), &jc)) != 0)
|
||||
goto err;
|
||||
|
||||
if ((ret = __os_malloc(dbenv, 256, &jc->j_key.data)) != 0)
|
||||
@@ -122,7 +113,7 @@ __db_join(primary, curslist, dbcp, flags)
|
||||
* the number of cursors involved in the join, because the
|
||||
* list is NULL-terminated.
|
||||
*/
|
||||
ncurs = jc->j_curslist - curslist;
|
||||
ncurs = (size_t)(jc->j_curslist - curslist);
|
||||
nslots = ncurs + 1;
|
||||
|
||||
/*
|
||||
@@ -208,18 +199,21 @@ __db_join(primary, curslist, dbcp, flags)
|
||||
* because this is the last thing that can fail. Modifier of this
|
||||
* function beware!
|
||||
*/
|
||||
if ((ret = jc->j_curslist[0]->c_dup(jc->j_curslist[0], jc->j_workcurs,
|
||||
DB_POSITIONI)) != 0)
|
||||
if ((ret =
|
||||
__db_c_dup(jc->j_curslist[0], jc->j_workcurs, DB_POSITION)) != 0)
|
||||
goto err;
|
||||
|
||||
dbc->c_close = __db_join_close;
|
||||
dbc->c_close = __db_join_close_pp;
|
||||
dbc->c_del = __db_join_del;
|
||||
dbc->c_get = __db_join_get;
|
||||
dbc->c_get = __db_join_get_pp;
|
||||
dbc->c_put = __db_join_put;
|
||||
dbc->internal = (DBC_INTERNAL *) jc;
|
||||
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_THREAD_LOCK(dbenv, primary->mutexp);
|
||||
@@ -233,7 +227,7 @@ err: if (jc != NULL) {
|
||||
__os_free(dbenv, jc->j_curslist);
|
||||
if (jc->j_workcurs != NULL) {
|
||||
if (jc->j_workcurs[0] != NULL)
|
||||
__os_free(dbenv, jc->j_workcurs[0]);
|
||||
(void)__db_c_close(jc->j_workcurs[0]);
|
||||
__os_free(dbenv, jc->j_workcurs);
|
||||
}
|
||||
if (jc->j_fdupcurs != NULL)
|
||||
@@ -247,6 +241,36 @@ err: if (jc != NULL) {
|
||||
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 *dbp;
|
||||
int handle_check, ret;
|
||||
|
||||
dbp = dbc->dbp;
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
PANIC_CHECK(dbenv);
|
||||
|
||||
handle_check = IS_REPLICATED(dbenv, dbp);
|
||||
if (handle_check &&
|
||||
(ret = __db_rep_enter(dbp, 0, 0, dbc->txn != NULL)) != 0)
|
||||
return (ret);
|
||||
|
||||
ret = __db_join_close(dbc);
|
||||
|
||||
if (handle_check)
|
||||
__env_db_rep_exit(dbenv);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
__db_join_put(dbc, key, data, flags)
|
||||
DBC *dbc;
|
||||
@@ -273,6 +297,77 @@ __db_join_del(dbc, flags)
|
||||
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;
|
||||
u_int32_t handle_check, save_flags;
|
||||
int ret;
|
||||
|
||||
dbp = dbc->dbp;
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
/* Save the original flags value. */
|
||||
save_flags = flags;
|
||||
|
||||
PANIC_CHECK(dbenv);
|
||||
|
||||
if (LF_ISSET(DB_DIRTY_READ | DB_DEGREE_2 | DB_RMW)) {
|
||||
if (!LOCKING_ON(dbp->dbenv))
|
||||
return (__db_fnl(dbp->dbenv, "DBcursor->c_get"));
|
||||
|
||||
LF_CLR(DB_DIRTY_READ | DB_DEGREE_2 | 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);
|
||||
}
|
||||
|
||||
handle_check = IS_REPLICATED(dbp->dbenv, dbp);
|
||||
if (handle_check &&
|
||||
(ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Restore the original flags value. */
|
||||
flags = save_flags;
|
||||
|
||||
ret = __db_join_get(dbc, key, data, flags);
|
||||
|
||||
if (handle_check)
|
||||
__env_db_rep_exit(dbenv);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
__db_join_get(dbc, key_arg, data_arg, flags)
|
||||
DBC *dbc;
|
||||
@@ -289,18 +384,13 @@ __db_join_get(dbc, key_arg, data_arg, flags)
|
||||
dbp = dbc->dbp;
|
||||
jc = (JOIN_CURSOR *)dbc->internal;
|
||||
|
||||
PANIC_CHECK(dbp->dbenv);
|
||||
|
||||
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_RMW | DB_DIRTY_READ);
|
||||
|
||||
if ((ret = __db_joingetchk(dbp, key_arg, flags)) != 0)
|
||||
return (ret);
|
||||
opmods = LF_ISSET(DB_RMW | DB_DEGREE_2 | DB_DIRTY_READ);
|
||||
|
||||
/*
|
||||
* Since we are fetching the key as a datum in the secondary indices,
|
||||
@@ -329,11 +419,10 @@ __db_join_get(dbc, key_arg, data_arg, flags)
|
||||
goto samekey;
|
||||
F_CLR(jc, JOIN_RETRY);
|
||||
|
||||
retry: ret = jc->j_workcurs[0]->c_real_get(jc->j_workcurs[0],
|
||||
&jc->j_key, key_n,
|
||||
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 == ENOMEM) {
|
||||
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)
|
||||
@@ -358,7 +447,7 @@ retry: ret = jc->j_workcurs[0]->c_real_get(jc->j_workcurs[0],
|
||||
*/
|
||||
for (i = 1; i < jc->j_ncurs; i++) {
|
||||
if (jc->j_fdupcurs[i] != NULL &&
|
||||
(ret = jc->j_fdupcurs[i]->c_close(jc->j_fdupcurs[i])) != 0)
|
||||
(ret = __db_c_close(jc->j_fdupcurs[i])) != 0)
|
||||
goto err;
|
||||
jc->j_fdupcurs[i] = NULL;
|
||||
}
|
||||
@@ -382,9 +471,8 @@ retry: ret = jc->j_workcurs[0]->c_real_get(jc->j_workcurs[0],
|
||||
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 = jc->j_curslist[i]->c_dup(
|
||||
jc->j_curslist[i], jc->j_workcurs + i,
|
||||
DB_POSITIONI)) != 0)
|
||||
if ((ret = __db_c_dup(jc->j_curslist[i],
|
||||
&jc->j_workcurs[i], DB_POSITION)) != 0)
|
||||
goto err;
|
||||
|
||||
retry2: cp = jc->j_workcurs[i];
|
||||
@@ -435,7 +523,7 @@ retry2: cp = jc->j_workcurs[i];
|
||||
* and let strange things happen--we
|
||||
* can't make rope childproof.
|
||||
*/
|
||||
if ((ret = jc->j_workcurs[j]->c_close(
|
||||
if ((ret = __db_c_close(
|
||||
jc->j_workcurs[j])) != 0)
|
||||
goto err;
|
||||
if (!SORTED_SET(jc, 0) ||
|
||||
@@ -448,10 +536,10 @@ retry2: cp = jc->j_workcurs[i];
|
||||
jc->j_workcurs[j] = NULL;
|
||||
else
|
||||
/* Partial reset suffices. */
|
||||
if ((jc->j_fdupcurs[j]->c_dup(
|
||||
if ((__db_c_dup(
|
||||
jc->j_fdupcurs[j],
|
||||
&jc->j_workcurs[j],
|
||||
DB_POSITIONI)) != 0)
|
||||
DB_POSITION)) != 0)
|
||||
goto err;
|
||||
jc->j_exhausted[j] = 0;
|
||||
}
|
||||
@@ -467,23 +555,21 @@ retry2: cp = jc->j_workcurs[i];
|
||||
for (j = i + 1;
|
||||
jc->j_workcurs[j] != NULL;
|
||||
j++) {
|
||||
if ((ret = jc->j_workcurs[j]->c_close(
|
||||
jc->j_workcurs[j])) != 0)
|
||||
if ((ret =
|
||||
__db_c_close(jc->j_workcurs[j])) != 0)
|
||||
goto err;
|
||||
jc->j_exhausted[j] = 0;
|
||||
if (jc->j_fdupcurs[j] != NULL &&
|
||||
(ret = jc->j_fdupcurs[j]->c_dup(
|
||||
jc->j_fdupcurs[j], &jc->j_workcurs[j],
|
||||
DB_POSITIONI)) != 0)
|
||||
goto err;
|
||||
else
|
||||
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 == ENOMEM) {
|
||||
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) {
|
||||
@@ -521,9 +607,8 @@ mem_err: __db_err(dbp->dbenv,
|
||||
* duplicate duplicates; store this into jc->j_fdupcurs[i].
|
||||
*/
|
||||
if (SORTED_SET(jc, i) && jc->j_fdupcurs[i] == NULL && (ret =
|
||||
cp->c_dup(cp, &jc->j_fdupcurs[i], DB_POSITIONI)) != 0)
|
||||
__db_c_dup(cp, &jc->j_fdupcurs[i], DB_POSITION)) != 0)
|
||||
goto err;
|
||||
|
||||
}
|
||||
|
||||
err: if (ret != 0)
|
||||
@@ -534,7 +619,7 @@ 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 = jc->j_workcurs[0]->c_real_get(jc->j_workcurs[0],
|
||||
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);
|
||||
@@ -615,7 +700,13 @@ samekey: /*
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
/*
|
||||
* __db_join_close --
|
||||
* DBC->c_close for join cursors.
|
||||
*
|
||||
* PUBLIC: int __db_join_close __P((DBC *));
|
||||
*/
|
||||
int
|
||||
__db_join_close(dbc)
|
||||
DBC *dbc;
|
||||
{
|
||||
@@ -653,11 +744,11 @@ __db_join_close(dbc)
|
||||
* mucking with.
|
||||
*/
|
||||
for (i = 0; i < jc->j_ncurs; i++) {
|
||||
if (jc->j_workcurs[i] != NULL && (t_ret =
|
||||
jc->j_workcurs[i]->c_close(jc->j_workcurs[i])) != 0)
|
||||
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 =
|
||||
jc->j_fdupcurs[i]->c_close(jc->j_fdupcurs[i])) != 0)
|
||||
if (jc->j_fdupcurs[i] != NULL &&
|
||||
(t_ret = __db_c_close(jc->j_fdupcurs[i])) != 0)
|
||||
ret = t_ret;
|
||||
}
|
||||
|
||||
@@ -711,7 +802,7 @@ __db_join_getnext(dbc, key, data, exhausted, opmods)
|
||||
*/
|
||||
memset(&ldata, 0, sizeof(DBT));
|
||||
F_SET(&ldata, DB_DBT_MALLOC);
|
||||
if ((ret = dbc->c_real_get(dbc,
|
||||
if ((ret = __db_c_get(dbc,
|
||||
key, &ldata, opmods | DB_CURRENT)) != 0)
|
||||
break;
|
||||
cmp = func(dbp, data, &ldata);
|
||||
@@ -736,7 +827,7 @@ __db_join_getnext(dbc, key, data, exhausted, opmods)
|
||||
__os_ufree(dbp->dbenv, ldata.data);
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
ret = dbc->c_real_get(dbc, key, data, opmods | DB_GET_BOTHC);
|
||||
ret = __db_c_get(dbc, key, data, opmods | DB_GET_BOTHC);
|
||||
break;
|
||||
default:
|
||||
ret = EINVAL;
|
||||
@@ -757,17 +848,14 @@ __db_join_cmp(a, b)
|
||||
DBC *dbca, *dbcb;
|
||||
db_recno_t counta, countb;
|
||||
|
||||
/* In case c_count fails, pretend cursors are equal. */
|
||||
counta = countb = 0;
|
||||
|
||||
dbca = *((DBC * const *)a);
|
||||
dbcb = *((DBC * const *)b);
|
||||
|
||||
if (dbca->c_count(dbca, &counta, 0) != 0 ||
|
||||
dbcb->c_count(dbcb, &countb, 0) != 0)
|
||||
if (__db_c_count(dbca, &counta) != 0 ||
|
||||
__db_c_count(dbcb, &countb) != 0)
|
||||
return (0);
|
||||
|
||||
return (counta - countb);
|
||||
return ((long)counta - (long)countb);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -784,7 +872,11 @@ __db_join_primget(dbp, txn, lockerid, key, data, flags)
|
||||
u_int32_t flags;
|
||||
{
|
||||
DBC *dbc;
|
||||
int dirty, ret, rmw, t_ret;
|
||||
int ret, rmw, 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
|
||||
@@ -793,17 +885,17 @@ __db_join_primget(dbp, txn, lockerid, key, data, flags)
|
||||
* It's a DB bug if we allow any other flags down in here.
|
||||
*/
|
||||
rmw = LF_ISSET(DB_RMW);
|
||||
dirty = LF_ISSET(DB_DIRTY_READ);
|
||||
LF_CLR(DB_RMW | DB_DIRTY_READ);
|
||||
DB_ASSERT(flags == 0);
|
||||
|
||||
if ((ret = __db_icursor(dbp,
|
||||
txn, dbp->type, PGNO_INVALID, 0, lockerid, &dbc)) != 0)
|
||||
return (ret);
|
||||
|
||||
if (dirty ||
|
||||
if (LF_ISSET(DB_DIRTY_READ) ||
|
||||
(txn != NULL && F_ISSET(txn, TXN_DIRTY_READ)))
|
||||
F_SET(dbc, DBC_DIRTY_READ);
|
||||
|
||||
if (LF_ISSET(DB_DEGREE_2) ||
|
||||
(txn != NULL && F_ISSET(txn, TXN_DEGREE_2)))
|
||||
F_SET(dbc, DBC_DEGREE_2);
|
||||
|
||||
LF_CLR(DB_RMW | DB_DIRTY_READ | DB_DEGREE_2);
|
||||
DB_ASSERT(flags == 0);
|
||||
|
||||
F_SET(dbc, DBC_TRANSIENT);
|
||||
|
||||
/*
|
||||
@@ -813,10 +905,26 @@ __db_join_primget(dbp, txn, lockerid, key, data, flags)
|
||||
*/
|
||||
SET_RET_MEM(dbc, dbp);
|
||||
|
||||
ret = dbc->c_get(dbc, key, data, DB_SET | rmw);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -38,14 +38,12 @@
|
||||
* 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_meta.c,v 11.89 2004/10/05 14:28:33 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_meta.c,v 11.61 2002/08/08 03:57:48 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -56,9 +54,10 @@ static const char revid[] = "$Id: db_meta.c,v 11.61 2002/08/08 03:57:48 bostic E
|
||||
#include "dbinc/db_page.h"
|
||||
#include "dbinc/db_shash.h"
|
||||
#include "dbinc/lock.h"
|
||||
#include "dbinc/mp.h"
|
||||
#include "dbinc/db_am.h"
|
||||
|
||||
static void __db_init_meta __P((void *, u_int32_t, db_pgno_t, u_int32_t));
|
||||
static void __db_init_meta __P((DB *, void *, db_pgno_t, u_int32_t));
|
||||
|
||||
/*
|
||||
* __db_init_meta --
|
||||
@@ -67,9 +66,9 @@ static void __db_init_meta __P((void *, u_int32_t, db_pgno_t, u_int32_t));
|
||||
* retain the page number and LSN of the existing page.
|
||||
*/
|
||||
static void
|
||||
__db_init_meta(p, pgsize, pgno, pgtype)
|
||||
__db_init_meta(dbp, p, pgno, pgtype)
|
||||
DB *dbp;
|
||||
void *p;
|
||||
u_int32_t pgsize;
|
||||
db_pgno_t pgno;
|
||||
u_int32_t pgtype;
|
||||
{
|
||||
@@ -80,7 +79,9 @@ __db_init_meta(p, pgsize, pgno, pgtype)
|
||||
save_lsn = meta->lsn;
|
||||
memset(meta, 0, sizeof(DBMETA));
|
||||
meta->lsn = save_lsn;
|
||||
meta->pagesize = pgsize;
|
||||
meta->pagesize = dbp->pgsize;
|
||||
if (F_ISSET(dbp, DB_AM_CHKSUM))
|
||||
FLD_SET(meta->metaflags, DBMETA_CHKSUM);
|
||||
meta->pgno = pgno;
|
||||
meta->type = (u_int8_t)pgtype;
|
||||
}
|
||||
@@ -103,8 +104,9 @@ __db_new(dbc, type, pagepp)
|
||||
DB_LSN lsn;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *h;
|
||||
db_pgno_t pgno, newnext;
|
||||
int meta_flags, extend, ret;
|
||||
db_pgno_t last, pgno, newnext;
|
||||
u_int32_t meta_flags;
|
||||
int extend, ret, t_ret;
|
||||
|
||||
meta = NULL;
|
||||
meta_flags = 0;
|
||||
@@ -117,15 +119,16 @@ __db_new(dbc, type, pagepp)
|
||||
if ((ret = __db_lget(dbc,
|
||||
LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
|
||||
goto err;
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0)
|
||||
goto err;
|
||||
last = meta->last_pgno;
|
||||
if (meta->free == PGNO_INVALID) {
|
||||
pgno = meta->last_pgno + 1;
|
||||
last = pgno = meta->last_pgno + 1;
|
||||
ZERO_LSN(lsn);
|
||||
extend = 1;
|
||||
} else {
|
||||
pgno = meta->free;
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
@@ -145,8 +148,8 @@ __db_new(dbc, type, pagepp)
|
||||
*/
|
||||
if (DBC_LOGGING(dbc)) {
|
||||
if ((ret = __db_pg_alloc_log(dbp, dbc->txn, &LSN(meta), 0,
|
||||
&LSN(meta), PGNO_BASE_MD, &lsn, pgno,
|
||||
(u_int32_t)type, newnext)) != 0)
|
||||
&LSN(meta), PGNO_BASE_MD, &lsn,
|
||||
pgno, (u_int32_t)type, newnext, meta->last_pgno)) != 0)
|
||||
goto err;
|
||||
} else
|
||||
LSN_NOT_LOGGED(LSN(meta));
|
||||
@@ -155,12 +158,12 @@ __db_new(dbc, type, pagepp)
|
||||
meta->free = newnext;
|
||||
|
||||
if (extend == 1) {
|
||||
meta->last_pgno++;
|
||||
if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_NEW, &h)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &pgno, DB_MPOOL_NEW, &h)) != 0)
|
||||
goto err;
|
||||
DB_ASSERT(last == pgno);
|
||||
meta->last_pgno = pgno;
|
||||
ZERO_LSN(h->lsn);
|
||||
h->pgno = pgno;
|
||||
DB_ASSERT(pgno == meta->last_pgno);
|
||||
}
|
||||
LSN(h) = LSN(meta);
|
||||
|
||||
@@ -169,14 +172,18 @@ __db_new(dbc, type, pagepp)
|
||||
if (TYPE(h) != P_INVALID)
|
||||
return (__db_panic(dbp->dbenv, EINVAL));
|
||||
|
||||
(void)mpf->put(mpf, (PAGE *)meta, DB_MPOOL_DIRTY);
|
||||
(void)__TLPUT(dbc, metalock);
|
||||
ret = __memp_fput(mpf, (PAGE *)meta, DB_MPOOL_DIRTY);
|
||||
meta = NULL;
|
||||
if ((t_ret = __TLPUT(dbc, metalock)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
switch (type) {
|
||||
case P_BTREEMETA:
|
||||
case P_HASHMETA:
|
||||
case P_QAMMETA:
|
||||
__db_init_meta(h, dbp->pgsize, h->pgno, type);
|
||||
__db_init_meta(dbp, h, h->pgno, type);
|
||||
break;
|
||||
default:
|
||||
P_INIT(h, dbp->pgsize,
|
||||
@@ -201,9 +208,9 @@ __db_new(dbc, type, pagepp)
|
||||
return (0);
|
||||
|
||||
err: if (h != NULL)
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
(void)__memp_fput(mpf, h, 0);
|
||||
if (meta != NULL)
|
||||
(void)mpf->put(mpf, meta, meta_flags);
|
||||
(void)__memp_fput(mpf, meta, meta_flags);
|
||||
(void)__TLPUT(dbc, metalock);
|
||||
return (ret);
|
||||
}
|
||||
@@ -221,7 +228,7 @@ __db_free(dbc, h)
|
||||
{
|
||||
DBMETA *meta;
|
||||
DB *dbp;
|
||||
DBT ldbt;
|
||||
DBT ddbt, ldbt;
|
||||
DB_LOCK metalock;
|
||||
DB_MPOOLFILE *mpf;
|
||||
db_pgno_t pgno;
|
||||
@@ -242,7 +249,7 @@ __db_free(dbc, h)
|
||||
if ((ret = __db_lget(dbc,
|
||||
LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
|
||||
goto err;
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0) {
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0) {
|
||||
(void)__TLPUT(dbc, metalock);
|
||||
goto err;
|
||||
}
|
||||
@@ -253,10 +260,42 @@ __db_free(dbc, h)
|
||||
memset(&ldbt, 0, sizeof(ldbt));
|
||||
ldbt.data = h;
|
||||
ldbt.size = P_OVERHEAD(dbp);
|
||||
if ((ret = __db_pg_free_log(dbp,
|
||||
dbc->txn, &LSN(meta), 0, h->pgno,
|
||||
&LSN(meta), PGNO_BASE_MD, &ldbt, meta->free)) != 0) {
|
||||
(void)mpf->put(mpf, (PAGE *)meta, 0);
|
||||
switch (h->type) {
|
||||
case P_HASH:
|
||||
case P_IBTREE:
|
||||
case P_IRECNO:
|
||||
case P_LBTREE:
|
||||
case P_LRECNO:
|
||||
case P_LDUP:
|
||||
if (h->entries > 0) {
|
||||
ldbt.size += h->entries * sizeof(db_indx_t);
|
||||
ddbt.data = (u_int8_t *)h + h->hf_offset;
|
||||
ddbt.size = dbp->pgsize - h->hf_offset;
|
||||
ret = __db_pg_freedata_log(dbp, dbc->txn,
|
||||
&LSN(meta), 0, h->pgno, &LSN(meta),
|
||||
PGNO_BASE_MD, &ldbt,
|
||||
meta->free, meta->last_pgno, &ddbt);
|
||||
break;
|
||||
}
|
||||
goto log;
|
||||
case P_HASHMETA:
|
||||
ldbt.size = sizeof(HMETA);
|
||||
goto log;
|
||||
case P_BTREEMETA:
|
||||
ldbt.size = sizeof(BTMETA);
|
||||
goto log;
|
||||
case P_OVERFLOW:
|
||||
ldbt.size += OV_LEN(h);
|
||||
goto log;
|
||||
default:
|
||||
DB_ASSERT(h->type != P_QAMDATA);
|
||||
|
||||
log: ret = __db_pg_free_log(dbp,
|
||||
dbc->txn, &LSN(meta), 0, h->pgno, &LSN(meta),
|
||||
PGNO_BASE_MD, &ldbt, meta->free, meta->last_pgno);
|
||||
}
|
||||
if (ret != 0) {
|
||||
(void)__memp_fput(mpf, (PAGE *)meta, 0);
|
||||
(void)__TLPUT(dbc, metalock);
|
||||
goto err;
|
||||
}
|
||||
@@ -264,20 +303,44 @@ __db_free(dbc, h)
|
||||
LSN_NOT_LOGGED(LSN(meta));
|
||||
LSN(h) = LSN(meta);
|
||||
|
||||
P_INIT(h, dbp->pgsize, h->pgno, PGNO_INVALID, meta->free, 0, P_INVALID);
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
if (h->pgno == meta->last_pgno) {
|
||||
if ((ret = __memp_fput(mpf, h, DB_MPOOL_DISCARD)) != 0)
|
||||
goto err;
|
||||
/* Give the page back to the OS. */
|
||||
if ((ret = __memp_ftruncate(mpf, meta->last_pgno, 0)) != 0)
|
||||
goto err;
|
||||
meta->last_pgno--;
|
||||
h = NULL;
|
||||
} else
|
||||
#endif
|
||||
|
||||
meta->free = h->pgno;
|
||||
{
|
||||
/*
|
||||
* If we are not truncating the page then we
|
||||
* reinitialize it and put it hat the head of
|
||||
* the free list.
|
||||
*/
|
||||
P_INIT(h, dbp->pgsize,
|
||||
h->pgno, PGNO_INVALID, meta->free, 0, P_INVALID);
|
||||
#ifdef DIAGNOSTIC
|
||||
memset((u_int8_t *) h + P_OVERHEAD(dbp),
|
||||
CLEAR_BYTE, dbp->pgsize - P_OVERHEAD(dbp));
|
||||
#endif
|
||||
meta->free = h->pgno;
|
||||
}
|
||||
|
||||
/* Discard the metadata page. */
|
||||
if ((t_ret =
|
||||
mpf->put(mpf, (PAGE *)meta, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
__memp_fput(mpf, (PAGE *)meta, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
if ((t_ret = __TLPUT(dbc, metalock)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/* Discard the caller's page reference. */
|
||||
dirty_flag = DB_MPOOL_DIRTY;
|
||||
err: if ((t_ret = mpf->put(mpf, h, dirty_flag)) != 0 && ret == 0)
|
||||
err: if (h != NULL &&
|
||||
(t_ret = __memp_fput(mpf, h, dirty_flag)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
/*
|
||||
@@ -298,34 +361,21 @@ int
|
||||
__db_lprint(dbc)
|
||||
DBC *dbc;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
DB *dbp;
|
||||
DB_LOCKREQ req;
|
||||
|
||||
dbp = dbc->dbp;
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
if (LOCKING_ON(dbp->dbenv)) {
|
||||
if (LOCKING_ON(dbenv)) {
|
||||
req.op = DB_LOCK_DUMP;
|
||||
dbp->dbenv->lock_vec(dbp->dbenv, dbc->locker, 0, &req, 1, NULL);
|
||||
(void)__lock_vec(dbenv, dbc->locker, 0, &req, 1, NULL);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Implement the rules for transactional locking. We can release the previous
|
||||
* lock if we are not in a transaction or COUPLE_ALWAYS is specifed (used in
|
||||
* record locking). If we are doing dirty reads then we can release read locks
|
||||
* and down grade write locks.
|
||||
*/
|
||||
#define DB_PUT_ACTION(dbc, action, lockp) \
|
||||
(((action == LCK_COUPLE || action == LCK_COUPLE_ALWAYS) && \
|
||||
LOCK_ISSET(*lockp)) ? \
|
||||
(dbc->txn == NULL || action == LCK_COUPLE_ALWAYS || \
|
||||
(F_ISSET(dbc, DBC_DIRTY_READ) && \
|
||||
(lockp)->mode == DB_LOCK_DIRTY)) ? LCK_COUPLE : \
|
||||
(F_ISSET((dbc)->dbp, DB_AM_DIRTY) && \
|
||||
(lockp)->mode == DB_LOCK_WRITE) ? LCK_DOWNGRADE : 0 : 0)
|
||||
|
||||
/*
|
||||
* __db_lget --
|
||||
* The standard lock get call.
|
||||
@@ -359,7 +409,7 @@ __db_lget(dbc, action, pgno, mode, lkflags, lockp)
|
||||
if (CDB_LOCKING(dbenv) ||
|
||||
!LOCKING_ON(dbenv) || F_ISSET(dbc, DBC_COMPENSATE) ||
|
||||
(F_ISSET(dbc, DBC_RECOVER) &&
|
||||
(action != LCK_ROLLBACK || F_ISSET(dbenv, DB_ENV_REP_CLIENT))) ||
|
||||
(action != LCK_ROLLBACK || IS_REP_CLIENT(dbenv))) ||
|
||||
(action != LCK_ALWAYS && F_ISSET(dbc, DBC_OPD))) {
|
||||
LOCK_INIT(*lockp);
|
||||
return (0);
|
||||
@@ -371,6 +421,8 @@ __db_lget(dbc, action, pgno, mode, lkflags, lockp)
|
||||
else
|
||||
dbc->lock.type = DB_PAGE_LOCK;
|
||||
lkflags &= ~DB_LOCK_RECORD;
|
||||
if (action == LCK_ROLLBACK)
|
||||
lkflags |= DB_LOCK_ABORT;
|
||||
|
||||
/*
|
||||
* If the transaction enclosing this cursor has DB_LOCK_NOWAIT set,
|
||||
@@ -382,42 +434,69 @@ __db_lget(dbc, action, pgno, mode, lkflags, lockp)
|
||||
if (F_ISSET(dbc, DBC_DIRTY_READ) && mode == DB_LOCK_READ)
|
||||
mode = DB_LOCK_DIRTY;
|
||||
|
||||
has_timeout = txn != NULL && F_ISSET(txn, TXN_LOCKTIMEOUT);
|
||||
has_timeout = F_ISSET(dbc, DBC_RECOVER) ||
|
||||
(txn != NULL && F_ISSET(txn, TXN_LOCKTIMEOUT));
|
||||
|
||||
switch (DB_PUT_ACTION(dbc, action, lockp)) {
|
||||
/*
|
||||
* Transactional locking.
|
||||
* Hold on to the previous read lock only if we are in full isolation.
|
||||
* COUPLE_ALWAYS indicates we are holding an interior node
|
||||
* which need not be isolated.
|
||||
* Downgrade write locks if we are supporting dirty readers.
|
||||
*/
|
||||
if ((action != LCK_COUPLE && action != LCK_COUPLE_ALWAYS) ||
|
||||
!LOCK_ISSET(*lockp))
|
||||
action = 0;
|
||||
else if (dbc->txn == NULL || action == LCK_COUPLE_ALWAYS)
|
||||
action = LCK_COUPLE;
|
||||
else if (F_ISSET(dbc, DBC_DEGREE_2) && lockp->mode == DB_LOCK_READ)
|
||||
action = LCK_COUPLE;
|
||||
else if (F_ISSET(dbc, DBC_DIRTY_READ) && lockp->mode == DB_LOCK_DIRTY)
|
||||
action = LCK_COUPLE;
|
||||
else if (F_ISSET(dbc->dbp, DB_AM_DIRTY) && lockp->mode == DB_LOCK_WRITE)
|
||||
action = LCK_DOWNGRADE;
|
||||
else
|
||||
action = 0;
|
||||
|
||||
switch (action) {
|
||||
case LCK_DOWNGRADE:
|
||||
if ((ret = __lock_downgrade(
|
||||
dbenv, lockp, DB_LOCK_WWRITE, 0)) != 0)
|
||||
return (ret);
|
||||
/* FALLTHROUGH */
|
||||
|
||||
default:
|
||||
if (!has_timeout) {
|
||||
ret = __lock_get(dbenv,
|
||||
dbc->locker, lkflags, &dbc->lock_dbt, mode, lockp);
|
||||
break;
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case LCK_COUPLE:
|
||||
lck_couple: couple[0].op = has_timeout? DB_LOCK_GET_TIMEOUT : DB_LOCK_GET;
|
||||
couple[0].op = has_timeout? DB_LOCK_GET_TIMEOUT : DB_LOCK_GET;
|
||||
couple[0].obj = &dbc->lock_dbt;
|
||||
couple[0].mode = mode;
|
||||
if (action == LCK_COUPLE_ALWAYS)
|
||||
action = LCK_COUPLE;
|
||||
UMRW_SET(couple[0].timeout);
|
||||
if (has_timeout)
|
||||
couple[0].timeout = txn->lock_timeout;
|
||||
couple[0].timeout =
|
||||
F_ISSET(dbc, DBC_RECOVER) ? 0 : txn->lock_timeout;
|
||||
if (action == LCK_COUPLE) {
|
||||
couple[1].op = DB_LOCK_PUT;
|
||||
couple[1].lock = *lockp;
|
||||
}
|
||||
|
||||
ret = dbenv->lock_vec(dbenv, dbc->locker,
|
||||
ret = __lock_vec(dbenv, dbc->locker,
|
||||
lkflags, couple, action == LCK_COUPLE ? 2 : 1, &reqp);
|
||||
if (ret == 0 || reqp == &couple[1])
|
||||
*lockp = couple[0].lock;
|
||||
break;
|
||||
case LCK_DOWNGRADE:
|
||||
if ((ret = dbenv->lock_downgrade(
|
||||
dbenv, lockp, DB_LOCK_WWRITE, 0)) != 0)
|
||||
return (ret);
|
||||
/* FALL THROUGH */
|
||||
default:
|
||||
if (has_timeout)
|
||||
goto lck_couple;
|
||||
ret = dbenv->lock_get(dbenv,
|
||||
dbc->locker, lkflags, &dbc->lock_dbt, mode, lockp);
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
if (txn != NULL && ret == DB_LOCK_DEADLOCK)
|
||||
F_SET(txn, TXN_DEADLOCK);
|
||||
return ((ret == DB_LOCK_NOTGRANTED &&
|
||||
!F_ISSET(dbenv, DB_ENV_TIME_NOTGRANTED)) ? DB_LOCK_DEADLOCK : ret);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -432,13 +511,28 @@ __db_lput(dbc, lockp)
|
||||
DB_LOCK *lockp;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int ret;
|
||||
int action, ret;
|
||||
|
||||
/*
|
||||
* Transactional locking.
|
||||
* Hold on to the read locks only if we are in full isolation.
|
||||
* Downgrade write locks if we are supporting dirty readers.
|
||||
*/
|
||||
if (F_ISSET(dbc->dbp, DB_AM_DIRTY) && lockp->mode == DB_LOCK_WRITE)
|
||||
action = LCK_DOWNGRADE;
|
||||
else if (dbc->txn == NULL)
|
||||
action = LCK_COUPLE;
|
||||
else if (F_ISSET(dbc, DBC_DEGREE_2) && lockp->mode == DB_LOCK_READ)
|
||||
action = LCK_COUPLE;
|
||||
else if (F_ISSET(dbc, DBC_DIRTY_READ) && lockp->mode == DB_LOCK_DIRTY)
|
||||
action = LCK_COUPLE;
|
||||
else
|
||||
action = 0;
|
||||
|
||||
dbenv = dbc->dbp->dbenv;
|
||||
|
||||
switch (DB_PUT_ACTION(dbc, LCK_COUPLE, lockp)) {
|
||||
switch (action) {
|
||||
case LCK_COUPLE:
|
||||
ret = dbenv->lock_put(dbenv, lockp);
|
||||
ret = __lock_put(dbenv, lockp, 0);
|
||||
break;
|
||||
case LCK_DOWNGRADE:
|
||||
ret = __lock_downgrade(dbenv, lockp, DB_LOCK_WWRITE, 0);
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1999-2002
|
||||
* Copyright (c) 1999-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_method.c,v 11.116 2004/10/11 18:22:05 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_method.c,v 11.78 2002/07/02 19:26:55 sue Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -21,44 +19,55 @@ static const char revid[] = "$Id: db_method.c,v 11.78 2002/07/02 19:26:55 sue Ex
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RPC
|
||||
#include "db_server.h"
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "dbinc/crypto.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/mp.h"
|
||||
#include "dbinc/qam.h"
|
||||
#include "dbinc/xa.h"
|
||||
#include "dbinc_auto/xa_ext.h"
|
||||
#include "dbinc/db_shash.h"
|
||||
#include "dbinc/lock.h"
|
||||
|
||||
#ifdef HAVE_RPC
|
||||
#include "dbinc_auto/db_server.h"
|
||||
#include "dbinc_auto/rpc_client_ext.h"
|
||||
#endif
|
||||
|
||||
static int __db_get_byteswapped __P((DB *, int *));
|
||||
static int __db_get_dbname __P((DB *, const char **, const char **));
|
||||
static DB_ENV *__db_get_env __P((DB *));
|
||||
static int __db_get_transactional __P((DB *));
|
||||
static int __db_get_type __P((DB *, DBTYPE *dbtype));
|
||||
static int __db_init __P((DB *, u_int32_t));
|
||||
static int __db_key_range
|
||||
__P((DB *, DB_TXN *, DBT *, DB_KEY_RANGE *, u_int32_t));
|
||||
static int __db_set_alloc __P((DB *, void *(*)(size_t),
|
||||
void *(*)(void *, size_t), void (*)(void *)));
|
||||
static int __db_set_append_recno __P((DB *, int (*)(DB *, DBT *, db_recno_t)));
|
||||
static int __db_get_cachesize __P((DB *, u_int32_t *, u_int32_t *, int *));
|
||||
static int __db_set_cachesize __P((DB *, u_int32_t, u_int32_t, int));
|
||||
static int __db_set_cache_priority __P((DB *, DB_CACHE_PRIORITY));
|
||||
static int __db_set_dup_compare
|
||||
__P((DB *, int (*)(DB *, const DBT *, const DBT *)));
|
||||
static int __db_get_encrypt_flags __P((DB *, u_int32_t *));
|
||||
static int __db_set_encrypt __P((DB *, const char *, u_int32_t));
|
||||
static int __db_set_feedback __P((DB *, void (*)(DB *, int, int)));
|
||||
static int __db_set_flags __P((DB *, u_int32_t));
|
||||
static int __db_set_pagesize __P((DB *, u_int32_t));
|
||||
static void __db_map_flags __P((DB *, u_int32_t *, u_int32_t *));
|
||||
static int __db_get_pagesize __P((DB *, u_int32_t *));
|
||||
static int __db_set_paniccall __P((DB *, void (*)(DB_ENV *, int)));
|
||||
static void __db_set_errcall __P((DB *, void (*)(const char *, char *)));
|
||||
static void __db_set_errcall
|
||||
__P((DB *, void (*)(const DB_ENV *, const char *, const char *)));
|
||||
static void __db_get_errfile __P((DB *, FILE **));
|
||||
static void __db_set_errfile __P((DB *, FILE *));
|
||||
static void __db_get_errpfx __P((DB *, const char **));
|
||||
static void __db_set_errpfx __P((DB *, const char *));
|
||||
static int __db_stat_fail __P((DB *, void *, u_int32_t));
|
||||
static void __db_set_msgcall
|
||||
__P((DB *, void (*)(const DB_ENV *, const char *)));
|
||||
static void __db_get_msgfile __P((DB *, FILE **));
|
||||
static void __db_set_msgfile __P((DB *, FILE *));
|
||||
static void __dbh_err __P((DB *, int, const char *, ...));
|
||||
static void __dbh_errx __P((DB *, const char *, ...));
|
||||
|
||||
@@ -85,6 +94,8 @@ db_create(dbpp, dbenv, flags)
|
||||
switch (flags) {
|
||||
case 0:
|
||||
break;
|
||||
case DB_REP_CREATE:
|
||||
break;
|
||||
case DB_XA_CREATE:
|
||||
if (dbenv != NULL) {
|
||||
__db_err(dbenv,
|
||||
@@ -113,25 +124,47 @@ db_create(dbpp, dbenv, flags)
|
||||
else
|
||||
#endif
|
||||
ret = __db_init(dbp, flags);
|
||||
if (ret != 0) {
|
||||
__os_free(dbenv, dbp);
|
||||
return (ret);
|
||||
}
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
/* If we don't have an environment yet, allocate a local one. */
|
||||
if (dbenv == NULL) {
|
||||
if ((ret = db_env_create(&dbenv, 0)) != 0) {
|
||||
__os_free(dbenv, dbp);
|
||||
return (ret);
|
||||
}
|
||||
if ((ret = db_env_create(&dbenv, 0)) != 0)
|
||||
goto err;
|
||||
F_SET(dbenv, DB_ENV_DBLOCAL);
|
||||
}
|
||||
++dbenv->db_ref;
|
||||
|
||||
dbp->dbenv = dbenv;
|
||||
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
|
||||
++dbenv->db_ref;
|
||||
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
|
||||
|
||||
/*
|
||||
* Set the replication timestamp; it's 0 if we're not in a replicated
|
||||
* environment.
|
||||
*/
|
||||
dbp->timestamp =
|
||||
(F_ISSET(dbenv, DB_ENV_DBLOCAL) || !REP_ON(dbenv)) ? 0 :
|
||||
((REGENV *)((REGINFO *)dbenv->reginfo)->primary)->rep_timestamp;
|
||||
|
||||
/* If not RPC, open a backing DB_MPOOLFILE handle in the memory pool. */
|
||||
#ifdef HAVE_RPC
|
||||
if (!RPC_ON(dbenv))
|
||||
#endif
|
||||
if ((ret = __memp_fcreate(dbenv, &dbp->mpf)) != 0)
|
||||
goto err;
|
||||
|
||||
dbp->type = DB_UNKNOWN;
|
||||
|
||||
*dbpp = dbp;
|
||||
return (0);
|
||||
|
||||
err: if (dbp->mpf != NULL)
|
||||
(void)__memp_fclose(dbp->mpf, 0);
|
||||
if (dbenv != NULL && F_ISSET(dbenv, DB_ENV_DBLOCAL))
|
||||
(void)__dbenv_close(dbenv, 0);
|
||||
__os_free(dbenv, dbp);
|
||||
*dbpp = NULL;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -156,42 +189,57 @@ __db_init(dbp, flags)
|
||||
FLD_SET(dbp->am_ok,
|
||||
DB_OK_BTREE | DB_OK_HASH | DB_OK_QUEUE | DB_OK_RECNO);
|
||||
|
||||
dbp->associate = __db_associate;
|
||||
dbp->close = __db_close;
|
||||
dbp->cursor = __db_cursor;
|
||||
dbp->del = __db_delete;
|
||||
dbp->associate = __db_associate_pp;
|
||||
dbp->close = __db_close_pp;
|
||||
dbp->cursor = __db_cursor_pp;
|
||||
dbp->del = __db_del_pp;
|
||||
dbp->dump = __db_dump_pp;
|
||||
dbp->err = __dbh_err;
|
||||
dbp->errx = __dbh_errx;
|
||||
dbp->fd = __db_fd;
|
||||
dbp->get = __db_get;
|
||||
dbp->fd = __db_fd_pp;
|
||||
dbp->get = __db_get_pp;
|
||||
dbp->get_byteswapped = __db_get_byteswapped;
|
||||
dbp->get_dbname = __db_get_dbname;
|
||||
dbp->get_env = __db_get_env;
|
||||
dbp->get_open_flags = __db_get_open_flags;
|
||||
dbp->get_transactional = __db_get_transactional;
|
||||
dbp->get_type = __db_get_type;
|
||||
dbp->join = __db_join;
|
||||
dbp->key_range = __db_key_range;
|
||||
dbp->open = __db_open;
|
||||
dbp->pget = __db_pget;
|
||||
dbp->put = __db_put;
|
||||
dbp->remove = __db_remove;
|
||||
dbp->rename = __db_rename;
|
||||
dbp->truncate = __db_truncate;
|
||||
dbp->join = __db_join_pp;
|
||||
dbp->key_range = __db_key_range_pp;
|
||||
dbp->open = __db_open_pp;
|
||||
dbp->pget = __db_pget_pp;
|
||||
dbp->put = __db_put_pp;
|
||||
dbp->remove = __db_remove_pp;
|
||||
dbp->rename = __db_rename_pp;
|
||||
dbp->truncate = __db_truncate_pp;
|
||||
dbp->set_alloc = __db_set_alloc;
|
||||
dbp->set_append_recno = __db_set_append_recno;
|
||||
dbp->get_cachesize = __db_get_cachesize;
|
||||
dbp->set_cachesize = __db_set_cachesize;
|
||||
dbp->set_cache_priority = __db_set_cache_priority;
|
||||
dbp->set_dup_compare = __db_set_dup_compare;
|
||||
dbp->get_encrypt_flags = __db_get_encrypt_flags;
|
||||
dbp->set_encrypt = __db_set_encrypt;
|
||||
dbp->set_errcall = __db_set_errcall;
|
||||
dbp->get_errfile = __db_get_errfile;
|
||||
dbp->set_errfile = __db_set_errfile;
|
||||
dbp->get_errpfx = __db_get_errpfx;
|
||||
dbp->set_errpfx = __db_set_errpfx;
|
||||
dbp->set_feedback = __db_set_feedback;
|
||||
dbp->get_flags = __db_get_flags;
|
||||
dbp->set_flags = __db_set_flags;
|
||||
dbp->get_lorder = __db_get_lorder;
|
||||
dbp->set_lorder = __db_set_lorder;
|
||||
dbp->set_msgcall = __db_set_msgcall;
|
||||
dbp->get_msgfile = __db_get_msgfile;
|
||||
dbp->set_msgfile = __db_set_msgfile;
|
||||
dbp->get_pagesize = __db_get_pagesize;
|
||||
dbp->set_pagesize = __db_set_pagesize;
|
||||
dbp->set_paniccall = __db_set_paniccall;
|
||||
dbp->stat = __db_stat_fail;
|
||||
dbp->sync = __db_sync;
|
||||
dbp->upgrade = __db_upgrade;
|
||||
dbp->verify = __db_verify;
|
||||
dbp->stat = __db_stat_pp;
|
||||
dbp->stat_print = __db_stat_print_pp;
|
||||
dbp->sync = __db_sync_pp;
|
||||
dbp->upgrade = __db_upgrade_pp;
|
||||
dbp->verify = __db_verify_pp;
|
||||
|
||||
/* Access method specific. */
|
||||
if ((ret = __bam_db_create(dbp)) != 0)
|
||||
@@ -208,6 +256,9 @@ __db_init(dbp, flags)
|
||||
if (LF_ISSET(DB_XA_CREATE) && (ret = __db_xa_create(dbp)) != 0)
|
||||
return (ret);
|
||||
|
||||
if (LF_ISSET(DB_REP_CREATE))
|
||||
F_SET(dbp, DB_AM_REPLICATION);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -245,7 +296,7 @@ __dbh_am_chk(dbp, flags)
|
||||
* Error message, including the standard error string.
|
||||
*/
|
||||
static void
|
||||
#ifdef __STDC__
|
||||
#ifdef STDC_HEADERS
|
||||
__dbh_err(DB *dbp, int error, const char *fmt, ...)
|
||||
#else
|
||||
__dbh_err(dbp, error, fmt, va_alist)
|
||||
@@ -263,7 +314,7 @@ __dbh_err(dbp, error, fmt, va_alist)
|
||||
* Error message.
|
||||
*/
|
||||
static void
|
||||
#ifdef __STDC__
|
||||
#ifdef STDC_HEADERS
|
||||
__dbh_errx(DB *dbp, const char *fmt, ...)
|
||||
#else
|
||||
__dbh_errx(dbp, fmt, va_alist)
|
||||
@@ -284,12 +335,52 @@ __db_get_byteswapped(dbp, isswapped)
|
||||
DB *dbp;
|
||||
int *isswapped;
|
||||
{
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "get_byteswapped");
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_byteswapped");
|
||||
|
||||
*isswapped = F_ISSET(dbp, DB_AM_SWAP) ? 1 : 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_get_dbname --
|
||||
* Get the name of the database as passed to DB->open.
|
||||
*/
|
||||
static int
|
||||
__db_get_dbname(dbp, fnamep, dnamep)
|
||||
DB *dbp;
|
||||
const char **fnamep, **dnamep;
|
||||
{
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_dbname");
|
||||
|
||||
if (fnamep != NULL)
|
||||
*fnamep = dbp->fname;
|
||||
if (dnamep != NULL)
|
||||
*dnamep = dbp->dname;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_get_env --
|
||||
* Get the DB_ENV handle that was passed to db_create.
|
||||
*/
|
||||
static DB_ENV *
|
||||
__db_get_env(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
return (dbp->dbenv);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_transactional --
|
||||
* Get whether this database was created in a transaction.
|
||||
*/
|
||||
static int
|
||||
__db_get_transactional(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
return (F_ISSET(dbp, DB_AM_TXN) ? 1 : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_get_type --
|
||||
* Return type of underlying database.
|
||||
@@ -299,35 +390,12 @@ __db_get_type(dbp, dbtype)
|
||||
DB *dbp;
|
||||
DBTYPE *dbtype;
|
||||
{
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "get_type");
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_type");
|
||||
|
||||
*dbtype = dbp->type;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_key_range --
|
||||
* Return proportion of keys above and below given key.
|
||||
*/
|
||||
static int
|
||||
__db_key_range(dbp, txn, key, kr, flags)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
DBT *key;
|
||||
DB_KEY_RANGE *kr;
|
||||
u_int32_t flags;
|
||||
{
|
||||
COMPQUIET(txn, NULL);
|
||||
COMPQUIET(key, NULL);
|
||||
COMPQUIET(kr, NULL);
|
||||
COMPQUIET(flags, 0);
|
||||
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "key_range");
|
||||
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_set_append_recno --
|
||||
* Set record number append routine.
|
||||
@@ -337,7 +405,7 @@ __db_set_append_recno(dbp, func)
|
||||
DB *dbp;
|
||||
int (*func) __P((DB *, DBT *, db_recno_t));
|
||||
{
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_append_recno");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_append_recno");
|
||||
DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
|
||||
|
||||
dbp->db_append_recno = func;
|
||||
@@ -345,6 +413,22 @@ __db_set_append_recno(dbp, func)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_get_cachesize --
|
||||
* Get underlying cache size.
|
||||
*/
|
||||
static int
|
||||
__db_get_cachesize(dbp, cache_gbytesp, cache_bytesp, ncachep)
|
||||
DB *dbp;
|
||||
u_int32_t *cache_gbytesp, *cache_bytesp;
|
||||
int *ncachep;
|
||||
{
|
||||
DB_ILLEGAL_IN_ENV(dbp, "DB->get_cachesize");
|
||||
|
||||
return (__memp_get_cachesize(dbp->dbenv,
|
||||
cache_gbytesp, cache_bytesp, ncachep));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_set_cachesize --
|
||||
* Set underlying cache size.
|
||||
@@ -355,33 +439,13 @@ __db_set_cachesize(dbp, cache_gbytes, cache_bytes, ncache)
|
||||
u_int32_t cache_gbytes, cache_bytes;
|
||||
int ncache;
|
||||
{
|
||||
DB_ILLEGAL_IN_ENV(dbp, "set_cachesize");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_cachesize");
|
||||
DB_ILLEGAL_IN_ENV(dbp, "DB->set_cachesize");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_cachesize");
|
||||
|
||||
return (dbp->dbenv->set_cachesize(
|
||||
return (__memp_set_cachesize(
|
||||
dbp->dbenv, cache_gbytes, cache_bytes, ncache));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_set_cache_priority --
|
||||
* Set cache priority for pages from this file.
|
||||
*/
|
||||
static int
|
||||
__db_set_cache_priority(dbp, priority)
|
||||
DB *dbp;
|
||||
DB_CACHE_PRIORITY priority;
|
||||
{
|
||||
/*
|
||||
* If an underlying DB_MPOOLFILE exists, call it. Otherwise, save
|
||||
* the information away until DB->open is called.
|
||||
*/
|
||||
if (dbp->mpf == NULL) {
|
||||
dbp->priority = priority;
|
||||
return (0);
|
||||
}
|
||||
return (dbp->mpf->set_priority(dbp->mpf, priority));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_set_dup_compare --
|
||||
* Set duplicate comparison routine.
|
||||
@@ -393,10 +457,10 @@ __db_set_dup_compare(dbp, func)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "dup_compare");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->dup_compare");
|
||||
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH);
|
||||
|
||||
if ((ret = dbp->set_flags(dbp, DB_DUPSORT)) != 0)
|
||||
if ((ret = __db_set_flags(dbp, DB_DUPSORT)) != 0)
|
||||
return (ret);
|
||||
|
||||
dbp->dup_compare = func;
|
||||
@@ -404,6 +468,19 @@ __db_set_dup_compare(dbp, func)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_get_encrypt_flags --
|
||||
*/
|
||||
static int
|
||||
__db_get_encrypt_flags(dbp, flagsp)
|
||||
DB *dbp;
|
||||
u_int32_t *flagsp;
|
||||
{
|
||||
DB_ILLEGAL_IN_ENV(dbp, "DB->get_encrypt_flags");
|
||||
|
||||
return (__dbenv_get_encrypt_flags(dbp->dbenv, flagsp));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_set_encrypt --
|
||||
* Set database passwd.
|
||||
@@ -417,10 +494,10 @@ __db_set_encrypt(dbp, passwd, flags)
|
||||
DB_CIPHER *db_cipher;
|
||||
int ret;
|
||||
|
||||
DB_ILLEGAL_IN_ENV(dbp, "set_encrypt");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_encrypt");
|
||||
DB_ILLEGAL_IN_ENV(dbp, "DB->set_encrypt");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_encrypt");
|
||||
|
||||
if ((ret = dbp->dbenv->set_encrypt(dbp->dbenv, passwd, flags)) != 0)
|
||||
if ((ret = __dbenv_set_encrypt(dbp->dbenv, passwd, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
@@ -432,15 +509,23 @@ __db_set_encrypt(dbp, passwd, flags)
|
||||
(ret = db_cipher->init(dbp->dbenv, db_cipher)) != 0)
|
||||
return (ret);
|
||||
|
||||
return (dbp->set_flags(dbp, DB_ENCRYPT));
|
||||
return (__db_set_flags(dbp, DB_ENCRYPT));
|
||||
}
|
||||
|
||||
static void
|
||||
__db_set_errcall(dbp, errcall)
|
||||
DB *dbp;
|
||||
void (*errcall) __P((const char *, char *));
|
||||
void (*errcall) __P((const DB_ENV *, const char *, const char *));
|
||||
{
|
||||
dbp->dbenv->set_errcall(dbp->dbenv, errcall);
|
||||
__dbenv_set_errcall(dbp->dbenv, errcall);
|
||||
}
|
||||
|
||||
static void
|
||||
__db_get_errfile(dbp, errfilep)
|
||||
DB *dbp;
|
||||
FILE **errfilep;
|
||||
{
|
||||
__dbenv_get_errfile(dbp->dbenv, errfilep);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -448,7 +533,15 @@ __db_set_errfile(dbp, errfile)
|
||||
DB *dbp;
|
||||
FILE *errfile;
|
||||
{
|
||||
dbp->dbenv->set_errfile(dbp->dbenv, errfile);
|
||||
__dbenv_set_errfile(dbp->dbenv, errfile);
|
||||
}
|
||||
|
||||
static void
|
||||
__db_get_errpfx(dbp, errpfxp)
|
||||
DB *dbp;
|
||||
const char **errpfxp;
|
||||
{
|
||||
__dbenv_get_errpfx(dbp->dbenv, errpfxp);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -456,7 +549,7 @@ __db_set_errpfx(dbp, errpfx)
|
||||
DB *dbp;
|
||||
const char *errpfx;
|
||||
{
|
||||
dbp->dbenv->set_errpfx(dbp->dbenv, errpfx);
|
||||
__dbenv_set_errpfx(dbp->dbenv, errpfx);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -468,42 +561,143 @@ __db_set_feedback(dbp, feedback)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
/*
|
||||
* __db_map_flags --
|
||||
* Maps between public and internal flag values.
|
||||
* This function doesn't check for validity, so it can't fail.
|
||||
*/
|
||||
static void
|
||||
__db_map_flags(dbp, inflagsp, outflagsp)
|
||||
DB *dbp;
|
||||
u_int32_t *inflagsp, *outflagsp;
|
||||
{
|
||||
COMPQUIET(dbp, NULL);
|
||||
|
||||
if (FLD_ISSET(*inflagsp, DB_CHKSUM)) {
|
||||
FLD_SET(*outflagsp, DB_AM_CHKSUM);
|
||||
FLD_CLR(*inflagsp, DB_CHKSUM);
|
||||
}
|
||||
if (FLD_ISSET(*inflagsp, DB_ENCRYPT)) {
|
||||
FLD_SET(*outflagsp, DB_AM_ENCRYPT | DB_AM_CHKSUM);
|
||||
FLD_CLR(*inflagsp, DB_ENCRYPT);
|
||||
}
|
||||
if (FLD_ISSET(*inflagsp, DB_TXN_NOT_DURABLE)) {
|
||||
FLD_SET(*outflagsp, DB_AM_NOT_DURABLE);
|
||||
FLD_CLR(*inflagsp, DB_TXN_NOT_DURABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_get_flags --
|
||||
* The DB->get_flags method.
|
||||
*
|
||||
* PUBLIC: int __db_get_flags __P((DB *, u_int32_t *));
|
||||
*/
|
||||
int
|
||||
__db_get_flags(dbp, flagsp)
|
||||
DB *dbp;
|
||||
u_int32_t *flagsp;
|
||||
{
|
||||
static const u_int32_t db_flags[] = {
|
||||
DB_CHKSUM,
|
||||
DB_DUP,
|
||||
DB_DUPSORT,
|
||||
DB_ENCRYPT,
|
||||
DB_INORDER,
|
||||
DB_RECNUM,
|
||||
DB_RENUMBER,
|
||||
DB_REVSPLITOFF,
|
||||
DB_SNAPSHOT,
|
||||
DB_TXN_NOT_DURABLE,
|
||||
0
|
||||
};
|
||||
u_int32_t f, flags, mapped_flag;
|
||||
int i;
|
||||
|
||||
flags = 0;
|
||||
for (i = 0; (f = db_flags[i]) != 0; i++) {
|
||||
mapped_flag = 0;
|
||||
__db_map_flags(dbp, &f, &mapped_flag);
|
||||
__bam_map_flags(dbp, &f, &mapped_flag);
|
||||
__ram_map_flags(dbp, &f, &mapped_flag);
|
||||
#ifdef HAVE_QUEUE
|
||||
__qam_map_flags(dbp, &f, &mapped_flag);
|
||||
#endif
|
||||
DB_ASSERT(f == 0);
|
||||
if (F_ISSET(dbp, mapped_flag) == mapped_flag)
|
||||
LF_SET(db_flags[i]);
|
||||
}
|
||||
|
||||
*flagsp = flags;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_set_flags --
|
||||
* DB->set_flags.
|
||||
*
|
||||
* PUBLIC: int __db_set_flags __P((DB *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_set_flags(dbp, flags)
|
||||
DB *dbp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* The hash access method only takes two flags: DB_DUP and DB_DUPSORT.
|
||||
* The Btree access method uses them for the same purposes, and so we
|
||||
* resolve them there.
|
||||
*
|
||||
* The queue access method takes no flags.
|
||||
*/
|
||||
if (LF_ISSET(DB_ENCRYPT)) {
|
||||
if (!CRYPTO_ON(dbp->dbenv)) {
|
||||
__db_err(dbp->dbenv,
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
if (LF_ISSET(DB_ENCRYPT) && !CRYPTO_ON(dbenv)) {
|
||||
__db_err(dbenv,
|
||||
"Database environment not configured for encryption");
|
||||
return (EINVAL);
|
||||
}
|
||||
F_SET(dbp, DB_AM_ENCRYPT);
|
||||
F_SET(dbp, DB_AM_CHKSUM);
|
||||
LF_CLR(DB_ENCRYPT);
|
||||
}
|
||||
if (LF_ISSET(DB_CHKSUM_SHA1)) {
|
||||
F_SET(dbp, DB_AM_CHKSUM);
|
||||
LF_CLR(DB_CHKSUM_SHA1);
|
||||
return (EINVAL);
|
||||
}
|
||||
if (LF_ISSET(DB_TXN_NOT_DURABLE))
|
||||
ENV_REQUIRES_CONFIG(dbenv,
|
||||
dbenv->tx_handle, "DB_NOT_DURABLE", DB_INIT_TXN);
|
||||
|
||||
__db_map_flags(dbp, &flags, &dbp->flags);
|
||||
|
||||
if ((ret = __bam_set_flags(dbp, &flags)) != 0)
|
||||
return (ret);
|
||||
if ((ret = __ram_set_flags(dbp, &flags)) != 0)
|
||||
return (ret);
|
||||
#ifdef HAVE_QUEUE
|
||||
if ((ret = __qam_set_flags(dbp, &flags)) != 0)
|
||||
return (ret);
|
||||
#endif
|
||||
|
||||
return (flags == 0 ? 0 : __db_ferr(dbp->dbenv, "DB->set_flags", 0));
|
||||
return (flags == 0 ? 0 : __db_ferr(dbenv, "DB->set_flags", 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_get_lorder --
|
||||
* Get whether lorder is swapped or not.
|
||||
*
|
||||
* PUBLIC: int __db_get_lorder __P((DB *, int *));
|
||||
*/
|
||||
int
|
||||
__db_get_lorder(dbp, db_lorderp)
|
||||
DB *dbp;
|
||||
int *db_lorderp;
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Flag if the specified byte order requires swapping. */
|
||||
switch (ret = __db_byteorder(dbp->dbenv, 1234)) {
|
||||
case 0:
|
||||
*db_lorderp = F_ISSET(dbp, DB_AM_SWAP) ? 4321 : 1234;
|
||||
break;
|
||||
case DB_SWAPBYTES:
|
||||
*db_lorderp = F_ISSET(dbp, DB_AM_SWAP) ? 1234 : 4321;
|
||||
break;
|
||||
default:
|
||||
return (ret);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -519,7 +713,7 @@ __db_set_lorder(dbp, db_lorder)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_lorder");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_lorder");
|
||||
|
||||
/* Flag if the specified byte order requires swapping. */
|
||||
switch (ret = __db_byteorder(dbp->dbenv, db_lorder)) {
|
||||
@@ -543,19 +737,57 @@ __db_set_alloc(dbp, mal_func, real_func, free_func)
|
||||
void *(*real_func) __P((void *, size_t));
|
||||
void (*free_func) __P((void *));
|
||||
{
|
||||
DB_ILLEGAL_IN_ENV(dbp, "set_alloc");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_alloc");
|
||||
DB_ILLEGAL_IN_ENV(dbp, "DB->set_alloc");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_alloc");
|
||||
|
||||
return (dbp->dbenv->set_alloc(dbp->dbenv,
|
||||
mal_func, real_func, free_func));
|
||||
return (__dbenv_set_alloc(dbp->dbenv, mal_func, real_func, free_func));
|
||||
}
|
||||
|
||||
static void
|
||||
__db_set_msgcall(dbp, msgcall)
|
||||
DB *dbp;
|
||||
void (*msgcall) __P((const DB_ENV *, const char *));
|
||||
{
|
||||
__dbenv_set_msgcall(dbp->dbenv, msgcall);
|
||||
}
|
||||
|
||||
static void
|
||||
__db_get_msgfile(dbp, msgfilep)
|
||||
DB *dbp;
|
||||
FILE **msgfilep;
|
||||
{
|
||||
__dbenv_get_msgfile(dbp->dbenv, msgfilep);
|
||||
}
|
||||
|
||||
static void
|
||||
__db_set_msgfile(dbp, msgfile)
|
||||
DB *dbp;
|
||||
FILE *msgfile;
|
||||
{
|
||||
__dbenv_set_msgfile(dbp->dbenv, msgfile);
|
||||
}
|
||||
|
||||
static int
|
||||
__db_get_pagesize(dbp, db_pagesizep)
|
||||
DB *dbp;
|
||||
u_int32_t *db_pagesizep;
|
||||
{
|
||||
*db_pagesizep = dbp->pgsize;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_set_pagesize --
|
||||
* DB->set_pagesize
|
||||
*
|
||||
* PUBLIC: int __db_set_pagesize __P((DB *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_set_pagesize(dbp, db_pagesize)
|
||||
DB *dbp;
|
||||
u_int32_t db_pagesize;
|
||||
{
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "set_pagesize");
|
||||
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_pagesize");
|
||||
|
||||
if (db_pagesize < DB_MIN_PGSIZE) {
|
||||
__db_err(dbp->dbenv, "page sizes may not be smaller than %lu",
|
||||
@@ -592,27 +824,7 @@ __db_set_paniccall(dbp, paniccall)
|
||||
DB *dbp;
|
||||
void (*paniccall) __P((DB_ENV *, int));
|
||||
{
|
||||
return (dbp->dbenv->set_paniccall(dbp->dbenv, paniccall));
|
||||
}
|
||||
|
||||
static int
|
||||
__db_stat_fail(dbp, sp, flags)
|
||||
DB *dbp;
|
||||
void *sp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
COMPQUIET(sp, NULL);
|
||||
COMPQUIET(flags, 0);
|
||||
|
||||
/*
|
||||
* DB->stat isn't initialized until the actual DB->open call,
|
||||
* but we don't want to core dump.
|
||||
*/
|
||||
PANIC_CHECK(dbp->dbenv);
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
|
||||
|
||||
/* NOTREACHED */
|
||||
return (EINVAL);
|
||||
return (__dbenv_set_paniccall(dbp->dbenv, paniccall));
|
||||
}
|
||||
|
||||
#ifdef HAVE_RPC
|
||||
@@ -642,9 +854,12 @@ __dbcl_init(dbp, dbenv, flags)
|
||||
dbp->fd = __dbcl_db_fd;
|
||||
dbp->get = __dbcl_db_get;
|
||||
dbp->get_byteswapped = __db_get_byteswapped;
|
||||
dbp->get_transactional = __db_get_transactional;
|
||||
dbp->get_type = __db_get_type;
|
||||
dbp->join = __dbcl_db_join;
|
||||
dbp->key_range = __dbcl_db_key_range;
|
||||
dbp->get_dbname = __dbcl_db_get_name;
|
||||
dbp->get_open_flags = __dbcl_db_get_open_flags;
|
||||
dbp->open = __dbcl_db_open_wrap;
|
||||
dbp->pget = __dbcl_db_pget;
|
||||
dbp->put = __dbcl_db_put;
|
||||
@@ -652,16 +867,22 @@ __dbcl_init(dbp, dbenv, flags)
|
||||
dbp->rename = __dbcl_db_rename;
|
||||
dbp->set_alloc = __dbcl_db_alloc;
|
||||
dbp->set_append_recno = __dbcl_db_set_append_recno;
|
||||
dbp->get_cachesize = __dbcl_db_get_cachesize;
|
||||
dbp->set_cachesize = __dbcl_db_cachesize;
|
||||
dbp->set_cache_priority = __dbcl_db_cache_priority;
|
||||
dbp->set_dup_compare = __dbcl_db_dup_compare;
|
||||
dbp->get_encrypt_flags = __dbcl_db_get_encrypt_flags;
|
||||
dbp->set_encrypt = __dbcl_db_encrypt;
|
||||
dbp->set_errcall = __db_set_errcall;
|
||||
dbp->get_errfile = __db_get_errfile;
|
||||
dbp->set_errfile = __db_set_errfile;
|
||||
dbp->get_errpfx = __db_get_errpfx;
|
||||
dbp->set_errpfx = __db_set_errpfx;
|
||||
dbp->set_feedback = __dbcl_db_feedback;
|
||||
dbp->get_flags = __dbcl_db_get_flags;
|
||||
dbp->set_flags = __dbcl_db_flags;
|
||||
dbp->get_lorder = __dbcl_db_get_lorder;
|
||||
dbp->set_lorder = __dbcl_db_lorder;
|
||||
dbp->get_pagesize = __dbcl_db_get_pagesize;
|
||||
dbp->set_pagesize = __dbcl_db_pagesize;
|
||||
dbp->set_paniccall = __dbcl_db_panic;
|
||||
dbp->stat = __dbcl_db_stat;
|
||||
@@ -675,15 +896,23 @@ __dbcl_init(dbp, dbenv, flags)
|
||||
*/
|
||||
dbp->set_bt_compare = __dbcl_db_bt_compare;
|
||||
dbp->set_bt_maxkey = __dbcl_db_bt_maxkey;
|
||||
dbp->get_bt_minkey = __dbcl_db_get_bt_minkey;
|
||||
dbp->set_bt_minkey = __dbcl_db_bt_minkey;
|
||||
dbp->set_bt_prefix = __dbcl_db_bt_prefix;
|
||||
dbp->get_h_ffactor = __dbcl_db_get_h_ffactor;
|
||||
dbp->set_h_ffactor = __dbcl_db_h_ffactor;
|
||||
dbp->set_h_hash = __dbcl_db_h_hash;
|
||||
dbp->get_h_nelem = __dbcl_db_get_h_nelem;
|
||||
dbp->set_h_nelem = __dbcl_db_h_nelem;
|
||||
dbp->get_q_extentsize = __dbcl_db_get_extentsize;
|
||||
dbp->set_q_extentsize = __dbcl_db_extentsize;
|
||||
dbp->get_re_delim = __dbcl_db_get_re_delim;
|
||||
dbp->set_re_delim = __dbcl_db_re_delim;
|
||||
dbp->get_re_len = __dbcl_db_get_re_len;
|
||||
dbp->set_re_len = __dbcl_db_re_len;
|
||||
dbp->get_re_pad = __dbcl_db_get_re_pad;
|
||||
dbp->set_re_pad = __dbcl_db_re_pad;
|
||||
dbp->get_re_source = __dbcl_db_get_re_source;
|
||||
dbp->set_re_source = __dbcl_db_re_source;
|
||||
|
||||
return (__dbcl_db_create(dbp, dbenv, flags));
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_open.c,v 11.240 2004/09/22 20:53:19 margo Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_open.c,v 11.215 2002/08/15 15:27:52 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
@@ -30,50 +27,49 @@ static const char revid[] = "$Id: db_open.c,v 11.215 2002/08/15 15:27:52 bostic
|
||||
#include "dbinc/hash.h"
|
||||
#include "dbinc/lock.h"
|
||||
#include "dbinc/log.h"
|
||||
#include "dbinc/mp.h"
|
||||
#include "dbinc/qam.h"
|
||||
#include "dbinc/txn.h"
|
||||
|
||||
static int __db_openchk __P((DB *,
|
||||
DB_TXN *, const char *, const char *, DBTYPE, u_int32_t));
|
||||
|
||||
/*
|
||||
* __db_open --
|
||||
* Main library interface to the DB access methods.
|
||||
* DB->open method.
|
||||
*
|
||||
* This routine gets called in three different ways:
|
||||
*
|
||||
* 1. It can be called to open a file/database. In this case, subdb will
|
||||
* be NULL and meta_pgno will be PGNO_BASE_MD.
|
||||
* 2. It can be called to open a subdatabase during normal operation. In
|
||||
* this case, name and subname will both be non-NULL and meta_pgno will
|
||||
* be PGNO_BASE_MD (also PGNO_INVALID).
|
||||
* 3. It can be called during recovery to open a file/database, in which case
|
||||
* name will be non-NULL, subname will be NULL, and meta-pgno will be
|
||||
* PGNO_BASE_MD.
|
||||
* 4. It can be called during recovery to open a subdatabase, in which case
|
||||
* name will be non-NULL, subname may be NULL and meta-pgno will be
|
||||
* a valid pgno (i.e., not PGNO_BASE_MD).
|
||||
*
|
||||
* PUBLIC: int __db_open __P((DB *, DB_TXN *,
|
||||
* PUBLIC: const char *, const char *, DBTYPE, u_int32_t, int));
|
||||
* PUBLIC: const char *, const char *, DBTYPE, u_int32_t, int, db_pgno_t));
|
||||
*/
|
||||
int
|
||||
__db_open(dbp, txn, name, subdb, type, flags, mode)
|
||||
__db_open(dbp, txn, fname, dname, type, flags, mode, meta_pgno)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
const char *name, *subdb;
|
||||
const char *fname, *dname;
|
||||
DBTYPE type;
|
||||
u_int32_t flags;
|
||||
int mode;
|
||||
db_pgno_t meta_pgno;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int remove_master, remove_me, ret, t_ret, txn_local;
|
||||
int ret;
|
||||
u_int32_t id;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
remove_me = remove_master = txn_local = 0;
|
||||
id = TXN_INVALID;
|
||||
|
||||
PANIC_CHECK(dbenv);
|
||||
|
||||
if ((ret = __db_openchk(dbp, txn, name, subdb, type, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* Create local transaction as necessary, check for consistent
|
||||
* transaction usage.
|
||||
*/
|
||||
if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
|
||||
if ((ret = __db_txn_auto(dbp, &txn)) != 0)
|
||||
return (ret);
|
||||
txn_local = 1;
|
||||
} else
|
||||
if (txn != NULL && !TXN_ON(dbenv))
|
||||
return (__db_not_txn_env(dbenv));
|
||||
DB_TEST_RECOVERY(dbp, DB_TEST_PREOPEN, ret, fname);
|
||||
|
||||
/*
|
||||
* If the environment was configured with threads, the DB handle
|
||||
@@ -92,123 +88,21 @@ __db_open(dbp, txn, name, subdb, type, flags, mode)
|
||||
if (LF_ISSET(DB_DIRTY_READ))
|
||||
F_SET(dbp, DB_AM_DIRTY);
|
||||
|
||||
if (txn != NULL)
|
||||
F_SET(dbp, DB_AM_TXN);
|
||||
|
||||
/* Fill in the type. */
|
||||
dbp->type = type;
|
||||
|
||||
/*
|
||||
* If we're opening a subdatabase, we have to open (and potentially
|
||||
* create) the main database, and then get (and potentially store)
|
||||
* our base page number in that database. Then, we can finally open
|
||||
* the subdatabase.
|
||||
*/
|
||||
if ((ret = __db_dbopen(
|
||||
dbp, txn, name, subdb, flags, mode, PGNO_BASE_MD)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* You can open the database that describes the subdatabases in the
|
||||
* rest of the file read-only. The content of each key's data is
|
||||
* unspecified and applications should never be adding new records
|
||||
* or updating existing records. However, during recovery, we need
|
||||
* to open these databases R/W so we can redo/undo changes in them.
|
||||
* Likewise, we need to open master databases read/write during
|
||||
* rename and remove so we can be sure they're fully sync'ed, so
|
||||
* we provide an override flag for the purpose.
|
||||
*/
|
||||
if (subdb == NULL && !IS_RECOVERING(dbenv) && !LF_ISSET(DB_RDONLY) &&
|
||||
!LF_ISSET(DB_RDWRMASTER) && F_ISSET(dbp, DB_AM_SUBDB)) {
|
||||
__db_err(dbenv,
|
||||
"files containing multiple databases may only be opened read-only");
|
||||
ret = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
err: /* If we were successful, don't discard the file on close. */
|
||||
if (ret == 0)
|
||||
/* If we were successful, don't discard the file on close. */
|
||||
F_CLR(dbp, DB_AM_DISCARD | DB_AM_CREATED | DB_AM_CREATED_MSTR);
|
||||
else {
|
||||
/*
|
||||
* If we are not transactional, we need to remove the
|
||||
* databases/subdatabases. If we are transactional, then
|
||||
* the abort of the child transaction should take care of
|
||||
* cleaning them up.
|
||||
*/
|
||||
remove_me = txn == NULL && F_ISSET(dbp, DB_AM_CREATED);
|
||||
remove_master = txn == NULL && F_ISSET(dbp, DB_AM_CREATED_MSTR);
|
||||
|
||||
/*
|
||||
* If we had an error, it may have happened before or after
|
||||
* we actually logged the open. If it happened before, then
|
||||
* abort won't know anything about it and won't close or
|
||||
* refresh the dbp, so we need to do it explicitly.
|
||||
*/
|
||||
(void)__db_refresh(dbp, txn, DB_NOSYNC);
|
||||
}
|
||||
|
||||
/* Remove anyone we created. */
|
||||
if (remove_master || (subdb == NULL && remove_me))
|
||||
/* Remove file. */
|
||||
(void)dbenv->dbremove(dbenv, txn, name, NULL, 0);
|
||||
else if (remove_me)
|
||||
/* Remove subdatabase. */
|
||||
(void)dbenv->dbremove(dbenv, txn, name, subdb, 0);
|
||||
|
||||
/* Commit for DB_AUTO_COMMIT. */
|
||||
if (txn_local) {
|
||||
if (ret == 0)
|
||||
ret = txn->commit(txn, 0);
|
||||
else
|
||||
if ((t_ret = txn->abort(txn)) != 0)
|
||||
ret = __db_panic(dbenv, t_ret);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_dbopen --
|
||||
* Open a database. This routine gets called in three different ways.
|
||||
* 1. It can be called to open a file/database. In this case, subdb will
|
||||
* be NULL and meta_pgno will be PGNO_BASE_MD.
|
||||
* 2. It can be called to open a subdatabase during normal operation. In
|
||||
* this case, name and subname will both be non-NULL and meta_pgno will
|
||||
* be PGNO_BAS_MD (also PGNO_INVALID).
|
||||
* 3. It can be called during recovery to open a subdatabase in which case
|
||||
* name will be non-NULL, subname mqy be NULL and meta-pgno will be
|
||||
* a valid pgno (i.e., not PGNO_BASE_MD).
|
||||
*
|
||||
* PUBLIC: int __db_dbopen __P((DB *, DB_TXN *,
|
||||
* PUBLIC: const char *, const char *, u_int32_t, int, db_pgno_t));
|
||||
*/
|
||||
int
|
||||
__db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
const char *name, *subdb;
|
||||
u_int32_t flags;
|
||||
int mode;
|
||||
db_pgno_t meta_pgno;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int ret;
|
||||
u_int32_t id;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
id = TXN_INVALID;
|
||||
if (txn != NULL)
|
||||
F_SET(dbp, DB_AM_TXN);
|
||||
|
||||
DB_TEST_RECOVERY(dbp, DB_TEST_PREOPEN, ret, name);
|
||||
/*
|
||||
* If name is NULL, it's always a create, so make sure that we
|
||||
* If fname is NULL, it's always a create, so make sure that we
|
||||
* have a type specified. It would be nice if this checking
|
||||
* were done in __db_open where most of the interface checking
|
||||
* is done, but this interface (__db_dbopen) is used by the
|
||||
* recovery and limbo system, so we need to safeguard this
|
||||
* interface as well.
|
||||
*/
|
||||
if (name == NULL) {
|
||||
if (fname == NULL) {
|
||||
F_SET(dbp, DB_AM_INMEM);
|
||||
|
||||
if (dbp->type == DB_UNKNOWN) {
|
||||
@@ -235,17 +129,17 @@ __db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
|
||||
* Store the locker in the file id structure -- we can get it
|
||||
* from there as necessary, and it saves having two copies.
|
||||
*/
|
||||
if (LOCKING_ON(dbenv) && (ret = dbenv->lock_id(dbenv,
|
||||
(u_int32_t *)dbp->fileid)) != 0)
|
||||
if (LOCKING_ON(dbenv) &&
|
||||
(ret = __lock_id(dbenv, (u_int32_t *)dbp->fileid)) != 0)
|
||||
return (ret);
|
||||
} else if (subdb == NULL && meta_pgno == PGNO_BASE_MD) {
|
||||
} else if (dname == NULL && meta_pgno == PGNO_BASE_MD) {
|
||||
/* Open/create the underlying file. Acquire locks. */
|
||||
if ((ret =
|
||||
__fop_file_setup(dbp, txn, name, mode, flags, &id)) != 0)
|
||||
__fop_file_setup(dbp, txn, fname, mode, flags, &id)) != 0)
|
||||
return (ret);
|
||||
} else {
|
||||
if ((ret = __fop_subdb_setup(dbp,
|
||||
txn, name, subdb, mode, flags)) != 0)
|
||||
txn, fname, dname, mode, flags)) != 0)
|
||||
return (ret);
|
||||
meta_pgno = dbp->meta_pgno;
|
||||
}
|
||||
@@ -261,13 +155,13 @@ __db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
|
||||
* opened and updated the master using access method interfaces,
|
||||
* so we don't want to get rid of any pages that are in the mpool.
|
||||
* If we created the file when we opened the master, we already hit
|
||||
* this check in a non-subdb context then.
|
||||
* this check in a non-subdatabase context then.
|
||||
*/
|
||||
if (subdb == NULL && F_ISSET(dbp, DB_AM_CREATED))
|
||||
if (dname == NULL && F_ISSET(dbp, DB_AM_CREATED))
|
||||
LF_SET(DB_TRUNCATE);
|
||||
|
||||
/* Set up the underlying environment. */
|
||||
if ((ret = __db_dbenv_setup(dbp, txn, name, id, flags)) != 0)
|
||||
if ((ret = __db_dbenv_setup(dbp, txn, fname, id, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
@@ -283,21 +177,21 @@ __db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
|
||||
* For unnamed files, we need to actually create the file now
|
||||
* that the mpool is open.
|
||||
*/
|
||||
if (name == NULL && (ret = __db_new_file(dbp, txn, NULL, NULL)) != 0)
|
||||
if (fname == NULL && (ret = __db_new_file(dbp, txn, NULL, NULL)) != 0)
|
||||
return (ret);
|
||||
|
||||
switch (dbp->type) {
|
||||
case DB_BTREE:
|
||||
ret = __bam_open(dbp, txn, name, meta_pgno, flags);
|
||||
ret = __bam_open(dbp, txn, fname, meta_pgno, flags);
|
||||
break;
|
||||
case DB_HASH:
|
||||
ret = __ham_open(dbp, txn, name, meta_pgno, flags);
|
||||
ret = __ham_open(dbp, txn, fname, meta_pgno, flags);
|
||||
break;
|
||||
case DB_RECNO:
|
||||
ret = __ram_open(dbp, txn, name, meta_pgno, flags);
|
||||
ret = __ram_open(dbp, txn, fname, meta_pgno, flags);
|
||||
break;
|
||||
case DB_QUEUE:
|
||||
ret = __qam_open(dbp, txn, name, meta_pgno, mode, flags);
|
||||
ret = __qam_open(dbp, txn, fname, meta_pgno, mode, flags);
|
||||
break;
|
||||
case DB_UNKNOWN:
|
||||
return (__db_unknown_type(dbenv, "__db_dbopen", dbp->type));
|
||||
@@ -305,7 +199,7 @@ __db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
DB_TEST_RECOVERY(dbp, DB_TEST_POSTOPEN, ret, name);
|
||||
DB_TEST_RECOVERY(dbp, DB_TEST_POSTOPEN, ret, fname);
|
||||
|
||||
/*
|
||||
* Unnamed files don't need handle locks, so we only have to check
|
||||
@@ -313,7 +207,7 @@ __db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
|
||||
* files.
|
||||
*/
|
||||
if (!F_ISSET(dbp, DB_AM_RECOVER) &&
|
||||
name != NULL && LOCK_ISSET(dbp->handle_lock)) {
|
||||
fname != NULL && LOCK_ISSET(dbp->handle_lock)) {
|
||||
if (txn != NULL) {
|
||||
ret = __txn_lockevent(dbenv,
|
||||
txn, dbp, &dbp->handle_lock, dbp->lid);
|
||||
@@ -327,6 +221,23 @@ err:
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_get_open_flags --
|
||||
* Accessor for flags passed into DB->open call
|
||||
*
|
||||
* PUBLIC: int __db_get_open_flags __P((DB *, u_int32_t *));
|
||||
*/
|
||||
int
|
||||
__db_get_open_flags(dbp, flagsp)
|
||||
DB *dbp;
|
||||
u_int32_t *flagsp;
|
||||
{
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_open_flags");
|
||||
|
||||
*flagsp = dbp->open_flags;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_new_file --
|
||||
* Create a new database file.
|
||||
@@ -353,6 +264,7 @@ __db_new_file(dbp, txn, fhp, name)
|
||||
case DB_QUEUE:
|
||||
ret = __qam_new_file(dbp, txn, fhp, name);
|
||||
break;
|
||||
case DB_UNKNOWN:
|
||||
default:
|
||||
__db_err(dbp->dbenv,
|
||||
"%s: Invalid type %d specified", name, dbp->type);
|
||||
@@ -391,10 +303,10 @@ __db_init_subdb(mdbp, dbp, name, txn)
|
||||
if (!F_ISSET(dbp, DB_AM_CREATED)) {
|
||||
/* Subdb exists; read meta-data page and initialize. */
|
||||
mpf = mdbp->mpf;
|
||||
if ((ret = mpf->get(mpf, &dbp->meta_pgno, 0, &meta)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &dbp->meta_pgno, 0, &meta)) != 0)
|
||||
goto err;
|
||||
ret = __db_meta_setup(mdbp->dbenv, dbp, name, meta, 0, 0);
|
||||
if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
|
||||
if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
/*
|
||||
* If __db_meta_setup found that the meta-page hadn't
|
||||
@@ -417,6 +329,7 @@ __db_init_subdb(mdbp, dbp, name, txn)
|
||||
case DB_QUEUE:
|
||||
ret = EINVAL;
|
||||
break;
|
||||
case DB_UNKNOWN:
|
||||
default:
|
||||
__db_err(dbp->dbenv,
|
||||
"Invalid subdatabase type %d specified", dbp->type);
|
||||
@@ -442,7 +355,8 @@ __db_chk_meta(dbenv, dbp, meta, do_metachk)
|
||||
DBMETA *meta;
|
||||
int do_metachk;
|
||||
{
|
||||
int is_hmac, ret;
|
||||
int is_hmac, ret, swapped;
|
||||
u_int32_t orig_chk;
|
||||
u_int8_t *chksum;
|
||||
|
||||
ret = 0;
|
||||
@@ -453,11 +367,34 @@ __db_chk_meta(dbenv, dbp, meta, do_metachk)
|
||||
|
||||
is_hmac = meta->encrypt_alg == 0 ? 0 : 1;
|
||||
chksum = ((BTMETA *)meta)->chksum;
|
||||
if (do_metachk && ((ret = __db_check_chksum(dbenv,
|
||||
(DB_CIPHER *)dbenv->crypto_handle, chksum, meta,
|
||||
DBMETASIZE, is_hmac)) != 0))
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we need to swap, the checksum function overwrites the
|
||||
* original checksum with 0, so we need to save a copy of the
|
||||
* original for swapping later.
|
||||
*/
|
||||
orig_chk = *(u_int32_t *)chksum;
|
||||
|
||||
/*
|
||||
* We cannot add this to __db_metaswap because that gets done
|
||||
* later after we've verified the checksum or decrypted.
|
||||
*/
|
||||
if (do_metachk) {
|
||||
swapped = 0;
|
||||
chk_retry: if ((ret = __db_check_chksum(dbenv,
|
||||
(DB_CIPHER *)dbenv->crypto_handle, chksum, meta,
|
||||
DBMETASIZE, is_hmac)) != 0) {
|
||||
if (is_hmac || swapped)
|
||||
return (ret);
|
||||
|
||||
M_32_SWAP(orig_chk);
|
||||
swapped = 1;
|
||||
*(u_int32_t *)chksum = orig_chk;
|
||||
goto chk_retry;
|
||||
}
|
||||
}
|
||||
} else if (dbp != NULL)
|
||||
F_CLR(dbp, DB_AM_CHKSUM);
|
||||
|
||||
#ifdef HAVE_CRYPTO
|
||||
ret = __crypto_decrypt_meta(dbenv, dbp, (u_int8_t *)meta, do_metachk);
|
||||
@@ -544,6 +481,10 @@ swap_retry:
|
||||
|
||||
switch (magic) {
|
||||
case DB_BTREEMAGIC:
|
||||
if (dbp->type != DB_UNKNOWN &&
|
||||
dbp->type != DB_RECNO && dbp->type != DB_BTREE)
|
||||
goto bad_format;
|
||||
|
||||
flags = meta->flags;
|
||||
if (F_ISSET(dbp, DB_AM_SWAP))
|
||||
M_32_SWAP(flags);
|
||||
@@ -556,12 +497,17 @@ swap_retry:
|
||||
return (ret);
|
||||
break;
|
||||
case DB_HASHMAGIC:
|
||||
if (dbp->type != DB_UNKNOWN && dbp->type != DB_HASH)
|
||||
goto bad_format;
|
||||
|
||||
dbp->type = DB_HASH;
|
||||
if ((oflags & DB_TRUNCATE) == 0 && (ret =
|
||||
__ham_metachk(dbp, name, (HMETA *)meta)) != 0)
|
||||
return (ret);
|
||||
break;
|
||||
case DB_QAMMAGIC:
|
||||
if (dbp->type != DB_UNKNOWN && dbp->type != DB_QUEUE)
|
||||
goto bad_format;
|
||||
dbp->type = DB_QUEUE;
|
||||
if ((oflags & DB_TRUNCATE) == 0 && (ret =
|
||||
__qam_metachk(dbp, name, (QMETA *)meta)) != 0)
|
||||
@@ -569,135 +515,20 @@ swap_retry:
|
||||
break;
|
||||
case DB_RENAMEMAGIC:
|
||||
F_SET(dbp, DB_AM_IN_RENAME);
|
||||
|
||||
/* Copy the file's ID. */
|
||||
memcpy(dbp->fileid, ((DBMETA *)meta)->uid, DB_FILE_ID_LEN);
|
||||
|
||||
break;
|
||||
default:
|
||||
goto bad_format;
|
||||
}
|
||||
return (0);
|
||||
|
||||
bad_format:
|
||||
__db_err(dbenv, "%s: unexpected file type or format", name);
|
||||
if (F_ISSET(dbp, DB_AM_RECOVER))
|
||||
ret = ENOENT;
|
||||
else
|
||||
__db_err(dbenv, "%s: unexpected file type or format", name);
|
||||
return (ret == 0 ? EINVAL : ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_openchk --
|
||||
* Interface error checking for open calls.
|
||||
*/
|
||||
static int
|
||||
__db_openchk(dbp, txn, name, subdb, type, flags)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
const char *name, *subdb;
|
||||
DBTYPE type;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int ret;
|
||||
u_int32_t ok_flags;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
/* Validate arguments. */
|
||||
#define OKFLAGS \
|
||||
(DB_AUTO_COMMIT | DB_CREATE | DB_DIRTY_READ | DB_EXCL | \
|
||||
DB_FCNTL_LOCKING | DB_NOMMAP | DB_RDONLY | DB_RDWRMASTER | \
|
||||
DB_THREAD | DB_TRUNCATE | DB_WRITEOPEN)
|
||||
if ((ret = __db_fchk(dbenv, "DB->open", flags, OKFLAGS)) != 0)
|
||||
return (ret);
|
||||
if (LF_ISSET(DB_EXCL) && !LF_ISSET(DB_CREATE))
|
||||
return (__db_ferr(dbenv, "DB->open", 1));
|
||||
if (LF_ISSET(DB_RDONLY) && LF_ISSET(DB_CREATE))
|
||||
return (__db_ferr(dbenv, "DB->open", 1));
|
||||
|
||||
#ifdef HAVE_VXWORKS
|
||||
if (LF_ISSET(DB_TRUNCATE)) {
|
||||
__db_err(dbenv, "DB_TRUNCATE unsupported in VxWorks");
|
||||
return (__db_eopnotsup(dbenv));
|
||||
}
|
||||
#endif
|
||||
switch (type) {
|
||||
case DB_UNKNOWN:
|
||||
if (LF_ISSET(DB_CREATE|DB_TRUNCATE)) {
|
||||
__db_err(dbenv,
|
||||
"%s: DB_UNKNOWN type specified with DB_CREATE or DB_TRUNCATE",
|
||||
name);
|
||||
return (EINVAL);
|
||||
}
|
||||
ok_flags = 0;
|
||||
break;
|
||||
case DB_BTREE:
|
||||
ok_flags = DB_OK_BTREE;
|
||||
break;
|
||||
case DB_HASH:
|
||||
ok_flags = DB_OK_HASH;
|
||||
break;
|
||||
case DB_QUEUE:
|
||||
ok_flags = DB_OK_QUEUE;
|
||||
break;
|
||||
case DB_RECNO:
|
||||
ok_flags = DB_OK_RECNO;
|
||||
break;
|
||||
default:
|
||||
__db_err(dbenv, "unknown type: %lu", (u_long)type);
|
||||
return (EINVAL);
|
||||
}
|
||||
if (ok_flags)
|
||||
DB_ILLEGAL_METHOD(dbp, ok_flags);
|
||||
|
||||
/* The environment may have been created, but never opened. */
|
||||
if (!F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_OPEN_CALLED)) {
|
||||
__db_err(dbenv, "environment not yet opened");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Historically, you could pass in an environment that didn't have a
|
||||
* mpool, and DB would create a private one behind the scenes. This
|
||||
* no longer works.
|
||||
*/
|
||||
if (!F_ISSET(dbenv, DB_ENV_DBLOCAL) && !MPOOL_ON(dbenv)) {
|
||||
__db_err(dbenv, "environment did not include a memory pool");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* You can't specify threads during DB->open if subsystems in the
|
||||
* environment weren't configured with them.
|
||||
*/
|
||||
if (LF_ISSET(DB_THREAD) &&
|
||||
!F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_THREAD)) {
|
||||
__db_err(dbenv, "environment not created using DB_THREAD");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/* DB_TRUNCATE is not transaction recoverable. */
|
||||
if (LF_ISSET(DB_TRUNCATE) && txn != NULL) {
|
||||
__db_err(dbenv,
|
||||
"DB_TRUNCATE illegal with transaction specified");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/* Subdatabase checks. */
|
||||
if (subdb != NULL) {
|
||||
/* Subdatabases must be created in named files. */
|
||||
if (name == NULL) {
|
||||
__db_err(dbenv,
|
||||
"multiple databases cannot be created in temporary files");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/* Truncate is a physical file operation */
|
||||
if (LF_ISSET(DB_TRUNCATE)) {
|
||||
__db_err(dbenv,
|
||||
"DB_TRUNCATE illegal with multiple databases");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/* QAM can't be done as a subdatabase. */
|
||||
if (type == DB_QUEUE) {
|
||||
__db_err(dbenv, "Queue databases must be one-per-file");
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@@ -38,14 +38,12 @@
|
||||
* 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_overflow.c,v 11.54 2004/03/28 17:17:50 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_overflow.c,v 11.46 2002/08/08 03:57:48 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -54,8 +52,9 @@ static const char revid[] = "$Id: db_overflow.c,v 11.46 2002/08/08 03:57:48 bost
|
||||
|
||||
#include "db_int.h"
|
||||
#include "dbinc/db_page.h"
|
||||
#include "dbinc/db_shash.h"
|
||||
#include "dbinc/db_am.h"
|
||||
#include "dbinc/db_verify.h"
|
||||
#include "dbinc/mp.h"
|
||||
|
||||
/*
|
||||
* Big key/data code.
|
||||
@@ -116,7 +115,7 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
|
||||
if (F_ISSET(dbt, DB_DBT_USERMEM)) {
|
||||
if (needed > dbt->ulen) {
|
||||
dbt->size = needed;
|
||||
return (ENOMEM);
|
||||
return (DB_BUFFER_SMALL);
|
||||
}
|
||||
} else if (F_ISSET(dbt, DB_DBT_MALLOC)) {
|
||||
if ((ret = __os_umalloc(dbenv, needed, &dbt->data)) != 0)
|
||||
@@ -124,13 +123,20 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
|
||||
} else if (F_ISSET(dbt, DB_DBT_REALLOC)) {
|
||||
if ((ret = __os_urealloc(dbenv, needed, &dbt->data)) != 0)
|
||||
return (ret);
|
||||
} else if (*bpsz == 0 || *bpsz < needed) {
|
||||
} else if (bpsz != NULL && (*bpsz == 0 || *bpsz < needed)) {
|
||||
if ((ret = __os_realloc(dbenv, needed, bpp)) != 0)
|
||||
return (ret);
|
||||
*bpsz = needed;
|
||||
dbt->data = *bpp;
|
||||
} else
|
||||
} else if (bpp != NULL)
|
||||
dbt->data = *bpp;
|
||||
else {
|
||||
DB_ASSERT(
|
||||
F_ISSET(dbt,
|
||||
DB_DBT_USERMEM | DB_DBT_MALLOC | DB_DBT_REALLOC) ||
|
||||
bpsz != NULL || bpp != NULL);
|
||||
return (DB_BUFFER_SMALL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Step through the linked list of pages, copying the data on each
|
||||
@@ -138,7 +144,7 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
|
||||
*/
|
||||
dbt->size = needed;
|
||||
for (curoff = 0, p = dbt->data; pgno != PGNO_INVALID && needed > 0;) {
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Check if we need any bytes from this page. */
|
||||
@@ -157,7 +163,7 @@ __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
|
||||
}
|
||||
curoff += OV_LEN(h);
|
||||
pgno = h->next_pgno;
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
(void)__memp_fput(mpf, h, 0);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -222,7 +228,7 @@ __db_poff(dbc, dbt, pgnop)
|
||||
lastp == NULL ? &null_lsn : &LSN(lastp),
|
||||
&null_lsn)) != 0) {
|
||||
if (lastp != NULL)
|
||||
(void)mpf->put(mpf,
|
||||
(void)__memp_fput(mpf,
|
||||
lastp, DB_MPOOL_DIRTY);
|
||||
lastp = pagep;
|
||||
break;
|
||||
@@ -251,12 +257,12 @@ __db_poff(dbc, dbt, pgnop)
|
||||
else {
|
||||
lastp->next_pgno = PGNO(pagep);
|
||||
pagep->prev_pgno = PGNO(lastp);
|
||||
(void)mpf->put(mpf, lastp, DB_MPOOL_DIRTY);
|
||||
(void)__memp_fput(mpf, lastp, DB_MPOOL_DIRTY);
|
||||
}
|
||||
lastp = pagep;
|
||||
}
|
||||
if (lastp != NULL &&
|
||||
(t_ret = mpf->put(mpf, lastp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
(t_ret = __memp_fput(mpf, lastp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
return (ret);
|
||||
}
|
||||
@@ -281,22 +287,20 @@ __db_ovref(dbc, pgno, adjust)
|
||||
dbp = dbc->dbp;
|
||||
mpf = dbp->mpf;
|
||||
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0) {
|
||||
__db_pgerr(dbp, pgno, ret);
|
||||
return (ret);
|
||||
}
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
|
||||
return (__db_pgerr(dbp, pgno, ret));
|
||||
|
||||
if (DBC_LOGGING(dbc)) {
|
||||
if ((ret = __db_ovref_log(dbp,
|
||||
dbc->txn, &LSN(h), 0, h->pgno, adjust, &LSN(h))) != 0) {
|
||||
(void)mpf->put(mpf, h, 0);
|
||||
(void)__memp_fput(mpf, h, 0);
|
||||
return (ret);
|
||||
}
|
||||
} else
|
||||
LSN_NOT_LOGGED(LSN(h));
|
||||
OV_REF(h) += adjust;
|
||||
|
||||
(void)mpf->put(mpf, h, DB_MPOOL_DIRTY);
|
||||
(void)__memp_fput(mpf, h, DB_MPOOL_DIRTY);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -322,10 +326,8 @@ __db_doff(dbc, pgno)
|
||||
mpf = dbp->mpf;
|
||||
|
||||
do {
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0) {
|
||||
__db_pgerr(dbp, pgno, ret);
|
||||
return (ret);
|
||||
}
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0)
|
||||
return (__db_pgerr(dbp, pgno, ret));
|
||||
|
||||
DB_ASSERT(TYPE(pagep) == P_OVERFLOW);
|
||||
/*
|
||||
@@ -333,7 +335,7 @@ __db_doff(dbc, pgno)
|
||||
* decrement the reference count and return.
|
||||
*/
|
||||
if (OV_REF(pagep) > 1) {
|
||||
(void)mpf->put(mpf, pagep, 0);
|
||||
(void)__memp_fput(mpf, pagep, 0);
|
||||
return (__db_ovref(dbc, pgno, -1));
|
||||
}
|
||||
|
||||
@@ -346,12 +348,13 @@ __db_doff(dbc, pgno)
|
||||
PGNO(pagep), PREV_PGNO(pagep),
|
||||
NEXT_PGNO(pagep), &tmp_dbt,
|
||||
&LSN(pagep), &null_lsn, &null_lsn)) != 0) {
|
||||
(void)mpf->put(mpf, pagep, 0);
|
||||
(void)__memp_fput(mpf, pagep, 0);
|
||||
return (ret);
|
||||
}
|
||||
} else
|
||||
LSN_NOT_LOGGED(LSN(pagep));
|
||||
pgno = pagep->next_pgno;
|
||||
OV_LEN(pagep) = 0;
|
||||
if ((ret = __db_free(dbc, pagep)) != 0)
|
||||
return (ret);
|
||||
} while (pgno != PGNO_INVALID);
|
||||
@@ -411,7 +414,7 @@ __db_moff(dbp, dbt, pgno, tlen, cmpfunc, cmpp)
|
||||
/* While there are both keys to compare. */
|
||||
for (*cmpp = 0, p1 = dbt->data,
|
||||
key_left = dbt->size; key_left > 0 && pgno != PGNO_INVALID;) {
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0)
|
||||
return (ret);
|
||||
|
||||
cmp_bytes = OV_LEN(pagep) < key_left ? OV_LEN(pagep) : key_left;
|
||||
@@ -424,7 +427,7 @@ __db_moff(dbp, dbt, pgno, tlen, cmpfunc, cmpp)
|
||||
break;
|
||||
}
|
||||
pgno = NEXT_PGNO(pagep);
|
||||
if ((ret = mpf->put(mpf, pagep, 0)) != 0)
|
||||
if ((ret = __memp_fput(mpf, pagep, 0)) != 0)
|
||||
return (ret);
|
||||
if (*cmpp != 0)
|
||||
return (0);
|
||||
@@ -438,289 +441,3 @@ __db_moff(dbp, dbt, pgno, tlen, cmpfunc, cmpp)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_vrfy_overflow --
|
||||
* Verify overflow page.
|
||||
*
|
||||
* PUBLIC: int __db_vrfy_overflow __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
|
||||
* PUBLIC: u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_vrfy_overflow(dbp, vdp, h, pgno, flags)
|
||||
DB *dbp;
|
||||
VRFY_DBINFO *vdp;
|
||||
PAGE *h;
|
||||
db_pgno_t pgno;
|
||||
u_int32_t flags;
|
||||
{
|
||||
VRFY_PAGEINFO *pip;
|
||||
int isbad, ret, t_ret;
|
||||
|
||||
isbad = 0;
|
||||
if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
|
||||
return (ret);
|
||||
|
||||
if ((ret = __db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) {
|
||||
if (ret == DB_VERIFY_BAD)
|
||||
isbad = 1;
|
||||
else
|
||||
goto err;
|
||||
}
|
||||
|
||||
pip->refcount = OV_REF(h);
|
||||
if (pip->refcount < 1) {
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: overflow page has zero reference count",
|
||||
(u_long)pgno));
|
||||
isbad = 1;
|
||||
}
|
||||
|
||||
/* Just store for now. */
|
||||
pip->olen = HOFFSET(h);
|
||||
|
||||
err: if ((t_ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0)
|
||||
ret = t_ret;
|
||||
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_vrfy_ovfl_structure --
|
||||
* Walk a list of overflow pages, avoiding cycles and marking
|
||||
* pages seen.
|
||||
*
|
||||
* PUBLIC: int __db_vrfy_ovfl_structure
|
||||
* PUBLIC: __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags)
|
||||
DB *dbp;
|
||||
VRFY_DBINFO *vdp;
|
||||
db_pgno_t pgno;
|
||||
u_int32_t tlen;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB *pgset;
|
||||
VRFY_PAGEINFO *pip;
|
||||
db_pgno_t next, prev;
|
||||
int isbad, p, ret, t_ret;
|
||||
u_int32_t refcount;
|
||||
|
||||
pgset = vdp->pgset;
|
||||
DB_ASSERT(pgset != NULL);
|
||||
isbad = 0;
|
||||
|
||||
/* This shouldn't happen, but just to be sure. */
|
||||
if (!IS_VALID_PGNO(pgno))
|
||||
return (DB_VERIFY_BAD);
|
||||
|
||||
/*
|
||||
* Check the first prev_pgno; it ought to be PGNO_INVALID,
|
||||
* since there's no prev page.
|
||||
*/
|
||||
if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* The refcount is stored on the first overflow page. */
|
||||
refcount = pip->refcount;
|
||||
|
||||
if (pip->type != P_OVERFLOW) {
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: overflow page of invalid type %lu",
|
||||
(u_long)pgno, (u_long)pip->type));
|
||||
ret = DB_VERIFY_BAD;
|
||||
goto err; /* Unsafe to continue. */
|
||||
}
|
||||
|
||||
prev = pip->prev_pgno;
|
||||
if (prev != PGNO_INVALID) {
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: first page in overflow chain has a prev_pgno %lu",
|
||||
(u_long)pgno, (u_long)prev));
|
||||
isbad = 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* This is slightly gross. Btree leaf pages reference
|
||||
* individual overflow trees multiple times if the overflow page
|
||||
* is the key to a duplicate set. The reference count does not
|
||||
* reflect this multiple referencing. Thus, if this is called
|
||||
* during the structure verification of a btree leaf page, we
|
||||
* check to see whether we've seen it from a leaf page before
|
||||
* and, if we have, adjust our count of how often we've seen it
|
||||
* accordingly.
|
||||
*
|
||||
* (This will screw up if it's actually referenced--and
|
||||
* correctly refcounted--from two different leaf pages, but
|
||||
* that's a very unlikely brokenness that we're not checking for
|
||||
* anyway.)
|
||||
*/
|
||||
|
||||
if (LF_ISSET(ST_OVFL_LEAF)) {
|
||||
if (F_ISSET(pip, VRFY_OVFL_LEAFSEEN)) {
|
||||
if ((ret =
|
||||
__db_vrfy_pgset_dec(pgset, pgno)) != 0)
|
||||
goto err;
|
||||
} else
|
||||
F_SET(pip, VRFY_OVFL_LEAFSEEN);
|
||||
}
|
||||
|
||||
if ((ret = __db_vrfy_pgset_get(pgset, pgno, &p)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* We may have seen this elsewhere, if the overflow entry
|
||||
* has been promoted to an internal page.
|
||||
*/
|
||||
if ((u_int32_t)p > refcount) {
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: encountered twice in overflow traversal",
|
||||
(u_long)pgno));
|
||||
ret = DB_VERIFY_BAD;
|
||||
goto err;
|
||||
}
|
||||
if ((ret = __db_vrfy_pgset_inc(pgset, pgno)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Keep a running tab on how much of the item we've seen. */
|
||||
tlen -= pip->olen;
|
||||
|
||||
/* Send feedback to the application about our progress. */
|
||||
if (!LF_ISSET(DB_SALVAGE))
|
||||
__db_vrfy_struct_feedback(dbp, vdp);
|
||||
|
||||
next = pip->next_pgno;
|
||||
|
||||
/* Are we there yet? */
|
||||
if (next == PGNO_INVALID)
|
||||
break;
|
||||
|
||||
/*
|
||||
* We've already checked this when we saved it, but just
|
||||
* to be sure...
|
||||
*/
|
||||
if (!IS_VALID_PGNO(next)) {
|
||||
DB_ASSERT(0);
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: bad next_pgno %lu on overflow page",
|
||||
(u_long)pgno, (u_long)next));
|
||||
ret = DB_VERIFY_BAD;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 ||
|
||||
(ret = __db_vrfy_getpageinfo(vdp, next, &pip)) != 0)
|
||||
return (ret);
|
||||
if (pip->prev_pgno != pgno) {
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: bad prev_pgno %lu on overflow page (should be %lu)",
|
||||
(u_long)next, (u_long)pip->prev_pgno,
|
||||
(u_long)pgno));
|
||||
isbad = 1;
|
||||
/*
|
||||
* It's safe to continue because we have separate
|
||||
* cycle detection.
|
||||
*/
|
||||
}
|
||||
|
||||
pgno = next;
|
||||
}
|
||||
|
||||
if (tlen > 0) {
|
||||
isbad = 1;
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: overflow item incomplete", (u_long)pgno));
|
||||
}
|
||||
|
||||
err: if ((t_ret =
|
||||
__db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_safe_goff --
|
||||
* Get an overflow item, very carefully, from an untrusted database,
|
||||
* in the context of the salvager.
|
||||
*
|
||||
* PUBLIC: int __db_safe_goff __P((DB *, VRFY_DBINFO *, db_pgno_t,
|
||||
* PUBLIC: DBT *, void **, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_safe_goff(dbp, vdp, pgno, dbt, buf, flags)
|
||||
DB *dbp;
|
||||
VRFY_DBINFO *vdp;
|
||||
db_pgno_t pgno;
|
||||
DBT *dbt;
|
||||
void **buf;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *h;
|
||||
int ret, t_ret;
|
||||
u_int32_t bytesgot, bytes;
|
||||
u_int8_t *src, *dest;
|
||||
|
||||
mpf = dbp->mpf;
|
||||
h = NULL;
|
||||
ret = t_ret = 0;
|
||||
bytesgot = bytes = 0;
|
||||
|
||||
while ((pgno != PGNO_INVALID) && (IS_VALID_PGNO(pgno))) {
|
||||
/*
|
||||
* Mark that we're looking at this page; if we've seen it
|
||||
* already, quit.
|
||||
*/
|
||||
if ((ret = __db_salvage_markdone(vdp, pgno)) != 0)
|
||||
break;
|
||||
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Make sure it's really an overflow page, unless we're
|
||||
* being aggressive, in which case we pretend it is.
|
||||
*/
|
||||
if (!LF_ISSET(DB_AGGRESSIVE) && TYPE(h) != P_OVERFLOW) {
|
||||
ret = DB_VERIFY_BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
src = (u_int8_t *)h + P_OVERHEAD(dbp);
|
||||
bytes = OV_LEN(h);
|
||||
|
||||
if (bytes + P_OVERHEAD(dbp) > dbp->pgsize)
|
||||
bytes = dbp->pgsize - P_OVERHEAD(dbp);
|
||||
|
||||
if ((ret = __os_realloc(dbp->dbenv,
|
||||
bytesgot + bytes, buf)) != 0)
|
||||
break;
|
||||
|
||||
dest = (u_int8_t *)*buf + bytesgot;
|
||||
bytesgot += bytes;
|
||||
|
||||
memcpy(dest, src, bytes);
|
||||
|
||||
pgno = NEXT_PGNO(h);
|
||||
|
||||
if ((ret = mpf->put(mpf, h, 0)) != 0)
|
||||
break;
|
||||
h = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're being aggressive, salvage a partial datum if there
|
||||
* was an error somewhere along the way.
|
||||
*/
|
||||
if (ret == 0 || LF_ISSET(DB_AGGRESSIVE)) {
|
||||
dbt->size = bytesgot;
|
||||
dbt->data = *buf;
|
||||
}
|
||||
|
||||
/* If we broke out on error, don't leave pages pinned. */
|
||||
if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
374
storage/bdb/db/db_ovfl_vrfy.c
Normal file
374
storage/bdb/db/db_ovfl_vrfy.c
Normal file
@@ -0,0 +1,374 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2004
|
||||
* 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: db_ovfl_vrfy.c,v 11.56 2004/01/28 03:35:57 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/db_am.h"
|
||||
#include "dbinc/db_verify.h"
|
||||
#include "dbinc/mp.h"
|
||||
|
||||
/*
|
||||
* __db_vrfy_overflow --
|
||||
* Verify overflow page.
|
||||
*
|
||||
* PUBLIC: int __db_vrfy_overflow __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
|
||||
* PUBLIC: u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_vrfy_overflow(dbp, vdp, h, pgno, flags)
|
||||
DB *dbp;
|
||||
VRFY_DBINFO *vdp;
|
||||
PAGE *h;
|
||||
db_pgno_t pgno;
|
||||
u_int32_t flags;
|
||||
{
|
||||
VRFY_PAGEINFO *pip;
|
||||
int isbad, ret, t_ret;
|
||||
|
||||
isbad = 0;
|
||||
if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
|
||||
return (ret);
|
||||
|
||||
if ((ret = __db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) {
|
||||
if (ret == DB_VERIFY_BAD)
|
||||
isbad = 1;
|
||||
else
|
||||
goto err;
|
||||
}
|
||||
|
||||
pip->refcount = OV_REF(h);
|
||||
if (pip->refcount < 1) {
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: overflow page has zero reference count",
|
||||
(u_long)pgno));
|
||||
isbad = 1;
|
||||
}
|
||||
|
||||
/* Just store for now. */
|
||||
pip->olen = HOFFSET(h);
|
||||
|
||||
err: if ((t_ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0)
|
||||
ret = t_ret;
|
||||
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_vrfy_ovfl_structure --
|
||||
* Walk a list of overflow pages, avoiding cycles and marking
|
||||
* pages seen.
|
||||
*
|
||||
* PUBLIC: int __db_vrfy_ovfl_structure
|
||||
* PUBLIC: __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags)
|
||||
DB *dbp;
|
||||
VRFY_DBINFO *vdp;
|
||||
db_pgno_t pgno;
|
||||
u_int32_t tlen;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB *pgset;
|
||||
VRFY_PAGEINFO *pip;
|
||||
db_pgno_t next, prev;
|
||||
int isbad, ret, seen_cnt, t_ret;
|
||||
u_int32_t refcount;
|
||||
|
||||
pgset = vdp->pgset;
|
||||
DB_ASSERT(pgset != NULL);
|
||||
isbad = 0;
|
||||
|
||||
/* This shouldn't happen, but just to be sure. */
|
||||
if (!IS_VALID_PGNO(pgno))
|
||||
return (DB_VERIFY_BAD);
|
||||
|
||||
/*
|
||||
* Check the first prev_pgno; it ought to be PGNO_INVALID,
|
||||
* since there's no prev page.
|
||||
*/
|
||||
if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* The refcount is stored on the first overflow page. */
|
||||
refcount = pip->refcount;
|
||||
|
||||
if (pip->type != P_OVERFLOW) {
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: overflow page of invalid type %lu",
|
||||
(u_long)pgno, (u_long)pip->type));
|
||||
ret = DB_VERIFY_BAD;
|
||||
goto err; /* Unsafe to continue. */
|
||||
}
|
||||
|
||||
prev = pip->prev_pgno;
|
||||
if (prev != PGNO_INVALID) {
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: first page in overflow chain has a prev_pgno %lu",
|
||||
(u_long)pgno, (u_long)prev));
|
||||
isbad = 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* We may have seen this page elsewhere, if the overflow entry
|
||||
* has been promoted to an internal page; we just want to
|
||||
* make sure that each overflow page is seen exactly as many
|
||||
* times as its refcount dictates.
|
||||
*
|
||||
* Note that this code also serves to keep us from looping
|
||||
* infinitely if there's a cycle in an overflow chain.
|
||||
*/
|
||||
if ((ret = __db_vrfy_pgset_get(pgset, pgno, &seen_cnt)) != 0)
|
||||
goto err;
|
||||
if ((u_int32_t)seen_cnt > refcount) {
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: encountered too many times in overflow traversal",
|
||||
(u_long)pgno));
|
||||
ret = DB_VERIFY_BAD;
|
||||
goto err;
|
||||
}
|
||||
if ((ret = __db_vrfy_pgset_inc(pgset, pgno)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Each overflow page can be referenced multiple times,
|
||||
* because it's possible for overflow Btree keys to get
|
||||
* promoted to internal pages. We want to make sure that
|
||||
* each page is referenced from a Btree leaf (or Hash data
|
||||
* page, which we consider a "leaf" here) exactly once; if
|
||||
* the parent was a leaf, set a flag to indicate that we've
|
||||
* seen this page in a leaf context.
|
||||
*
|
||||
* If the parent is not a leaf--in which case it's a Btree
|
||||
* internal page--we don't need to bother doing any further
|
||||
* verification, as we'll do it when we hit the leaf (or
|
||||
* complain that we never saw the leaf). Only the first
|
||||
* page in an overflow chain should ever have a refcount
|
||||
* greater than 1, and the combination of the LEAFSEEN check
|
||||
* and the fact that we bail after the first page for
|
||||
* non-leaves should ensure this.
|
||||
*
|
||||
* Note that each "child" of a page, such as an overflow page,
|
||||
* is stored and verified in a structure check exactly once,
|
||||
* so this code does not need to contend with the fact that
|
||||
* overflow chains used as Btree duplicate keys may be
|
||||
* referenced multiply from a single Btree leaf page.
|
||||
*/
|
||||
if (LF_ISSET(ST_OVFL_LEAF)) {
|
||||
if (F_ISSET(pip, VRFY_OVFL_LEAFSEEN)) {
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: overflow page linked twice from leaf or data page",
|
||||
(u_long)pgno));
|
||||
ret = DB_VERIFY_BAD;
|
||||
goto err;
|
||||
}
|
||||
F_SET(pip, VRFY_OVFL_LEAFSEEN);
|
||||
}
|
||||
|
||||
/*
|
||||
* We want to verify each overflow chain only once, and
|
||||
* although no chain should be linked more than once from a
|
||||
* leaf page, we can't guarantee that it'll be linked that
|
||||
* once if it's linked from an internal page and the key
|
||||
* is gone.
|
||||
*
|
||||
* seen_cnt is the number of times we'd encountered this page
|
||||
* before calling this function.
|
||||
*/
|
||||
if (seen_cnt == 0) {
|
||||
/*
|
||||
* Keep a running tab on how much of the item we've
|
||||
* seen.
|
||||
*/
|
||||
tlen -= pip->olen;
|
||||
|
||||
/* Send the application feedback about our progress. */
|
||||
if (!LF_ISSET(DB_SALVAGE))
|
||||
__db_vrfy_struct_feedback(dbp, vdp);
|
||||
} else
|
||||
goto done;
|
||||
|
||||
next = pip->next_pgno;
|
||||
|
||||
/* Are we there yet? */
|
||||
if (next == PGNO_INVALID)
|
||||
break;
|
||||
|
||||
/*
|
||||
* We've already checked this when we saved it, but just
|
||||
* to be sure...
|
||||
*/
|
||||
if (!IS_VALID_PGNO(next)) {
|
||||
DB_ASSERT(0);
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: bad next_pgno %lu on overflow page",
|
||||
(u_long)pgno, (u_long)next));
|
||||
ret = DB_VERIFY_BAD;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 ||
|
||||
(ret = __db_vrfy_getpageinfo(vdp, next, &pip)) != 0)
|
||||
return (ret);
|
||||
if (pip->prev_pgno != pgno) {
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: bad prev_pgno %lu on overflow page (should be %lu)",
|
||||
(u_long)next, (u_long)pip->prev_pgno,
|
||||
(u_long)pgno));
|
||||
isbad = 1;
|
||||
/*
|
||||
* It's safe to continue because we have separate
|
||||
* cycle detection.
|
||||
*/
|
||||
}
|
||||
|
||||
pgno = next;
|
||||
}
|
||||
|
||||
if (tlen > 0) {
|
||||
isbad = 1;
|
||||
EPRINT((dbp->dbenv,
|
||||
"Page %lu: overflow item incomplete", (u_long)pgno));
|
||||
}
|
||||
|
||||
done:
|
||||
err: if ((t_ret =
|
||||
__db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_safe_goff --
|
||||
* Get an overflow item, very carefully, from an untrusted database,
|
||||
* in the context of the salvager.
|
||||
*
|
||||
* PUBLIC: int __db_safe_goff __P((DB *, VRFY_DBINFO *, db_pgno_t,
|
||||
* PUBLIC: DBT *, void *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_safe_goff(dbp, vdp, pgno, dbt, buf, flags)
|
||||
DB *dbp;
|
||||
VRFY_DBINFO *vdp;
|
||||
db_pgno_t pgno;
|
||||
DBT *dbt;
|
||||
void *buf;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *h;
|
||||
int ret, t_ret;
|
||||
u_int32_t bytesgot, bytes;
|
||||
u_int8_t *src, *dest;
|
||||
|
||||
mpf = dbp->mpf;
|
||||
h = NULL;
|
||||
ret = t_ret = 0;
|
||||
bytesgot = bytes = 0;
|
||||
|
||||
while ((pgno != PGNO_INVALID) && (IS_VALID_PGNO(pgno))) {
|
||||
/*
|
||||
* Mark that we're looking at this page; if we've seen it
|
||||
* already, quit.
|
||||
*/
|
||||
if ((ret = __db_salvage_markdone(vdp, pgno)) != 0)
|
||||
break;
|
||||
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Make sure it's really an overflow page, unless we're
|
||||
* being aggressive, in which case we pretend it is.
|
||||
*/
|
||||
if (!LF_ISSET(DB_AGGRESSIVE) && TYPE(h) != P_OVERFLOW) {
|
||||
ret = DB_VERIFY_BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
src = (u_int8_t *)h + P_OVERHEAD(dbp);
|
||||
bytes = OV_LEN(h);
|
||||
|
||||
if (bytes + P_OVERHEAD(dbp) > dbp->pgsize)
|
||||
bytes = dbp->pgsize - P_OVERHEAD(dbp);
|
||||
|
||||
if ((ret = __os_realloc(dbp->dbenv,
|
||||
bytesgot + bytes, buf)) != 0)
|
||||
break;
|
||||
|
||||
dest = *(u_int8_t **)buf + bytesgot;
|
||||
bytesgot += bytes;
|
||||
|
||||
memcpy(dest, src, bytes);
|
||||
|
||||
pgno = NEXT_PGNO(h);
|
||||
|
||||
if ((ret = __memp_fput(mpf, h, 0)) != 0)
|
||||
break;
|
||||
h = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're being aggressive, salvage a partial datum if there
|
||||
* was an error somewhere along the way.
|
||||
*/
|
||||
if (ret == 0 || LF_ISSET(DB_AGGRESSIVE)) {
|
||||
dbt->size = bytesgot;
|
||||
dbt->data = *(void **)buf;
|
||||
}
|
||||
|
||||
/* If we broke out on error, don't leave pages pinned. */
|
||||
if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_reclaim.c,v 11.42 2004/06/10 04:46:44 ubell Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_reclaim.c,v 11.28 2002/08/06 06:11:17 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
@@ -20,7 +18,7 @@ static const char revid[] = "$Id: db_reclaim.c,v 11.28 2002/08/06 06:11:17 bosti
|
||||
#include "dbinc/db_page.h"
|
||||
#include "dbinc/db_shash.h"
|
||||
#include "dbinc/btree.h"
|
||||
#include "dbinc/lock.h"
|
||||
#include "dbinc/mp.h"
|
||||
|
||||
/*
|
||||
* __db_traverse_big
|
||||
@@ -48,12 +46,18 @@ __db_traverse_big(dbp, pgno, callback, cookie)
|
||||
|
||||
do {
|
||||
did_put = 0;
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &p)) != 0)
|
||||
if ((ret = __memp_fget(mpf, &pgno, 0, &p)) != 0)
|
||||
return (ret);
|
||||
/*
|
||||
* If we are freeing pages only process the overflow
|
||||
* chain if the head of the chain has a refcount of 1.
|
||||
*/
|
||||
pgno = NEXT_PGNO(p);
|
||||
if (callback == __db_truncate_callback && OV_REF(p) != 1)
|
||||
pgno = PGNO_INVALID;
|
||||
if ((ret = callback(dbp, p, cookie, &did_put)) == 0 &&
|
||||
!did_put)
|
||||
ret = mpf->put(mpf, p, 0);
|
||||
ret = __memp_fput(mpf, p, 0);
|
||||
} while (ret == 0 && pgno != PGNO_INVALID);
|
||||
|
||||
return (ret);
|
||||
@@ -79,8 +83,15 @@ __db_reclaim_callback(dbp, p, cookie, putp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
COMPQUIET(dbp, NULL);
|
||||
/*
|
||||
* We don't want to log the free of the root with the subdb.
|
||||
* If we abort then the subdb may not be openable to undo
|
||||
* the free.
|
||||
*/
|
||||
|
||||
if ((dbp->type == DB_BTREE || dbp->type == DB_RECNO) &&
|
||||
PGNO(p) == ((BTREE *)dbp->bt_internal)->bt_root)
|
||||
return (0);
|
||||
if ((ret = __db_free(cookie, p)) != 0)
|
||||
return (ret);
|
||||
*putp = 1;
|
||||
@@ -103,12 +114,9 @@ __db_truncate_callback(dbp, p, cookie, putp)
|
||||
void *cookie;
|
||||
int *putp;
|
||||
{
|
||||
DBMETA *meta;
|
||||
DBT ldbt;
|
||||
DB_LOCK metalock;
|
||||
DB_MPOOLFILE *mpf;
|
||||
DBT ddbt, ldbt;
|
||||
db_indx_t indx, len, off, tlen, top;
|
||||
db_pgno_t pgno;
|
||||
db_trunc_param *param;
|
||||
u_int8_t *hk, type;
|
||||
int ret;
|
||||
@@ -147,7 +155,12 @@ __db_truncate_callback(dbp, p, cookie, putp)
|
||||
*putp = 0;
|
||||
break;
|
||||
case P_LRECNO:
|
||||
param->count += top;
|
||||
for (indx = 0; indx < top; indx += O_INDX) {
|
||||
type = GET_BKEYDATA(dbp, p, indx)->type;
|
||||
if (!B_DISSET(type))
|
||||
++param->count;
|
||||
}
|
||||
|
||||
if (((BTREE *)dbp->bt_internal)->bt_root == PGNO(p)) {
|
||||
type = P_LRECNO;
|
||||
goto reinit;
|
||||
@@ -165,8 +178,8 @@ __db_truncate_callback(dbp, p, cookie, putp)
|
||||
for (indx = 0; indx < top; indx += P_INDX) {
|
||||
switch (*H_PAIRDATA(dbp, p, indx)) {
|
||||
case H_OFFDUP:
|
||||
case H_OFFPAGE:
|
||||
break;
|
||||
case H_OFFPAGE:
|
||||
case H_KEYDATA:
|
||||
++param->count;
|
||||
break;
|
||||
@@ -174,12 +187,15 @@ __db_truncate_callback(dbp, p, cookie, putp)
|
||||
tlen = LEN_HDATA(dbp, p, 0, indx);
|
||||
hk = H_PAIRDATA(dbp, p, indx);
|
||||
for (off = 0; off < tlen;
|
||||
off += len + 2 * sizeof (db_indx_t)) {
|
||||
off += len + 2 * sizeof(db_indx_t)) {
|
||||
++param->count;
|
||||
memcpy(&len,
|
||||
HKEYDATA_DATA(hk)
|
||||
+ off, sizeof(db_indx_t));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return (__db_pgfmt(dbp->dbenv, p->pgno));
|
||||
}
|
||||
}
|
||||
/* Don't free the head of the bucket. */
|
||||
@@ -188,41 +204,16 @@ __db_truncate_callback(dbp, p, cookie, putp)
|
||||
|
||||
reinit: *putp = 0;
|
||||
if (DBC_LOGGING(param->dbc)) {
|
||||
pgno = PGNO_BASE_MD;
|
||||
if ((ret = __db_lget(param->dbc, LCK_ALWAYS,
|
||||
pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
|
||||
return (ret);
|
||||
if ((ret = mpf->get(mpf,
|
||||
&pgno, 0, (PAGE **)&meta)) != 0) {
|
||||
goto err;
|
||||
}
|
||||
memset(&ldbt, 0, sizeof(ldbt));
|
||||
memset(&ddbt, 0, sizeof(ddbt));
|
||||
ldbt.data = p;
|
||||
ldbt.size = P_OVERHEAD(dbp);
|
||||
if ((ret = __db_pg_free_log(dbp,
|
||||
param->dbc->txn, &LSN(meta), 0,
|
||||
p->pgno, &LSN(meta),
|
||||
PGNO_BASE_MD, &ldbt, meta->free)) != 0)
|
||||
goto err;
|
||||
LSN(p) = LSN(meta);
|
||||
|
||||
if ((ret =
|
||||
__db_pg_alloc_log(dbp,
|
||||
param->dbc->txn, &LSN(meta), 0,
|
||||
&LSN(meta), PGNO_BASE_MD,
|
||||
&p->lsn, p->pgno, type, meta->free)) != 0) {
|
||||
err: (void)mpf->put(mpf, (PAGE *)meta, 0);
|
||||
(void)__TLPUT(param->dbc, metalock);
|
||||
return (ret);
|
||||
}
|
||||
LSN(p) = LSN(meta);
|
||||
|
||||
if ((ret = mpf->put(mpf,
|
||||
(PAGE *)meta, DB_MPOOL_DIRTY)) != 0) {
|
||||
(void)__TLPUT(param->dbc, metalock);
|
||||
return (ret);
|
||||
}
|
||||
if ((ret = __TLPUT(param->dbc, metalock)) != 0)
|
||||
ldbt.size += p->entries * sizeof(db_indx_t);
|
||||
ddbt.data = (u_int8_t *)p + p->hf_offset;
|
||||
ddbt.size = dbp->pgsize - p->hf_offset;
|
||||
if ((ret = __db_pg_init_log(dbp,
|
||||
param->dbc->txn, &LSN(p), 0,
|
||||
p->pgno, &ldbt, &ddbt)) != 0)
|
||||
return (ret);
|
||||
} else
|
||||
LSN_NOT_LOGGED(LSN(p));
|
||||
@@ -239,7 +230,7 @@ err: (void)mpf->put(mpf, (PAGE *)meta, 0);
|
||||
if ((ret = __db_free(param->dbc, p)) != 0)
|
||||
return (ret);
|
||||
} else {
|
||||
if ((ret = mpf->put(mpf, p, DB_MPOOL_DIRTY)) != 0)
|
||||
if ((ret = __memp_fput(mpf, p, DB_MPOOL_DIRTY)) != 0)
|
||||
return (ret);
|
||||
*putp = 1;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 2001-2002
|
||||
* Copyright (c) 2001-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_remove.c,v 11.219 2004/09/16 17:55:17 margo Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_remove.c,v 11.203 2002/08/19 18:34:18 margo Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -23,27 +21,25 @@ static const char revid[] = "$Id: db_remove.c,v 11.203 2002/08/19 18:34:18 margo
|
||||
#include "dbinc/db_shash.h"
|
||||
#include "dbinc/lock.h"
|
||||
|
||||
static int __db_subdb_remove __P((DB *, DB_TXN *, const char *, const char *));
|
||||
static int __db_dbtxn_remove __P((DB *, DB_TXN *, const char *));
|
||||
static int __db_subdb_remove __P((DB *, DB_TXN *, const char *, const char *));
|
||||
|
||||
/*
|
||||
* __dbenv_dbremove
|
||||
* Remove method for DB_ENV.
|
||||
* __dbenv_dbremove_pp
|
||||
* DB_ENV->dbremove pre/post processing.
|
||||
*
|
||||
* PUBLIC: int __dbenv_dbremove __P((DB_ENV *,
|
||||
* PUBLIC: int __dbenv_dbremove_pp __P((DB_ENV *,
|
||||
* PUBLIC: DB_TXN *, const char *, const char *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__dbenv_dbremove(dbenv, txn, name, subdb, flags)
|
||||
__dbenv_dbremove_pp(dbenv, txn, name, subdb, flags)
|
||||
DB_ENV *dbenv;
|
||||
DB_TXN *txn;
|
||||
const char *name, *subdb;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB *dbp;
|
||||
int ret, t_ret, txn_local;
|
||||
|
||||
txn_local = 0;
|
||||
int handle_check, ret, t_ret, txn_local;
|
||||
|
||||
PANIC_CHECK(dbenv);
|
||||
ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->dbremove");
|
||||
@@ -52,63 +48,79 @@ __dbenv_dbremove(dbenv, txn, name, subdb, flags)
|
||||
if ((ret = __db_fchk(dbenv, "DB->remove", flags, DB_AUTO_COMMIT)) != 0)
|
||||
return (ret);
|
||||
|
||||
if ((ret = db_create(&dbp, dbenv, 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* Create local transaction as necessary, check for consistent
|
||||
* transaction usage.
|
||||
*/
|
||||
if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
|
||||
if ((ret = __db_txn_auto(dbp, &txn)) != 0)
|
||||
if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
|
||||
return (ret);
|
||||
txn_local = 1;
|
||||
} else
|
||||
} else {
|
||||
if (txn != NULL && !TXN_ON(dbenv))
|
||||
return (__db_not_txn_env(dbenv));
|
||||
txn_local = 0;
|
||||
}
|
||||
|
||||
ret = __db_remove_i(dbp, txn, name, subdb);
|
||||
if ((ret = db_create(&dbp, dbenv, 0)) != 0)
|
||||
goto err;
|
||||
|
||||
handle_check = IS_REPLICATED(dbenv, dbp);
|
||||
if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, txn != NULL)) != 0)
|
||||
goto err;
|
||||
|
||||
ret = __db_remove_int(dbp, txn, name, subdb, flags);
|
||||
|
||||
/* Commit for DB_AUTO_COMMIT. */
|
||||
if (txn_local) {
|
||||
if (ret == 0)
|
||||
ret = txn->commit(txn, 0);
|
||||
else
|
||||
if ((t_ret = txn->abort(txn)) != 0)
|
||||
ret = __db_panic(dbenv, t_ret);
|
||||
/*
|
||||
* We created the DBP here and when we committed/aborted,
|
||||
* we release all the tranasctional locks, which includes
|
||||
* the handle lock; mark the handle cleared explicitly.
|
||||
* We created the DBP here and when we commit/abort, we'll
|
||||
* release all the transactional locks, including the handle
|
||||
* lock; mark the handle cleared explicitly.
|
||||
*/
|
||||
LOCK_INIT(dbp->handle_lock);
|
||||
dbp->lid = DB_LOCK_INVALIDID;
|
||||
} else if (txn != NULL) {
|
||||
/*
|
||||
* We created this handle locally so we need to close it
|
||||
* and clean it up. Unfortunately, it's holding transactional
|
||||
* locks that need to persist until the end of transaction.
|
||||
* If we invalidate the locker id (dbp->lid), then the close
|
||||
* won't free these locks prematurely.
|
||||
*/
|
||||
dbp->lid = DB_LOCK_INVALIDID;
|
||||
}
|
||||
|
||||
if (handle_check)
|
||||
__env_db_rep_exit(dbenv);
|
||||
|
||||
err: if (txn_local)
|
||||
ret = __db_txn_auto_resolve(dbenv, txn, 0, ret);
|
||||
|
||||
/*
|
||||
* We never opened this dbp for real, so don't call the transactional
|
||||
* version of DB->close, and use NOSYNC to avoid calling into mpool.
|
||||
* We never opened this dbp for real, so don't include a transaction
|
||||
* handle, and use NOSYNC to avoid calling into mpool.
|
||||
*/
|
||||
if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
|
||||
if ((t_ret = __db_close(dbp, NULL, DB_NOSYNC)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_remove
|
||||
* Remove method for DB.
|
||||
* __db_remove_pp
|
||||
* DB->remove pre/post processing.
|
||||
*
|
||||
* PUBLIC: int __db_remove __P((DB *, const char *, const char *, u_int32_t));
|
||||
* PUBLIC: int __db_remove_pp
|
||||
* PUBLIC: __P((DB *, const char *, const char *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_remove(dbp, name, subdb, flags)
|
||||
__db_remove_pp(dbp, name, subdb, flags)
|
||||
DB *dbp;
|
||||
const char *name, *subdb;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int ret, t_ret;
|
||||
int handle_check, ret;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
@@ -126,57 +138,85 @@ __db_remove(dbp, name, subdb, flags)
|
||||
*/
|
||||
if (F_ISSET(dbp, DB_AM_OPEN_CALLED)) {
|
||||
ret = __db_mi_open(dbenv, "DB->remove", 1);
|
||||
goto err;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* Validate arguments. */
|
||||
if ((ret = __db_fchk(dbenv, "DB->remove", flags, 0)) != 0)
|
||||
goto err;
|
||||
return (ret);
|
||||
|
||||
/* Check for consistent transaction usage. */
|
||||
if ((ret = __db_check_txn(dbp, NULL, DB_LOCK_INVALIDID, 0)) != 0)
|
||||
goto err;
|
||||
return (ret);
|
||||
|
||||
handle_check = IS_REPLICATED(dbenv, dbp);
|
||||
if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Remove the file. */
|
||||
ret = __db_remove_i(dbp, NULL, name, subdb);
|
||||
ret = __db_remove(dbp, NULL, name, subdb, flags);
|
||||
|
||||
/*
|
||||
* We never opened this dbp for real, use NOSYNC to avoid calling into
|
||||
* mpool.
|
||||
*/
|
||||
err: if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
|
||||
if (handle_check)
|
||||
__env_db_rep_exit(dbenv);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_remove
|
||||
* DB->remove method.
|
||||
*
|
||||
* PUBLIC: int __db_remove
|
||||
* PUBLIC: __P((DB *, DB_TXN *, const char *, const char *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_remove(dbp, txn, name, subdb, flags)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
const char *name, *subdb;
|
||||
u_int32_t flags;
|
||||
{
|
||||
int ret, t_ret;
|
||||
|
||||
ret = __db_remove_int(dbp, txn, name, subdb, flags);
|
||||
|
||||
if ((t_ret = __db_close(dbp, txn, DB_NOSYNC)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_remove_i
|
||||
* Internal remove method for DB.
|
||||
* __db_remove_int
|
||||
* Worker function for the DB->remove method.
|
||||
*
|
||||
* PUBLIC: int __db_remove_i __P((DB *, DB_TXN *, const char *, const char *));
|
||||
* PUBLIC: int __db_remove_int __P((DB *,
|
||||
* PUBLIC: DB_TXN *, const char *, const char *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_remove_i(dbp, txn, name, subdb)
|
||||
__db_remove_int(dbp, txn, name, subdb, flags)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
const char *name, *subdb;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
DB_LSN newlsn;
|
||||
int ret;
|
||||
char *real_name;
|
||||
char *real_name, *tmpname;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
real_name = NULL;
|
||||
real_name = tmpname = NULL;
|
||||
|
||||
/* Handle subdatabase removes separately. */
|
||||
if (subdb != NULL)
|
||||
return (__db_subdb_remove(dbp, txn, name, subdb));
|
||||
if (subdb != NULL) {
|
||||
ret = __db_subdb_remove(dbp, txn, name, subdb);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Handle transactional file removes separately. */
|
||||
if (txn != NULL)
|
||||
return (__db_dbtxn_remove(dbp, txn, name));
|
||||
if (txn != NULL) {
|
||||
ret = __db_dbtxn_remove(dbp, txn, name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* The remaining case is a non-transactional file remove.
|
||||
@@ -185,20 +225,30 @@ __db_remove_i(dbp, txn, name, subdb)
|
||||
*/
|
||||
if ((ret = __db_appname(dbenv,
|
||||
DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
|
||||
return (ret);
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* If force is set, remove the temporary file. Ignore errors because
|
||||
* the backup file might not exist.
|
||||
*/
|
||||
if (LF_ISSET(DB_FORCE) &&
|
||||
(ret = __db_backup_name(dbenv, real_name, NULL, &tmpname)) == 0)
|
||||
(void)__os_unlink(dbenv, tmpname);
|
||||
|
||||
if ((ret = __fop_remove_setup(dbp, NULL, real_name, 0)) != 0)
|
||||
goto err;
|
||||
|
||||
if (dbp->db_am_remove != NULL &&
|
||||
(ret = dbp->db_am_remove(dbp, NULL, name, subdb, &newlsn)) != 0)
|
||||
(ret = dbp->db_am_remove(dbp, NULL, name, subdb)) != 0)
|
||||
goto err;
|
||||
|
||||
ret = __fop_remove(dbenv, NULL, dbp->fileid, name, DB_APP_DATA);
|
||||
ret = __fop_remove(dbenv, NULL, dbp->fileid, name, DB_APP_DATA,
|
||||
F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0);
|
||||
|
||||
err:
|
||||
if (real_name != NULL)
|
||||
err: if (real_name != NULL)
|
||||
__os_free(dbenv, real_name);
|
||||
if (tmpname != NULL)
|
||||
__os_free(dbenv, tmpname);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -222,7 +272,7 @@ __db_subdb_remove(dbp, txn, name, subdb)
|
||||
if ((ret = db_create(&sdbp, dbp->dbenv, 0)) != 0)
|
||||
goto err;
|
||||
if ((ret = __db_open(sdbp,
|
||||
txn, name, subdb, DB_UNKNOWN, DB_WRITEOPEN, 0)) != 0)
|
||||
txn, name, subdb, DB_UNKNOWN, DB_WRITEOPEN, 0, PGNO_BASE_MD)) != 0)
|
||||
goto err;
|
||||
|
||||
DB_TEST_RECOVERY(sdbp, DB_TEST_PREDESTROY, ret, name);
|
||||
@@ -238,6 +288,8 @@ __db_subdb_remove(dbp, txn, name, subdb)
|
||||
if ((ret = __ham_reclaim(sdbp, txn)) != 0)
|
||||
goto err;
|
||||
break;
|
||||
case DB_QUEUE:
|
||||
case DB_UNKNOWN:
|
||||
default:
|
||||
ret = __db_unknown_type(
|
||||
sdbp->dbenv, "__db_subdb_remove", sdbp->type);
|
||||
@@ -260,11 +312,11 @@ __db_subdb_remove(dbp, txn, name, subdb)
|
||||
DB_TEST_RECOVERY_LABEL
|
||||
err:
|
||||
/* Close the main and subdatabases. */
|
||||
if ((t_ret = __db_close_i(sdbp, txn, 0)) != 0 && ret == 0)
|
||||
if ((t_ret = __db_close(sdbp, txn, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
if (mdbp != NULL &&
|
||||
(t_ret = __db_close_i(mdbp, txn, 0)) != 0 && ret == 0)
|
||||
(t_ret = __db_close(mdbp, txn, DB_NOSYNC)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (ret);
|
||||
@@ -277,7 +329,6 @@ __db_dbtxn_remove(dbp, txn, name)
|
||||
const char *name;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
DB_LSN newlsn;
|
||||
int ret;
|
||||
char *tmpname;
|
||||
|
||||
@@ -297,15 +348,16 @@ __db_dbtxn_remove(dbp, txn, name)
|
||||
|
||||
DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, name);
|
||||
|
||||
if ((ret = __db_rename_i(dbp, txn, name, NULL, tmpname)) != 0)
|
||||
if ((ret = __db_rename_int(dbp, txn, name, NULL, tmpname)) != 0)
|
||||
goto err;
|
||||
|
||||
/* The internal removes will also translate into delayed removes. */
|
||||
if (dbp->db_am_remove != NULL &&
|
||||
(ret = dbp->db_am_remove(dbp, txn, tmpname, NULL, &newlsn)) != 0)
|
||||
(ret = dbp->db_am_remove(dbp, txn, tmpname, NULL)) != 0)
|
||||
goto err;
|
||||
|
||||
ret = __fop_remove(dbenv, txn, dbp->fileid, tmpname, DB_APP_DATA);
|
||||
ret = __fop_remove(dbenv, txn, dbp->fileid, tmpname, DB_APP_DATA,
|
||||
F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0);
|
||||
|
||||
DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, name);
|
||||
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 2001-2002
|
||||
* Copyright (c) 2001-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_rename.c,v 11.216 2004/09/16 17:55:17 margo Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_rename.c,v 11.203 2002/08/07 16:16:47 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
@@ -23,28 +21,28 @@ static const char revid[] = "$Id: db_rename.c,v 11.203 2002/08/07 16:16:47 bosti
|
||||
#include "dbinc/fop.h"
|
||||
#include "dbinc/lock.h"
|
||||
#include "dbinc/log.h"
|
||||
#include "dbinc/mp.h"
|
||||
|
||||
static int __db_subdb_rename __P(( DB *, DB_TXN *,
|
||||
const char *, const char *, const char *));
|
||||
static int __dbenv_dbrename __P((DB_ENV *,
|
||||
DB_TXN *, const char *, const char *, const char *, int));
|
||||
static int __db_subdb_rename __P((DB *,
|
||||
DB_TXN *, const char *, const char *, const char *));
|
||||
|
||||
/*
|
||||
* __dbenv_dbrename
|
||||
* Rename method for DB_ENV.
|
||||
* __dbenv_dbrename_pp
|
||||
* DB_ENV->dbrename pre/post processing.
|
||||
*
|
||||
* PUBLIC: int __dbenv_dbrename __P((DB_ENV *, DB_TXN *,
|
||||
* PUBLIC: int __dbenv_dbrename_pp __P((DB_ENV *, DB_TXN *,
|
||||
* PUBLIC: const char *, const char *, const char *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__dbenv_dbrename(dbenv, txn, name, subdb, newname, flags)
|
||||
__dbenv_dbrename_pp(dbenv, txn, name, subdb, newname, flags)
|
||||
DB_ENV *dbenv;
|
||||
DB_TXN *txn;
|
||||
const char *name, *subdb, *newname;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB *dbp;
|
||||
int ret, t_ret, txn_local;
|
||||
|
||||
txn_local = 0;
|
||||
int ret, txn_local;
|
||||
|
||||
PANIC_CHECK(dbenv);
|
||||
ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->dbrename");
|
||||
@@ -53,67 +51,97 @@ __dbenv_dbrename(dbenv, txn, name, subdb, newname, flags)
|
||||
if ((ret = __db_fchk(dbenv, "DB->rename", flags, DB_AUTO_COMMIT)) != 0)
|
||||
return (ret);
|
||||
|
||||
if ((ret = db_create(&dbp, dbenv, 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* Create local transaction as necessary, check for consistent
|
||||
* transaction usage.
|
||||
*/
|
||||
if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
|
||||
if ((ret = __db_txn_auto(dbp, &txn)) != 0)
|
||||
if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
|
||||
return (ret);
|
||||
txn_local = 1;
|
||||
} else
|
||||
} else {
|
||||
if (txn != NULL && !TXN_ON(dbenv))
|
||||
return (__db_not_txn_env(dbenv));
|
||||
txn_local = 0;
|
||||
}
|
||||
|
||||
ret = __db_rename_i(dbp, txn, name, subdb, newname);
|
||||
ret = __dbenv_dbrename(dbenv, txn, name, subdb, newname, txn_local);
|
||||
|
||||
return (txn_local ? __db_txn_auto_resolve(dbenv, txn, 0, ret) : ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __dbenv_dbrename
|
||||
* DB_ENV->dbrename.
|
||||
*/
|
||||
static int
|
||||
__dbenv_dbrename(dbenv, txn, name, subdb, newname, txn_local)
|
||||
DB_ENV *dbenv;
|
||||
DB_TXN *txn;
|
||||
const char *name, *subdb, *newname;
|
||||
int txn_local;
|
||||
{
|
||||
DB *dbp;
|
||||
int handle_check, ret, t_ret;
|
||||
|
||||
if ((ret = db_create(&dbp, dbenv, 0)) != 0)
|
||||
return (ret);
|
||||
if (txn != NULL)
|
||||
F_SET(dbp, DB_AM_TXN);
|
||||
|
||||
handle_check = IS_REPLICATED(dbenv, dbp);
|
||||
if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, txn != NULL)) != 0)
|
||||
goto err;
|
||||
|
||||
ret = __db_rename_int(dbp, txn, name, subdb, newname);
|
||||
|
||||
/* Commit for DB_AUTO_COMMIT. */
|
||||
if (txn_local) {
|
||||
if (ret == 0)
|
||||
ret = txn->commit(txn, 0);
|
||||
else
|
||||
if ((t_ret = txn->abort(txn)) != 0)
|
||||
ret = __db_panic(dbenv, t_ret);
|
||||
|
||||
/*
|
||||
* We created the DBP here and when we committed/aborted,
|
||||
* we release all the tranasctional locks, which includes
|
||||
* the handle lock; mark the handle cleared explicitly.
|
||||
* We created the DBP here and when we commit/abort, we'll
|
||||
* release all the transactional locks, including the handle
|
||||
* lock; mark the handle cleared explicitly.
|
||||
*/
|
||||
LOCK_INIT(dbp->handle_lock);
|
||||
dbp->lid = DB_LOCK_INVALIDID;
|
||||
} else if (txn != NULL) {
|
||||
/*
|
||||
* We created this handle locally so we need to close it
|
||||
* and clean it up. Unfortunately, it's holding transactional
|
||||
* locks that need to persist until the end of transaction.
|
||||
* If we invalidate the locker id (dbp->lid), then the close
|
||||
* won't free these locks prematurely.
|
||||
*/
|
||||
dbp->lid = DB_LOCK_INVALIDID;
|
||||
}
|
||||
|
||||
/*
|
||||
* We never opened this dbp for real, so don't call the transactional
|
||||
* version of DB->close, and use NOSYNC to avoid calling into mpool.
|
||||
*/
|
||||
if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
|
||||
if (handle_check)
|
||||
__env_db_rep_exit(dbenv);
|
||||
|
||||
err:
|
||||
if ((t_ret = __db_close(dbp, txn, DB_NOSYNC)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_rename
|
||||
* Rename method for DB.
|
||||
* __db_rename_pp
|
||||
* DB->rename pre/post processing.
|
||||
*
|
||||
* PUBLIC: int __db_rename __P((DB *,
|
||||
* PUBLIC: int __db_rename_pp __P((DB *,
|
||||
* PUBLIC: const char *, const char *, const char *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_rename(dbp, name, subdb, newname, flags)
|
||||
__db_rename_pp(dbp, name, subdb, newname, flags)
|
||||
DB *dbp;
|
||||
const char *name, *subdb, *newname;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int ret, t_ret;
|
||||
int handle_check, ret;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
handle_check = 0;
|
||||
|
||||
PANIC_CHECK(dbenv);
|
||||
|
||||
@@ -140,28 +168,54 @@ __db_rename(dbp, name, subdb, newname, flags)
|
||||
if ((ret = __db_check_txn(dbp, NULL, DB_LOCK_INVALIDID, 0)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Rename the file. */
|
||||
ret = __db_rename_i(dbp, NULL, name, subdb, newname);
|
||||
handle_check = IS_REPLICATED(dbenv, dbp);
|
||||
if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, 0)) != 0) {
|
||||
handle_check = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* We never opened this dbp for real, use NOSYNC to avoid calling into
|
||||
* mpool.
|
||||
*/
|
||||
err: if ((t_ret = dbp->close(dbp, DB_NOSYNC)) != 0 && ret == 0)
|
||||
/* Rename the file. */
|
||||
ret = __db_rename(dbp, NULL, name, subdb, newname);
|
||||
|
||||
err: if (handle_check)
|
||||
__env_db_rep_exit(dbenv);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_rename
|
||||
* DB->rename method.
|
||||
*
|
||||
* PUBLIC: int __db_rename
|
||||
* PUBLIC: __P((DB *, DB_TXN *, const char *, const char *, const char *));
|
||||
*/
|
||||
int
|
||||
__db_rename(dbp, txn, name, subdb, newname)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
const char *name, *subdb, *newname;
|
||||
{
|
||||
int ret, t_ret;
|
||||
|
||||
ret = __db_rename_int(dbp, txn, name, subdb, newname);
|
||||
|
||||
if ((t_ret = __db_close(dbp, txn, DB_NOSYNC)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_rename_i
|
||||
* Internal rename method for DB.
|
||||
* __db_rename_int
|
||||
* Worker function for DB->rename method; the close of the dbp is
|
||||
* left in the wrapper routine.
|
||||
*
|
||||
* PUBLIC: int __db_rename_i __P((DB *,
|
||||
* PUBLIC: DB_TXN *, const char *, const char *, const char *));
|
||||
* PUBLIC: int __db_rename_int
|
||||
* PUBLIC: __P((DB *, DB_TXN *, const char *, const char *, const char *));
|
||||
*/
|
||||
int
|
||||
__db_rename_i(dbp, txn, name, subdb, newname)
|
||||
__db_rename_int(dbp, txn, name, subdb, newname)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
const char *name, *subdb, *newname;
|
||||
@@ -180,9 +234,11 @@ __db_rename_i(dbp, txn, name, subdb, newname)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* From here on down, this pertains to files. */
|
||||
|
||||
/* Find the real name of the file. */
|
||||
/*
|
||||
* From here on down, this pertains to files.
|
||||
*
|
||||
* Find the real name of the file.
|
||||
*/
|
||||
if ((ret = __db_appname(dbenv,
|
||||
DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
|
||||
goto err;
|
||||
@@ -220,8 +276,7 @@ __db_rename_i(dbp, txn, name, subdb, newname)
|
||||
DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, newname);
|
||||
|
||||
DB_TEST_RECOVERY_LABEL
|
||||
err:
|
||||
if (real_name != NULL)
|
||||
err: if (real_name != NULL)
|
||||
__os_free(dbenv, real_name);
|
||||
|
||||
return (ret);
|
||||
@@ -265,14 +320,14 @@ __db_subdb_rename(dbp, txn, name, subdb, newname)
|
||||
MU_OPEN, NULL, 0)) != 0)
|
||||
goto err;
|
||||
|
||||
if ((ret = mdbp->mpf->get(mdbp->mpf, &dbp->meta_pgno, 0, &meta)) != 0)
|
||||
if ((ret = __memp_fget(mdbp->mpf, &dbp->meta_pgno, 0, &meta)) != 0)
|
||||
goto err;
|
||||
memcpy(&dbp->fileid, ((DBMETA *)meta)->uid, DB_FILE_ID_LEN);
|
||||
memcpy(dbp->fileid, ((DBMETA *)meta)->uid, DB_FILE_ID_LEN);
|
||||
if ((ret = __fop_lock_handle(dbenv,
|
||||
dbp, mdbp->lid, DB_LOCK_WRITE, NULL, 0)) != 0)
|
||||
dbp, mdbp->lid, DB_LOCK_WRITE, NULL, NOWAIT_FLAG(txn))) != 0)
|
||||
goto err;
|
||||
|
||||
ret = mdbp->mpf->put(mdbp->mpf, meta, 0);
|
||||
ret = __memp_fput(mdbp->mpf, meta, 0);
|
||||
meta = NULL;
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
@@ -286,11 +341,11 @@ __db_subdb_rename(dbp, txn, name, subdb, newname)
|
||||
DB_TEST_RECOVERY_LABEL
|
||||
err:
|
||||
if (meta != NULL &&
|
||||
(t_ret = mdbp->mpf->put(mdbp->mpf, meta, 0)) != 0 && ret == 0)
|
||||
(t_ret = __memp_fput(mdbp->mpf, meta, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
if (mdbp != NULL &&
|
||||
(t_ret = __db_close_i(mdbp, txn, 0)) != 0 && ret == 0)
|
||||
(t_ret = __db_close(mdbp, txn, DB_NOSYNC)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (ret);
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_ret.c,v 11.26 2004/02/05 02:25:13 mjc Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_ret.c,v 11.21 2002/03/28 19:21:47 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -92,6 +90,8 @@ __db_retcopy(dbenv, dbt, data, len, memp, memsize)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
|
||||
/* If returning a partial record, reset the length. */
|
||||
if (F_ISSET(dbt, DB_DBT_PARTIAL)) {
|
||||
data = (u_int8_t *)data + dbt->doff;
|
||||
@@ -103,14 +103,6 @@ __db_retcopy(dbenv, dbt, data, len, memp, memsize)
|
||||
len = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the length of the returned record in the DBT size field.
|
||||
* This satisfies the requirement that if we're using user memory
|
||||
* and insufficient memory was provided, return the amount necessary
|
||||
* in the size field.
|
||||
*/
|
||||
dbt->size = len;
|
||||
|
||||
/*
|
||||
* Allocate memory to be owned by the application: DB_DBT_MALLOC,
|
||||
* DB_DBT_REALLOC.
|
||||
@@ -127,28 +119,36 @@ __db_retcopy(dbenv, dbt, data, len, memp, memsize)
|
||||
* memory pointer is allowed to be NULL.
|
||||
*/
|
||||
if (F_ISSET(dbt, DB_DBT_MALLOC)) {
|
||||
if ((ret = __os_umalloc(dbenv, len, &dbt->data)) != 0)
|
||||
return (ret);
|
||||
ret = __os_umalloc(dbenv, len, &dbt->data);
|
||||
} else if (F_ISSET(dbt, DB_DBT_REALLOC)) {
|
||||
if ((ret = __os_urealloc(dbenv, len, &dbt->data)) != 0)
|
||||
return (ret);
|
||||
if (dbt->data == NULL || dbt->size == 0 || dbt->size < len)
|
||||
ret = __os_urealloc(dbenv, len, &dbt->data);
|
||||
} else if (F_ISSET(dbt, DB_DBT_USERMEM)) {
|
||||
if (len != 0 && (dbt->data == NULL || dbt->ulen < len))
|
||||
return (ENOMEM);
|
||||
ret = DB_BUFFER_SMALL;
|
||||
} else if (memp == NULL || memsize == NULL) {
|
||||
return (EINVAL);
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
if (len != 0 && (*memsize == 0 || *memsize < len)) {
|
||||
if ((ret = __os_realloc(dbenv, len, memp)) != 0) {
|
||||
if ((ret = __os_realloc(dbenv, len, memp)) == 0)
|
||||
*memsize = len;
|
||||
else
|
||||
*memsize = 0;
|
||||
return (ret);
|
||||
}
|
||||
*memsize = len;
|
||||
}
|
||||
dbt->data = *memp;
|
||||
if (ret == 0)
|
||||
dbt->data = *memp;
|
||||
}
|
||||
|
||||
if (len != 0)
|
||||
if (ret == 0 && len != 0)
|
||||
memcpy(dbt->data, data, len);
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Return the length of the returned record in the DBT size field.
|
||||
* This satisfies the requirement that if we're using user memory
|
||||
* and insufficient memory was provided, return the amount necessary
|
||||
* in the size field.
|
||||
*/
|
||||
dbt->size = len;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
155
storage/bdb/db/db_setid.c
Normal file
155
storage/bdb/db/db_setid.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 2000-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_setid.c,v 1.6 2004/09/24 13:41:08 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_swap.h"
|
||||
#include "dbinc/db_am.h"
|
||||
|
||||
/*
|
||||
* __db_fileid_reset --
|
||||
* Reset the file IDs for every database in the file.
|
||||
*
|
||||
* PUBLIC: int __db_fileid_reset __P((DB_ENV *, char *, int));
|
||||
*/
|
||||
int
|
||||
__db_fileid_reset(dbenv, name, passwd)
|
||||
DB_ENV *dbenv;
|
||||
char *name;
|
||||
int passwd;
|
||||
{
|
||||
DB *dbp;
|
||||
DBC *dbcp;
|
||||
DBT key, data;
|
||||
DB_MPOOLFILE *mpf;
|
||||
db_pgno_t pgno;
|
||||
int t_ret, ret;
|
||||
void *pagep;
|
||||
char *real_name;
|
||||
u_int8_t fileid[DB_FILE_ID_LEN];
|
||||
|
||||
dbp = NULL;
|
||||
dbcp = NULL;
|
||||
real_name = NULL;
|
||||
|
||||
/* Get the real backing file name. */
|
||||
if ((ret = __db_appname(dbenv,
|
||||
DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Get a new file ID. */
|
||||
if ((ret = __os_fileid(dbenv, real_name, 1, fileid)) != 0) {
|
||||
dbenv->err(dbenv, ret, "unable to get new file ID");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Create the DB object. */
|
||||
if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "db_create");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* If configured with a password, the databases are encrypted. */
|
||||
if (passwd && (ret = dbp->set_flags(dbp, DB_ENCRYPT)) != 0) {
|
||||
dbp->err(dbp, ret, "DB->set_flags: DB_ENCRYPT");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the DB file.
|
||||
*
|
||||
* !!!
|
||||
* Note DB_RDWRMASTER flag, we need to open the master database file
|
||||
* for writing in this case.
|
||||
*/
|
||||
if ((ret = dbp->open(dbp,
|
||||
NULL, name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0)) != 0) {
|
||||
dbp->err(dbp, ret, "DB->open: %s", name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
mpf = dbp->mpf;
|
||||
|
||||
pgno = PGNO_BASE_MD;
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0) {
|
||||
dbp->err(dbp, ret,
|
||||
"%s: DB_MPOOLFILE->get: %lu", name, (u_long)pgno);
|
||||
goto err;
|
||||
}
|
||||
memcpy(((DBMETA *)pagep)->uid, fileid, DB_FILE_ID_LEN);
|
||||
if ((ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0) {
|
||||
dbp->err(dbp, ret,
|
||||
"%s: DB_MPOOLFILE->put: %lu", name, (u_long)pgno);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the database file doesn't support subdatabases, we only have
|
||||
* to update a single metadata page. Otherwise, we have to open a
|
||||
* cursor and step through the master database, and update all of
|
||||
* the subdatabases' metadata pages.
|
||||
*/
|
||||
if (!F_ISSET(dbp, DB_AM_SUBDB))
|
||||
goto err;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
memset(&data, 0, sizeof(data));
|
||||
if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
|
||||
dbp->err(dbp, ret, "DB->cursor");
|
||||
goto err;
|
||||
}
|
||||
while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
|
||||
/*
|
||||
* XXX
|
||||
* We're handling actual data, not on-page meta-data, so it
|
||||
* hasn't been converted to/from opposite endian architectures.
|
||||
* Do it explicitly, now.
|
||||
*/
|
||||
memcpy(&pgno, data.data, sizeof(db_pgno_t));
|
||||
DB_NTOHL(&pgno);
|
||||
if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0) {
|
||||
dbp->err(dbp, ret,
|
||||
"%s: DB_MPOOLFILE->get: %lu", name, (u_long)pgno);
|
||||
goto err;
|
||||
}
|
||||
memcpy(((DBMETA *)pagep)->uid, fileid, DB_FILE_ID_LEN);
|
||||
if ((ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0) {
|
||||
dbp->err(dbp, ret,
|
||||
"%s: DB_MPOOLFILE->put: %lu", name, (u_long)pgno);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (ret == DB_NOTFOUND)
|
||||
ret = 0;
|
||||
else
|
||||
dbp->err(dbp, ret, "DBcursor->get");
|
||||
|
||||
err: if (dbcp != NULL && (t_ret = dbcp->c_close(dbcp)) != 0) {
|
||||
dbp->err(dbp, ret, "DBcursor->close");
|
||||
if (ret == 0)
|
||||
ret = t_ret;
|
||||
}
|
||||
if (dbp != NULL && (t_ret = dbp->close(dbp, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "DB->close");
|
||||
if (ret == 0)
|
||||
ret = t_ret;
|
||||
}
|
||||
if (real_name != NULL)
|
||||
__os_free(dbenv, real_name);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
83
storage/bdb/db/db_setlsn.c
Normal file
83
storage/bdb/db/db_setlsn.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 2000-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_setlsn.c,v 1.2 2004/04/27 16:10:13 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_am.h"
|
||||
|
||||
/*
|
||||
* __db_lsn_reset --
|
||||
* Reset the LSNs for every page in the file.
|
||||
*
|
||||
* PUBLIC: int __db_lsn_reset __P((DB_ENV *, char *, int));
|
||||
*/
|
||||
int
|
||||
__db_lsn_reset(dbenv, name, passwd)
|
||||
DB_ENV *dbenv;
|
||||
char *name;
|
||||
int passwd;
|
||||
{
|
||||
DB *dbp;
|
||||
DB_MPOOLFILE *mpf;
|
||||
PAGE *pagep;
|
||||
db_pgno_t pgno;
|
||||
int t_ret, ret;
|
||||
|
||||
/* Create the DB object. */
|
||||
if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
|
||||
dbenv->err(dbenv, ret, "db_create");
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* If configured with a password, the databases are encrypted. */
|
||||
if (passwd && (ret = dbp->set_flags(dbp, DB_ENCRYPT)) != 0) {
|
||||
dbp->err(dbp, ret, "DB->set_flags: DB_ENCRYPT");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the DB file.
|
||||
*
|
||||
* !!!
|
||||
* Note DB_RDWRMASTER flag, we need to open the master database file
|
||||
* for writing in this case.
|
||||
*/
|
||||
if ((ret = dbp->open(dbp,
|
||||
NULL, name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0)) != 0) {
|
||||
dbp->err(dbp, ret, "DB->open: %s", name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Reset the LSN on every page of the database file. */
|
||||
mpf = dbp->mpf;
|
||||
for (pgno = 0; (ret = mpf->get(mpf, &pgno, 0, &pagep)) == 0; ++pgno) {
|
||||
LSN_NOT_LOGGED(pagep->lsn);
|
||||
if ((ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0) {
|
||||
dbp->err(dbp, ret, "DB_MPOOLFILE->put: %s", name);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == DB_PAGE_NOTFOUND)
|
||||
ret = 0;
|
||||
else
|
||||
dbp->err(dbp, ret, "DB_MPOOLFILE->get: %s", name);
|
||||
|
||||
err: if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
return (ret == 0 ? 0 : 1);
|
||||
}
|
||||
500
storage/bdb/db/db_stati.c
Normal file
500
storage/bdb/db/db_stati.c
Normal file
@@ -0,0 +1,500 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_stati.c,v 11.123 2004/07/19 16:40:51 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.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"
|
||||
|
||||
#include "dbinc/db_page.h"
|
||||
#include "dbinc/db_shash.h"
|
||||
#include "dbinc/btree.h"
|
||||
#include "dbinc/hash.h"
|
||||
#include "dbinc/qam.h"
|
||||
#include "dbinc/log.h"
|
||||
#include "dbinc/mp.h"
|
||||
|
||||
#ifdef HAVE_STATISTICS
|
||||
static int __db_print_all __P((DB *, u_int32_t));
|
||||
static int __db_print_citem __P((DBC *));
|
||||
static int __db_print_cursor __P((DB *));
|
||||
static int __db_print_stats __P((DB *, u_int32_t));
|
||||
static int __db_stat_arg __P((DB *, u_int32_t));
|
||||
|
||||
/*
|
||||
* __db_stat_pp --
|
||||
* DB->stat pre/post processing.
|
||||
*
|
||||
* PUBLIC: int __db_stat_pp __P((DB *, DB_TXN *, void *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_stat_pp(dbp, txn, spp, flags)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
void *spp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int handle_check, ret;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
PANIC_CHECK(dbp->dbenv);
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
|
||||
|
||||
if ((ret = __db_stat_arg(dbp, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Check for replication block. */
|
||||
handle_check = IS_REPLICATED(dbenv, dbp);
|
||||
if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
ret = __db_stat(dbp, txn, spp, flags);
|
||||
|
||||
/* Release replication block. */
|
||||
if (handle_check)
|
||||
__env_db_rep_exit(dbenv);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_stat --
|
||||
* DB->stat.
|
||||
*
|
||||
* PUBLIC: int __db_stat __P((DB *, DB_TXN *, void *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_stat(dbp, txn, spp, flags)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
void *spp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
DBC *dbc;
|
||||
int ret, t_ret;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
/* Acquire a cursor. */
|
||||
if ((ret = __db_cursor(dbp, txn,
|
||||
&dbc, LF_ISSET(DB_DEGREE_2 | DB_DIRTY_READ))) != 0)
|
||||
return (ret);
|
||||
|
||||
DEBUG_LWRITE(dbc, NULL, "DB->stat", NULL, NULL, flags);
|
||||
LF_CLR(DB_DEGREE_2 | DB_DIRTY_READ);
|
||||
|
||||
switch (dbp->type) {
|
||||
case DB_BTREE:
|
||||
case DB_RECNO:
|
||||
ret = __bam_stat(dbc, spp, flags);
|
||||
break;
|
||||
case DB_HASH:
|
||||
ret = __ham_stat(dbc, spp, flags);
|
||||
break;
|
||||
case DB_QUEUE:
|
||||
ret = __qam_stat(dbc, spp, flags);
|
||||
break;
|
||||
case DB_UNKNOWN:
|
||||
default:
|
||||
ret = (__db_unknown_type(dbenv, "DB->stat", dbp->type));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_stat_arg --
|
||||
* Check DB->stat arguments.
|
||||
*/
|
||||
static int
|
||||
__db_stat_arg(dbp, flags)
|
||||
DB *dbp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
/* Check for invalid function flags. */
|
||||
LF_CLR(DB_DEGREE_2 | DB_DIRTY_READ);
|
||||
switch (flags) {
|
||||
case 0:
|
||||
case DB_FAST_STAT:
|
||||
case DB_CACHED_COUNTS: /* Deprecated and undocumented. */
|
||||
break;
|
||||
case DB_RECORDCOUNT: /* Deprecated and undocumented. */
|
||||
if (dbp->type == DB_RECNO)
|
||||
break;
|
||||
if (dbp->type == DB_BTREE && F_ISSET(dbp, DB_AM_RECNUM))
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
return (__db_ferr(dbenv, "DB->stat", 0));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_stat_print_pp --
|
||||
* DB->stat_print pre/post processing.
|
||||
*
|
||||
* PUBLIC: int __db_stat_print_pp __P((DB *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_stat_print_pp(dbp, flags)
|
||||
DB *dbp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int handle_check, ret;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
PANIC_CHECK(dbenv);
|
||||
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* The actual argument checking is simple, do it inline.
|
||||
*/
|
||||
if ((ret = __db_fchk(dbenv, "DB->stat_print",
|
||||
flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Check for replication block. */
|
||||
handle_check = IS_REPLICATED(dbenv, dbp);
|
||||
if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
ret = __db_stat_print(dbp, flags);
|
||||
|
||||
/* Release replication block. */
|
||||
if (handle_check)
|
||||
__env_db_rep_exit(dbenv);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_stat_print --
|
||||
* DB->stat_print.
|
||||
*
|
||||
* PUBLIC: int __db_stat_print __P((DB *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_stat_print(dbp, flags)
|
||||
DB *dbp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
|
||||
ret = __db_print_stats(dbp, flags);
|
||||
if (flags == 0 || ret != 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if (LF_ISSET(DB_STAT_ALL) && (ret = __db_print_all(dbp, flags)) != 0)
|
||||
return (ret);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_print_stats --
|
||||
* Display default DB handle statistics.
|
||||
*/
|
||||
static int
|
||||
__db_print_stats(dbp, flags)
|
||||
DB *dbp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DBC *dbc;
|
||||
DB_ENV *dbenv;
|
||||
int ret, t_ret;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
/* Acquire a cursor. */
|
||||
if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
DEBUG_LWRITE(dbc, NULL, "DB->stat_print", NULL, NULL, 0);
|
||||
|
||||
switch (dbp->type) {
|
||||
case DB_BTREE:
|
||||
case DB_RECNO:
|
||||
ret = __bam_stat_print(dbc, flags);
|
||||
break;
|
||||
case DB_HASH:
|
||||
ret = __ham_stat_print(dbc, flags);
|
||||
break;
|
||||
case DB_QUEUE:
|
||||
ret = __qam_stat_print(dbc, flags);
|
||||
break;
|
||||
case DB_UNKNOWN:
|
||||
default:
|
||||
ret = (__db_unknown_type(dbenv, "DB->stat_print", dbp->type));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_print_all --
|
||||
* Display debugging DB handle statistics.
|
||||
*/
|
||||
static int
|
||||
__db_print_all(dbp, flags)
|
||||
DB *dbp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
static const FN fn[] = {
|
||||
{ DB_AM_CHKSUM, "DB_AM_CHKSUM" },
|
||||
{ DB_AM_CL_WRITER, "DB_AM_CL_WRITER" },
|
||||
{ DB_AM_COMPENSATE, "DB_AM_COMPENSATE" },
|
||||
{ DB_AM_CREATED, "DB_AM_CREATED" },
|
||||
{ DB_AM_CREATED_MSTR, "DB_AM_CREATED_MSTR" },
|
||||
{ DB_AM_DBM_ERROR, "DB_AM_DBM_ERROR" },
|
||||
{ DB_AM_DELIMITER, "DB_AM_DELIMITER" },
|
||||
{ DB_AM_DIRTY, "DB_AM_DIRTY" },
|
||||
{ DB_AM_DISCARD, "DB_AM_DISCARD" },
|
||||
{ DB_AM_DUP, "DB_AM_DUP" },
|
||||
{ DB_AM_DUPSORT, "DB_AM_DUPSORT" },
|
||||
{ DB_AM_ENCRYPT, "DB_AM_ENCRYPT" },
|
||||
{ DB_AM_FIXEDLEN, "DB_AM_FIXEDLEN" },
|
||||
{ DB_AM_INMEM, "DB_AM_INMEM" },
|
||||
{ DB_AM_IN_RENAME, "DB_AM_IN_RENAME" },
|
||||
{ DB_AM_NOT_DURABLE, "DB_AM_NOT_DURABLE" },
|
||||
{ DB_AM_OPEN_CALLED, "DB_AM_OPEN_CALLED" },
|
||||
{ DB_AM_PAD, "DB_AM_PAD" },
|
||||
{ DB_AM_PGDEF, "DB_AM_PGDEF" },
|
||||
{ DB_AM_RDONLY, "DB_AM_RDONLY" },
|
||||
{ DB_AM_RECNUM, "DB_AM_RECNUM" },
|
||||
{ DB_AM_RECOVER, "DB_AM_RECOVER" },
|
||||
{ DB_AM_RENUMBER, "DB_AM_RENUMBER" },
|
||||
{ DB_AM_REPLICATION, "DB_AM_REPLICATION" },
|
||||
{ DB_AM_REVSPLITOFF, "DB_AM_REVSPLITOFF" },
|
||||
{ DB_AM_SECONDARY, "DB_AM_SECONDARY" },
|
||||
{ DB_AM_SNAPSHOT, "DB_AM_SNAPSHOT" },
|
||||
{ DB_AM_SUBDB, "DB_AM_SUBDB" },
|
||||
{ DB_AM_SWAP, "DB_AM_SWAP" },
|
||||
{ DB_AM_TXN, "DB_AM_TXN" },
|
||||
{ DB_AM_VERIFYING, "DB_AM_VERIFYING" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
DB_ENV *dbenv;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
|
||||
__db_msg(dbenv, "DB handle information:");
|
||||
STAT_ULONG("Page size", dbp->pgsize);
|
||||
STAT_ISSET("Append recno", dbp->db_append_recno);
|
||||
STAT_ISSET("Feedback", dbp->db_feedback);
|
||||
STAT_ISSET("Dup compare", dbp->dup_compare);
|
||||
STAT_ISSET("App private", dbp->app_private);
|
||||
STAT_ISSET("DbEnv", dbp->dbenv);
|
||||
STAT_STRING("Type", __db_dbtype_to_string(dbp->type));
|
||||
|
||||
__db_print_mutex(dbenv, NULL, dbp->mutexp, "Thread mutex", flags);
|
||||
|
||||
STAT_STRING("File", dbp->fname);
|
||||
STAT_STRING("Database", dbp->dname);
|
||||
STAT_HEX("Open flags", dbp->open_flags);
|
||||
|
||||
__db_print_fileid(dbenv, dbp->fileid, "\tFile ID");
|
||||
|
||||
STAT_ULONG("Cursor adjust ID", dbp->adj_fileid);
|
||||
STAT_ULONG("Meta pgno", dbp->meta_pgno);
|
||||
STAT_ULONG("Locker ID", dbp->lid);
|
||||
STAT_ULONG("Handle lock", dbp->cur_lid);
|
||||
STAT_ULONG("Associate lock", dbp->associate_lid);
|
||||
STAT_ULONG("RPC remote ID", dbp->cl_id);
|
||||
|
||||
__db_msg(dbenv,
|
||||
"%.24s\tReplication handle timestamp",
|
||||
dbp->timestamp == 0 ? "0" : ctime(&dbp->timestamp));
|
||||
|
||||
STAT_ISSET("Secondary callback", dbp->s_callback);
|
||||
STAT_ISSET("Primary handle", dbp->s_primary);
|
||||
|
||||
STAT_ISSET("api internal", dbp->api_internal);
|
||||
STAT_ISSET("Btree/Recno internal", dbp->bt_internal);
|
||||
STAT_ISSET("Hash internal", dbp->h_internal);
|
||||
STAT_ISSET("Queue internal", dbp->q_internal);
|
||||
STAT_ISSET("XA internal", dbp->xa_internal);
|
||||
|
||||
__db_prflags(dbenv, NULL, dbp->flags, fn, NULL, "\tFlags");
|
||||
|
||||
if (dbp->log_filename == NULL)
|
||||
STAT_ISSET("File naming information", dbp->log_filename);
|
||||
else
|
||||
__dbreg_print_fname(dbenv, dbp->log_filename);
|
||||
|
||||
(void)__db_print_cursor(dbp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_print_cursor --
|
||||
* Display the cursor active and free queues.
|
||||
*/
|
||||
static int
|
||||
__db_print_cursor(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
DBC *dbc;
|
||||
int ret, t_ret;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
__db_msg(dbenv, "%s", DB_GLOBAL(db_line));
|
||||
__db_msg(dbenv, "DB handle cursors:");
|
||||
|
||||
ret = 0;
|
||||
MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
|
||||
__db_msg(dbenv, "Active queue:");
|
||||
for (dbc = TAILQ_FIRST(&dbp->active_queue);
|
||||
dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
|
||||
if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
__db_msg(dbenv, "Join queue:");
|
||||
for (dbc = TAILQ_FIRST(&dbp->join_queue);
|
||||
dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
|
||||
if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
__db_msg(dbenv, "Free queue:");
|
||||
for (dbc = TAILQ_FIRST(&dbp->free_queue);
|
||||
dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
|
||||
if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static
|
||||
int __db_print_citem(dbc)
|
||||
DBC *dbc;
|
||||
{
|
||||
static const FN fn[] = {
|
||||
{ DBC_ACTIVE, "DBC_ACTIVE" },
|
||||
{ DBC_COMPENSATE, "DBC_COMPENSATE" },
|
||||
{ DBC_DEGREE_2, "DBC_DEGREE_2" },
|
||||
{ DBC_DIRTY_READ, "DBC_DIRTY_READ" },
|
||||
{ DBC_OPD, "DBC_OPD" },
|
||||
{ DBC_RECOVER, "DBC_RECOVER" },
|
||||
{ DBC_RMW, "DBC_RMW" },
|
||||
{ DBC_TRANSIENT, "DBC_TRANSIENT" },
|
||||
{ DBC_WRITECURSOR, "DBC_WRITECURSOR" },
|
||||
{ DBC_WRITER, "DBC_WRITER" },
|
||||
{ DBC_MULTIPLE, "DBC_MULTIPLE" },
|
||||
{ DBC_MULTIPLE_KEY, "DBC_MULTIPLE_KEY" },
|
||||
{ DBC_OWN_LID, "DBC_OWN_LID" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
DB *dbp;
|
||||
DBC_INTERNAL *cp;
|
||||
DB_ENV *dbenv;
|
||||
|
||||
dbp = dbc->dbp;
|
||||
dbenv = dbp->dbenv;
|
||||
cp = dbc->internal;
|
||||
|
||||
STAT_HEX("DBC", dbc);
|
||||
STAT_HEX("Associated dbp", dbc->dbp);
|
||||
STAT_HEX("Associated txn", dbc->txn);
|
||||
STAT_HEX("Internal", cp);
|
||||
STAT_HEX("Default locker ID", dbc->lid);
|
||||
STAT_HEX("Locker", dbc->locker);
|
||||
STAT_STRING("Type", __db_dbtype_to_string(dbc->dbtype));
|
||||
|
||||
STAT_HEX("Off-page duplicate cursor", cp->opd);
|
||||
STAT_HEX("Referenced page", cp->page);
|
||||
STAT_ULONG("Root", cp->root);
|
||||
STAT_ULONG("Page number", cp->pgno);
|
||||
STAT_ULONG("Page index", cp->indx);
|
||||
STAT_STRING("Lock mode", __db_lockmode_to_string(cp->lock_mode));
|
||||
__db_prflags(dbenv, NULL, dbc->flags, fn, NULL, "\tFlags");
|
||||
|
||||
switch (dbc->dbtype) {
|
||||
case DB_BTREE:
|
||||
case DB_RECNO:
|
||||
__bam_print_cursor(dbc);
|
||||
break;
|
||||
case DB_HASH:
|
||||
__ham_print_cursor(dbc);
|
||||
break;
|
||||
case DB_UNKNOWN:
|
||||
DB_ASSERT(dbp->type != DB_UNKNOWN);
|
||||
/* FALLTHROUGH */
|
||||
case DB_QUEUE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
#else /* !HAVE_STATISTICS */
|
||||
|
||||
int
|
||||
__db_stat_pp(dbp, txn, spp, flags)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
void *spp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
COMPQUIET(spp, NULL);
|
||||
COMPQUIET(txn, NULL);
|
||||
COMPQUIET(flags, 0);
|
||||
|
||||
return (__db_stat_not_built(dbp->dbenv));
|
||||
}
|
||||
|
||||
int
|
||||
__db_stat_print_pp(dbp, flags)
|
||||
DB *dbp;
|
||||
u_int32_t flags;
|
||||
{
|
||||
COMPQUIET(flags, 0);
|
||||
|
||||
return (__db_stat_not_built(dbp->dbenv));
|
||||
}
|
||||
#endif
|
||||
@@ -1,95 +1,202 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 2001-2002
|
||||
* Copyright (c) 2001-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_truncate.c,v 11.201 2004/07/15 15:52:51 sue Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_truncate.c,v 11.185 2002/08/07 16:16:48 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "db_int.h"
|
||||
#include "dbinc/db_page.h"
|
||||
#include "dbinc/log.h"
|
||||
#include "dbinc/btree.h"
|
||||
#include "dbinc/hash.h"
|
||||
#include "dbinc/qam.h"
|
||||
#include "dbinc/txn.h"
|
||||
|
||||
static int __db_cursor_check __P((DB *));
|
||||
|
||||
/*
|
||||
* __db_truncate
|
||||
* truncate method for DB.
|
||||
* __db_truncate_pp
|
||||
* DB->truncate pre/post processing.
|
||||
*
|
||||
* PUBLIC: int __db_truncate __P((DB *, DB_TXN *, u_int32_t *, u_int32_t));
|
||||
* PUBLIC: int __db_truncate_pp __P((DB *, DB_TXN *, u_int32_t *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_truncate(dbp, txn, countp, flags)
|
||||
__db_truncate_pp(dbp, txn, countp, flags)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
u_int32_t *countp, flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int ret, t_ret, txn_local;
|
||||
int handle_check, ret, txn_local;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
ret = txn_local = 0;
|
||||
|
||||
PANIC_CHECK(dbenv);
|
||||
|
||||
/* Check for invalid flags. */
|
||||
if (F_ISSET(dbp, DB_AM_SECONDARY)) {
|
||||
__db_err(dbenv,
|
||||
"DBP->truncate forbidden on secondary indices");
|
||||
return (EINVAL);
|
||||
}
|
||||
if ((ret =
|
||||
__db_fchk(dbenv, "DB->truncate", flags, DB_AUTO_COMMIT)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* Make sure there are no active cursors on this db. Since we drop
|
||||
* pages we cannot really adjust cursors.
|
||||
*/
|
||||
if (__db_cursor_check(dbp) != 0) {
|
||||
__db_err(dbenv,
|
||||
"DB->truncate not permitted with active cursors");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create local transaction as necessary, check for consistent
|
||||
* transaction usage.
|
||||
*/
|
||||
txn_local = 0;
|
||||
if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
|
||||
if ((ret = __db_txn_auto(dbp, &txn)) != 0)
|
||||
return (ret);
|
||||
if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
|
||||
goto err;
|
||||
txn_local = 1;
|
||||
} else
|
||||
if (txn != NULL && !TXN_ON(dbenv))
|
||||
return (__db_not_txn_env(dbenv));
|
||||
LF_CLR(DB_AUTO_COMMIT);
|
||||
} else if (txn != NULL && !TXN_ON(dbenv)) {
|
||||
ret = __db_not_txn_env(dbenv);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
handle_check = IS_REPLICATED(dbenv, dbp);
|
||||
if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0)
|
||||
goto err;
|
||||
|
||||
ret = __db_truncate(dbp, txn, countp);
|
||||
|
||||
if (handle_check)
|
||||
__env_db_rep_exit(dbenv);
|
||||
|
||||
err: return (txn_local ? __db_txn_auto_resolve(dbenv, txn, 0, ret) : ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_truncate
|
||||
* DB->truncate.
|
||||
*
|
||||
* PUBLIC: int __db_truncate __P((DB *, DB_TXN *, u_int32_t *));
|
||||
*/
|
||||
int
|
||||
__db_truncate(dbp, txn, countp)
|
||||
DB *dbp;
|
||||
DB_TXN *txn;
|
||||
u_int32_t *countp;
|
||||
{
|
||||
DB *sdbp;
|
||||
DBC *dbc;
|
||||
DB_ENV *dbenv;
|
||||
u_int32_t scount;
|
||||
int ret, t_ret;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
dbc = NULL;
|
||||
ret = 0;
|
||||
|
||||
/*
|
||||
* Run through all secondaries and truncate them first. The count
|
||||
* returned is the count of the primary only. QUEUE uses normal
|
||||
* processing to truncate so it will update the secondaries normally.
|
||||
*/
|
||||
if (dbp->type != DB_QUEUE && LIST_FIRST(&dbp->s_secondaries) != NULL) {
|
||||
for (sdbp = __db_s_first(dbp);
|
||||
sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp))
|
||||
if ((ret = __db_truncate(sdbp, txn, &scount)) != 0)
|
||||
break;
|
||||
if (sdbp != NULL)
|
||||
(void)__db_s_done(sdbp);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, NULL);
|
||||
|
||||
/* Acquire a cursor. */
|
||||
if ((ret = __db_cursor(dbp, txn, &dbc, 0)) != 0)
|
||||
return (ret);
|
||||
|
||||
DEBUG_LWRITE(dbc, txn, "DB->truncate", NULL, NULL, 0);
|
||||
|
||||
switch (dbp->type) {
|
||||
case DB_BTREE:
|
||||
case DB_RECNO:
|
||||
if ((ret = __bam_truncate(dbp, txn, countp)) != 0)
|
||||
goto err;
|
||||
break;
|
||||
case DB_HASH:
|
||||
if ((ret = __ham_truncate(dbp, txn, countp)) != 0)
|
||||
goto err;
|
||||
break;
|
||||
case DB_QUEUE:
|
||||
if ((ret = __qam_truncate(dbp, txn, countp)) != 0)
|
||||
goto err;
|
||||
break;
|
||||
default:
|
||||
ret = __db_unknown_type(
|
||||
dbenv, "__db_truncate", dbp->type);
|
||||
goto err;
|
||||
case DB_BTREE:
|
||||
case DB_RECNO:
|
||||
ret = __bam_truncate(dbc, countp);
|
||||
break;
|
||||
case DB_HASH:
|
||||
ret = __ham_truncate(dbc, countp);
|
||||
break;
|
||||
case DB_QUEUE:
|
||||
ret = __qam_truncate(dbc, countp);
|
||||
break;
|
||||
case DB_UNKNOWN:
|
||||
default:
|
||||
ret = __db_unknown_type(dbenv, "DB->truncate", dbp->type);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Discard the cursor. */
|
||||
if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
|
||||
DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, NULL);
|
||||
|
||||
DB_TEST_RECOVERY_LABEL
|
||||
err:
|
||||
/* Commit for DB_AUTO_COMMIT. */
|
||||
if (txn_local) {
|
||||
if (ret == 0)
|
||||
ret = txn->commit(txn, 0);
|
||||
else
|
||||
if ((t_ret = txn->abort(txn)) != 0)
|
||||
ret = __db_panic(dbenv, t_ret);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_cursor_check --
|
||||
* See if there are any active cursors on this db.
|
||||
*/
|
||||
static int
|
||||
__db_cursor_check(dbp)
|
||||
DB *dbp;
|
||||
{
|
||||
DB *ldbp;
|
||||
DBC *dbc;
|
||||
DB_ENV *dbenv;
|
||||
int found;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
|
||||
for (found = 0, ldbp = __dblist_get(dbenv, dbp->adj_fileid);
|
||||
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
|
||||
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
|
||||
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
|
||||
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
|
||||
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
|
||||
if (IS_INITIALIZED(dbc)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
|
||||
if (found == 1)
|
||||
break;
|
||||
}
|
||||
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
|
||||
|
||||
return (found);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_upg.c,v 11.35 2004/03/24 20:37:35 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_upg.c,v 11.29 2002/03/27 18:59:04 krinsky Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -36,11 +34,43 @@ static int (* const func_31_list[P_PAGETYPE_MAX])
|
||||
NULL, /* P_OVERFLOW */
|
||||
__ham_31_hashmeta, /* P_HASHMETA */
|
||||
__bam_31_btreemeta, /* P_BTREEMETA */
|
||||
NULL, /* P_QAMMETA */
|
||||
NULL, /* P_QAMDATA */
|
||||
NULL, /* P_LDUP */
|
||||
};
|
||||
|
||||
static int __db_page_pass __P((DB *, char *, u_int32_t, int (* const [])
|
||||
(DB *, char *, u_int32_t, DB_FH *, PAGE *, int *), DB_FH *));
|
||||
|
||||
/*
|
||||
* __db_upgrade_pp --
|
||||
* DB->upgrade pre/post processing.
|
||||
*
|
||||
* PUBLIC: int __db_upgrade_pp __P((DB *, const char *, u_int32_t));
|
||||
*/
|
||||
int
|
||||
__db_upgrade_pp(dbp, fname, flags)
|
||||
DB *dbp;
|
||||
const char *fname;
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
int ret;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
PANIC_CHECK(dbp->dbenv);
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* The actual argument checking is simple, do it inline.
|
||||
*/
|
||||
if ((ret = __db_fchk(dbenv, "DB->upgrade", flags, DB_DUPSORT)) != 0)
|
||||
return (ret);
|
||||
|
||||
return (__db_upgrade(dbp, fname, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* __db_upgrade --
|
||||
* Upgrade an existing database.
|
||||
@@ -54,17 +84,14 @@ __db_upgrade(dbp, fname, flags)
|
||||
u_int32_t flags;
|
||||
{
|
||||
DB_ENV *dbenv;
|
||||
DB_FH fh;
|
||||
DB_FH *fhp;
|
||||
size_t n;
|
||||
int ret, t_ret;
|
||||
u_int8_t mbuf[256];
|
||||
char *real_name;
|
||||
|
||||
dbenv = dbp->dbenv;
|
||||
|
||||
/* Validate arguments. */
|
||||
if ((ret = __db_fchk(dbenv, "DB->upgrade", flags, DB_DUPSORT)) != 0)
|
||||
return (ret);
|
||||
fhp = NULL;
|
||||
|
||||
/* Get the real backing file name. */
|
||||
if ((ret = __db_appname(dbenv,
|
||||
@@ -72,7 +99,7 @@ __db_upgrade(dbp, fname, flags)
|
||||
return (ret);
|
||||
|
||||
/* Open the file. */
|
||||
if ((ret = __os_open(dbenv, real_name, 0, 0, &fh)) != 0) {
|
||||
if ((ret = __os_open(dbenv, real_name, 0, 0, &fhp)) != 0) {
|
||||
__db_err(dbenv, "%s: %s", real_name, db_strerror(ret));
|
||||
return (ret);
|
||||
}
|
||||
@@ -85,7 +112,7 @@ __db_upgrade(dbp, fname, flags)
|
||||
* Read the metadata page. We read 256 bytes, which is larger than
|
||||
* any access method's metadata page and smaller than any disk sector.
|
||||
*/
|
||||
if ((ret = __os_read(dbenv, &fh, mbuf, sizeof(mbuf), &n)) != 0)
|
||||
if ((ret = __os_read(dbenv, fhp, mbuf, sizeof(mbuf), &n)) != 0)
|
||||
goto err;
|
||||
|
||||
switch (((DBMETA *)mbuf)->magic) {
|
||||
@@ -100,9 +127,9 @@ __db_upgrade(dbp, fname, flags)
|
||||
__bam_30_btreemeta(dbp, real_name, mbuf)) != 0)
|
||||
goto err;
|
||||
if ((ret = __os_seek(dbenv,
|
||||
&fh, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
|
||||
fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
|
||||
goto err;
|
||||
if ((ret = __os_write(dbenv, &fh, mbuf, 256, &n)) != 0)
|
||||
if ((ret = __os_write(dbenv, fhp, mbuf, 256, &n)) != 0)
|
||||
goto err;
|
||||
/* FALLTHROUGH */
|
||||
case 7:
|
||||
@@ -113,7 +140,7 @@ __db_upgrade(dbp, fname, flags)
|
||||
memcpy(&dbp->pgsize, mbuf + 20, sizeof(u_int32_t));
|
||||
|
||||
if ((ret = __db_page_pass(
|
||||
dbp, real_name, flags, func_31_list, &fh)) != 0)
|
||||
dbp, real_name, flags, func_31_list, fhp)) != 0)
|
||||
goto err;
|
||||
/* FALLTHROUGH */
|
||||
case 8:
|
||||
@@ -138,9 +165,9 @@ __db_upgrade(dbp, fname, flags)
|
||||
__ham_30_hashmeta(dbp, real_name, mbuf)) != 0)
|
||||
goto err;
|
||||
if ((ret = __os_seek(dbenv,
|
||||
&fh, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
|
||||
fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
|
||||
goto err;
|
||||
if ((ret = __os_write(dbenv, &fh, mbuf, 256, &n)) != 0)
|
||||
if ((ret = __os_write(dbenv, fhp, mbuf, 256, &n)) != 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
@@ -152,14 +179,14 @@ __db_upgrade(dbp, fname, flags)
|
||||
* the end of the database file.
|
||||
*
|
||||
* In DB 3.X, we now create all the hash pages
|
||||
* belonging to a doubling atomicly; it's not
|
||||
* belonging to a doubling atomically; it's not
|
||||
* safe to just save them for later, because when
|
||||
* we create an overflow page we'll just create
|
||||
* a new last page (whatever that may be). Grow
|
||||
* the database to the end of the current doubling.
|
||||
*/
|
||||
if ((ret =
|
||||
__ham_30_sizefix(dbp, &fh, real_name, mbuf)) != 0)
|
||||
__ham_30_sizefix(dbp, fhp, real_name, mbuf)) != 0)
|
||||
goto err;
|
||||
/* FALLTHROUGH */
|
||||
case 6:
|
||||
@@ -170,7 +197,7 @@ __db_upgrade(dbp, fname, flags)
|
||||
memcpy(&dbp->pgsize, mbuf + 20, sizeof(u_int32_t));
|
||||
|
||||
if ((ret = __db_page_pass(
|
||||
dbp, real_name, flags, func_31_list, &fh)) != 0)
|
||||
dbp, real_name, flags, func_31_list, fhp)) != 0)
|
||||
goto err;
|
||||
/* FALLTHROUGH */
|
||||
case 7:
|
||||
@@ -198,9 +225,9 @@ __db_upgrade(dbp, fname, flags)
|
||||
if ((ret = __qam_32_qammeta(dbp, real_name, mbuf)) != 0)
|
||||
return (ret);
|
||||
if ((ret = __os_seek(dbenv,
|
||||
&fh, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
|
||||
fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0)
|
||||
goto err;
|
||||
if ((ret = __os_write(dbenv, &fh, mbuf, 256, &n)) != 0)
|
||||
if ((ret = __os_write(dbenv, fhp, mbuf, 256, &n)) != 0)
|
||||
goto err;
|
||||
/* FALLTHROUGH */
|
||||
case 3:
|
||||
@@ -232,9 +259,10 @@ __db_upgrade(dbp, fname, flags)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = __os_fsync(dbenv, &fh);
|
||||
ret = __os_fsync(dbenv, fhp);
|
||||
|
||||
err: if ((t_ret = __os_closehandle(dbenv, &fh)) != 0 && ret == 0)
|
||||
err: if (fhp != NULL &&
|
||||
(t_ret = __os_closehandle(dbenv, fhp)) != 0 && ret == 0)
|
||||
ret = t_ret;
|
||||
__os_free(dbenv, real_name);
|
||||
|
||||
@@ -277,7 +305,8 @@ __db_page_pass(dbp, real_name, flags, fl, fhp)
|
||||
/* Walk the file, calling the underlying conversion functions. */
|
||||
for (i = 0; i < pgno_last; ++i) {
|
||||
if (dbp->db_feedback != NULL)
|
||||
dbp->db_feedback(dbp, DB_UPGRADE, (i * 100)/pgno_last);
|
||||
dbp->db_feedback(
|
||||
dbp, DB_UPGRADE, (int)((i * 100)/pgno_last));
|
||||
if ((ret = __os_seek(dbenv,
|
||||
fhp, dbp->pgsize, i, 0, 0, DB_OS_SEEK_SET)) != 0)
|
||||
break;
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*-
|
||||
* See the file LICENSE for redistribution information.
|
||||
*
|
||||
* Copyright (c) 1996-2002
|
||||
* Copyright (c) 1996-2004
|
||||
* Sleepycat Software. All rights reserved.
|
||||
*
|
||||
* $Id: db_upg_opd.c,v 11.21 2004/03/19 16:10:26 bostic Exp $
|
||||
*/
|
||||
|
||||
#include "db_config.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char revid[] = "$Id: db_upg_opd.c,v 11.18 2002/08/06 06:11:18 bostic Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef NO_SYSTEM_INCLUDES
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -102,26 +100,26 @@ __db_31_offdup(dbp, real_name, fhp, sorted, pgnop)
|
||||
}
|
||||
|
||||
/* If we only have a single page, it's easy. */
|
||||
if (cur_cnt > 1) {
|
||||
/*
|
||||
* pgno_cur is the list of pages we just converted. We're
|
||||
* going to walk that list, but we'll need to create a new
|
||||
* list while we do so.
|
||||
*/
|
||||
if ((ret = __os_malloc(dbp->dbenv,
|
||||
cur_cnt * sizeof(db_pgno_t), &pgno_next)) != 0)
|
||||
goto err;
|
||||
if (cur_cnt <= 1)
|
||||
goto done;
|
||||
|
||||
/* Figure out where we can start allocating new pages. */
|
||||
if ((ret = __db_lastpgno(dbp, real_name, fhp, &pgno_last)) != 0)
|
||||
goto err;
|
||||
/*
|
||||
* pgno_cur is the list of pages we just converted. We're
|
||||
* going to walk that list, but we'll need to create a new
|
||||
* list while we do so.
|
||||
*/
|
||||
if ((ret = __os_malloc(dbp->dbenv,
|
||||
cur_cnt * sizeof(db_pgno_t), &pgno_next)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Allocate room for an internal page. */
|
||||
if ((ret = __os_malloc(dbp->dbenv,
|
||||
dbp->pgsize, &ipage)) != 0)
|
||||
goto err;
|
||||
PGNO(ipage) = PGNO_INVALID;
|
||||
}
|
||||
/* Figure out where we can start allocating new pages. */
|
||||
if ((ret = __db_lastpgno(dbp, real_name, fhp, &pgno_last)) != 0)
|
||||
goto err;
|
||||
|
||||
/* Allocate room for an internal page. */
|
||||
if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &ipage)) != 0)
|
||||
goto err;
|
||||
PGNO(ipage) = PGNO_INVALID;
|
||||
|
||||
/*
|
||||
* Repeatedly walk the list of pages, building internal pages, until
|
||||
@@ -181,7 +179,7 @@ __db_31_offdup(dbp, real_name, fhp, sorted, pgnop)
|
||||
pgno_next = tmp;
|
||||
}
|
||||
|
||||
*pgnop = pgno_cur[0];
|
||||
done: *pgnop = pgno_cur[0];
|
||||
|
||||
err: if (pgno_cur != NULL)
|
||||
__os_free(dbp->dbenv, pgno_cur);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user