Merge mysql.com:/home/jimw/my/mysql-5.1-bdb

into  mysql.com:/home/jimw/my/mysql-5.1-clean
This commit is contained in:
jimw@mysql.com 2005-12-06 10:57:55 -08:00
commit 6ec4bcc664
979 changed files with 30354 additions and 166312 deletions

View file

@ -133,137 +133,107 @@ autom4te.cache/*
autom4te.cache/output.0
autom4te.cache/requests
autom4te.cache/traces.0
bdb/*.ds?
bdb/*.vcproj
bdb/README
bdb/btree/btree_auto.c
bdb/build_unix/*
bdb/build_vxworks/db.h
bdb/build_vxworks/db_int.h
bdb/build_win32/db.h
bdb/build_win32/db_archive.dsp
bdb/build_win32/db_checkpoint.dsp
bdb/build_win32/db_config.h
bdb/build_win32/db_cxx.h
bdb/build_win32/db_deadlock.dsp
bdb/build_win32/db_dll.dsp
bdb/build_win32/db_dump.dsp
bdb/build_win32/db_int.h
bdb/build_win32/db_java.dsp
bdb/build_win32/db_load.dsp
bdb/build_win32/db_perf.dsp
bdb/build_win32/db_printlog.dsp
bdb/build_win32/db_recover.dsp
bdb/build_win32/db_stat.dsp
bdb/build_win32/db_static.dsp
bdb/build_win32/db_tcl.dsp
bdb/build_win32/db_test.dsp
bdb/build_win32/db_upgrade.dsp
bdb/build_win32/db_verify.dsp
bdb/build_win32/ex_access.dsp
bdb/build_win32/ex_btrec.dsp
bdb/build_win32/ex_env.dsp
bdb/build_win32/ex_lock.dsp
bdb/build_win32/ex_mpool.dsp
bdb/build_win32/ex_tpcb.dsp
bdb/build_win32/excxx_access.dsp
bdb/build_win32/excxx_btrec.dsp
bdb/build_win32/excxx_env.dsp
bdb/build_win32/excxx_lock.dsp
bdb/build_win32/excxx_mpool.dsp
bdb/build_win32/excxx_tpcb.dsp
bdb/build_win32/include.tcl
bdb/build_win32/libdb.def
bdb/build_win32/libdb.rc
bdb/db/crdel_auto.c
bdb/db/db_auto.c
bdb/dbinc_auto/*.*
bdb/dbreg/dbreg_auto.c
bdb/dist/autom4te-2.53.cache/*
bdb/dist/autom4te-2.53.cache/output.0
bdb/dist/autom4te-2.53.cache/requests
bdb/dist/autom4te-2.53.cache/traces.0
bdb/dist/autom4te.cache/*
bdb/dist/autom4te.cache/output.0
bdb/dist/autom4te.cache/requests
bdb/dist/autom4te.cache/traces.0
bdb/dist/config.hin
bdb/dist/configure
bdb/dist/tags
bdb/dist/template/db_server_proc
bdb/dist/template/gen_client_ret
bdb/dist/template/rec_btree
bdb/dist/template/rec_crdel
bdb/dist/template/rec_db
bdb/dist/template/rec_dbreg
bdb/dist/template/rec_fileops
bdb/dist/template/rec_hash
bdb/dist/template/rec_log
bdb/dist/template/rec_qam
bdb/dist/template/rec_txn
bdb/examples_c/ex_apprec/ex_apprec_auto.c
bdb/examples_c/ex_apprec/ex_apprec_auto.h
bdb/examples_c/ex_apprec/ex_apprec_template
bdb/examples_java
bdb/fileops/fileops_auto.c
bdb/hash/hash_auto.c
bdb/include/btree_auto.h
bdb/include/btree_ext.h
bdb/include/clib_ext.h
bdb/include/common_ext.h
bdb/include/crdel_auto.h
bdb/include/db_auto.h
bdb/include/db_ext.h
bdb/include/db_server.h
bdb/include/env_ext.h
bdb/include/gen_client_ext.h
bdb/include/gen_server_ext.h
bdb/include/hash_auto.h
bdb/include/hash_ext.h
bdb/include/lock_ext.h
bdb/include/log_auto.h
bdb/include/log_ext.h
bdb/include/mp_ext.h
bdb/include/mutex_ext.h
bdb/include/os_ext.h
bdb/include/qam_auto.h
bdb/include/qam_ext.h
bdb/include/rpc_client_ext.h
bdb/include/rpc_server_ext.h
bdb/include/tcl_ext.h
bdb/include/txn_auto.h
bdb/include/txn_ext.h
bdb/include/xa_ext.h
bdb/java/src/com/sleepycat/db/Db.java
bdb/java/src/com/sleepycat/db/DbBtreeStat.java
bdb/java/src/com/sleepycat/db/DbConstants.java
bdb/java/src/com/sleepycat/db/DbHashStat.java
bdb/java/src/com/sleepycat/db/DbLockStat.java
bdb/java/src/com/sleepycat/db/DbLogStat.java
bdb/java/src/com/sleepycat/db/DbMpoolFStat.java
bdb/java/src/com/sleepycat/db/DbQueueStat.java
bdb/java/src/com/sleepycat/db/DbRepStat.java
bdb/java/src/com/sleepycat/db/DbTxnStat.java
bdb/libdb_java/java_stat_auto.c
bdb/libdb_java/java_stat_auto.h
bdb/log/log_auto.c
bdb/qam/qam_auto.c
bdb/rpc_client/db_server_clnt.c
bdb/rpc_client/gen_client.c
bdb/rpc_server/c/db_server_proc.c
bdb/rpc_server/c/db_server_proc.sed
bdb/rpc_server/c/db_server_svc.c
bdb/rpc_server/c/db_server_xdr.c
bdb/rpc_server/c/gen_db_server.c
bdb/rpc_server/db_server.x
bdb/rpc_server/db_server_proc.sed
bdb/rpc_server/db_server_svc.c
bdb/rpc_server/db_server_xdr.c
bdb/rpc_server/gen_db_server.c
bdb/test/TESTS
bdb/test/include.tcl
bdb/test/logtrack.list
bdb/txn/txn_auto.c
storage/bdb/*.ds?
storage/bdb/*.vcproj
storage/bdb/README
storage/bdb/btree/btree_auto.c
storage/bdb/build_unix/*
storage/bdb/build_vxworks/db.h
storage/bdb/build_vxworks/db_int.h
storage/bdb/build_win32/db.h
storage/bdb/build_win32/db_archive.dsp
storage/bdb/build_win32/db_checkpoint.dsp
storage/bdb/build_win32/db_config.h
storage/bdb/build_win32/db_cxx.h
storage/bdb/build_win32/db_deadlock.dsp
storage/bdb/build_win32/db_dll.dsp
storage/bdb/build_win32/db_dump.dsp
storage/bdb/build_win32/db_int.h
storage/bdb/build_win32/db_java.dsp
storage/bdb/build_win32/db_load.dsp
storage/bdb/build_win32/db_perf.dsp
storage/bdb/build_win32/db_printlog.dsp
storage/bdb/build_win32/db_recover.dsp
storage/bdb/build_win32/db_stat.dsp
storage/bdb/build_win32/db_static.dsp
storage/bdb/build_win32/db_tcl.dsp
storage/bdb/build_win32/db_test.dsp
storage/bdb/build_win32/db_upgrade.dsp
storage/bdb/build_win32/db_verify.dsp
storage/bdb/build_win32/ex_access.dsp
storage/bdb/build_win32/ex_btrec.dsp
storage/bdb/build_win32/ex_env.dsp
storage/bdb/build_win32/ex_lock.dsp
storage/bdb/build_win32/ex_mpool.dsp
storage/bdb/build_win32/ex_tpcb.dsp
storage/bdb/build_win32/excxx_access.dsp
storage/bdb/build_win32/excxx_btrec.dsp
storage/bdb/build_win32/excxx_env.dsp
storage/bdb/build_win32/excxx_lock.dsp
storage/bdb/build_win32/excxx_mpool.dsp
storage/bdb/build_win32/excxx_tpcb.dsp
storage/bdb/build_win32/include.tcl
storage/bdb/build_win32/libdb.def
storage/bdb/build_win32/libdb.rc
storage/bdb/db/crdel_auto.c
storage/bdb/db/db_auto.c
storage/bdb/dbinc_auto/*.*
storage/bdb/dbreg/dbreg_auto.c
storage/bdb/dist/autom4te-2.53.cache/*
storage/bdb/dist/autom4te-2.53.cache/output.0
storage/bdb/dist/autom4te-2.53.cache/requests
storage/bdb/dist/autom4te-2.53.cache/traces.0
storage/bdb/dist/autom4te.cache/*
storage/bdb/dist/autom4te.cache/output.0
storage/bdb/dist/autom4te.cache/requests
storage/bdb/dist/autom4te.cache/traces.0
storage/bdb/dist/config.hin
storage/bdb/dist/configure
storage/bdb/dist/tags
storage/bdb/dist/template/db_server_proc
storage/bdb/dist/template/gen_client_ret
storage/bdb/dist/template/rec_btree
storage/bdb/dist/template/rec_crdel
storage/bdb/dist/template/rec_db
storage/bdb/dist/template/rec_dbreg
storage/bdb/dist/template/rec_fileops
storage/bdb/dist/template/rec_hash
storage/bdb/dist/template/rec_log
storage/bdb/dist/template/rec_qam
storage/bdb/dist/template/rec_txn
storage/bdb/fileops/fileops_auto.c
storage/bdb/hash/hash_auto.c
storage/bdb/include/btree_auto.h
storage/bdb/include/btree_ext.h
storage/bdb/include/clib_ext.h
storage/bdb/include/common_ext.h
storage/bdb/include/crdel_auto.h
storage/bdb/include/db_auto.h
storage/bdb/include/db_ext.h
storage/bdb/include/db_server.h
storage/bdb/include/env_ext.h
storage/bdb/include/gen_client_ext.h
storage/bdb/include/gen_server_ext.h
storage/bdb/include/hash_auto.h
storage/bdb/include/hash_ext.h
storage/bdb/include/lock_ext.h
storage/bdb/include/log_auto.h
storage/bdb/include/log_ext.h
storage/bdb/include/mp_ext.h
storage/bdb/include/mutex_ext.h
storage/bdb/include/os_ext.h
storage/bdb/include/qam_auto.h
storage/bdb/include/qam_ext.h
storage/bdb/include/rpc_client_ext.h
storage/bdb/include/rpc_server_ext.h
storage/bdb/include/tcl_ext.h
storage/bdb/include/txn_auto.h
storage/bdb/include/txn_ext.h
storage/bdb/include/xa_ext.h
storage/bdb/log/log_auto.c
storage/bdb/qam/qam_auto.c
storage/bdb/txn/txn_auto.c
storage/bdb/txn/txn_autop.c
binary/*
bkpull.log
bkpull.log*

View file

@ -120,6 +120,28 @@
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
<File
RelativePath="crypto\aes_method.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\btree\bt_compact.c">
</File>
<File
RelativePath="btree\bt_compare.c">
<FileConfiguration
@ -500,6 +522,25 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="crypto\crypto.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="db\db.c">
<FileConfiguration
@ -595,6 +636,9 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\common\db_clock.c">
</File>
<File
RelativePath="db\db_conv.c">
<FileConfiguration
@ -994,25 +1038,6 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="env\db_shash.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="db\db_setid.c">
<FileConfiguration
@ -1051,6 +1076,25 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="env\db_shash.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="db\db_stati.c">
<FileConfiguration
@ -1279,6 +1323,9 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\env\env_failchk.c">
</File>
<File
RelativePath="env\env_file.c">
<FileConfiguration
@ -1374,6 +1421,9 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\env\env_register.c">
</File>
<File
RelativePath="env\env_stat.c">
<FileConfiguration
@ -1811,6 +1861,9 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\lock\lock_failchk.c">
</File>
<File
RelativePath="lock\lock_id.c">
<FileConfiguration
@ -1831,7 +1884,7 @@
</FileConfiguration>
</File>
<File
RelativePath="lock\lock_method.c">
RelativePath="lock\lock_list.c">
<FileConfiguration
Name="Max|Win32">
<Tool
@ -1850,7 +1903,7 @@
</FileConfiguration>
</File>
<File
RelativePath="lock\lock_list.c">
RelativePath="lock\lock_method.c">
<FileConfiguration
Name="Max|Win32">
<Tool
@ -2001,6 +2054,9 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\log\log_debug.c">
</File>
<File
RelativePath="log\log_get.c">
<FileConfiguration
@ -2324,6 +2380,37 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="crypto\mersenne\mt19937db.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\mutex\mut_alloc.c">
</File>
<File
RelativePath=".\mutex\mut_method.c">
</File>
<File
RelativePath=".\mutex\mut_region.c">
</File>
<File
RelativePath=".\mutex\mut_stat.c">
</File>
<File
RelativePath="mutex\mut_tas.c">
<FileConfiguration
@ -2362,25 +2449,6 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="mutex\mutex.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="os_win32\os_abs.c">
<FileConfiguration
@ -2514,6 +2582,9 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\os_win32\os_flock.c">
</File>
<File
RelativePath="os_win32\os_fsync.c">
<FileConfiguration
@ -3103,6 +3174,12 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\rep\rep_elect.c">
</File>
<File
RelativePath=".\rep\rep_log.c">
</File>
<File
RelativePath="rep\rep_method.c">
<FileConfiguration
@ -3179,6 +3256,9 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\rep\rep_stub.c">
</File>
<File
RelativePath="rep\rep_util.c">
<FileConfiguration
@ -3198,6 +3278,47 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\rep\rep_verify.c">
</File>
<File
RelativePath="crypto\rijndael\rijndael-alg-fst.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="crypto\rijndael\rijndael-api-fst.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="hmac\sha1.c">
<FileConfiguration
@ -3274,6 +3395,12 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\txn\txn_chkpt.c">
</File>
<File
RelativePath=".\txn\txn_failchk.c">
</File>
<File
RelativePath="txn\txn_method.c">
<FileConfiguration
@ -3483,101 +3610,6 @@
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="crypto\aes_method.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="crypto\crypto.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="crypto\mersenne\mt19937db.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="crypto\rijndael\rijndael-api-fst.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="crypto\rijndael\rijndael-alg-fst.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"

View file

@ -1,5 +1,5 @@
/*-
* $Id: LICENSE,v 11.12 2004/03/30 20:49:44 bostic Exp $
* $Id: LICENSE,v 12.1 2005/06/16 20:20:10 bostic Exp $
*/
The following is the license that applies to this copy of the Berkeley DB
@ -10,7 +10,7 @@ the Web at http://www.sleepycat.com.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
/*
* Copyright (c) 1990-2004
* Copyright (c) 1990-2005
* Sleepycat Software. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

View file

@ -24,13 +24,12 @@ top_srcdir = @top_srcdir@
bdb_build = build_unix
files = LICENSE Makefile Makefile.in README
subdirs = btree build_vxworks build_win32 clib common cxx db dbinc \
subdirs = btree build_win32 clib common cxx db dbinc \
dbinc_auto db185 db_archive db_checkpoint db_deadlock db_dump \
db_dump185 db_load db_printlog db_recover db_stat db_upgrade \
db_verify dbm dbreg dist env examples_c examples_cxx fileops hash \
hsearch hmac include java libdb_java lock log mp mutex os os_vxworks \
os_win32 perl.BerkeleyDB perl.DB_File qam rep rpc_client rpc_server tcl \
test txn xa sequence
db_dump185 db_hotbackup db_load db_printlog db_recover db_stat db_upgrade \
db_verify dbm dbreg dist env fileops hash \
hsearch hmac include lock log mp mutex os \
os_win32 qam rep txn xa sequence
@SET_MAKE@

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -39,7 +39,7 @@
* 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 $
* $Id: bt_compare.c,v 12.1 2005/06/16 20:20:13 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_conv.c,v 11.15 2004/01/28 03:35:48 bostic Exp $
* $Id: bt_conv.c,v 12.2 2005/06/16 20:20:13 bostic Exp $
*/
#include "db_config.h"
@ -88,7 +88,7 @@ __bam_mswap(pg)
p = (u_int8_t *)pg + sizeof(DBMETA);
SWAP32(p); /* maxkey */
p += sizeof(u_int32_t); /* unused */
SWAP32(p); /* minkey */
SWAP32(p); /* re_len */
SWAP32(p); /* re_pad */

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_curadj.c,v 11.37 2004/03/13 14:11:33 bostic Exp $
* $Id: bt_curadj.c,v 12.3 2005/07/20 16:50:45 bostic Exp $
*/
#include "db_config.h"
@ -35,14 +35,14 @@ static int __bam_opd_cursor __P((DB *, DBC *, db_pgno_t, u_int32_t, u_int32_t));
* Update the cursors when items are deleted and when already deleted
* items are overwritten. Return the number of relevant cursors found.
*
* PUBLIC: int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, int));
* PUBLIC: int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, int, int *));
*/
int
__bam_ca_delete(dbp, pgno, indx, delete)
__bam_ca_delete(dbp, pgno, indx, delete, countp)
DB *dbp;
db_pgno_t pgno;
u_int32_t indx;
int delete;
int delete, *countp;
{
BTREE_CURSOR *cp;
DB *ldbp;
@ -63,11 +63,11 @@ __bam_ca_delete(dbp, pgno, indx, delete)
* Each cursor is single-threaded, so we only need to lock the
* list of DBs and then the list of cursors in each DB.
*/
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (count = 0, ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (BTREE_CURSOR *)dbc->internal;
@ -92,23 +92,26 @@ __bam_ca_delete(dbp, pgno, indx, delete)
++count;
}
}
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (count);
if (countp != NULL)
*countp = count;
return (0);
}
/*
* __ram_ca_delete --
* Return the number of relevant cursors.
* Return if any relevant cursors found.
*
* PUBLIC: int __ram_ca_delete __P((DB *, db_pgno_t));
* PUBLIC: int __ram_ca_delete __P((DB *, db_pgno_t, int *));
*/
int
__ram_ca_delete(dbp, root_pgno)
__ram_ca_delete(dbp, root_pgno, foundp)
DB *dbp;
db_pgno_t root_pgno;
int *foundp;
{
DB *ldbp;
DBC *dbc;
@ -121,19 +124,21 @@ __ram_ca_delete(dbp, root_pgno)
/*
* Review the cursors. See the comment in __bam_ca_delete().
*/
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
found == 0 && ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
found == 0 && dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
if (dbc->internal->root == root_pgno)
found = 1;
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
return (found);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
*foundp = found;
return (0);
}
/*
@ -166,11 +171,11 @@ __bam_ca_di(my_dbc, pgno, indx, adjust)
* Adjust the cursors. See the comment in __bam_ca_delete().
*/
found = 0;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO)
@ -188,9 +193,9 @@ __bam_ca_di(my_dbc, pgno, indx, adjust)
found = 1;
}
}
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn, &lsn, 0,
@ -289,11 +294,11 @@ __bam_ca_dup(my_dbc, first, fpgno, fi, tpgno, ti)
* Adjust the cursors. See the comment in __bam_ca_delete().
*/
found = 0;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
loop: MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
/* Find cursors pointing to this record. */
@ -308,7 +313,7 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
if (orig_cp->opd != NULL)
continue;
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
/* [#8032]
DB_ASSERT(!STD_LOCKING(dbc) ||
orig_cp->lock_mode != DB_LOCK_NG);
@ -321,9 +326,9 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
/* We released the mutex to get a cursor, start over. */
goto loop;
}
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn,
@ -359,11 +364,11 @@ __bam_ca_undodup(dbp, first, fpgno, fi, ti)
/*
* Adjust the cursors. See the comment in __bam_ca_delete().
*/
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
loop: MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
orig_cp = (BTREE_CURSOR *)dbc->internal;
@ -377,11 +382,10 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
*/
if (orig_cp->pgno != fpgno ||
orig_cp->indx != first ||
orig_cp->opd == NULL ||
((BTREE_CURSOR *)orig_cp->opd->internal)->indx
!= ti)
orig_cp->opd == NULL || ((BTREE_CURSOR *)
orig_cp->opd->internal)->indx != ti)
continue;
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
if ((ret = __db_c_close(orig_cp->opd)) != 0)
return (ret);
orig_cp->opd = NULL;
@ -392,9 +396,9 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
*/
goto loop;
}
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (0);
}
@ -425,11 +429,11 @@ __bam_ca_rsplit(my_dbc, fpgno, tpgno)
* Adjust the cursors. See the comment in __bam_ca_delete().
*/
found = 0;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO)
@ -444,9 +448,9 @@ __bam_ca_rsplit(my_dbc, fpgno, tpgno)
found = 1;
}
}
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn,
@ -493,11 +497,11 @@ __bam_ca_split(my_dbc, ppgno, lpgno, rpgno, split_indx, cleft)
* records split to the left page.
*/
found = 0;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO)
@ -519,9 +523,9 @@ __bam_ca_split(my_dbc, ppgno, lpgno, rpgno, split_indx, cleft)
}
}
}
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp,
@ -540,10 +544,10 @@ __bam_ca_split(my_dbc, ppgno, lpgno, rpgno, split_indx, cleft)
* left and the right pages.
* Called only during undo processing.
*
* PUBLIC: void __bam_ca_undosplit __P((DB *,
* PUBLIC: int __bam_ca_undosplit __P((DB *,
* PUBLIC: db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t));
*/
void
int
__bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx)
DB *dbp;
db_pgno_t frompgno, topgno, lpgno;
@ -562,11 +566,11 @@ __bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx)
* When backing out a split, we move the cursor back
* to the original offset and bump it by the split_indx.
*/
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO)
@ -578,7 +582,9 @@ __bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx)
} else if (cp->pgno == lpgno)
cp->pgno = frompgno;
}
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (0);
}

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_cursor.c,v 11.190 2004/09/22 21:46:32 ubell Exp $
* $Id: bt_cursor.c,v 12.7 2005/08/08 14:27:59 bostic Exp $
*/
#include "db_config.h"
@ -26,10 +26,8 @@ static int __bam_bulk __P((DBC *, DBT *, u_int32_t));
static int __bam_c_close __P((DBC *, db_pgno_t, int *));
static int __bam_c_del __P((DBC *));
static int __bam_c_destroy __P((DBC *));
static int __bam_c_first __P((DBC *));
static int __bam_c_get __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
static int __bam_c_getstack __P((DBC *));
static int __bam_c_last __P((DBC *));
static int __bam_c_next __P((DBC *, int, int));
static int __bam_c_physdel __P((DBC *));
static int __bam_c_prev __P((DBC *));
@ -68,21 +66,6 @@ static int __bam_isopd __P((DBC *, db_pgno_t *));
ret = __memp_fget(__mpf, &(fpgno), 0, &(pagep)); \
} while (0)
#undef ACQUIRE_COUPLE
#define ACQUIRE_COUPLE(dbc, mode, lpgno, lock, fpgno, pagep, ret) do { \
DB_MPOOLFILE *__mpf = (dbc)->dbp->mpf; \
if ((pagep) != NULL) { \
ret = __memp_fput(__mpf, pagep, 0); \
pagep = NULL; \
} else \
ret = 0; \
if ((ret) == 0 && STD_LOCKING(dbc)) \
ret = __db_lget(dbc, \
LCK_COUPLE_ALWAYS, lpgno, mode, 0, &(lock)); \
if ((ret) == 0) \
ret = __memp_fget(__mpf, &(fpgno), 0, &(pagep)); \
} while (0)
/* Acquire a new page/lock for a cursor. */
#undef ACQUIRE_CUR
#define ACQUIRE_CUR(dbc, mode, p, ret) do { \
@ -96,23 +79,6 @@ static int __bam_isopd __P((DBC *, db_pgno_t *));
} \
} while (0)
/*
* Acquire a new page/lock for a cursor and release the previous.
* This is typically used when descending a tree and we do not
* want to hold the interior nodes locked.
*/
#undef ACQUIRE_CUR_COUPLE
#define ACQUIRE_CUR_COUPLE(dbc, mode, p, ret) do { \
BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal; \
if (p != __cp->pgno) \
__cp->pgno = PGNO_INVALID; \
ACQUIRE_COUPLE(dbc, mode, p, __cp->lock, p, __cp->page, ret); \
if ((ret) == 0) { \
__cp->pgno = p; \
__cp->lock_mode = (mode); \
} \
} while (0)
/*
* Acquire a write lock if we don't already have one.
*
@ -196,11 +162,11 @@ __bam_c_init(dbc, dbtype)
/* Allocate/initialize the internal structure. */
if (dbc->internal == NULL && (ret =
__os_malloc(dbenv, sizeof(BTREE_CURSOR), &dbc->internal)) != 0)
__os_calloc(dbenv, 1, sizeof(BTREE_CURSOR), &dbc->internal)) != 0)
return (ret);
/* Initialize methods. */
dbc->c_close = __db_c_close;
dbc->c_close = __db_c_close_pp;
dbc->c_count = __db_c_count_pp;
dbc->c_del = __db_c_del_pp;
dbc->c_dup = __db_c_dup_pp;
@ -257,8 +223,11 @@ __bam_c_refresh(dbc)
LOCK_INIT(cp->lock);
cp->lock_mode = DB_LOCK_NG;
cp->sp = cp->csp = cp->stack;
cp->esp = cp->stack + sizeof(cp->stack) / sizeof(cp->stack[0]);
if (cp->sp == NULL) {
cp->sp = cp->stack;
cp->esp = cp->stack + sizeof(cp->stack) / sizeof(cp->stack[0]);
}
BT_STK_CLR(cp);
/*
* The btree leaf page data structures require that two key/data pairs
@ -308,7 +277,7 @@ __bam_c_close(dbc, root_pgno, rmroot)
DBC *dbc_opd, *dbc_c;
DB_MPOOLFILE *mpf;
PAGE *h;
int cdb_lock, ret;
int cdb_lock, count, ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
@ -378,22 +347,28 @@ __bam_c_close(dbc, root_pgno, rmroot)
dbc_c = dbc;
switch (dbc->dbtype) {
case DB_BTREE: /* Case #1, #3. */
if (__bam_ca_delete(dbp, cp->pgno, cp->indx, 1) == 0)
if ((ret = __bam_ca_delete(
dbp, cp->pgno, cp->indx, 1, &count)) != 0)
goto err;
if (count == 0)
goto lock;
goto done;
case DB_RECNO:
if (!F_ISSET(dbc, DBC_OPD)) /* Case #1. */
goto done;
/* Case #3. */
if (__ram_ca_delete(dbp, cp->root) == 0)
if ((ret = __ram_ca_delete(dbp, cp->root, &count)) != 0)
goto err;
if (count == 0)
goto lock;
goto done;
case DB_HASH:
case DB_QUEUE:
case DB_UNKNOWN:
default:
return (__db_unknown_type(dbp->dbenv,
"__bam_c_close", dbc->dbtype));
ret = __db_unknown_type(dbp->dbenv,
"__bam_c_close", dbc->dbtype);
goto err;
}
}
@ -414,20 +389,26 @@ __bam_c_close(dbc, root_pgno, rmroot)
dbc_c = dbc_opd;
switch (dbc_opd->dbtype) {
case DB_BTREE:
if (__bam_ca_delete(
dbp, cp_opd->pgno, cp_opd->indx, 1) == 0)
if ((ret = __bam_ca_delete(
dbp, cp_opd->pgno, cp_opd->indx, 1, &count)) != 0)
goto err;
if (count == 0)
goto lock;
goto done;
case DB_RECNO:
if (__ram_ca_delete(dbp, cp_opd->root) == 0)
if ((ret =
__ram_ca_delete(dbp, cp_opd->root, &count)) != 0)
goto err;
if (count == 0)
goto lock;
goto done;
case DB_HASH:
case DB_QUEUE:
case DB_UNKNOWN:
default:
return (__db_unknown_type(
dbp->dbenv, "__bam_c_close", dbc->dbtype));
ret = __db_unknown_type(
dbp->dbenv, "__bam_c_close", dbc->dbtype);
goto err;
}
}
goto done;
@ -588,8 +569,14 @@ static int
__bam_c_destroy(dbc)
DBC *dbc;
{
BTREE_CURSOR *cp;
cp = (BTREE_CURSOR *)dbc->internal;
/* Discard the structures. */
__os_free(dbc->dbp->dbenv, dbc->internal);
if (cp->sp != cp->stack)
__os_free(dbc->dbp->dbenv, cp->sp);
__os_free(dbc->dbp->dbenv, cp);
return (0);
}
@ -693,7 +680,7 @@ __bam_c_del(dbc)
BTREE_CURSOR *cp;
DB *dbp;
DB_MPOOLFILE *mpf;
int ret, t_ret;
int count, ret, t_ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
@ -760,9 +747,12 @@ err: /*
cp->page = NULL;
/* Update the cursors last, after all chance of failure is past. */
/*
* Update the cursors last, after all chance of recoverable failure
* is past.
*/
if (ret == 0)
(void)__bam_ca_delete(dbp, cp->pgno, cp->indx, 1);
ret = __bam_ca_delete(dbp, cp->pgno, cp->indx, 1, &count);
return (ret);
}
@ -846,7 +836,8 @@ __bam_c_get(dbc, key, data, flags, pgnop)
break;
case DB_FIRST:
newopd = 1;
if ((ret = __bam_c_first(dbc)) != 0)
if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, flags, &exact)) != 0)
goto err;
break;
case DB_GET_BOTH:
@ -910,13 +901,15 @@ __bam_c_get(dbc, key, data, flags, pgnop)
break;
case DB_LAST:
newopd = 1;
if ((ret = __bam_c_last(dbc)) != 0)
if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, flags, &exact)) != 0)
goto err;
break;
case DB_NEXT:
newopd = 1;
if (cp->pgno == PGNO_INVALID) {
if ((ret = __bam_c_first(dbc)) != 0)
if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, DB_FIRST, &exact)) != 0)
goto err;
} else
if ((ret = __bam_c_next(dbc, 1, 0)) != 0)
@ -933,7 +926,8 @@ __bam_c_get(dbc, key, data, flags, pgnop)
case DB_NEXT_NODUP:
newopd = 1;
if (cp->pgno == PGNO_INVALID) {
if ((ret = __bam_c_first(dbc)) != 0)
if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, DB_FIRST, &exact)) != 0)
goto err;
} else
do {
@ -944,7 +938,8 @@ __bam_c_get(dbc, key, data, flags, pgnop)
case DB_PREV:
newopd = 1;
if (cp->pgno == PGNO_INVALID) {
if ((ret = __bam_c_last(dbc)) != 0)
if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, DB_LAST, &exact)) != 0)
goto err;
} else
if ((ret = __bam_c_prev(dbc)) != 0)
@ -953,7 +948,8 @@ __bam_c_get(dbc, key, data, flags, pgnop)
case DB_PREV_NODUP:
newopd = 1;
if (cp->pgno == PGNO_INVALID) {
if ((ret = __bam_c_last(dbc)) != 0)
if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, DB_LAST, &exact)) != 0)
goto err;
} else
do {
@ -2136,99 +2132,6 @@ __bam_c_writelock(dbc)
return (ret);
}
/*
* __bam_c_first --
* Return the first record.
*/
static int
__bam_c_first(dbc)
DBC *dbc;
{
BTREE_CURSOR *cp;
db_pgno_t pgno;
int ret;
cp = (BTREE_CURSOR *)dbc->internal;
ret = 0;
/* Walk down the left-hand side of the tree. */
for (pgno = cp->root;;) {
ACQUIRE_CUR_COUPLE(dbc, DB_LOCK_READ, pgno, ret);
if (ret != 0)
return (ret);
/* If we find a leaf page, we're done. */
if (ISLEAF(cp->page))
break;
pgno = GET_BINTERNAL(dbc->dbp, cp->page, 0)->pgno;
}
/* If we want a write lock instead of a read lock, get it now. */
if (F_ISSET(dbc, DBC_RMW)) {
ACQUIRE_WRITE_LOCK(dbc, ret);
if (ret != 0)
return (ret);
}
cp->indx = 0;
/* If on an empty page or a deleted record, move to the next one. */
if (NUM_ENT(cp->page) == 0 || IS_CUR_DELETED(dbc))
if ((ret = __bam_c_next(dbc, 0, 0)) != 0)
return (ret);
return (0);
}
/*
* __bam_c_last --
* Return the last record.
*/
static int
__bam_c_last(dbc)
DBC *dbc;
{
BTREE_CURSOR *cp;
db_pgno_t pgno;
int ret;
cp = (BTREE_CURSOR *)dbc->internal;
ret = 0;
/* Walk down the right-hand side of the tree. */
for (pgno = cp->root;;) {
ACQUIRE_CUR_COUPLE(dbc, DB_LOCK_READ, pgno, ret);
if (ret != 0)
return (ret);
/* If we find a leaf page, we're done. */
if (ISLEAF(cp->page))
break;
pgno = GET_BINTERNAL(dbc->dbp, cp->page,
NUM_ENT(cp->page) - O_INDX)->pgno;
}
/* If we want a write lock instead of a read lock, get it now. */
if (F_ISSET(dbc, DBC_RMW)) {
ACQUIRE_WRITE_LOCK(dbc, ret);
if (ret != 0)
return (ret);
}
cp->indx = NUM_ENT(cp->page) == 0 ? 0 :
NUM_ENT(cp->page) -
(TYPE(cp->page) == P_LBTREE ? P_INDX : O_INDX);
/* If on an empty page or a deleted record, move to the previous one. */
if (NUM_ENT(cp->page) == 0 || IS_CUR_DELETED(dbc))
if ((ret = __bam_c_prev(dbc)) != 0)
return (ret);
return (0);
}
/*
* __bam_c_next --
* Move to the next record.
@ -2398,6 +2301,12 @@ __bam_c_search(dbc, root_pgno, key, flags, exactp)
return (ret);
switch (flags) {
case DB_FIRST:
sflags = (F_ISSET(dbc, DBC_RMW) ? S_WRITE : S_READ) | S_MIN;
goto search;
case DB_LAST:
sflags = (F_ISSET(dbc, DBC_RMW) ? S_WRITE : S_READ) | S_MAX;
goto search;
case DB_SET_RECNO:
if ((ret = __ram_getno(dbc, key, &recno, 0)) != 0)
return (ret);
@ -2575,7 +2484,6 @@ search: if ((ret = __bam_search(dbc, root_pgno,
default:
return (__db_unknown_flag(dbp->dbenv, "__bam_c_search", flags));
}
/* Initialize the cursor from the stack. */
cp->page = cp->csp->page;
cp->pgno = cp->csp->page->pgno;
@ -2583,6 +2491,16 @@ search: if ((ret = __bam_search(dbc, root_pgno,
cp->lock = cp->csp->lock;
cp->lock_mode = cp->csp->lock_mode;
/* If on an empty page or a deleted record, move to the next one. */
if (flags == DB_FIRST &&
(NUM_ENT(cp->page) == 0 || IS_CUR_DELETED(dbc)))
if ((ret = __bam_c_next(dbc, 0, 0)) != 0)
return (ret);
if (flags == DB_LAST &&
(NUM_ENT(cp->page) == 0 || IS_CUR_DELETED(dbc)))
if ((ret = __bam_c_prev(dbc)) != 0)
return (ret);
return (0);
}
@ -2597,15 +2515,10 @@ __bam_c_physdel(dbc)
BTREE_CURSOR *cp;
DB *dbp;
DBT key;
DB_LOCK lock;
DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t pgno;
int delete_page, empty_page, exact, level, ret;
int delete_page, empty_page, exact, ret;
dbp = dbc->dbp;
memset(&key, 0, sizeof(DBT));
mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
delete_page = empty_page = ret = 0;
@ -2683,91 +2596,7 @@ __bam_c_physdel(dbc)
if (!delete_page)
return (0);
/*
* Call __bam_search to reacquire the empty leaf page, but this time
* get both the leaf page and it's parent, locked. Jump back up the
* tree, until we have the top pair of pages that we want to delete.
* Once we have the top page that we want to delete locked, lock the
* underlying pages and check to make sure they're still empty. If
* they are, delete them.
*/
for (level = LEAFLEVEL;; ++level) {
/* Acquire a page and its parent, locked. */
if ((ret = __bam_search(dbc, PGNO_INVALID,
&key, S_WRPAIR, level, NULL, &exact)) != 0)
return (ret);
/*
* If we reach the root or the parent page isn't going to be
* empty when we delete one record, stop.
*/
h = cp->csp[-1].page;
if (h->pgno == cp->root || NUM_ENT(h) != 1)
break;
/* Discard the stack, retaining no locks. */
(void)__bam_stkrel(dbc, STK_NOLOCK);
}
/*
* Move the stack pointer one after the last entry, we may be about
* to push more items onto the page stack.
*/
++cp->csp;
/*
* cp->csp[-2].page is now the parent page, which we may or may not be
* going to delete, and cp->csp[-1].page is the first page we know we
* are going to delete. Walk down the chain of pages, acquiring pages
* until we've acquired a leaf page. Generally, this shouldn't happen;
* we should only see a single internal page with one item and a single
* leaf page with no items. The scenario where we could see something
* else is if reverse splits were turned off for awhile and then turned
* back on. That could result in all sorts of strangeness, e.g., empty
* pages in the tree, trees that looked like linked lists, and so on.
*
* !!!
* Sheer paranoia: if we find any pages that aren't going to be emptied
* by the delete, someone else added an item while we were walking the
* tree, and we discontinue the delete. Shouldn't be possible, but we
* check regardless.
*/
for (h = cp->csp[-1].page;;) {
if (ISLEAF(h)) {
if (NUM_ENT(h) != 0)
break;
break;
} else
if (NUM_ENT(h) != 1)
break;
/*
* Get the next page, write lock it and push it onto the stack.
* We know it's index 0, because it can only have one element.
*/
switch (TYPE(h)) {
case P_IBTREE:
pgno = GET_BINTERNAL(dbp, h, 0)->pgno;
break;
case P_IRECNO:
pgno = GET_RINTERNAL(dbp, h, 0)->pgno;
break;
default:
return (__db_pgfmt(dbp->dbenv, PGNO(h)));
}
if ((ret =
__db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &lock)) != 0)
break;
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
break;
BT_STK_PUSH(dbp->dbenv, cp, h, 0, lock, DB_LOCK_WRITE, ret);
if (ret != 0)
break;
}
/* Adjust the cursor stack to reference the last page on the stack. */
BT_STK_POP(cp);
ret = __bam_search(dbc, PGNO_INVALID, &key, S_DEL, 0, NULL, &exact);
/*
* If everything worked, delete the stack, otherwise, release the
@ -2776,7 +2605,7 @@ __bam_c_physdel(dbc)
if (ret == 0)
DISCARD_CUR(dbc, ret);
if (ret == 0)
ret = __bam_dpages(dbc, cp->sp);
ret = __bam_dpages(dbc, 1, 0);
else
(void)__bam_stkrel(dbc, 0);

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -39,7 +39,7 @@
* 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 $
* $Id: bt_delete.c,v 12.13 2005/10/20 18:14:59 bostic Exp $
*/
#include "db_config.h"
@ -220,12 +220,13 @@ __bam_adjindx(dbc, h, indx, indx_copy, is_insert)
* __bam_dpages --
* Delete a set of locked pages.
*
* PUBLIC: int __bam_dpages __P((DBC *, EPG *));
* PUBLIC: int __bam_dpages __P((DBC *, int, int));
*/
int
__bam_dpages(dbc, stack_epg)
__bam_dpages(dbc, use_top, update)
DBC *dbc;
EPG *stack_epg;
int use_top;
int update;
{
BTREE_CURSOR *cp;
BINTERNAL *bi;
@ -233,7 +234,7 @@ __bam_dpages(dbc, stack_epg)
DBT a, b;
DB_LOCK c_lock, p_lock;
DB_MPOOLFILE *mpf;
EPG *epg;
EPG *epg, *save_sp, *stack_epg;
PAGE *child, *parent;
db_indx_t nitems;
db_pgno_t pgno, root_pgno;
@ -243,30 +244,27 @@ __bam_dpages(dbc, stack_epg)
dbp = dbc->dbp;
mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
nitems = 0;
pgno = PGNO_INVALID;
/*
* We have the entire stack of deletable pages locked.
*
* Btree calls us with a pointer to the beginning of a stack, where
* the first page in the stack is to have a single item deleted, and
* the rest of the pages are to be removed.
* Btree calls us with the first page in the stack is to have a
* single item deleted, and the rest of the pages are to be removed.
*
* Recno calls us with a pointer into the middle of the stack, where
* the referenced page is to have a single item deleted, and pages
* after the stack reference are to be removed.
*
* First, discard any pages that we don't care about.
* Recno always has a stack to the root and __bam_merge operations
* may have unneeded items in the sack. We find the lowest page
* in the stack that has more than one record in it and start there.
*/
ret = 0;
for (epg = cp->sp; epg < stack_epg; ++epg) {
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;
}
if (ret != 0)
goto err;
if (use_top)
stack_epg = cp->sp;
else
for (stack_epg = cp->csp; stack_epg > cp->sp; --stack_epg)
if (NUM_ENT(stack_epg->page) > 1)
break;
epg = stack_epg;
/*
* !!!
* There is an interesting deadlock situation here. We have to relink
@ -276,8 +274,9 @@ __bam_dpages(dbc, stack_epg)
* It will deadlock here. Before we unlink the subtree, we relink the
* leaf page chain.
*/
if ((ret = __bam_relink(dbc, cp->csp->page, NULL)) != 0)
goto err;
if (LEVEL(cp->csp->page) == 1 &&
(ret = __bam_relink(dbc, cp->csp->page, PGNO_INVALID)) != 0)
goto discard;
/*
* Delete the last item that references the underlying pages that are
@ -288,9 +287,18 @@ __bam_dpages(dbc, stack_epg)
* immediately.
*/
if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0)
goto err;
goto discard;
if ((ret = __bam_ca_di(dbc, PGNO(epg->page), epg->indx, -1)) != 0)
goto err;
goto discard;
if (update && epg->indx == 0) {
save_sp = cp->csp;
cp->csp = epg;
ret = __bam_pupdate(dbc, epg->page);
cp->csp = save_sp;
if (ret != 0)
goto discard;
}
pgno = PGNO(epg->page);
nitems = NUM_ENT(epg->page);
@ -301,6 +309,17 @@ __bam_dpages(dbc, stack_epg)
if (ret != 0)
goto err_inc;
/* Then, discard any pages that we don't care about. */
discard: for (epg = cp->sp; epg < stack_epg; ++epg) {
if ((t_ret = __memp_fput(mpf, epg->page, 0)) != 0 && ret == 0)
ret = t_ret;
epg->page = NULL;
if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
ret = t_ret;
}
if (ret != 0)
goto err;
/* Free the rest of the pages in the stack. */
while (++epg <= cp->csp) {
/*
@ -310,13 +329,24 @@ __bam_dpages(dbc, stack_epg)
* be referenced by a cursor.
*/
if (NUM_ENT(epg->page) != 0) {
DB_ASSERT(NUM_ENT(epg->page) == 1);
DB_ASSERT(LEVEL(epg->page) != 1);
if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0)
goto err;
/*
* Sheer paranoia: if we find any pages that aren't
* emptied by the delete, someone else added an item
* while we were walking the tree, and we discontinue
* the delete. Shouldn't be possible, but we check
* regardless.
*/
if (NUM_ENT(epg->page) != 0)
goto err;
}
ret = __db_free(dbc, epg->page);
if (cp->page == epg->page)
cp->page = NULL;
epg->page = NULL;
if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
ret = t_ret;
@ -468,12 +498,13 @@ stop: done = 1;
* __bam_relink --
* Relink around a deleted page.
*
* PUBLIC: int __bam_relink __P((DBC *, PAGE *, PAGE **));
* PUBLIC: int __bam_relink __P((DBC *, PAGE *, db_pgno_t));
*/
int
__bam_relink(dbc, pagep, new_next)
__bam_relink(dbc, pagep, new_pgno)
DBC *dbc;
PAGE *pagep, **new_next;
PAGE *pagep;
db_pgno_t new_pgno;
{
DB *dbp;
PAGE *np, *pp;
@ -519,7 +550,7 @@ __bam_relink(dbc, pagep, new_next)
/* 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->pgno, new_pgno, pagep->prev_pgno, plsnp,
pagep->next_pgno, nlsnp)) != 0)
goto err;
} else
@ -528,33 +559,27 @@ __bam_relink(dbc, pagep, new_next)
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 (new_pgno == PGNO_INVALID)
np->prev_pgno = pagep->prev_pgno;
else
np->prev_pgno = new_pgno;
ret = __memp_fput(mpf, np, DB_MPOOL_DIRTY);
if ((t_ret = __TLPUT(dbc, npl)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
goto err;
} else if (new_next != NULL)
*new_next = NULL;
}
if (pp != NULL) {
pp->next_pgno = pagep->next_pgno;
if (new_pgno == PGNO_INVALID)
pp->next_pgno = pagep->next_pgno;
else
pp->next_pgno = new_pgno;
ret = __memp_fput(mpf, pp, DB_MPOOL_DIRTY);
if ((t_ret = __TLPUT(dbc, ppl)) != 0 && ret == 0)
ret = t_ret;
@ -571,3 +596,48 @@ err: if (np != NULL)
(void)__TLPUT(dbc, ppl);
return (ret);
}
/*
* __bam_pupdate --
* Update parent key pointers up the tree.
*
* PUBLIC: int __bam_pupdate __P((DBC *, PAGE *));
*/
int
__bam_pupdate(dbc, lpg)
DBC *dbc;
PAGE *lpg;
{
BTREE_CURSOR *cp;
DB_ENV *dbenv;
EPG *epg;
int ret;
dbenv = dbc->dbp->dbenv;
cp = (BTREE_CURSOR *)dbc->internal;
ret = 0;
/*
* Update the parents up the tree. __bam_pinsert only looks at the
* left child if is a leaf page, so we don't need to change it. We
* just do a delete and insert; a replace is possible but reusing
* pinsert is better.
*/
for (epg = &cp->csp[-1]; epg >= cp->sp; epg--) {
if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0)
return (ret);
epg->indx--;
if ((ret = __bam_pinsert(dbc, epg,
lpg, epg[1].page, BPI_NORECNUM)) != 0) {
if (ret == DB_NEEDSPLIT) {
/* This should not happen. */
__db_err(dbenv,
"Not enough room in parent: %s: page %lu",
dbc->dbp->fname, (u_long)PGNO(epg->page));
ret = __db_panic(dbenv, EINVAL);
}
return (ret);
}
}
return (ret);
}

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1999-2004
* Copyright (c) 1999-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_method.c,v 11.38 2004/09/22 03:31:26 bostic Exp $
* $Id: bt_method.c,v 12.2 2005/06/16 20:20:16 bostic Exp $
*/
#include "db_config.h"
@ -18,7 +18,6 @@
#include "dbinc/btree.h"
#include "dbinc/qam.h"
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 *)));
@ -52,7 +51,6 @@ __bam_db_create(dbp)
t->bt_prefix = __bam_defpfx;
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;
@ -208,31 +206,6 @@ __bam_set_bt_compare(dbp, func)
return (0);
}
/*
* __bam_set_bt_maxkey --
* Set the maximum keys per page.
*/
static int
__bam_set_bt_maxkey(dbp, bt_maxkey)
DB *dbp;
u_int32_t bt_maxkey;
{
BTREE *t;
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_maxkey");
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
t = dbp->bt_internal;
if (bt_maxkey < 1) {
__db_err(dbp->dbenv, "minimum bt_maxkey value is 1");
return (EINVAL);
}
t->bt_maxkey = bt_maxkey;
return (0);
}
/*
* __db_get_bt_minkey --
* Get the minimum keys per page.

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -39,7 +39,7 @@
* 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 $
* $Id: bt_open.c,v 12.5 2005/09/28 17:44:17 margo Exp $
*/
#include "db_config.h"
@ -311,7 +311,6 @@ __bam_read_root(dbp, txn, base_pgno, flags)
* metadata page will be created/initialized elsewhere.
*/
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;
@ -395,7 +394,6 @@ __bam_init_meta(dbp, meta, pgno, lsnp)
memcpy(meta->dbmeta.uid, dbp->fileid, DB_FILE_ID_LEN);
t = dbp->bt_internal;
meta->maxkey = t->bt_maxkey;
meta->minkey = t->bt_minkey;
meta->re_len = t->re_len;
meta->re_pad = (u_int32_t)t->re_pad;
@ -428,7 +426,7 @@ __bam_new_file(dbp, txn, fhp, name)
DBT pdbt;
PAGE *root;
db_pgno_t pgno;
int ret;
int ret, t_ret;
void *buf;
dbenv = dbp->dbenv;
@ -437,7 +435,7 @@ __bam_new_file(dbp, txn, fhp, name)
meta = NULL;
buf = NULL;
if (name == NULL) {
if (F_ISSET(dbp, DB_AM_INMEM)) {
/* Build the meta-data page. */
pgno = PGNO_BASE_MD;
if ((ret =
@ -447,6 +445,9 @@ __bam_new_file(dbp, txn, fhp, name)
__bam_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
meta->root = 1;
meta->dbmeta.last_pgno = 1;
if ((ret =
__db_log_page(dbp, txn, &lsn, pgno, (PAGE *)meta)) != 0)
goto err;
ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY);
meta = NULL;
if (ret != 0)
@ -460,6 +461,9 @@ __bam_new_file(dbp, txn, fhp, name)
P_INIT(root, dbp->pgsize, 1, PGNO_INVALID, PGNO_INVALID,
LEAFLEVEL, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE);
LSN_NOT_LOGGED(root->lsn);
if ((ret =
__db_log_page(dbp, txn, &root->lsn, pgno, root)) != 0)
goto err;
ret = __memp_fput(mpf, root, DB_MPOOL_DIRTY);
root = NULL;
if (ret != 0)
@ -509,10 +513,12 @@ __bam_new_file(dbp, txn, fhp, name)
err: if (buf != NULL)
__os_free(dbenv, buf);
else {
if (meta != NULL)
(void)__memp_fput(mpf, meta, 0);
if (root != NULL)
(void)__memp_fput(mpf, root, 0);
if (meta != NULL &&
(t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
ret = t_ret;
if (root != NULL &&
(t_ret = __memp_fput(mpf, root, 0)) != 0 && ret == 0)
ret = t_ret;
}
return (ret);
}

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -39,7 +39,7 @@
* 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 $
* $Id: bt_put.c,v 12.10 2005/10/20 18:57:00 bostic Exp $
*/
#include "db_config.h"
@ -58,7 +58,9 @@
static int __bam_build
__P((DBC *, u_int32_t, DBT *, PAGE *, u_int32_t, u_int32_t));
static int __bam_dup_convert __P((DBC *, PAGE *, u_int32_t));
static int __bam_dup_check __P((DBC *, u_int32_t,
PAGE *, u_int32_t, u_int32_t, db_indx_t *));
static int __bam_dup_convert __P((DBC *, PAGE *, u_int32_t, u_int32_t));
static int __bam_ovput
__P((DBC *, u_int32_t, db_pgno_t, PAGE *, u_int32_t, DBT *));
static u_int32_t
@ -84,11 +86,12 @@ __bam_iitem(dbc, key, data, op, flags)
DBT bk_hdr, tdbt;
DB_MPOOLFILE *mpf;
PAGE *h;
db_indx_t indx;
u_int32_t data_size, have_bytes, need_bytes, needed;
db_indx_t cnt, indx;
u_int32_t data_size, have_bytes, need_bytes, needed, pages, pagespace;
int cmp, bigkey, bigdata, dupadjust, padrec, replace, ret, was_deleted;
COMPQUIET(bk, NULL);
COMPQUIET(cnt, 0);
dbp = dbc->dbp;
dbenv = dbp->dbenv;
@ -217,13 +220,39 @@ __bam_iitem(dbc, key, data, op, flags)
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.
*/
/* Split the page if there's not enough room. */
if (P_FREESPACE(dbp, h) < needed)
return (DB_NEEDSPLIT);
/*
* Check to see if we will convert to off page duplicates -- if
* so, we'll need a page.
*/
if (F_ISSET(dbp, DB_AM_DUP) &&
TYPE(h) == P_LBTREE && op != DB_KEYFIRST &&
P_FREESPACE(dbp, h) - needed <= dbp->pgsize / 2 &&
__bam_dup_check(dbc, op, h, indx, needed, &cnt)) {
pages = 1;
dupadjust = 1;
} else
pages = 0;
/*
* If we are not using transactions and there is a page limit
* set on the file, then figure out if things will fit before
* taking action.
*/
if (dbc->txn == NULL && dbp->mpf->mfp->maxpgno != 0) {
pagespace = P_MAXSPACE(dbp, dbp->pgsize);
if (bigdata)
pages += ((data_size - 1) / pagespace) + 1;
if (bigkey)
pages += ((key->size - 1) / pagespace) + 1;
if (pages > (dbp->mpf->mfp->maxpgno - dbp->mpf->mfp->last_pgno))
return (__db_space_err(dbp));
}
/*
* The code breaks it up into five cases:
*
@ -259,7 +288,6 @@ __bam_iitem(dbc, key, data, op, flags)
return (ret);
indx += 3;
dupadjust = 1;
cp->indx += 2;
} else {
@ -276,7 +304,6 @@ __bam_iitem(dbc, key, data, op, flags)
return (ret);
++indx;
dupadjust = 1;
}
break;
case DB_CURRENT:
@ -287,11 +314,11 @@ __bam_iitem(dbc, key, data, op, flags)
* will try and remove the item because the cursor's delete
* flag is set.
*/
(void)__bam_ca_delete(dbp, PGNO(h), indx, 0);
if ((ret = __bam_ca_delete(dbp, PGNO(h), indx, 0, NULL)) != 0)
return (ret);
if (TYPE(h) == P_LBTREE) {
++indx;
dupadjust = 1;
}
/*
@ -380,10 +407,9 @@ __bam_iitem(dbc, key, data, op, flags)
* up at least 25% of the space on the page. If it does, move it onto
* its own page.
*/
if (dupadjust && P_FREESPACE(dbp, h) <= dbp->pgsize / 2) {
if ((ret = __bam_dup_convert(dbc, h, indx - O_INDX)) != 0)
return (ret);
}
if (dupadjust &&
(ret = __bam_dup_convert(dbc, h, indx - O_INDX, cnt)) != 0)
return (ret);
/* If we've modified a recno file, set the flag. */
if (dbc->dbtype == DB_RECNO)
@ -664,26 +690,22 @@ __bam_ritem(dbc, h, indx, data)
}
/*
* __bam_dup_convert --
* __bam_dup_check --
* Check to see if the duplicate set at indx should have its own page.
* If it should, create it.
*/
static int
__bam_dup_convert(dbc, h, indx)
__bam_dup_check(dbc, op, h, indx, sz, cntp)
DBC *dbc;
u_int32_t op;
PAGE *h;
u_int32_t indx;
u_int32_t indx, sz;
db_indx_t *cntp;
{
BKEYDATA *bk;
DB *dbp;
DBT hdr;
DB_MPOOLFILE *mpf;
PAGE *dp;
db_indx_t cnt, cpindx, dindx, first, *inp, sz;
int ret;
db_indx_t cnt, first, *inp;
dbp = dbc->dbp;
mpf = dbp->mpf;
inp = P_INP(dbp, h);
/*
@ -695,11 +717,21 @@ __bam_dup_convert(dbc, h, indx)
/* Count the key once. */
bk = GET_BKEYDATA(dbp, h, indx);
sz = B_TYPE(bk->type) == B_KEYDATA ?
sz += B_TYPE(bk->type) == B_KEYDATA ?
BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE;
/* Sum up all the data items. */
for (cnt = 0, first = indx;
first = indx;
/*
* Account for the record being inserted. If we are replacing it,
* don't count it twice.
*
* We execute the loop with first == indx to get the size of the
* first record.
*/
cnt = op == DB_CURRENT ? 0 : 1;
for (first = indx;
indx < NUM_ENT(h) && inp[first] == inp[indx];
++cnt, indx += P_INDX) {
bk = GET_BKEYDATA(dbp, h, indx + O_INDX);
@ -726,6 +758,36 @@ __bam_dup_convert(dbc, h, indx)
if (sz < dbp->pgsize / 4)
return (0);
*cntp = cnt;
return (1);
}
/*
* __bam_dup_convert --
* Move a set of duplicates off-page and into their own tree.
*/
static int
__bam_dup_convert(dbc, h, indx, cnt)
DBC *dbc;
PAGE *h;
u_int32_t indx, cnt;
{
BKEYDATA *bk;
DB *dbp;
DBT hdr;
DB_MPOOLFILE *mpf;
PAGE *dp;
db_indx_t cpindx, dindx, first, *inp;
int ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
inp = P_INP(dbp, h);
/* Move to the beginning of the dup set. */
while (indx > 0 && inp[indx] == inp[indx - P_INDX])
indx -= P_INDX;
/* Get a new page. */
if ((ret = __db_new(dbc,
dbp->dup_compare == NULL ? P_LRECNO : P_LDUP, &dp)) != 0)
@ -739,8 +801,8 @@ __bam_dup_convert(dbc, h, indx)
* we're dealing with.
*/
memset(&hdr, 0, sizeof(hdr));
dindx = first;
indx = first;
first = indx;
dindx = indx;
cpindx = 0;
do {
/* Move cursors referencing the old entry to the new entry. */

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_rec.c,v 11.70 2004/09/24 00:43:12 bostic Exp $
* $Id: bt_rec.c,v 12.11 2005/10/20 18:57:01 bostic Exp $
*/
#include "db_config.h"
@ -58,7 +58,7 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
_lp = lp = np = pp = _rp = rp = NULL;
sp = NULL;
REC_INTRO(__bam_split_read, 1);
REC_INTRO(__bam_split_read, 1, 0);
/*
* There are two kinds of splits that we have to recover from. The
@ -96,21 +96,21 @@ redo: if (DB_REDO(op)) {
REC_FGET(mpf, root_pgno, &pp, do_left);
cmp =
log_compare(&LSN(pp), &LSN(argp->pg.data));
CHECK_LSN(op,
CHECK_LSN(dbenv, op,
cmp, &LSN(pp), &LSN(argp->pg.data));
p_update = cmp == 0;
}
do_left: if (lp != NULL) {
cmp = log_compare(&LSN(lp), &argp->llsn);
CHECK_LSN(op, cmp, &LSN(lp), &argp->llsn);
CHECK_LSN(dbenv, op, cmp, &LSN(lp), &argp->llsn);
if (cmp == 0)
l_update = 1;
}
if (rp != NULL) {
cmp = log_compare(&LSN(rp), &argp->rlsn);
CHECK_LSN(op, cmp, &LSN(rp), &argp->rlsn);
CHECK_LSN(dbenv, op, cmp, &LSN(rp), &argp->rlsn);
if (cmp == 0)
r_update = 1;
}
@ -211,7 +211,7 @@ check_next: /*
goto done;
}
cmp = log_compare(&LSN(np), &argp->nlsn);
CHECK_LSN(op, cmp, &LSN(np), &argp->nlsn);
CHECK_LSN(dbenv, op, cmp, &LSN(np), &argp->nlsn);
if (cmp == 0) {
PREV_PGNO(np) = argp->right;
np->lsn = *lsnp;
@ -337,12 +337,13 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
DB_MPOOLFILE *mpf;
PAGE *pagep;
db_pgno_t pgno, root_pgno;
db_recno_t rcnt;
int cmp_n, cmp_p, modified, ret;
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__bam_rsplit_print);
REC_INTRO(__bam_rsplit_read, 1);
REC_INTRO(__bam_rsplit_read, 1, 1);
/* Fix the root page. */
pgno = root_pgno = argp->root_pgno;
@ -361,10 +362,19 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->rootlsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->rootlsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->rootlsn);
if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */
/*
* Copy the new data to the root page. If it is not now a
* leaf page we need to restore the record number. We could
* try to determine if C_RECNUM was set in the btree, but
* that's not really necessary since the field is not used
* otherwise.
*/
rcnt = RE_NREC(pagep);
memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size);
if (LEVEL(pagep) > LEAFLEVEL)
RE_NREC_SET(pagep, rcnt);
pagep->pgno = root_pgno;
pagep->lsn = *lsnp;
modified = 1;
@ -403,7 +413,7 @@ do_page:
(void)__ua_memcpy(&copy_lsn, &LSN(argp->pgdbt.data), sizeof(DB_LSN));
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &copy_lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &copy_lsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &copy_lsn);
if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */
pagep->lsn = *lsnp;
@ -450,7 +460,7 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__bam_adj_print);
REC_INTRO(__bam_adj_read, 1);
REC_INTRO(__bam_adj_read, 1, 1);
/* Get the page; if it never existed and we're undoing, we're done. */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
@ -468,7 +478,7 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */
if ((ret = __bam_adjindx(dbc,
@ -524,7 +534,7 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__bam_cadjust_print);
REC_INTRO(__bam_cadjust_read, 1);
REC_INTRO(__bam_cadjust_read, 1, 0);
/* Get the page; if it never existed and we're undoing, we're done. */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
@ -542,7 +552,7 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */
if (IS_BTREE_PAGE(pagep)) {
@ -613,7 +623,7 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__bam_cdel_print);
REC_INTRO(__bam_cdel_read, 1);
REC_INTRO(__bam_cdel_read, 1, 0);
/* Get the page; if it never existed and we're undoing, we're done. */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
@ -631,7 +641,7 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */
indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0);
@ -644,7 +654,9 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0);
B_DCLR(GET_BKEYDATA(file_dbp, pagep, indx)->type);
(void)__bam_ca_delete(file_dbp, argp->pgno, argp->indx, 0);
if ((ret = __bam_ca_delete(
file_dbp, argp->pgno, argp->indx, 0, NULL)) != 0)
goto out;
LSN(pagep) = argp->lsn;
modified = 1;
@ -689,7 +701,7 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__bam_repl_print);
REC_INTRO(__bam_repl_read, 1);
REC_INTRO(__bam_repl_read, 1, 1);
/* Get the page; if it never existed and we're undoing, we're done. */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
@ -708,7 +720,7 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) {
/*
* Need to redo update described.
@ -799,7 +811,7 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info)
meta = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__bam_root_print);
REC_INTRO(__bam_root_read, 0);
REC_INTRO(__bam_root_read, 0, 0);
if ((ret = __memp_fget(mpf, &argp->meta_pgno, 0, &meta)) != 0) {
if (ret != DB_PAGE_NOTFOUND
@ -816,7 +828,7 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info)
modified = 0;
cmp_n = log_compare(lsnp, &LSN(meta));
cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(meta), &argp->meta_lsn);
if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */
meta->root = argp->root_pgno;
@ -866,7 +878,7 @@ __bam_curadj_recover(dbenv, dbtp, lsnp, op, info)
COMPQUIET(mpf, NULL);
REC_PRINT(__bam_curadj_print);
REC_INTRO(__bam_curadj_read, 0);
REC_INTRO(__bam_curadj_read, 0, 1);
ret = 0;
if (op != DB_TXN_ABORT)
@ -891,8 +903,9 @@ __bam_curadj_recover(dbenv, dbtp, lsnp, op, info)
break;
case DB_CA_SPLIT:
__bam_ca_undosplit(file_dbp, argp->from_pgno,
argp->to_pgno, argp->left_pgno, argp->from_indx);
if ((ret = __bam_ca_undosplit(file_dbp, argp->from_pgno,
argp->to_pgno, argp->left_pgno, argp->from_indx)) != 0)
goto out;
break;
}
@ -928,7 +941,7 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
rdbc = NULL;
REC_PRINT(__bam_rcuradj_print);
REC_INTRO(__bam_rcuradj_read, 0);
REC_INTRO(__bam_rcuradj_read, 0, 1);
ret = t_ret = 0;
@ -1008,7 +1021,7 @@ __bam_relink_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__bam_relink_print);
REC_INTRO(__bam_relink_read, 1);
REC_INTRO(__bam_relink_read, 1, 0);
/*
* There are up to three pages we need to check -- the page, and the
@ -1016,38 +1029,7 @@ __bam_relink_recover(dbenv, dbtp, lsnp, op, info)
* 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 = __memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
if (ret != DB_PAGE_NOTFOUND
#ifndef HAVE_FTRUNCATE
|| DB_REDO(op)
@ -1062,24 +1044,24 @@ next2: if ((ret = __memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
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);
CHECK_LSN(dbenv, 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;
/* Redo the remove or replace. */
if (argp->new_pgno == PGNO_INVALID)
pagep->prev_pgno = argp->prev;
else
pagep->prev_pgno = argp->new_pgno;
pagep->lsn = *lsnp;
modified = 1;
} else if (cmp_n == 0 && DB_UNDO(op)) {
/* Undo the remove or redo the add. */
/* Undo the remove or replace. */
pagep->prev_pgno = argp->pgno;
pagep->lsn = argp->lsn_next;
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;
@ -1098,24 +1080,24 @@ prev: if ((ret = __memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) {
modified = 0;
cmp_p = log_compare(&LSN(pagep), &argp->lsn_prev);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_prev);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn_prev);
if (cmp_p == 0 && DB_REDO(op)) {
/* Redo the relink. */
pagep->next_pgno = argp->next;
if (argp->new_pgno == PGNO_INVALID)
pagep->next_pgno = argp->next;
else
pagep->next_pgno = argp->new_pgno;
pagep->lsn = *lsnp;
modified = 1;
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
/* Undo the relink. */
pagep->next_pgno = argp->pgno;
pagep->lsn = argp->lsn_prev;
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;
@ -1127,3 +1109,281 @@ out: if (pagep != NULL)
(void)__memp_fput(mpf, pagep, 0);
REC_CLOSE;
}
/*
* __bam_merge_recover --
* Recovery function for merge.
*
* PUBLIC: int __bam_merge_recover
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
int
__bam_merge_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__bam_merge_args *argp;
BKEYDATA *bk;
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
db_indx_t indx, *ninp, *pinp;
u_int32_t size;
u_int8_t *bp;
int cmp_n, cmp_p, i, modified, ret;
COMPQUIET(info, NULL);
REC_PRINT(__bam_merge_print);
REC_INTRO(__bam_merge_read, 1, 1);
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 next;
}
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(file_dbp->dbenv, op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) {
/*
* If the header is provided the page is empty, copy the
* needed data.
*/
DB_ASSERT(argp->hdr.size == 0 || NUM_ENT(pagep) == 0);
if (argp->hdr.size != 0) {
P_INIT(pagep, file_dbp->pgsize, pagep->pgno,
PREV_PGNO(argp->hdr.data),
NEXT_PGNO(argp->hdr.data),
LEVEL(argp->hdr.data), TYPE(argp->hdr.data));
}
if (TYPE(pagep) == P_OVERFLOW) {
OV_REF(pagep) = OV_REF(argp->hdr.data);
OV_LEN(pagep) = OV_LEN(argp->hdr.data);
bp = (u_int8_t *) pagep + P_OVERHEAD(file_dbp);
memcpy(bp, argp->data.data, argp->data.size);
} else {
/* Copy the data segment. */
bp = (u_int8_t *)pagep +
(db_indx_t)(HOFFSET(pagep) - argp->data.size);
memcpy(bp, argp->data.data, argp->data.size);
/* Copy index table offset past the current entries. */
pinp = P_INP(file_dbp, pagep) + NUM_ENT(pagep);
ninp = argp->ind.data;
for (i = 0;
i < (int)(argp->ind.size / sizeof(*ninp)); i++)
*pinp++ = *ninp++
- (file_dbp->pgsize - HOFFSET(pagep));
HOFFSET(pagep) -= argp->data.size;
NUM_ENT(pagep) += i;
}
pagep->lsn = *lsnp;
modified = 1;
} else if (cmp_n == 0 && !DB_REDO(op)) {
/*
* Since logging is logical at the page level
* we cannot just truncate the data space. Delete
* the proper number of items from the logical end
* of the page.
*/
for (i = 0; i < (int)(argp->ind.size / sizeof(*ninp)); i++) {
indx = NUM_ENT(pagep) - 1;
if (P_INP(file_dbp, pagep)[indx] ==
P_INP(file_dbp, pagep)[indx - P_INDX]) {
NUM_ENT(pagep)--;
continue;
}
switch (TYPE(pagep)) {
case P_LBTREE:
case P_LRECNO:
case P_LDUP:
bk = GET_BKEYDATA(file_dbp, pagep, indx);
size = BITEM_SIZE(bk);
break;
case P_IBTREE:
size = BINTERNAL_SIZE(
GET_BINTERNAL(file_dbp, pagep, indx)->len);
break;
case P_IRECNO:
size = RINTERNAL_SIZE;
break;
default:
ret = __db_pgfmt(dbenv, PGNO(pagep));
goto out;
}
if ((ret =
__db_ditem(dbc, pagep, indx, size)) != 0)
goto out;
}
if (argp->ind.size == 0)
HOFFSET(pagep) = file_dbp->pgsize;
pagep->lsn = argp->lsn;
modified = 1;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
next: if ((ret = __memp_fget(mpf, &argp->npgno, 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;
}
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->nlsn);
CHECK_LSN(file_dbp->dbenv, op, cmp_p, &LSN(pagep), &argp->nlsn);
if (cmp_p == 0 && DB_REDO(op)) {
/* Need to truncate the page. */
HOFFSET(pagep) = file_dbp->pgsize;
NUM_ENT(pagep) = 0;
pagep->lsn = *lsnp;
modified = 1;
} else if (cmp_n == 0 && !DB_REDO(op)) {
/* Need to put the data back on the page. */
if (TYPE(pagep) == P_OVERFLOW) {
OV_REF(pagep) = OV_REF(argp->hdr.data);
OV_LEN(pagep) = OV_LEN(argp->hdr.data);
bp = (u_int8_t *) pagep + P_OVERHEAD(file_dbp);
memcpy(bp, argp->data.data, argp->data.size);
} else {
bp = (u_int8_t *)pagep +
(db_indx_t)(HOFFSET(pagep) - argp->data.size);
memcpy(bp, argp->data.data, argp->data.size);
/* Copy index table. */
pinp = P_INP(file_dbp, pagep) + NUM_ENT(pagep);
ninp = argp->ind.data;
for (i = 0;
i < (int)(argp->ind.size / sizeof(*ninp)); i++)
*pinp++ = *ninp++;
HOFFSET(pagep) -= argp->data.size;
NUM_ENT(pagep) = i;
}
pagep->lsn = argp->nlsn;
modified = 1;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
done:
*lsnp = argp->prev_lsn;
ret = 0;
out: REC_CLOSE;
}
/*
* __bam_pgno_recover --
* Recovery function for page number replacment.
*
* PUBLIC: int __bam_pgno_recover
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
int
__bam_pgno_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
BINTERNAL *bi;
__bam_pgno_args *argp;
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep, *npagep;
db_pgno_t *pgnop;
int cmp_n, cmp_p, modified, ret;
COMPQUIET(info, NULL);
REC_PRINT(__bam_pgno_print);
REC_INTRO(__bam_pgno_read, 1, 0);
REC_FGET(mpf, argp->pgno, &pagep, done);
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(file_dbp->dbenv, op, cmp_p, &LSN(pagep), &argp->lsn);
if ((cmp_p == 0 && DB_REDO(op)) || (cmp_n == 0 && !DB_REDO(op))) {
switch (TYPE(pagep)) {
case P_IBTREE:
/*
* An internal record can have both a overflow
* and child pointer. Fetch the page to see
* which it is.
*/
bi = GET_BINTERNAL(file_dbp, pagep, argp->indx);
if (B_TYPE(bi->type) == B_OVERFLOW) {
REC_FGET(mpf, argp->npgno, &npagep, out);
if (TYPE(npagep) == P_OVERFLOW)
pgnop =
&((BOVERFLOW *)(bi->data))->pgno;
else
pgnop = &bi->pgno;
if ((ret = __memp_fput(mpf, npagep, 0)) != 0)
goto out;
break;
}
pgnop = &bi->pgno;
break;
case P_IRECNO:
pgnop =
&GET_RINTERNAL(file_dbp, pagep, argp->indx)->pgno;
break;
default:
pgnop =
&GET_BOVERFLOW(file_dbp, pagep, argp->indx)->pgno;
break;
}
if (DB_REDO(op)) {
/* Need to redo update described. */
*pgnop = argp->npgno;
pagep->lsn = *lsnp;
modified = 1;
} else {
*pgnop = argp->opgno;
pagep->lsn = argp->lsn;
modified = 1;
}
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
done:
*lsnp = argp->prev_lsn;
ret = 0;
out: REC_CLOSE;
}

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1998-2004
* Copyright (c) 1998-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_reclaim.c,v 11.15 2004/01/28 03:35:49 bostic Exp $
* $Id: bt_reclaim.c,v 12.2 2005/06/16 20:20:19 bostic Exp $
*/
#include "db_config.h"
@ -69,7 +69,8 @@ __bam_truncate(dbc, countp)
ret = __bam_traverse(dbc,
DB_LOCK_WRITE, dbc->internal->root, __db_truncate_callback, &trunc);
*countp = trunc.count;
if (countp != NULL)
*countp = trunc.count;
return (ret);
}

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2004
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_recno.c,v 11.117 2004/03/28 17:01:01 bostic Exp $
* $Id: bt_recno.c,v 12.6 2005/08/08 14:27:59 bostic Exp $
*/
#include "db_config.h"
@ -203,7 +203,6 @@ __ram_c_del(dbc)
DB *dbp;
DB_LSN lsn;
DBT hdr, data;
EPG *epg;
int exact, ret, stack, t_ret;
dbp = dbc->dbp;
@ -280,21 +279,11 @@ __ram_c_del(dbc)
* are closed, and then clean it up.
*/
if (NUM_ENT(cp->page) == 0 && PGNO(cp->page) != cp->root) {
/*
* We already have a locked stack of pages. However,
* there are likely entries in the stack that aren't
* going to be emptied by removing the single reference
* to the emptied page (or one of its parents).
*/
for (epg = cp->csp; epg >= cp->sp; --epg)
if (NUM_ENT(epg->page) > 1)
break;
/*
* We want to delete a single item out of the last page
* that we're not deleting.
*/
ret = __bam_dpages(dbc, epg);
ret = __bam_dpages(dbc, 0, 0);
/*
* Regardless of the return from __bam_dpages, it will
@ -764,7 +753,7 @@ __ram_ca(dbc_arg, op)
*/
DB_ASSERT(F_ISSET(cp_arg, C_RENUMBER));
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
/*
* Adjust the cursors. See the comment in __bam_ca_delete().
*/
@ -780,7 +769,7 @@ __ram_ca(dbc_arg, op)
for (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);
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (BTREE_CURSOR *)dbc->internal;
@ -789,7 +778,7 @@ __ram_ca(dbc_arg, op)
order <= cp->order)
order = cp->order + 1;
}
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
}
} else
order = INVALID_ORDER;
@ -798,7 +787,7 @@ __ram_ca(dbc_arg, op)
for (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);
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (BTREE_CURSOR *)dbc->internal;
@ -868,9 +857,9 @@ iafter: if (!adjusted && C_LESSTHAN(cp_arg, cp)) {
break;
}
}
MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbp->dbenv, dbp->mutex);
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (found);
}
@ -1037,6 +1026,18 @@ __ram_writeback(dbp)
return (0);
}
/*
* We step through the records, writing each one out. Use the record
* number and the dbp->get() function, instead of a cursor, so we find
* and write out "deleted" or non-existent records. The DB handle may
* be threaded, so allocate memory as we go.
*/
memset(&key, 0, sizeof(key));
key.size = sizeof(db_recno_t);
key.data = &keyno;
memset(&data, 0, sizeof(data));
F_SET(&data, DB_DBT_REALLOC);
/* Allocate a cursor. */
if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)
return (ret);
@ -1064,7 +1065,7 @@ __ram_writeback(dbp)
*/
if ((ret =
__ram_update(dbc, DB_MAX_RECORDS, 0)) != 0 && ret != DB_NOTFOUND)
return (ret);
goto err;
/*
* Close any existing file handle and re-open the file, truncating it.
@ -1082,18 +1083,6 @@ __ram_writeback(dbp)
goto err;
}
/*
* We step through the records, writing each one out. Use the record
* number and the dbp->get() function, instead of a cursor, so we find
* and write out "deleted" or non-existent records. The DB handle may
* be threaded, so allocate memory as we go.
*/
memset(&key, 0, sizeof(key));
key.size = sizeof(db_recno_t);
key.data = &keyno;
memset(&data, 0, sizeof(data));
F_SET(&data, DB_DBT_REALLOC);
/*
* We'll need the delimiter if we're doing variable-length records,
* and the pad character if we're doing fixed-length records.

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -36,7 +36,7 @@
* 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 $
* $Id: bt_rsearch.c,v 12.5 2005/08/08 03:37:05 ubell Exp $
*/
#include "db_config.h"
@ -100,44 +100,14 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
*
* Retrieve the root page.
*/
pg = cp->root;
stack = LF_ISSET(S_STACK) ? 1 : 0;
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 = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
/*
* Decide if we need to save this page; if we do, write lock it.
* We deliberately don't lock-couple on this call. If the tree
* is tiny, i.e., one page, and two threads are busily updating
* the root page, we're almost guaranteed deadlocks galore, as
* each one gets a read lock and then blocks the other's attempt
* for a write lock.
*/
if (!stack &&
((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) ||
(LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
ret = __memp_fput(mpf, h, 0);
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
stack = 1;
}
if ((ret = __bam_get_root(dbc, cp->root, stop, flags, &stack)) != 0)
return (ret);
lock_mode = cp->csp->lock_mode;
lock = cp->csp->lock;
h = cp->csp->page;
BT_STK_CLR(cp);
/*
* If appending to the tree, set the record number now -- we have the
* root page locked.
@ -260,15 +230,15 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
}
--indx;
/* Return if this is the lowest page wanted. */
if (stop == LEVEL(h)) {
BT_STK_ENTER(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
return (0);
}
if (stack) {
/* Return if this is the lowest page wanted. */
if (LF_ISSET(S_PARENT) && stop == h->level) {
BT_STK_ENTER(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
return (0);
}
BT_STK_PUSH(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret);
if (ret != 0)
@ -286,8 +256,8 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
* never unlock it.
*/
if ((LF_ISSET(S_PARENT) &&
(u_int8_t)(stop + 1) >= (u_int8_t)(h->level - 1)) ||
(h->level - 1) == LEAFLEVEL)
(u_int8_t)(stop + 1) >= (u_int8_t)(LEVEL(h) - 1)) ||
(LEVEL(h) - 1) == LEAFLEVEL)
stack = 1;
if ((ret = __memp_fput(mpf, h, 0)) != 0)

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -39,7 +39,7 @@
* 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 $
* $Id: bt_search.c,v 12.17 2005/11/10 21:17:13 ubell Exp $
*/
#include "db_config.h"
@ -57,6 +57,102 @@
#include "dbinc/lock.h"
#include "dbinc/mp.h"
/*
* __bam_get_root --
* Fetch the root of a tree and see if we want to keep
* it in the stack.
*
* PUBLIC: int __bam_get_root __P((DBC *, db_pgno_t, int, u_int32_t, int *));
*/
int
__bam_get_root(dbc, pg, slevel, flags, stack)
DBC *dbc;
db_pgno_t pg;
int slevel;
u_int32_t flags;
int *stack;
{
BTREE_CURSOR *cp;
DB *dbp;
DB_LOCK lock;
DB_MPOOLFILE *mpf;
PAGE *h;
db_lockmode_t lock_mode;
int ret, t_ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
/*
* If write-locking pages, we need to know whether or not to acquire a
* write lock on a page before getting it. This depends on how deep it
* is in tree, which we don't know until we acquire the root page. So,
* if we need to lock the root page we may have to upgrade it later,
* because we won't get the correct lock initially.
*
* Retrieve the root page.
*/
try_again:
*stack = LF_ISSET(S_STACK) &&
(dbc->dbtype == DB_RECNO || F_ISSET(cp, C_RECNUM));
lock_mode = DB_LOCK_READ;
if (*stack ||
LF_ISSET(S_DEL) || (LF_ISSET(S_NEXT) && LF_ISSET(S_WRITE)))
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
/*
* Decide if we need to save this page; if we do, write lock it.
* We deliberately don't lock-couple on this call. If the tree
* is tiny, i.e., one page, and two threads are busily updating
* the root page, we're almost guaranteed deadlocks galore, as
* each one gets a read lock and then blocks the other's attempt
* for a write lock.
*/
if (!*stack &&
((LF_ISSET(S_PARENT) && (u_int8_t)(slevel + 1) >= LEVEL(h)) ||
(LF_ISSET(S_WRITE) && LEVEL(h) == LEAFLEVEL) ||
(LF_ISSET(S_START) && slevel == LEVEL(h)))) {
if (!STD_LOCKING(dbc))
goto no_relock;
ret = __memp_fput(mpf, h, 0);
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
if (!((LF_ISSET(S_PARENT) &&
(u_int8_t)(slevel + 1) >= LEVEL(h)) ||
(LF_ISSET(S_WRITE) && LEVEL(h) == LEAFLEVEL) ||
(LF_ISSET(S_START) && slevel == LEVEL(h)))) {
/* Someone else split the root, start over. */
ret = __memp_fput(mpf, h, 0);
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
goto try_again;
}
no_relock: *stack = 1;
}
BT_STK_ENTER(dbp->dbenv, cp, h, 0, lock, lock_mode, ret);
return (ret);
}
/*
* __bam_search --
* Search a btree for a key.
@ -65,12 +161,12 @@
* PUBLIC: const DBT *, u_int32_t, int, db_recno_t *, int *));
*/
int
__bam_search(dbc, root_pgno, key, flags, stop, recnop, exactp)
__bam_search(dbc, root_pgno, key, flags, slevel, recnop, exactp)
DBC *dbc;
db_pgno_t root_pgno;
const DBT *key;
u_int32_t flags;
int stop, *exactp;
int slevel, *exactp;
db_recno_t *recnop;
{
BTREE *t;
@ -102,64 +198,17 @@ __bam_search(dbc, root_pgno, key, flags, stop, recnop, exactp)
* deleted items, and if we are locking pairs of pages. In addition,
* if we're modifying record numbers, we have to lock the entire tree
* regardless. See btree.h for more details.
*
* If write-locking pages, we need to know whether or not to acquire a
* write lock on a page before getting it. This depends on how deep it
* is in tree, which we don't know until we acquire the root page. So,
* if we need to lock the root page we may have to upgrade it later,
* because we won't get the correct lock initially.
*
* Retrieve the root page.
*/
try_again:
pg = root_pgno == PGNO_INVALID ? cp->root : root_pgno;
stack = LF_ISSET(S_STACK) && F_ISSET(cp, C_RECNUM);
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 = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
/*
* Decide if we need to save this page; if we do, write lock it.
* We deliberately don't lock-couple on this call. If the tree
* is tiny, i.e., one page, and two threads are busily updating
* the root page, we're almost guaranteed deadlocks galore, as
* each one gets a read lock and then blocks the other's attempt
* for a write lock.
*/
if (!stack &&
((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) ||
(LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
ret = __memp_fput(mpf, h, 0);
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
if (!((LF_ISSET(S_PARENT) &&
(u_int8_t)(stop + 1) >= h->level) ||
(LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
/* Someone else split the root, start over. */
ret = __memp_fput(mpf, h, 0);
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
goto try_again;
}
stack = 1;
}
if (root_pgno == PGNO_INVALID)
root_pgno = cp->root;
if ((ret = __bam_get_root(dbc, root_pgno, slevel, flags, &stack)) != 0)
return (ret);
lock_mode = cp->csp->lock_mode;
lock = cp->csp->lock;
h = cp->csp->page;
BT_STK_CLR(cp);
/* Choose a comparison function. */
func = F_ISSET(dbc, DBC_OPD) ?
@ -168,6 +217,23 @@ try_again:
for (;;) {
inp = P_INP(dbp, h);
adjust = TYPE(h) == P_LBTREE ? P_INDX : O_INDX;
if (LF_ISSET(S_MIN | S_MAX)) {
if (LF_ISSET(S_MIN) || NUM_ENT(h) == 0)
indx = 0;
else if (TYPE(h) == P_LBTREE)
indx = NUM_ENT(h) - 2;
else
indx = NUM_ENT(h) - 1;
if (LEVEL(h) == LEAFLEVEL ||
(!LF_ISSET(S_START) && LEVEL(h) == slevel)) {
if (LF_ISSET(S_NEXT))
goto get_next;
goto found;
}
goto next;
}
/*
* Do a binary search on the current page. If we're searching
* a Btree leaf page, we have to walk the indices in groups of
@ -175,7 +241,6 @@ try_again:
* page, they're an index per page item. If we find an exact
* match on a leaf page, we're done.
*/
adjust = TYPE(h) == P_LBTREE ? P_INDX : O_INDX;
for (base = 0,
lim = NUM_ENT(h) / (db_indx_t)adjust; lim != 0; lim >>= 1) {
indx = base + ((lim >> 1) * adjust);
@ -183,8 +248,13 @@ try_again:
__bam_cmp(dbp, key, h, indx, func, &cmp)) != 0)
goto err;
if (cmp == 0) {
if (TYPE(h) == P_LBTREE || TYPE(h) == P_LDUP)
if (LEVEL(h) == LEAFLEVEL ||
(!LF_ISSET(S_START) &&
LEVEL(h) == slevel)) {
if (LF_ISSET(S_NEXT))
goto get_next;
goto found;
}
goto next;
}
if (cmp > 0) {
@ -197,10 +267,12 @@ try_again:
* No match found. Base is the smallest index greater than
* key and may be zero or a last + O_INDX index.
*
* If it's a leaf page, return base as the "found" value.
* If it's a leaf page or the stopping point,
* return base as the "found" value.
* Delete only deletes exact matches.
*/
if (TYPE(h) == P_LBTREE || TYPE(h) == P_LDUP) {
if (LEVEL(h) == LEAFLEVEL ||
(!LF_ISSET(S_START) && LEVEL(h) == slevel)) {
*exactp = 0;
if (LF_ISSET(S_EXACT)) {
@ -218,6 +290,43 @@ try_again:
ret = t_ret;
return (ret);
}
if (LF_ISSET(S_NEXT)) {
get_next: /*
* The caller could have asked for a NEXT
* at the root if the tree recently collapsed.
*/
if (PGNO(h) == root_pgno) {
ret = DB_NOTFOUND;
goto err;
}
/*
* Save the root of the subtree
* and drop the rest of the subtree
* and search down again starting at
* the next child.
*/
if ((ret = __LPUT(dbc, lock)) != 0)
goto err;
if ((ret = __memp_fput(mpf, h, 0)) != 0)
goto err;
h = NULL;
LF_SET(S_MIN);
LF_CLR(S_NEXT);
indx = cp->sp->indx + 1;
if (indx == NUM_ENT(cp->sp->page)) {
ret = DB_NOTFOUND;
cp->csp++;
goto err;
}
h = cp->sp->page;
cp->sp->page = NULL;
lock = cp->sp->lock;
LOCK_INIT(cp->sp->lock);
if ((ret = __bam_stkrel(dbc, STK_NOLOCK)) != 0)
goto err;
stack = 1;
goto next;
}
/*
* !!!
@ -227,6 +336,8 @@ try_again:
* to find an undeleted record. This is handled by the
* calling routine.
*/
if (LF_ISSET(S_DEL) && cp->csp == cp->sp)
cp->csp++;
BT_STK_ENTER(dbp->dbenv,
cp, h, base, lock, lock_mode, ret);
if (ret != 0)
@ -252,8 +363,12 @@ next: if (recnop != NULL)
pg = GET_BINTERNAL(dbp, h, indx)->pgno;
/* See if we are at the level to start stacking. */
if (LF_ISSET(S_START) && slevel == LEVEL(h))
stack = 1;
if (LF_ISSET(S_STK_ONLY)) {
if (stop == h->level) {
if (slevel == LEVEL(h)) {
BT_STK_NUM(dbp->dbenv, cp, h, indx, ret);
if ((t_ret =
__LPUT(dbc, lock)) != 0 && ret == 0)
@ -278,13 +393,24 @@ next: if (recnop != NULL)
}
} else if (stack) {
/* Return if this is the lowest page wanted. */
if (LF_ISSET(S_PARENT) && stop == h->level) {
if (LF_ISSET(S_PARENT) && slevel == LEVEL(h)) {
BT_STK_ENTER(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
return (0);
}
if (LF_ISSET(S_DEL) && NUM_ENT(h) > 1) {
/*
* There was a page with a singleton pointer
* to a non-empty subtree.
*/
cp->csp--;
if ((ret = __bam_stkrel(dbc, STK_NOLOCK)) != 0)
goto err;
stack = 0;
goto do_del;
}
BT_STK_PUSH(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret);
if (ret != 0)
@ -302,16 +428,69 @@ next: if (recnop != NULL)
* unlock it.
*/
if ((LF_ISSET(S_PARENT) &&
(u_int8_t)(stop + 1) >= (u_int8_t)(h->level - 1)) ||
(h->level - 1) == LEAFLEVEL)
(u_int8_t)(slevel + 1) >= (LEVEL(h) - 1)) ||
(LEVEL(h) - 1) == LEAFLEVEL)
stack = 1;
if ((ret = __memp_fput(mpf, h, 0)) != 0)
goto err;
h = NULL;
/*
* Returning a subtree. See if we have hit the start
* point if so save the parent and set stack.
* Otherwise free the parent and temporarily
* save this one.
* For S_DEL we need to find a page with 1 entry.
* For S_NEXT we want find the minimal subtree
* that contains the key and the next page.
* We save pages as long as we are at the right
* edge of the subtree. When we leave the right
* edge, then drop the subtree.
*/
if (!LF_ISSET(S_DEL | S_NEXT)) {
if ((ret = __memp_fput(mpf, h, 0)) != 0)
goto err;
goto lock_next;
}
lock_mode = stack &&
LF_ISSET(S_WRITE) ? DB_LOCK_WRITE : DB_LOCK_READ;
if ((LF_ISSET(S_DEL) && NUM_ENT(h) == 1)) {
stack = 1;
LF_SET(S_WRITE);
/* Push the parent. */
cp->csp++;
/* Push this node. */
BT_STK_PUSH(dbp->dbenv, cp, h,
indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
LOCK_INIT(lock);
} else {
/*
* See if we want to save the tree so far.
* If we are looking for the next key,
* then we must save this node if we are
* at the end of the page. If not then
* discard anything we have saved so far.
* For delete only keep one node until
* we find a singleton.
*/
do_del: if (cp->csp->page != NULL) {
if (LF_ISSET(S_NEXT) &&
indx == NUM_ENT(h) - 1)
cp->csp++;
else if ((ret =
__bam_stkrel(dbc, STK_NOLOCK)) != 0)
goto err;
}
/* Save this node. */
BT_STK_ENTER(dbp->dbenv, cp,
h, indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
LOCK_INIT(lock);
}
lock_next: h = NULL;
if (stack && LF_ISSET(S_WRITE))
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc,
LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) {
/*
@ -320,6 +499,8 @@ next: if (recnop != NULL)
* descending the tree holding read-locks.
*/
(void)__LPUT(dbc, lock);
if (LF_ISSET(S_DEL | S_NEXT))
cp->csp++;
goto err;
}
}
@ -340,12 +521,12 @@ found: *exactp = 1;
* all duplicate sets that are not on overflow pages exist on a
* single leaf page.
*/
if (TYPE(h) == P_LBTREE) {
if (TYPE(h) == P_LBTREE && NUM_ENT(h) > P_INDX) {
if (LF_ISSET(S_DUPLAST))
while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
inp[indx] == inp[indx + P_INDX])
indx += P_INDX;
else
else if (LF_ISSET(S_DUPFIRST))
while (indx > 0 &&
inp[indx] == inp[indx - P_INDX])
indx -= P_INDX;
@ -406,8 +587,11 @@ found: *exactp = 1;
ret = t_ret;
if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret;
} else
} else {
if (LF_ISSET(S_DEL) && cp->csp == cp->sp)
cp->csp++;
BT_STK_ENTER(dbp->dbenv, cp, h, indx, lock, lock_mode, ret);
}
if (ret != 0)
goto err;
@ -471,6 +655,13 @@ __bam_stkrel(dbc, flags)
*/
epg->page = NULL;
}
/*
* We set this if we need to release our pins,
* but are not logically ready to have the pages
* visible.
*/
if (LF_ISSET(STK_PGONLY))
continue;
if (LF_ISSET(STK_NOLOCK)) {
if ((t_ret = __LPUT(dbc, epg->lock)) != 0 && ret == 0)
ret = t_ret;
@ -480,7 +671,8 @@ __bam_stkrel(dbc, flags)
}
/* Clear the stack, all pages have been released. */
BT_STK_CLR(cp);
if (!LF_ISSET(STK_PGONLY))
BT_STK_CLR(cp);
return (ret);
}

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -36,7 +36,7 @@
* 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 $
* $Id: bt_split.c,v 12.4 2005/06/16 20:20:22 bostic Exp $
*/
#include "db_config.h"
@ -56,7 +56,6 @@
static int __bam_broot __P((DBC *, PAGE *, PAGE *, PAGE *));
static int __bam_page __P((DBC *, EPG *, EPG *));
static int __bam_pinsert __P((DBC *, EPG *, PAGE *, PAGE *, int));
static int __bam_psplit __P((DBC *, EPG *, PAGE *, PAGE *, db_indx_t *));
static int __bam_root __P((DBC *, EPG *));
static int __ram_root __P((DBC *, PAGE *, PAGE *, PAGE *));
@ -338,7 +337,7 @@ __bam_page(dbc, pp, cp)
* page can't hold the new keys, and has to be split in turn, in which
* case we want to release all the locks we can.
*/
if ((ret = __bam_pinsert(dbc, pp, lp, rp, 1)) != 0)
if ((ret = __bam_pinsert(dbc, pp, lp, rp, BPI_SPACEONLY)) != 0)
goto err;
/*
@ -349,7 +348,7 @@ __bam_page(dbc, pp, cp)
* a page that's not in our direct ancestry. Consider a cursor walking
* backward through the leaf pages, that has our following page locked,
* and is waiting on a lock for the page we're splitting. In that case
* we're going to deadlock here . It's probably OK, stepping backward
* we're going to deadlock here. It's probably OK, stepping backward
* through the tree isn't a common operation.
*/
if (ISLEAF(cp->page) && NEXT_PGNO(cp->page) != PGNO_INVALID) {
@ -685,13 +684,15 @@ __ram_root(dbc, rootp, lp, rp)
/*
* __bam_pinsert --
* Insert a new key into a parent page, completing the split.
*
* PUBLIC: int __bam_pinsert __P((DBC *, EPG *, PAGE *, PAGE *, int));
*/
static int
__bam_pinsert(dbc, parent, lchild, rchild, space_check)
int
__bam_pinsert(dbc, parent, lchild, rchild, flags)
DBC *dbc;
EPG *parent;
PAGE *lchild, *rchild;
int space_check;
int flags;
{
BINTERNAL bi, *child_bi;
BKEYDATA *child_bk, *tmp_bk;
@ -714,7 +715,7 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
/* If handling record numbers, count records split to the right page. */
nrecs = F_ISSET(cp, C_RECNUM) &&
!space_check ? __bam_total(dbp, rchild) : 0;
!LF_ISSET(BPI_SPACEONLY) ? __bam_total(dbp, rchild) : 0;
/*
* Now we insert the new page's first key into the parent page, which
@ -750,7 +751,7 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT);
if (space_check)
if (LF_ISSET(BPI_SPACEONLY))
return (0);
/* Add a new record for the right page. */
@ -780,7 +781,11 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
child_bk = GET_BKEYDATA(dbp, rchild, 0);
switch (B_TYPE(child_bk->type)) {
case B_KEYDATA:
nbytes = BINTERNAL_PSIZE(child_bk->len);
nksize = child_bk->len;
/*
* Prefix compression:
* We set t->bt_prefix to NULL if we have a comparison
* callback but no prefix compression callback. But,
* if we're splitting in an off-page duplicates tree,
@ -792,6 +797,14 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
* as there's no way for an application to specify a
* prefix compression callback that corresponds to its
* comparison callback.
*
* No prefix compression if we don't have a compression
* function, or the key we'd compress isn't a normal
* key (for example, it references an overflow page).
*
* Generate a parent page key for the right child page
* from a comparison of the last key on the left child
* page and the first key on the right child page.
*/
if (F_ISSET(dbc, DBC_OPD)) {
if (dbp->dup_compare == __bam_defcmp)
@ -800,13 +813,8 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
func = NULL;
} else
func = t->bt_prefix;
nbytes = BINTERNAL_PSIZE(child_bk->len);
nksize = child_bk->len;
if (func == NULL)
goto noprefix;
if (ppage->prev_pgno == PGNO_INVALID && off <= 1)
goto noprefix;
tmp_bk = GET_BKEYDATA(dbp, lchild, NUM_ENT(lchild) -
(TYPE(lchild) == P_LDUP ? O_INDX : P_INDX));
if (B_TYPE(tmp_bk->type) != B_KEYDATA)
@ -821,11 +829,11 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
if ((n = BINTERNAL_PSIZE(nksize)) < nbytes)
nbytes = n;
else
noprefix: nksize = child_bk->len;
nksize = child_bk->len;
if (P_FREESPACE(dbp, ppage) < nbytes)
noprefix: if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT);
if (space_check)
if (LF_ISSET(BPI_SPACEONLY))
return (0);
memset(&bi, 0, sizeof(bi));
@ -849,7 +857,7 @@ noprefix: nksize = child_bk->len;
if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT);
if (space_check)
if (LF_ISSET(BPI_SPACEONLY))
return (0);
memset(&bi, 0, sizeof(bi));
@ -883,7 +891,7 @@ noprefix: nksize = child_bk->len;
if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT);
if (space_check)
if (LF_ISSET(BPI_SPACEONLY))
return (0);
/* Add a new record for the right page. */
@ -904,13 +912,13 @@ noprefix: nksize = child_bk->len;
* If a Recno or Btree with record numbers AM page, or an off-page
* duplicates tree, adjust the parent page's left page record count.
*/
if (F_ISSET(cp, C_RECNUM)) {
if (F_ISSET(cp, C_RECNUM) && !LF_ISSET(BPI_NORECNUM)) {
/* Log the change. */
if (DBC_LOGGING(dbc)) {
if ((ret = __bam_cadjust_log(dbp, dbc->txn,
&LSN(ppage), 0, PGNO(ppage),
&LSN(ppage), parent->indx, -(int32_t)nrecs, 0)) != 0)
return (ret);
if ((ret = __bam_cadjust_log(dbp, dbc->txn,
&LSN(ppage), 0, PGNO(ppage), &LSN(ppage),
parent->indx, -(int32_t)nrecs, 0)) != 0)
return (ret);
} else
LSN_NOT_LOGGED(LSN(ppage));

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_stat.c,v 11.78 2004/09/22 03:31:26 bostic Exp $
* $Id: bt_stat.c,v 12.3 2005/06/16 20:20:23 bostic Exp $
*/
#include "db_config.h"
@ -155,7 +155,6 @@ meta_only:
/* Get metadata page statistics. */
sp->bt_metaflags = meta->dbmeta.flags;
sp->bt_maxkey = meta->maxkey;
sp->bt_minkey = meta->minkey;
sp->bt_re_len = meta->re_len;
sp->bt_re_pad = meta->re_pad;
@ -246,16 +245,12 @@ __bam_stat_print(dbc, flags)
}
__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
if (dbp->type == DB_BTREE)
__db_dl(dbenv, "Minimum keys per-page", (u_long)sp->bt_minkey);
}
if (dbp->type == DB_RECNO) {
__db_dl(dbenv,
"Fixed-length record size", (u_long)sp->bt_re_len);
__db_dl(dbenv,
__db_msg(dbenv,
"%#x\tFixed-length record pad", (u_int)sp->bt_re_pad);
}
__db_dl(dbenv,

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_upgrade.c,v 11.30 2004/01/28 03:35:49 bostic Exp $
* $Id: bt_upgrade.c,v 12.1 2005/06/16 20:20:23 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1999-2004
* Copyright (c) 1999-2005
* Sleepycat Software. All rights reserved.
*
* $Id: bt_verify.c,v 1.97 2004/10/11 18:47:46 bostic Exp $
* $Id: bt_verify.c,v 12.13 2005/11/11 20:27:49 ubell Exp $
*/
#include "db_config.h"
@ -89,10 +89,8 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
} else
pip->bt_minkey = meta->minkey;
/* bt_maxkey: unsupported so no constraints. */
pip->bt_maxkey = meta->maxkey;
/* re_len: no constraints on this (may be zero or huge--we make rope) */
pip->re_pad = meta->re_pad;
pip->re_len = meta->re_len;
/*
@ -1618,8 +1616,17 @@ bad_prev: isbad = 1;
if (relenp)
*relenp = relen;
}
if (LF_ISSET(ST_RECNUM))
if (LF_ISSET(ST_RECNUM)) {
if (child->nrecs != child_nrecs) {
isbad = 1;
EPRINT((dbenv,
"Page %lu: record count incorrect: actual %lu, in record %lu",
(u_long)child->pgno,
(u_long)child_nrecs,
(u_long)child->nrecs));
}
nrecs += child_nrecs;
}
if (isbad == 0 && level != child_level + 1) {
isbad = 1;
EPRINT((dbenv,
@ -2037,38 +2044,36 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
DBT *key;
u_int32_t flags;
{
DBT dbt, unkdbt;
DB_ENV *dbenv;
BKEYDATA *bk;
BOVERFLOW *bo;
DBT dbt, unknown_key, unknown_data;
DB_ENV *dbenv;
VRFY_ITEM *pgmap;
db_indx_t i, beg, end, *inp;
db_indx_t i, last, beg, end, *inp;
u_int32_t himark;
void *ovflbuf;
int t_ret, ret, err_ret;
int ret, t_ret, t2_ret;
dbenv = dbp->dbenv;
/* Shut up lint. */
COMPQUIET(end, 0);
ovflbuf = pgmap = NULL;
err_ret = ret = 0;
inp = P_INP(dbp, h);
memset(&dbt, 0, sizeof(DBT));
dbt.flags = DB_DBT_REALLOC;
memset(&unkdbt, 0, sizeof(DBT));
unkdbt.size = (u_int32_t)(strlen("UNKNOWN") + 1);
unkdbt.data = "UNKNOWN";
memset(&unknown_key, 0, sizeof(DBT));
unknown_key.size = (u_int32_t)strlen("UNKNOWN_KEY");
unknown_key.data = "UNKNOWN_KEY";
memset(&unknown_data, 0, sizeof(DBT));
unknown_data.size = (u_int32_t)strlen("UNKNOWN_DATA");
unknown_data.data = "UNKNOWN_DATA";
/*
* Allocate a buffer for overflow items. Start at one page;
* __db_safe_goff will realloc as needed.
*/
if ((ret = __os_malloc(dbenv, dbp->pgsize, &ovflbuf)) != 0)
return (ret);
goto err;
if (LF_ISSET(DB_AGGRESSIVE) && (ret =
__os_calloc(dbenv, dbp->pgsize, sizeof(pgmap[0]), &pgmap)) != 0)
@ -2077,161 +2082,185 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
/*
* Loop through the inp array, spitting out key/data pairs.
*
* If we're salvaging normally, loop from 0 through NUM_ENT(h).
* If we're being aggressive, loop until we hit the end of the page--
* If we're salvaging normally, loop from 0 through NUM_ENT(h). If
* we're being aggressive, loop until we hit the end of the page --
* NUM_ENT() may be bogus.
*/
himark = dbp->pgsize;
for (i = 0;; i += O_INDX) {
for (i = 0, last = UINT16_MAX;; i += O_INDX) {
/* If we're not aggressive, break when we hit NUM_ENT(h). */
if (!LF_ISSET(DB_AGGRESSIVE) && i >= NUM_ENT(h))
break;
/* Verify the current item. */
ret = __db_vrfy_inpitem(dbp,
h, pgno, i, 1, flags, &himark, NULL);
/* If this returned a fatality, it's time to break. */
if (ret == DB_VERIFY_FATAL) {
t_ret =
__db_vrfy_inpitem(dbp, h, pgno, i, 1, flags, &himark, NULL);
if (t_ret != 0) {
/*
* Don't return DB_VERIFY_FATAL; it's private
* and means only that we can't go on with this
* page, not with the whole database. It's
* not even an error if we've run into it
* after NUM_ENT(h).
* If this is a btree leaf and we've printed out a key
* but not its associated data item, fix this imbalance
* by printing an "UNKNOWN_DATA".
*/
ret = (i < NUM_ENT(h)) ? DB_VERIFY_BAD : 0;
break;
if (pgtype == P_LBTREE && i % P_INDX == 1 &&
last == i - 1 && (t2_ret = __db_vrfy_prdbt(
&unknown_data,
0, " ", handle, callback, 0, vdp)) != 0) {
if (ret == 0)
ret = t2_ret;
goto err;
}
/*
* Don't return DB_VERIFY_FATAL; it's private and means
* only that we can't go on with this page, not with
* the whole database. It's not even an error if we've
* run into it after NUM_ENT(h).
*/
if (t_ret == DB_VERIFY_FATAL) {
if (i < NUM_ENT(h) && ret == 0)
ret = DB_VERIFY_BAD;
break;
}
continue;
}
/*
* If this returned 0, it's safe to print or (carefully)
* try to fetch.
*
* We only print deleted items if DB_AGGRESSIVE is set.
*/
if (ret == 0) {
/*
* We only want to print deleted items if
* DB_AGGRESSIVE is set.
*/
bk = GET_BKEYDATA(dbp, h, i);
if (!LF_ISSET(DB_AGGRESSIVE) && B_DISSET(bk->type))
continue;
bk = GET_BKEYDATA(dbp, h, i);
if (!LF_ISSET(DB_AGGRESSIVE) && B_DISSET(bk->type))
continue;
/*
* We're going to go try to print the next item. If
* key is non-NULL, we're a dup page, so we've got to
* print the key first, unless SA_SKIPFIRSTKEY is set
* and we're on the first entry.
*/
if (key != NULL &&
(i != 0 || !LF_ISSET(SA_SKIPFIRSTKEY)))
if ((ret = __db_vrfy_prdbt(key,
0, " ", handle, callback, 0, vdp)) != 0)
err_ret = ret;
/*
* If this is a btree leaf and we're about to print out a data
* item for which we didn't print out a key, fix this imbalance
* by printing an "UNKNOWN_KEY".
*/
if (pgtype == P_LBTREE && i % P_INDX == 1 &&
last != i - 1 && (t_ret = __db_vrfy_prdbt(
&unknown_key, 0, " ", handle, callback, 0, vdp)) != 0) {
if (ret == 0)
ret = t_ret;
goto err;
}
last = i;
beg = inp[i];
switch (B_TYPE(bk->type)) {
case B_DUPLICATE:
end = beg + BOVERFLOW_SIZE - 1;
/*
* If we're not on a normal btree leaf page,
* there shouldn't be off-page
* dup sets. Something's confused; just
* drop it, and the code to pick up unlinked
* offpage dup sets will print it out
* with key "UNKNOWN" later.
*/
if (pgtype != P_LBTREE)
break;
bo = (BOVERFLOW *)bk;
/*
* If the page number is unreasonable, or
* if this is supposed to be a key item,
* just spit out "UNKNOWN"--the best we
* can do is run into the data items in the
* unlinked offpage dup pass.
*/
if (!IS_VALID_PGNO(bo->pgno) ||
(i % P_INDX == 0)) {
/* Not much to do on failure. */
if ((ret =
__db_vrfy_prdbt(&unkdbt, 0, " ",
handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
}
if ((ret = __db_salvage_duptree(dbp,
vdp, bo->pgno, &dbt, handle, callback,
flags | SA_SKIPFIRSTKEY)) != 0)
err_ret = ret;
break;
case B_KEYDATA:
end = (db_indx_t)DB_ALIGN(
beg + bk->len, sizeof(u_int32_t)) - 1;
dbt.data = bk->data;
dbt.size = bk->len;
if ((ret = __db_vrfy_prdbt(&dbt,
0, " ", handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
case B_OVERFLOW:
end = beg + BOVERFLOW_SIZE - 1;
bo = (BOVERFLOW *)bk;
if ((ret = __db_safe_goff(dbp, vdp,
bo->pgno, &dbt, &ovflbuf, flags)) != 0) {
err_ret = ret;
/* We care about err_ret more. */
(void)__db_vrfy_prdbt(&unkdbt, 0, " ",
handle, callback, 0, vdp);
break;
}
if ((ret = __db_vrfy_prdbt(&dbt,
0, " ", handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
default:
/*
* We should never get here; __db_vrfy_inpitem
* should not be returning 0 if bk->type
* is unrecognizable.
*/
DB_ASSERT(0);
return (EINVAL);
/*
* We're going to go try to print the next item. If key is
* non-NULL, we're a dup page, so we've got to print the key
* first, unless SA_SKIPFIRSTKEY is set and we're on the first
* entry.
*/
if (key != NULL && (i != 0 || !LF_ISSET(SA_SKIPFIRSTKEY)))
if ((t_ret = __db_vrfy_prdbt(key,
0, " ", handle, callback, 0, vdp)) != 0) {
if (ret == 0)
ret = t_ret;
goto err;
}
beg = inp[i];
switch (B_TYPE(bk->type)) {
case B_DUPLICATE:
end = beg + BOVERFLOW_SIZE - 1;
/*
* If we're being aggressive, mark the beginning
* and end of the item; we'll come back and print
* whatever "junk" is in the gaps in case we had
* any bogus inp elements and thereby missed stuff.
* If we're not on a normal btree leaf page, there
* shouldn't be off-page dup sets. Something's
* confused; just drop it, and the code to pick up
* unlinked offpage dup sets will print it out
* with key "UNKNOWN" later.
*/
if (LF_ISSET(DB_AGGRESSIVE)) {
pgmap[beg] = VRFY_ITEM_BEGIN;
pgmap[end] = VRFY_ITEM_END;
if (pgtype != P_LBTREE)
break;
bo = (BOVERFLOW *)bk;
/*
* If the page number is unreasonable, or if this is
* supposed to be a key item, output "UNKNOWN_KEY" --
* the best we can do is run into the data items in
* the unlinked offpage dup pass.
*/
if (!IS_VALID_PGNO(bo->pgno) || (i % P_INDX == 0)) {
/* Not much to do on failure. */
if ((t_ret = __db_vrfy_prdbt(&unknown_key,
0, " ", handle, callback, 0, vdp)) != 0) {
if (ret == 0)
ret = t_ret;
goto err;
}
break;
}
/* Don't stop on error. */
if ((t_ret = __db_salvage_duptree(dbp,
vdp, bo->pgno, &dbt, handle, callback,
flags | SA_SKIPFIRSTKEY)) != 0 && ret == 0)
ret = t_ret;
break;
case B_KEYDATA:
end = (db_indx_t)DB_ALIGN(
beg + bk->len, sizeof(u_int32_t)) - 1;
dbt.data = bk->data;
dbt.size = bk->len;
if ((t_ret = __db_vrfy_prdbt(&dbt,
0, " ", handle, callback, 0, vdp)) != 0) {
if (ret == 0)
ret = t_ret;
goto err;
}
break;
case B_OVERFLOW:
end = beg + BOVERFLOW_SIZE - 1;
bo = (BOVERFLOW *)bk;
/* Don't stop on error. */
if ((t_ret = __db_safe_goff(dbp, vdp,
bo->pgno, &dbt, &ovflbuf, flags)) != 0 && ret == 0)
ret = t_ret;
if ((t_ret = __db_vrfy_prdbt(
t_ret == 0 ? &dbt : &unknown_key,
0, " ", handle, callback, 0, vdp)) != 0 && ret == 0)
ret = t_ret;
break;
default:
/*
* We should never get here; __db_vrfy_inpitem should
* not be returning 0 if bk->type is unrecognizable.
*/
DB_ASSERT(0);
if (ret == 0)
ret = EINVAL;
goto err;
}
/*
* If we're being aggressive, mark the beginning and end of
* the item; we'll come back and print whatever "junk" is in
* the gaps in case we had any bogus inp elements and thereby
* missed stuff.
*/
if (LF_ISSET(DB_AGGRESSIVE)) {
pgmap[beg] = VRFY_ITEM_BEGIN;
pgmap[end] = VRFY_ITEM_END;
}
}
/*
* If i is odd and this is a btree leaf, we've printed out a key but not
* a datum; fix this imbalance by printing an "UNKNOWN".
*/
if (pgtype == P_LBTREE && (i % P_INDX == 1) && ((ret =
__db_vrfy_prdbt(&unkdbt, 0, " ", handle, callback, 0, vdp)) != 0))
err_ret = ret;
err: if (pgmap != NULL)
__os_free(dbenv, pgmap);
__os_free(dbenv, ovflbuf);
if (ovflbuf != NULL)
__os_free(dbenv, ovflbuf);
/* Mark this page as done. */
if ((t_ret = __db_salvage_markdone(vdp, pgno)) != 0)
return (t_ret);
if ((t_ret = __db_salvage_markdone(vdp, pgno)) != 0 && ret == 0)
ret = t_ret;
return ((err_ret != 0) ? err_ret : ret);
return (ret);
}
/*

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: btree.src,v 10.42 2004/06/17 17:35:12 bostic Exp $
* $Id: btree.src,v 12.3 2005/08/08 03:37:05 ubell Exp $
*/
PREFIX __bam
@ -210,10 +210,10 @@ END
BEGIN relink 147
/* Fileid of db affected. */
DB fileid int32_t ld
/* The page being changed. */
/* The page being removed. */
ARG pgno db_pgno_t lu
/* The page's original lsn. */
POINTER lsn DB_LSN * lu
/* The new page number, if any. */
ARG new_pgno db_pgno_t lu
/* The previous page. */
ARG prev db_pgno_t lu
/* The previous page's original lsn. */
@ -223,3 +223,30 @@ ARG next db_pgno_t lu
/* The previous page's original lsn. */
POINTER lsn_next DB_LSN * lu
END
/*
* BTREE-merge -- Handles merging of pages during a compaction.
*/
BEGIN merge 148
DB fileid int32_t ld
ARG pgno db_pgno_t lu
POINTER lsn DB_LSN * lu
ARG npgno db_pgno_t lu
POINTER nlsn DB_LSN * lu
DBT hdr DBT s
DBT data DBT s
DBT ind DBT s
END
/*
* BTREE-pgno -- Handles replacing a page number in the record
* refernece on pgno by indx.
*/
BEGIN pgno 149
DB fileid int32_t ld
ARG pgno db_pgno_t lu
POINTER lsn DB_LSN * lu
ARG indx u_int32_t lu
ARG opgno db_pgno_t lu
ARG npgno db_pgno_t lu
END

View file

@ -1,29 +0,0 @@
Document file - DO NOT EDIT
<BEGIN> CORE_INFO_TYPE
Workspace
<END>
<BEGIN> CORE_INFO_VERSION
2.0
<END>
<BEGIN> projectList
$(PRJ_DIR)/BerkeleyDB.wpj \
$(PRJ_DIR)/db_archive/db_archive.wpj \
$(PRJ_DIR)/db_checkpoint/db_checkpoint.wpj \
$(PRJ_DIR)/db_deadlock/db_deadlock.wpj \
$(PRJ_DIR)/db_dump/db_dump.wpj \
$(PRJ_DIR)/db_load/db_load.wpj \
$(PRJ_DIR)/db_printlog/db_printlog.wpj \
$(PRJ_DIR)/db_recover/db_recover.wpj \
$(PRJ_DIR)/db_stat/db_stat.wpj \
$(PRJ_DIR)/db_upgrade/db_upgrade.wpj \
$(PRJ_DIR)/db_verify/db_verify.wpj \
$(PRJ_DIR)/dbdemo/dbdemo.wpj
<END>
<BEGIN> userComments
<END>

View file

@ -1,251 +0,0 @@
/*-
* 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);
}

View file

@ -1,39 +0,0 @@
This README describes the steps needed to run a demo example of BerkeleyDB.
1. Read the pages in the Reference Guide that describe building
BerkeleyDB on VxWorks:
$(WIND_BASE)/target/src/BerkeleyDB/docs/ref/build_vxworks/intro.html
$(WIND_BASE)/target/src/BerkeleyDB/docs/ref/build_vxworks/notes.html
$(WIND_BASE)/target/src/BerkeleyDB/docs/ref/build_vxworks/faq.html
2. Launch Tornado 2.0 and open up the BerkeleyDB project.
3. Add the demo project to that workspace:
$(WIND_BASE)/target/src/BerkeleyDB/build_vxworks/demo/dbdemo.wpj
4. Build BerkeleyDB as described in the Reference Guide.
5. Build the dbdemo project.
6. Download BerkeleyDB onto the target.
7. Download the dbdemo project onto the target.
8. Open a windsh to the target and run the demo:
-> dbdemo "<pathname>/<dbname>"
Where pathname is a pathname string pointing to a directory that the
demo can create a database in. That directory should already exist.
The dbname is the name for the database. For example:
-> dbdemo "/tmp/demo.db"
9. The demo program will ask for input. You can type in any string.
The program will add an entry to the database with that string as
the key and the reverse of that string as the data item for that key.
It will continue asking for input until you hit ^D or enter "quit".
Upon doing so, the demo program will display all the keys you have
entered as input and their data items.

View file

@ -21,12 +21,15 @@ Package=<4>
Project_Dep_Name db_deadlock
End Project Dependency
Begin Project Dependency
Project_Dep_Name DB_DLL
Project_Dep_Name db_dll
End Project Dependency
Begin Project Dependency
Project_Dep_Name db_dump
End Project Dependency
Begin Project Dependency
Project_Dep_Name db_hotbackup
End Project Dependency
Begin Project Dependency
Project_Dep_Name db_load
End Project Dependency
Begin Project Dependency
@ -45,7 +48,7 @@ Package=<4>
Project_Dep_Name db_verify
End Project Dependency
Begin Project Dependency
Project_Dep_Name DB_Static
Project_Dep_Name db_static
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_access
@ -63,9 +66,18 @@ Package=<4>
Project_Dep_Name ex_mpool
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_sequence
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_tpcb
End Project Dependency
Begin Project Dependency
Project_Dep_Name example_database_load
End Project Dependency
Begin Project Dependency
Project_Dep_Name example_database_read
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_access
End Project Dependency
Begin Project Dependency
@ -81,10 +93,31 @@ Package=<4>
Project_Dep_Name excxx_mpool
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_sequence
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_tpcb
End Project Dependency
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name excxx_example_database_load
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_example_database_read
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_repquote
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_txnguide
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_txnguide_inmem
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_txnguide
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_txnguide_inmem
End Project Dependency
}}}
@ -99,7 +132,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -114,7 +147,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -129,7 +162,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name DB_DLL
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -156,7 +189,22 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "db_hotbackup"=.\db_hotbackup.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -168,29 +216,11 @@ Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name DB_DLL
End Project Dependency
}}}
###############################################################################
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
}}}
###############################################################################
@ -204,7 +234,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -219,7 +249,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -234,12 +264,24 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "db_small"=.\db_small.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "db_stat"=.\db_stat.dsp - Package Owner=<4>
Package=<5>
@ -249,7 +291,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -276,7 +318,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name DB_DLL
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -309,7 +351,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -324,7 +366,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -339,7 +381,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -354,7 +396,58 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_csvcode"=.\ex_csvcode.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_csvload"=.\ex_csvload.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_csvcode
End Project Dependency
}}}
###############################################################################
Project: "ex_csvquery"=.\ex_csvquery.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_csvcode
End Project Dependency
}}}
@ -369,7 +462,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -384,7 +477,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -399,7 +492,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -414,7 +507,22 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_sequence"=.\ex_sequence.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -429,7 +537,67 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_txnguide"=.\ex_txnguide.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_txnguide_inmem"=.\ex_txnguide_inmem.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "example_database_load"=.\example_database_load.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "example_database_read"=.\example_database_read.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -444,7 +612,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -459,7 +627,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -474,7 +642,37 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_example_database_load"=.\excxx_example_database_load.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_example_database_read"=.\excxx_example_database_read.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -489,7 +687,7 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -504,7 +702,22 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_sequence"=.\excxx_sequence.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
@ -519,7 +732,37 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_lib
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_txnguide"=.\excxx_txnguide.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_txnguide_inmem"=.\excxx_txnguide_inmem.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}

View file

@ -4,7 +4,7 @@
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=@project_name@ - Win32 Debug Static
CFG=@project_name@ - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
@ -13,14 +13,18 @@ CFG=@project_name@ - Win32 Debug Static
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "@project_name@.mak" CFG="@project_name@ - Win32 Debug Static"
!MESSAGE NMAKE /f "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Release Static" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Debug Static" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 ASCII Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 ASCII Release" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win64 Debug AMD64" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win64 Release AMD64" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win64 Debug IA64" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win64 Release IA64" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
@ -34,99 +38,207 @@ RSC=rc.exe
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Output_Dir "@bin_rel_dest@"
# PROP BASE Intermediate_Dir "Release/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Output_Dir "@bin_rel_dest@"
# PROP Intermediate_Dir "Release/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /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 CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcmt"
# ADD BASE LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcmt" /libpath:"@lib_rel_dest@"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Output_Dir "@bin_debug_dest@"
# PROP BASE Intermediate_Dir "Debug/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Output_Dir "@bin_debug_dest@"
# PROP Intermediate_Dir "Debug/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /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 CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"libcmtd" /fixed:no
# ADD BASE LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"libcmtd" /fixed:no /libpath:"@lib_debug_dest@"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Release Static"
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@bin_debug_dest@_ASCII"
# PROP BASE Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@bin_debug_dest@_ASCII"
# PROP Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"libcmtd" /fixed:no
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"libcmtd" /fixed:no /libpath:"@lib_debug_dest@_ASCII"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Output_Dir "@bin_rel_dest@_ASCII"
# PROP BASE Intermediate_Dir "Release_ASCII/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_static"
# PROP Intermediate_Dir "Release_static"
# PROP Output_Dir "@bin_rel_dest@_ASCII"
# PROP Intermediate_Dir "Release_ASCII/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /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 CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 Release_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 Release_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib /nologo /subsystem:console /machine:I386
# ADD BASE LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcmt"
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcmt" /libpath:"@lib_rel_dest@_ASCII"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug Static"
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Output_Dir "@bin_debug_dest@_AMD64"
# PROP BASE Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_static"
# PROP Intermediate_Dir "Debug_static"
# PROP Output_Dir "@bin_debug_dest@_AMD64"
# PROP Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /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 CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD LINK32 Debug_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no
# ADD BASE LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:AMD64 /nodefaultlib:"libcmtd" /fixed:no
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:AMD64 /nodefaultlib:"libcmtd" /fixed:no /libpath:"@lib_debug_dest@_AMD64"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@bin_rel_dest@_AMD64"
# PROP BASE Intermediate_Dir "Release_AMD64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@bin_rel_dest@_AMD64"
# PROP Intermediate_Dir "Release_AMD64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:AMD64 /nodefaultlib:"libcmt"
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:AMD64 /nodefaultlib:"libcmt" /libpath:"@lib_rel_dest@_AMD64"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@bin_debug_dest@_IA64"
# PROP BASE Intermediate_Dir "Debug_IA64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@bin_debug_dest@_IA64"
# PROP Intermediate_Dir "Debug_IA64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:IA64 /nodefaultlib:"libcmtd" /fixed:no
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:IA64 /nodefaultlib:"libcmtd" /fixed:no /libpath:"@lib_debug_dest@_IA64"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@bin_rel_dest@_IA64"
# PROP BASE Intermediate_Dir "Release_IA64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@bin_rel_dest@_IA64"
# PROP Intermediate_Dir "Release_IA64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:IA64 /nodefaultlib:"libcmt"
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:IA64 /nodefaultlib:"libcmt" /libpath:"@lib_rel_dest@_IA64"
@POST_BUILD@
!ENDIF
@ -134,8 +246,12 @@ LINK32=link.exe
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
# Name "@project_name@ - Win32 Release Static"
# Name "@project_name@ - Win32 Debug Static"
# Name "@project_name@ - Win32 ASCII Debug"
# Name "@project_name@ - Win32 ASCII Release"
# Name "@project_name@ - Win64 Debug AMD64"
# Name "@project_name@ - Win64 Release AMD64"
# Name "@project_name@ - Win64 Debug IA64"
# Name "@project_name@ - Win64 Release IA64"
@SOURCE_FILES@
# Begin Source File

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1999-2004
* Copyright (c) 1999-2005
* Sleepycat Software. All rights reserved.
*
* $Id: dbkill.cpp,v 11.9 2004/01/28 03:35:52 bostic Exp $
* $Id: dbkill.cpp,v 12.1 2005/06/16 20:20:43 bostic Exp $
*/
/*
* Kill -

View file

@ -19,6 +19,12 @@ CFG=@project_name@ - Win32 Debug
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 ASCII Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 ASCII Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win64 Debug AMD64" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win64 Release AMD64" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win64 Debug IA64" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win64 Release IA64" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
@ -33,17 +39,17 @@ RSC=rc.exe
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Output_Dir "@lib_rel_dest@"
# PROP BASE Intermediate_Dir "Release/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Output_Dir "@lib_rel_dest@"
# PROP Intermediate_Dir "Release/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
@ -52,24 +58,25 @@ BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
# ADD BASE LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"@bin_rel_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll" /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Output_Dir "@lib_debug_dest@"
# PROP BASE Intermediate_Dir "Debug/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 2
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Output_Dir "@lib_debug_dest@"
# PROP Intermediate_Dir "Debug/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DB_CREATE_DLL" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# SUBTRACT CPP /Fr
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
@ -79,8 +86,182 @@ BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 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 /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
# ADD BASE LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /export:__db_assert /pdb:none /debug /machine:I386 /out:"@bin_debug_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_ASCII"
# PROP BASE Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_ASCII"
# PROP Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# SUBTRACT BASE CPP /Fr
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# SUBTRACT CPP /Fr
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"@bin_debug_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
# ADD LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /export:__db_assert /pdb:none /debug /machine:I386 /out:"@bin_debug_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_ASCII"
# PROP BASE Intermediate_Dir "Release_ASCII/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_ASCII"
# PROP Intermediate_Dir "Release_ASCII/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"@bin_rel_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
# ADD LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"@bin_rel_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll" /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_AMD64"
# PROP BASE Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_AMD64"
# PROP Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# SUBTRACT BASE CPP /Fr
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /Wp64 /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /debug /machine:AMD64 /out:"@bin_debug_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
# ADD LINK32 @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /export:__db_assert /debug /machine:AMD64 /out:"@bin_debug_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_AMD64"
# PROP BASE Intermediate_Dir "Release_AMD64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_AMD64"
# PROP Intermediate_Dir "Release_AMD64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:AMD64 /out:"@bin_rel_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
# ADD LINK32 @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:AMD64 /out:"@bin_rel_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll" /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_IA64"
# PROP BASE Intermediate_Dir "Debug_IA64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_IA64"
# PROP Intermediate_Dir "Debug_IA64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# SUBTRACT BASE CPP /Fr
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# SUBTRACT CPP /Fr
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /debug /machine:IA64 /out:"@bin_debug_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
# ADD LINK32 @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /export:__db_assert /debug /machine:IA64 /out:"@bin_debug_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_IA64"
# PROP BASE Intermediate_Dir "Release_IA64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_IA64"
# PROP Intermediate_Dir "Release_IA64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:IA64 /out:"@bin_rel_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
# ADD LINK32 @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:IA64 /out:"@bin_rel_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll" /libpath:"$(OUTDIR)"
@POST_BUILD@
!ENDIF
@ -88,6 +269,13 @@ LINK32=link.exe
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
# Name "@project_name@ - Win32 ASCII Debug"
# Name "@project_name@ - Win32 ASCII Release"
# Name "@project_name@ - Win64 Debug AMD64"
# Name "@project_name@ - Win64 Release AMD64"
# Name "@project_name@ - Win64 Debug IA64"
# Name "@project_name@ - Win64 Release IA64"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -1,4 +1,4 @@
; $Id: libdb_tcl.def,v 11.7 2002/10/14 23:44:20 mjc Exp $
; $Id: libdb_tcl.def,v 12.0 2004/11/17 03:48:15 bostic Exp $
DESCRIPTION 'Berkeley DB TCL interface Library'
EXPORTS

View file

@ -17,11 +17,11 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Sleepycat Software\0"
VALUE "FileDescription", "Berkeley DB 3.0 DLL\0"
VALUE "FileDescription", "Berkeley DB %MAJOR%.%MINOR% DLL\0"
VALUE "FileVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
VALUE "InternalName", "libdb.dll\0"
VALUE "LegalCopyright", "Copyright © Sleepycat Software Inc. 1997-2004\0"
VALUE "OriginalFilename", "libdb.dll\0"
VALUE "InternalName", "libdb%MAJOR%%MINOR%.dll\0"
VALUE "LegalCopyright", "Copyright © Sleepycat Software Inc. 1997-2005\0"
VALUE "OriginalFilename", "libdb%MAJOR%%MINOR%.dll\0"
VALUE "ProductName", "Sleepycat Software libdb\0"
VALUE "ProductVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
END

View file

@ -4,7 +4,7 @@
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=@project_name@ - Win32 Debug Static
CFG=@project_name@ - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
@ -13,12 +13,18 @@ CFG=@project_name@ - Win32 Debug Static
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "@project_name@.mak" CFG="@project_name@ - Win32 Debug Static"
!MESSAGE NMAKE /f "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "@project_name@ - Win32 Release Static" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win32 Debug Static" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win32 ASCII Release" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win32 ASCII Debug" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win64 Debug AMD64" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win64 Release AMD64" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win64 Debug IA64" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win64 Release IA64" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
@ -28,58 +34,202 @@ CFG=@project_name@ - Win32 Debug Static
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "@project_name@ - Win32 Release Static"
!IF "$(CFG)" == "@project_name@ - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release_static"
# PROP BASE Intermediate_Dir "Release_static"
# PROP BASE Output_Dir "@lib_rel_dest@"
# PROP BASE Intermediate_Dir "Release/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_static"
# PROP Intermediate_Dir "Release_static"
# PROP Output_Dir "@lib_rel_dest@"
# PROP Intermediate_Dir "Release/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
# ADD LIB32 /nologo /out:"Release_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
# ADD BASE LIB32 /nologo /out:"@lib_rel_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
# ADD LIB32 /nologo /out:"@lib_rel_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug Static"
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug"
# PROP BASE Use_MFC 1
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug_static"
# PROP BASE Intermediate_Dir "Debug_static"
# PROP BASE Output_Dir "@lib_debug_dest@"
# PROP BASE Intermediate_Dir "Debug/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 1
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_static"
# PROP Intermediate_Dir "Debug_static"
# PROP Output_Dir "@lib_debug_dest@"
# PROP Intermediate_Dir "Debug/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX"config.h" /FD /c
# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
# ADD LIB32 /nologo /out:"Debug_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
# ADD BASE LIB32 /nologo /out:"@lib_debug_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
# ADD LIB32 /nologo /out:"@lib_debug_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_ASCII"
# PROP BASE Intermediate_Dir "Release_ASCII/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_ASCII"
# PROP Intermediate_Dir "Release_ASCII/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_rel_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
# ADD LIB32 /nologo /out:"@lib_rel_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_ASCII"
# PROP BASE Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_ASCII"
# PROP Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_debug_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
# ADD LIB32 /nologo /out:"@lib_debug_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_AMD64"
# PROP BASE Intermediate_Dir "Debug/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_AMD64"
# PROP Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /Wp64 /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_debug_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
# ADD LIB32 /nologo /out:"@lib_debug_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_AMD64"
# PROP BASE Intermediate_Dir "Release_AMD64/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_AMD64"
# PROP Intermediate_Dir "Release_AMD64/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_rel_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
# ADD LIB32 /nologo /out:"@lib_rel_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_IA64"
# PROP BASE Intermediate_Dir "Debug_IA64/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_IA64"
# PROP Intermediate_Dir "Debug_IA64/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_debug_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
# ADD LIB32 /nologo /out:"@lib_debug_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib"
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_IA64"
# PROP BASE Intermediate_Dir "Release_IA64/@project_name@"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_IA64"
# PROP Intermediate_Dir "Release_IA64/@project_name@"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"@lib_rel_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
# ADD LIB32 /nologo /out:"@lib_rel_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib"
!ENDIF
# Begin Target
# Name "@project_name@ - Win32 Release Static"
# Name "@project_name@ - Win32 Debug Static"
# Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug"
# Name "@project_name@ - Win32 ASCII Release"
# Name "@project_name@ - Win32 ASCII Debug"
# Name "@project_name@ - Win64 Debug AMD64"
# Name "@project_name@ - Win64 Release AMD64"
# Name "@project_name@ - Win64 Debug IA64"
# Name "@project_name@ - Win64 Release IA64"
@SOURCE_FILES@
# End Target
# End Project

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -32,7 +32,7 @@
* 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 $
* $Id: getcwd.c,v 12.1 2005/06/16 20:20:48 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -32,7 +32,7 @@
* 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 $
* $Id: getopt.c,v 12.1 2005/06/16 20:20:48 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -32,7 +32,7 @@
* 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 $
* $Id: memcmp.c,v 12.1 2005/06/16 20:20:48 bostic Exp $
*/
#include "db_config.h"

View file

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

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2004
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: raise.c,v 11.8 2004/01/28 03:35:52 bostic Exp $
* $Id: raise.c,v 12.2 2005/06/16 20:20:50 bostic Exp $
*/
#include "db_config.h"
@ -26,9 +26,5 @@ int
raise(s)
int s;
{
/*
* Do not use __os_id(), as it may not return the process ID -- any
* system with kill(3) probably has getpid(3).
*/
return (kill(getpid(), s));
}

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: snprintf.c,v 11.18 2004/09/22 03:32:43 bostic Exp $
* $Id: snprintf.c,v 12.1 2005/06/16 20:20:50 bostic Exp $
*/
#include "db_config.h"

View file

@ -30,7 +30,7 @@
* 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 $
* $Id: strcasecmp.c,v 12.0 2004/11/17 03:43:15 bostic Exp $
*/
#include "db_config.h"

View file

@ -30,7 +30,7 @@
* 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 $
* $Id: strdup.c,v 12.0 2004/11/17 03:43:15 bostic Exp $
*/
#include "db_config.h"

View file

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

View file

@ -30,7 +30,7 @@
* 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 $
* $Id: strtol.c,v 12.0 2004/11/17 03:43:15 bostic Exp $
*/
#include "db_config.h"

View file

@ -30,7 +30,7 @@
* 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 $
* $Id: strtoul.c,v 12.0 2004/11/17 03:43:15 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: crypto_stub.c,v 1.4 2004/01/28 03:35:52 bostic Exp $
* $Id: crypto_stub.c,v 12.2 2005/07/20 16:50:55 bostic Exp $
*/
#include "db_config.h"
@ -32,9 +32,9 @@ __crypto_region_init(dbenv)
infop = dbenv->reginfo;
renv = infop->primary;
MUTEX_LOCK(dbenv, &renv->mutex);
MUTEX_LOCK(dbenv, renv->mtx_regenv);
ret = !(renv->cipher_off == INVALID_ROFF);
MUTEX_UNLOCK(dbenv, &renv->mutex);
MUTEX_UNLOCK(dbenv, renv->mtx_regenv);
if (ret == 0)
return (0);

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_byteorder.c,v 11.10 2004/01/28 03:35:52 bostic Exp $
* $Id: db_byteorder.c,v 12.1 2005/06/16 20:20:52 bostic Exp $
*/
#include "db_config.h"

View file

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

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_err.c,v 11.123 2004/09/22 03:07:50 bostic Exp $
* $Id: db_err.c,v 12.19 2005/10/19 19:06:29 sue Exp $
*/
#include "db_config.h"
@ -22,6 +22,7 @@
#include "dbinc/db_shash.h"
#include "dbinc/lock.h"
#include "dbinc/log.h"
#include "dbinc/mp.h"
#include "dbinc/txn.h"
static void __db_msgcall __P((const DB_ENV *, const char *, va_list));
@ -88,7 +89,7 @@ __db_fnl(dbenv, name)
const char *name;
{
__db_err(dbenv,
"%s: the DB_DIRTY_READ, DB_DEGREE_2 and DB_RMW flags require locking",
"%s: DB_READ_COMMITTED, DB_READ_UNCOMMITTED and DB_RMW require locking",
name);
return (EINVAL);
}
@ -186,7 +187,7 @@ __db_panic(dbenv, errval)
int errval;
{
if (dbenv != NULL) {
PANIC_SET(dbenv, 1);
__db_panic_set(dbenv, 1);
__db_err(dbenv, "PANIC: %s", db_strerror(errval));
@ -213,6 +214,22 @@ __db_panic(dbenv, errval)
return (DB_RUNRECOVERY);
}
/*
* __db_panic_set --
* Set/clear unrecoverable error.
*
* PUBLIC: void __db_panic_set __P((DB_ENV *, int));
*/
void
__db_panic_set(dbenv, on)
DB_ENV *dbenv;
int on;
{
if (dbenv != NULL && dbenv->reginfo != NULL)
((REGENV *)
((REGINFO *)dbenv->reginfo)->primary)->panic = on ? 1 : 0;
}
/*
* db_strerror --
* ANSI C strerror(3) for DB.
@ -275,8 +292,16 @@ db_strerror(error)
return ("DB_REP_HANDLE_DEAD: Handle is no longer valid");
case DB_REP_HOLDELECTION:
return ("DB_REP_HOLDELECTION: Need to hold an election");
case DB_REP_IGNORE:
return ("DB_REP_IGNORE: Replication record ignored");
case DB_REP_ISPERM:
return ("DB_REP_ISPERM: Permanent record written");
case DB_REP_JOIN_FAILURE:
return
("DB_REP_JOIN_FAILURE: Unable to join replication group");
case DB_REP_LOCKOUT:
return
("DB_REP_LOCKOUT: Waiting for replication recovery to complete");
case DB_REP_NEWMASTER:
return ("DB_REP_NEWMASTER: A new master has declared itself");
case DB_REP_NEWSITE:
@ -502,59 +527,6 @@ __db_msgfile(dbenv, fmt, ap)
(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: __attribute__ ((__format__ (__printf__, 5, 6)));
*/
void
#ifdef STDC_HEADERS
__db_logmsg(const DB_ENV *dbenv,
DB_TXN *txnid, const char *opname, u_int32_t flags, const char *fmt, ...)
#else
__db_logmsg(dbenv, txnid, opname, flags, fmt, va_alist)
const DB_ENV *dbenv;
DB_TXN *txnid;
const char *opname, *fmt;
u_int32_t flags;
va_dcl
#endif
{
DBT opdbt, msgdbt;
DB_LSN lsn;
va_list ap;
char __logbuf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
if (!LOGGING_ON(dbenv))
return;
#ifdef STDC_HEADERS
va_start(ap, fmt);
#else
va_start(ap);
#endif
memset(&opdbt, 0, sizeof(opdbt));
opdbt.data = (void *)opname;
opdbt.size = (u_int32_t)(strlen(opname) + 1);
memset(&msgdbt, 0, sizeof(msgdbt));
msgdbt.data = __logbuf;
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.
*/
(void)__db_debug_log(
(DB_ENV *)dbenv, txnid, &lsn, flags, &opdbt, -1, &msgdbt, NULL, 0);
}
/*
* __db_unknown_flag -- report internal error
*
@ -620,38 +592,14 @@ __db_check_txn(dbp, txn, assoc_lid, read_op)
/*
* Check for common transaction errors:
* Failure to pass a transaction handle to a DB operation
* Failure to configure the DB handle in a proper environment
* Operation on a handle whose open commit hasn't completed.
*
* Read operations don't require a txn even if we've used one before
* with this handle, although if they do have a txn, we'd better be
* prepared for it.
* an operation on a handle whose open commit hasn't completed.
* a transaction handle in a non-transactional environment
* a transaction handle for a non-transactional database
*/
if (txn == NULL) {
if (!read_op && F_ISSET(dbp, DB_AM_TXN)) {
__db_err(dbenv,
"DB handle previously used in transaction, missing transaction handle");
return (EINVAL);
}
if (dbp->cur_lid >= TXN_MINIMUM)
goto open_err;
} else {
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));
@ -660,6 +608,19 @@ __db_check_txn(dbp, txn, assoc_lid, read_op)
"Transaction specified for a DB handle opened outside a transaction");
return (EINVAL);
}
if (F_ISSET(txn, TXN_DEADLOCK)) {
__db_err(dbenv,
"Previous deadlock return not resolved");
return (EINVAL);
}
if (dbp->cur_lid >= TXN_MINIMUM && dbp->cur_lid != txn->txnid) {
if ((ret = __lock_locker_is_parent(dbenv,
dbp->cur_lid, txn->txnid, &isp)) != 0)
return (ret);
if (!isp)
goto open_err;
}
}
/*
@ -684,6 +645,15 @@ __db_check_txn(dbp, txn, assoc_lid, read_op)
return (EINVAL);
}
/*
* Check the txn and dbp are from the same env.
*/
if (txn != NULL && dbenv != txn->mgrp->dbenv) {
__db_err(dbenv,
"Transaction and database from different environments");
return (EINVAL);
}
return (0);
open_err:
__db_err(dbenv,
@ -738,6 +708,69 @@ __db_rec_repl(dbenv, data_size, data_dlen)
return (EINVAL);
}
#if defined(DIAGNOSTIC) || defined(DEBUG_ROP) || defined(DEBUG_WOP)
/*
* __dbc_logging --
* In DIAGNOSTIC mode, check for bad replication combinations.
*
* PUBLIC: int __dbc_logging __P((DBC *));
*/
int
__dbc_logging(dbc)
DBC *dbc;
{
DB_ENV *dbenv;
DB_REP *db_rep;
int ret;
dbenv = dbc->dbp->dbenv;
db_rep = dbenv->rep_handle;
ret = LOGGING_ON(dbenv) &&
!F_ISSET(dbc, DBC_RECOVER) && !IS_REP_CLIENT(dbenv);
/*
* If we're not using replication or running recovery, return.
*/
if (db_rep == NULL || F_ISSET(dbc, DBC_RECOVER))
return (ret);
#ifndef DEBUG_ROP
/*
* Only check when DEBUG_ROP is not configured. People often do
* non-transactional reads, and debug_rop is going to write
* a log record.
*/
{
REP *rep;
rep = db_rep->region;
/*
* If we're a client and not running recovery or internally, error.
*/
if (IS_REP_CLIENT(dbenv) && !F_ISSET(dbc->dbp, DB_AM_CL_WRITER)) {
__db_err(dbenv, "Dbc_logging: Client update");
goto err;
}
if (IS_REP_MASTER(dbenv) && dbc->txn == NULL) {
__db_err(dbenv, "Dbc_logging: Master non-txn update");
goto err;
}
if (0) {
err: __db_err(dbenv, "Rep: flags 0x%lx msg_th %lu, start_th %d",
(u_long)rep->flags, (u_long)rep->msg_th, rep->start_th);
__db_err(dbenv, "Rep: handle %lu, opcnt %lu, in_rec %d",
(u_long)rep->handle_cnt, (u_long)rep->op_cnt,
rep->in_recovery);
abort();
}
}
#endif
return (ret);
}
#endif
/*
* __db_check_lsn --
* Display the log sequence error message.
@ -755,3 +788,53 @@ __db_check_lsn(dbenv, lsn, prev)
(u_long)(prev)->file, (u_long)(prev)->offset);
return (EINVAL);
}
/*
* __db_rdonly --
* Common readonly message.
* PUBLIC: int __db_rdonly __P((const DB_ENV *, const char *));
*/
int
__db_rdonly(dbenv, name)
const DB_ENV *dbenv;
const char *name;
{
__db_err(dbenv, "%s: attempt to modify a read-only database", name);
return (EACCES);
}
/*
* __db_space_err --
* Common out of space message.
* PUBLIC: int __db_space_err __P((const DB *));
*/
int
__db_space_err(dbp)
const DB *dbp;
{
__db_err(dbp->dbenv,
"%s: file limited to %lu pages",
dbp->fname, (u_long)dbp->mpf->mfp->maxpgno);
return (ENOSPC);
}
/*
* __db_failed --
* Common failed thread message.
*
* PUBLIC: int __db_failed __P((const DB_ENV *,
* PUBLIC: const char *, pid_t, db_threadid_t));
*/
int
__db_failed(dbenv, msg, pid, tid)
const DB_ENV *dbenv;
const char *msg;
pid_t pid;
db_threadid_t tid;
{
char buf[DB_THREADID_STRLEN];
__db_err(dbenv, "Thread/process %s failed: %s",
dbenv->thread_id_string((DB_ENV*)dbenv, pid, tid, buf), msg);
return (DB_RUNRECOVERY);
}

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_getlong.c,v 11.22 2004/10/28 14:43:26 bostic Exp $
* $Id: db_getlong.c,v 12.1 2005/06/16 20:20:53 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2004
* Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_idspace.c,v 1.9 2004/01/28 03:35:52 bostic Exp $
* $Id: db_idspace.c,v 12.1 2005/06/16 20:20:53 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -35,7 +35,7 @@
* 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 $
* $Id: db_log2.c,v 12.1 2005/06/16 20:20:53 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2004
* Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved.
*
* $Id: util_arg.c,v 1.6 2004/01/28 03:35:52 bostic Exp $
* $Id: util_arg.c,v 12.1 2005/06/16 20:20:53 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2004
* Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved.
*
* $Id: util_cache.c,v 1.8 2004/02/17 16:03:05 bostic Exp $
* $Id: util_cache.c,v 12.1 2005/06/16 20:20:54 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2004
* Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved.
*
* $Id: util_log.c,v 1.14 2004/01/28 03:35:52 bostic Exp $
* $Id: util_log.c,v 12.4 2005/10/12 17:47:17 bostic Exp $
*/
#include "db_config.h"
@ -40,16 +40,18 @@ __db_util_logset(progname, fname)
const char *progname;
char *fname;
{
pid_t pid;
db_threadid_t tid;
FILE *fp;
time_t now;
u_int32_t id;
if ((fp = fopen(fname, "w")) == NULL)
goto err;
(void)time(&now);
__os_id(&id);
fprintf(fp, "%s: %lu %s", progname, (u_long)id, ctime(&now));
__os_id(NULL, &pid, &tid);
fprintf(fp, "%s: %lu %s", progname, (u_long)pid, ctime(&now));
if (fclose(fp) == EOF)
goto err;

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2004
* Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved.
*
* $Id: util_sig.c,v 1.9 2004/01/28 03:35:54 bostic Exp $
* $Id: util_sig.c,v 12.1 2005/06/16 20:20:55 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2004
* Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved.
*
* Some parts of this code originally written by Adam Stubblefield,
* -- astubble@rice.edu.
*
* $Id: aes_method.c,v 1.20 2004/09/17 22:00:25 mjc Exp $
* $Id: aes_method.c,v 12.1 2005/06/16 20:20:55 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,13 +1,13 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* Some parts of this code originally written by Adam Stubblefield
* -- astubble@rice.edu
*
* $Id: crypto.c,v 1.31 2004/10/15 16:59:38 bostic Exp $
* $Id: crypto.c,v 12.5 2005/07/20 16:50:56 bostic Exp $
*/
#include "db_config.h"
@ -40,35 +40,31 @@ __crypto_region_init(dbenv)
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;
return (0);
if (!F_ISSET(infop, REGION_CREATE)) {
__db_err(dbenv,
"Joining non-encrypted environment with encryption key");
ret = EINVAL;
goto err;
return (EINVAL);
}
if (F_ISSET(db_cipher, CIPHER_ANY)) {
__db_err(dbenv, "Encryption algorithm not supplied");
ret = EINVAL;
goto err;
return (EINVAL);
}
/*
* Must create the shared information. We need:
* Shared cipher information that contains the passwd.
* After we copy the passwd, we smash and free the one in the
* dbenv.
* 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;
if ((ret =
__db_shalloc(infop, sizeof(CIPHER), 0, &cipher)) != 0)
return (ret);
memset(cipher, 0, sizeof(*cipher));
if ((ret = __db_shalloc(
infop, dbenv->passwd_len, 0, &sh_passwd)) != 0) {
__db_shalloc_free(infop, cipher);
goto err;
return (ret);
}
memset(sh_passwd, 0, dbenv->passwd_len);
cipher->passwd = R_OFFSET(infop, sh_passwd);
@ -79,51 +75,44 @@ __crypto_region_init(dbenv)
} else {
if (!CRYPTO_ON(dbenv)) {
__db_err(dbenv,
"Encrypted environment: no encryption key supplied");
ret = EINVAL;
goto err;
"Encrypted environment: no encryption key supplied");
return (EINVAL);
}
cipher = R_ADDR(infop, renv->cipher_off);
sh_passwd = R_ADDR(infop, cipher->passwd);
if ((cipher->passwd_len != dbenv->passwd_len) ||
memcmp(dbenv->passwd, sh_passwd, cipher->passwd_len) != 0) {
__db_err(dbenv, "Invalid password");
ret = EPERM;
goto err;
return (EPERM);
}
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;
return (EINVAL);
}
if (F_ISSET(db_cipher, CIPHER_ANY))
/*
* We have CIPHER_ANY and we are joining the
* existing env. Setup our cipher structure
* for whatever algorithm this env has.
* 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;
return (ret);
}
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.
* 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);
}
@ -236,33 +225,54 @@ __crypto_decrypt_meta(dbenv, dbp, mbuf, do_metachk)
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 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;
/*
* !!!
* We used an "unused" field in the meta-data page to flag whether or
* not the database is encrypted. Unfortunately, that unused field
* was used in Berkeley DB releases before 3.0 (for example, 2.7.7).
* It would have been OK, except encryption doesn't follow the usual
* rules of "upgrade before doing anything else", we check encryption
* before checking for old versions of the database.
*
* We don't have to check Btree databases -- before 3.0, the field of
* interest was the bt_maxkey field (which was never supported and has
* since been removed).
*
* Ugly check to jump out if this format is older than what we support.
* It assumes no encrypted page will have an unencrypted magic number,
* but that seems relatively safe. [#10920]
*/
if (meta->magic == DB_HASHMAGIC && meta->version <= 5)
return (0);
/*
* Meta-pages may be encrypted for DBMETASIZE bytes. If we have a
* non-zero IV (that is written after encryption) then we decrypt (or
* error if the user isn't set up for security). We guarantee that
* the IV space on non-encrypted pages will be zero and a zero-IV is
* illegal for encryption. Therefore any non-zero IV means an
* encrypted database. This basically checks the passwd on the file
* if we cannot find a good magic number. We walk through all the
* algorithms we know about attempting to decrypt (and possibly
* byteswap).
*
* !!!
* All method meta pages have the IV and checksum at the exact same
* location, but not in DBMETA, use BTMETA.
*/
if (meta->encrypt_alg != 0) {
db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
if (!F_ISSET(dbp, DB_AM_ENCRYPT)) {
@ -272,11 +282,10 @@ __crypto_decrypt_meta(dbenv, dbp, mbuf, do_metachk)
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.
* 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);
}
@ -294,9 +303,9 @@ __crypto_decrypt_meta(dbenv, dbp, mbuf, do_metachk)
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.
* 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:
@ -330,10 +339,10 @@ alg_retry:
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.
* 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.
@ -381,5 +390,5 @@ __crypto_set_passwd(dbenv_src, dbenv_dest)
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));
return (__env_set_encrypt(dbenv_dest, sh_passwd, DB_ENCRYPT_AES));
}

View file

@ -108,7 +108,7 @@ The setup of the security subsystem will be similar to replication initializatio
since it is a sort of subsystem, but it does not have its own region.&nbsp;
When the environment handle is created via <i>db_env_create</i>, we initialize
our <i>set_encrypt</i> method to be the RPC or local version.&nbsp; Therefore
the <i>__dbenv</i> structure needs a new pointer:
the <i>DB_ENV</i> structure needs a new pointer:
<pre>&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp; *crypto_handle;&nbsp;&nbsp; /* Security handle */</pre>
The crypto handle will really point to a new <i>__db_cipher</i> structure
that will contain a set of functions and a pointer to the in-memory information
@ -134,21 +134,21 @@ this is set up, it is read-only forever.
<p>During <a href="../docs/api_c/env_set_encrypt.html">dbenv->set_encrypt</a>,
we set the encryption, decryption and checksumming methods to the appropriate
functions based on the flags.&nbsp; This function will allocate us a crypto
handle that we store in the <i>__dbenv</i> structure just like all the
handle that we store in the <i>DB_ENV</i> structure just like all the
other subsystems.&nbsp; For now, only AES ciphering functions and SHA1
checksumming functions are supported.&nbsp; Also we will copy the password
into the <i>__dbenv</i> structure.&nbsp; We ultimately need to keep the
into the <i>DB_ENV</i> structure.&nbsp; We ultimately need to keep the
password in the environment's shared memory region or compare this one
against the one that is there, if we are joining an existing environment,
but we do not have it yet because open has not yet been called.&nbsp; We
will allocate a structure that will be used in initialization and set up
the function pointers to point to the algorithm-specific functions.
<p>In the&nbsp; <i>__dbenv_open</i> path, in <i>__db_e_attach</i>, if we
<p>In the&nbsp; <i>__env_open</i> path, in <i>__db_e_attach</i>, if we
are creating the region and the <i>dbenv->passwd</i> field is set, we need
to use the length of the password in the initial computation of the environment's
size.&nbsp; This guarantees sufficient space for storing the password in
shared memory.&nbsp; Then we will call a new function to initialize the
security region, <i>__crypto_region_init</i> in <i>__dbenv_open</i>.&nbsp;
security region, <i>__crypto_region_init</i> in <i>__env_open</i>.&nbsp;
If we are the creator, we will allocate space in the shared region to store
the password and copy the password into that space.&nbsp; Or, if we are
not the creator we will compare the password stored in the dbenv with the
@ -304,7 +304,7 @@ We will have per-process state vectors that are set up when a process begins.&nb
That way we minimize the contention and only multi-threaded processes need
acquire locks for the IV.&nbsp; We will have the state vector in the environment
handle in heap memory, as well as the index and there will be a mutex protecting
it for threaded access.&nbsp; This will be added to the <i>__dbenv</i>
it for threaded access.&nbsp; This will be added to the <i>DB_ENV</i>
structure:
<pre>&nbsp;&nbsp;&nbsp; DB_MUTEX&nbsp;&nbsp;&nbsp; *mt_mutexp;&nbsp;&nbsp; /* Mersenne Twister mutex */
&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *mti;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* MT index */

View file

@ -1,5 +1,5 @@
/*
* $Id: mt19937db.c,v 1.12 2004/06/14 16:54:27 mjc Exp $
* $Id: mt19937db.c,v 12.1 2005/07/20 16:50:57 bostic Exp $
*/
#include "db_config.h"
@ -69,7 +69,7 @@ __db_generate_iv(dbenv, iv)
ret = 0;
n = DB_IV_BYTES / sizeof(u_int32_t);
MUTEX_THREAD_LOCK(dbenv, dbenv->mt_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_mt);
if (dbenv->mt == NULL) {
if ((ret = __os_calloc(dbenv, 1, N*sizeof(unsigned long),
&dbenv->mt)) != 0)
@ -77,17 +77,16 @@ __db_generate_iv(dbenv, iv)
/* mti==N+1 means mt[N] is not initialized */
dbenv->mti = N + 1;
}
for (i = 0; i < n; i++)
{
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);
MUTEX_UNLOCK(dbenv, dbenv->mtx_mt);
return (0);
}
@ -137,7 +136,7 @@ __db_lsgenrand(seed_array, mt, mtip)
static unsigned long
__db_genrand(dbenv)
DB_ENV *dbenv;
DB_ENV *dbenv;
{
unsigned long y;
static unsigned long mag01[2]={0x0, MATRIX_A};
@ -145,7 +144,7 @@ __db_genrand(dbenv)
u_int32_t secs, seed, usecs;
/*
* We are called with the mt_mutexp locked
* We are called with DB_ENV->mtx_mt locked.
*/
if (dbenv->mti >= N) { /* generate N words at one time */
int kk;

View file

@ -1,5 +1,5 @@
/*
* $Id: rijndael-alg-fst.h,v 1.2 2002/01/08 18:53:37 sue Exp $
* $Id: rijndael-alg-fst.h,v 12.0 2004/11/17 03:43:17 bostic Exp $
*/
/**
* rijndael-alg-fst.h

View file

@ -1,5 +1,5 @@
/*
* $Id: rijndael-api-fst.h,v 1.5 2003/03/17 19:42:18 bostic Exp $
* $Id: rijndael-api-fst.h,v 12.0 2004/11/17 03:43:17 bostic Exp $
*/
/**
* rijndael-api-fst.h

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2004
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_db.cpp,v 11.87 2004/07/15 18:26:48 ubell Exp $
* $Id: cxx_db.cpp,v 12.4 2005/10/18 14:25:53 mjc Exp $
*/
#include "db_config.h"
@ -219,6 +219,9 @@ int Db::error_policy()
}
DB_DESTRUCTOR(close, (u_int32_t flags), (db, flags), DB_RETOK_STD)
DB_METHOD(compact, (DbTxn *txnid, Dbt *start, Dbt *stop,
DB_COMPACT *c_data, u_int32_t flags, Dbt *end),
(db, unwrap(txnid), start, stop, c_data, flags, end), DB_RETOK_STD)
// The following cast implies that Dbc can be no larger than DBC
DB_METHOD(cursor, (DbTxn *txnid, Dbc **cursorp, u_int32_t flags),
@ -331,7 +334,7 @@ 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))
if (ret == DB_BUFFER_SMALL && DB_OVERFLOWED_DBT(value))
DB_ERROR_DBT(env_, "Db::pget", value, error_policy());
else
DB_ERROR(env_, "Db::pget", ret, error_policy());
@ -536,8 +539,6 @@ int Db::verify(const char *name, const char *subdb,
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),

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2004
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_dbc.cpp,v 11.59 2004/01/28 03:35:56 bostic Exp $
* $Id: cxx_dbc.cpp,v 12.2 2005/09/30 07:38:25 mjc Exp $
*/
#include "db_config.h"
@ -80,10 +80,10 @@ int Dbc::get(Dbt* key, Dbt *data, u_int32_t _flags)
ret = dbc->c_get(dbc, key, data, _flags);
if (!DB_RETOK_DBCGET(ret)) {
if (ret == ENOMEM && DB_OVERFLOWED_DBT(key))
if (ret == DB_BUFFER_SMALL && DB_OVERFLOWED_DBT(key))
DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::get", key, ON_ERROR_UNKNOWN);
else if (ret == ENOMEM && DB_OVERFLOWED_DBT(data))
else if (ret == DB_BUFFER_SMALL && DB_OVERFLOWED_DBT(data))
DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::get", data, ON_ERROR_UNKNOWN);
else
@ -103,10 +103,10 @@ 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))
if (ret == DB_BUFFER_SMALL && DB_OVERFLOWED_DBT(key))
DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::pget", key, ON_ERROR_UNKNOWN);
else if (ret == ENOMEM && DB_OVERFLOWED_DBT(data))
else if (ret == DB_BUFFER_SMALL && DB_OVERFLOWED_DBT(data))
DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::pget", data, ON_ERROR_UNKNOWN);
else

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2004
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_dbt.cpp,v 11.55 2004/01/28 03:35:56 bostic Exp $
* $Id: cxx_dbt.cpp,v 12.1 2005/06/16 20:20:58 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2004
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_env.cpp,v 11.105 2004/09/22 22:20:31 mjc Exp $
* $Id: cxx_env.cpp,v 12.14 2005/10/18 14:49:27 mjc Exp $
*/
#include "db_config.h"
@ -17,7 +17,11 @@
#include "dbinc/cxx_int.h"
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_am.h"
#include "dbinc/log.h"
#include "dbinc_auto/common_ext.h"
#include "dbinc_auto/log_ext.h"
#ifdef HAVE_CXX_STDHEADERS
using std::cerr;
@ -91,7 +95,7 @@ void _paniccall_intercept_c(DB_ENV *env, int errval)
extern "C"
void _stream_error_function_c(const DB_ENV *env,
const char *prefix, const char *message)
const char *prefix, const char *message)
{
DbEnv::_stream_error_function(env, prefix, message);
}
@ -103,21 +107,38 @@ void _stream_message_function_c(const DB_ENV *env, const char *message)
}
extern "C"
int _app_dispatch_intercept_c(DB_ENV *env, DBT *dbt,
DB_LSN *lsn, db_recops op)
int _app_dispatch_intercept_c(DB_ENV *env, DBT *dbt, 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, const DB_LSN *lsn, int id,
u_int32_t flags)
int _rep_send_intercept_c(DB_ENV *env, const DBT *cntrl, const DBT *data,
const DB_LSN *lsn, int id, u_int32_t flags)
{
return (DbEnv::_rep_send_intercept(env,
cntrl, data, lsn, id, flags));
}
extern "C"
int _isalive_intercept_c(DB_ENV *env, pid_t pid, db_threadid_t thrid)
{
return (DbEnv::_isalive_intercept(env, pid, thrid));
}
extern "C"
void _thread_id_intercept_c(DB_ENV *env, pid_t *pidp, db_threadid_t *thridp)
{
DbEnv::_thread_id_intercept(env, pidp, thridp);
}
extern "C"
char *_thread_id_string_intercept_c(DB_ENV *env, pid_t pid,
db_threadid_t thrid, char *buf)
{
return (DbEnv::_thread_id_string_intercept(env, pid, thrid, buf));
}
void DbEnv::_feedback_intercept(DB_ENV *env, int opcode, int pct)
{
DbEnv *cxxenv = DbEnv::get_DbEnv(env);
@ -150,8 +171,8 @@ void DbEnv::_paniccall_intercept(DB_ENV *env, int errval)
(*cxxenv->paniccall_callback_)(cxxenv, errval);
}
int DbEnv::_app_dispatch_intercept(DB_ENV *env, DBT *dbt,
DB_LSN *lsn, db_recops op)
int DbEnv::_app_dispatch_intercept(DB_ENV *env, DBT *dbt, DB_LSN *lsn,
db_recops op)
{
DbEnv *cxxenv = DbEnv::get_DbEnv(env);
if (cxxenv == 0) {
@ -170,9 +191,19 @@ int DbEnv::_app_dispatch_intercept(DB_ENV *env, DBT *dbt,
return ((*cxxenv->app_dispatch_callback_)(cxxenv, cxxdbt, cxxlsn, op));
}
int DbEnv::_rep_send_intercept(DB_ENV *env, const DBT *cntrl,
const DBT *data, const DB_LSN *lsn,
int id, u_int32_t flags)
int DbEnv::_isalive_intercept(DB_ENV *env, pid_t pid, db_threadid_t thrid)
{
DbEnv *cxxenv = DbEnv::get_DbEnv(env);
if (cxxenv == 0) {
DB_ERROR(DbEnv::get_DbEnv(env),
"DbEnv::isalive_callback", EINVAL, ON_ERROR_UNKNOWN);
return (0);
}
return ((*cxxenv->isalive_callback_)(cxxenv, pid, thrid));
}
int DbEnv::_rep_send_intercept(DB_ENV *env, const DBT *cntrl, const DBT *data,
const DB_LSN *lsn, int id, u_int32_t flags)
{
DbEnv *cxxenv = DbEnv::get_DbEnv(env);
if (cxxenv == 0) {
@ -187,6 +218,28 @@ int DbEnv::_rep_send_intercept(DB_ENV *env, const DBT *cntrl,
cxxcntrl, cxxdata, cxxlsn, id, flags));
}
void DbEnv::_thread_id_intercept(DB_ENV *env, pid_t *pidp, db_threadid_t *thridp)
{
DbEnv *cxxenv = DbEnv::get_DbEnv(env);
if (cxxenv == 0) {
DB_ERROR(DbEnv::get_DbEnv(env),
"DbEnv::thread_id_callback", EINVAL, ON_ERROR_UNKNOWN);
} else
cxxenv->thread_id_callback_(cxxenv, pidp, thridp);
}
char *DbEnv::_thread_id_string_intercept(DB_ENV *env, pid_t pid,
db_threadid_t thrid, char *buf)
{
DbEnv *cxxenv = DbEnv::get_DbEnv(env);
if (cxxenv == 0) {
DB_ERROR(DbEnv::get_DbEnv(env),
"DbEnv::thread_id_string_callback", EINVAL, ON_ERROR_UNKNOWN);
return (NULL);
}
return (cxxenv->thread_id_string_callback_(cxxenv, pid, thrid, buf));
}
// A truism for the DbEnv object is that there is a valid
// DB_ENV handle from the constructor until close().
// After the close, the DB_ENV handle is invalid and
@ -208,8 +261,6 @@ DbEnv::DbEnv(u_int32_t flags)
, app_dispatch_callback_(0)
, feedback_callback_(0)
, paniccall_callback_(0)
, pgin_callback_(0)
, pgout_callback_(0)
, rep_send_callback_(0)
{
if ((construct_error_ = initialize(0)) != 0)
@ -226,8 +277,6 @@ DbEnv::DbEnv(DB_ENV *env, u_int32_t flags)
, app_dispatch_callback_(0)
, feedback_callback_(0)
, paniccall_callback_(0)
, pgin_callback_(0)
, pgout_callback_(0)
, rep_send_callback_(0)
{
if ((construct_error_ = initialize(env)) != 0)
@ -326,10 +375,20 @@ void *DbEnv::get_app_private() const
return unwrapConst(this)->app_private;
}
DBENV_METHOD(failchk, (u_int32_t flags), (dbenv, flags))
DBENV_METHOD(fileid_reset, (const char *file, u_int32_t flags),
(dbenv, file, flags))
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))
bool DbEnv::is_bigendian()
{
return unwrap(this)->is_bigendian() ? true : false;
}
DBENV_METHOD(set_thread_count, (u_int32_t count), (dbenv, count))
// used internally during constructor
// to associate an existing DB_ENV with this DbEnv,
// or create a new one.
@ -392,10 +451,27 @@ DBENV_METHOD(log_file, (DbLsn *lsn, char *namep, size_t len),
DBENV_METHOD(log_flush, (const DbLsn *lsn), (dbenv, lsn))
DBENV_METHOD(log_put, (DbLsn *lsn, const Dbt *data, u_int32_t flags),
(dbenv, lsn, data, flags))
int DbEnv::log_printf(DbTxn *txn, const char *fmt, ...)
{
DB_ENV *env = unwrap(this);
va_list ap;
int ret;
va_start(ap, fmt);
ret = __log_printf_pp(env, unwrap(txn), fmt, ap);
va_end(ap);
return (ret);
}
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))
DBENV_METHOD(lsn_reset, (const char *file, u_int32_t flags),
(dbenv, file, flags))
int DbEnv::memp_fcreate(DbMpoolFile **dbmfp, u_int32_t flags)
{
DB_ENV *env = unwrap(this);
@ -500,6 +576,12 @@ void DbEnv::runtime_error(DbEnv *env,
throw lng_except;
}
break;
case DB_REP_HANDLE_DEAD:
{
DbRepHandleDeadException dl_except(caller);
dl_except.set_env(env);
throw dl_except;
}
default:
{
DbException except(caller, error);
@ -612,10 +694,14 @@ 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(set_intermediate_dir, (int mode, u_int32_t flags),
(dbenv, mode, flags))
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_filemode, (int *modep), (dbenv, modep))
DBENV_METHOD(set_lg_filemode, (int mode), (dbenv, mode))
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))
@ -635,6 +721,10 @@ 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_max_openfd, (int *maxopenfdp), (dbenv, maxopenfdp))
DBENV_METHOD(set_mp_max_openfd, (int maxopenfd), (dbenv, maxopenfd))
DBENV_METHOD(get_mp_max_write, (int *maxwritep, int *maxwrite_sleepp), (dbenv, maxwritep, maxwrite_sleepp))
DBENV_METHOD(set_mp_max_write, (int maxwrite, int maxwrite_sleep), (dbenv, maxwrite, maxwrite_sleep))
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))
@ -644,6 +734,8 @@ 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(stat_print, (u_int32_t flags), (dbenv, flags))
DBENV_METHOD_QUIET(set_alloc,
(db_malloc_fcn_type malloc_fcn, db_realloc_fcn_type realloc_fcn,
db_free_fcn_type free_fcn),
@ -694,7 +786,8 @@ 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,
arg == 0 ? 0 : _feedback_intercept_c));
}
DBENV_METHOD(get_flags, (u_int32_t *flagsp), (dbenv, flagsp))
@ -708,7 +801,7 @@ void DbEnv::set_msgcall(void (*arg)(const DbEnv *, const char *))
message_stream_ = 0;
dbenv->set_msgcall(dbenv, (arg == 0) ? 0 :
_stream_message_function_c);
_stream_message_function_c);
}
__DB_STD(ostream) *DbEnv::get_message_stream()
@ -733,7 +826,8 @@ int DbEnv::set_paniccall(void (*arg)(DbEnv *, int))
paniccall_callback_ = arg;
return (dbenv->set_paniccall(dbenv, _paniccall_intercept_c));
return (dbenv->set_paniccall(dbenv,
arg == 0 ? 0 : _paniccall_intercept_c));
}
DBENV_METHOD(set_rpc_server,
@ -741,9 +835,6 @@ DBENV_METHOD(set_rpc_server,
(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
(int (*arg)(DbEnv *, Dbt *, DbLsn *, db_recops))
@ -753,18 +844,77 @@ int DbEnv::set_app_dispatch
app_dispatch_callback_ = arg;
if ((ret = dbenv->set_app_dispatch(dbenv,
_app_dispatch_intercept_c)) != 0)
arg == 0 ? 0 : _app_dispatch_intercept_c)) != 0)
DB_ERROR(this, "DbEnv::set_app_dispatch", ret, error_policy());
return (ret);
}
int DbEnv::set_isalive
(int (*arg)(DbEnv *, pid_t, db_threadid_t))
{
DB_ENV *dbenv = unwrap(this);
int ret;
isalive_callback_ = arg;
if ((ret = dbenv->set_isalive(dbenv,
arg == 0 ? 0 : _isalive_intercept_c)) != 0)
DB_ERROR(this, "DbEnv::set_isalive", 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))
DBENV_METHOD(mutex_alloc,
(u_int32_t flags, db_mutex_t *mutexp), (dbenv, flags, mutexp))
DBENV_METHOD(mutex_free, (db_mutex_t mutex), (dbenv, mutex))
DBENV_METHOD(mutex_get_align, (u_int32_t *argp), (dbenv, argp))
DBENV_METHOD(mutex_get_increment, (u_int32_t *argp), (dbenv, argp))
DBENV_METHOD(mutex_get_max, (u_int32_t *argp), (dbenv, argp))
DBENV_METHOD(mutex_get_tas_spins, (u_int32_t *argp), (dbenv, argp))
DBENV_METHOD(mutex_lock, (db_mutex_t mutex), (dbenv, mutex))
DBENV_METHOD(mutex_set_align, (u_int32_t arg), (dbenv, arg))
DBENV_METHOD(mutex_set_increment, (u_int32_t arg), (dbenv, arg))
DBENV_METHOD(mutex_set_max, (u_int32_t arg), (dbenv, arg))
DBENV_METHOD(mutex_set_tas_spins, (u_int32_t arg), (dbenv, arg))
DBENV_METHOD(mutex_stat,
(DB_MUTEX_STAT **statp, u_int32_t flags), (dbenv, statp, flags))
DBENV_METHOD(mutex_stat_print, (u_int32_t flags), (dbenv, flags))
DBENV_METHOD(mutex_unlock, (db_mutex_t mutex), (dbenv, mutex))
int DbEnv::set_thread_id(void (*arg)(DbEnv *, pid_t *, db_threadid_t *))
{
DB_ENV *dbenv = unwrap(this);
int ret;
thread_id_callback_ = arg;
if ((ret = dbenv->set_thread_id(dbenv,
arg == 0 ? 0 : _thread_id_intercept_c)) != 0)
DB_ERROR(this, "DbEnv::set_thread_id", ret, error_policy());
return (ret);
}
int DbEnv::set_thread_id_string(
char *(*arg)(DbEnv *, pid_t, db_threadid_t, char *))
{
DB_ENV *dbenv = unwrap(this);
int ret;
thread_id_string_callback_ = arg;
if ((ret = dbenv->set_thread_id_string(dbenv,
arg == 0 ? 0 : _thread_id_string_intercept_c)) != 0)
DB_ERROR(this, "DbEnv::set_thread_id_string", ret,
error_policy());
return (ret);
}
int DbEnv::txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags)
{
DB_ENV *env = unwrap(this);
@ -831,15 +981,14 @@ DBENV_METHOD(txn_stat, (DB_TXN_STAT **statp, u_int32_t flags),
DBENV_METHOD(txn_stat_print, (u_int32_t flags), (dbenv, flags))
int DbEnv::set_rep_transport(int myid,
int (*f_send)(DbEnv *, const Dbt *, const Dbt *, const DbLsn *, int,
u_int32_t))
int (*arg)(DbEnv *, const Dbt *, const Dbt *, const DbLsn *, int, u_int32_t))
{
DB_ENV *dbenv = unwrap(this);
int ret;
rep_send_callback_ = f_send;
if ((ret = dbenv->set_rep_transport(dbenv,
myid, _rep_send_intercept_c)) != 0)
rep_send_callback_ = arg;
if ((ret = dbenv->set_rep_transport(dbenv, myid,
arg == 0 ? 0 : _rep_send_intercept_c)) != 0)
DB_ERROR(this, "DbEnv::set_rep_transport", ret, error_policy());
return (ret);
@ -849,6 +998,10 @@ DBENV_METHOD(rep_elect,
(int nsites,
int nvotes, int priority, u_int32_t timeout, int *eidp, u_int32_t flags),
(dbenv, nsites, nvotes, priority, timeout, eidp, flags))
DBENV_METHOD(rep_flush, (), (dbenv))
DBENV_METHOD(rep_get_config, (u_int32_t which, int *onoffp),
(dbenv, which, onoffp))
DBENV_METHOD(set_rep_request, (u_int32_t min, u_int32_t max), (dbenv, min, max))
int DbEnv::rep_process_message(Dbt *control,
Dbt *rec, int *idp, DbLsn *ret_lsnp)
@ -864,6 +1017,8 @@ int DbEnv::rep_process_message(Dbt *control,
return (ret);
}
DBENV_METHOD(rep_set_config,
(u_int32_t which, int onoff), (dbenv, which, onoff))
DBENV_METHOD(rep_start,
(Dbt *cookie, u_int32_t flags),
(dbenv, (DBT *)cookie, flags))
@ -871,6 +1026,7 @@ 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(rep_sync, (u_int32_t flags), (dbenv, flags))
DBENV_METHOD(get_rep_limit, (u_int32_t *gbytesp, u_int32_t *bytesp),
(dbenv, gbytesp, bytesp))

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2004
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_except.cpp,v 11.28 2004/09/22 03:34:48 bostic Exp $
* $Id: cxx_except.cpp,v 12.2 2005/10/14 12:20:04 mjc Exp $
*/
#include "db_config.h"
@ -295,6 +295,35 @@ int DbLockNotGrantedException::get_index() const
return index_;
}
////////////////////////////////////////////////////////////////////////
// //
// DbRepHandleDeadException //
// //
////////////////////////////////////////////////////////////////////////
DbRepHandleDeadException::~DbRepHandleDeadException() throw()
{
}
DbRepHandleDeadException::DbRepHandleDeadException(const char *description)
: DbException(description, DB_REP_HANDLE_DEAD)
{
}
DbRepHandleDeadException::DbRepHandleDeadException
(const DbRepHandleDeadException &that)
: DbException(that)
{
}
DbRepHandleDeadException
&DbRepHandleDeadException::operator =(const DbRepHandleDeadException &that)
{
if (this != &that)
DbException::operator=(that);
return (*this);
}
////////////////////////////////////////////////////////////////////////
// //
// DbRunRecoveryException //

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2004
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_lock.cpp,v 11.19 2004/01/28 03:35:56 bostic Exp $
* $Id: cxx_lock.cpp,v 12.1 2005/06/16 20:20:59 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2004
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_logc.cpp,v 11.13 2004/02/05 02:25:12 mjc Exp $
* $Id: cxx_logc.cpp,v 12.1 2005/06/16 20:21:00 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2004
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_mpool.cpp,v 11.28 2004/01/28 03:35:56 bostic Exp $
* $Id: cxx_mpool.cpp,v 12.1 2005/06/16 20:21:02 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2004
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_multi.cpp,v 1.4 2004/01/28 03:35:56 bostic Exp $
* $Id: cxx_multi.cpp,v 12.3 2005/09/30 07:40:20 mjc Exp $
*/
#include "db_config.h"
@ -29,7 +29,7 @@ bool DbMultipleDataIterator::next(Dbt &data)
if (data.get_size() == 0 && data.get_data() == data_)
data.set_data(0);
}
return (data.get_data() != 0);
return (p_ != 0);
}
bool DbMultipleKeyDataIterator::next(Dbt &key, Dbt &data)
@ -46,7 +46,7 @@ bool DbMultipleKeyDataIterator::next(Dbt &key, Dbt &data)
data.set_data(data_ + *p_--);
data.set_size(*p_--);
}
return (data.get_data() != 0);
return (p_ != 0);
}
bool DbMultipleRecnoDataIterator::next(db_recno_t &recno, Dbt &data)
@ -61,5 +61,5 @@ bool DbMultipleRecnoDataIterator::next(db_recno_t &recno, Dbt &data)
data.set_data(data_ + *p_--);
data.set_size(*p_--);
}
return (recno != 0);
return (p_ != 0);
}

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2004
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_seq.cpp,v 11.3 2004/09/23 20:05:08 mjc Exp $
* $Id: cxx_seq.cpp,v 12.2 2005/10/13 20:49:47 bostic Exp $
*/
#include "db_config.h"
@ -90,20 +90,20 @@ 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)

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2004
* Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved.
*
* $Id: cxx_txn.cpp,v 11.33 2004/09/22 22:20:31 mjc Exp $
* $Id: cxx_txn.cpp,v 12.2 2005/06/16 20:21:03 bostic Exp $
*/
#include "db_config.h"
@ -67,7 +67,9 @@ u_int32_t DbTxn::id()
return (txn->id(txn)); // no error
}
DBTXN_METHOD(get_name, 0, (const char **namep), (txn, namep))
DBTXN_METHOD(prepare, 0, (u_int8_t *gid), (txn, gid))
DBTXN_METHOD(set_name, 0, (const char *name), (txn, name))
DBTXN_METHOD(set_timeout, 0, (db_timeout_t timeout, u_int32_t flags),
(txn, timeout, flags))

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: crdel.src,v 11.29 2004/06/17 17:35:15 bostic Exp $
* $Id: crdel.src,v 12.2 2005/09/28 17:44:18 margo Exp $
*/
PREFIX __crdel
@ -41,3 +41,40 @@ PGDBT page DBT s
POINTER lsn DB_LSN * lu
END
/*
* Inmem_create: Log the creation of an in-memory database.
*
* name: Name of the database
* fid: File id of the database
*/
BEGIN inmem_create 138
ARG fileid int32_t ld
DBT name DBT s
DBT fid DBT s
ARG pgsize u_int32_t lu
END
/*
* Inmem_rename: Log the renaming of an in-memory only database.
*
* oldname: database's starting name
* newname: database's ending name
* fid: fileid
*/
BEGIN inmem_rename 139
DBT oldname DBT s
DBT newname DBT s
DBT fid DBT s
END
/*
* Inmem_remove: Log the removal of an in-memory only database.
*
* name: database's ending name
* fid: fileid
*/
BEGIN inmem_remove 140
DBT name DBT s
DBT fid DBT s
END

View file

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

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: db.c,v 11.300 2004/10/26 17:38:41 bostic Exp $
* $Id: db.c,v 12.22 2005/11/12 17:41:44 bostic Exp $
*/
#include "db_config.h"
@ -52,6 +52,7 @@
#include "dbinc/db_shash.h"
#include "dbinc/db_swap.h"
#include "dbinc/btree.h"
#include "dbinc/fop.h"
#include "dbinc/hash.h"
#include "dbinc/lock.h"
#include "dbinc/log.h"
@ -241,8 +242,9 @@ __db_master_update(mdbp, sdbp, txn, subdb, type, action, newname, flags)
__memp_fget(mdbp->mpf, &sdbp->meta_pgno, 0, &p)) != 0)
goto err;
/* Free the root on the master db. */
if (TYPE(p) == P_BTREEMETA) {
/* Free the root on the master db if it was created. */
if (TYPE(p) == P_BTREEMETA &&
((BTMETA *)p)->root != PGNO_INVALID) {
if ((ret = __memp_fget(mdbp->mpf,
&((BTMETA *)p)->root, 0, &r)) != 0)
goto err;
@ -389,18 +391,17 @@ done: /*
* Set up the underlying environment during a db_open.
*
* PUBLIC: int __db_dbenv_setup __P((DB *,
* PUBLIC: DB_TXN *, const char *, u_int32_t, u_int32_t));
* PUBLIC: DB_TXN *, const char *, const char *, u_int32_t, u_int32_t));
*/
int
__db_dbenv_setup(dbp, txn, fname, id, flags)
__db_dbenv_setup(dbp, txn, fname, dname, id, flags)
DB *dbp;
DB_TXN *txn;
const char *fname;
const char *fname, *dname;
u_int32_t id, flags;
{
DB *ldbp;
DB_ENV *dbenv;
DB_MPOOL *dbmp;
u_int32_t maxid;
int ret;
@ -415,25 +416,20 @@ __db_dbenv_setup(dbp, txn, fname, id, flags)
dbenv, 0, dbp->pgsize * DB_MINPAGECACHE, 0)) != 0)
return (ret);
if ((ret = __dbenv_open(dbenv, NULL, DB_CREATE |
if ((ret = __env_open(dbenv, NULL, DB_CREATE |
DB_INIT_MPOOL | DB_PRIVATE | LF_ISSET(DB_THREAD), 0)) != 0)
return (ret);
}
/* Join the underlying cache. */
if ((ret = __db_dbenv_mpool(dbp, fname, flags)) != 0)
if ((!F_ISSET(dbp, DB_AM_INMEM) || dname == NULL) &&
(ret = __db_dbenv_mpool(dbp, fname, flags)) != 0)
return (ret);
/*
* We may need a per-thread mutex. Allocate it from the mpool
* region, there's supposed to be extra space there for that purpose.
*/
if (LF_ISSET(DB_THREAD)) {
dbmp = dbenv->mp_handle;
if ((ret = __db_mutex_setup(dbenv, dbmp->reginfo, &dbp->mutexp,
MUTEX_ALLOC | MUTEX_THREAD)) != 0)
return (ret);
}
/* We may need a per-thread mutex. */
if (LF_ISSET(DB_THREAD) && (ret = __mutex_alloc(
dbenv, MTX_DB_HANDLE, DB_MUTEX_THREAD, &dbp->mutex)) != 0)
return (ret);
/*
* Set up a bookkeeping entry for this database in the log region,
@ -441,13 +437,14 @@ __db_dbenv_setup(dbp, txn, fname, id, flags)
* or a replication client, where we won't log registries, we'll
* still need an FNAME struct, so LOGGING_ON is the correct macro.
*/
if (LOGGING_ON(dbenv) &&
(ret = __dbreg_setup(dbp, fname, id)) != 0)
if (LOGGING_ON(dbenv) && dbp->log_filename == NULL &&
(ret = __dbreg_setup(dbp,
F_ISSET(dbp, DB_AM_INMEM) ? dname : fname, id)) != 0)
return (ret);
/*
* If we're actively logging and our caller isn't a recovery function
* that already did so, assign this dbp a log fileid.
* that already did so, then assign this dbp a log fileid.
*/
if (DBENV_LOGGING(dbenv) && !F_ISSET(dbp, DB_AM_RECOVER) &&
#if !defined(DEBUG_ROP)
@ -465,13 +462,18 @@ __db_dbenv_setup(dbp, txn, fname, id, flags)
* routines, where we don't want to do a lot of ugly and
* expensive memcmps.
*/
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (maxid = 0, ldbp = LIST_FIRST(&dbenv->dblist);
ldbp != NULL; ldbp = LIST_NEXT(ldbp, dblistlinks)) {
if (fname != NULL &&
memcmp(ldbp->fileid, dbp->fileid, DB_FILE_ID_LEN) == 0 &&
ldbp->meta_pgno == dbp->meta_pgno)
break;
if (!F_ISSET(dbp, DB_AM_INMEM)) {
if (memcmp(ldbp->fileid, dbp->fileid, DB_FILE_ID_LEN)
== 0 && ldbp->meta_pgno == dbp->meta_pgno)
break;
} else if (dname != NULL) {
if (F_ISSET(ldbp, DB_AM_INMEM) &&
strcmp(ldbp->dname, dname) == 0)
break;
}
if (ldbp->adj_fileid > maxid)
maxid = ldbp->adj_fileid;
}
@ -493,7 +495,7 @@ __db_dbenv_setup(dbp, txn, fname, id, flags)
dbp->adj_fileid = ldbp->adj_fileid;
LIST_INSERT_AFTER(ldbp, dbp, dblistlinks);
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (0);
}
@ -514,12 +516,19 @@ __db_dbenv_mpool(dbp, fname, flags)
DBT pgcookie;
DB_MPOOLFILE *mpf;
DB_PGINFO pginfo;
int fidset, ftype, ret;
int32_t lsn_off;
u_int8_t nullfid[DB_FILE_ID_LEN];
u_int32_t clear_len;
int ftype, ret;
COMPQUIET(mpf, NULL);
dbenv = dbp->dbenv;
lsn_off = 0;
/* It's possible that this database is already open. */
if (F_ISSET(dbp, DB_AM_OPEN_CALLED))
return (0);
/*
* If we need to pre- or post-process a file's pages on I/O, set the
@ -534,17 +543,28 @@ __db_dbenv_mpool(dbp, fname, flags)
case DB_RECNO:
ftype = F_ISSET(dbp, DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM)
? DB_FTYPE_SET : DB_FTYPE_NOTSET;
clear_len = CRYPTO_ON(dbenv) ? dbp->pgsize : DB_PAGE_DB_LEN;
clear_len = CRYPTO_ON(dbenv) ?
(dbp->pgsize != 0 ? dbp->pgsize : DB_CLEARLEN_NOTSET) :
DB_PAGE_DB_LEN;
break;
case DB_HASH:
ftype = DB_FTYPE_SET;
clear_len = CRYPTO_ON(dbenv) ? dbp->pgsize : DB_PAGE_DB_LEN;
clear_len = CRYPTO_ON(dbenv) ?
(dbp->pgsize != 0 ? dbp->pgsize : DB_CLEARLEN_NOTSET) :
DB_PAGE_DB_LEN;
break;
case DB_QUEUE:
ftype = F_ISSET(dbp,
DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM) ?
DB_FTYPE_SET : DB_FTYPE_NOTSET;
clear_len = CRYPTO_ON(dbenv) ? dbp->pgsize : DB_PAGE_QUEUE_LEN;
/*
* If we came in here without a pagesize set, then we need
* to mark the in-memory handle as having clear_len not
* set, because we don't really know the clear length or
* the page size yet (since the file doesn't yet exist).
*/
clear_len = dbp->pgsize != 0 ? dbp->pgsize : DB_CLEARLEN_NOTSET;
break;
case DB_UNKNOWN:
/*
@ -564,6 +584,18 @@ __db_dbenv_mpool(dbp, fname, flags)
clear_len = DB_PAGE_DB_LEN;
break;
}
/*
* This might be an in-memory file and we won't know its
* file type until after we open it and read the meta-data
* page.
*/
if (F_ISSET(dbp, DB_AM_INMEM)) {
clear_len = DB_CLEARLEN_NOTSET;
ftype = DB_FTYPE_NOTSET;
lsn_off = DB_LSN_OFF_NOTSET;
break;
}
/* FALLTHROUGH */
default:
return (__db_unknown_type(dbenv, "DB->open", dbp->type));
@ -571,10 +603,14 @@ __db_dbenv_mpool(dbp, fname, flags)
mpf = dbp->mpf;
memset(nullfid, 0, DB_FILE_ID_LEN);
fidset = memcmp(nullfid, dbp->fileid, DB_FILE_ID_LEN);
if (fidset)
(void)__memp_set_fileid(mpf, dbp->fileid);
(void)__memp_set_clear_len(mpf, clear_len);
(void)__memp_set_fileid(mpf, dbp->fileid);
(void)__memp_set_ftype(mpf, ftype);
(void)__memp_set_lsn_offset(mpf, 0);
(void)__memp_set_lsn_offset(mpf, lsn_off);
pginfo.db_pagesize = dbp->pgsize;
pginfo.flags =
@ -585,12 +621,34 @@ __db_dbenv_mpool(dbp, fname, flags)
(void)__memp_set_pgcookie(mpf, &pgcookie);
if ((ret = __memp_fopen(mpf, NULL, fname,
LF_ISSET(DB_RDONLY | DB_NOMMAP |
DB_ODDFILESIZE | DB_TRUNCATE) |
LF_ISSET(DB_CREATE | DB_DURABLE_UNKNOWN |
DB_NOMMAP | DB_ODDFILESIZE | DB_RDONLY | DB_TRUNCATE) |
(F_ISSET(dbenv, DB_ENV_DIRECT_DB) ? DB_DIRECT : 0) |
(F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_TXN_NOT_DURABLE : 0),
0, dbp->pgsize)) != 0)
0, dbp->pgsize)) != 0) {
/*
* The open didn't work; we need to reset the mpf,
* retaining the in-memory semantics (if any).
*/
(void)__memp_fclose(dbp->mpf, 0);
(void)__memp_fcreate(dbenv, &dbp->mpf);
if (F_ISSET(dbp, DB_AM_INMEM))
MAKE_INMEM(dbp);
return (ret);
}
/*
* Set the open flag. We use it to mean that the dbp has gone
* through mpf setup, including dbreg_register. Also, below,
* the underlying access method open functions may want to do
* things like acquire cursors, so the open flag has to be set
* before calling them.
*/
F_SET(dbp, DB_AM_OPEN_CALLED);
if (!fidset && fname != NULL) {
(void)__memp_get_fileid(dbp->mpf, dbp->fileid);
dbp->preserve_fid = 1;
}
return (0);
}
@ -624,7 +682,7 @@ __db_close(dbp, txn, flags)
(void)__db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0);
/* Refresh the structure and close any underlying resources. */
ret = __db_refresh(dbp, txn, flags, &deferred_close);
ret = __db_refresh(dbp, txn, flags, &deferred_close, 0);
/*
* If we've deferred the close because the logging of the close failed,
@ -644,11 +702,11 @@ __db_close(dbp, txn, flags)
* dbenv, someone's already badly screwed up, so there's no reason
* to bother engineering around this possibility.
*/
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
db_ref = --dbenv->db_ref;
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (F_ISSET(dbenv, DB_ENV_DBLOCAL) && db_ref == 0 &&
(t_ret = __dbenv_close(dbenv, 0)) != 0 && ret == 0)
(t_ret = __env_close(dbenv, 0)) != 0 && ret == 0)
ret = t_ret;
/* Free the database handle. */
@ -666,25 +724,32 @@ __db_close(dbp, txn, flags)
* the actual handle) and during abort processing, we may have a
* fully opened handle.
*
* PUBLIC: int __db_refresh __P((DB *, DB_TXN *, u_int32_t, int *));
* PUBLIC: int __db_refresh __P((DB *, DB_TXN *, u_int32_t, int *, int));
*/
int
__db_refresh(dbp, txn, flags, deferred_closep)
__db_refresh(dbp, txn, flags, deferred_closep, reuse)
DB *dbp;
DB_TXN *txn;
u_int32_t flags;
int *deferred_closep;
int *deferred_closep, reuse;
{
DB *sdbp;
DBC *dbc;
DB_ENV *dbenv;
DB_LOCKREQ lreq;
DB_MPOOL *dbmp;
REGENV *renv;
REGINFO *infop;
u_int32_t save_flags;
int resync, ret, t_ret;
ret = 0;
dbenv = dbp->dbenv;
infop = dbenv->reginfo;
if (infop != NULL)
renv = infop->primary;
else
renv = NULL;
/* If never opened, or not currently open, it's easy. */
if (!F_ISSET(dbp, DB_AM_OPEN_CALLED))
@ -768,6 +833,7 @@ __db_refresh(dbp, txn, flags, deferred_closep)
(t_ret = __memp_fsync(dbp->mpf)) != 0 && ret == 0)
ret = t_ret;
never_opened:
/*
* At this point, we haven't done anything to render the DB
* handle unusable, at least by a transaction abort. Take the
@ -779,12 +845,15 @@ __db_refresh(dbp, txn, flags, deferred_closep)
* In this case, we put off actually closing the dbp until we've
* performed the abort.
*/
if (LOGGING_ON(dbp->dbenv)) {
if (!reuse && LOGGING_ON(dbp->dbenv)) {
/*
* Discard the log file id, if any. We want to log the close
* if and only if this is not a recovery dbp.
* if and only if this is not a recovery dbp or a client dbp,
* or a dead dbp handle.
*/
if (F_ISSET(dbp, DB_AM_RECOVER))
DB_ASSERT(renv != NULL);
if (F_ISSET(dbp, DB_AM_RECOVER) || IS_REP_CLIENT(dbenv) ||
dbp->timestamp != renv->rep_timestamp)
t_ret = __dbreg_revoke_id(dbp, 0, DB_LOGFILEID_INVALID);
else {
if ((t_ret = __dbreg_close_id(dbp,
@ -808,6 +877,17 @@ __db_refresh(dbp, txn, flags, deferred_closep)
*deferred_closep = 1;
return (t_ret);
}
/*
* If dbreg_close_id failed and we were not in a
* transaction, then we need to finish this close
* because the caller can't do anything with the
* handle after we return an error. We rely on
* dbreg_close_id to mark the entry in some manner
* so that we do not do a clean shutdown of this
* environment. If shutdown isn't clean, then the
* application *must* run recovery and that will
* generate the RCLOSE record.
*/
}
if (ret == 0)
@ -824,7 +904,6 @@ __db_refresh(dbp, txn, flags, deferred_closep)
ret == 0)
ret = t_ret;
never_opened:
/*
* Remove this DB handle from the DB_ENV's dblist, if it's been added.
*
@ -832,8 +911,8 @@ never_opened:
* want to race with a thread searching for our underlying cache link
* while opening a DB handle.
*/
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
if (dbp->dblistlinks.le_prev != NULL) {
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
if (!reuse && dbp->dblistlinks.le_prev != NULL) {
LIST_REMOVE(dbp, dblistlinks);
dbp->dblistlinks.le_prev = NULL;
}
@ -845,9 +924,13 @@ never_opened:
ret == 0)
ret = t_ret;
dbp->mpf = NULL;
if (reuse &&
(t_ret = __memp_fcreate(dbenv, &dbp->mpf)) != 0 &&
ret == 0)
ret = t_ret;
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
/*
* Call the access specific close function.
@ -883,7 +966,7 @@ never_opened:
* access-method specific data.
*/
if (dbp->lid != DB_LOCK_INVALIDID) {
if (!reuse && dbp->lid != DB_LOCK_INVALIDID) {
/* We may have pending trade operations on this dbp. */
if (txn != NULL)
__txn_remlock(dbenv, txn, &dbp->handle_lock, dbp->lid);
@ -901,20 +984,57 @@ never_opened:
LOCK_INIT(dbp->handle_lock);
}
/* Discard the locker ID allocated as the fileid. */
if (F_ISSET(dbp, DB_AM_INMEM) && LOCKING_ON(dbenv) &&
/*
* If this is a temporary file (un-named in-memory file), then
* discard the locker ID allocated as the fileid.
*/
if (LOCKING_ON(dbenv) &&
F_ISSET(dbp, DB_AM_INMEM) && !dbp->preserve_fid &&
*(u_int32_t *)dbp->fileid != DB_LOCK_INVALIDID &&
(t_ret = __lock_id_free(dbenv, *(u_int32_t *)dbp->fileid)) != 0 &&
ret == 0)
ret = t_ret;
if (reuse) {
/*
* If we are reusing this dbp, then we're done now. Re-init
* the handle, preserving important flags, and then return.
* This code is borrowed from __db_init, which does more
* than we can do here.
*/
save_flags = F_ISSET(dbp, DB_AM_INMEM | DB_AM_TXN);
/*
* XXX If this is an XA handle, we'll want to specify
* DB_XA_CREATE.
*/
if ((ret = __bam_db_create(dbp)) != 0)
return (ret);
if ((ret = __ham_db_create(dbp)) != 0)
return (ret);
if ((ret = __qam_db_create(dbp)) != 0)
return (ret);
/* Restore flags */
dbp->flags = dbp->orig_flags | save_flags;
if (FLD_ISSET(save_flags, DB_AM_INMEM)) {
/*
* If this is inmem, then it may have a fileid
* even if it was never opened, and we need to
* clear out that fileid.
*/
memset(dbp->fileid, 0, sizeof(dbp->fileid));
MAKE_INMEM(dbp);
}
return (ret);
}
dbp->type = DB_UNKNOWN;
/* Discard the thread mutex. */
if (dbp->mutexp != NULL) {
dbmp = dbenv->mp_handle;
__db_mutex_free(dbenv, dbmp->reginfo, dbp->mutexp);
dbp->mutexp = NULL;
}
if ((t_ret = __mutex_free(dbenv, &dbp->mutex)) != 0 && ret == 0)
ret = t_ret;
/* Discard any memory allocated for the file and database names. */
if (dbp->fname != NULL) {
@ -1004,7 +1124,7 @@ __db_log_page(dbp, txn, lsn, pgno, page)
* PUBLIC: const char *, DB_TXN *, char **));
*/
#undef BACKUP_PREFIX
#define BACKUP_PREFIX "__db."
#define BACKUP_PREFIX "__db"
#undef MAX_LSN_TO_TEXT
#define MAX_LSN_TO_TEXT 17
@ -1026,16 +1146,18 @@ __db_backup_name(dbenv, name, txn, backup)
* we allocate enough space for it, even in the case where we don't
* use the entire filename for the backup name.
*/
len = strlen(name) + strlen(BACKUP_PREFIX) + MAX_LSN_TO_TEXT;
len = strlen(name) + strlen(BACKUP_PREFIX) + 1 + MAX_LSN_TO_TEXT;
if ((ret = __os_malloc(dbenv, len, &retp)) != 0)
return (ret);
/*
* Create the name. Backup file names are in one of two forms:
* Create the name. Backup file names are in one of three forms:
*
* In a transactional env: __db.LSN(8).LSN(8)
* and
* in a non-transactional env: __db.FILENAME
* In VXWORKS (where we want 8.3 support)
* and
* in any other non-transactional env: __db.FILENAME
*
* If the transaction doesn't have a current LSN, we write a dummy
* log record to force it, so we ensure all tmp names are unique.
@ -1051,14 +1173,37 @@ __db_backup_name(dbenv, name, txn, backup)
* 4. multi-component path + transaction
*/
p = __db_rpath(name);
if (txn == NULL)
if (txn == NULL) {
#ifdef HAVE_VXWORKS
{ int i, n;
/* On VxWorks we must support 8.3 names. */
if (p == NULL) /* Case 1. */
snprintf(retp, len, "%s%s", BACKUP_PREFIX, name);
else /* Case 3. */
snprintf(retp, len, "%.*s%s%s",
n = snprintf(retp,
len, "%s%.4s.tmp", BACKUP_PREFIX, name);
else /* Case 3. */
n = snprintf(retp, len, "%.*s%s%.4s.tmp",
(int)(p - name) + 1, name, BACKUP_PREFIX, p + 1);
else {
if (IS_ZERO_LSN(txn->last_lsn)) {
/*
* Overwrite "." in the characters copied from the name.
* If we backup 8 characters from the end, we're guaranteed
* to a) include the four bytes we copied from the name
* and b) not run off the beginning of the string.
*/
for (i = 0, p = (retp + n) - 8; i < 4; p++, i++)
if (*p == '.')
*p = '_';
}
#else
if (p == NULL) /* Case 1. */
snprintf(retp, len, "%s.%s", BACKUP_PREFIX, name);
else /* Case 3. */
snprintf(retp, len, "%.*s%s.%s",
(int)(p - name) + 1, name, BACKUP_PREFIX, p + 1);
#endif
} else {
lsn = ((TXN_DETAIL *)txn->td)->last_lsn;
if (IS_ZERO_LSN(lsn)) {
/*
* Write dummy log record. The two choices for dummy
* log records are __db_noop_log and __db_debug_log;
@ -1071,12 +1216,11 @@ __db_backup_name(dbenv, name, txn, backup)
__os_free(dbenv, retp);
return (ret);
}
} else
lsn = txn->last_lsn;
}
if (p == NULL) /* Case 2. */
snprintf(retp, len,
"%s%x.%x", BACKUP_PREFIX, lsn.file, lsn.offset);
"%s.%x.%x", BACKUP_PREFIX, lsn.file, lsn.offset);
else /* Case 4. */
snprintf(retp, len, "%.*s%x.%x",
(int)(p - name) + 1, name, lsn.file, lsn.offset);
@ -1235,7 +1379,8 @@ __db_testdocopy(dbenv, name)
/*
* Maximum size of file, including adding a ".afterop".
*/
len = strlen(real_name) + strlen(BACKUP_PREFIX) + MAX_LSN_TO_TEXT + 9;
len = strlen(real_name) +
strlen(BACKUP_PREFIX) + 1 + MAX_LSN_TO_TEXT + 9;
if ((ret = __os_malloc(dbenv, len, &copy)) != 0)
goto err;
@ -1264,7 +1409,7 @@ __db_testdocopy(dbenv, name)
* files named, say, 'a' and 'abc' we won't match 'abc' when
* looking for 'a'.
*/
snprintf(backup, len, "%s%s.0x", BACKUP_PREFIX, name);
snprintf(backup, len, "%s.%s.0x", BACKUP_PREFIX, name);
/*
* We need the directory path to do the __os_dirlist.
@ -1343,10 +1488,10 @@ __db_makecopy(dbenv, src, dest)
return;
if (__os_open(dbenv,
src, DB_OSO_RDONLY, __db_omode("rw----"), &rfhp) != 0)
src, DB_OSO_RDONLY, __db_omode(OWNER_RW), &rfhp) != 0)
goto err;
if (__os_open(dbenv, dest,
DB_OSO_CREATE | DB_OSO_TRUNC, __db_omode("rw----"), &wfhp) != 0)
DB_OSO_CREATE | DB_OSO_TRUNC, __db_omode(OWNER_RW), &wfhp) != 0)
goto err;
for (;;)

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db.src,v 11.28 2004/06/17 17:35:15 bostic Exp $
* $Id: db.src,v 12.2 2005/08/08 03:37:06 ubell Exp $
*/
PREFIX __db
@ -236,3 +236,24 @@ ARG pgno db_pgno_t lu
PGDBT header DBT s
PGDBT data DBT s
END
/*
* pg_sort: sort the free list
*
* meta: meta page number
* meta_lsn: lsn on meta page.
* last_free: page number of new last free page.
* last_lsn; lsn of last free page.
* last_pgno: current last page number.
* list: list of pages and lsns to sort.
*/
BEGIN pg_sort 61
DB fileid int32_t ld
ARG meta db_pgno_t lu
POINTER meta_lsn DB_LSN * lu
ARG last_free db_pgno_t lu
POINTER last_lsn DB_LSN * lu
ARG last_pgno db_pgno_t lu
DBT list DBT s
END

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1998-2004
* Copyright (c) 1998-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_am.c,v 11.120 2004/10/07 17:33:32 sue Exp $
* $Id: db_am.c,v 12.12 2005/11/01 00:44:09 bostic Exp $
*/
#include "db_config.h"
@ -48,7 +48,9 @@ __db_cursor_int(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
DBC *dbc;
DBC_INTERNAL *cp;
DB_ENV *dbenv;
db_threadid_t tid;
int allocated, ret;
pid_t pid;
dbenv = dbp->dbenv;
allocated = 0;
@ -61,7 +63,7 @@ __db_cursor_int(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
* right type. With off page dups we may have different kinds
* of cursors on the queue for a single database.
*/
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&dbp->free_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
if (dbtype == dbc->dbtype) {
@ -69,7 +71,7 @@ __db_cursor_int(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
F_CLR(dbc, ~DBC_OWN_LID);
break;
}
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
if (dbc == NULL) {
if ((ret = __os_calloc(dbenv, 1, sizeof(DBC), &dbc)) != 0)
@ -92,13 +94,14 @@ __db_cursor_int(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
* environment handles.
*/
if (!DB_IS_THREADED(dbp)) {
if (dbp->dbenv->env_lid == DB_LOCK_INVALIDID &&
(ret =
__lock_id(dbenv,&dbp->dbenv->env_lid)) != 0)
if (dbp->dbenv->env_lref == NULL &&
(ret = __lock_id(dbenv, NULL,
(DB_LOCKER **)&dbp->dbenv->env_lref)) != 0)
goto err;
dbc->lid = dbp->dbenv->env_lid;
dbc->lref = dbp->dbenv->env_lref;
} else {
if ((ret = __lock_id(dbenv, &dbc->lid)) != 0)
if ((ret = __lock_id(dbenv, NULL,
(DB_LOCKER **)&dbc->lref)) != 0)
goto err;
F_SET(dbc, DBC_OWN_LID);
}
@ -175,7 +178,9 @@ __db_cursor_int(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
dbc->dbtype = dbtype;
RESET_RET_MEM(dbc);
if ((dbc->txn = txn) == NULL) {
if ((dbc->txn = txn) != NULL)
dbc->locker = txn->txnid;
else if (LOCKING_ON(dbenv)) {
/*
* There are certain cases in which we want to create a
* new cursor with a particular locker ID that is known
@ -193,16 +198,25 @@ __db_cursor_int(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
* primary are subdatabases or we're using env-wide locking,
* this is disastrous.
*
* In these cases, our caller will pass a nonzero locker ID
* into this function. Use this locker ID instead of dbc->lid
* as the locker ID for our new cursor.
* In these cases, our caller will pass a nonzero locker
* ID into this function. Use this locker ID instead of
* the default as the locker ID for our new cursor.
*/
if (lockerid != DB_LOCK_INVALIDID)
dbc->locker = lockerid;
else
dbc->locker = dbc->lid;
} else
dbc->locker = txn->txnid;
else {
/*
* If we are threaded then we need to set the
* proper thread id into the locker.
*/
if (DB_IS_THREADED(dbp)) {
dbenv->thread_id(dbenv, &pid, &tid);
__lock_set_thread_id(
(DB_LOCKER *)dbc->lref, pid, tid);
}
dbc->locker = ((DB_LOCKER *)dbc->lref)->id;
}
}
/*
* These fields change when we are used as a secondary index, so
@ -253,10 +267,10 @@ __db_cursor_int(dbp, txn, dbtype, root, is_opd, lockerid, dbcp)
if (txn != NULL)
++txn->cursors;
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_INSERT_TAIL(&dbp->active_queue, dbc, links);
F_SET(dbc, DBC_ACTIVE);
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
*dbcp = dbc;
return (0);
@ -445,38 +459,60 @@ __db_del(dbp, txn, key, flags)
f_next |= DB_RMW;
}
/* Walk through the set of key/data pairs, deleting as we go. */
if ((ret = __db_c_get(dbc, key, &data, f_init)) != 0)
goto err;
/*
* Hash permits an optimization in DB->del: since on-page
* duplicates are stored in a single HKEYDATA structure, it's
* possible to delete an entire set of them at once, and as
* the HKEYDATA has to be rebuilt and re-put each time it
* changes, this is much faster than deleting the duplicates
* one by one. Thus, if we're not pointing at an off-page
* duplicate set, and we're not using secondary indices (in
* which case we'd have to examine the items one by one anyway),
* let hash do this "quick delete".
* Optimize the simple cases. For all AMs if we don't have secondaries
* and are not a secondary and there are no dups then we can avoid a
* bunch of overhead. For queue we don't need to fetch the record since
* we delete by direct calculation from the record number.
*
* Hash permits an optimization in DB->del: since on-page duplicates are
* stored in a single HKEYDATA structure, it's possible to delete an
* entire set of them at once, and as the HKEYDATA has to be rebuilt
* and re-put each time it changes, this is much faster than deleting
* the duplicates one by one. Thus, if not pointing at an off-page
* duplicate set, and we're not using secondary indices (in which case
* we'd have to examine the items one by one anyway), let hash do this
* "quick delete".
*
* !!!
* Note that this is the only application-executed delete call in
* Berkeley DB that does not go through the __db_c_del function.
* If anything other than the delete itself (like a secondary index
* update) has to happen there in a particular situation, the
* conditions here should be modified not to call __ham_quick_delete.
* The ordinary AM-independent alternative will work just fine with
* a hash; it'll just be slower.
* conditions here should be modified not to use these optimizations.
* The ordinary AM-independent alternative will work just fine;
* it'll just be slower.
*/
if (dbp->type == DB_HASH)
if (LIST_FIRST(&dbp->s_secondaries) == NULL &&
!F_ISSET(dbp, DB_AM_SECONDARY) &&
dbc->internal->opd == NULL) {
if (!F_ISSET(dbp, DB_AM_SECONDARY) &&
LIST_FIRST(&dbp->s_secondaries) == NULL) {
#ifdef HAVE_QUEUE
if (dbp->type == DB_QUEUE) {
ret = __qam_delete(dbc, key);
goto done;
}
#endif
/* Fetch the first record. */
if ((ret = __db_c_get(dbc, key, &data, f_init)) != 0)
goto err;
#ifdef HAVE_HASH
if (dbp->type == DB_HASH && dbc->internal->opd == NULL) {
ret = __ham_quick_delete(dbc);
goto done;
}
#endif
if ((dbp->type == DB_BTREE || dbp->type == DB_RECNO) &&
!F_ISSET(dbp, DB_AM_DUP)) {
ret = dbc->c_am_del(dbc);
goto done;
}
} else if ((ret = __db_c_get(dbc, key, &data, f_init)) != 0)
goto err;
/* Walk through the set of key/data pairs, deleting as we go. */
for (;;) {
if ((ret = __db_c_del(dbc, 0)) != 0)
break;
@ -554,21 +590,11 @@ __db_associate(dbp, txn, sdbp, callback, flags)
pdbc = sdbc = NULL;
ret = 0;
sdbp->s_callback = callback;
sdbp->s_primary = dbp;
sdbp->stored_get = sdbp->get;
sdbp->get = __db_secondary_get;
sdbp->stored_close = sdbp->close;
sdbp->close = __db_secondary_close_pp;
F_SET(sdbp, DB_AM_SECONDARY);
/*
* Check to see if the secondary is empty--and thus if we should
* build it--before we link it in and risk making it show up in
* other threads.
* Check to see if the secondary is empty -- and thus if we should
* build it -- before we link it in and risk making it show up in other
* threads. Do this first so that the databases remain unassociated on
* error.
*/
build = 0;
if (LF_ISSET(DB_CREATE)) {
@ -590,10 +616,6 @@ __db_associate(dbp, txn, sdbp, callback, flags)
ret = 0;
}
/*
* Secondary cursors have special refcounting close
* methods. Be careful.
*/
if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
ret = t_ret;
@ -604,18 +626,35 @@ __db_associate(dbp, txn, sdbp, callback, flags)
goto err;
}
/*
* Set up the database handle as a secondary.
*/
sdbp->s_callback = callback;
sdbp->s_primary = dbp;
sdbp->stored_get = sdbp->get;
sdbp->get = __db_secondary_get;
sdbp->stored_close = sdbp->close;
sdbp->close = __db_secondary_close_pp;
F_SET(sdbp, DB_AM_SECONDARY);
if (LF_ISSET(DB_IMMUTABLE_KEY))
FLD_SET(sdbp->s_assoc_flags, DB_ASSOC_IMMUTABLE_KEY);
/*
* Add the secondary to the list on the primary. Do it here
* so that we see any updates that occur while we're walking
* the primary.
*/
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
MUTEX_LOCK(dbenv, dbp->mutex);
/* See __db_s_next for an explanation of secondary refcounting. */
DB_ASSERT(sdbp->s_refcnt == 0);
sdbp->s_refcnt = 1;
LIST_INSERT_HEAD(&dbp->s_secondaries, sdbp, s_links);
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
if (build) {
/*
@ -650,11 +689,13 @@ __db_associate(dbp, txn, sdbp, callback, flags)
continue;
goto err;
}
SWAP_IF_NEEDED(dbp, sdbp, &key);
if ((ret = __db_c_put(sdbc,
&skey, &key, DB_UPDATE_SECONDARY)) != 0) {
FREE_IF_NEEDED(sdbp, &skey);
goto err;
}
SWAP_IF_NEEDED(dbp, sdbp, &key);
FREE_IF_NEEDED(sdbp, &skey);
}
@ -709,7 +750,7 @@ __db_secondary_close(sdbp, flags)
doclose = 0;
primary = sdbp->s_primary;
MUTEX_THREAD_LOCK(primary->dbenv, primary->mutexp);
MUTEX_LOCK(primary->dbenv, primary->mutex);
/*
* Check the refcount--if it was at 1 when we were called, no
* thread is currently updating this secondary through the primary,
@ -725,7 +766,7 @@ __db_secondary_close(sdbp, flags)
/* We don't want to call close while the mutex is held. */
doclose = 1;
}
MUTEX_THREAD_UNLOCK(primary->dbenv, primary->mutexp);
MUTEX_UNLOCK(primary->dbenv, primary->mutex);
/*
* sdbp->close is this function; call the real one explicitly if
@ -793,14 +834,14 @@ __db_append_primary(dbc, key, data)
* just that section into a common function, but the basic
* overview is the same here.
*/
for (sdbp = __db_s_first(dbp);
sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
if ((ret = __db_s_first(dbp, &sdbp)) != 0)
goto err;
for (; sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
memset(&skey, 0, sizeof(DBT));
if ((ret = sdbp->s_callback(sdbp, key, data, &skey)) != 0) {
if (ret == DB_DONOTINDEX)
continue;
else
goto err;
goto err;
}
if ((ret = __db_cursor_int(sdbp, dbc->txn, sdbp->type,
@ -851,7 +892,6 @@ err1: FREE_IF_NEEDED(sdbp, &skey);
if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
goto err;
}

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2004
* Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_cam.c,v 11.156 2004/09/28 18:07:32 ubell Exp $
* $Id: db_cam.c,v 12.21 2005/10/07 20:21:22 ubell Exp $
*/
#include "db_config.h"
@ -52,6 +52,7 @@ static int __db_wrlock_err __P((DB_ENV *));
if (F_ISSET(dbc, DBC_WRITECURSOR)) \
(void)__lock_downgrade( \
(dbp)->dbenv, &(dbc)->mylock, DB_LOCK_IWRITE, 0);
/*
* __db_c_close --
* DBC->c_close.
@ -85,16 +86,18 @@ __db_c_close(dbc)
* access specific cursor close routine, btree depends on having that
* order of operations.
*/
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
MUTEX_LOCK(dbenv, dbp->mutex);
if (opd != NULL) {
DB_ASSERT(F_ISSET(opd, DBC_ACTIVE));
F_CLR(opd, DBC_ACTIVE);
TAILQ_REMOVE(&dbp->active_queue, opd, links);
}
DB_ASSERT(F_ISSET(dbc, DBC_ACTIVE));
F_CLR(dbc, DBC_ACTIVE);
TAILQ_REMOVE(&dbp->active_queue, dbc, links);
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
/* Call the access specific cursor close routine. */
if ((t_ret =
@ -125,7 +128,7 @@ __db_c_close(dbc)
dbc->txn->cursors--;
/* Move the cursor(s) to the free queue. */
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
MUTEX_LOCK(dbenv, dbp->mutex);
if (opd != NULL) {
if (dbc->txn != NULL)
dbc->txn->cursors--;
@ -133,7 +136,7 @@ __db_c_close(dbc)
opd = NULL;
}
TAILQ_INSERT_TAIL(&dbp->free_queue, dbc, links);
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
return (ret);
}
@ -156,9 +159,9 @@ __db_c_destroy(dbc)
dbenv = dbp->dbenv;
/* Remove the cursor from the free queue. */
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_REMOVE(&dbp->free_queue, dbc, links);
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
/* Free up allocated memory. */
if (dbc->my_rskey.data != NULL)
@ -176,7 +179,8 @@ __db_c_destroy(dbc)
*/
if (LOCKING_ON(dbenv) &&
F_ISSET(dbc, DBC_OWN_LID) &&
(t_ret = __lock_id_free(dbenv, dbc->lid)) != 0 && ret == 0)
(t_ret = __lock_id_free(dbenv,
((DB_LOCKER *)dbc->lref)->id)) != 0 && ret == 0)
ret = t_ret;
__os_free(dbenv, dbc);
@ -298,7 +302,7 @@ __db_c_del(dbc, flags)
* to explicitly downgrade this lock. The closed cursor
* may only have had a read lock.
*/
if (F_ISSET(dbc->dbp, DB_AM_DIRTY) &&
if (F_ISSET(dbc->dbp, DB_AM_READ_UNCOMMITTED) &&
dbc->internal->lock_mode == DB_LOCK_WRITE) {
if ((t_ret =
__TLPUT(dbc, dbc->internal->lock)) != 0 && ret == 0)
@ -413,8 +417,8 @@ __db_c_idup(dbc_orig, dbcp, flags)
}
/* Copy the locking flags to the new cursor. */
F_SET(dbc_n,
F_ISSET(dbc_orig, DBC_WRITECURSOR | DBC_DIRTY_READ | DBC_DEGREE_2));
F_SET(dbc_n, F_ISSET(dbc_orig,
DBC_READ_COMMITTED | DBC_READ_UNCOMMITTED | DBC_WRITECURSOR));
/*
* If we're in CDB and this isn't an offpage dup cursor, then
@ -504,9 +508,13 @@ __db_c_get(dbc_arg, key, data, flags)
DBC_INTERNAL *cp, *cp_n;
DB_MPOOLFILE *mpf;
db_pgno_t pgno;
u_int32_t multi, tmp_dirty, tmp_flags, tmp_rmw;
u_int32_t multi, orig_ulen, tmp_flags, tmp_read_uncommitted, tmp_rmw;
u_int8_t type;
int ret, t_ret;
int key_small, ret, t_ret;
COMPQUIET(orig_ulen, 0);
key_small = 0;
/*
* Cursor Cleanup Note:
@ -526,8 +534,10 @@ __db_c_get(dbc_arg, key, data, flags)
tmp_rmw = LF_ISSET(DB_RMW);
LF_CLR(DB_RMW);
tmp_dirty = LF_ISSET(DB_DIRTY_READ);
LF_CLR(DB_DIRTY_READ);
tmp_read_uncommitted =
LF_ISSET(DB_READ_UNCOMMITTED) &&
!F_ISSET(dbc_arg, DBC_READ_UNCOMMITTED);
LF_CLR(DB_READ_UNCOMMITTED);
multi = LF_ISSET(DB_MULTIPLE|DB_MULTIPLE_KEY);
LF_CLR(DB_MULTIPLE|DB_MULTIPLE_KEY);
@ -539,13 +549,13 @@ __db_c_get(dbc_arg, key, data, flags)
if (flags == DB_GET_RECNO) {
if (tmp_rmw)
F_SET(dbc_arg, DBC_RMW);
if (tmp_dirty)
F_SET(dbc_arg, DBC_DIRTY_READ);
if (tmp_read_uncommitted)
F_SET(dbc_arg, DBC_READ_UNCOMMITTED);
ret = __bam_c_rget(dbc_arg, data);
if (tmp_rmw)
F_CLR(dbc_arg, DBC_RMW);
if (tmp_dirty)
F_CLR(dbc_arg, DBC_DIRTY_READ);
if (tmp_read_uncommitted)
F_CLR(dbc_arg, DBC_READ_UNCOMMITTED);
return (ret);
}
@ -613,8 +623,8 @@ __db_c_get(dbc_arg, key, data, flags)
break;
}
if (tmp_dirty)
F_SET(dbc_arg, DBC_DIRTY_READ);
if (tmp_read_uncommitted)
F_SET(dbc_arg, DBC_READ_UNCOMMITTED);
/*
* If this cursor is going to be closed immediately, we don't
@ -624,8 +634,8 @@ __db_c_get(dbc_arg, key, data, flags)
dbc_n = dbc_arg;
else {
ret = __db_c_idup(dbc_arg, &dbc_n, tmp_flags);
if (tmp_dirty)
F_CLR(dbc_arg, DBC_DIRTY_READ);
if (tmp_read_uncommitted)
F_CLR(dbc_arg, DBC_READ_UNCOMMITTED);
if (ret != 0)
goto err;
@ -654,8 +664,8 @@ __db_c_get(dbc_arg, key, data, flags)
ret = dbc_n->c_am_get(dbc_n, key, data, flags, &pgno);
if (tmp_rmw)
F_CLR(dbc_n, DBC_RMW);
if (tmp_dirty)
F_CLR(dbc_arg, DBC_DIRTY_READ);
if (tmp_read_uncommitted)
F_CLR(dbc_arg, DBC_READ_UNCOMMITTED);
F_CLR(dbc_n, DBC_MULTIPLE|DBC_MULTIPLE_KEY);
if (ret != 0)
goto err;
@ -721,8 +731,22 @@ done: /*
goto err;
if ((ret = __db_ret(dbp, cp_n->page, cp_n->indx,
key, &dbc_arg->rkey->data, &dbc_arg->rkey->ulen)) != 0)
goto err;
key, &dbc_arg->rkey->data, &dbc_arg->rkey->ulen)) != 0) {
/*
* If the key DBT is too small, we still want to return
* the size of the data. Otherwise applications are
* forced to check each one with a separate call. We
* don't want to copy the data, so we set the ulen to
* zero before calling __db_ret.
*/
if (ret == DB_BUFFER_SMALL &&
F_ISSET(data, DB_DBT_USERMEM)) {
key_small = 1;
orig_ulen = data->ulen;
data->ulen = 0;
} else
goto err;
}
}
if (multi != 0) {
/*
@ -793,11 +817,11 @@ err: /* Don't pass DB_DBT_ISSET back to application level, error or no. */
* about the referencing page or cursor we need
* to peek at the OPD cursor and get the lock here.
*/
if (F_ISSET(dbc_arg->dbp, DB_AM_DIRTY) &&
if (F_ISSET(dbc_arg->dbp, DB_AM_READ_UNCOMMITTED) &&
F_ISSET((BTREE_CURSOR *)
dbc_arg->internal->opd->internal, C_DELETED))
if ((t_ret =
dbc_arg->c_am_writelock(dbc_arg)) != 0 && ret != 0)
dbc_arg->c_am_writelock(dbc_arg)) != 0 && ret == 0)
ret = t_ret;
if ((t_ret = __db_c_cleanup(
dbc_arg->internal->opd, opd, ret)) != 0 && ret == 0)
@ -808,6 +832,12 @@ err: /* Don't pass DB_DBT_ISSET back to application level, error or no. */
if ((t_ret = __db_c_cleanup(dbc_arg, dbc_n, ret)) != 0 && ret == 0)
ret = t_ret;
if (key_small) {
data->ulen = orig_ulen;
if (ret == 0)
ret = DB_BUFFER_SMALL;
}
if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT)
CDB_LOCKING_DONE(dbp, dbc_arg);
return (ret);
@ -1011,8 +1041,10 @@ __db_c_put(dbc_arg, key, data, flags)
}
/*
* Now build the new datum from olddata and the partial
* data we were given.
* Now build the new datum from olddata and the partial data we
* were given. It's okay to do this if no record was returned
* above: a partial put on an empty record is allowed, if a
* little strange. The data is zero-padded.
*/
if ((ret =
__db_buildpartial(dbp, &olddata, data, &newdata)) != 0)
@ -1071,8 +1103,18 @@ __db_c_put(dbc_arg, key, data, flags)
* Note that __db_s_first and __db_s_next will take care of
* thread-locking and refcounting issues.
*/
for (sdbp = __db_s_first(dbp);
sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
if ((ret = __db_s_first(dbp, &sdbp)) != 0)
goto err;
for (; sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
/*
* Don't process this secondary if the key is immutable and we
* know that the old record exists. This optimization can't be
* used if we have not checked for the old record yet.
*/
if (have_oldrec && !nodel &&
FLD_ISSET(sdbp->s_assoc_flags, DB_ASSOC_IMMUTABLE_KEY))
continue;
/*
* Call the callback for this secondary, to get the
* appropriate secondary key.
@ -1088,8 +1130,7 @@ __db_c_put(dbc_arg, key, data, flags)
* any necessary deletes in step 5.
*/
continue;
else
goto err;
goto err;
}
/*
@ -1118,6 +1159,14 @@ __db_c_put(dbc_arg, key, data, flags)
F_SET(sdbc, DBC_WRITER);
}
/*
* Swap the primary key to the byte order of this secondary, if
* necessary. By doing this now, we can compare directly
* against the data already in the secondary without having to
* swap it after reading.
*/
SWAP_IF_NEEDED(dbp, sdbp, &pkey);
/*
* There are three cases here--
* 1) The secondary supports sorted duplicates.
@ -1161,9 +1210,9 @@ __db_c_put(dbc_arg, key, data, flags)
"Put results in a non-unique secondary key in an ",
"index not configured to support duplicates");
ret = EINVAL;
goto skipput;
}
} else if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY)
}
if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY)
goto skipput;
} else if (!F_ISSET(sdbp, DB_AM_DUPSORT)) {
/* Case 2. */
@ -1191,6 +1240,9 @@ __db_c_put(dbc_arg, key, data, flags)
skipput: FREE_IF_NEEDED(sdbp, &skey)
/* Make sure the primary key is back in native byte-order. */
SWAP_IF_NEEDED(dbp, sdbp, &pkey);
if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
ret = t_ret;
@ -1227,8 +1279,17 @@ skipput: FREE_IF_NEEDED(sdbp, &skey)
if (nodel)
goto skip_s_update;
for (sdbp = __db_s_first(dbp);
sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
if ((ret = __db_s_first(dbp, &sdbp)) != 0)
goto err;
for (; sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
/*
* Don't process this secondary if the key is immutable. We
* know that the old record exists, so this optimization can
* always be used.
*/
if (FLD_ISSET(sdbp->s_assoc_flags, DB_ASSOC_IMMUTABLE_KEY))
continue;
/*
* Call the callback for this secondary to get the
* old secondary key.
@ -1243,8 +1304,7 @@ skipput: FREE_IF_NEEDED(sdbp, &skey)
* secondary.
*/
continue;
else
goto err;
goto err;
}
memset(&skey, 0, sizeof(DBT));
if ((ret = sdbp->s_callback(sdbp,
@ -1280,6 +1340,7 @@ skipput: FREE_IF_NEEDED(sdbp, &skey)
memset(&tempskey, 0, sizeof(DBT));
tempskey.data = oldskey.data;
tempskey.size = oldskey.size;
SWAP_IF_NEEDED(dbp, sdbp, &pkey);
memset(&temppkey, 0, sizeof(DBT));
temppkey.data = pkey.data;
temppkey.size = pkey.size;
@ -1288,6 +1349,7 @@ skipput: FREE_IF_NEEDED(sdbp, &skey)
ret = __db_c_del(sdbc, DB_UPDATE_SECONDARY);
else if (ret == DB_NOTFOUND)
ret = __db_secondary_corrupt(dbp);
SWAP_IF_NEEDED(dbp, sdbp, &pkey);
}
FREE_IF_NEEDED(sdbp, &skey);
@ -1328,9 +1390,8 @@ skip_s_update:
goto err;
}
if ((ret = dbc_arg->c_am_writelock(dbc_arg)) != 0)
return (ret);
if ((ret = __db_c_dup(dbc_arg, &dbc_n, DB_POSITION)) != 0)
if ((ret = dbc_arg->c_am_writelock(dbc_arg)) != 0 ||
(ret = __db_c_dup(dbc_arg, &dbc_n, DB_POSITION)) != 0)
goto err;
opd = dbc_n->internal->opd;
if ((ret = opd->c_am_put(
@ -1530,7 +1591,7 @@ __db_c_cleanup(dbc, dbc_n, failed)
* to explicitly downgrade this lock. The closed cursor
* may only have had a read lock.
*/
if (F_ISSET(dbp, DB_AM_DIRTY) &&
if (F_ISSET(dbp, DB_AM_READ_UNCOMMITTED) &&
dbc->internal->lock_mode == DB_LOCK_WRITE) {
if ((t_ret =
__TLPUT(dbc, dbc->internal->lock)) != 0 && ret == 0)
@ -1573,13 +1634,14 @@ __db_c_pget(dbc, skey, pkey, data, flags)
u_int32_t flags;
{
DB *pdbp, *sdbp;
DBC *pdbc;
DBT *save_rdata, nullpkey;
u_int32_t save_pkey_flags;
DBC *dbc_n, *pdbc;
DBT nullpkey;
u_int32_t save_pkey_flags, tmp_flags, tmp_read_uncommitted, tmp_rmw;
int pkeymalloc, ret, t_ret;
sdbp = dbc->dbp;
pdbp = sdbp->s_primary;
dbc_n = NULL;
pkeymalloc = t_ret = 0;
/*
@ -1599,13 +1661,32 @@ __db_c_pget(dbc, skey, pkey, data, flags)
pkey = &nullpkey;
}
/* Clear OR'd in additional bits so we can check for flag equality. */
tmp_rmw = LF_ISSET(DB_RMW);
LF_CLR(DB_RMW);
tmp_read_uncommitted =
LF_ISSET(DB_READ_UNCOMMITTED) &&
!F_ISSET(dbc, DBC_READ_UNCOMMITTED);
LF_CLR(DB_READ_UNCOMMITTED);
/*
* DB_GET_RECNO is a special case, because we're interested not in
* the primary key/data pair, but rather in the primary's record
* number.
*/
if ((flags & DB_OPFLAGS_MASK) == DB_GET_RECNO)
return (__db_c_pget_recno(dbc, pkey, data, flags));
if (flags == DB_GET_RECNO) {
if (tmp_rmw)
F_SET(dbc, DBC_RMW);
if (tmp_read_uncommitted)
F_SET(dbc, DBC_READ_UNCOMMITTED);
ret = __db_c_pget_recno(dbc, pkey, data, flags);
if (tmp_rmw)
F_CLR(dbc, DBC_RMW);
if (tmp_read_uncommitted)
F_CLR(dbc, DBC_READ_UNCOMMITTED);
return (ret);
}
/*
* If the DBTs we've been passed don't have any of the
@ -1623,28 +1704,23 @@ __db_c_pget(dbc, skey, pkey, data, flags)
* the rkey/rdata from the *secondary* cursor.
*
* We accomplish all this by passing in the DBTs we started out
* with to the c_get, but having swapped the contents of rskey and
* rkey, respectively, into rkey and rdata; __db_ret will treat
* them like the normal key/data pair in a c_get call, and will
* realloc them as need be (this is "step 1"). Then, for "step 2",
* we swap back rskey/rkey/rdata to normal, and do a get on the primary
* with the secondary dbc appointed as the owner of the returned-data
* memory.
* with to the c_get, but swapping the contents of rskey and rkey,
* respectively, into rkey and rdata; __db_ret will treat them like
* the normal key/data pair in a c_get call, and will realloc them as
* need be (this is "step 1"). Then, for "step 2", we swap back
* rskey/rkey/rdata to normal, and do a get on the primary with the
* secondary dbc appointed as the owner of the returned-data memory.
*
* Note that in step 2, we copy the flags field in case we need to
* pass down a DB_DBT_PARTIAL or other flag that is compatible with
* letting DB do the memory management.
*/
/* Step 1. */
save_rdata = dbc->rdata;
dbc->rdata = dbc->rkey;
dbc->rkey = dbc->rskey;
/*
* It is correct, though slightly sick, to attempt a partial get
* of a primary key. However, if we do so here, we'll never find the
* primary record; clear the DB_DBT_PARTIAL field of pkey just
* for the duration of the next call.
* It is correct, though slightly sick, to attempt a partial get of a
* primary key. However, if we do so here, we'll never find the
* primary record; clear the DB_DBT_PARTIAL field of pkey just for the
* duration of the next call.
*/
save_pkey_flags = pkey->flags;
F_CLR(pkey, DB_DBT_PARTIAL);
@ -1653,67 +1729,114 @@ __db_c_pget(dbc, skey, pkey, data, flags)
* Now we can go ahead with the meat of this call. First, get the
* primary key from the secondary index. (What exactly we get depends
* on the flags, but the underlying cursor get will take care of the
* dirty work.)
* dirty work.) Duplicate the cursor, in case the later get on the
* primary fails.
*/
if ((ret = __db_c_get(dbc, skey, pkey, flags)) != 0) {
/* Restore rskey/rkey/rdata and return. */
pkey->flags = save_pkey_flags;
dbc->rskey = dbc->rkey;
dbc->rkey = dbc->rdata;
dbc->rdata = save_rdata;
goto err;
switch (flags) {
case DB_CURRENT:
case DB_GET_BOTHC:
case DB_NEXT:
case DB_NEXT_DUP:
case DB_NEXT_NODUP:
case DB_PREV:
case DB_PREV_NODUP:
tmp_flags = DB_POSITION;
break;
default:
tmp_flags = 0;
break;
}
if (tmp_read_uncommitted)
F_SET(dbc, DBC_READ_UNCOMMITTED);
if ((ret = __db_c_dup(dbc, &dbc_n, tmp_flags)) != 0) {
if (tmp_read_uncommitted)
F_CLR(dbc, DBC_READ_UNCOMMITTED);
return (ret);
}
F_SET(dbc_n, DBC_TRANSIENT);
if (tmp_rmw)
F_SET(dbc_n, DBC_RMW);
/*
* If we've been handed a primary key, it will be in native byte order,
* so we need to swap it before reading from the secondary.
*/
if (flags == DB_GET_BOTH || flags == DB_GET_BOTHC ||
flags == DB_GET_BOTH_RANGE)
SWAP_IF_NEEDED(pdbp, sdbp, pkey);
/* Step 1. */
dbc_n->rdata = dbc->rkey;
dbc_n->rkey = dbc->rskey;
ret = __db_c_get(dbc_n, skey, pkey, flags);
/* Restore pkey's flags in case we stomped the PARTIAL flag. */
pkey->flags = save_pkey_flags;
/*
* Restore the cursor's rskey, rkey, and rdata DBTs. If DB
* is handling the memory management, we now have newly
* reallocated buffers and ulens in rkey and rdata which we want
* to put in rskey and rkey. save_rdata contains the old value
* of dbc->rdata.
*/
dbc->rskey = dbc->rkey;
dbc->rkey = dbc->rdata;
dbc->rdata = save_rdata;
if (tmp_read_uncommitted)
F_CLR(dbc_n, DBC_READ_UNCOMMITTED);
if (tmp_rmw)
F_CLR(dbc_n, DBC_RMW);
/*
* Now we're ready for "step 2". If either or both of pkey and
* data do not have memory management flags set--that is, if DB is
* managing their memory--we need to swap around the rkey/rdata
* structures so that we don't wind up trying to use memory managed
* by the primary database cursor, which we'll close before we return.
* We need to swap the primary key to native byte order if we read it
* successfully, or if we swapped it on entry above. We can't return
* with the application's data modified.
*/
if (ret == 0 || flags == DB_GET_BOTH || flags == DB_GET_BOTHC ||
flags == DB_GET_BOTH_RANGE)
SWAP_IF_NEEDED(pdbp, sdbp, pkey);
if (ret != 0)
goto err;
/*
* Now we're ready for "step 2". If either or both of pkey and data do
* not have memory management flags set--that is, if DB is managing
* their memory--we need to swap around the rkey/rdata structures so
* that we don't wind up trying to use memory managed by the primary
* database cursor, which we'll close before we return.
*
* !!!
* If you're carefully following the bouncing ball, you'll note
* that in the DB-managed case, the buffer hanging off of pkey is
* the same as dbc->rkey->data. This is just fine; we may well
* realloc and stomp on it when we return, if we're going a
* DB_GET_BOTH and need to return a different partial or key
* (depending on the comparison function), but this is safe.
* If you're carefully following the bouncing ball, you'll note that in
* the DB-managed case, the buffer hanging off of pkey is the same as
* dbc->rkey->data. This is just fine; we may well realloc and stomp
* on it when we return, if we're doing a DB_GET_BOTH and need to
* return a different partial or key (depending on the comparison
* function), but this is safe.
*
* !!!
* We need to use __db_cursor_int here rather than simply calling
* pdbp->cursor, because otherwise, if we're in CDB, we'll
* allocate a new locker ID and leave ourselves open to deadlocks.
* (Even though we're only acquiring read locks, we'll still block
* if there are any waiters.)
* pdbp->cursor, because otherwise, if we're in CDB, we'll allocate a
* new locker ID and leave ourselves open to deadlocks. (Even though
* we're only acquiring read locks, we'll still block if there are any
* waiters.)
*/
if ((ret = __db_cursor_int(pdbp,
dbc->txn, pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0)
goto err;
if (tmp_read_uncommitted)
F_SET(pdbc, DBC_READ_UNCOMMITTED);
if (tmp_rmw)
F_SET(pdbc, DBC_RMW);
if (F_ISSET(dbc, DBC_READ_COMMITTED))
F_SET(pdbc, DBC_READ_COMMITTED);
/*
* We're about to use pkey a second time. If DB_DBT_MALLOC
* is set on it, we'll leak the memory we allocated the first time.
* Thus, set DB_DBT_REALLOC instead so that we reuse that memory
* instead of leaking it.
* We're about to use pkey a second time. If DB_DBT_MALLOC is set on
* it, we'll leak the memory we allocated the first time. Thus, set
* DB_DBT_REALLOC instead so that we reuse that memory instead of
* leaking it.
*
* !!!
* This assumes that the user must always specify a compatible
* realloc function if a malloc function is specified. I think
* this is a reasonable requirement.
* This assumes that the user must always specify a compatible realloc
* function if a malloc function is specified. I think this is a
* reasonable requirement.
*/
if (F_ISSET(pkey, DB_DBT_MALLOC)) {
F_CLR(pkey, DB_DBT_MALLOC);
@ -1722,38 +1845,41 @@ __db_c_pget(dbc, skey, pkey, data, flags)
}
/*
* Do the actual get. Set DBC_TRANSIENT since we don't care
* about preserving the position on error, and it's faster.
* SET_RET_MEM so that the secondary DBC owns any returned-data
* memory.
* Do the actual get. Set DBC_TRANSIENT since we don't care about
* preserving the position on error, and it's faster. SET_RET_MEM so
* that the secondary DBC owns any returned-data memory.
*/
F_SET(pdbc, DBC_TRANSIENT);
SET_RET_MEM(pdbc, dbc);
ret = __db_c_get(pdbc, pkey, data, DB_SET);
/*
* If the item wasn't found in the primary, this is a bug;
* our secondary has somehow gotten corrupted, and contains
* elements that don't correspond to anything in the primary.
* Complain.
* If the item wasn't found in the primary, this is a bug; our
* secondary has somehow gotten corrupted, and contains elements that
* don't correspond to anything in the primary. Complain.
*/
if (ret == DB_NOTFOUND)
ret = __db_secondary_corrupt(pdbp);
/* Now close the primary cursor. */
t_ret = __db_c_close(pdbc);
if ((t_ret = __db_c_close(pdbc)) != 0 && ret == 0)
ret = t_ret;
err: if (pkeymalloc) {
err: /* Cleanup and cursor resolution. */
if ((t_ret = __db_c_cleanup(dbc, dbc_n, ret)) != 0 && ret == 0)
ret = t_ret;
if (pkeymalloc) {
/*
* If pkey had a MALLOC flag, we need to restore it;
* otherwise, if the user frees the buffer but reuses
* the DBT without NULL'ing its data field or changing
* the flags, we may drop core.
* If pkey had a MALLOC flag, we need to restore it; otherwise,
* if the user frees the buffer but reuses the DBT without
* NULL'ing its data field or changing the flags, we may drop
* core.
*/
F_CLR(pkey, DB_DBT_REALLOC);
F_SET(pkey, DB_DBT_MALLOC);
}
return (t_ret == 0 ? ret : t_ret);
return (ret);
}
/*
@ -1880,6 +2006,7 @@ __db_c_del_secondary(dbc)
memset(&skey, 0, sizeof(DBT));
memset(&pkey, 0, sizeof(DBT));
pdbp = dbc->dbp->s_primary;
/*
* Get the current item that we're pointing at.
@ -1890,6 +2017,8 @@ __db_c_del_secondary(dbc)
if ((ret = __db_c_get(dbc, &skey, &pkey, DB_CURRENT)) != 0)
return (ret);
SWAP_IF_NEEDED(pdbp, dbc->dbp, &pkey);
/*
* Create a cursor on the primary with our locker ID,
* so that when it calls back, we don't conflict.
@ -1900,7 +2029,6 @@ __db_c_del_secondary(dbc)
* interface. This shouldn't be any less efficient
* anyway.
*/
pdbp = dbc->dbp->s_primary;
if ((ret = __db_cursor_int(pdbp, dbc->txn,
pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0)
return (ret);
@ -1968,8 +2096,9 @@ __db_c_del_primary(dbc)
if ((ret = __db_c_get(dbc, &pkey, &data, DB_CURRENT)) != 0)
return (ret);
for (sdbp = __db_s_first(dbp);
sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
if ((ret = __db_s_first(dbp, &sdbp)) != 0)
goto err;
for (; sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
/*
* Get the secondary key for this secondary and the current
* item.
@ -1985,13 +2114,13 @@ __db_c_del_primary(dbc)
/* We had a substantive error. Bail. */
FREE_IF_NEEDED(sdbp, &skey);
goto done;
goto err;
}
/* Open a secondary cursor. */
if ((ret = __db_cursor_int(sdbp, dbc->txn, sdbp->type,
PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0)
goto done;
goto err;
/* See comment above and in __db_c_put. */
if (CDB_LOCKING(sdbp->dbenv)) {
DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
@ -2014,6 +2143,7 @@ __db_c_del_primary(dbc)
memset(&tempskey, 0, sizeof(DBT));
tempskey.data = skey.data;
tempskey.size = skey.size;
SWAP_IF_NEEDED(dbp, sdbp, &pkey);
memset(&temppkey, 0, sizeof(DBT));
temppkey.data = pkey.data;
temppkey.size = pkey.size;
@ -2022,16 +2152,17 @@ __db_c_del_primary(dbc)
ret = __db_c_del(sdbc, DB_UPDATE_SECONDARY);
else if (ret == DB_NOTFOUND)
ret = __db_secondary_corrupt(dbp);
SWAP_IF_NEEDED(dbp, sdbp, &pkey);
FREE_IF_NEEDED(sdbp, &skey);
if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
goto done;
goto err;
}
done: if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)
err: if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
@ -2040,23 +2171,25 @@ done: if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)
* __db_s_first --
* Get the first secondary, if any are present, from the primary.
*
* PUBLIC: DB *__db_s_first __P((DB *));
* PUBLIC: int __db_s_first __P((DB *, DB **));
*/
DB *
__db_s_first(pdbp)
DB *pdbp;
int
__db_s_first(pdbp, sdbpp)
DB *pdbp, **sdbpp;
{
DB *sdbp;
MUTEX_THREAD_LOCK(pdbp->dbenv, pdbp->mutexp);
MUTEX_LOCK(pdbp->dbenv, pdbp->mutex);
sdbp = LIST_FIRST(&pdbp->s_secondaries);
/* See __db_s_next. */
if (sdbp != NULL)
sdbp->s_refcnt++;
MUTEX_THREAD_UNLOCK(pdbp->dbenv, pdbp->mutexp);
MUTEX_UNLOCK(pdbp->dbenv, pdbp->mutex);
return (sdbp);
*sdbpp = sdbp;
return (0);
}
/*
@ -2099,7 +2232,7 @@ __db_s_next(sdbpp)
pdbp = sdbp->s_primary;
closeme = NULL;
MUTEX_THREAD_LOCK(pdbp->dbenv, pdbp->mutexp);
MUTEX_LOCK(pdbp->dbenv, pdbp->mutex);
DB_ASSERT(sdbp->s_refcnt != 0);
if (--sdbp->s_refcnt == 0) {
LIST_REMOVE(sdbp, s_links);
@ -2108,7 +2241,7 @@ __db_s_next(sdbpp)
sdbp = LIST_NEXT(sdbp, s_links);
if (sdbp != NULL)
sdbp->s_refcnt++;
MUTEX_THREAD_UNLOCK(pdbp->dbenv, pdbp->mutexp);
MUTEX_UNLOCK(pdbp->dbenv, pdbp->mutex);
*sdbpp = sdbp;
@ -2136,13 +2269,13 @@ __db_s_done(sdbp)
pdbp = sdbp->s_primary;
doclose = 0;
MUTEX_THREAD_LOCK(pdbp->dbenv, pdbp->mutexp);
MUTEX_LOCK(pdbp->dbenv, pdbp->mutex);
DB_ASSERT(sdbp->s_refcnt != 0);
if (--sdbp->s_refcnt == 0) {
LIST_REMOVE(sdbp, s_links);
doclose = 1;
}
MUTEX_THREAD_UNLOCK(pdbp->dbenv, pdbp->mutexp);
MUTEX_UNLOCK(pdbp->dbenv, pdbp->mutex);
return (doclose ? __db_close(sdbp, NULL, 0) : 0);
}

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -36,7 +36,7 @@
* 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 $
* $Id: db_conv.c,v 12.1 2005/06/16 20:21:09 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: db_dispatch.c,v 11.169 2004/10/27 16:44:26 ubell Exp $
* $Id: db_dispatch.c,v 12.12 2005/11/10 21:11:42 bostic Exp $
*/
#include "db_config.h"
@ -43,22 +43,26 @@
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#ifndef HAVE_FTRUNCATE
#include "dbinc/db_shash.h"
#endif
#include "dbinc/hash.h"
#include "dbinc/log.h"
#ifndef HAVE_FTRUNCATE
#include "dbinc/lock.h"
#include "dbinc/mp.h"
#endif
#include "dbinc/log.h"
#include "dbinc/fop.h"
#include "dbinc/txn.h"
#ifndef HAVE_FTRUNCATE
static int __db_limbo_fix __P((DB *,
DB_TXN *, DB_TXNLIST *, db_pgno_t *, DBMETA *, db_limbo_state));
static int __db_limbo_fix __P((DB *, DB_TXN *,
DB_TXNLIST *, db_pgno_t *, DBMETA *, db_limbo_state));
static int __db_limbo_bucket __P((DB_ENV *,
DB_TXN *, DB_TXNLIST *, db_limbo_state));
static int __db_limbo_move __P((DB_ENV *, DB_TXN *, DB_TXN *, DB_TXNLIST *));
@ -66,11 +70,11 @@ static int __db_limbo_prepare __P(( DB *, DB_TXN *, DB_TXNLIST *));
static int __db_lock_move __P((DB_ENV *,
u_int8_t *, db_pgno_t, db_lockmode_t, DB_TXN *, DB_TXN *));
static int __db_txnlist_pgnoadd __P((DB_ENV *, DB_TXNHEAD *,
int32_t, u_int8_t [DB_FILE_ID_LEN], char *, db_pgno_t));
int32_t, u_int8_t *, char *, db_pgno_t));
#endif
static int __db_txnlist_find_internal __P((DB_ENV *,
void *, db_txnlist_type, u_int32_t, u_int8_t[DB_FILE_ID_LEN],
DB_TXNLIST **, int, u_int32_t *));
static int __db_txnlist_find_internal __P((DB_ENV *, DB_TXNHEAD *,
db_txnlist_type, u_int32_t, u_int8_t *, DB_TXNLIST **,
int, u_int32_t *));
/*
* __db_dispatch --
@ -83,7 +87,7 @@ static int __db_txnlist_find_internal __P((DB_ENV *,
*
* PUBLIC: int __db_dispatch __P((DB_ENV *,
* PUBLIC: int (**)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)),
* PUBLIC: size_t, DBT *, DB_LSN *, db_recops, void *));
* PUBLIC: size_t, DBT *, DB_LSN *, db_recops, DB_TXNHEAD *));
*/
int
__db_dispatch(dbenv, dtab, dtabsize, db, lsnp, redo, info)
@ -93,7 +97,7 @@ __db_dispatch(dbenv, dtab, dtabsize, db, lsnp, redo, info)
DBT *db; /* The log record upon which to dispatch. */
DB_LSN *lsnp; /* The lsn of the record being dispatched. */
db_recops redo; /* Redo this op (or undo it). */
void *info;
DB_TXNHEAD *info; /* Transaction list. */
{
DB_LSN prev_lsn;
u_int32_t rectype, status, txnid;
@ -235,7 +239,9 @@ __db_dispatch(dbenv, dtab, dtabsize, db, lsnp, redo, info)
break;
default:
if (txnid != 0) {
if (txnid == 0)
status = 0;
else {
ret = __db_txnlist_find(dbenv,
info, txnid, &status);
@ -364,14 +370,14 @@ __db_add_recovery(dbenv, dtab, dtabsize, func, ndx)
* Initialize transaction linked list.
*
* PUBLIC: int __db_txnlist_init __P((DB_ENV *,
* PUBLIC: u_int32_t, u_int32_t, DB_LSN *, void *));
* PUBLIC: u_int32_t, u_int32_t, DB_LSN *, DB_TXNHEAD **));
*/
int
__db_txnlist_init(dbenv, low_txn, hi_txn, trunc_lsn, retp)
DB_ENV *dbenv;
u_int32_t low_txn, hi_txn;
DB_LSN *trunc_lsn;
void *retp;
DB_TXNHEAD **retp;
{
DB_TXNHEAD *headp;
u_int32_t size, tmp;
@ -427,7 +433,7 @@ __db_txnlist_init(dbenv, low_txn, hi_txn, trunc_lsn, retp)
}
ZERO_LSN(headp->ckplsn);
*(void **)retp = headp;
*retp = headp;
return (0);
}
@ -436,23 +442,21 @@ __db_txnlist_init(dbenv, low_txn, hi_txn, trunc_lsn, retp)
* Add an element to our transaction linked list.
*
* PUBLIC: int __db_txnlist_add __P((DB_ENV *,
* PUBLIC: void *, u_int32_t, u_int32_t, DB_LSN *));
* PUBLIC: DB_TXNHEAD *, u_int32_t, u_int32_t, DB_LSN *));
*/
int
__db_txnlist_add(dbenv, listp, txnid, status, lsn)
__db_txnlist_add(dbenv, hp, txnid, status, lsn)
DB_ENV *dbenv;
void *listp;
DB_TXNHEAD *hp;
u_int32_t txnid, status;
DB_LSN *lsn;
{
DB_TXNHEAD *hp;
DB_TXNLIST *elp;
int ret;
if ((ret = __os_malloc(dbenv, sizeof(DB_TXNLIST), &elp)) != 0)
return (ret);
hp = (DB_TXNHEAD *)listp;
LIST_INSERT_HEAD(&hp->head[DB_TXNLIST_MASK(hp, txnid)], elp, links);
elp->type = TXNLIST_TXNID;
@ -474,19 +478,19 @@ __db_txnlist_add(dbenv, listp, txnid, status, lsn)
* __db_txnlist_remove --
* Remove an element from our transaction linked list.
*
* PUBLIC: int __db_txnlist_remove __P((DB_ENV *, void *, u_int32_t));
* PUBLIC: int __db_txnlist_remove __P((DB_ENV *, DB_TXNHEAD *, u_int32_t));
*/
int
__db_txnlist_remove(dbenv, listp, txnid)
__db_txnlist_remove(dbenv, hp, txnid)
DB_ENV *dbenv;
void *listp;
DB_TXNHEAD *hp;
u_int32_t txnid;
{
DB_TXNLIST *entry;
u_int32_t status;
return (__db_txnlist_find_internal(dbenv,
listp, TXNLIST_TXNID, txnid, NULL, &entry, 1, &status));
hp, TXNLIST_TXNID, txnid, NULL, &entry, 1, &status));
}
/*
@ -497,20 +501,17 @@ __db_txnlist_remove(dbenv, listp, txnid)
* recovery, we are going to virtually truncate the log and we need
* to retain the last checkpoint before the truncation point.
*
* PUBLIC: void __db_txnlist_ckp __P((DB_ENV *, void *, DB_LSN *));
* PUBLIC: void __db_txnlist_ckp __P((DB_ENV *, DB_TXNHEAD *, DB_LSN *));
*/
void
__db_txnlist_ckp(dbenv, listp, ckp_lsn)
__db_txnlist_ckp(dbenv, hp, ckp_lsn)
DB_ENV *dbenv;
void *listp;
DB_TXNHEAD *hp;
DB_LSN *ckp_lsn;
{
DB_TXNHEAD *hp;
COMPQUIET(dbenv, NULL);
hp = (DB_TXNHEAD *)listp;
if (IS_ZERO_LSN(hp->ckplsn) && !IS_ZERO_LSN(hp->maxlsn) &&
log_compare(&hp->maxlsn, ckp_lsn) >= 0)
hp->ckplsn = *ckp_lsn;
@ -520,26 +521,24 @@ __db_txnlist_ckp(dbenv, listp, ckp_lsn)
* __db_txnlist_end --
* Discard transaction linked list.
*
* PUBLIC: void __db_txnlist_end __P((DB_ENV *, void *));
* PUBLIC: void __db_txnlist_end __P((DB_ENV *, DB_TXNHEAD *));
*/
void
__db_txnlist_end(dbenv, listp)
__db_txnlist_end(dbenv, hp)
DB_ENV *dbenv;
void *listp;
{
DB_TXNHEAD *hp;
DB_TXNLIST *p;
{
u_int32_t i;
DB_TXNLIST *p;
if ((hp = (DB_TXNHEAD *)listp) == NULL)
if (hp == NULL)
return;
for (i = 0; i < hp->nslots; i++)
while (hp != NULL && (p = LIST_FIRST(&hp->head[i])) != NULL) {
LIST_REMOVE(p, links);
switch (p->type) {
case TXNLIST_LSN:
__os_free(dbenv, p->u.l.lsn_array);
__os_free(dbenv, p->u.l.lsn_stack);
break;
case TXNLIST_DELETE:
case TXNLIST_PGNO:
@ -551,12 +550,13 @@ __db_txnlist_end(dbenv, listp)
*/
break;
}
LIST_REMOVE(p, links);
__os_free(dbenv, p);
}
if (hp->gen_array != NULL)
__os_free(dbenv, hp->gen_array);
__os_free(dbenv, listp);
__os_free(dbenv, hp);
}
/*
@ -568,12 +568,12 @@ __db_txnlist_end(dbenv, listp)
* was generated while not in a transaction.
*
* PUBLIC: int __db_txnlist_find __P((DB_ENV *,
* PUBLIC: void *, u_int32_t, u_int32_t *));
* PUBLIC: DB_TXNHEAD *, u_int32_t, u_int32_t *));
*/
int
__db_txnlist_find(dbenv, listp, txnid, statusp)
__db_txnlist_find(dbenv, hp, txnid, statusp)
DB_ENV *dbenv;
void *listp;
DB_TXNHEAD *hp;
u_int32_t txnid, *statusp;
{
DB_TXNLIST *entry;
@ -581,7 +581,7 @@ __db_txnlist_find(dbenv, listp, txnid, statusp)
if (txnid == 0)
return (DB_NOTFOUND);
return (__db_txnlist_find_internal(dbenv, listp,
return (__db_txnlist_find_internal(dbenv, hp,
TXNLIST_TXNID, txnid, NULL, &entry, 0, statusp));
}
@ -590,32 +590,30 @@ __db_txnlist_find(dbenv, listp, txnid, statusp)
* Change the status of an existing transaction entry.
* Returns DB_NOTFOUND if no such entry exists.
*
* PUBLIC: int __db_txnlist_update __P((DB_ENV *,
* PUBLIC: void *, u_int32_t, u_int32_t, DB_LSN *, u_int32_t *, int));
* PUBLIC: int __db_txnlist_update __P((DB_ENV *, DB_TXNHEAD *,
* PUBLIC: u_int32_t, u_int32_t, DB_LSN *, u_int32_t *, int));
*/
int
__db_txnlist_update(dbenv, listp, txnid, status, lsn, ret_status, add_ok)
__db_txnlist_update(dbenv, hp, txnid, status, lsn, ret_status, add_ok)
DB_ENV *dbenv;
void *listp;
DB_TXNHEAD *hp;
u_int32_t txnid, status;
DB_LSN *lsn;
u_int32_t *ret_status;
int add_ok;
{
DB_TXNHEAD *hp;
DB_TXNLIST *elp;
int ret;
if (txnid == 0)
return (DB_NOTFOUND);
hp = (DB_TXNHEAD *)listp;
ret = __db_txnlist_find_internal(dbenv,
listp, TXNLIST_TXNID, txnid, NULL, &elp, 0, ret_status);
hp, TXNLIST_TXNID, txnid, NULL, &elp, 0, ret_status);
if (ret == DB_NOTFOUND && add_ok) {
*ret_status = status;
return (__db_txnlist_add(dbenv, listp, txnid, status, lsn));
return (__db_txnlist_add(dbenv, hp, txnid, status, lsn));
}
if (ret != 0)
return (ret);
@ -640,9 +638,9 @@ __db_txnlist_update(dbenv, listp, txnid, status, lsn, ret_status, add_ok)
*/
static int
__db_txnlist_find_internal(dbenv,
listp, type, txnid, uid, txnlistp, delete, statusp)
hp, type, txnid, uid, txnlistp, delete, statusp)
DB_ENV *dbenv;
void *listp;
DB_TXNHEAD *hp;
db_txnlist_type type;
u_int32_t txnid;
u_int8_t uid[DB_FILE_ID_LEN];
@ -651,14 +649,13 @@ __db_txnlist_find_internal(dbenv,
u_int32_t *statusp;
{
struct __db_headlink *head;
DB_TXNHEAD *hp;
DB_TXNLIST *p;
u_int32_t generation, hash, i;
int ret;
ret = 0;
if ((hp = (DB_TXNHEAD *)listp) == NULL)
if (hp == NULL)
return (DB_NOTFOUND);
switch (type) {
@ -712,12 +709,14 @@ __db_txnlist_find_internal(dbenv,
if (delete == 1) {
LIST_REMOVE(p, links);
__os_free(dbenv, p);
*txnlistp = NULL;
} else if (p != LIST_FIRST(head)) {
/* Move it to head of list. */
LIST_REMOVE(p, links);
LIST_INSERT_HEAD(head, p, links);
}
*txnlistp = p;
*txnlistp = p;
} else
*txnlistp = p;
return (ret);
}
@ -729,16 +728,15 @@ __db_txnlist_find_internal(dbenv,
* Change the current generation number.
*
* PUBLIC: int __db_txnlist_gen __P((DB_ENV *,
* PUBLIC: void *, int, u_int32_t, u_int32_t));
* PUBLIC: DB_TXNHEAD *, int, u_int32_t, u_int32_t));
*/
int
__db_txnlist_gen(dbenv, listp, incr, min, max)
__db_txnlist_gen(dbenv, hp, incr, min, max)
DB_ENV *dbenv;
void *listp;
DB_TXNHEAD *hp;
int incr;
u_int32_t min, max;
{
DB_TXNHEAD *hp;
int ret;
/*
@ -753,7 +751,6 @@ __db_txnlist_gen(dbenv, listp, incr, min, max)
* is given the generation number of the first range it falls into
* in the stack.
*/
hp = (DB_TXNHEAD *)listp;
if (incr < 0) {
--hp->generation;
memmove(hp->gen_array, &hp->gen_array[1],
@ -775,71 +772,78 @@ __db_txnlist_gen(dbenv, listp, incr, min, max)
return (0);
}
#define TXN_BUBBLE(AP, MAX) { \
DB_LSN __tmp; \
u_int32_t __j; \
\
for (__j = 0; __j < MAX - 1; __j++) \
if (log_compare(&AP[__j], &AP[__j + 1]) < 0) { \
__tmp = AP[__j]; \
AP[__j] = AP[__j + 1]; \
AP[__j + 1] = __tmp; \
} \
}
/*
* __db_txnlist_lsnadd --
* Add to or re-sort the transaction list lsn entry. Note that since this
* is used during an abort, the __txn_undo code calls into the "recovery"
* subsystem explicitly, and there is only a single TXNLIST_LSN entry on
* the list.
* Save the prev_lsn from a txn_child record.
*
* PUBLIC: int __db_txnlist_lsnadd __P((DB_ENV *, void *, DB_LSN *, u_int32_t));
* PUBLIC: int __db_txnlist_lsnadd __P((DB_ENV *, DB_TXNHEAD *, DB_LSN *));
*/
int
__db_txnlist_lsnadd(dbenv, listp, lsnp, flags)
__db_txnlist_lsnadd(dbenv, hp, lsnp)
DB_ENV *dbenv;
void *listp;
DB_LSN *lsnp;
u_int32_t flags;
{
DB_TXNHEAD *hp;
DB_LSN *lsnp;
{
DB_TXNLIST *elp;
u_int32_t i;
int ret;
hp = (DB_TXNHEAD *)listp;
if (IS_ZERO_LSN(*lsnp))
return (0);
for (elp = LIST_FIRST(&hp->head[0]);
elp != NULL; elp = LIST_NEXT(elp, links))
if (elp->type == TXNLIST_LSN)
break;
if (elp == NULL)
if (elp == NULL) {
if ((ret = __db_txnlist_lsninit(dbenv, hp, lsnp)) != 0)
return (ret);
return (DB_SURPRISE_KID);
}
if (LF_ISSET(TXNLIST_NEW)) {
if (elp->u.l.ntxns >= elp->u.l.maxn) {
if ((ret = __os_realloc(dbenv,
2 * elp->u.l.maxn * sizeof(DB_LSN),
&elp->u.l.lsn_array)) != 0)
return (ret);
elp->u.l.maxn *= 2;
if (elp->u.l.stack_indx == elp->u.l.stack_size) {
elp->u.l.stack_size <<= 1;
if ((ret = __os_realloc(dbenv, sizeof(DB_LSN) *
elp->u.l.stack_size, &elp->u.l.lsn_stack)) != 0) {
__db_txnlist_end(dbenv, hp);
return (ret);
}
elp->u.l.lsn_array[elp->u.l.ntxns++] = *lsnp;
} else
/* Simply replace the 0th element. */
elp->u.l.lsn_array[0] = *lsnp;
}
elp->u.l.lsn_stack[elp->u.l.stack_indx++] = *lsnp;
/*
* If we just added a new entry and there may be NULL entries, so we
* have to do a complete bubble sort, not just trickle a changed entry
* around.
*/
for (i = 0; i < (!LF_ISSET(TXNLIST_NEW) ? 1 : elp->u.l.ntxns); i++)
TXN_BUBBLE(elp->u.l.lsn_array, elp->u.l.ntxns);
return (0);
}
*lsnp = elp->u.l.lsn_array[0];
/*
* __db_txnlist_lsnget --
*
* PUBLIC: int __db_txnlist_lsnget __P((DB_ENV *,
* PUBLIC: DB_TXNHEAD *, DB_LSN *, u_int32_t));
* Get the lsn saved from a txn_child record.
*/
int
__db_txnlist_lsnget(dbenv, hp, lsnp, flags)
DB_ENV *dbenv;
DB_TXNHEAD *hp;
DB_LSN *lsnp;
u_int32_t flags;
{
DB_TXNLIST *elp;
COMPQUIET(dbenv, NULL);
COMPQUIET(flags, 0);
for (elp = LIST_FIRST(&hp->head[0]);
elp != NULL; elp = LIST_NEXT(elp, links))
if (elp->type == TXNLIST_LSN)
break;
if (elp == NULL || elp->u.l.stack_indx == 0) {
ZERO_LSN(*lsnp);
return (0);
}
*lsnp = elp->u.l.lsn_stack[--elp->u.l.stack_indx];
return (0);
}
@ -865,13 +869,13 @@ __db_txnlist_lsninit(dbenv, hp, lsnp)
goto err;
LIST_INSERT_HEAD(&hp->head[0], elp, links);
if ((ret = __os_malloc(dbenv,
12 * sizeof(DB_LSN), &elp->u.l.lsn_array)) != 0)
goto err;
elp->type = TXNLIST_LSN;
elp->u.l.maxn = 12;
elp->u.l.ntxns = 1;
elp->u.l.lsn_array[0] = *lsnp;
if ((ret = __os_malloc(dbenv,
sizeof(DB_LSN) * DB_LSN_STACK_SIZE, &elp->u.l.lsn_stack)) != 0)
goto err;
elp->u.l.stack_indx = 1;
elp->u.l.stack_size = DB_LSN_STACK_SIZE;
elp->u.l.lsn_stack[0] = *lsnp;
return (0);
@ -886,13 +890,13 @@ err: __db_txnlist_end(dbenv, hp);
*
* PUBLIC: #ifndef HAVE_FTRUNCATE
* PUBLIC: int __db_add_limbo __P((DB_ENV *,
* PUBLIC: void *, int32_t, db_pgno_t, int32_t));
* PUBLIC: DB_TXNHEAD *, int32_t, db_pgno_t, int32_t));
* PUBLIC: #endif
*/
int
__db_add_limbo(dbenv, info, fileid, pgno, count)
__db_add_limbo(dbenv, hp, fileid, pgno, count)
DB_ENV *dbenv;
void *info;
DB_TXNHEAD *hp;
int32_t fileid;
db_pgno_t pgno;
int32_t count;
@ -907,7 +911,7 @@ __db_add_limbo(dbenv, info, fileid, pgno, count)
do {
if ((ret =
__db_txnlist_pgnoadd(dbenv, info, fileid, fnp->ufid,
__db_txnlist_pgnoadd(dbenv, hp, fileid, fnp->ufid,
R_ADDR(&dblp->reginfo, fnp->name_off), pgno)) != 0)
return (ret);
pgno++;
@ -1136,9 +1140,9 @@ retry: dbp_created = 0;
dbp_created = 1;
/* It is ok if the file is nolonger there. */
ret = __db_open(dbp,
t, elp->u.p.fname, NULL, DB_UNKNOWN,
DB_ODDFILESIZE, __db_omode("rw----"), PGNO_BASE_MD);
ret = __db_open(dbp, t, elp->u.p.fname, NULL,
DB_UNKNOWN, DB_ODDFILESIZE, __db_omode(OWNER_RW),
PGNO_BASE_MD);
if (ret == ENOENT)
goto next;
}
@ -1153,7 +1157,7 @@ retry: dbp_created = 0;
mpf = dbp->mpf;
last_pgno = PGNO_INVALID;
if (meta == NULL &&
if (meta == NULL &&
(ctxn == NULL || state == LIMBO_COMPENSATE)) {
pgno = PGNO_BASE_MD;
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0)
@ -1383,6 +1387,15 @@ __db_limbo_fix(dbp, ctxn, elp, lastp, meta, state)
* do the open, we have to mark it explicitly.
*/
F_SET(dbc, DBC_COMPENSATE);
/*
* If aborting a txn for a different process
* via XA or failchk, DB_AM_RECOVER will be
* set but we need to log the compensating
* transactions.
*/
F_CLR(dbc, DBC_RECOVER);
ret = __db_free(dbc, pagep);
pagep = NULL;
@ -1537,19 +1550,16 @@ err: return (ret);
* __db_txnlist_print --
* Print out the transaction list.
*
* PUBLIC: void __db_txnlist_print __P((void *));
* PUBLIC: void __db_txnlist_print __P((DB_TXNHEAD *));
*/
void
__db_txnlist_print(listp)
void *listp;
{
__db_txnlist_print(hp)
DB_TXNHEAD *hp;
{
DB_TXNLIST *p;
u_int32_t i;
char *txntype;
hp = (DB_TXNHEAD *)listp;
printf("Maxid: %lu Generation: %lu\n",
(u_long)hp->maxid, (u_long)hp->generation);
for (i = 0; i < hp->nslots; i++)

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_dup.c,v 11.39 2004/02/18 21:34:37 bostic Exp $
* $Id: db_dup.c,v 12.2 2005/06/16 20:21:10 bostic Exp $
*/
#include "db_config.h"
@ -66,7 +66,7 @@ __db_ditem(dbc, pagep, indx, nbytes)
* memmove(3), the regions may overlap.
*/
from = (u_int8_t *)pagep + HOFFSET(pagep);
DB_ASSERT((int)inp[indx] - HOFFSET(pagep) >= 0);
DB_ASSERT(inp[indx] >= HOFFSET(pagep));
memmove(from + nbytes, from, inp[indx] - HOFFSET(pagep));
HOFFSET(pagep) += nbytes;

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,10 @@
/*
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1998-2004
* Copyright (c) 1998-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_join.c,v 11.75 2004/09/22 03:30:23 bostic Exp $
* $Id: db_join.c,v 12.6 2005/10/07 20:21:22 ubell Exp $
*/
#include "db_config.h"
@ -216,9 +216,9 @@ __db_join(primary, curslist, dbcp, flags)
*dbcp = dbc;
MUTEX_THREAD_LOCK(dbenv, primary->mutexp);
MUTEX_LOCK(dbenv, primary->mutex);
TAILQ_INSERT_TAIL(&primary->join_queue, dbc, links);
MUTEX_THREAD_UNLOCK(dbenv, primary->mutexp);
MUTEX_UNLOCK(dbenv, primary->mutex);
return (0);
@ -250,24 +250,30 @@ __db_join_close_pp(dbc)
DBC *dbc;
{
DB_ENV *dbenv;
DB_THREAD_INFO *ip;
DB *dbp;
int handle_check, ret;
int handle_check, ret, t_ret;
dbp = dbc->dbp;
dbenv = dbp->dbenv;
PANIC_CHECK(dbenv);
handle_check = IS_REPLICATED(dbenv, dbp);
ENV_ENTER(dbenv, ip);
handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check &&
(ret = __db_rep_enter(dbp, 0, 0, dbc->txn != NULL)) != 0)
return (ret);
(ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0) {
handle_check = 0;
goto err;
}
ret = __db_join_close(dbc);
if (handle_check)
__env_db_rep_exit(dbenv);
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret);
}
@ -309,8 +315,9 @@ __db_join_get_pp(dbc, key, data, flags)
{
DB *dbp;
DB_ENV *dbenv;
DB_THREAD_INFO *ip;
u_int32_t handle_check, save_flags;
int ret;
int ret, t_ret;
dbp = dbc->dbp;
dbenv = dbp->dbenv;
@ -320,11 +327,10 @@ __db_join_get_pp(dbc, key, data, flags)
PANIC_CHECK(dbenv);
if (LF_ISSET(DB_DIRTY_READ | DB_DEGREE_2 | DB_RMW)) {
if (LF_ISSET(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW)) {
if (!LOCKING_ON(dbp->dbenv))
return (__db_fnl(dbp->dbenv, "DBcursor->c_get"));
LF_CLR(DB_DIRTY_READ | DB_DEGREE_2 | DB_RMW);
LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW);
}
switch (flags) {
@ -352,19 +358,24 @@ __db_join_get_pp(dbc, key, data, flags)
return (EINVAL);
}
handle_check = IS_REPLICATED(dbp->dbenv, dbp);
ENV_ENTER(dbenv, ip);
handle_check = IS_ENV_REPLICATED(dbp->dbenv);
if (handle_check &&
(ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0)
return (ret);
(ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0) {
handle_check = 0;
goto err;
}
/* Restore the original flags value. */
flags = save_flags;
ret = __db_join_get(dbc, key, data, flags);
if (handle_check)
__env_db_rep_exit(dbenv);
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret);
}
@ -390,7 +401,7 @@ __db_join_get(dbc, key_arg, data_arg, flags)
* If the set of flags here changes, check that __db_join_primget
* is updated to handle them properly.
*/
opmods = LF_ISSET(DB_RMW | DB_DEGREE_2 | DB_DIRTY_READ);
opmods = LF_ISSET(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW);
/*
* Since we are fetching the key as a datum in the secondary indices,
@ -726,9 +737,9 @@ __db_join_close(dbc)
* must happen before any action that can fail and return, or else
* __db_close may loop indefinitely.
*/
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_REMOVE(&dbp->join_queue, dbc, links);
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
PANIC_CHECK(dbenv);
@ -872,28 +883,29 @@ __db_join_primget(dbp, txn, lockerid, key, data, flags)
u_int32_t flags;
{
DBC *dbc;
int ret, rmw, t_ret;
u_int32_t rmw;
int ret, t_ret;
if ((ret = __db_cursor_int(dbp,
txn, dbp->type, PGNO_INVALID, 0, lockerid, &dbc)) != 0)
return (ret);
/*
* The only allowable flags here are the two flags copied into
* "opmods" in __db_join_get, DB_RMW and DB_DIRTY_READ. The former
* is an op on the c_get call, the latter on the cursor call.
* It's a DB bug if we allow any other flags down in here.
* The only allowable flags here are the two flags copied into "opmods"
* in __db_join_get, DB_RMW and DB_READ_UNCOMMITTED. The former is an
* op on the c_get call, the latter on the cursor call. It's a DB bug
* if we allow any other flags down in here.
*/
rmw = LF_ISSET(DB_RMW);
if (LF_ISSET(DB_DIRTY_READ) ||
(txn != NULL && F_ISSET(txn, TXN_DIRTY_READ)))
F_SET(dbc, DBC_DIRTY_READ);
if (LF_ISSET(DB_READ_UNCOMMITTED) ||
(txn != NULL && F_ISSET(txn, TXN_READ_UNCOMMITTED)))
F_SET(dbc, DBC_READ_UNCOMMITTED);
if (LF_ISSET(DB_DEGREE_2) ||
(txn != NULL && F_ISSET(txn, TXN_DEGREE_2)))
F_SET(dbc, DBC_DEGREE_2);
if (LF_ISSET(DB_READ_COMMITTED) ||
(txn != NULL && F_ISSET(txn, TXN_READ_COMMITTED)))
F_SET(dbc, DBC_READ_COMMITTED);
LF_CLR(DB_RMW | DB_DIRTY_READ | DB_DEGREE_2);
LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW);
DB_ASSERT(flags == 0);
F_SET(dbc, DBC_TRANSIENT);

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -39,7 +39,7 @@
* 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 $
* $Id: db_meta.c,v 12.22 2005/10/27 01:46:34 bostic Exp $
*/
#include "db_config.h"
@ -47,6 +47,7 @@
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#endif
@ -58,6 +59,12 @@
#include "dbinc/db_am.h"
static void __db_init_meta __P((DB *, void *, db_pgno_t, u_int32_t));
#ifdef HAVE_FTRUNCATE
static void __db_freelist_sort __P((struct pglist *, u_int32_t));
static int __db_pglistcmp __P((const void *, const void *));
static int __db_truncate_freelist __P((DBC *, DBMETA *,
PAGE *, db_pgno_t *, u_int32_t, u_int32_t));
#endif
/*
* __db_init_meta --
@ -104,7 +111,7 @@ __db_new(dbc, type, pagepp)
DB_LSN lsn;
DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t last, pgno, newnext;
db_pgno_t last, *list, pgno, newnext;
u_int32_t meta_flags;
int extend, ret, t_ret;
@ -123,6 +130,10 @@ __db_new(dbc, type, pagepp)
goto err;
last = meta->last_pgno;
if (meta->free == PGNO_INVALID) {
if (FLD_ISSET(type, P_DONTEXTEND)) {
*pagepp = NULL;
goto err;
}
last = pgno = meta->last_pgno + 1;
ZERO_LSN(lsn);
extend = 1;
@ -141,6 +152,8 @@ __db_new(dbc, type, pagepp)
extend = 0;
}
FLD_CLR(type, P_DONTEXTEND);
/*
* Log the allocation before fetching the new page. If we
* don't have room in the log then we don't want to tell
@ -191,19 +204,40 @@ __db_new(dbc, type, pagepp)
break;
}
/* Fix up the sorted free list if necessary. */
#ifdef HAVE_FTRUNCATE
if (extend == 0) {
u_int32_t nelems = 0;
if ((ret = __memp_get_freelist(dbp->mpf, &nelems, &list)) != 0)
goto err;
if (nelems != 0) {
DB_ASSERT(h->pgno == list[0]);
memmove(list, &list[1], (nelems - 1) * sizeof(*list));
if ((ret = __memp_extend_freelist(
dbp->mpf, nelems - 1, &list)) != 0)
goto err;
}
}
#else
COMPQUIET(list, NULL);
#endif
/*
* If dirty reads are enabled and we are in a transaction, we could
* abort this allocation after the page(s) pointing to this
* one have their locks downgraded. This would permit dirty readers
* to access this page which is ok, but they must be off the
* page when we abort. This will also prevent updates happening
* to this page until we commit.
* page when we abort. We never lock overflow pages or off page
* duplicate trees.
*/
if (F_ISSET(dbc->dbp, DB_AM_DIRTY) && dbc->txn != NULL) {
if (type != P_OVERFLOW && !F_ISSET(dbc, DBC_OPD) &&
F_ISSET(dbc->dbp, DB_AM_READ_UNCOMMITTED) && dbc->txn != NULL) {
if ((ret = __db_lget(dbc, 0,
h->pgno, DB_LOCK_WWRITE, 0, &metalock)) != 0)
goto err;
}
*pagepp = h;
return (0);
@ -231,16 +265,29 @@ __db_free(dbc, h)
DBT ddbt, ldbt;
DB_LOCK metalock;
DB_MPOOLFILE *mpf;
db_pgno_t pgno;
u_int32_t dirty_flag;
int ret, t_ret;
db_pgno_t last_pgno, *lp, next_pgno, pgno, prev_pgno;
u_int32_t dirty_flag, lflag, nelem;
int do_truncate, ret, t_ret;
#ifdef HAVE_FTRUNCATE
db_pgno_t *list;
u_int32_t position, start;
#endif
dbp = dbc->dbp;
mpf = dbp->mpf;
prev_pgno = PGNO_INVALID;
nelem = 0;
meta = NULL;
do_truncate = 0;
lp = NULL;
/*
* Retrieve the metadata page and insert the page at the head of
* the free list. If either the lock get or page get routines
* Retrieve the metadata page. If we are not keeping a sorted
* free list put the page at the head of the the free list.
* If we are keeping a sorted free list, for truncation,
* then figure out where this page belongs and either
* link it in or truncate the file as much as possible.
* If either the lock get or page get routines
* fail, then we need to put the page with which we were called
* back because our caller assumes we take care of it.
*/
@ -249,12 +296,76 @@ __db_free(dbc, h)
if ((ret = __db_lget(dbc,
LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
goto err;
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0) {
(void)__TLPUT(dbc, metalock);
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0)
goto err1;
last_pgno = meta->last_pgno;
next_pgno = meta->free;
DB_ASSERT(h->pgno != next_pgno);
#ifdef HAVE_FTRUNCATE
/*
* If we are maintaining a sorted free list see if we either have a
* new truncation point or the page goes somewhere in the middle of
* the list. If it goes in the middle of the list, we will drop the
* meta page and get the previous page.
*/
if ((ret = __memp_get_freelist(mpf, &nelem, &list)) != 0)
goto err;
if (list == NULL)
goto no_sort;
if (h->pgno != last_pgno) {
/*
* Put the page number in the sorted list.
* Finds its position and the previous page,
* extend the list, make room and insert.
*/
position = 0;
if (nelem != 0) {
__db_freelist_pos(h->pgno, list, nelem, &position);
DB_ASSERT(h->pgno != list[position]);
/* Get the previous page if this is not the smallest. */
if (position != 0 || h->pgno > list[0])
prev_pgno = list[position];
}
/* Put the page number into the list. */
if ((ret = __memp_extend_freelist(mpf, nelem + 1, &list)) != 0)
return (ret);
if (prev_pgno != PGNO_INVALID)
lp = &list[position + 1];
else
lp = list;
if (nelem != 0 && position != nelem)
memmove(lp + 1, lp,
(size_t)((u_int8_t*)&list[nelem] - (u_int8_t*)lp));
*lp = h->pgno;
} else if (nelem != 0) {
/* Find the truncation point. */
for (lp = &list[nelem - 1]; lp >= list; lp--)
if (--last_pgno != *lp)
break;
if (lp < list || last_pgno < h->pgno - 1)
do_truncate = 1;
last_pgno = meta->last_pgno;
}
DB_ASSERT(h->pgno != meta->free);
no_sort:
if (prev_pgno != PGNO_INVALID) {
if ((ret = __memp_fput(mpf, meta, 0)) != 0)
goto err1;
meta = NULL;
pgno = prev_pgno;
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0)
goto err1;
next_pgno = NEXT_PGNO(meta);
}
#endif
/* Log the change. */
if (DBC_LOGGING(dbc)) {
memset(&ldbt, 0, sizeof(ldbt));
@ -269,47 +380,61 @@ __db_free(dbc, h)
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;
ddbt.data = (u_int8_t *)h + HOFFSET(h);
ddbt.size = dbp->pgsize - HOFFSET(h);
if ((ret = __db_pg_freedata_log(dbp, dbc->txn,
&LSN(meta), 0, h->pgno, &LSN(meta), pgno,
&ldbt, next_pgno, last_pgno, &ddbt)) != 0)
goto err1;
goto logged;
}
goto log;
break;
case P_HASHMETA:
ldbt.size = sizeof(HMETA);
goto log;
break;
case P_BTREEMETA:
ldbt.size = sizeof(BTMETA);
goto log;
break;
case P_OVERFLOW:
ldbt.size += OV_LEN(h);
goto log;
break;
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;
}
/*
* If we are truncating the file, we need to make sure
* the logging happens before the truncation. If we
* are truncating multiple pages we don't need to flush the
* log here as it will be flushed by __db_truncate_freelist.
*/
lflag = 0;
#ifdef HAVE_FTRUNCATE
if (do_truncate == 0 && h->pgno == last_pgno)
lflag = DB_FLUSH;
#endif
if ((ret = __db_pg_free_log(dbp,
dbc->txn, &LSN(meta), lflag, h->pgno,
&LSN(meta), pgno, &ldbt, next_pgno, last_pgno)) != 0)
goto err1;
} else
LSN_NOT_LOGGED(LSN(meta));
LSN(h) = LSN(meta);
logged: LSN(h) = LSN(meta);
#ifdef HAVE_FTRUNCATE
if (h->pgno == meta->last_pgno) {
if (do_truncate) {
start = (u_int32_t) (lp - list) + 1;
meta->last_pgno--;
ret = __db_truncate_freelist(
dbc, meta, h, list, start, nelem);
h = NULL;
} else if (h->pgno == 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)
if ((ret = __memp_ftruncate(mpf, last_pgno, 0)) != 0)
goto err;
DB_ASSERT(meta->pgno == PGNO_BASE_MD);
meta->last_pgno--;
h = NULL;
} else
@ -318,20 +443,23 @@ log: ret = __db_pg_free_log(dbp,
{
/*
* If we are not truncating the page then we
* reinitialize it and put it hat the head of
* reinitialize it and put it at the head of
* the free list.
*/
P_INIT(h, dbp->pgsize,
h->pgno, PGNO_INVALID, meta->free, 0, P_INVALID);
h->pgno, PGNO_INVALID, next_pgno, 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;
if (prev_pgno == PGNO_INVALID)
meta->free = h->pgno;
else
NEXT_PGNO(meta) = h->pgno;
}
/* Discard the metadata page. */
if ((t_ret =
/* Discard the metadata or previous page. */
err1: if (meta != NULL && (t_ret =
__memp_fput(mpf, (PAGE *)meta, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
if ((t_ret = __TLPUT(dbc, metalock)) != 0 && ret == 0)
@ -350,6 +478,377 @@ err: if (h != NULL &&
return (ret);
}
#ifdef HAVE_FTRUNCATE
/*
* __db_freelist_pos -- find the position of a page in the freelist.
* The list is sorted, we do a binary search.
*
* PUBLIC: #ifdef HAVE_FTRUNCATE
* PUBLIC: void __db_freelist_pos __P((db_pgno_t,
* PUBLIC: db_pgno_t *, u_int32_t, u_int32_t *));
* PUBLIC: #endif
*/
void
__db_freelist_pos(pgno, list, nelem, posp)
db_pgno_t pgno;
db_pgno_t *list;
u_int32_t nelem;
u_int32_t *posp;
{
u_int32_t base, indx, lim;
indx = 0;
for (base = 0, lim = nelem; lim != 0; lim >>= 1) {
indx = base + (lim >> 1);
if (pgno == list[indx]) {
*posp = indx;
return;
}
if (pgno > list[indx]) {
base = indx + 1;
--lim;
}
}
if (base != 0)
base--;
*posp = base;
return;
}
static int
__db_pglistcmp(a, b)
const void *a, *b;
{
struct pglist *ap, *bp;
ap = (struct pglist *)a;
bp = (struct pglist *)b;
return ((ap->pgno > bp->pgno) ? 1 : (ap->pgno < bp->pgno) ? -1: 0);
}
/*
* __db_freelist_sort -- sort a list of free pages.
*/
static void
__db_freelist_sort(list, nelems)
struct pglist *list;
u_int32_t nelems;
{
qsort(list, (size_t)nelems, sizeof(struct pglist), __db_pglistcmp);
}
/*
* __db_pg_truncate -- sort the freelist and find the truncation point.
*
* PUBLIC: #ifdef HAVE_FTRUNCATE
* PUBLIC: int __db_pg_truncate __P((DB_MPOOLFILE *, struct pglist *list,
* PUBLIC: DB_COMPACT *, u_int32_t *, db_pgno_t *, DB_LSN *, int));
* PUBLIC: #endif
*/
int
__db_pg_truncate(mpf, list, c_data, nelemp, last_pgno, lsnp, in_recovery)
DB_MPOOLFILE *mpf;
struct pglist *list;
DB_COMPACT *c_data;
u_int32_t *nelemp;
db_pgno_t *last_pgno;
DB_LSN *lsnp;
int in_recovery;
{
PAGE *h;
struct pglist *lp;
db_pgno_t pgno;
u_int32_t nelems;
int modified, ret;
ret = 0;
nelems = *nelemp;
/* Sort the list */
__db_freelist_sort(list, nelems);
/* Find the truncation point. */
pgno = *last_pgno;
lp = &list[nelems - 1];
while (nelems != 0) {
if (lp->pgno != pgno)
break;
pgno--;
nelems--;
lp--;
}
/*
* Figure out what (if any) pages can be truncated immediately and
* record the place from which we can truncate, so we can do the
* memp_ftruncate below. We also use this to avoid ever putting
* these pages on the freelist, which we are about to relink.
*/
for (lp = list; lp < &list[nelems]; lp++) {
if ((ret = __memp_fget(mpf, &lp->pgno, 0, &h)) != 0) {
/* Page may have been truncated later. */
if (in_recovery && ret == DB_PAGE_NOTFOUND) {
ret = 0;
continue;
}
goto err;
}
modified = 0;
if (!in_recovery || log_compare(&LSN(h), &lp->lsn) == 0) {
if (lp == &list[nelems - 1])
NEXT_PGNO(h) = PGNO_INVALID;
else
NEXT_PGNO(h) = lp[1].pgno;
DB_ASSERT(NEXT_PGNO(h) < *last_pgno);
LSN(h) = *lsnp;
modified = 1;
}
if ((ret = __memp_fput(mpf, h,
modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto err;
}
if (pgno != *last_pgno) {
if ((ret = __memp_ftruncate(mpf,
pgno + 1, in_recovery ? MP_TRUNC_RECOVER : 0)) != 0)
goto err;
if (c_data)
c_data->compact_pages_truncated += *last_pgno - pgno;
*last_pgno = pgno;
}
*nelemp = nelems;
err: return (ret);
}
/*
* __db_free_truncate --
* Truncate free pages at the end of the file.
*
* PUBLIC: #ifdef HAVE_FTRUNCATE
* PUBLIC: int __db_free_truncate __P((DB *, DB_TXN *, u_int32_t,
* PUBLIC: DB_COMPACT *, struct pglist **, u_int32_t *, db_pgno_t *));
* PUBLIC: #endif
*/
int
__db_free_truncate(dbp, txn, flags, c_data, listp, nelemp, last_pgnop)
DB *dbp;
DB_TXN *txn;
u_int32_t flags;
DB_COMPACT *c_data;
struct pglist **listp;
u_int32_t *nelemp;
db_pgno_t *last_pgnop;
{
DBC *dbc;
DB_ENV *dbenv;
DBMETA *meta;
DBT ddbt;
DB_LOCK metalock;
DB_LSN null_lsn;
DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t pgno;
u_int32_t nelems;
struct pglist *list, *lp;
int ret, t_ret;
size_t size;
COMPQUIET(flags, 0);
list = NULL;
meta = NULL;
dbenv = dbp->dbenv;
mpf = dbp->mpf;
h = NULL;
nelems = 0;
if (listp != NULL) {
*listp = NULL;
DB_ASSERT(nelemp != NULL);
*nelemp = 0;
}
if ((ret = __db_cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
return (ret);
pgno = PGNO_BASE_MD;
if ((ret = __db_lget(dbc,
LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
goto err;
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0)
goto err;
if (last_pgnop != NULL)
*last_pgnop = meta->last_pgno;
if ((pgno = meta->free) == PGNO_INVALID)
goto done;
size = 128;
if ((ret = __os_malloc(dbenv, size * sizeof(*list), &list)) != 0)
goto err;
lp = list;
do {
if (lp == &list[size]) {
size *= 2;
if ((ret = __os_realloc(dbenv,
size * sizeof(*list), &list)) != 0)
goto err;
lp = &list[size / 2];
}
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
goto err;
lp->pgno = pgno;
lp->lsn = LSN(h);
pgno = NEXT_PGNO(h);
if ((ret = __memp_fput(mpf, h, 0)) != 0)
goto err;
lp++;
} while (pgno != PGNO_INVALID);
nelems = (u_int32_t)(lp - list);
/* Log the current state of the free list */
if (DBC_LOGGING(dbc)) {
ddbt.data = list;
ddbt.size = nelems * sizeof(*lp);
ZERO_LSN(null_lsn);
if ((ret = __db_pg_sort_log(dbp,
dbc->txn, &LSN(meta), DB_FLUSH, PGNO_BASE_MD, &LSN(meta),
PGNO_INVALID, &null_lsn, meta->last_pgno, &ddbt)) != 0)
goto err;
} else
LSN_NOT_LOGGED(LSN(meta));
if ((ret = __db_pg_truncate(mpf, list, c_data,
&nelems, &meta->last_pgno, &LSN(meta), 0)) != 0)
goto err;
if (nelems == 0)
meta->free = PGNO_INVALID;
else
meta->free = list[0].pgno;
done: if (last_pgnop != NULL)
*last_pgnop = meta->last_pgno;
/*
* The truncate point is the number of pages in the free
* list back from the last page. The number of pages
* in the free list are the number that we can swap in.
*/
if (c_data)
c_data->compact_truncate = (u_int32_t)meta->last_pgno - nelems;
if (nelems != 0 && listp != NULL) {
*listp = list;
*nelemp = nelems;
list = NULL;
}
err: if (list != NULL)
__os_free(dbenv, list);
if (meta != NULL && (t_ret =
__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;
if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
static int
__db_truncate_freelist(dbc, meta, h, list, start, nelem)
DBC *dbc;
DBMETA *meta;
PAGE *h;
db_pgno_t *list;
u_int32_t start, nelem;
{
DB *dbp;
DB_LSN null_lsn;
DB_MPOOLFILE *mpf;
DBT ddbt;
PAGE *last_free, *pg;
db_pgno_t *lp;
struct pglist *plist, *pp;
int ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
plist = NULL;
last_free = NULL;
if (start != 0 &&
(ret = __memp_fget(mpf, &list[start - 1], 0, &last_free)) != 0)
goto err;
if (DBC_LOGGING(dbc)) {
if ((ret = __os_malloc(dbp->dbenv,
(nelem - start) * sizeof(*pp), &plist)) != 0)
goto err;
pp = plist;
for (lp = &list[start]; lp < &list[nelem]; lp++) {
pp->pgno = *lp;
if ((ret = __memp_fget(mpf, lp, 0, &pg)) != 0)
goto err;
pp->lsn = LSN(pg);
if ((ret = __memp_fput(mpf, pg, DB_MPOOL_DISCARD)) != 0)
goto err;
pp++;
}
ddbt.data = plist;
ddbt.size = (nelem - start) * sizeof(*pp);
ZERO_LSN(null_lsn);
if (last_free != NULL) {
if ((ret = __db_pg_sort_log(dbp, dbc->txn, &LSN(meta),
DB_FLUSH, PGNO(meta), &LSN(meta), PGNO(last_free),
&LSN(last_free), meta->last_pgno, &ddbt)) != 0)
goto err;
} else if ((ret = __db_pg_sort_log(dbp, dbc->txn,
&LSN(meta), DB_FLUSH, PGNO(meta), &LSN(meta),
PGNO_INVALID, &null_lsn, meta->last_pgno, &ddbt)) != 0)
goto err;
} else
LSN_NOT_LOGGED(LSN(meta));
if (last_free != NULL)
LSN(last_free) = LSN(meta);
if ((ret = __memp_fput(mpf, h, DB_MPOOL_DISCARD)) != 0)
goto err;
h = NULL;
if ((ret = __memp_ftruncate(mpf, list[start], 0)) != 0)
goto err;
meta->last_pgno = list[start] - 1;
if (start == 0)
meta->free = PGNO_INVALID;
else {
NEXT_PGNO(last_free) = PGNO_INVALID;
if ((ret = __memp_fput(mpf, last_free, DB_MPOOL_DIRTY)) != 0)
goto err;
last_free = NULL;
}
/* Shrink the number of elements in the list. */
ret = __memp_extend_freelist(mpf, start, &list);
err: if (plist != NULL)
__os_free(dbp->dbenv, plist);
/* We need to put the page on error. */
if (h != NULL)
(void)__memp_fput(mpf, h, 0);
if (last_free != NULL)
(void)__memp_fput(mpf, last_free, 0);
return (ret);
}
#endif
#ifdef DEBUG
/*
* __db_lprint --
@ -394,9 +893,9 @@ __db_lget(dbc, action, pgno, mode, lkflags, lockp)
{
DB *dbp;
DB_ENV *dbenv;
DB_LOCKREQ couple[2], *reqp;
DB_LOCKREQ couple[3], *reqp;
DB_TXN *txn;
int has_timeout, ret;
int has_timeout, i, ret;
dbp = dbc->dbp;
dbenv = dbp->dbenv;
@ -431,8 +930,8 @@ __db_lget(dbc, action, pgno, mode, lkflags, lockp)
if (DB_NONBLOCK(dbc))
lkflags |= DB_LOCK_NOWAIT;
if (F_ISSET(dbc, DBC_DIRTY_READ) && mode == DB_LOCK_READ)
mode = DB_LOCK_DIRTY;
if (F_ISSET(dbc, DBC_READ_UNCOMMITTED) && mode == DB_LOCK_READ)
mode = DB_LOCK_READ_UNCOMMITTED;
has_timeout = F_ISSET(dbc, DBC_RECOVER) ||
(txn != NULL && F_ISSET(txn, TXN_LOCKTIMEOUT));
@ -440,8 +939,8 @@ __db_lget(dbc, action, pgno, mode, lkflags, 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.
* 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) ||
@ -449,47 +948,54 @@ __db_lget(dbc, action, pgno, mode, lkflags, 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)
else if (F_ISSET(dbc,
DBC_READ_COMMITTED) && lockp->mode == DB_LOCK_READ)
action = LCK_COUPLE;
else if (F_ISSET(dbc, DBC_DIRTY_READ) && lockp->mode == DB_LOCK_DIRTY)
else if (F_ISSET(dbc,
DBC_READ_UNCOMMITTED) && lockp->mode == DB_LOCK_READ_UNCOMMITTED)
action = LCK_COUPLE;
else if (F_ISSET(dbc->dbp, DB_AM_DIRTY) && lockp->mode == DB_LOCK_WRITE)
else if (F_ISSET(dbc->dbp,
DB_AM_READ_UNCOMMITTED) && lockp->mode == DB_LOCK_WRITE)
action = LCK_DOWNGRADE;
else
action = 0;
i = 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;
}
if (has_timeout)
goto couple;
ret = __lock_get(dbenv,
dbc->locker, lkflags, &dbc->lock_dbt, mode, lockp);
break;
case LCK_DOWNGRADE:
couple[0].op = DB_LOCK_GET;
couple[0].obj = NULL;
couple[0].lock = *lockp;
couple[0].mode = DB_LOCK_WWRITE;
UMRW_SET(couple[0].timeout);
i++;
/* FALLTHROUGH */
case LCK_COUPLE:
couple[0].op = has_timeout? DB_LOCK_GET_TIMEOUT : DB_LOCK_GET;
couple[0].obj = &dbc->lock_dbt;
couple[0].mode = mode;
UMRW_SET(couple[0].timeout);
couple: couple[i].op = has_timeout? DB_LOCK_GET_TIMEOUT : DB_LOCK_GET;
couple[i].obj = &dbc->lock_dbt;
couple[i].mode = mode;
UMRW_SET(couple[i].timeout);
i++;
if (has_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;
if (action == LCK_COUPLE || action == LCK_DOWNGRADE) {
couple[i].op = DB_LOCK_PUT;
couple[i].lock = *lockp;
i++;
}
ret = __lock_vec(dbenv, dbc->locker,
lkflags, couple, action == LCK_COUPLE ? 2 : 1, &reqp);
if (ret == 0 || reqp == &couple[1])
*lockp = couple[0].lock;
ret = __lock_vec(dbenv,
dbc->locker, lkflags, couple, i, &reqp);
if (ret == 0 || reqp == &couple[i - 1])
*lockp = i == 1 ? couple[0].lock : couple[i - 2].lock;
break;
}
@ -511,6 +1017,7 @@ __db_lput(dbc, lockp)
DB_LOCK *lockp;
{
DB_ENV *dbenv;
DB_LOCKREQ couple[2], *reqp;
int action, ret;
/*
@ -518,13 +1025,16 @@ __db_lput(dbc, lockp)
* 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)
if (F_ISSET(dbc->dbp,
DB_AM_READ_UNCOMMITTED) && 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)
else if (F_ISSET(dbc,
DBC_READ_COMMITTED) && lockp->mode == DB_LOCK_READ)
action = LCK_COUPLE;
else if (F_ISSET(dbc, DBC_DIRTY_READ) && lockp->mode == DB_LOCK_DIRTY)
else if (F_ISSET(dbc,
DBC_READ_UNCOMMITTED) && lockp->mode == DB_LOCK_READ_UNCOMMITTED)
action = LCK_COUPLE;
else
action = 0;
@ -532,10 +1042,19 @@ __db_lput(dbc, lockp)
dbenv = dbc->dbp->dbenv;
switch (action) {
case LCK_COUPLE:
ret = __lock_put(dbenv, lockp, 0);
ret = __lock_put(dbenv, lockp);
break;
case LCK_DOWNGRADE:
ret = __lock_downgrade(dbenv, lockp, DB_LOCK_WWRITE, 0);
couple[0].op = DB_LOCK_GET;
couple[0].obj = NULL;
couple[0].mode = DB_LOCK_WWRITE;
couple[0].lock = *lockp;
UMRW_SET(couple[0].timeout);
couple[1].op = DB_LOCK_PUT;
couple[1].lock = *lockp;
ret = __lock_vec(dbenv, dbc->locker, 0, couple, 2, &reqp);
if (ret == 0 || reqp == &couple[1])
*lockp = couple[0].lock;
break;
default:
ret = 0;

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1999-2004
* Copyright (c) 1999-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_method.c,v 11.116 2004/10/11 18:22:05 bostic Exp $
* $Id: db_method.c,v 12.15 2005/11/08 03:24:58 bostic Exp $
*/
#include "db_config.h"
@ -32,8 +32,7 @@
#include "dbinc/lock.h"
#include "dbinc/mp.h"
#include "dbinc/qam.h"
#include "dbinc/xa.h"
#include "dbinc_auto/xa_ext.h"
#include "dbinc/txn.h"
#ifdef HAVE_RPC
#include "dbinc_auto/rpc_client_ext.h"
@ -42,9 +41,10 @@
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 DB_MPOOLFILE *__db_get_mpf __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_init __P((DB_ENV *, DB *, 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)));
@ -71,10 +71,6 @@ 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 *, ...));
#ifdef HAVE_RPC
static int __dbcl_init __P((DB *, DB_ENV *, u_int32_t));
#endif
/*
* db_create --
* DB constructor.
@ -88,14 +84,14 @@ db_create(dbpp, dbenv, flags)
u_int32_t flags;
{
DB *dbp;
DB_THREAD_INFO *ip;
DB_REP *db_rep;
int ret;
/* Check for invalid function flags. */
switch (flags) {
case 0:
break;
case DB_REP_CREATE:
break;
case DB_XA_CREATE:
if (dbenv != NULL) {
__db_err(dbenv,
@ -115,16 +111,17 @@ db_create(dbpp, dbenv, flags)
return (__db_ferr(dbenv, "db_create", 0));
}
ip = NULL;
if (dbenv != NULL)
ENV_ENTER(dbenv, ip);
/* Allocate the DB. */
if ((ret = __os_calloc(dbenv, 1, sizeof(*dbp), &dbp)) != 0)
if ((ret = __os_calloc(dbenv, 1, sizeof(*dbp), &dbp)) != 0) {
if (dbenv != NULL)
ENV_LEAVE(dbenv, ip);
return (ret);
#ifdef HAVE_RPC
if (dbenv != NULL && RPC_ON(dbenv))
ret = __dbcl_init(dbp, dbenv, flags);
else
#endif
ret = __db_init(dbp, flags);
if (ret != 0)
}
if ((ret = __db_init(dbenv, dbp, flags)) != 0)
goto err;
/* If we don't have an environment yet, allocate a local one. */
@ -132,26 +129,34 @@ db_create(dbpp, dbenv, flags)
if ((ret = db_env_create(&dbenv, 0)) != 0)
goto err;
F_SET(dbenv, DB_ENV_DBLOCAL);
ENV_ENTER(dbenv, ip);
}
dbp->dbenv = dbenv;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
++dbenv->db_ref;
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
/*
* Set the replication timestamp; it's 0 if we're not in a replicated
* environment.
* environment. Don't acquire a lock to read the value, even though
* it's opaque: all we check later is value equality, nothing else.
*/
dbp->timestamp =
(F_ISSET(dbenv, DB_ENV_DBLOCAL) || !REP_ON(dbenv)) ? 0 :
((REGENV *)((REGINFO *)dbenv->reginfo)->primary)->rep_timestamp;
dbp->timestamp = REP_ON(dbenv) ?
((REGENV *)((REGINFO *)dbenv->reginfo)->primary)->rep_timestamp : 0;
/*
* Set the replication generation number for fid management; valid
* replication generations start at 1. Don't acquire a lock to
* read the value. All we check later is value equality.
*/
db_rep = dbenv->rep_handle;
dbp->fid_gen =
(REP_ON(dbenv) && db_rep->region != NULL) ?
((REP *)db_rep->region)->gen : 0;
/* 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;
if (!RPC_ON(dbenv) &&
(ret = __memp_fcreate(dbenv, &dbp->mpf)) != 0)
goto err;
dbp->type = DB_UNKNOWN;
@ -161,9 +166,10 @@ db_create(dbpp, dbenv, flags)
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);
(void)__env_close(dbenv, 0);
__os_free(dbenv, dbp);
*dbpp = NULL;
ENV_LEAVE(dbenv, ip);
return (ret);
}
@ -172,7 +178,8 @@ err: if (dbp->mpf != NULL)
* Initialize a DB structure.
*/
static int
__db_init(dbp, flags)
__db_init(dbenv, dbp, flags)
DB_ENV *dbenv;
DB *dbp;
u_int32_t flags;
{
@ -189,8 +196,10 @@ __db_init(dbp, flags)
FLD_SET(dbp->am_ok,
DB_OK_BTREE | DB_OK_HASH | DB_OK_QUEUE | DB_OK_RECNO);
/* DB PUBLIC HANDLE LIST BEGIN */
dbp->associate = __db_associate_pp;
dbp->close = __db_close_pp;
dbp->compact = __db_compact_pp;
dbp->cursor = __db_cursor_pp;
dbp->del = __db_del_pp;
dbp->dump = __db_dump_pp;
@ -199,9 +208,18 @@ __db_init(dbp, flags)
dbp->fd = __db_fd_pp;
dbp->get = __db_get_pp;
dbp->get_byteswapped = __db_get_byteswapped;
dbp->get_cachesize = __db_get_cachesize;
dbp->get_dbname = __db_get_dbname;
dbp->get_encrypt_flags = __db_get_encrypt_flags;
dbp->get_env = __db_get_env;
dbp->get_errfile = __db_get_errfile;
dbp->get_errpfx = __db_get_errpfx;
dbp->get_flags = __db_get_flags;
dbp->get_lorder = __db_get_lorder;
dbp->get_mpf = __db_get_mpf;
dbp->get_msgfile = __db_get_msgfile;
dbp->get_open_flags = __db_get_open_flags;
dbp->get_pagesize = __db_get_pagesize;
dbp->get_transactional = __db_get_transactional;
dbp->get_type = __db_get_type;
dbp->join = __db_join_pp;
@ -211,35 +229,28 @@ __db_init(dbp, flags)
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_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_pp;
dbp->stat_print = __db_stat_print_pp;
dbp->sync = __db_sync_pp;
dbp->truncate = __db_truncate_pp;
dbp->upgrade = __db_upgrade_pp;
dbp->verify = __db_verify_pp;
/* DB PUBLIC HANDLE LIST END */
/* Access method specific. */
if ((ret = __bam_db_create(dbp)) != 0)
@ -256,8 +267,25 @@ __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);
#ifdef HAVE_RPC
/*
* RPC specific: must be last, as we replace methods set by the
* access methods.
*/
if (dbenv != NULL && RPC_ON(dbenv)) {
__dbcl_dbp_init(dbp);
/*
* !!!
* We wrap the DB->open method for RPC, and the rpc.src file
* can't handle that.
*/
dbp->open = __dbcl_db_open_wrap;
if ((ret = __dbcl_db_create(dbp, dbenv, flags)) != 0)
return (ret);
}
#else
COMPQUIET(dbenv, NULL);
#endif
return (0);
}
@ -370,6 +398,17 @@ __db_get_env(dbp)
return (dbp->dbenv);
}
/*
* __db_get_mpf --
* Get the underlying DB_MPOOLFILE handle.
*/
static DB_MPOOLFILE *
__db_get_mpf(dbp)
DB *dbp;
{
return (dbp->mpf);
}
/*
* get_transactional --
* Get whether this database was created in a transaction.
@ -478,7 +517,7 @@ __db_get_encrypt_flags(dbp, flagsp)
{
DB_ILLEGAL_IN_ENV(dbp, "DB->get_encrypt_flags");
return (__dbenv_get_encrypt_flags(dbp->dbenv, flagsp));
return (__env_get_encrypt_flags(dbp->dbenv, flagsp));
}
/*
@ -497,7 +536,7 @@ __db_set_encrypt(dbp, passwd, flags)
DB_ILLEGAL_IN_ENV(dbp, "DB->set_encrypt");
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_encrypt");
if ((ret = __dbenv_set_encrypt(dbp->dbenv, passwd, flags)) != 0)
if ((ret = __env_set_encrypt(dbp->dbenv, passwd, flags)) != 0)
return (ret);
/*
@ -517,7 +556,7 @@ __db_set_errcall(dbp, errcall)
DB *dbp;
void (*errcall) __P((const DB_ENV *, const char *, const char *));
{
__dbenv_set_errcall(dbp->dbenv, errcall);
__env_set_errcall(dbp->dbenv, errcall);
}
static void
@ -525,7 +564,7 @@ __db_get_errfile(dbp, errfilep)
DB *dbp;
FILE **errfilep;
{
__dbenv_get_errfile(dbp->dbenv, errfilep);
__env_get_errfile(dbp->dbenv, errfilep);
}
static void
@ -533,7 +572,7 @@ __db_set_errfile(dbp, errfile)
DB *dbp;
FILE *errfile;
{
__dbenv_set_errfile(dbp->dbenv, errfile);
__env_set_errfile(dbp->dbenv, errfile);
}
static void
@ -541,7 +580,7 @@ __db_get_errpfx(dbp, errpfxp)
DB *dbp;
const char **errpfxp;
{
__dbenv_get_errpfx(dbp->dbenv, errpfxp);
__env_get_errpfx(dbp->dbenv, errpfxp);
}
static void
@ -549,7 +588,7 @@ __db_set_errpfx(dbp, errpfx)
DB *dbp;
const char *errpfx;
{
__dbenv_set_errpfx(dbp->dbenv, errpfx);
__env_set_errpfx(dbp->dbenv, errpfx);
}
static int
@ -740,7 +779,7 @@ __db_set_alloc(dbp, mal_func, real_func, free_func)
DB_ILLEGAL_IN_ENV(dbp, "DB->set_alloc");
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_alloc");
return (__dbenv_set_alloc(dbp->dbenv, mal_func, real_func, free_func));
return (__env_set_alloc(dbp->dbenv, mal_func, real_func, free_func));
}
static void
@ -748,7 +787,7 @@ __db_set_msgcall(dbp, msgcall)
DB *dbp;
void (*msgcall) __P((const DB_ENV *, const char *));
{
__dbenv_set_msgcall(dbp->dbenv, msgcall);
__env_set_msgcall(dbp->dbenv, msgcall);
}
static void
@ -756,7 +795,7 @@ __db_get_msgfile(dbp, msgfilep)
DB *dbp;
FILE **msgfilep;
{
__dbenv_get_msgfile(dbp->dbenv, msgfilep);
__env_get_msgfile(dbp->dbenv, msgfilep);
}
static void
@ -764,7 +803,7 @@ __db_set_msgfile(dbp, msgfile)
DB *dbp;
FILE *msgfile;
{
__dbenv_set_msgfile(dbp->dbenv, msgfile);
__env_set_msgfile(dbp->dbenv, msgfile);
}
static int
@ -824,97 +863,5 @@ __db_set_paniccall(dbp, paniccall)
DB *dbp;
void (*paniccall) __P((DB_ENV *, int));
{
return (__dbenv_set_paniccall(dbp->dbenv, paniccall));
return (__env_set_paniccall(dbp->dbenv, paniccall));
}
#ifdef HAVE_RPC
/*
* __dbcl_init --
* Initialize a DB structure on the server.
*/
static int
__dbcl_init(dbp, dbenv, flags)
DB *dbp;
DB_ENV *dbenv;
u_int32_t flags;
{
TAILQ_INIT(&dbp->free_queue);
TAILQ_INIT(&dbp->active_queue);
/* !!!
* Note that we don't need to initialize the join_queue; it's
* not used in RPC clients. See the comment in __dbcl_db_join_ret().
*/
dbp->associate = __dbcl_db_associate;
dbp->close = __dbcl_db_close;
dbp->cursor = __dbcl_db_cursor;
dbp->del = __dbcl_db_del;
dbp->err = __dbh_err;
dbp->errx = __dbh_errx;
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;
dbp->remove = __dbcl_db_remove;
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_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;
dbp->sync = __dbcl_db_sync;
dbp->truncate = __dbcl_db_truncate;
dbp->upgrade = __dbcl_db_upgrade;
dbp->verify = __dbcl_db_verify;
/*
* Set all the method specific functions to client funcs as well.
*/
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));
}
#endif

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_open.c,v 11.240 2004/09/22 20:53:19 margo Exp $
* $Id: db_open.c,v 12.13 2005/10/12 17:45:53 bostic Exp $
*/
#include "db_config.h"
@ -42,12 +42,15 @@
* 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
* 3. It can be called to open an in-memory database (name == NULL;
* subname = name).
* 4. 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
* 5. 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).
* 6. It can be called during recovery to open an in-memory database.
*
* PUBLIC: int __db_open __P((DB *, DB_TXN *,
* PUBLIC: const char *, const char *, DBTYPE, u_int32_t, int, db_pgno_t));
@ -85,8 +88,8 @@ __db_open(dbp, txn, fname, dname, type, flags, mode, meta_pgno)
/* Convert any DB->open flags. */
if (LF_ISSET(DB_RDONLY))
F_SET(dbp, DB_AM_RDONLY);
if (LF_ISSET(DB_DIRTY_READ))
F_SET(dbp, DB_AM_DIRTY);
if (LF_ISSET(DB_READ_UNCOMMITTED))
F_SET(dbp, DB_AM_READ_UNCOMMITTED);
if (txn != NULL)
F_SET(dbp, DB_AM_TXN);
@ -95,43 +98,64 @@ __db_open(dbp, txn, fname, dname, type, flags, mode, meta_pgno)
dbp->type = type;
/*
* 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 both fname and subname are NULL, it's always a create, so make
* sure that we have both DB_CREATE and 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 (fname == NULL) {
F_SET(dbp, DB_AM_INMEM);
if (dname == NULL) {
if (!LF_ISSET(DB_CREATE)) {
__db_err(dbenv,
"DB_CREATE must be specified to create databases.");
return (ENOENT);
}
if (dbp->type == DB_UNKNOWN) {
__db_err(dbenv,
"DBTYPE of unknown without existing file");
return (EINVAL);
}
F_SET(dbp, DB_AM_INMEM);
F_SET(dbp, DB_AM_CREATED);
if (dbp->pgsize == 0)
dbp->pgsize = DB_DEF_IOSIZE;
if (dbp->type == DB_UNKNOWN) {
__db_err(dbenv,
"DBTYPE of unknown without existing file");
return (EINVAL);
}
if (dbp->pgsize == 0)
dbp->pgsize = DB_DEF_IOSIZE;
/*
* If the file is a temporary file and we're
* doing locking, then we have to create a
* unique file ID. We can't use our normal
* dev/inode pair (or whatever this OS uses
* in place of dev/inode pairs) because no
* backing file will be created until the
* mpool cache is filled forcing the buffers
* to disk. Grab a random locker ID to use
* as a file ID. The created ID must never
* match a potential real file ID -- we know
* it won't because real file IDs contain a
* time stamp after the dev/inode pair, and
* we're simply storing a 4-byte value.
* !!!
* 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 = __lock_id(dbenv,
(u_int32_t *)dbp->fileid, NULL)) != 0)
return (ret);
} else
MAKE_INMEM(dbp);
/*
* If the file is a temporary file and we're doing locking,
* then we have to create a unique file ID. We can't use our
* normal dev/inode pair (or whatever this OS uses in place of
* dev/inode pairs) because no backing file will be created
* until the mpool cache is filled forcing the buffers to disk.
* Grab a random locker ID to use as a file ID. The created
* ID must never match a potential real file ID -- we know it
* won't because real file IDs contain a time stamp after the
* dev/inode pair, and we're simply storing a 4-byte value.
*
* !!!
* Store the locker in the file id structure -- we can get it
* from there as necessary, and it saves having two copies.
* Normally we would do handle locking here, however, with
* in-memory files, we cannot do any database manipulation
* until the mpool is open, so it happens later.
*/
if (LOCKING_ON(dbenv) &&
(ret = __lock_id(dbenv, (u_int32_t *)dbp->fileid)) != 0)
return (ret);
} else if (dname == NULL && meta_pgno == PGNO_BASE_MD) {
/* Open/create the underlying file. Acquire locks. */
if ((ret =
@ -161,40 +185,46 @@ __db_open(dbp, txn, fname, dname, type, flags, mode, meta_pgno)
LF_SET(DB_TRUNCATE);
/* Set up the underlying environment. */
if ((ret = __db_dbenv_setup(dbp, txn, fname, id, flags)) != 0)
if ((ret = __db_dbenv_setup(dbp, txn, fname, dname, id, flags)) != 0)
return (ret);
/*
* Set the open flag. We use it to mean that the dbp has gone
* through mpf setup, including dbreg_register. Also, below,
* the underlying access method open functions may want to do
* things like acquire cursors, so the open flag has to be set
* before calling them.
*/
F_SET(dbp, DB_AM_OPEN_CALLED);
/*
* For unnamed files, we need to actually create the file now
* that the mpool is open.
*/
if (fname == NULL && (ret = __db_new_file(dbp, txn, NULL, NULL)) != 0)
return (ret);
/* For in-memory databases, we now need to open/create the database. */
if (F_ISSET(dbp, DB_AM_INMEM)) {
if (dname == NULL)
ret = __db_new_file(dbp, txn, NULL, NULL);
else {
id = TXN_INVALID;
if ((ret = __fop_file_setup(dbp,
txn, dname, mode, flags, &id)) == 0 &&
DBENV_LOGGING(dbenv) && !F_ISSET(dbp, DB_AM_RECOVER)
#if !defined(DEBUG_ROP)
&& !F_ISSET(dbp, DB_AM_RDONLY)
#endif
)
ret = __dbreg_log_id(dbp,
txn, dbp->log_filename->id, 1);
}
if (ret != 0)
goto err;
}
switch (dbp->type) {
case DB_BTREE:
ret = __bam_open(dbp, txn, fname, meta_pgno, flags);
break;
case DB_HASH:
ret = __ham_open(dbp, txn, fname, meta_pgno, flags);
break;
case DB_RECNO:
ret = __ram_open(dbp, txn, fname, meta_pgno, flags);
break;
case DB_QUEUE:
ret = __qam_open(dbp, txn, fname, meta_pgno, mode, flags);
break;
case DB_UNKNOWN:
return (__db_unknown_type(dbenv, "__db_dbopen", dbp->type));
case DB_BTREE:
ret = __bam_open(dbp, txn, fname, meta_pgno, flags);
break;
case DB_HASH:
ret = __ham_open(dbp, txn, fname, meta_pgno, flags);
break;
case DB_RECNO:
ret = __ram_open(dbp, txn, fname, meta_pgno, flags);
break;
case DB_QUEUE:
ret = __qam_open(
dbp, txn, fname, meta_pgno, mode, flags);
break;
case DB_UNKNOWN:
return (
__db_unknown_type(dbenv, "__db_dbopen", dbp->type));
}
if (ret != 0)
goto err;
@ -202,16 +232,16 @@ __db_open(dbp, txn, fname, dname, type, flags, mode, meta_pgno)
DB_TEST_RECOVERY(dbp, DB_TEST_POSTOPEN, ret, fname);
/*
* Unnamed files don't need handle locks, so we only have to check
* Temporary files don't need handle locks, so we only have to check
* for a handle lock downgrade or lockevent in the case of named
* files.
*/
if (!F_ISSET(dbp, DB_AM_RECOVER) &&
fname != NULL && LOCK_ISSET(dbp->handle_lock)) {
if (txn != NULL) {
if (!F_ISSET(dbp, DB_AM_RECOVER) && (fname != NULL || dname != NULL)
&& LOCK_ISSET(dbp->handle_lock)) {
if (txn != NULL)
ret = __txn_lockevent(dbenv,
txn, dbp, &dbp->handle_lock, dbp->lid);
} else if (LOCKING_ON(dbenv))
else if (LOCKING_ON(dbenv))
/* Trade write handle lock for read handle lock. */
ret = __lock_downgrade(dbenv,
&dbp->handle_lock, DB_LOCK_READ, 0);
@ -341,8 +371,8 @@ err: return (ret);
/*
* __db_chk_meta --
* Take a buffer containing a meta-data page and check it for a checksum
* (and verify the checksum if necessary) and possibly decrypt it.
* Take a buffer containing a meta-data page and check it for a valid LSN,
* checksum (and verify the checksum if necessary) and possibly decrypt it.
*
* Return 0 on success, >0 (errno) on error, -1 on checksum mismatch.
*
@ -355,11 +385,13 @@ __db_chk_meta(dbenv, dbp, meta, do_metachk)
DBMETA *meta;
int do_metachk;
{
DB_LSN cur_lsn, swap_lsn;
int is_hmac, ret, swapped;
u_int32_t orig_chk;
u_int32_t magic, orig_chk;
u_int8_t *chksum;
ret = 0;
swapped = 0;
if (FLD_ISSET(meta->metaflags, DBMETA_CHKSUM)) {
if (dbp != NULL)
@ -399,6 +431,56 @@ chk_retry: if ((ret = __db_check_chksum(dbenv,
#ifdef HAVE_CRYPTO
ret = __crypto_decrypt_meta(dbenv, dbp, (u_int8_t *)meta, do_metachk);
#endif
/* Now that we're decrypted, we can check LSN. */
if (LOGGING_ON(dbenv)) {
/*
* This gets called both before and after swapping, so we
* need to check ourselves. If we already swapped it above,
* we'll know that here.
*/
swap_lsn = meta->lsn;
magic = meta->magic;
lsn_retry:
if (swapped) {
M_32_SWAP(swap_lsn.file);
M_32_SWAP(swap_lsn.offset);
M_32_SWAP(magic);
}
switch (magic) {
case DB_BTREEMAGIC:
case DB_HASHMAGIC:
case DB_QAMMAGIC:
case DB_RENAMEMAGIC:
break;
default:
if (swapped)
return (EINVAL);
swapped = 1;
goto lsn_retry;
}
if (!IS_REP_CLIENT(dbenv) &&
!IS_NOT_LOGGED_LSN(swap_lsn) && !IS_ZERO_LSN(swap_lsn)) {
/* Need to do check. */
if ((ret = __log_current_lsn(dbenv,
&cur_lsn, NULL, NULL)) != 0)
return (ret);
if (log_compare(&swap_lsn, &cur_lsn) > 0) {
__db_err(dbenv,
"file %s (meta pgno = %lu) has LSN [%lu][%lu].",
dbp->fname == NULL
? "unknown" : dbp->fname,
(u_long)dbp->meta_pgno,
(u_long)swap_lsn.file,
(u_long)swap_lsn.offset);
__db_err(dbenv, "end of log is [%lu][%lu]",
(u_long)cur_lsn.file,
(u_long)cur_lsn.offset);
return (EINVAL);
}
}
}
return (ret);
}
@ -433,7 +515,7 @@ __db_meta_setup(dbenv, dbp, name, meta, oflags, do_metachk)
* we don't consider it an error, for example, if the user set
* an expected byte order and the found file doesn't match it.
*/
F_CLR(dbp, DB_AM_SWAP);
F_CLR(dbp, DB_AM_SWAP | DB_AM_IN_RENAME);
magic = meta->magic;
swap_retry:

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -39,7 +39,7 @@
* 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 $
* $Id: db_overflow.c,v 12.3 2005/08/08 17:30:51 bostic Exp $
*/
#include "db_config.h"
@ -241,8 +241,6 @@ __db_poff(dbc, dbt, pgnop)
LSN(lastp) = new_lsn;
LSN(pagep) = new_lsn;
P_INIT(pagep, dbp->pgsize,
PGNO(pagep), PGNO_INVALID, PGNO_INVALID, 0, P_OVERFLOW);
OV_LEN(pagep) = pagespace;
OV_REF(pagep) = 1;
memcpy((u_int8_t *)pagep + P_OVERHEAD(dbp), p, pagespace);
@ -288,7 +286,7 @@ __db_ovref(dbc, pgno, adjust)
mpf = dbp->mpf;
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
return (__db_pgerr(dbp, pgno, ret));
return (ret);
if (DBC_LOGGING(dbc)) {
if ((ret = __db_ovref_log(dbp,
@ -327,7 +325,7 @@ __db_doff(dbc, pgno)
do {
if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0)
return (__db_pgerr(dbp, pgno, ret));
return (ret);
DB_ASSERT(TYPE(pagep) == P_OVERFLOW);
/*

View file

@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*/
/*
@ -39,7 +39,7 @@
* 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 $
* $Id: db_ovfl_vrfy.c,v 12.1 2005/06/16 20:21:13 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_pr.c,v 11.121 2004/10/28 14:48:43 bostic Exp $
* $Id: db_pr.c,v 12.17 2005/11/08 03:13:30 bostic Exp $
*/
#include "db_config.h"
@ -35,9 +35,10 @@
void
__db_loadme()
{
u_int32_t id;
pid_t pid;
db_threadid_t tid;
__os_id(&id);
__os_id(NULL, &pid, &tid);
}
#ifdef HAVE_STATISTICS
@ -106,38 +107,37 @@ __db_dumptree(dbp, op, name)
}
static const FN __db_flags_fn[] = {
{ DB_AM_CHKSUM, "checksumming" },
{ DB_AM_CL_WRITER, "client replica writer" },
{ DB_AM_COMPENSATE, "created by compensating transaction" },
{ DB_AM_CREATED, "database created" },
{ DB_AM_CREATED_MSTR, "encompassing file created" },
{ DB_AM_DBM_ERROR, "dbm/ndbm error" },
{ DB_AM_DELIMITER, "variable length" },
{ DB_AM_DIRTY, "dirty reads" },
{ DB_AM_DISCARD, "discard cached pages" },
{ DB_AM_DUP, "duplicates" },
{ DB_AM_DUPSORT, "sorted duplicates" },
{ DB_AM_ENCRYPT, "encrypted" },
{ DB_AM_FIXEDLEN, "fixed-length records" },
{ DB_AM_INMEM, "in-memory" },
{ DB_AM_IN_RENAME, "file is being renamed" },
{ DB_AM_NOT_DURABLE, "changes not logged" },
{ DB_AM_OPEN_CALLED, "open called" },
{ DB_AM_PAD, "pad value" },
{ DB_AM_PGDEF, "default page size" },
{ DB_AM_RDONLY, "read-only" },
{ DB_AM_RECNUM, "Btree record numbers" },
{ DB_AM_RECOVER, "opened for recovery" },
{ DB_AM_RENUMBER, "renumber" },
{ DB_AM_REPLICATION, "replication file" },
{ DB_AM_REVSPLITOFF, "no reverse splits" },
{ DB_AM_SECONDARY, "secondary" },
{ DB_AM_SNAPSHOT, "load on open" },
{ DB_AM_SUBDB, "subdatabases" },
{ DB_AM_SWAP, "needswap" },
{ DB_AM_TXN, "transactional" },
{ DB_AM_VERIFYING, "verifier" },
{ 0, NULL }
{ DB_AM_CHKSUM, "checksumming" },
{ DB_AM_CL_WRITER, "client replica writer" },
{ DB_AM_COMPENSATE, "created by compensating transaction" },
{ DB_AM_CREATED, "database created" },
{ DB_AM_CREATED_MSTR, "encompassing file created" },
{ DB_AM_DBM_ERROR, "dbm/ndbm error" },
{ DB_AM_DELIMITER, "variable length" },
{ DB_AM_DISCARD, "discard cached pages" },
{ DB_AM_DUP, "duplicates" },
{ DB_AM_DUPSORT, "sorted duplicates" },
{ DB_AM_ENCRYPT, "encrypted" },
{ DB_AM_FIXEDLEN, "fixed-length records" },
{ DB_AM_INMEM, "in-memory" },
{ DB_AM_IN_RENAME, "file is being renamed" },
{ DB_AM_NOT_DURABLE, "changes not logged" },
{ DB_AM_OPEN_CALLED, "open called" },
{ DB_AM_PAD, "pad value" },
{ DB_AM_PGDEF, "default page size" },
{ DB_AM_RDONLY, "read-only" },
{ DB_AM_READ_UNCOMMITTED, "read-uncommitted" },
{ DB_AM_RECNUM, "Btree record numbers" },
{ DB_AM_RECOVER, "opened for recovery" },
{ DB_AM_RENUMBER, "renumber" },
{ DB_AM_REVSPLITOFF, "no reverse splits" },
{ DB_AM_SECONDARY, "secondary" },
{ DB_AM_SNAPSHOT, "load on open" },
{ DB_AM_SUBDB, "subdatabases" },
{ DB_AM_SWAP, "needswap" },
{ DB_AM_TXN, "transactional" },
{ DB_AM_VERIFYING, "verifier" },
{ 0, NULL }
};
/*
@ -182,8 +182,7 @@ __db_prdb(dbp, flags)
bt = dbp->bt_internal;
__db_msg(dbenv, "bt_meta: %lu bt_root: %lu",
(u_long)bt->bt_meta, (u_long)bt->bt_root);
__db_msg(dbenv, "bt_maxkey: %lu bt_minkey: %lu",
(u_long)bt->bt_maxkey, (u_long)bt->bt_minkey);
__db_msg(dbenv, "bt_minkey: %lu", (u_long)bt->bt_minkey);
if (!LF_ISSET(DB_PR_RECOVERYTEST))
__db_msg(dbenv, "bt_compare: %#lx bt_prefix: %#lx",
P_TO_ULONG(bt->bt_compare),
@ -246,7 +245,8 @@ __db_prtree(dbp, flags)
* Find out the page number of the last page in the database, then
* dump each page.
*/
__memp_last_pgno(mpf, &last);
if ((ret = __memp_last_pgno(mpf, &last)) != 0)
return (ret);
for (i = 0; i <= last; ++i) {
if ((ret = __memp_fget(mpf, &i, 0, &h)) != 0)
return (ret);
@ -362,8 +362,7 @@ __db_bmeta(dbp, h, flags)
__db_meta(dbp, (DBMETA *)h, fn, flags);
__db_msg(dbenv, "\tmaxkey: %lu minkey: %lu",
(u_long)h->maxkey, (u_long)h->minkey);
__db_msg(dbenv, "\tminkey: %lu", (u_long)h->minkey);
if (dbp->type == DB_RECNO)
__db_msg(dbenv, "\tre_len: %#lx re_pad: %#lx",
(u_long)h->re_len, (u_long)h->re_pad);
@ -518,19 +517,29 @@ __db_prpage(dbp, h, flags)
pagesize = (u_int32_t)dbp->mpf->mfp->stat.st_pagesize;
/* Page number, page type. */
__db_msgadd(dbenv, &mb, "page %lu: %s level: %lu",
(u_long)h->pgno, s, (u_long)h->level);
__db_msgadd(dbenv, &mb, "page %lu: %s:", (u_long)h->pgno, s);
/*
* LSNs on a metadata page will be different from the original after an
* abort, in some cases. Don't display them if we're testing recovery.
*/
if (!LF_ISSET(DB_PR_RECOVERYTEST) ||
(TYPE(h) != P_BTREEMETA && TYPE(h) != P_HASHMETA &&
TYPE(h) != P_QAMMETA && TYPE(h) != P_QAMDATA))
__db_msgadd(dbenv, &mb, " LSN [%lu][%lu]:",
(u_long)LSN(h).file, (u_long)LSN(h).offset);
/*
* Page level (only applicable for Btree/Recno, but we always display
* it, for no particular reason.
*/
__db_msgadd(dbenv, &mb, " level %lu", (u_long)h->level);
/* Record count. */
if (TYPE(h) == P_IBTREE ||
TYPE(h) == P_IRECNO || (TYPE(h) == P_LRECNO &&
h->pgno == ((BTREE *)dbp->bt_internal)->bt_root))
__db_msgadd(dbenv, &mb, " records: %lu", (u_long)RE_NREC(h));
/* LSN. */
if (!LF_ISSET(DB_PR_RECOVERYTEST))
__db_msgadd(dbenv, &mb, " (lsn.file: %lu lsn.offset: %lu)",
(u_long)LSN(h).file, (u_long)LSN(h).offset);
DB_MSGBUF_FLUSH(dbenv, &mb);
switch (TYPE(h)) {
@ -564,11 +573,6 @@ __db_prpage(dbp, h, flags)
break;
}
/* LSN. */
if (LF_ISSET(DB_PR_RECOVERYTEST))
__db_msg(dbenv, " (lsn.file: %lu lsn.offset: %lu)",
(u_long)LSN(h).file, (u_long)LSN(h).offset);
s = "\t";
if (TYPE(h) != P_IBTREE && TYPE(h) != P_IRECNO) {
__db_msgadd(dbenv, &mb, "%sprev: %4lu next: %4lu",
@ -680,7 +684,7 @@ __db_prpage(dbp, h, flags)
case P_IBTREE:
bi = sp;
__db_msgadd(dbenv, &mb,
"count: %4lu pgno: %4lu type: %4lu",
"count: %4lu pgno: %4lu type: %lu ",
(u_long)bi->nrecs, (u_long)bi->pgno,
(u_long)bi->type);
switch (B_TYPE(bi->type)) {
@ -867,8 +871,8 @@ __db_lockmode_to_string(mode)
return ("Intent shared/read");
case DB_LOCK_IWR:
return ("Intent to read/write");
case DB_LOCK_DIRTY:
return ("Dirty read");
case DB_LOCK_READ_UNCOMMITTED:
return ("Read uncommitted");
case DB_LOCK_WWRITE:
return ("Was written");
default:
@ -988,25 +992,31 @@ __db_dump_pp(dbp, subname, callback, handle, pflag, keyflag)
int pflag, keyflag;
{
DB_ENV *dbenv;
int handle_check, ret;
DB_THREAD_INFO *ip;
int handle_check, ret, t_ret;
dbenv = dbp->dbenv;
PANIC_CHECK(dbenv);
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->dump");
ENV_ENTER(dbenv, ip);
/* Check for replication block. */
handle_check = IS_REPLICATED(dbenv, dbp);
if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 1)) != 0)
return (ret);
handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 1)) != 0) {
handle_check = 0;
goto err;
}
ret = __db_dump(dbp, subname, callback, handle, pflag, keyflag);
/* Release replication block. */
if (handle_check)
__env_db_rep_exit(dbenv);
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
return (0);
err: ENV_LEAVE(dbenv, ip);
return (ret);
}
/*
@ -1088,8 +1098,11 @@ retry: while ((ret =
data.ulen = data.size;
goto retry;
}
if (ret == DB_NOTFOUND)
ret = 0;
(void)__db_prfooter(handle, callback);
if ((t_ret = __db_prfooter(handle, callback)) != 0 && ret == 0)
ret = t_ret;
err: if ((t_ret = __db_c_close(dbcp)) != 0 && ret == 0)
ret = t_ret;
@ -1310,39 +1323,28 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
case DB_BTREE:
if ((ret = callback(handle, "type=btree\n")) != 0)
goto err;
if (using_vdp) {
if (F_ISSET(pip, VRFY_HAS_RECNUMS))
if ((ret =
callback(handle, "recnum=1\n")) != 0)
goto err;
if (pip->bt_maxkey != 0) {
snprintf(buf, buflen,
"bt_maxkey=%lu\n", (u_long)pip->bt_maxkey);
if ((ret = callback(handle, buf)) != 0)
goto err;
}
if (pip->bt_minkey != 0 &&
pip->bt_minkey != DEFMINKEYPAGE) {
snprintf(buf, buflen,
"bt_minkey=%lu\n", (u_long)pip->bt_minkey);
if ((ret = callback(handle, buf)) != 0)
goto err;
}
break;
}
if ((ret = __db_get_flags(dbp, &flags)) != 0) {
__db_err(dbenv, "DB->get_flags: %s", db_strerror(ret));
goto err;
}
if (F_ISSET(dbp, DB_AM_RECNUM))
if ((ret = callback(handle, "recnum=1\n")) != 0)
if (using_vdp)
tmp_int = F_ISSET(pip, VRFY_HAS_RECNUMS) ? 1 : 0;
else {
if ((ret = __db_get_flags(dbp, &flags)) != 0) {
__db_err(dbenv,
"DB->get_flags: %s", db_strerror(ret));
goto err;
if ((ret = __bam_get_bt_minkey(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv,
"DB->get_bt_minkey: %s", db_strerror(ret));
goto err;
}
tmp_int = F_ISSET(dbp, DB_AM_RECNUM) ? 1 : 0;
}
if (tmp_int && (ret = callback(handle, "recnum=1\n")) != 0)
goto err;
if (using_vdp)
tmp_u_int32 = pip->bt_minkey;
else
if ((ret =
__bam_get_bt_minkey(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv,
"DB->get_bt_minkey: %s", db_strerror(ret));
goto err;
}
if (tmp_u_int32 != 0 && tmp_u_int32 != DEFMINKEYPAGE) {
snprintf(buf, buflen,
"bt_minkey=%lu\n", (u_long)tmp_u_int32);
@ -1354,38 +1356,35 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
#ifdef HAVE_HASH
if ((ret = callback(handle, "type=hash\n")) != 0)
goto err;
if (using_vdp) {
if (pip->h_ffactor != 0) {
snprintf(buf, buflen,
"h_ffactor=%lu\n", (u_long)pip->h_ffactor);
if ((ret = callback(handle, buf)) != 0)
goto err;
if (using_vdp)
tmp_u_int32 = pip->h_ffactor;
else
if ((ret =
__ham_get_h_ffactor(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv,
"DB->get_h_ffactor: %s", db_strerror(ret));
goto err;
}
if (pip->h_nelem != 0) {
snprintf(buf, buflen,
"h_nelem=%lu\n", (u_long)pip->h_nelem);
if ((ret = callback(handle, buf)) != 0)
goto err;
}
break;
}
if ((ret = __ham_get_h_ffactor(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv,
"DB->get_h_ffactor: %s", db_strerror(ret));
goto err;
}
if (tmp_u_int32 != 0) {
snprintf(buf, buflen,
"h_ffactor=%lu\n", (u_long)tmp_u_int32);
if ((ret = callback(handle, buf)) != 0)
goto err;
}
if ((ret = __ham_get_h_nelem(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv,
"DB->get_h_nelem: %s", db_strerror(ret));
goto err;
}
if (tmp_u_int32 != 0) {
if (using_vdp)
tmp_u_int32 = pip->h_nelem;
else
if ((ret = __ham_get_h_nelem(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv,
"DB->get_h_nelem: %s", db_strerror(ret));
goto err;
}
/*
* Hash databases have an h_nelem field of 0 or 1, neither
* of those values is interesting.
*/
if (tmp_u_int32 > 1) {
snprintf(buf, buflen,
"h_nelem=%lu\n", (u_long)tmp_u_int32);
if ((ret = callback(handle, buf)) != 0)
@ -1400,36 +1399,41 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
#ifdef HAVE_QUEUE
if ((ret = callback(handle, "type=queue\n")) != 0)
goto err;
if (vdp != NULL) {
snprintf(buf,
buflen, "re_len=%lu\n", (u_long)vdp->re_len);
if ((ret = callback(handle, buf)) != 0)
if (using_vdp)
tmp_u_int32 = vdp->re_len;
else
if ((ret = __ram_get_re_len(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv,
"DB->get_re_len: %s", db_strerror(ret));
goto err;
break;
}
if ((ret = __ram_get_re_len(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv,
"DB->get_re_len: %s", db_strerror(ret));
goto err;
}
}
snprintf(buf, buflen, "re_len=%lu\n", (u_long)tmp_u_int32);
if ((ret = callback(handle, buf)) != 0)
goto err;
if ((ret = __ram_get_re_pad(dbp, &tmp_int)) != 0) {
__db_err(dbenv,
"DB->get_re_pad: %s", db_strerror(ret));
goto err;
}
if (using_vdp)
tmp_int = (int)vdp->re_pad;
else
if ((ret = __ram_get_re_pad(dbp, &tmp_int)) != 0) {
__db_err(dbenv,
"DB->get_re_pad: %s", db_strerror(ret));
goto err;
}
if (tmp_int != 0 && tmp_int != ' ') {
snprintf(buf, buflen, "re_pad=%#x\n", tmp_int);
if ((ret = callback(handle, buf)) != 0)
goto err;
}
if ((ret = __qam_get_extentsize(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv,
"DB->get_q_extentsize: %s", db_strerror(ret));
goto err;
}
if (using_vdp)
tmp_u_int32 = vdp->page_ext;
else
if ((ret =
__qam_get_extentsize(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv, "DB->get_q_extentsize: %s",
db_strerror(ret));
goto err;
}
if (tmp_u_int32 != 0) {
snprintf(buf, buflen,
"extentsize=%lu\n", (u_long)tmp_u_int32);
@ -1444,38 +1448,42 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
case DB_RECNO:
if ((ret = callback(handle, "type=recno\n")) != 0)
goto err;
if (using_vdp) {
if (F_ISSET(pip, VRFY_IS_RRECNO))
if (using_vdp)
tmp_int = F_ISSET(pip, VRFY_IS_RRECNO) ? 1 : 0;
else
tmp_int = F_ISSET(dbp, DB_AM_RENUMBER) ? 1 : 0;
if (tmp_int != 0 &&
(ret = callback(handle, "renumber=1\n")) != 0)
goto err;
if (using_vdp)
tmp_int = F_ISSET(pip, VRFY_IS_FIXEDLEN) ? 1 : 0;
else
tmp_int = F_ISSET(dbp, DB_AM_FIXEDLEN) ? 1 : 0;
if (tmp_int) {
if (using_vdp)
tmp_u_int32 = pip->re_len;
else
if ((ret =
callback(handle, "renumber=1\n")) != 0)
__ram_get_re_len(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv, "DB->get_re_len: %s",
db_strerror(ret));
goto err;
if (pip->re_len > 0) {
snprintf(buf, buflen,
"re_len=%lu\n", (u_long)pip->re_len);
if ((ret = callback(handle, buf)) != 0)
goto err;
}
break;
}
if (F_ISSET(dbp, DB_AM_RENUMBER))
if ((ret = callback(handle, "renumber=1\n")) != 0)
goto err;
if (F_ISSET(dbp, DB_AM_FIXEDLEN)) {
if ((ret = __ram_get_re_len(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv,
"DB->get_re_len: %s", db_strerror(ret));
goto err;
}
}
snprintf(buf, buflen,
"re_len=%lu\n", (u_long)tmp_u_int32);
if ((ret = callback(handle, buf)) != 0)
goto err;
if ((ret = __ram_get_re_pad(dbp, &tmp_int)) != 0) {
__db_err(dbenv,
"DB->get_re_pad: %s", db_strerror(ret));
goto err;
}
if (using_vdp)
tmp_int = (int)pip->re_pad;
else
if ((ret =
__ram_get_re_pad(dbp, &tmp_int)) != 0) {
__db_err(dbenv, "DB->get_re_pad: %s",
db_strerror(ret));
goto err;
}
if (tmp_int != 0 && tmp_int != ' ') {
snprintf(buf,
buflen, "re_pad=%#x\n", (u_int)tmp_int);
@ -1493,13 +1501,21 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
}
if (using_vdp) {
if (F_ISSET(pip, VRFY_HAS_CHKSUM))
if ((ret = callback(handle, "chksum=1\n")) != 0)
goto err;
if (F_ISSET(pip, VRFY_HAS_DUPS))
if ((ret = callback(handle, "duplicates=1\n")) != 0)
goto err;
if (F_ISSET(pip, VRFY_HAS_DUPSORT))
if ((ret = callback(handle, "dupsort=1\n")) != 0)
goto err;
/* We should handle page size. XXX */
/*
* !!!
* We don't know if the page size was the default if we're
* salvaging. It doesn't seem that interesting to have, so
* we ignore it for now.
*/
} else {
if (F_ISSET(dbp, DB_AM_CHKSUM))
if ((ret = callback(handle, "chksum=1\n")) != 0)

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_rec.c,v 11.61 2004/10/21 14:39:58 bostic Exp $
* $Id: db_rec.c,v 12.12 2005/10/27 01:03:01 bostic Exp $
*/
#include "db_config.h"
@ -51,13 +51,13 @@ __db_addrem_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_addrem_print);
REC_INTRO(__db_addrem_read, 1);
REC_INTRO(__db_addrem_read, 1, 1);
REC_FGET(mpf, argp->pgno, &pagep, done);
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->pagelsn);
change = 0;
if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_DUP) ||
(cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_DUP)) {
@ -121,7 +121,7 @@ __db_big_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_big_print);
REC_INTRO(__db_big_read, 1);
REC_INTRO(__db_big_read, 1, 0);
REC_FGET(mpf, argp->pgno, &pagep, ppage);
@ -133,7 +133,7 @@ __db_big_recover(dbenv, dbtp, lsnp, op, info)
*/
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->pagelsn);
change = 0;
if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) ||
(cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_BIG)) {
@ -176,7 +176,7 @@ ppage: if (argp->prev_pgno != PGNO_INVALID) {
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->prevlsn);
if (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) {
/* Redo add, undo delete. */
@ -202,7 +202,7 @@ npage: if (argp->next_pgno != PGNO_INVALID) {
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->nextlsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->nextlsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->nextlsn);
if (cmp_p == 0 && DB_REDO(op)) {
PREV_PGNO(pagep) = PGNO_INVALID;
change = DB_MPOOL_DIRTY;
@ -250,13 +250,13 @@ __db_ovref_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_ovref_print);
REC_INTRO(__db_ovref_read, 1);
REC_INTRO(__db_ovref_read, 1, 0);
REC_FGET(mpf, argp->pgno, &pagep, done);
modified = 0;
cmp = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp, &LSN(pagep), &argp->lsn);
CHECK_LSN(dbenv, op, cmp, &LSN(pagep), &argp->lsn);
if (cmp == 0 && DB_REDO(op)) {
/* Need to redo update described. */
OV_REF(pagep) += argp->adjust;
@ -339,13 +339,13 @@ __db_noop_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_noop_print);
REC_INTRO(__db_noop_read, 0);
REC_INTRO(__db_noop_read, 0, 0);
REC_FGET(mpf, argp->pgno, &pagep, done);
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->prevlsn);
change = 0;
if (cmp_p == 0 && DB_REDO(op)) {
LSN(pagep) = *lsnp;
@ -391,7 +391,7 @@ __db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL;
created = meta_modified = modified = 0;
REC_PRINT(__db_pg_alloc_print);
REC_INTRO(__db_pg_alloc_read, 0);
REC_INTRO(__db_pg_alloc_read, 0, 0);
/*
* Fix up the metadata page. If we're redoing the operation, we have
@ -410,7 +410,7 @@ __db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
}
cmp_n = log_compare(lsnp, &LSN(meta));
cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(meta), &argp->meta_lsn);
if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */
LSN(meta) = *lsnp;
@ -439,6 +439,29 @@ __db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
meta_modified = 1;
}
#ifdef HAVE_FTRUNCATE
/*
* Check to see if we are keeping a sorted
* freelist, if so put this back in the in
* memory list. It must be the first element.
*/
if (op == DB_TXN_ABORT && !IS_ZERO_LSN(argp->page_lsn)) {
db_pgno_t *list;
u_int32_t nelem;
if ((ret = __memp_get_freelist(mpf, &nelem, &list)) != 0)
goto out;
if (list != NULL) {
if ((ret =
__memp_extend_freelist(mpf, nelem + 1, &list)) != 0)
goto out;
if (nelem != 0)
memmove(list + 1, list, nelem * sizeof(list));
*list = argp->pgno;
}
}
#endif
/*
* Fix up the allocated page. If the page does not exist
* and we can truncate it then don't create it.
@ -485,7 +508,7 @@ __db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
(IS_ZERO_LSN(argp->page_lsn) && IS_INIT_LSN(LSN(pagep))))
cmp_p = 0;
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->page_lsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->page_lsn);
/*
* Another special case we have to handle is if we ended up with a
* page of all 0's which can happen if we abort between allocating a
@ -594,26 +617,30 @@ __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, data)
{
DBMETA *meta;
DB_LSN copy_lsn;
PAGE *pagep;
db_pgno_t pgno;
int cmp_n, cmp_p, meta_modified, modified, ret;
PAGE *pagep, *prevp;
int cmp_n, cmp_p, is_meta, meta_modified, modified, ret;
meta = NULL;
pagep = NULL;
prevp = NULL;
meta_modified = modified = 0;
/*
* Get the metapage first so we can see where we are.
* Get the "metapage". This will either be the metapage
* or the previous page in the free list if we are doing
* sorted allocations. If its a previous page then
* we will not be truncating.
*/
pgno = PGNO_BASE_MD;
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0) {
/* The metadata page must always exist. */
ret = __db_pgerr(file_dbp, pgno, ret);
goto out;
}
is_meta = argp->meta_pgno == PGNO_BASE_MD;
REC_FGET(mpf, argp->meta_pgno, &meta, check_meta);
if (argp->meta_pgno != PGNO_BASE_MD)
prevp = (PAGE *)meta;
cmp_n = log_compare(lsnp, &LSN(meta));
cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(meta), &argp->meta_lsn);
/*
* Fix up the metadata page. If we're redoing or undoing the operation
@ -627,30 +654,45 @@ __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, data)
*/
if (argp->pgno == argp->last_pgno)
meta->last_pgno = argp->pgno - 1;
else
else if (prevp == NULL)
meta->free = argp->pgno;
else
NEXT_PGNO(prevp) = argp->pgno;
#else
/* Need to redo the deallocation. */
meta->free = argp->pgno;
if (prevp == NULL)
meta->free = argp->pgno;
else
NEXT_PGNO(prevp) = argp->pgno;
/*
* If this was a compensating transaction and
* we are a replica, then we never executed the
* original allocation which incremented meta->free.
*/
if (meta->last_pgno < meta->free)
if (prevp == NULL && meta->last_pgno < meta->free)
meta->last_pgno = meta->free;
#endif
LSN(meta) = *lsnp;
meta_modified = 1;
} else if (cmp_n == 0 && DB_UNDO(op)) {
/* Need to undo the deallocation. */
meta->free = argp->next;
if (prevp == NULL)
meta->free = argp->next;
else
NEXT_PGNO(prevp) = argp->next;
LSN(meta) = argp->meta_lsn;
if (meta->last_pgno < argp->pgno)
if (prevp == NULL && meta->last_pgno < argp->pgno)
meta->last_pgno = argp->pgno;
meta_modified = 1;
}
check_meta:
if (ret != 0 && is_meta) {
/* The metadata page must always exist. */
ret = __db_pgerr(file_dbp, argp->meta_pgno, ret);
goto out;
}
/*
* Get the freed page. If we support truncate then don't
* create the page if we are going to free it. If we're
@ -661,7 +703,7 @@ __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, data)
* and roll it back.
*/
#ifdef HAVE_FTRUNCATE
if (DB_REDO(op) || meta->last_pgno < argp->pgno) {
if (DB_REDO(op) || (is_meta && meta->last_pgno < argp->pgno)) {
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (ret == DB_PAGE_NOTFOUND)
goto done;
@ -687,14 +729,19 @@ __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, data)
cmp_p = 0;
#endif
CHECK_LSN(op, cmp_p, &LSN(pagep), &copy_lsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &copy_lsn);
if (DB_REDO(op) &&
(cmp_p == 0 ||
(IS_ZERO_LSN(copy_lsn) &&
log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
/* Need to redo the deallocation. */
#ifdef HAVE_FTRUNCATE
if (meta->last_pgno <= argp->pgno) {
/*
* The page can be truncated if it was truncated at runtime
* and the current metapage reflects the truncation.
*/
if (is_meta && meta->last_pgno <= argp->pgno &&
argp->last_pgno <= argp->pgno) {
if ((ret =
__memp_fput(mpf, pagep, DB_MPOOL_DISCARD)) != 0)
goto out;
@ -720,7 +767,7 @@ __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, data)
/* Need to reallocate the page. */
memcpy(pagep, argp->header.data, argp->header.size);
if (data)
memcpy((u_int8_t*)pagep + pagep->hf_offset,
memcpy((u_int8_t*)pagep + HOFFSET(pagep),
argp->data.data, argp->data.size);
modified = 1;
@ -731,9 +778,38 @@ __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, data)
pagep = NULL;
#ifdef HAVE_FTRUNCATE
/*
* If we are keeping an in memory free list remove this
* element from the list.
*/
if (op == DB_TXN_ABORT && argp->pgno != argp->last_pgno) {
db_pgno_t *lp;
u_int32_t nelem, pos;
if ((ret = __memp_get_freelist(mpf, &nelem, &lp)) != 0)
goto out;
if (lp != NULL) {
pos = 0;
if (!is_meta && nelem != 0) {
__db_freelist_pos(argp->pgno, lp, nelem, &pos);
DB_ASSERT(argp->pgno == lp[pos]);
DB_ASSERT(argp->meta_pgno == lp[pos - 1]);
}
if (nelem != 0 && pos != nelem)
memmove(&lp[pos], &lp[pos + 1],
(nelem - pos) * sizeof(*lp));
/* Shrink the list */
if ((ret =
__memp_extend_freelist(mpf, nelem - 1, &lp)) != 0)
goto out;
}
}
done:
#endif
if ((ret = __memp_fput(mpf,
if (meta != NULL && (ret = __memp_fput(mpf,
meta, meta_modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
meta = NULL;
@ -771,7 +847,7 @@ __db_pg_free_recover(dbenv, dbtp, lsnp, op, info)
COMPQUIET(info, NULL);
REC_PRINT(__db_pg_free_print);
REC_INTRO(__db_pg_free_read, 1);
REC_INTRO(__db_pg_free_read, 1, 0);
ret = __db_pg_free_recover_int(dbenv,
(__db_pg_freedata_args *)argp, file_dbp, lsnp, mpf, op, 0);
@ -805,7 +881,7 @@ __db_pg_new_recover(dbenv, dbtp, lsnp, op, info)
int ret;
REC_PRINT(__db_pg_free_print);
REC_INTRO(__db_pg_free_read, 1);
REC_INTRO(__db_pg_free_read, 1, 0);
COMPQUIET(op, DB_TXN_ABORT);
if ((ret =
@ -848,7 +924,7 @@ __db_pg_freedata_recover(dbenv, dbtp, lsnp, op, info)
COMPQUIET(info, NULL);
REC_PRINT(__db_pg_freedata_print);
REC_INTRO(__db_pg_freedata_read, 1);
REC_INTRO(__db_pg_freedata_read, 1, 0);
ret = __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, 1);
@ -925,7 +1001,7 @@ __db_pg_prepare_recover(dbenv, dbtp, lsnp, op, info)
int ret, t_ret;
REC_PRINT(__db_pg_prepare_print);
REC_INTRO(__db_pg_prepare_read, 1);
REC_INTRO(__db_pg_prepare_read, 1, 0);
mpf = file_dbp->mpf;
@ -993,11 +1069,11 @@ __db_pg_init_recover(dbenv, dbtp, lsnp, op, info)
DB_LSN copy_lsn;
DB_MPOOLFILE *mpf;
PAGE *pagep;
int cmp_n, cmp_p, modified, ret;
int cmp_n, cmp_p, modified, ret, type;
COMPQUIET(info, NULL);
REC_PRINT(__db_pg_init_print);
REC_INTRO(__db_pg_init_read, 1);
REC_INTRO(__db_pg_init_read, 1, 0);
mpf = file_dbp->mpf;
REC_FGET(mpf, argp->pgno, &pagep, done);
@ -1006,18 +1082,22 @@ __db_pg_init_recover(dbenv, dbtp, lsnp, op, info)
(void)__ua_memcpy(&copy_lsn, &LSN(argp->header.data), sizeof(DB_LSN));
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &copy_lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &copy_lsn);
CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &copy_lsn);
if (cmp_p == 0 && DB_REDO(op)) {
if (TYPE(pagep) == P_HASH)
type = P_HASH;
else
type = file_dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE;
P_INIT(pagep, file_dbp->pgsize, PGNO(pagep), PGNO_INVALID,
PGNO_INVALID, TYPE(pagep) == P_HASH ? 0 : 1, TYPE(pagep));
PGNO_INVALID, TYPE(pagep) == P_HASH ? 0 : 1, type);
pagep->lsn = *lsnp;
modified = 1;
} else if (cmp_n == 0 && DB_UNDO(op)) {
/* Put the data back on the page. */
memcpy(pagep, argp->header.data, argp->header.size);
if (argp->data.size > 0)
memcpy((u_int8_t*)pagep + pagep->hf_offset,
memcpy((u_int8_t*)pagep + HOFFSET(pagep),
argp->data.data, argp->data.size);
modified = 1;
@ -1029,3 +1109,158 @@ done: *lsnp = argp->prev_lsn;
out:
REC_CLOSE;
}
/*
* __db_pg_sort_recover --
* Recovery function for pg_sort.
*
* PUBLIC: int __db_pg_sort_recover
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
int
__db_pg_sort_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
#ifdef HAVE_FTRUNCATE
__db_pg_sort_args *argp;
DB *file_dbp;
DBC *dbc;
DBMETA *meta;
DB_MPOOLFILE *mpf;
PAGE *pagep;
db_pgno_t pgno, *list;
u_int32_t felem, nelem;
struct pglist *pglist, *lp;
int modified, ret;
COMPQUIET(info, NULL);
REC_PRINT(__db_pg_sort_print);
REC_INTRO(__db_pg_sort_read, 1, 1);
modified = 0;
pglist = (struct pglist *) argp->list.data;
nelem = argp->list.size / sizeof(struct pglist);
if (DB_REDO(op)) {
pgno = argp->last_pgno;
if ((ret = __db_pg_truncate(mpf,
pglist, NULL, &nelem, &pgno, lsnp, 1)) != 0)
goto out;
if (argp->last_free != PGNO_INVALID) {
if ((ret = __memp_fget(mpf,
&argp->last_free, 0, &meta)) == 0) {
if (log_compare(&LSN(meta),
&argp->last_lsn) == 0) {
NEXT_PGNO(meta) = PGNO_INVALID;
LSN(meta) = *lsnp;
modified = 1;
}
if ((ret = __memp_fput(mpf,
meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
meta = NULL;
modified = 0;
} else if (ret != DB_PAGE_NOTFOUND)
goto out;
}
if ((ret = __memp_fget(mpf, &argp->meta, 0, &meta)) != 0)
goto out;
if (log_compare(&LSN(meta), &argp->meta_lsn) == 0) {
if (argp->last_free == PGNO_INVALID) {
if (nelem == 0)
meta->free = PGNO_INVALID;
else
meta->free = pglist->pgno;
}
meta->last_pgno = pgno;
LSN(meta) = *lsnp;
modified = 1;
}
} else {
/* Put the free list back in its original order. */
for (lp = pglist; lp < &pglist[nelem]; lp++) {
if ((ret = __memp_fget(mpf,
&lp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
if (IS_ZERO_LSN(LSN(pagep)) ||
log_compare(&LSN(pagep), lsnp) == 0) {
if (lp == &pglist[nelem - 1])
pgno = PGNO_INVALID;
else
pgno = lp[1].pgno;
P_INIT(pagep, file_dbp->pgsize,
lp->pgno, PGNO_INVALID, pgno, 0, P_INVALID);
LSN(pagep) = lp->lsn;
modified = 1;
}
if ((ret = __memp_fput(mpf,
pagep, modified ? DB_MPOOL_DIRTY: 0)) != 0)
goto out;
}
if (argp->last_free != PGNO_INVALID) {
if ((ret = __memp_fget(mpf,
&argp->last_free, 0, &meta)) == 0) {
if (log_compare(&LSN(meta), lsnp) == 0) {
NEXT_PGNO(meta) = pglist->pgno;
LSN(meta) = argp->last_lsn;
modified = 1;
}
if ((ret = __memp_fput(mpf,
meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
} else if (ret != DB_PAGE_NOTFOUND)
goto out;
modified = 0;
meta = NULL;
}
if ((ret = __memp_fget(mpf, &argp->meta, 0, &meta)) != 0)
goto out;
if (log_compare(&LSN(meta), lsnp) == 0) {
meta->last_pgno = argp->last_pgno;
if (argp->last_pgno == PGNO_INVALID)
meta->free = pglist->pgno;
LSN(meta) = argp->meta_lsn;
modified = 1;
}
}
if (op == DB_TXN_ABORT) {
if ((ret = __memp_get_freelist(mpf, &felem, &list)) != 0)
goto out;
if (list != NULL) {
DB_ASSERT(felem == 0 ||
argp->last_free == list[felem - 1]);
if ((ret = __memp_extend_freelist(
mpf, felem + nelem, &list)) != 0)
goto out;
for (lp = pglist; lp < &pglist[nelem]; lp++)
list[felem++] = lp->pgno;
}
}
if ((ret = __memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
done: *lsnp = argp->prev_lsn;
ret = 0;
out: REC_CLOSE;
#else
/*
* If HAVE_FTRUNCATE is not defined, we'll never see pg_sort records
* to recover.
*/
COMPQUIET(dbenv, NULL);
COMPQUIET(dbtp, NULL);
COMPQUIET(lsnp, NULL);
COMPQUIET(op, DB_TXN_ABORT);
COMPQUIET(info, NULL);
return (EINVAL);
#endif
}

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_reclaim.c,v 11.42 2004/06/10 04:46:44 ubell Exp $
* $Id: db_reclaim.c,v 12.2 2005/06/16 20:21:14 bostic Exp $
*/
#include "db_config.h"
@ -209,8 +209,8 @@ reinit: *putp = 0;
ldbt.data = p;
ldbt.size = P_OVERHEAD(dbp);
ldbt.size += p->entries * sizeof(db_indx_t);
ddbt.data = (u_int8_t *)p + p->hf_offset;
ddbt.size = dbp->pgsize - p->hf_offset;
ddbt.data = (u_int8_t *)p + HOFFSET(p);
ddbt.size = dbp->pgsize - HOFFSET(p);
if ((ret = __db_pg_init_log(dbp,
param->dbc->txn, &LSN(p), 0,
p->pgno, &ldbt, &ddbt)) != 0)

View file

@ -1,16 +1,18 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2004
* Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_remove.c,v 11.219 2004/09/16 17:55:17 margo Exp $
* $Id: db_remove.c,v 12.16 2005/10/27 01:25:53 mjc Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#include "db_int.h"
@ -20,55 +22,70 @@
#include "dbinc/hash.h"
#include "dbinc/db_shash.h"
#include "dbinc/lock.h"
#include "dbinc/mp.h"
#include "dbinc/txn.h"
static int __db_dbtxn_remove __P((DB *, DB_TXN *, const char *));
static int __db_dbtxn_remove __P((DB *, DB_TXN *, const char *, const char *));
static int __db_subdb_remove __P((DB *, DB_TXN *, const char *, const char *));
/*
* __dbenv_dbremove_pp
* __env_dbremove_pp
* DB_ENV->dbremove pre/post processing.
*
* PUBLIC: int __dbenv_dbremove_pp __P((DB_ENV *,
* PUBLIC: int __env_dbremove_pp __P((DB_ENV *,
* PUBLIC: DB_TXN *, const char *, const char *, u_int32_t));
*/
int
__dbenv_dbremove_pp(dbenv, txn, name, subdb, flags)
__env_dbremove_pp(dbenv, txn, name, subdb, flags)
DB_ENV *dbenv;
DB_TXN *txn;
const char *name, *subdb;
u_int32_t flags;
{
DB *dbp;
DB_THREAD_INFO *ip;
int handle_check, ret, t_ret, txn_local;
dbp = NULL;
txn_local = 0;
PANIC_CHECK(dbenv);
ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->dbremove");
/* Validate arguments. */
/*
* The actual argument checking is simple, do it inline, outside of
* the replication block.
*/
if ((ret = __db_fchk(dbenv, "DB->remove", flags, DB_AUTO_COMMIT)) != 0)
return (ret);
ENV_ENTER(dbenv, ip);
/* Check for replication block. */
handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check && (ret = __env_rep_enter(dbenv, 1)) != 0) {
handle_check = 0;
goto err;
}
/*
* Create local transaction as necessary, check for consistent
* transaction usage.
*/
if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
if (IS_ENV_AUTO_COMMIT(dbenv, txn, flags)) {
if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
return (ret);
goto err;
txn_local = 1;
} else {
if (txn != NULL && !TXN_ON(dbenv))
return (__db_not_txn_env(dbenv));
txn_local = 0;
}
} else
if (txn != NULL && !TXN_ON(dbenv)) {
ret = __db_not_txn_env(dbenv);
goto err;
}
LF_CLR(DB_AUTO_COMMIT);
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);
if (txn_local) {
@ -90,19 +107,27 @@ __dbenv_dbremove_pp(dbenv, txn, name, subdb, flags)
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);
err: if (txn_local && (t_ret =
__db_txn_auto_resolve(dbenv, txn, 0, ret)) != 0 && ret == 0)
ret = t_ret;
/*
* We never opened this dbp for real, so don't include a transaction
* handle, and use NOSYNC to avoid calling into mpool.
*
* !!!
* Note we're reversing the order of operations: we started the txn and
* then opened the DB handle; we're resolving the txn and then closing
* closing the DB handle -- it's safer.
*/
if ((t_ret = __db_close(dbp, NULL, DB_NOSYNC)) != 0 && ret == 0)
if (dbp != NULL &&
(t_ret = __db_close(dbp, NULL, DB_NOSYNC)) != 0 && ret == 0)
ret = t_ret;
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
ENV_LEAVE(dbenv, ip);
return (ret);
}
@ -120,7 +145,8 @@ __db_remove_pp(dbp, name, subdb, flags)
u_int32_t flags;
{
DB_ENV *dbenv;
int handle_check, ret;
DB_THREAD_INFO *ip;
int handle_check, ret, t_ret;
dbenv = dbp->dbenv;
@ -149,15 +175,21 @@ __db_remove_pp(dbp, name, subdb, flags)
if ((ret = __db_check_txn(dbp, NULL, DB_LOCK_INVALIDID, 0)) != 0)
return (ret);
handle_check = IS_REPLICATED(dbenv, dbp);
if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, 0)) != 0)
return (ret);
ENV_ENTER(dbenv, ip);
handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, 0)) != 0) {
handle_check = 0;
goto err;
}
/* Remove the file. */
ret = __db_remove(dbp, NULL, name, subdb, flags);
if (handle_check)
__env_db_rep_exit(dbenv);
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret);
}
@ -206,15 +238,23 @@ __db_remove_int(dbp, txn, name, subdb, flags)
dbenv = dbp->dbenv;
real_name = tmpname = NULL;
/* Handle subdatabase removes separately. */
if (subdb != NULL) {
if (name == NULL && subdb == NULL) {
__db_err(dbenv, "Remove on temporary files invalid");
ret = EINVAL;
goto err;
}
if (name == NULL) {
MAKE_INMEM(dbp);
real_name = (char *)subdb;
} else if (subdb != NULL) {
ret = __db_subdb_remove(dbp, txn, name, subdb);
goto err;
}
/* Handle transactional file removes separately. */
if (txn != NULL) {
ret = __db_dbtxn_remove(dbp, txn, name);
ret = __db_dbtxn_remove(dbp, txn, name, subdb);
goto err;
}
@ -223,15 +263,16 @@ __db_remove_int(dbp, txn, name, subdb, flags)
*
* Find the real name of the file.
*/
if ((ret = __db_appname(dbenv,
DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
if (!F_ISSET(dbp, DB_AM_INMEM) && (ret =
__db_appname(dbenv, DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
goto err;
/*
* If force is set, remove the temporary file. Ignore errors because
* the backup file might not exist.
* If this is a file and force is set, remove the temporary file, which
* may have been left around. Ignore errors because the temporary file
* might not exist.
*/
if (LF_ISSET(DB_FORCE) &&
if (!F_ISSET(dbp, DB_AM_INMEM) && LF_ISSET(DB_FORCE) &&
(ret = __db_backup_name(dbenv, real_name, NULL, &tmpname)) == 0)
(void)__os_unlink(dbenv, tmpname);
@ -242,10 +283,12 @@ __db_remove_int(dbp, txn, name, subdb, flags)
(ret = dbp->db_am_remove(dbp, NULL, name, subdb)) != 0)
goto err;
ret = __fop_remove(dbenv, NULL, dbp->fileid, name, DB_APP_DATA,
ret = F_ISSET(dbp, DB_AM_INMEM) ?
__db_inmem_remove(dbp, NULL, real_name) :
__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 (!F_ISSET(dbp, DB_AM_INMEM) && real_name != NULL)
__os_free(dbenv, real_name);
if (tmpname != NULL)
__os_free(dbenv, tmpname);
@ -253,6 +296,78 @@ err: if (real_name != NULL)
return (ret);
}
/*
* __db_inmem_remove --
* Removal of a named in-memory database.
* PUBLIC: int __db_inmem_remove __P((DB *, DB_TXN *, const char *));
*/
int
__db_inmem_remove(dbp, txn, name)
DB *dbp;
DB_TXN *txn;
const char *name;
{
DB_ENV *dbenv;
DB_LSN lsn;
DBT fid_dbt, name_dbt;
u_int32_t locker;
int ret;
dbenv = dbp->dbenv;
locker = DB_LOCK_INVALIDID;
DB_ASSERT(name != NULL);
/* This had better exist if we are trying to do a remove. */
(void)__memp_set_flags(dbp->mpf, DB_MPOOL_NOFILE, 1);
if ((ret = __memp_fopen(dbp->mpf, NULL, name, 0, 0, 0)) != 0)
return (ret);
if ((ret = __memp_get_fileid(dbp->mpf, dbp->fileid)) != 0)
goto err;
dbp->preserve_fid = 1;
if (LOCKING_ON(dbenv)) {
if (dbp->lid == DB_LOCK_INVALIDID &&
(ret = __lock_id(dbenv, &dbp->lid, NULL)) != 0)
goto err;
locker = txn == NULL ? dbp->lid : txn->txnid;
}
/*
* In a transactional environment, we'll play the same game
* that we play for databases in the file system -- create a
* temporary database and put it in with the current name
* and then rename this one to another name. We'll then use
* a commit-time event to remove the entry.
*/
if ((ret = __fop_lock_handle(dbenv,
dbp, locker, DB_LOCK_WRITE, NULL, 0)) != 0)
goto err;
if (LOGGING_ON(dbenv)) {
memset(&fid_dbt, 0, sizeof(fid_dbt));
fid_dbt.data = dbp->fileid;
fid_dbt.size = DB_FILE_ID_LEN;
memset(&name_dbt, 0, sizeof(name_dbt));
name_dbt.data = (void *)name;
name_dbt.size = (u_int32_t)strlen(name) + 1;
if (txn != NULL && (ret =
__txn_remevent(dbenv, txn, name, dbp->fileid, 1)) != 0)
goto err;
if ((ret = __crdel_inmem_remove_log(dbenv,
txn, &lsn, 0, &name_dbt, &fid_dbt)) != 0)
goto err;
}
if (txn == NULL)
ret = __memp_nameop(dbenv, dbp->fileid, NULL, name, NULL, 1);
err: return (ret);
}
/*
* __db_subdb_remove --
* Remove a subdatabase.
@ -323,10 +438,10 @@ err:
}
static int
__db_dbtxn_remove(dbp, txn, name)
__db_dbtxn_remove(dbp, txn, name, subdb)
DB *dbp;
DB_TXN *txn;
const char *name;
const char *name, *subdb;
{
DB_ENV *dbenv;
int ret;
@ -336,27 +451,32 @@ __db_dbtxn_remove(dbp, txn, name)
tmpname = NULL;
/*
* This is a transactional rename, so we have to keep the name
* This is a transactional remove, so we have to keep the name
* of the file locked until the transaction commits. As a result,
* we implement remove by renaming the file to some other name
* (which creates a dummy named file as a placeholder for the
* file being rename/dremoved) and then deleting that file as
* a delayed remove at commit.
*/
if ((ret = __db_backup_name(dbenv, name, txn, &tmpname)) != 0)
if ((ret = __db_backup_name(dbenv,
F_ISSET(dbp, DB_AM_INMEM) ? subdb : name, txn, &tmpname)) != 0)
return (ret);
DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, name);
if ((ret = __db_rename_int(dbp, txn, name, NULL, tmpname)) != 0)
if ((ret = __db_rename_int(dbp, txn, name, subdb, tmpname)) != 0)
goto err;
/* The internal removes will also translate into delayed removes. */
/*
* The internal removes will also translate into delayed removes.
*/
if (dbp->db_am_remove != NULL &&
(ret = dbp->db_am_remove(dbp, txn, tmpname, NULL)) != 0)
goto err;
ret = __fop_remove(dbenv, txn, dbp->fileid, tmpname, DB_APP_DATA,
ret = F_ISSET(dbp, DB_AM_INMEM) ?
__db_inmem_remove(dbp, txn, tmpname) :
__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);

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2004
* Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_rename.c,v 11.216 2004/09/16 17:55:17 margo Exp $
* $Id: db_rename.c,v 12.11 2005/10/07 20:21:22 ubell Exp $
*/
#include "db_config.h"
@ -23,74 +23,66 @@
#include "dbinc/log.h"
#include "dbinc/mp.h"
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_pp
* __env_dbrename_pp
* DB_ENV->dbrename pre/post processing.
*
* PUBLIC: int __dbenv_dbrename_pp __P((DB_ENV *, DB_TXN *,
* PUBLIC: int __env_dbrename_pp __P((DB_ENV *, DB_TXN *,
* PUBLIC: const char *, const char *, const char *, u_int32_t));
*/
int
__dbenv_dbrename_pp(dbenv, txn, name, subdb, newname, flags)
__env_dbrename_pp(dbenv, txn, name, subdb, newname, flags)
DB_ENV *dbenv;
DB_TXN *txn;
const char *name, *subdb, *newname;
u_int32_t flags;
{
int ret, txn_local;
DB *dbp;
DB_THREAD_INFO *ip;
int handle_check, ret, t_ret, txn_local;
dbp = NULL;
txn_local = 0;
PANIC_CHECK(dbenv);
ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->dbrename");
/* Validate arguments. */
/*
* The actual argument checking is simple, do it inline, outside of
* the replication block.
*/
if ((ret = __db_fchk(dbenv, "DB->rename", flags, DB_AUTO_COMMIT)) != 0)
return (ret);
ENV_ENTER(dbenv, ip);
/* Check for replication block. */
handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check && (ret = __env_rep_enter(dbenv, 1)) != 0) {
handle_check = 0;
goto err;
}
/*
* Create local transaction as necessary, check for consistent
* transaction usage.
*/
if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
if (IS_ENV_AUTO_COMMIT(dbenv, txn, flags)) {
if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
return (ret);
goto err;
txn_local = 1;
} else {
if (txn != NULL && !TXN_ON(dbenv))
return (__db_not_txn_env(dbenv));
txn_local = 0;
}
} else
if (txn != NULL && !TXN_ON(dbenv)) {
ret = __db_not_txn_env(dbenv);
goto err;
}
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;
LF_CLR(DB_AUTO_COMMIT);
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);
@ -114,13 +106,27 @@ __dbenv_dbrename(dbenv, txn, name, subdb, newname, txn_local)
dbp->lid = DB_LOCK_INVALIDID;
}
if (handle_check)
__env_db_rep_exit(dbenv);
err:
if ((t_ret = __db_close(dbp, txn, DB_NOSYNC)) != 0 && ret == 0)
err: if (txn_local && (t_ret =
__db_txn_auto_resolve(dbenv, txn, 0, ret)) != 0 && ret == 0)
ret = t_ret;
/*
* We never opened this dbp for real, so don't include a transaction
* handle, and use NOSYNC to avoid calling into mpool.
*
* !!!
* Note we're reversing the order of operations: we started the txn and
* then opened the DB handle; we're resolving the txn and then closing
* closing the DB handle -- it's safer.
*/
if (dbp != NULL &&
(t_ret = __db_close(dbp, NULL, DB_NOSYNC)) != 0 && ret == 0)
ret = t_ret;
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
ENV_LEAVE(dbenv, ip);
return (ret);
}
@ -138,7 +144,8 @@ __db_rename_pp(dbp, name, subdb, newname, flags)
u_int32_t flags;
{
DB_ENV *dbenv;
int handle_check, ret;
DB_THREAD_INFO *ip;
int handle_check, ret, t_ret;
dbenv = dbp->dbenv;
handle_check = 0;
@ -155,20 +162,20 @@ __db_rename_pp(dbp, name, subdb, newname, flags)
* a database -- we'll destroy the handle, and the application won't
* ever be able to close the database.
*/
if (F_ISSET(dbp, DB_AM_OPEN_CALLED)) {
ret = __db_mi_open(dbenv, "DB->rename", 1);
goto err;
}
if (F_ISSET(dbp, DB_AM_OPEN_CALLED))
return (__db_mi_open(dbenv, "DB->rename", 1));
/* Validate arguments. */
if ((ret = __db_fchk(dbenv, "DB->rename", 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);
ENV_ENTER(dbenv, ip);
handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, 0)) != 0) {
handle_check = 0;
goto err;
@ -177,9 +184,9 @@ __db_rename_pp(dbp, name, subdb, newname, flags)
/* Rename the file. */
ret = __db_rename(dbp, NULL, name, subdb, newname);
err: if (handle_check)
__env_db_rep_exit(dbenv);
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret);
}
@ -222,26 +229,40 @@ __db_rename_int(dbp, txn, name, subdb, newname)
{
DB_ENV *dbenv;
int ret;
char *real_name;
char *old, *real_name;
dbenv = dbp->dbenv;
real_name = NULL;
DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, name);
if (subdb != NULL) {
if (name == NULL && subdb == NULL) {
__db_err(dbenv, "Rename on temporary files invalid");
ret = EINVAL;
goto err;
}
if (name == NULL)
MAKE_INMEM(dbp);
else if (subdb != NULL) {
ret = __db_subdb_rename(dbp, txn, name, subdb, newname);
goto err;
}
/*
* From here on down, this pertains to files.
* From here on down, this pertains to files or in-memory databases.
*
* Find the real name of the file.
*/
if ((ret = __db_appname(dbenv,
DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
goto err;
if (F_ISSET(dbp, DB_AM_INMEM)) {
old = (char *)subdb;
real_name = (char *)subdb;
} else {
if ((ret = __db_appname(dbenv,
DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
goto err;
old = (char *)name;
}
if ((ret = __fop_remove_setup(dbp, txn, real_name, 0)) != 0)
goto err;
@ -259,10 +280,10 @@ __db_rename_int(dbp, txn, name, subdb, newname)
* taken care of in the fop layer.
*/
if (txn != NULL) {
if ((ret = __fop_dummy(dbp, txn, name, newname, 0)) != 0)
if ((ret = __fop_dummy(dbp, txn, old, newname, 0)) != 0)
goto err;
} else {
if ((ret = __fop_dbrename(dbp, name, newname)) != 0)
if ((ret = __fop_dbrename(dbp, old, newname)) != 0)
goto err;
}
@ -276,7 +297,7 @@ __db_rename_int(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 (!F_ISSET(dbp, DB_AM_INMEM) && real_name != NULL)
__os_free(dbenv, real_name);
return (ret);

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_ret.c,v 11.26 2004/02/05 02:25:13 mjc Exp $
* $Id: db_ret.c,v 12.1 2005/06/16 20:21:14 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2004
* Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_setid.c,v 1.6 2004/09/24 13:41:08 bostic Exp $
* $Id: db_setid.c,v 12.8 2005/10/18 14:17:08 mjc Exp $
*/
#include "db_config.h"
@ -17,20 +17,64 @@
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/db_swap.h"
#include "dbinc/db_am.h"
#include "dbinc/mp.h"
static int __env_fileid_reset __P((DB_ENV *, const char *, int));
/*
* __db_fileid_reset --
* Reset the file IDs for every database in the file.
* __env_fileid_reset_pp --
* DB_ENV->fileid_reset pre/post processing.
*
* PUBLIC: int __db_fileid_reset __P((DB_ENV *, char *, int));
* PUBLIC: int __env_fileid_reset_pp __P((DB_ENV *, const char *, u_int32_t));
*/
int
__db_fileid_reset(dbenv, name, passwd)
__env_fileid_reset_pp(dbenv, name, flags)
DB_ENV *dbenv;
char *name;
int passwd;
const char *name;
u_int32_t flags;
{
DB_THREAD_INFO *ip;
int handle_check, ret, t_ret;
PANIC_CHECK(dbenv);
ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->fileid_reset");
/*
* !!!
* The actual argument checking is simple, do it inline, outside of
* the replication block.
*/
if (flags != 0 && flags != DB_ENCRYPT)
return (__db_ferr(dbenv, "DB_ENV->fileid_reset", 0));
ENV_ENTER(dbenv, ip);
/* Check for replication block. */
handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check && (ret = __env_rep_enter(dbenv, 1)) != 0)
goto err;
ret = __env_fileid_reset(dbenv, name, LF_ISSET(DB_ENCRYPT) ? 1 : 0);
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret);
}
/*
* __env_fileid_reset --
* Reset the file IDs for every database in the file.
*/
static int
__env_fileid_reset(dbenv, name, encrypted)
DB_ENV *dbenv;
const char *name;
int encrypted;
{
DB *dbp;
DBC *dbcp;
@ -47,27 +91,21 @@ __db_fileid_reset(dbenv, name, passwd)
real_name = NULL;
/* Get the real backing file name. */
if ((ret = __db_appname(dbenv,
DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
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");
if ((ret = __os_fileid(dbenv, real_name, 1, fileid)) != 0)
goto err;
}
/* Create the DB object. */
if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
if ((ret = db_create(&dbp, dbenv, 0)) != 0)
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");
if (encrypted && (ret = __db_set_flags(dbp, DB_ENCRYPT)) != 0)
goto err;
}
/*
* Open the DB file.
@ -76,26 +114,18 @@ __db_fileid_reset(dbenv, name, passwd)
* 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);
if ((ret = __db_open(dbp, NULL,
name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0, PGNO_BASE_MD)) != 0)
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);
if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0)
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);
if ((ret = __memp_fput(mpf, pagep, DB_MPOOL_DIRTY)) != 0)
goto err;
}
/*
* If the database file doesn't support subdatabases, we only have
@ -108,11 +138,9 @@ __db_fileid_reset(dbenv, name, passwd)
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");
if ((ret = __db_cursor(dbp, NULL, &dbcp, 0)) != 0)
goto err;
}
while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
while ((ret = __db_c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
/*
* XXX
* We're handling actual data, not on-page meta-data, so it
@ -121,33 +149,19 @@ __db_fileid_reset(dbenv, name, passwd)
*/
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);
if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0)
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);
if ((ret = __memp_fput(mpf, pagep, DB_MPOOL_DIRTY)) != 0)
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;
}
err: if (dbcp != NULL && (t_ret = __db_c_close(dbcp)) != 0 && ret == 0)
ret = t_ret;
if (dbp != NULL && (t_ret = __db_close(dbp, NULL, 0)) != 0 && ret == 0)
ret = t_ret;
if (real_name != NULL)
__os_free(dbenv, real_name);

View file

@ -1,35 +1,77 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2004
* Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_setlsn.c,v 1.2 2004/04/27 16:10:13 bostic Exp $
* $Id: db_setlsn.c,v 12.8 2005/10/21 19:17:40 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/mp.h"
static int __env_lsn_reset __P((DB_ENV *, const char *, int));
/*
* __db_lsn_reset --
* Reset the LSNs for every page in the file.
* __env_lsn_reset_pp --
* DB_ENV->lsn_reset pre/post processing.
*
* PUBLIC: int __db_lsn_reset __P((DB_ENV *, char *, int));
* PUBLIC: int __env_lsn_reset_pp __P((DB_ENV *, const char *, u_int32_t));
*/
int
__db_lsn_reset(dbenv, name, passwd)
__env_lsn_reset_pp(dbenv, name, flags)
DB_ENV *dbenv;
char *name;
int passwd;
const char *name;
u_int32_t flags;
{
DB_THREAD_INFO *ip;
int handle_check, ret, t_ret;
PANIC_CHECK(dbenv);
ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->lsn_reset");
/*
* !!!
* The actual argument checking is simple, do it inline, outside of
* the replication block.
*/
if (flags != 0 && flags != DB_ENCRYPT)
return (__db_ferr(dbenv, "DB_ENV->lsn_reset", 0));
ENV_ENTER(dbenv, ip);
/* Check for replication block. */
handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check && (ret = __env_rep_enter(dbenv, 1)) != 0)
goto err;
ret = __env_lsn_reset(dbenv, name, LF_ISSET(DB_ENCRYPT) ? 1 : 0);
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret);
}
/*
* __env_lsn_reset --
* Reset the LSNs for every page in the file.
*/
static int
__env_lsn_reset(dbenv, name, encrypted)
DB_ENV *dbenv;
const char *name;
int encrypted;
{
DB *dbp;
DB_MPOOLFILE *mpf;
@ -38,16 +80,12 @@ __db_lsn_reset(dbenv, name, passwd)
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 ((ret = db_create(&dbp, dbenv, 0)) != 0)
return (ret);
/* 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");
if (encrypted && (ret = __db_set_flags(dbp, DB_ENCRYPT)) != 0)
goto err;
}
/*
* Open the DB file.
@ -56,28 +94,23 @@ __db_lsn_reset(dbenv, name, passwd)
* 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);
if ((ret = __db_open(dbp, NULL,
name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0, PGNO_BASE_MD)) != 0)
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) {
for (pgno = 0;
(ret = __memp_fget(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);
if ((ret = __memp_fput(mpf, pagep, DB_MPOOL_DIRTY)) != 0)
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)
err: if ((t_ret = __db_close(dbp, NULL, 0)) != 0 && ret == 0)
ret = t_ret;
return (ret == 0 ? 0 : 1);
return (ret);
}

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_stati.c,v 11.123 2004/07/19 16:40:51 bostic Exp $
* $Id: db_stati.c,v 12.10 2005/11/08 03:13:31 bostic Exp $
*/
#include "db_config.h"
@ -33,6 +33,7 @@
#include "dbinc/btree.h"
#include "dbinc/hash.h"
#include "dbinc/qam.h"
#include "dbinc/lock.h"
#include "dbinc/log.h"
#include "dbinc/mp.h"
@ -57,7 +58,8 @@ __db_stat_pp(dbp, txn, spp, flags)
u_int32_t flags;
{
DB_ENV *dbenv;
int handle_check, ret;
DB_THREAD_INFO *ip;
int handle_check, ret, t_ret;
dbenv = dbp->dbenv;
@ -67,17 +69,22 @@ __db_stat_pp(dbp, txn, spp, flags)
if ((ret = __db_stat_arg(dbp, flags)) != 0)
return (ret);
ENV_ENTER(dbenv, ip);
/* Check for replication block. */
handle_check = IS_REPLICATED(dbenv, dbp);
if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0)
return (ret);
handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0) {
handle_check = 0;
goto err;
}
ret = __db_stat(dbp, txn, spp, flags);
/* Release replication block. */
if (handle_check)
__env_db_rep_exit(dbenv);
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret);
}
@ -102,11 +109,11 @@ __db_stat(dbp, txn, spp, flags)
/* Acquire a cursor. */
if ((ret = __db_cursor(dbp, txn,
&dbc, LF_ISSET(DB_DEGREE_2 | DB_DIRTY_READ))) != 0)
&dbc, LF_ISSET(DB_READ_COMMITTED | DB_READ_UNCOMMITTED))) != 0)
return (ret);
DEBUG_LWRITE(dbc, NULL, "DB->stat", NULL, NULL, flags);
LF_CLR(DB_DEGREE_2 | DB_DIRTY_READ);
LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED);
switch (dbp->type) {
case DB_BTREE:
@ -145,7 +152,7 @@ __db_stat_arg(dbp, flags)
dbenv = dbp->dbenv;
/* Check for invalid function flags. */
LF_CLR(DB_DEGREE_2 | DB_DIRTY_READ);
LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED);
switch (flags) {
case 0:
case DB_FAST_STAT:
@ -176,7 +183,8 @@ __db_stat_print_pp(dbp, flags)
u_int32_t flags;
{
DB_ENV *dbenv;
int handle_check, ret;
DB_THREAD_INFO *ip;
int handle_check, ret, t_ret;
dbenv = dbp->dbenv;
@ -187,21 +195,26 @@ __db_stat_print_pp(dbp, flags)
* !!!
* 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)
if ((ret = __db_fchk(dbenv,
"DB->stat_print", flags, DB_FAST_STAT | DB_STAT_ALL)) != 0)
return (ret);
ENV_ENTER(dbenv, ip);
/* Check for replication block. */
handle_check = IS_REPLICATED(dbenv, dbp);
if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0)
return (ret);
handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0) {
handle_check = 0;
goto err;
}
ret = __db_stat_print(dbp, flags);
/* Release replication block. */
if (handle_check)
__env_db_rep_exit(dbenv);
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret);
}
@ -217,16 +230,17 @@ __db_stat_print(dbp, flags)
u_int32_t flags;
{
int ret;
time_t now;
if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
ret = __db_print_stats(dbp, flags);
if (flags == 0 || ret != 0)
return (ret);
}
(void)time(&now);
__db_msg(dbp->dbenv, "%.24s\tLocal time", ctime(&now));
if (LF_ISSET(DB_STAT_ALL) && (ret = __db_print_all(dbp, flags)) != 0)
return (ret);
if ((ret = __db_print_stats(dbp, flags)) != 0)
return (ret);
return (0);
}
@ -284,38 +298,37 @@ __db_print_all(dbp, flags)
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_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_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_READ_UNCOMMITTED, "DB_AM_READ_UNCOMMITTED" },
{ DB_AM_RECNUM, "DB_AM_RECNUM" },
{ DB_AM_RECOVER, "DB_AM_RECOVER" },
{ DB_AM_RENUMBER, "DB_AM_RENUMBER" },
{ 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;
@ -331,7 +344,7 @@ __db_print_all(dbp, flags)
STAT_ISSET("DbEnv", dbp->dbenv);
STAT_STRING("Type", __db_dbtype_to_string(dbp->type));
__db_print_mutex(dbenv, NULL, dbp->mutexp, "Thread mutex", flags);
__mutex_print_debug_single(dbenv, "Thread mutex", dbp->mutex, flags);
STAT_STRING("File", dbp->fname);
STAT_STRING("Database", dbp->dname);
@ -389,7 +402,7 @@ __db_print_cursor(dbp)
__db_msg(dbenv, "DB handle cursors:");
ret = 0;
MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
MUTEX_LOCK(dbp->dbenv, dbp->mutex);
__db_msg(dbenv, "Active queue:");
for (dbc = TAILQ_FIRST(&dbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
@ -405,7 +418,7 @@ __db_print_cursor(dbp)
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);
MUTEX_UNLOCK(dbp->dbenv, dbp->mutex);
return (ret);
}
@ -417,17 +430,17 @@ int __db_print_citem(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_MULTIPLE, "DBC_MULTIPLE" },
{ DBC_MULTIPLE_KEY, "DBC_MULTIPLE_KEY" },
{ DBC_OPD, "DBC_OPD" },
{ DBC_OWN_LID, "DBC_OWN_LID" },
{ DBC_READ_COMMITTED, "DBC_READ_COMMITTED" },
{ DBC_READ_UNCOMMITTED, "DBC_READ_UNCOMMITTED" },
{ 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;
@ -438,16 +451,17 @@ int __db_print_citem(dbc)
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_POINTER("DBC", dbc);
STAT_POINTER("Associated dbp", dbc->dbp);
STAT_POINTER("Associated txn", dbc->txn);
STAT_POINTER("Internal", cp);
STAT_HEX("Default locker ID",
dbc->lref == NULL ? 0 : ((DB_LOCKER *)dbc->lref)->id);
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_POINTER("Off-page duplicate cursor", cp->opd);
STAT_POINTER("Referenced page", cp->page);
STAT_ULONG("Root", cp->root);
STAT_ULONG("Page number", cp->pgno);
STAT_ULONG("Page index", cp->indx);

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2004
* Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_truncate.c,v 11.201 2004/07/15 15:52:51 sue Exp $
* $Id: db_truncate.c,v 12.10 2005/10/21 19:22:59 bostic Exp $
*/
#include "db_config.h"
@ -17,10 +17,12 @@
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/log.h"
#include "dbinc/db_shash.h"
#include "dbinc/btree.h"
#include "dbinc/hash.h"
#include "dbinc/qam.h"
#include "dbinc/lock.h"
#include "dbinc/log.h"
#include "dbinc/txn.h"
static int __db_cursor_check __P((DB *));
@ -38,22 +40,27 @@ __db_truncate_pp(dbp, txn, countp, flags)
u_int32_t *countp, flags;
{
DB_ENV *dbenv;
int handle_check, ret, txn_local;
DB_THREAD_INFO *ip;
int handle_check, ret, t_ret, txn_local;
dbenv = dbp->dbenv;
txn_local = 0;
handle_check = 0;
PANIC_CHECK(dbenv);
STRIP_AUTO_COMMIT(flags);
/* Check for invalid flags. */
if (F_ISSET(dbp, DB_AM_SECONDARY)) {
__db_err(dbenv,
"DBP->truncate forbidden on secondary indices");
"DB->truncate forbidden on secondary indices");
return (EINVAL);
}
if ((ret =
__db_fchk(dbenv, "DB->truncate", flags, DB_AUTO_COMMIT)) != 0)
if ((ret = __db_fchk(dbenv, "DB->truncate", flags, 0)) != 0)
return (ret);
ENV_ENTER(dbenv, ip);
/*
* Make sure there are no active cursors on this db. Since we drop
* pages we cannot really adjust cursors.
@ -61,34 +68,57 @@ __db_truncate_pp(dbp, txn, countp, flags)
if (__db_cursor_check(dbp) != 0) {
__db_err(dbenv,
"DB->truncate not permitted with active cursors");
return (EINVAL);
goto err;
}
#if CONFIG_TEST
if (IS_REP_MASTER(dbenv))
DB_TEST_WAIT(dbenv, dbenv->test_check);
#endif
/* Check for replication block. */
handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check &&
(ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0) {
handle_check = 0;
goto err;
}
/*
* Check for changes to a read-only database.
* This must be after the replication block so that we
* cannot race master/client state changes.
*/
if (DB_IS_READONLY(dbp)) {
ret = __db_rdonly(dbenv, "DB->truncate");
goto err;
}
/*
* 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_init(dbenv, &txn)) != 0)
if (IS_DB_AUTO_COMMIT(dbp, txn)) {
if ((ret = __txn_begin(dbenv, NULL, &txn, 0)) != 0)
goto err;
txn_local = 1;
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)
/* Check for consistent transaction usage. */
if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
goto err;
ret = __db_truncate(dbp, txn, countp);
if (handle_check)
__env_db_rep_exit(dbenv);
err: if (txn_local &&
(t_ret = __db_txn_auto_resolve(dbenv, txn, 0, ret)) && ret == 0)
ret = t_ret;
err: return (txn_local ? __db_txn_auto_resolve(dbenv, txn, 0, ret) : ret);
/* Release replication block. */
if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
ret = t_ret;
ENV_LEAVE(dbenv, ip);
return (ret);
}
/*
@ -119,8 +149,9 @@ __db_truncate(dbp, txn, countp)
* 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_s_first(dbp, &sdbp)) != 0)
return (ret);
for (; sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp))
if ((ret = __db_truncate(sdbp, txn, &scount)) != 0)
break;
if (sdbp != NULL)
@ -180,11 +211,11 @@ __db_cursor_check(dbp)
dbenv = dbp->dbenv;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
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);
MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (IS_INITIALIZED(dbc)) {
@ -192,11 +223,11 @@ __db_cursor_check(dbp)
break;
}
}
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
MUTEX_UNLOCK(dbenv, dbp->mutex);
if (found == 1)
break;
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (found);
}

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_upg.c,v 11.35 2004/03/24 20:37:35 bostic Exp $
* $Id: db_upg.c,v 12.1 2005/06/16 20:21:15 bostic Exp $
*/
#include "db_config.h"

View file

@ -1,10 +1,10 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved.
*
* $Id: db_upg_opd.c,v 11.21 2004/03/19 16:10:26 bostic Exp $
* $Id: db_upg_opd.c,v 12.1 2005/06/16 20:21:15 bostic Exp $
*/
#include "db_config.h"

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