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/output.0
autom4te.cache/requests autom4te.cache/requests
autom4te.cache/traces.0 autom4te.cache/traces.0
bdb/*.ds? storage/bdb/*.ds?
bdb/*.vcproj storage/bdb/*.vcproj
bdb/README storage/bdb/README
bdb/btree/btree_auto.c storage/bdb/btree/btree_auto.c
bdb/build_unix/* storage/bdb/build_unix/*
bdb/build_vxworks/db.h storage/bdb/build_vxworks/db.h
bdb/build_vxworks/db_int.h storage/bdb/build_vxworks/db_int.h
bdb/build_win32/db.h storage/bdb/build_win32/db.h
bdb/build_win32/db_archive.dsp storage/bdb/build_win32/db_archive.dsp
bdb/build_win32/db_checkpoint.dsp storage/bdb/build_win32/db_checkpoint.dsp
bdb/build_win32/db_config.h storage/bdb/build_win32/db_config.h
bdb/build_win32/db_cxx.h storage/bdb/build_win32/db_cxx.h
bdb/build_win32/db_deadlock.dsp storage/bdb/build_win32/db_deadlock.dsp
bdb/build_win32/db_dll.dsp storage/bdb/build_win32/db_dll.dsp
bdb/build_win32/db_dump.dsp storage/bdb/build_win32/db_dump.dsp
bdb/build_win32/db_int.h storage/bdb/build_win32/db_int.h
bdb/build_win32/db_java.dsp storage/bdb/build_win32/db_java.dsp
bdb/build_win32/db_load.dsp storage/bdb/build_win32/db_load.dsp
bdb/build_win32/db_perf.dsp storage/bdb/build_win32/db_perf.dsp
bdb/build_win32/db_printlog.dsp storage/bdb/build_win32/db_printlog.dsp
bdb/build_win32/db_recover.dsp storage/bdb/build_win32/db_recover.dsp
bdb/build_win32/db_stat.dsp storage/bdb/build_win32/db_stat.dsp
bdb/build_win32/db_static.dsp storage/bdb/build_win32/db_static.dsp
bdb/build_win32/db_tcl.dsp storage/bdb/build_win32/db_tcl.dsp
bdb/build_win32/db_test.dsp storage/bdb/build_win32/db_test.dsp
bdb/build_win32/db_upgrade.dsp storage/bdb/build_win32/db_upgrade.dsp
bdb/build_win32/db_verify.dsp storage/bdb/build_win32/db_verify.dsp
bdb/build_win32/ex_access.dsp storage/bdb/build_win32/ex_access.dsp
bdb/build_win32/ex_btrec.dsp storage/bdb/build_win32/ex_btrec.dsp
bdb/build_win32/ex_env.dsp storage/bdb/build_win32/ex_env.dsp
bdb/build_win32/ex_lock.dsp storage/bdb/build_win32/ex_lock.dsp
bdb/build_win32/ex_mpool.dsp storage/bdb/build_win32/ex_mpool.dsp
bdb/build_win32/ex_tpcb.dsp storage/bdb/build_win32/ex_tpcb.dsp
bdb/build_win32/excxx_access.dsp storage/bdb/build_win32/excxx_access.dsp
bdb/build_win32/excxx_btrec.dsp storage/bdb/build_win32/excxx_btrec.dsp
bdb/build_win32/excxx_env.dsp storage/bdb/build_win32/excxx_env.dsp
bdb/build_win32/excxx_lock.dsp storage/bdb/build_win32/excxx_lock.dsp
bdb/build_win32/excxx_mpool.dsp storage/bdb/build_win32/excxx_mpool.dsp
bdb/build_win32/excxx_tpcb.dsp storage/bdb/build_win32/excxx_tpcb.dsp
bdb/build_win32/include.tcl storage/bdb/build_win32/include.tcl
bdb/build_win32/libdb.def storage/bdb/build_win32/libdb.def
bdb/build_win32/libdb.rc storage/bdb/build_win32/libdb.rc
bdb/db/crdel_auto.c storage/bdb/db/crdel_auto.c
bdb/db/db_auto.c storage/bdb/db/db_auto.c
bdb/dbinc_auto/*.* storage/bdb/dbinc_auto/*.*
bdb/dbreg/dbreg_auto.c storage/bdb/dbreg/dbreg_auto.c
bdb/dist/autom4te-2.53.cache/* storage/bdb/dist/autom4te-2.53.cache/*
bdb/dist/autom4te-2.53.cache/output.0 storage/bdb/dist/autom4te-2.53.cache/output.0
bdb/dist/autom4te-2.53.cache/requests storage/bdb/dist/autom4te-2.53.cache/requests
bdb/dist/autom4te-2.53.cache/traces.0 storage/bdb/dist/autom4te-2.53.cache/traces.0
bdb/dist/autom4te.cache/* storage/bdb/dist/autom4te.cache/*
bdb/dist/autom4te.cache/output.0 storage/bdb/dist/autom4te.cache/output.0
bdb/dist/autom4te.cache/requests storage/bdb/dist/autom4te.cache/requests
bdb/dist/autom4te.cache/traces.0 storage/bdb/dist/autom4te.cache/traces.0
bdb/dist/config.hin storage/bdb/dist/config.hin
bdb/dist/configure storage/bdb/dist/configure
bdb/dist/tags storage/bdb/dist/tags
bdb/dist/template/db_server_proc storage/bdb/dist/template/db_server_proc
bdb/dist/template/gen_client_ret storage/bdb/dist/template/gen_client_ret
bdb/dist/template/rec_btree storage/bdb/dist/template/rec_btree
bdb/dist/template/rec_crdel storage/bdb/dist/template/rec_crdel
bdb/dist/template/rec_db storage/bdb/dist/template/rec_db
bdb/dist/template/rec_dbreg storage/bdb/dist/template/rec_dbreg
bdb/dist/template/rec_fileops storage/bdb/dist/template/rec_fileops
bdb/dist/template/rec_hash storage/bdb/dist/template/rec_hash
bdb/dist/template/rec_log storage/bdb/dist/template/rec_log
bdb/dist/template/rec_qam storage/bdb/dist/template/rec_qam
bdb/dist/template/rec_txn storage/bdb/dist/template/rec_txn
bdb/examples_c/ex_apprec/ex_apprec_auto.c storage/bdb/fileops/fileops_auto.c
bdb/examples_c/ex_apprec/ex_apprec_auto.h storage/bdb/hash/hash_auto.c
bdb/examples_c/ex_apprec/ex_apprec_template storage/bdb/include/btree_auto.h
bdb/examples_java storage/bdb/include/btree_ext.h
bdb/fileops/fileops_auto.c storage/bdb/include/clib_ext.h
bdb/hash/hash_auto.c storage/bdb/include/common_ext.h
bdb/include/btree_auto.h storage/bdb/include/crdel_auto.h
bdb/include/btree_ext.h storage/bdb/include/db_auto.h
bdb/include/clib_ext.h storage/bdb/include/db_ext.h
bdb/include/common_ext.h storage/bdb/include/db_server.h
bdb/include/crdel_auto.h storage/bdb/include/env_ext.h
bdb/include/db_auto.h storage/bdb/include/gen_client_ext.h
bdb/include/db_ext.h storage/bdb/include/gen_server_ext.h
bdb/include/db_server.h storage/bdb/include/hash_auto.h
bdb/include/env_ext.h storage/bdb/include/hash_ext.h
bdb/include/gen_client_ext.h storage/bdb/include/lock_ext.h
bdb/include/gen_server_ext.h storage/bdb/include/log_auto.h
bdb/include/hash_auto.h storage/bdb/include/log_ext.h
bdb/include/hash_ext.h storage/bdb/include/mp_ext.h
bdb/include/lock_ext.h storage/bdb/include/mutex_ext.h
bdb/include/log_auto.h storage/bdb/include/os_ext.h
bdb/include/log_ext.h storage/bdb/include/qam_auto.h
bdb/include/mp_ext.h storage/bdb/include/qam_ext.h
bdb/include/mutex_ext.h storage/bdb/include/rpc_client_ext.h
bdb/include/os_ext.h storage/bdb/include/rpc_server_ext.h
bdb/include/qam_auto.h storage/bdb/include/tcl_ext.h
bdb/include/qam_ext.h storage/bdb/include/txn_auto.h
bdb/include/rpc_client_ext.h storage/bdb/include/txn_ext.h
bdb/include/rpc_server_ext.h storage/bdb/include/xa_ext.h
bdb/include/tcl_ext.h storage/bdb/log/log_auto.c
bdb/include/txn_auto.h storage/bdb/qam/qam_auto.c
bdb/include/txn_ext.h storage/bdb/txn/txn_auto.c
bdb/include/xa_ext.h storage/bdb/txn/txn_autop.c
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
binary/* binary/*
bkpull.log bkpull.log
bkpull.log* bkpull.log*

View file

@ -120,6 +120,28 @@
<Filter <Filter
Name="Source Files" Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"> 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 <File
RelativePath="btree\bt_compare.c"> RelativePath="btree\bt_compare.c">
<FileConfiguration <FileConfiguration
@ -500,6 +522,25 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </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 <File
RelativePath="db\db.c"> RelativePath="db\db.c">
<FileConfiguration <FileConfiguration
@ -595,6 +636,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\common\db_clock.c">
</File>
<File <File
RelativePath="db\db_conv.c"> RelativePath="db\db_conv.c">
<FileConfiguration <FileConfiguration
@ -994,25 +1038,6 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </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 <File
RelativePath="db\db_setid.c"> RelativePath="db\db_setid.c">
<FileConfiguration <FileConfiguration
@ -1051,6 +1076,25 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </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 <File
RelativePath="db\db_stati.c"> RelativePath="db\db_stati.c">
<FileConfiguration <FileConfiguration
@ -1279,6 +1323,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\env\env_failchk.c">
</File>
<File <File
RelativePath="env\env_file.c"> RelativePath="env\env_file.c">
<FileConfiguration <FileConfiguration
@ -1374,6 +1421,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\env\env_register.c">
</File>
<File <File
RelativePath="env\env_stat.c"> RelativePath="env\env_stat.c">
<FileConfiguration <FileConfiguration
@ -1811,6 +1861,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\lock\lock_failchk.c">
</File>
<File <File
RelativePath="lock\lock_id.c"> RelativePath="lock\lock_id.c">
<FileConfiguration <FileConfiguration
@ -1831,7 +1884,7 @@
</FileConfiguration> </FileConfiguration>
</File> </File>
<File <File
RelativePath="lock\lock_method.c"> RelativePath="lock\lock_list.c">
<FileConfiguration <FileConfiguration
Name="Max|Win32"> Name="Max|Win32">
<Tool <Tool
@ -1850,7 +1903,7 @@
</FileConfiguration> </FileConfiguration>
</File> </File>
<File <File
RelativePath="lock\lock_list.c"> RelativePath="lock\lock_method.c">
<FileConfiguration <FileConfiguration
Name="Max|Win32"> Name="Max|Win32">
<Tool <Tool
@ -2001,6 +2054,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\log\log_debug.c">
</File>
<File <File
RelativePath="log\log_get.c"> RelativePath="log\log_get.c">
<FileConfiguration <FileConfiguration
@ -2324,6 +2380,37 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </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 <File
RelativePath="mutex\mut_tas.c"> RelativePath="mutex\mut_tas.c">
<FileConfiguration <FileConfiguration
@ -2362,25 +2449,6 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </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 <File
RelativePath="os_win32\os_abs.c"> RelativePath="os_win32\os_abs.c">
<FileConfiguration <FileConfiguration
@ -2514,6 +2582,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\os_win32\os_flock.c">
</File>
<File <File
RelativePath="os_win32\os_fsync.c"> RelativePath="os_win32\os_fsync.c">
<FileConfiguration <FileConfiguration
@ -3103,6 +3174,12 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\rep\rep_elect.c">
</File>
<File
RelativePath=".\rep\rep_log.c">
</File>
<File <File
RelativePath="rep\rep_method.c"> RelativePath="rep\rep_method.c">
<FileConfiguration <FileConfiguration
@ -3179,6 +3256,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\rep\rep_stub.c">
</File>
<File <File
RelativePath="rep\rep_util.c"> RelativePath="rep\rep_util.c">
<FileConfiguration <FileConfiguration
@ -3198,6 +3278,47 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </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 <File
RelativePath="hmac\sha1.c"> RelativePath="hmac\sha1.c">
<FileConfiguration <FileConfiguration
@ -3274,6 +3395,12 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\txn\txn_chkpt.c">
</File>
<File
RelativePath=".\txn\txn_failchk.c">
</File>
<File <File
RelativePath="txn\txn_method.c"> RelativePath="txn\txn_method.c">
<FileConfiguration <FileConfiguration
@ -3483,101 +3610,6 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </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>
<Filter <Filter
Name="Header Files" 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 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. * Sleepycat Software. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 bdb_build = build_unix
files = LICENSE Makefile Makefile.in README 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 \ dbinc_auto db185 db_archive db_checkpoint db_deadlock db_dump \
db_dump185 db_load db_printlog db_recover db_stat db_upgrade \ db_dump185 db_hotbackup db_load db_printlog db_recover db_stat db_upgrade \
db_verify dbm dbreg dist env examples_c examples_cxx fileops hash \ db_verify dbm dbreg dist env fileops hash \
hsearch hmac include java libdb_java lock log mp mutex os os_vxworks \ hsearch hmac include lock log mp mutex os \
os_win32 perl.BerkeleyDB perl.DB_File qam rep rpc_client rpc_server tcl \ os_win32 qam rep txn xa sequence
test txn xa sequence
@SET_MAKE@ @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. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -39,7 +39,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -88,7 +88,7 @@ __bam_mswap(pg)
p = (u_int8_t *)pg + sizeof(DBMETA); p = (u_int8_t *)pg + sizeof(DBMETA);
SWAP32(p); /* maxkey */ p += sizeof(u_int32_t); /* unused */
SWAP32(p); /* minkey */ SWAP32(p); /* minkey */
SWAP32(p); /* re_len */ SWAP32(p); /* re_len */
SWAP32(p); /* re_pad */ SWAP32(p); /* re_pad */

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #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 * Update the cursors when items are deleted and when already deleted
* items are overwritten. Return the number of relevant cursors found. * 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 int
__bam_ca_delete(dbp, pgno, indx, delete) __bam_ca_delete(dbp, pgno, indx, delete, countp)
DB *dbp; DB *dbp;
db_pgno_t pgno; db_pgno_t pgno;
u_int32_t indx; u_int32_t indx;
int delete; int delete, *countp;
{ {
BTREE_CURSOR *cp; BTREE_CURSOR *cp;
DB *ldbp; 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 * Each cursor is single-threaded, so we only need to lock the
* list of DBs and then the list of cursors in each DB. * 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); for (count = 0, ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (BTREE_CURSOR *)dbc->internal; cp = (BTREE_CURSOR *)dbc->internal;
@ -92,23 +92,26 @@ __bam_ca_delete(dbp, pgno, indx, delete)
++count; ++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 -- * __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 int
__ram_ca_delete(dbp, root_pgno) __ram_ca_delete(dbp, root_pgno, foundp)
DB *dbp; DB *dbp;
db_pgno_t root_pgno; db_pgno_t root_pgno;
int *foundp;
{ {
DB *ldbp; DB *ldbp;
DBC *dbc; DBC *dbc;
@ -121,19 +124,21 @@ __ram_ca_delete(dbp, root_pgno)
/* /*
* Review the cursors. See the comment in __bam_ca_delete(). * 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); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
found == 0 && ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; found == 0 && ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
found == 0 && dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) found == 0 && dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
if (dbc->internal->root == root_pgno) if (dbc->internal->root == root_pgno)
found = 1; 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);
return (found);
*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(). * Adjust the cursors. See the comment in __bam_ca_delete().
*/ */
found = 0; found = 0;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO) if (dbc->dbtype == DB_RECNO)
@ -188,9 +193,9 @@ __bam_ca_di(my_dbc, pgno, indx, adjust)
found = 1; 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 (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn, &lsn, 0, 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(). * Adjust the cursors. See the comment in __bam_ca_delete().
*/ */
found = 0; found = 0;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { 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); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
/* Find cursors pointing to this record. */ /* Find cursors pointing to this record. */
@ -308,7 +313,7 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
if (orig_cp->opd != NULL) if (orig_cp->opd != NULL)
continue; continue;
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
/* [#8032] /* [#8032]
DB_ASSERT(!STD_LOCKING(dbc) || DB_ASSERT(!STD_LOCKING(dbc) ||
orig_cp->lock_mode != DB_LOCK_NG); 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. */ /* We released the mutex to get a cursor, start over. */
goto loop; 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 (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn, 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(). * 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); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { 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); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
orig_cp = (BTREE_CURSOR *)dbc->internal; orig_cp = (BTREE_CURSOR *)dbc->internal;
@ -377,11 +382,10 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
*/ */
if (orig_cp->pgno != fpgno || if (orig_cp->pgno != fpgno ||
orig_cp->indx != first || orig_cp->indx != first ||
orig_cp->opd == NULL || orig_cp->opd == NULL || ((BTREE_CURSOR *)
((BTREE_CURSOR *)orig_cp->opd->internal)->indx orig_cp->opd->internal)->indx != ti)
!= ti)
continue; continue;
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
if ((ret = __db_c_close(orig_cp->opd)) != 0) if ((ret = __db_c_close(orig_cp->opd)) != 0)
return (ret); return (ret);
orig_cp->opd = NULL; orig_cp->opd = NULL;
@ -392,9 +396,9 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
*/ */
goto loop; 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); return (0);
} }
@ -425,11 +429,11 @@ __bam_ca_rsplit(my_dbc, fpgno, tpgno)
* Adjust the cursors. See the comment in __bam_ca_delete(). * Adjust the cursors. See the comment in __bam_ca_delete().
*/ */
found = 0; found = 0;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO) if (dbc->dbtype == DB_RECNO)
@ -444,9 +448,9 @@ __bam_ca_rsplit(my_dbc, fpgno, tpgno)
found = 1; 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 (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn, 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. * records split to the left page.
*/ */
found = 0; found = 0;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO) 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 (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, 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. * left and the right pages.
* Called only during undo processing. * 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)); * PUBLIC: db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t));
*/ */
void int
__bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx) __bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx)
DB *dbp; DB *dbp;
db_pgno_t frompgno, topgno, lpgno; 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 * When backing out a split, we move the cursor back
* to the original offset and bump it by the split_indx. * 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); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO) if (dbc->dbtype == DB_RECNO)
@ -578,7 +582,9 @@ __bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx)
} else if (cp->pgno == lpgno) } else if (cp->pgno == lpgno)
cp->pgno = frompgno; 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. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #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_close __P((DBC *, db_pgno_t, int *));
static int __bam_c_del __P((DBC *)); static int __bam_c_del __P((DBC *));
static int __bam_c_destroy __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_get __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
static int __bam_c_getstack __P((DBC *)); 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_next __P((DBC *, int, int));
static int __bam_c_physdel __P((DBC *)); static int __bam_c_physdel __P((DBC *));
static int __bam_c_prev __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)); \ ret = __memp_fget(__mpf, &(fpgno), 0, &(pagep)); \
} while (0) } 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. */ /* Acquire a new page/lock for a cursor. */
#undef ACQUIRE_CUR #undef ACQUIRE_CUR
#define ACQUIRE_CUR(dbc, mode, p, ret) do { \ #define ACQUIRE_CUR(dbc, mode, p, ret) do { \
@ -96,23 +79,6 @@ static int __bam_isopd __P((DBC *, db_pgno_t *));
} \ } \
} while (0) } 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. * 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. */ /* Allocate/initialize the internal structure. */
if (dbc->internal == NULL && (ret = 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); return (ret);
/* Initialize methods. */ /* Initialize methods. */
dbc->c_close = __db_c_close; dbc->c_close = __db_c_close_pp;
dbc->c_count = __db_c_count_pp; dbc->c_count = __db_c_count_pp;
dbc->c_del = __db_c_del_pp; dbc->c_del = __db_c_del_pp;
dbc->c_dup = __db_c_dup_pp; dbc->c_dup = __db_c_dup_pp;
@ -257,8 +223,11 @@ __bam_c_refresh(dbc)
LOCK_INIT(cp->lock); LOCK_INIT(cp->lock);
cp->lock_mode = DB_LOCK_NG; cp->lock_mode = DB_LOCK_NG;
cp->sp = cp->csp = cp->stack; if (cp->sp == NULL) {
cp->esp = cp->stack + sizeof(cp->stack) / sizeof(cp->stack[0]); 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 * 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; DBC *dbc_opd, *dbc_c;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
PAGE *h; PAGE *h;
int cdb_lock, ret; int cdb_lock, count, ret;
dbp = dbc->dbp; dbp = dbc->dbp;
mpf = dbp->mpf; mpf = dbp->mpf;
@ -378,22 +347,28 @@ __bam_c_close(dbc, root_pgno, rmroot)
dbc_c = dbc; dbc_c = dbc;
switch (dbc->dbtype) { switch (dbc->dbtype) {
case DB_BTREE: /* Case #1, #3. */ 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 lock;
goto done; goto done;
case DB_RECNO: case DB_RECNO:
if (!F_ISSET(dbc, DBC_OPD)) /* Case #1. */ if (!F_ISSET(dbc, DBC_OPD)) /* Case #1. */
goto done; goto done;
/* Case #3. */ /* 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 lock;
goto done; goto done;
case DB_HASH: case DB_HASH:
case DB_QUEUE: case DB_QUEUE:
case DB_UNKNOWN: case DB_UNKNOWN:
default: default:
return (__db_unknown_type(dbp->dbenv, ret = __db_unknown_type(dbp->dbenv,
"__bam_c_close", dbc->dbtype)); "__bam_c_close", dbc->dbtype);
goto err;
} }
} }
@ -414,20 +389,26 @@ __bam_c_close(dbc, root_pgno, rmroot)
dbc_c = dbc_opd; dbc_c = dbc_opd;
switch (dbc_opd->dbtype) { switch (dbc_opd->dbtype) {
case DB_BTREE: case DB_BTREE:
if (__bam_ca_delete( if ((ret = __bam_ca_delete(
dbp, cp_opd->pgno, cp_opd->indx, 1) == 0) dbp, cp_opd->pgno, cp_opd->indx, 1, &count)) != 0)
goto err;
if (count == 0)
goto lock; goto lock;
goto done; goto done;
case DB_RECNO: 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 lock;
goto done; goto done;
case DB_HASH: case DB_HASH:
case DB_QUEUE: case DB_QUEUE:
case DB_UNKNOWN: case DB_UNKNOWN:
default: default:
return (__db_unknown_type( ret = __db_unknown_type(
dbp->dbenv, "__bam_c_close", dbc->dbtype)); dbp->dbenv, "__bam_c_close", dbc->dbtype);
goto err;
} }
} }
goto done; goto done;
@ -588,8 +569,14 @@ static int
__bam_c_destroy(dbc) __bam_c_destroy(dbc)
DBC *dbc; DBC *dbc;
{ {
BTREE_CURSOR *cp;
cp = (BTREE_CURSOR *)dbc->internal;
/* Discard the structures. */ /* 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); return (0);
} }
@ -693,7 +680,7 @@ __bam_c_del(dbc)
BTREE_CURSOR *cp; BTREE_CURSOR *cp;
DB *dbp; DB *dbp;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
int ret, t_ret; int count, ret, t_ret;
dbp = dbc->dbp; dbp = dbc->dbp;
mpf = dbp->mpf; mpf = dbp->mpf;
@ -760,9 +747,12 @@ err: /*
cp->page = NULL; 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) 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); return (ret);
} }
@ -846,7 +836,8 @@ __bam_c_get(dbc, key, data, flags, pgnop)
break; break;
case DB_FIRST: case DB_FIRST:
newopd = 1; newopd = 1;
if ((ret = __bam_c_first(dbc)) != 0) if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, flags, &exact)) != 0)
goto err; goto err;
break; break;
case DB_GET_BOTH: case DB_GET_BOTH:
@ -910,13 +901,15 @@ __bam_c_get(dbc, key, data, flags, pgnop)
break; break;
case DB_LAST: case DB_LAST:
newopd = 1; newopd = 1;
if ((ret = __bam_c_last(dbc)) != 0) if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, flags, &exact)) != 0)
goto err; goto err;
break; break;
case DB_NEXT: case DB_NEXT:
newopd = 1; newopd = 1;
if (cp->pgno == PGNO_INVALID) { 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; goto err;
} else } else
if ((ret = __bam_c_next(dbc, 1, 0)) != 0) 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: case DB_NEXT_NODUP:
newopd = 1; newopd = 1;
if (cp->pgno == PGNO_INVALID) { 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; goto err;
} else } else
do { do {
@ -944,7 +938,8 @@ __bam_c_get(dbc, key, data, flags, pgnop)
case DB_PREV: case DB_PREV:
newopd = 1; newopd = 1;
if (cp->pgno == PGNO_INVALID) { 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; goto err;
} else } else
if ((ret = __bam_c_prev(dbc)) != 0) if ((ret = __bam_c_prev(dbc)) != 0)
@ -953,7 +948,8 @@ __bam_c_get(dbc, key, data, flags, pgnop)
case DB_PREV_NODUP: case DB_PREV_NODUP:
newopd = 1; newopd = 1;
if (cp->pgno == PGNO_INVALID) { 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; goto err;
} else } else
do { do {
@ -2136,99 +2132,6 @@ __bam_c_writelock(dbc)
return (ret); 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 -- * __bam_c_next --
* Move to the next record. * Move to the next record.
@ -2398,6 +2301,12 @@ __bam_c_search(dbc, root_pgno, key, flags, exactp)
return (ret); return (ret);
switch (flags) { 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: case DB_SET_RECNO:
if ((ret = __ram_getno(dbc, key, &recno, 0)) != 0) if ((ret = __ram_getno(dbc, key, &recno, 0)) != 0)
return (ret); return (ret);
@ -2575,7 +2484,6 @@ search: if ((ret = __bam_search(dbc, root_pgno,
default: default:
return (__db_unknown_flag(dbp->dbenv, "__bam_c_search", flags)); return (__db_unknown_flag(dbp->dbenv, "__bam_c_search", flags));
} }
/* Initialize the cursor from the stack. */ /* Initialize the cursor from the stack. */
cp->page = cp->csp->page; cp->page = cp->csp->page;
cp->pgno = cp->csp->page->pgno; 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 = cp->csp->lock;
cp->lock_mode = cp->csp->lock_mode; 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); return (0);
} }
@ -2597,15 +2515,10 @@ __bam_c_physdel(dbc)
BTREE_CURSOR *cp; BTREE_CURSOR *cp;
DB *dbp; DB *dbp;
DBT key; DBT key;
DB_LOCK lock; int delete_page, empty_page, exact, ret;
DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t pgno;
int delete_page, empty_page, exact, level, ret;
dbp = dbc->dbp; dbp = dbc->dbp;
memset(&key, 0, sizeof(DBT)); memset(&key, 0, sizeof(DBT));
mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal; cp = (BTREE_CURSOR *)dbc->internal;
delete_page = empty_page = ret = 0; delete_page = empty_page = ret = 0;
@ -2683,91 +2596,7 @@ __bam_c_physdel(dbc)
if (!delete_page) if (!delete_page)
return (0); return (0);
/* ret = __bam_search(dbc, PGNO_INVALID, &key, S_DEL, 0, NULL, &exact);
* 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);
/* /*
* If everything worked, delete the stack, otherwise, release the * If everything worked, delete the stack, otherwise, release the
@ -2776,7 +2605,7 @@ __bam_c_physdel(dbc)
if (ret == 0) if (ret == 0)
DISCARD_CUR(dbc, ret); DISCARD_CUR(dbc, ret);
if (ret == 0) if (ret == 0)
ret = __bam_dpages(dbc, cp->sp); ret = __bam_dpages(dbc, 1, 0);
else else
(void)__bam_stkrel(dbc, 0); (void)__bam_stkrel(dbc, 0);

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -39,7 +39,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"
@ -220,12 +220,13 @@ __bam_adjindx(dbc, h, indx, indx_copy, is_insert)
* __bam_dpages -- * __bam_dpages --
* Delete a set of locked pages. * Delete a set of locked pages.
* *
* PUBLIC: int __bam_dpages __P((DBC *, EPG *)); * PUBLIC: int __bam_dpages __P((DBC *, int, int));
*/ */
int int
__bam_dpages(dbc, stack_epg) __bam_dpages(dbc, use_top, update)
DBC *dbc; DBC *dbc;
EPG *stack_epg; int use_top;
int update;
{ {
BTREE_CURSOR *cp; BTREE_CURSOR *cp;
BINTERNAL *bi; BINTERNAL *bi;
@ -233,7 +234,7 @@ __bam_dpages(dbc, stack_epg)
DBT a, b; DBT a, b;
DB_LOCK c_lock, p_lock; DB_LOCK c_lock, p_lock;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
EPG *epg; EPG *epg, *save_sp, *stack_epg;
PAGE *child, *parent; PAGE *child, *parent;
db_indx_t nitems; db_indx_t nitems;
db_pgno_t pgno, root_pgno; db_pgno_t pgno, root_pgno;
@ -243,30 +244,27 @@ __bam_dpages(dbc, stack_epg)
dbp = dbc->dbp; dbp = dbc->dbp;
mpf = dbp->mpf; mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal; cp = (BTREE_CURSOR *)dbc->internal;
nitems = 0;
pgno = PGNO_INVALID;
/* /*
* We have the entire stack of deletable pages locked. * We have the entire stack of deletable pages locked.
* *
* Btree calls us with a pointer to the beginning of a stack, where * Btree calls us with the first page in the stack is to have a
* the first page in the stack is to have a single item deleted, and * single item deleted, and the rest of the pages are to be removed.
* the rest of the pages are to be removed.
* *
* Recno calls us with a pointer into the middle of the stack, where * Recno always has a stack to the root and __bam_merge operations
* the referenced page is to have a single item deleted, and pages * may have unneeded items in the sack. We find the lowest page
* after the stack reference are to be removed. * in the stack that has more than one record in it and start there.
*
* First, discard any pages that we don't care about.
*/ */
ret = 0; ret = 0;
for (epg = cp->sp; epg < stack_epg; ++epg) { if (use_top)
if ((t_ret = __memp_fput(mpf, epg->page, 0)) != 0 && ret == 0) stack_epg = cp->sp;
ret = t_ret; else
if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0) for (stack_epg = cp->csp; stack_epg > cp->sp; --stack_epg)
ret = t_ret; if (NUM_ENT(stack_epg->page) > 1)
} break;
if (ret != 0) epg = stack_epg;
goto err;
/* /*
* !!! * !!!
* There is an interesting deadlock situation here. We have to relink * 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 * It will deadlock here. Before we unlink the subtree, we relink the
* leaf page chain. * leaf page chain.
*/ */
if ((ret = __bam_relink(dbc, cp->csp->page, NULL)) != 0) if (LEVEL(cp->csp->page) == 1 &&
goto err; (ret = __bam_relink(dbc, cp->csp->page, PGNO_INVALID)) != 0)
goto discard;
/* /*
* Delete the last item that references the underlying pages that are * Delete the last item that references the underlying pages that are
@ -288,9 +287,18 @@ __bam_dpages(dbc, stack_epg)
* immediately. * immediately.
*/ */
if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0) 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) 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); pgno = PGNO(epg->page);
nitems = NUM_ENT(epg->page); nitems = NUM_ENT(epg->page);
@ -301,6 +309,17 @@ __bam_dpages(dbc, stack_epg)
if (ret != 0) if (ret != 0)
goto err_inc; 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. */ /* Free the rest of the pages in the stack. */
while (++epg <= cp->csp) { while (++epg <= cp->csp) {
/* /*
@ -310,13 +329,24 @@ __bam_dpages(dbc, stack_epg)
* be referenced by a cursor. * be referenced by a cursor.
*/ */
if (NUM_ENT(epg->page) != 0) { 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) if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0)
goto err; 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); ret = __db_free(dbc, epg->page);
if (cp->page == epg->page)
cp->page = NULL;
epg->page = NULL; epg->page = NULL;
if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0) if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
@ -468,12 +498,13 @@ stop: done = 1;
* __bam_relink -- * __bam_relink --
* Relink around a deleted page. * Relink around a deleted page.
* *
* PUBLIC: int __bam_relink __P((DBC *, PAGE *, PAGE **)); * PUBLIC: int __bam_relink __P((DBC *, PAGE *, db_pgno_t));
*/ */
int int
__bam_relink(dbc, pagep, new_next) __bam_relink(dbc, pagep, new_pgno)
DBC *dbc; DBC *dbc;
PAGE *pagep, **new_next; PAGE *pagep;
db_pgno_t new_pgno;
{ {
DB *dbp; DB *dbp;
PAGE *np, *pp; PAGE *np, *pp;
@ -519,7 +550,7 @@ __bam_relink(dbc, pagep, new_next)
/* Log the change. */ /* Log the change. */
if (DBC_LOGGING(dbc)) { if (DBC_LOGGING(dbc)) {
if ((ret = __bam_relink_log(dbp, dbc->txn, &ret_lsn, 0, 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) pagep->next_pgno, nlsnp)) != 0)
goto err; goto err;
} else } else
@ -528,33 +559,27 @@ __bam_relink(dbc, pagep, new_next)
np->lsn = ret_lsn; np->lsn = ret_lsn;
if (pp != NULL) if (pp != NULL)
pp->lsn = ret_lsn; pp->lsn = ret_lsn;
pagep->lsn = ret_lsn;
/* /*
* Modify and release the two pages. * Modify and release the two pages.
*
* !!!
* The parameter new_next gets set to the page following the page we
* are removing. If there is no following page, then new_next gets
* set to NULL.
*/ */
if (np != NULL) { if (np != NULL) {
np->prev_pgno = pagep->prev_pgno; if (new_pgno == PGNO_INVALID)
if (new_next == NULL) np->prev_pgno = pagep->prev_pgno;
ret = __memp_fput(mpf, np, DB_MPOOL_DIRTY); else
else { np->prev_pgno = new_pgno;
*new_next = np; ret = __memp_fput(mpf, np, DB_MPOOL_DIRTY);
ret = __memp_fset(mpf, np, DB_MPOOL_DIRTY);
}
if ((t_ret = __TLPUT(dbc, npl)) != 0 && ret == 0) if ((t_ret = __TLPUT(dbc, npl)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
if (ret != 0) if (ret != 0)
goto err; goto err;
} else if (new_next != NULL) }
*new_next = NULL;
if (pp != 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); ret = __memp_fput(mpf, pp, DB_MPOOL_DIRTY);
if ((t_ret = __TLPUT(dbc, ppl)) != 0 && ret == 0) if ((t_ret = __TLPUT(dbc, ppl)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
@ -571,3 +596,48 @@ err: if (np != NULL)
(void)__TLPUT(dbc, ppl); (void)__TLPUT(dbc, ppl);
return (ret); 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. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1999-2004 * Copyright (c) 1999-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -18,7 +18,6 @@
#include "dbinc/btree.h" #include "dbinc/btree.h"
#include "dbinc/qam.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_minkey __P((DB *, u_int32_t));
static int __bam_set_bt_prefix static int __bam_set_bt_prefix
__P((DB *, size_t(*)(DB *, const DBT *, const DBT *))); __P((DB *, size_t(*)(DB *, const DBT *, const DBT *)));
@ -52,7 +51,6 @@ __bam_db_create(dbp)
t->bt_prefix = __bam_defpfx; t->bt_prefix = __bam_defpfx;
dbp->set_bt_compare = __bam_set_bt_compare; 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->get_bt_minkey = __bam_get_bt_minkey;
dbp->set_bt_minkey = __bam_set_bt_minkey; dbp->set_bt_minkey = __bam_set_bt_minkey;
dbp->set_bt_prefix = __bam_set_bt_prefix; dbp->set_bt_prefix = __bam_set_bt_prefix;
@ -208,31 +206,6 @@ __bam_set_bt_compare(dbp, func)
return (0); 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 -- * __db_get_bt_minkey --
* Get the minimum keys per page. * Get the minimum keys per page.

View file

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

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -39,7 +39,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"
@ -58,7 +58,9 @@
static int __bam_build static int __bam_build
__P((DBC *, u_int32_t, DBT *, PAGE *, u_int32_t, u_int32_t)); __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 static int __bam_ovput
__P((DBC *, u_int32_t, db_pgno_t, PAGE *, u_int32_t, DBT *)); __P((DBC *, u_int32_t, db_pgno_t, PAGE *, u_int32_t, DBT *));
static u_int32_t static u_int32_t
@ -84,11 +86,12 @@ __bam_iitem(dbc, key, data, op, flags)
DBT bk_hdr, tdbt; DBT bk_hdr, tdbt;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
PAGE *h; PAGE *h;
db_indx_t indx; db_indx_t cnt, indx;
u_int32_t data_size, have_bytes, need_bytes, needed; u_int32_t data_size, have_bytes, need_bytes, needed, pages, pagespace;
int cmp, bigkey, bigdata, dupadjust, padrec, replace, ret, was_deleted; int cmp, bigkey, bigdata, dupadjust, padrec, replace, ret, was_deleted;
COMPQUIET(bk, NULL); COMPQUIET(bk, NULL);
COMPQUIET(cnt, 0);
dbp = dbc->dbp; dbp = dbc->dbp;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
@ -217,13 +220,39 @@ __bam_iitem(dbc, key, data, op, flags)
return (__db_unknown_flag(dbenv, "DB->put", op)); return (__db_unknown_flag(dbenv, "DB->put", op));
} }
/* /* Split the page if there's not enough room. */
* 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.
*/
if (P_FREESPACE(dbp, h) < needed) if (P_FREESPACE(dbp, h) < needed)
return (DB_NEEDSPLIT); 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: * The code breaks it up into five cases:
* *
@ -259,7 +288,6 @@ __bam_iitem(dbc, key, data, op, flags)
return (ret); return (ret);
indx += 3; indx += 3;
dupadjust = 1;
cp->indx += 2; cp->indx += 2;
} else { } else {
@ -276,7 +304,6 @@ __bam_iitem(dbc, key, data, op, flags)
return (ret); return (ret);
++indx; ++indx;
dupadjust = 1;
} }
break; break;
case DB_CURRENT: 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 * will try and remove the item because the cursor's delete
* flag is set. * flag is set.
*/ */
(void)__bam_ca_delete(dbp, PGNO(h), indx, 0); if ((ret = __bam_ca_delete(dbp, PGNO(h), indx, 0, NULL)) != 0)
return (ret);
if (TYPE(h) == P_LBTREE) { if (TYPE(h) == P_LBTREE) {
++indx; ++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 * up at least 25% of the space on the page. If it does, move it onto
* its own page. * its own page.
*/ */
if (dupadjust && P_FREESPACE(dbp, h) <= dbp->pgsize / 2) { if (dupadjust &&
if ((ret = __bam_dup_convert(dbc, h, indx - O_INDX)) != 0) (ret = __bam_dup_convert(dbc, h, indx - O_INDX, cnt)) != 0)
return (ret); return (ret);
}
/* If we've modified a recno file, set the flag. */ /* If we've modified a recno file, set the flag. */
if (dbc->dbtype == DB_RECNO) 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. * Check to see if the duplicate set at indx should have its own page.
* If it should, create it.
*/ */
static int static int
__bam_dup_convert(dbc, h, indx) __bam_dup_check(dbc, op, h, indx, sz, cntp)
DBC *dbc; DBC *dbc;
u_int32_t op;
PAGE *h; PAGE *h;
u_int32_t indx; u_int32_t indx, sz;
db_indx_t *cntp;
{ {
BKEYDATA *bk; BKEYDATA *bk;
DB *dbp; DB *dbp;
DBT hdr; db_indx_t cnt, first, *inp;
DB_MPOOLFILE *mpf;
PAGE *dp;
db_indx_t cnt, cpindx, dindx, first, *inp, sz;
int ret;
dbp = dbc->dbp; dbp = dbc->dbp;
mpf = dbp->mpf;
inp = P_INP(dbp, h); inp = P_INP(dbp, h);
/* /*
@ -695,11 +717,21 @@ __bam_dup_convert(dbc, h, indx)
/* Count the key once. */ /* Count the key once. */
bk = GET_BKEYDATA(dbp, h, indx); 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; BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE;
/* Sum up all the data items. */ /* 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]; indx < NUM_ENT(h) && inp[first] == inp[indx];
++cnt, indx += P_INDX) { ++cnt, indx += P_INDX) {
bk = GET_BKEYDATA(dbp, h, indx + O_INDX); bk = GET_BKEYDATA(dbp, h, indx + O_INDX);
@ -726,6 +758,36 @@ __bam_dup_convert(dbc, h, indx)
if (sz < dbp->pgsize / 4) if (sz < dbp->pgsize / 4)
return (0); 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. */ /* Get a new page. */
if ((ret = __db_new(dbc, if ((ret = __db_new(dbc,
dbp->dup_compare == NULL ? P_LRECNO : P_LDUP, &dp)) != 0) dbp->dup_compare == NULL ? P_LRECNO : P_LDUP, &dp)) != 0)
@ -739,8 +801,8 @@ __bam_dup_convert(dbc, h, indx)
* we're dealing with. * we're dealing with.
*/ */
memset(&hdr, 0, sizeof(hdr)); memset(&hdr, 0, sizeof(hdr));
dindx = first; first = indx;
indx = first; dindx = indx;
cpindx = 0; cpindx = 0;
do { do {
/* Move cursors referencing the old entry to the new entry. */ /* Move cursors referencing the old entry to the new entry. */

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -58,7 +58,7 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
_lp = lp = np = pp = _rp = rp = NULL; _lp = lp = np = pp = _rp = rp = NULL;
sp = 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 * 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); REC_FGET(mpf, root_pgno, &pp, do_left);
cmp = cmp =
log_compare(&LSN(pp), &LSN(argp->pg.data)); log_compare(&LSN(pp), &LSN(argp->pg.data));
CHECK_LSN(op, CHECK_LSN(dbenv, op,
cmp, &LSN(pp), &LSN(argp->pg.data)); cmp, &LSN(pp), &LSN(argp->pg.data));
p_update = cmp == 0; p_update = cmp == 0;
} }
do_left: if (lp != NULL) { do_left: if (lp != NULL) {
cmp = log_compare(&LSN(lp), &argp->llsn); 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) if (cmp == 0)
l_update = 1; l_update = 1;
} }
if (rp != NULL) { if (rp != NULL) {
cmp = log_compare(&LSN(rp), &argp->rlsn); 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) if (cmp == 0)
r_update = 1; r_update = 1;
} }
@ -211,7 +211,7 @@ check_next: /*
goto done; goto done;
} }
cmp = log_compare(&LSN(np), &argp->nlsn); 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) { if (cmp == 0) {
PREV_PGNO(np) = argp->right; PREV_PGNO(np) = argp->right;
np->lsn = *lsnp; np->lsn = *lsnp;
@ -337,12 +337,13 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
PAGE *pagep; PAGE *pagep;
db_pgno_t pgno, root_pgno; db_pgno_t pgno, root_pgno;
db_recno_t rcnt;
int cmp_n, cmp_p, modified, ret; int cmp_n, cmp_p, modified, ret;
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_rsplit_print); REC_PRINT(__bam_rsplit_print);
REC_INTRO(__bam_rsplit_read, 1); REC_INTRO(__bam_rsplit_read, 1, 1);
/* Fix the root page. */ /* Fix the root page. */
pgno = root_pgno = argp->root_pgno; pgno = root_pgno = argp->root_pgno;
@ -361,10 +362,19 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->rootlsn); 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)) { 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); memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size);
if (LEVEL(pagep) > LEAFLEVEL)
RE_NREC_SET(pagep, rcnt);
pagep->pgno = root_pgno; pagep->pgno = root_pgno;
pagep->lsn = *lsnp; pagep->lsn = *lsnp;
modified = 1; modified = 1;
@ -403,7 +413,7 @@ do_page:
(void)__ua_memcpy(&copy_lsn, &LSN(argp->pgdbt.data), sizeof(DB_LSN)); (void)__ua_memcpy(&copy_lsn, &LSN(argp->pgdbt.data), sizeof(DB_LSN));
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &copy_lsn); 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 (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */ /* Need to redo update described. */
pagep->lsn = *lsnp; pagep->lsn = *lsnp;
@ -450,7 +460,7 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_adj_print); 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. */ /* Get the page; if it never existed and we're undoing, we're done. */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
@ -468,7 +478,7 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn); 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)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */ /* Need to redo update described. */
if ((ret = __bam_adjindx(dbc, if ((ret = __bam_adjindx(dbc,
@ -524,7 +534,7 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_cadjust_print); 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. */ /* Get the page; if it never existed and we're undoing, we're done. */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
@ -542,7 +552,7 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn); 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)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */ /* Need to redo update described. */
if (IS_BTREE_PAGE(pagep)) { if (IS_BTREE_PAGE(pagep)) {
@ -613,7 +623,7 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_cdel_print); 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. */ /* Get the page; if it never existed and we're undoing, we're done. */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
@ -631,7 +641,7 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn); 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)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */ /* Need to redo update described. */
indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0); 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); indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0);
B_DCLR(GET_BKEYDATA(file_dbp, pagep, indx)->type); 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; LSN(pagep) = argp->lsn;
modified = 1; modified = 1;
@ -689,7 +701,7 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_repl_print); 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. */ /* Get the page; if it never existed and we're undoing, we're done. */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
@ -708,7 +720,7 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn); 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)) { if (cmp_p == 0 && DB_REDO(op)) {
/* /*
* Need to redo update described. * Need to redo update described.
@ -799,7 +811,7 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info)
meta = NULL; meta = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_root_print); 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 = __memp_fget(mpf, &argp->meta_pgno, 0, &meta)) != 0) {
if (ret != DB_PAGE_NOTFOUND if (ret != DB_PAGE_NOTFOUND
@ -816,7 +828,7 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info)
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(meta)); cmp_n = log_compare(lsnp, &LSN(meta));
cmp_p = log_compare(&LSN(meta), &argp->meta_lsn); 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)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */ /* Need to redo update described. */
meta->root = argp->root_pgno; meta->root = argp->root_pgno;
@ -866,7 +878,7 @@ __bam_curadj_recover(dbenv, dbtp, lsnp, op, info)
COMPQUIET(mpf, NULL); COMPQUIET(mpf, NULL);
REC_PRINT(__bam_curadj_print); REC_PRINT(__bam_curadj_print);
REC_INTRO(__bam_curadj_read, 0); REC_INTRO(__bam_curadj_read, 0, 1);
ret = 0; ret = 0;
if (op != DB_TXN_ABORT) if (op != DB_TXN_ABORT)
@ -891,8 +903,9 @@ __bam_curadj_recover(dbenv, dbtp, lsnp, op, info)
break; break;
case DB_CA_SPLIT: case DB_CA_SPLIT:
__bam_ca_undosplit(file_dbp, argp->from_pgno, if ((ret = __bam_ca_undosplit(file_dbp, argp->from_pgno,
argp->to_pgno, argp->left_pgno, argp->from_indx); argp->to_pgno, argp->left_pgno, argp->from_indx)) != 0)
goto out;
break; break;
} }
@ -928,7 +941,7 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
rdbc = NULL; rdbc = NULL;
REC_PRINT(__bam_rcuradj_print); REC_PRINT(__bam_rcuradj_print);
REC_INTRO(__bam_rcuradj_read, 0); REC_INTRO(__bam_rcuradj_read, 0, 1);
ret = t_ret = 0; ret = t_ret = 0;
@ -1008,7 +1021,7 @@ __bam_relink_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_relink_print); 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 * 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 * the current page is the result of a split and is being recovered
* elsewhere, so all we need do is recover the next page. * elsewhere, so all we need do is recover the next page.
*/ */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { if ((ret = __memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
if (ret != DB_PAGE_NOTFOUND
#ifndef HAVE_FTRUNCATE
|| DB_REDO(op)
#endif
) {
ret = __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
} else
goto next2;
}
modified = 0;
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) {
/* Redo the relink. */
pagep->lsn = *lsnp;
modified = 1;
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
/* Undo the relink. */
pagep->next_pgno = argp->next;
pagep->prev_pgno = argp->prev;
pagep->lsn = argp->lsn;
modified = 1;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
pagep = NULL;
next2: if ((ret = __memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
if (ret != DB_PAGE_NOTFOUND if (ret != DB_PAGE_NOTFOUND
#ifndef HAVE_FTRUNCATE #ifndef HAVE_FTRUNCATE
|| DB_REDO(op) || DB_REDO(op)
@ -1062,24 +1044,24 @@ next2: if ((ret = __memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn_next); 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)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Redo the remove or undo the add. */ /* Redo the remove or replace. */
pagep->prev_pgno = argp->prev; if (argp->new_pgno == PGNO_INVALID)
pagep->prev_pgno = argp->prev;
else
pagep->prev_pgno = argp->new_pgno;
pagep->lsn = *lsnp;
modified = 1; modified = 1;
} else if (cmp_n == 0 && DB_UNDO(op)) { } 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->prev_pgno = argp->pgno;
pagep->lsn = argp->lsn_next;
modified = 1; 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) if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out; goto out;
pagep = NULL; pagep = NULL;
@ -1098,24 +1080,24 @@ prev: if ((ret = __memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) {
modified = 0; modified = 0;
cmp_p = log_compare(&LSN(pagep), &argp->lsn_prev); 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)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Redo the relink. */ /* 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; modified = 1;
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) { } else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
/* Undo the relink. */ /* Undo the relink. */
pagep->next_pgno = argp->pgno; pagep->next_pgno = argp->pgno;
pagep->lsn = argp->lsn_prev;
modified = 1; 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) if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out; goto out;
pagep = NULL; pagep = NULL;
@ -1127,3 +1109,281 @@ out: if (pagep != NULL)
(void)__memp_fput(mpf, pagep, 0); (void)__memp_fput(mpf, pagep, 0);
REC_CLOSE; 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. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1998-2004 * Copyright (c) 1998-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -69,7 +69,8 @@ __bam_truncate(dbc, countp)
ret = __bam_traverse(dbc, ret = __bam_traverse(dbc,
DB_LOCK_WRITE, dbc->internal->root, __db_truncate_callback, &trunc); DB_LOCK_WRITE, dbc->internal->root, __db_truncate_callback, &trunc);
*countp = trunc.count; if (countp != NULL)
*countp = trunc.count;
return (ret); return (ret);
} }

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -203,7 +203,6 @@ __ram_c_del(dbc)
DB *dbp; DB *dbp;
DB_LSN lsn; DB_LSN lsn;
DBT hdr, data; DBT hdr, data;
EPG *epg;
int exact, ret, stack, t_ret; int exact, ret, stack, t_ret;
dbp = dbc->dbp; dbp = dbc->dbp;
@ -280,21 +279,11 @@ __ram_c_del(dbc)
* are closed, and then clean it up. * are closed, and then clean it up.
*/ */
if (NUM_ENT(cp->page) == 0 && PGNO(cp->page) != cp->root) { 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 * We want to delete a single item out of the last page
* that we're not deleting. * 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 * 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)); 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(). * 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); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (BTREE_CURSOR *)dbc->internal; cp = (BTREE_CURSOR *)dbc->internal;
@ -789,7 +778,7 @@ __ram_ca(dbc_arg, op)
order <= cp->order) order <= cp->order)
order = cp->order + 1; order = cp->order + 1;
} }
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
} }
} else } else
order = INVALID_ORDER; order = INVALID_ORDER;
@ -798,7 +787,7 @@ __ram_ca(dbc_arg, op)
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (BTREE_CURSOR *)dbc->internal; cp = (BTREE_CURSOR *)dbc->internal;
@ -868,9 +857,9 @@ iafter: if (!adjusted && C_LESSTHAN(cp_arg, cp)) {
break; 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); return (found);
} }
@ -1037,6 +1026,18 @@ __ram_writeback(dbp)
return (0); 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. */ /* Allocate a cursor. */
if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0) if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)
return (ret); return (ret);
@ -1064,7 +1065,7 @@ __ram_writeback(dbp)
*/ */
if ((ret = if ((ret =
__ram_update(dbc, DB_MAX_RECORDS, 0)) != 0 && ret != DB_NOTFOUND) __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. * Close any existing file handle and re-open the file, truncating it.
@ -1082,18 +1083,6 @@ __ram_writeback(dbp)
goto err; 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, * We'll need the delimiter if we're doing variable-length records,
* and the pad character if we're doing fixed-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. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"
@ -100,44 +100,14 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
* *
* Retrieve the root page. * 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);
}
/* if ((ret = __bam_get_root(dbc, cp->root, stop, flags, &stack)) != 0)
* Decide if we need to save this page; if we do, write lock it. return (ret);
* We deliberately don't lock-couple on this call. If the tree lock_mode = cp->csp->lock_mode;
* is tiny, i.e., one page, and two threads are busily updating lock = cp->csp->lock;
* the root page, we're almost guaranteed deadlocks galore, as h = cp->csp->page;
* 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;
}
BT_STK_CLR(cp);
/* /*
* If appending to the tree, set the record number now -- we have the * If appending to the tree, set the record number now -- we have the
* root page locked. * root page locked.
@ -260,15 +230,15 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
} }
--indx; --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) { 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, BT_STK_PUSH(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret); cp, h, indx, lock, lock_mode, ret);
if (ret != 0) if (ret != 0)
@ -286,8 +256,8 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
* never unlock it. * never unlock it.
*/ */
if ((LF_ISSET(S_PARENT) && if ((LF_ISSET(S_PARENT) &&
(u_int8_t)(stop + 1) >= (u_int8_t)(h->level - 1)) || (u_int8_t)(stop + 1) >= (u_int8_t)(LEVEL(h) - 1)) ||
(h->level - 1) == LEAFLEVEL) (LEVEL(h) - 1) == LEAFLEVEL)
stack = 1; stack = 1;
if ((ret = __memp_fput(mpf, h, 0)) != 0) if ((ret = __memp_fput(mpf, h, 0)) != 0)

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -39,7 +39,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"
@ -57,6 +57,102 @@
#include "dbinc/lock.h" #include "dbinc/lock.h"
#include "dbinc/mp.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 -- * __bam_search --
* Search a btree for a key. * Search a btree for a key.
@ -65,12 +161,12 @@
* PUBLIC: const DBT *, u_int32_t, int, db_recno_t *, int *)); * PUBLIC: const DBT *, u_int32_t, int, db_recno_t *, int *));
*/ */
int int
__bam_search(dbc, root_pgno, key, flags, stop, recnop, exactp) __bam_search(dbc, root_pgno, key, flags, slevel, recnop, exactp)
DBC *dbc; DBC *dbc;
db_pgno_t root_pgno; db_pgno_t root_pgno;
const DBT *key; const DBT *key;
u_int32_t flags; u_int32_t flags;
int stop, *exactp; int slevel, *exactp;
db_recno_t *recnop; db_recno_t *recnop;
{ {
BTREE *t; 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, * 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 * if we're modifying record numbers, we have to lock the entire tree
* regardless. See btree.h for more details. * 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);
}
/* if (root_pgno == PGNO_INVALID)
* Decide if we need to save this page; if we do, write lock it. root_pgno = cp->root;
* We deliberately don't lock-couple on this call. If the tree if ((ret = __bam_get_root(dbc, root_pgno, slevel, flags, &stack)) != 0)
* is tiny, i.e., one page, and two threads are busily updating return (ret);
* the root page, we're almost guaranteed deadlocks galore, as lock_mode = cp->csp->lock_mode;
* each one gets a read lock and then blocks the other's attempt lock = cp->csp->lock;
* for a write lock. h = cp->csp->page;
*/
if (!stack && BT_STK_CLR(cp);
((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;
}
/* Choose a comparison function. */ /* Choose a comparison function. */
func = F_ISSET(dbc, DBC_OPD) ? func = F_ISSET(dbc, DBC_OPD) ?
@ -168,6 +217,23 @@ try_again:
for (;;) { for (;;) {
inp = P_INP(dbp, h); 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 * 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 * 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 * page, they're an index per page item. If we find an exact
* match on a leaf page, we're done. * match on a leaf page, we're done.
*/ */
adjust = TYPE(h) == P_LBTREE ? P_INDX : O_INDX;
for (base = 0, for (base = 0,
lim = NUM_ENT(h) / (db_indx_t)adjust; lim != 0; lim >>= 1) { lim = NUM_ENT(h) / (db_indx_t)adjust; lim != 0; lim >>= 1) {
indx = base + ((lim >> 1) * adjust); indx = base + ((lim >> 1) * adjust);
@ -183,8 +248,13 @@ try_again:
__bam_cmp(dbp, key, h, indx, func, &cmp)) != 0) __bam_cmp(dbp, key, h, indx, func, &cmp)) != 0)
goto err; goto err;
if (cmp == 0) { 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 found;
}
goto next; goto next;
} }
if (cmp > 0) { if (cmp > 0) {
@ -197,10 +267,12 @@ try_again:
* No match found. Base is the smallest index greater than * No match found. Base is the smallest index greater than
* key and may be zero or a last + O_INDX index. * 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. * 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; *exactp = 0;
if (LF_ISSET(S_EXACT)) { if (LF_ISSET(S_EXACT)) {
@ -218,6 +290,43 @@ try_again:
ret = t_ret; ret = t_ret;
return (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 * to find an undeleted record. This is handled by the
* calling routine. * calling routine.
*/ */
if (LF_ISSET(S_DEL) && cp->csp == cp->sp)
cp->csp++;
BT_STK_ENTER(dbp->dbenv, BT_STK_ENTER(dbp->dbenv,
cp, h, base, lock, lock_mode, ret); cp, h, base, lock, lock_mode, ret);
if (ret != 0) if (ret != 0)
@ -252,8 +363,12 @@ next: if (recnop != NULL)
pg = GET_BINTERNAL(dbp, h, indx)->pgno; 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 (LF_ISSET(S_STK_ONLY)) {
if (stop == h->level) { if (slevel == LEVEL(h)) {
BT_STK_NUM(dbp->dbenv, cp, h, indx, ret); BT_STK_NUM(dbp->dbenv, cp, h, indx, ret);
if ((t_ret = if ((t_ret =
__LPUT(dbc, lock)) != 0 && ret == 0) __LPUT(dbc, lock)) != 0 && ret == 0)
@ -278,13 +393,24 @@ next: if (recnop != NULL)
} }
} else if (stack) { } else if (stack) {
/* Return if this is the lowest page wanted. */ /* 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, BT_STK_ENTER(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret); cp, h, indx, lock, lock_mode, ret);
if (ret != 0) if (ret != 0)
goto err; goto err;
return (0); 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, BT_STK_PUSH(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret); cp, h, indx, lock, lock_mode, ret);
if (ret != 0) if (ret != 0)
@ -302,16 +428,69 @@ next: if (recnop != NULL)
* unlock it. * unlock it.
*/ */
if ((LF_ISSET(S_PARENT) && if ((LF_ISSET(S_PARENT) &&
(u_int8_t)(stop + 1) >= (u_int8_t)(h->level - 1)) || (u_int8_t)(slevel + 1) >= (LEVEL(h) - 1)) ||
(h->level - 1) == LEAFLEVEL) (LEVEL(h) - 1) == LEAFLEVEL)
stack = 1; stack = 1;
if ((ret = __memp_fput(mpf, h, 0)) != 0) /*
goto err; * Returning a subtree. See if we have hit the start
h = NULL; * 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 && if ((LF_ISSET(S_DEL) && NUM_ENT(h) == 1)) {
LF_ISSET(S_WRITE) ? DB_LOCK_WRITE : DB_LOCK_READ; 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, if ((ret = __db_lget(dbc,
LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) { LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) {
/* /*
@ -320,6 +499,8 @@ next: if (recnop != NULL)
* descending the tree holding read-locks. * descending the tree holding read-locks.
*/ */
(void)__LPUT(dbc, lock); (void)__LPUT(dbc, lock);
if (LF_ISSET(S_DEL | S_NEXT))
cp->csp++;
goto err; goto err;
} }
} }
@ -340,12 +521,12 @@ found: *exactp = 1;
* all duplicate sets that are not on overflow pages exist on a * all duplicate sets that are not on overflow pages exist on a
* single leaf page. * single leaf page.
*/ */
if (TYPE(h) == P_LBTREE) { if (TYPE(h) == P_LBTREE && NUM_ENT(h) > P_INDX) {
if (LF_ISSET(S_DUPLAST)) if (LF_ISSET(S_DUPLAST))
while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) && while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
inp[indx] == inp[indx + P_INDX]) inp[indx] == inp[indx + P_INDX])
indx += P_INDX; indx += P_INDX;
else else if (LF_ISSET(S_DUPFIRST))
while (indx > 0 && while (indx > 0 &&
inp[indx] == inp[indx - P_INDX]) inp[indx] == inp[indx - P_INDX])
indx -= P_INDX; indx -= P_INDX;
@ -406,8 +587,11 @@ found: *exactp = 1;
ret = t_ret; ret = t_ret;
if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0) if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret; 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); BT_STK_ENTER(dbp->dbenv, cp, h, indx, lock, lock_mode, ret);
}
if (ret != 0) if (ret != 0)
goto err; goto err;
@ -471,6 +655,13 @@ __bam_stkrel(dbc, flags)
*/ */
epg->page = NULL; 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 (LF_ISSET(STK_NOLOCK)) {
if ((t_ret = __LPUT(dbc, epg->lock)) != 0 && ret == 0) if ((t_ret = __LPUT(dbc, epg->lock)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
@ -480,7 +671,8 @@ __bam_stkrel(dbc, flags)
} }
/* Clear the stack, all pages have been released. */ /* Clear the stack, all pages have been released. */
BT_STK_CLR(cp); if (!LF_ISSET(STK_PGONLY))
BT_STK_CLR(cp);
return (ret); return (ret);
} }

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"
@ -56,7 +56,6 @@
static int __bam_broot __P((DBC *, PAGE *, PAGE *, PAGE *)); static int __bam_broot __P((DBC *, PAGE *, PAGE *, PAGE *));
static int __bam_page __P((DBC *, EPG *, EPG *)); 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_psplit __P((DBC *, EPG *, PAGE *, PAGE *, db_indx_t *));
static int __bam_root __P((DBC *, EPG *)); static int __bam_root __P((DBC *, EPG *));
static int __ram_root __P((DBC *, PAGE *, PAGE *, PAGE *)); 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 * 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. * 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; goto err;
/* /*
@ -349,7 +348,7 @@ __bam_page(dbc, pp, cp)
* a page that's not in our direct ancestry. Consider a cursor walking * a page that's not in our direct ancestry. Consider a cursor walking
* backward through the leaf pages, that has our following page locked, * 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 * 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. * through the tree isn't a common operation.
*/ */
if (ISLEAF(cp->page) && NEXT_PGNO(cp->page) != PGNO_INVALID) { if (ISLEAF(cp->page) && NEXT_PGNO(cp->page) != PGNO_INVALID) {
@ -685,13 +684,15 @@ __ram_root(dbc, rootp, lp, rp)
/* /*
* __bam_pinsert -- * __bam_pinsert --
* Insert a new key into a parent page, completing the split. * Insert a new key into a parent page, completing the split.
*
* PUBLIC: int __bam_pinsert __P((DBC *, EPG *, PAGE *, PAGE *, int));
*/ */
static int int
__bam_pinsert(dbc, parent, lchild, rchild, space_check) __bam_pinsert(dbc, parent, lchild, rchild, flags)
DBC *dbc; DBC *dbc;
EPG *parent; EPG *parent;
PAGE *lchild, *rchild; PAGE *lchild, *rchild;
int space_check; int flags;
{ {
BINTERNAL bi, *child_bi; BINTERNAL bi, *child_bi;
BKEYDATA *child_bk, *tmp_bk; 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. */ /* If handling record numbers, count records split to the right page. */
nrecs = F_ISSET(cp, C_RECNUM) && 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 * 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) if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT); return (DB_NEEDSPLIT);
if (space_check) if (LF_ISSET(BPI_SPACEONLY))
return (0); return (0);
/* Add a new record for the right page. */ /* 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); child_bk = GET_BKEYDATA(dbp, rchild, 0);
switch (B_TYPE(child_bk->type)) { switch (B_TYPE(child_bk->type)) {
case B_KEYDATA: 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 * We set t->bt_prefix to NULL if we have a comparison
* callback but no prefix compression callback. But, * callback but no prefix compression callback. But,
* if we're splitting in an off-page duplicates tree, * 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 * as there's no way for an application to specify a
* prefix compression callback that corresponds to its * prefix compression callback that corresponds to its
* comparison callback. * 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 (F_ISSET(dbc, DBC_OPD)) {
if (dbp->dup_compare == __bam_defcmp) if (dbp->dup_compare == __bam_defcmp)
@ -800,13 +813,8 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
func = NULL; func = NULL;
} else } else
func = t->bt_prefix; func = t->bt_prefix;
nbytes = BINTERNAL_PSIZE(child_bk->len);
nksize = child_bk->len;
if (func == NULL) if (func == NULL)
goto noprefix; goto noprefix;
if (ppage->prev_pgno == PGNO_INVALID && off <= 1)
goto noprefix;
tmp_bk = GET_BKEYDATA(dbp, lchild, NUM_ENT(lchild) - tmp_bk = GET_BKEYDATA(dbp, lchild, NUM_ENT(lchild) -
(TYPE(lchild) == P_LDUP ? O_INDX : P_INDX)); (TYPE(lchild) == P_LDUP ? O_INDX : P_INDX));
if (B_TYPE(tmp_bk->type) != B_KEYDATA) 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) if ((n = BINTERNAL_PSIZE(nksize)) < nbytes)
nbytes = n; nbytes = n;
else 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); return (DB_NEEDSPLIT);
if (space_check) if (LF_ISSET(BPI_SPACEONLY))
return (0); return (0);
memset(&bi, 0, sizeof(bi)); memset(&bi, 0, sizeof(bi));
@ -849,7 +857,7 @@ noprefix: nksize = child_bk->len;
if (P_FREESPACE(dbp, ppage) < nbytes) if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT); return (DB_NEEDSPLIT);
if (space_check) if (LF_ISSET(BPI_SPACEONLY))
return (0); return (0);
memset(&bi, 0, sizeof(bi)); memset(&bi, 0, sizeof(bi));
@ -883,7 +891,7 @@ noprefix: nksize = child_bk->len;
if (P_FREESPACE(dbp, ppage) < nbytes) if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT); return (DB_NEEDSPLIT);
if (space_check) if (LF_ISSET(BPI_SPACEONLY))
return (0); return (0);
/* Add a new record for the right page. */ /* 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 * 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. * 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. */ /* Log the change. */
if (DBC_LOGGING(dbc)) { if (DBC_LOGGING(dbc)) {
if ((ret = __bam_cadjust_log(dbp, dbc->txn, if ((ret = __bam_cadjust_log(dbp, dbc->txn,
&LSN(ppage), 0, PGNO(ppage), &LSN(ppage), 0, PGNO(ppage), &LSN(ppage),
&LSN(ppage), parent->indx, -(int32_t)nrecs, 0)) != 0) parent->indx, -(int32_t)nrecs, 0)) != 0)
return (ret); return (ret);
} else } else
LSN_NOT_LOGGED(LSN(ppage)); LSN_NOT_LOGGED(LSN(ppage));

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -155,7 +155,6 @@ meta_only:
/* Get metadata page statistics. */ /* Get metadata page statistics. */
sp->bt_metaflags = meta->dbmeta.flags; sp->bt_metaflags = meta->dbmeta.flags;
sp->bt_maxkey = meta->maxkey;
sp->bt_minkey = meta->minkey; sp->bt_minkey = meta->minkey;
sp->bt_re_len = meta->re_len; sp->bt_re_len = meta->re_len;
sp->bt_re_pad = meta->re_pad; sp->bt_re_pad = meta->re_pad;
@ -246,16 +245,12 @@ __bam_stat_print(dbc, flags)
} }
__db_msg(dbenv, "%s\tByte order", s); __db_msg(dbenv, "%s\tByte order", s);
__db_prflags(dbenv, NULL, sp->bt_metaflags, fn, NULL, "\tFlags"); __db_prflags(dbenv, NULL, sp->bt_metaflags, fn, NULL, "\tFlags");
if (dbp->type == DB_BTREE) { if (dbp->type == DB_BTREE)
#ifdef NOT_IMPLEMENTED
__db_dl(dbenv, "Maximum keys per-page", (u_long)sp->bt_maxkey);
#endif
__db_dl(dbenv, "Minimum keys per-page", (u_long)sp->bt_minkey); __db_dl(dbenv, "Minimum keys per-page", (u_long)sp->bt_minkey);
}
if (dbp->type == DB_RECNO) { if (dbp->type == DB_RECNO) {
__db_dl(dbenv, __db_dl(dbenv,
"Fixed-length record size", (u_long)sp->bt_re_len); "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); "%#x\tFixed-length record pad", (u_int)sp->bt_re_pad);
} }
__db_dl(dbenv, __db_dl(dbenv,

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1999-2004 * Copyright (c) 1999-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -89,10 +89,8 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
} else } else
pip->bt_minkey = meta->minkey; 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) */ /* 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; pip->re_len = meta->re_len;
/* /*
@ -1618,8 +1616,17 @@ bad_prev: isbad = 1;
if (relenp) if (relenp)
*relenp = relen; *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; nrecs += child_nrecs;
}
if (isbad == 0 && level != child_level + 1) { if (isbad == 0 && level != child_level + 1) {
isbad = 1; isbad = 1;
EPRINT((dbenv, EPRINT((dbenv,
@ -2037,38 +2044,36 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
DBT *key; DBT *key;
u_int32_t flags; u_int32_t flags;
{ {
DBT dbt, unkdbt;
DB_ENV *dbenv;
BKEYDATA *bk; BKEYDATA *bk;
BOVERFLOW *bo; BOVERFLOW *bo;
DBT dbt, unknown_key, unknown_data;
DB_ENV *dbenv;
VRFY_ITEM *pgmap; VRFY_ITEM *pgmap;
db_indx_t i, beg, end, *inp; db_indx_t i, last, beg, end, *inp;
u_int32_t himark; u_int32_t himark;
void *ovflbuf; void *ovflbuf;
int t_ret, ret, err_ret; int ret, t_ret, t2_ret;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
/* Shut up lint. */
COMPQUIET(end, 0);
ovflbuf = pgmap = NULL; ovflbuf = pgmap = NULL;
err_ret = ret = 0;
inp = P_INP(dbp, h); inp = P_INP(dbp, h);
memset(&dbt, 0, sizeof(DBT)); memset(&dbt, 0, sizeof(DBT));
dbt.flags = DB_DBT_REALLOC; dbt.flags = DB_DBT_REALLOC;
memset(&unkdbt, 0, sizeof(DBT)); memset(&unknown_key, 0, sizeof(DBT));
unkdbt.size = (u_int32_t)(strlen("UNKNOWN") + 1); unknown_key.size = (u_int32_t)strlen("UNKNOWN_KEY");
unkdbt.data = "UNKNOWN"; 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; * Allocate a buffer for overflow items. Start at one page;
* __db_safe_goff will realloc as needed. * __db_safe_goff will realloc as needed.
*/ */
if ((ret = __os_malloc(dbenv, dbp->pgsize, &ovflbuf)) != 0) if ((ret = __os_malloc(dbenv, dbp->pgsize, &ovflbuf)) != 0)
return (ret); goto err;
if (LF_ISSET(DB_AGGRESSIVE) && (ret = if (LF_ISSET(DB_AGGRESSIVE) && (ret =
__os_calloc(dbenv, dbp->pgsize, sizeof(pgmap[0]), &pgmap)) != 0) __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. * 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 salvaging normally, loop from 0 through NUM_ENT(h). If
* If we're being aggressive, loop until we hit the end of the page-- * we're being aggressive, loop until we hit the end of the page --
* NUM_ENT() may be bogus. * NUM_ENT() may be bogus.
*/ */
himark = dbp->pgsize; 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 we're not aggressive, break when we hit NUM_ENT(h). */
if (!LF_ISSET(DB_AGGRESSIVE) && i >= NUM_ENT(h)) if (!LF_ISSET(DB_AGGRESSIVE) && i >= NUM_ENT(h))
break; break;
/* Verify the current item. */ /* Verify the current item. */
ret = __db_vrfy_inpitem(dbp, t_ret =
h, pgno, i, 1, flags, &himark, NULL); __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) { if (t_ret != 0) {
/* /*
* Don't return DB_VERIFY_FATAL; it's private * If this is a btree leaf and we've printed out a key
* and means only that we can't go on with this * but not its associated data item, fix this imbalance
* page, not with the whole database. It's * by printing an "UNKNOWN_DATA".
* not even an error if we've run into it
* after NUM_ENT(h).
*/ */
ret = (i < NUM_ENT(h)) ? DB_VERIFY_BAD : 0; if (pgtype == P_LBTREE && i % P_INDX == 1 &&
break; 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) * If this returned 0, it's safe to print or (carefully)
* try to fetch. * try to fetch.
*
* We only print deleted items if DB_AGGRESSIVE is set.
*/ */
if (ret == 0) { bk = GET_BKEYDATA(dbp, h, i);
/* if (!LF_ISSET(DB_AGGRESSIVE) && B_DISSET(bk->type))
* We only want to print deleted items if continue;
* DB_AGGRESSIVE is set.
*/
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 * If this is a btree leaf and we're about to print out a data
* key is non-NULL, we're a dup page, so we've got to * item for which we didn't print out a key, fix this imbalance
* print the key first, unless SA_SKIPFIRSTKEY is set * by printing an "UNKNOWN_KEY".
* and we're on the first entry. */
*/ if (pgtype == P_LBTREE && i % P_INDX == 1 &&
if (key != NULL && last != i - 1 && (t_ret = __db_vrfy_prdbt(
(i != 0 || !LF_ISSET(SA_SKIPFIRSTKEY))) &unknown_key, 0, " ", handle, callback, 0, vdp)) != 0) {
if ((ret = __db_vrfy_prdbt(key, if (ret == 0)
0, " ", handle, callback, 0, vdp)) != 0) ret = t_ret;
err_ret = ret; goto err;
}
last = i;
beg = inp[i]; /*
switch (B_TYPE(bk->type)) { * We're going to go try to print the next item. If key is
case B_DUPLICATE: * non-NULL, we're a dup page, so we've got to print the key
end = beg + BOVERFLOW_SIZE - 1; * first, unless SA_SKIPFIRSTKEY is set and we're on the first
/* * entry.
* If we're not on a normal btree leaf page, */
* there shouldn't be off-page if (key != NULL && (i != 0 || !LF_ISSET(SA_SKIPFIRSTKEY)))
* dup sets. Something's confused; just if ((t_ret = __db_vrfy_prdbt(key,
* drop it, and the code to pick up unlinked 0, " ", handle, callback, 0, vdp)) != 0) {
* offpage dup sets will print it out if (ret == 0)
* with key "UNKNOWN" later. ret = t_ret;
*/ goto err;
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);
} }
beg = inp[i];
switch (B_TYPE(bk->type)) {
case B_DUPLICATE:
end = beg + BOVERFLOW_SIZE - 1;
/* /*
* If we're being aggressive, mark the beginning * If we're not on a normal btree leaf page, there
* and end of the item; we'll come back and print * shouldn't be off-page dup sets. Something's
* whatever "junk" is in the gaps in case we had * confused; just drop it, and the code to pick up
* any bogus inp elements and thereby missed stuff. * unlinked offpage dup sets will print it out
* with key "UNKNOWN" later.
*/ */
if (LF_ISSET(DB_AGGRESSIVE)) { if (pgtype != P_LBTREE)
pgmap[beg] = VRFY_ITEM_BEGIN; break;
pgmap[end] = VRFY_ITEM_END;
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) err: if (pgmap != NULL)
__os_free(dbenv, pgmap); __os_free(dbenv, pgmap);
__os_free(dbenv, ovflbuf); if (ovflbuf != NULL)
__os_free(dbenv, ovflbuf);
/* Mark this page as done. */ /* Mark this page as done. */
if ((t_ret = __db_salvage_markdone(vdp, pgno)) != 0) if ((t_ret = __db_salvage_markdone(vdp, pgno)) != 0 && ret == 0)
return (t_ret); 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. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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 PREFIX __bam
@ -210,10 +210,10 @@ END
BEGIN relink 147 BEGIN relink 147
/* Fileid of db affected. */ /* Fileid of db affected. */
DB fileid int32_t ld DB fileid int32_t ld
/* The page being changed. */ /* The page being removed. */
ARG pgno db_pgno_t lu ARG pgno db_pgno_t lu
/* The page's original lsn. */ /* The new page number, if any. */
POINTER lsn DB_LSN * lu ARG new_pgno db_pgno_t lu
/* The previous page. */ /* The previous page. */
ARG prev db_pgno_t lu ARG prev db_pgno_t lu
/* The previous page's original lsn. */ /* The previous page's original lsn. */
@ -223,3 +223,30 @@ ARG next db_pgno_t lu
/* The previous page's original lsn. */ /* The previous page's original lsn. */
POINTER lsn_next DB_LSN * lu POINTER lsn_next DB_LSN * lu
END 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 Project_Dep_Name db_deadlock
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name DB_DLL Project_Dep_Name db_dll
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_dump Project_Dep_Name db_dump
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_hotbackup
End Project Dependency
Begin Project Dependency
Project_Dep_Name db_load Project_Dep_Name db_load
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
@ -45,7 +48,7 @@ Package=<4>
Project_Dep_Name db_verify Project_Dep_Name db_verify
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name DB_Static Project_Dep_Name db_static
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name ex_access Project_Dep_Name ex_access
@ -63,9 +66,18 @@ Package=<4>
Project_Dep_Name ex_mpool Project_Dep_Name ex_mpool
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name ex_sequence
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_tpcb Project_Dep_Name ex_tpcb
End Project Dependency End Project Dependency
Begin 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 Project_Dep_Name excxx_access
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
@ -81,10 +93,31 @@ Package=<4>
Project_Dep_Name excxx_mpool Project_Dep_Name excxx_mpool
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name excxx_sequence
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_tpcb Project_Dep_Name excxx_tpcb
End Project Dependency End Project Dependency
Begin 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 End Project Dependency
}}} }}}
@ -99,7 +132,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -114,7 +147,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -129,7 +162,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name DB_DLL Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -156,7 +189,22 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency 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 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> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_dll Project_Dep_Name db_dll
End Project Dependency End Project Dependency
Begin Project Dependency
Project_Dep_Name db_static
End Project Dependency
}}} }}}
############################################################################### ###############################################################################
@ -204,7 +234,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -219,7 +249,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -234,12 +264,24 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency 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> Project: "db_stat"=.\db_stat.dsp - Package Owner=<4>
Package=<5> Package=<5>
@ -249,7 +291,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -276,7 +318,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name DB_DLL Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -309,7 +351,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -324,7 +366,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -339,7 +381,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -354,7 +396,58 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency 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 End Project Dependency
}}} }}}
@ -369,7 +462,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -384,7 +477,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -399,7 +492,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -414,7 +507,22 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency 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 End Project Dependency
}}} }}}
@ -429,7 +537,67 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency 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 End Project Dependency
}}} }}}
@ -444,7 +612,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -459,7 +627,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -474,7 +642,37 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency 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 End Project Dependency
}}} }}}
@ -489,7 +687,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -504,7 +702,22 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency 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 End Project Dependency
}}} }}}
@ -519,7 +732,37 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency 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 End Project Dependency
}}} }}}

View file

@ -4,7 +4,7 @@
# TARGTYPE "Win32 (x86) Console Application" 0x0103 # 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 This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run !MESSAGE use the Export Makefile command and run
!MESSAGE !MESSAGE
@ -13,14 +13,18 @@ CFG=@project_name@ - Win32 Debug Static
!MESSAGE You can specify a configuration when running NMAKE !MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE !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
!MESSAGE Possible choices for configuration are: !MESSAGE Possible choices for configuration are:
!MESSAGE !MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Console Application") !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 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Release Static" (based on "Win32 (x86) Console Application") !MESSAGE "@project_name@ - Win32 ASCII Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Debug Static" (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 !MESSAGE
# Begin Project # Begin Project
@ -34,99 +38,207 @@ RSC=rc.exe
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0 # PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release" # PROP BASE Output_Dir "@bin_rel_dest@"
# PROP BASE Intermediate_Dir "Release" # PROP BASE Intermediate_Dir "Release/@project_name@"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 0 # PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release" # PROP Output_Dir "@bin_rel_dest@"
# PROP Intermediate_Dir "Release" # PROP Intermediate_Dir "Release/@project_name@"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /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" /D "_MBCS" /YX /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 BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe 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 BASE LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.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 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" !ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug"
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1 # PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug" # PROP BASE Output_Dir "@bin_debug_dest@"
# PROP BASE Intermediate_Dir "Debug" # PROP BASE Intermediate_Dir "Debug/@project_name@"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 1 # PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug" # PROP Output_Dir "@bin_debug_dest@"
# PROP Intermediate_Dir "Debug" # PROP Intermediate_Dir "Debug/@project_name@"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /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" /D "_MBCS" /YX /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 BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe 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 BASE LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.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 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_MFC 0
# PROP BASE Use_Debug_Libraries 0 # PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release" # PROP BASE Output_Dir "@bin_rel_dest@_ASCII"
# PROP BASE Intermediate_Dir "Release" # PROP BASE Intermediate_Dir "Release_ASCII/@project_name@"
# PROP BASE Ignore_Export_Lib 0 # PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 0 # PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_static" # PROP Output_Dir "@bin_rel_dest@_ASCII"
# PROP Intermediate_Dir "Release_static" # PROP Intermediate_Dir "Release_ASCII/@project_name@"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # 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 BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /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" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 Release_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.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 Release_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.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@_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_MFC 0
# PROP BASE Use_Debug_Libraries 1 # PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug" # PROP BASE Output_Dir "@bin_debug_dest@_AMD64"
# PROP BASE Intermediate_Dir "Debug" # PROP BASE Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP BASE Ignore_Export_Lib 0 # PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 1 # PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_static" # PROP Output_Dir "@bin_debug_dest@_AMD64"
# PROP Intermediate_Dir "Debug_static" # PROP Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # 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 BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /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 BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe 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 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 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 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 !ENDIF
@ -134,8 +246,12 @@ LINK32=link.exe
# Name "@project_name@ - Win32 Release" # Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug" # Name "@project_name@ - Win32 Debug"
# Name "@project_name@ - Win32 Release Static" # Name "@project_name@ - Win32 ASCII Debug"
# Name "@project_name@ - Win32 Debug Static" # 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@ @SOURCE_FILES@
# Begin Source File # Begin Source File

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1999-2004 * Copyright (c) 1999-2005
* Sleepycat Software. All rights reserved. * 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 - * Kill -

View file

@ -19,6 +19,12 @@ CFG=@project_name@ - Win32 Debug
!MESSAGE !MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !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 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 !MESSAGE
# Begin Project # Begin Project
@ -33,17 +39,17 @@ RSC=rc.exe
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0 # PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release" # PROP BASE Output_Dir "@lib_rel_dest@"
# PROP BASE Intermediate_Dir "Release" # PROP BASE Intermediate_Dir "Release/@project_name@"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 0 # PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release" # PROP Output_Dir "@lib_rel_dest@"
# PROP Intermediate_Dir "Release" # PROP Intermediate_Dir "Release/@project_name@"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /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 "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "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 BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD 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 BASE RSC /l 0x409 /d "NDEBUG"
@ -52,24 +58,25 @@ BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe 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 BASE LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.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 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" !ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug"
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1 # PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug" # PROP BASE Output_Dir "@lib_debug_dest@"
# PROP BASE Intermediate_Dir "Debug" # PROP BASE Intermediate_Dir "Debug/@project_name@"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 2 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 1 # PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug" # PROP Output_Dir "@lib_debug_dest@"
# PROP Intermediate_Dir "Debug" # PROP Intermediate_Dir "Debug/@project_name@"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /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 "DB_CREATE_DLL" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c # ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "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 # SUBTRACT CPP /Fr
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD 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 BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe 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 BASE LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.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 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 !ENDIF
@ -88,6 +269,13 @@ LINK32=link.exe
# Name "@project_name@ - Win32 Release" # Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug" # 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@ @SOURCE_FILES@
# End Target # End Target
# End Project # 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' DESCRIPTION 'Berkeley DB TCL interface Library'
EXPORTS EXPORTS

View file

@ -17,11 +17,11 @@ BEGIN
BLOCK "040904b0" BLOCK "040904b0"
BEGIN BEGIN
VALUE "CompanyName", "Sleepycat Software\0" 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 "FileVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
VALUE "InternalName", "libdb.dll\0" VALUE "InternalName", "libdb%MAJOR%%MINOR%.dll\0"
VALUE "LegalCopyright", "Copyright © Sleepycat Software Inc. 1997-2004\0" VALUE "LegalCopyright", "Copyright © Sleepycat Software Inc. 1997-2005\0"
VALUE "OriginalFilename", "libdb.dll\0" VALUE "OriginalFilename", "libdb%MAJOR%%MINOR%.dll\0"
VALUE "ProductName", "Sleepycat Software libdb\0" VALUE "ProductName", "Sleepycat Software libdb\0"
VALUE "ProductVersion", "%MAJOR%.%MINOR%.%PATCH%\0" VALUE "ProductVersion", "%MAJOR%.%MINOR%.%PATCH%\0"
END END

View file

@ -4,7 +4,7 @@
# TARGTYPE "Win32 (x86) Static Library" 0x0104 # 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 This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run !MESSAGE use the Export Makefile command and run
!MESSAGE !MESSAGE
@ -13,12 +13,18 @@ CFG=@project_name@ - Win32 Debug Static
!MESSAGE You can specify a configuration when running NMAKE !MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE !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
!MESSAGE Possible choices for configuration are: !MESSAGE Possible choices for configuration are:
!MESSAGE !MESSAGE
!MESSAGE "@project_name@ - Win32 Release Static" (based on "Win32 (x86) Static Library") !MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "@project_name@ - Win32 Debug Static" (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 !MESSAGE
# Begin Project # Begin Project
@ -28,58 +34,202 @@ CFG=@project_name@ - Win32 Debug Static
CPP=cl.exe CPP=cl.exe
RSC=rc.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_MFC 0
# PROP BASE Use_Debug_Libraries 0 # PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release_static" # PROP BASE Output_Dir "@lib_rel_dest@"
# PROP BASE Intermediate_Dir "Release_static" # PROP BASE Intermediate_Dir "Release/@project_name@"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 0 # PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_static" # PROP Output_Dir "@lib_rel_dest@"
# PROP Intermediate_Dir "Release_static" # PROP Intermediate_Dir "Release/@project_name@"
# PROP Target_Dir "" # 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 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 /MT /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /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 BASE RSC /l 0xc09
# ADD RSC /l 0xc09 # ADD RSC /l 0xc09
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LIB32=link.exe -lib LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"Release/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:"Release_static/libdb@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 Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug_static" # PROP BASE Output_Dir "@lib_debug_dest@"
# PROP BASE Intermediate_Dir "Debug_static" # PROP BASE Intermediate_Dir "Debug/@project_name@"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 1 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 1 # PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_static" # PROP Output_Dir "@lib_debug_dest@"
# PROP Intermediate_Dir "Debug_static" # PROP Intermediate_Dir "Debug/@project_name@"
# PROP Target_Dir "" # 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 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 /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c # ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DIAGNOSTIC" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0xc09 # ADD BASE RSC /l 0xc09
# ADD RSC /l 0xc09 # ADD RSC /l 0xc09
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LIB32=link.exe -lib LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"Debug/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:"Debug_static/libdb@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 !ENDIF
# Begin Target # Begin Target
# Name "@project_name@ - Win32 Release Static" # Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug Static" # 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@ @SOURCE_FILES@
# End Target # End Target
# End Project # End Project

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -26,9 +26,5 @@ int
raise(s) raise(s)
int 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)); return (kill(getpid(), s));
} }

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

View file

@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"

View file

@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"

View file

@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"

View file

@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -32,9 +32,9 @@ __crypto_region_init(dbenv)
infop = dbenv->reginfo; infop = dbenv->reginfo;
renv = infop->primary; renv = infop->primary;
MUTEX_LOCK(dbenv, &renv->mutex); MUTEX_LOCK(dbenv, renv->mtx_regenv);
ret = !(renv->cipher_off == INVALID_ROFF); ret = !(renv->cipher_off == INVALID_ROFF);
MUTEX_UNLOCK(dbenv, &renv->mutex); MUTEX_UNLOCK(dbenv, renv->mtx_regenv);
if (ret == 0) if (ret == 0)
return (0); return (0);

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #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. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -22,6 +22,7 @@
#include "dbinc/db_shash.h" #include "dbinc/db_shash.h"
#include "dbinc/lock.h" #include "dbinc/lock.h"
#include "dbinc/log.h" #include "dbinc/log.h"
#include "dbinc/mp.h"
#include "dbinc/txn.h" #include "dbinc/txn.h"
static void __db_msgcall __P((const DB_ENV *, const char *, va_list)); static void __db_msgcall __P((const DB_ENV *, const char *, va_list));
@ -88,7 +89,7 @@ __db_fnl(dbenv, name)
const char *name; const char *name;
{ {
__db_err(dbenv, __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); name);
return (EINVAL); return (EINVAL);
} }
@ -186,7 +187,7 @@ __db_panic(dbenv, errval)
int errval; int errval;
{ {
if (dbenv != NULL) { if (dbenv != NULL) {
PANIC_SET(dbenv, 1); __db_panic_set(dbenv, 1);
__db_err(dbenv, "PANIC: %s", db_strerror(errval)); __db_err(dbenv, "PANIC: %s", db_strerror(errval));
@ -213,6 +214,22 @@ __db_panic(dbenv, errval)
return (DB_RUNRECOVERY); 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 -- * db_strerror --
* ANSI C strerror(3) for DB. * ANSI C strerror(3) for DB.
@ -275,8 +292,16 @@ db_strerror(error)
return ("DB_REP_HANDLE_DEAD: Handle is no longer valid"); return ("DB_REP_HANDLE_DEAD: Handle is no longer valid");
case DB_REP_HOLDELECTION: case DB_REP_HOLDELECTION:
return ("DB_REP_HOLDELECTION: Need to hold an election"); return ("DB_REP_HOLDELECTION: Need to hold an election");
case DB_REP_IGNORE:
return ("DB_REP_IGNORE: Replication record ignored");
case DB_REP_ISPERM: case DB_REP_ISPERM:
return ("DB_REP_ISPERM: Permanent record written"); 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: case DB_REP_NEWMASTER:
return ("DB_REP_NEWMASTER: A new master has declared itself"); return ("DB_REP_NEWMASTER: A new master has declared itself");
case DB_REP_NEWSITE: case DB_REP_NEWSITE:
@ -502,59 +527,6 @@ __db_msgfile(dbenv, fmt, ap)
(void)fflush(fp); (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 * __db_unknown_flag -- report internal error
* *
@ -620,38 +592,14 @@ __db_check_txn(dbp, txn, assoc_lid, read_op)
/* /*
* Check for common transaction errors: * Check for common transaction errors:
* Failure to pass a transaction handle to a DB operation * an operation on a handle whose open commit hasn't completed.
* Failure to configure the DB handle in a proper environment * a transaction handle in a non-transactional environment
* Operation on a handle whose open commit hasn't completed. * a transaction handle for a non-transactional database
*
* 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.
*/ */
if (txn == NULL) { 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) if (dbp->cur_lid >= TXN_MINIMUM)
goto open_err; goto open_err;
} else { } 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)) if (!TXN_ON(dbenv))
return (__db_not_txn_env(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"); "Transaction specified for a DB handle opened outside a transaction");
return (EINVAL); 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); 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); return (0);
open_err: open_err:
__db_err(dbenv, __db_err(dbenv,
@ -738,6 +708,69 @@ __db_rec_repl(dbenv, data_size, data_dlen)
return (EINVAL); 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 -- * __db_check_lsn --
* Display the log sequence error message. * Display the log sequence error message.
@ -755,3 +788,53 @@ __db_check_lsn(dbenv, lsn, prev)
(u_long)(prev)->file, (u_long)(prev)->offset); (u_long)(prev)->file, (u_long)(prev)->offset);
return (EINVAL); 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. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 2001-2004 * Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 2001-2004 * Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 2000-2004 * Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 2000-2004 * Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -40,16 +40,18 @@ __db_util_logset(progname, fname)
const char *progname; const char *progname;
char *fname; char *fname;
{ {
pid_t pid;
db_threadid_t tid;
FILE *fp; FILE *fp;
time_t now; time_t now;
u_int32_t id;
if ((fp = fopen(fname, "w")) == NULL) if ((fp = fopen(fname, "w")) == NULL)
goto err; goto err;
(void)time(&now); (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) if (fclose(fp) == EOF)
goto err; goto err;

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 2000-2004 * Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

View file

@ -1,13 +1,13 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 2001-2004 * Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* Some parts of this code originally written by Adam Stubblefield, * Some parts of this code originally written by Adam Stubblefield,
* -- astubble@rice.edu. * -- 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" #include "db_config.h"

View file

@ -1,13 +1,13 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* Some parts of this code originally written by Adam Stubblefield * Some parts of this code originally written by Adam Stubblefield
* -- astubble@rice.edu * -- 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" #include "db_config.h"
@ -40,35 +40,31 @@ __crypto_region_init(dbenv)
ret = 0; ret = 0;
infop = dbenv->reginfo; infop = dbenv->reginfo;
renv = infop->primary; renv = infop->primary;
MUTEX_LOCK(dbenv, &renv->mutex);
if (renv->cipher_off == INVALID_ROFF) { if (renv->cipher_off == INVALID_ROFF) {
if (!CRYPTO_ON(dbenv)) if (!CRYPTO_ON(dbenv))
goto err; return (0);
if (!F_ISSET(infop, REGION_CREATE)) { if (!F_ISSET(infop, REGION_CREATE)) {
__db_err(dbenv, __db_err(dbenv,
"Joining non-encrypted environment with encryption key"); "Joining non-encrypted environment with encryption key");
ret = EINVAL; return (EINVAL);
goto err;
} }
if (F_ISSET(db_cipher, CIPHER_ANY)) { if (F_ISSET(db_cipher, CIPHER_ANY)) {
__db_err(dbenv, "Encryption algorithm not supplied"); __db_err(dbenv, "Encryption algorithm not supplied");
ret = EINVAL; return (EINVAL);
goto err;
} }
/* /*
* Must create the shared information. We need: * Must create the shared information. We need: Shared cipher
* Shared cipher information that contains the passwd. * information that contains the passwd. After we copy the
* After we copy the passwd, we smash and free the one in the * passwd, we smash and free the one in the dbenv.
* dbenv.
*/ */
if ((ret = __db_shalloc( if ((ret =
infop, sizeof(CIPHER), MUTEX_ALIGN, &cipher)) != 0) __db_shalloc(infop, sizeof(CIPHER), 0, &cipher)) != 0)
goto err; return (ret);
memset(cipher, 0, sizeof(*cipher)); memset(cipher, 0, sizeof(*cipher));
if ((ret = __db_shalloc( if ((ret = __db_shalloc(
infop, dbenv->passwd_len, 0, &sh_passwd)) != 0) { infop, dbenv->passwd_len, 0, &sh_passwd)) != 0) {
__db_shalloc_free(infop, cipher); __db_shalloc_free(infop, cipher);
goto err; return (ret);
} }
memset(sh_passwd, 0, dbenv->passwd_len); memset(sh_passwd, 0, dbenv->passwd_len);
cipher->passwd = R_OFFSET(infop, sh_passwd); cipher->passwd = R_OFFSET(infop, sh_passwd);
@ -79,51 +75,44 @@ __crypto_region_init(dbenv)
} else { } else {
if (!CRYPTO_ON(dbenv)) { if (!CRYPTO_ON(dbenv)) {
__db_err(dbenv, __db_err(dbenv,
"Encrypted environment: no encryption key supplied"); "Encrypted environment: no encryption key supplied");
ret = EINVAL; return (EINVAL);
goto err;
} }
cipher = R_ADDR(infop, renv->cipher_off); cipher = R_ADDR(infop, renv->cipher_off);
sh_passwd = R_ADDR(infop, cipher->passwd); sh_passwd = R_ADDR(infop, cipher->passwd);
if ((cipher->passwd_len != dbenv->passwd_len) || if ((cipher->passwd_len != dbenv->passwd_len) ||
memcmp(dbenv->passwd, sh_passwd, cipher->passwd_len) != 0) { memcmp(dbenv->passwd, sh_passwd, cipher->passwd_len) != 0) {
__db_err(dbenv, "Invalid password"); __db_err(dbenv, "Invalid password");
ret = EPERM; return (EPERM);
goto err;
} }
if (!F_ISSET(db_cipher, CIPHER_ANY) && if (!F_ISSET(db_cipher, CIPHER_ANY) &&
db_cipher->alg != cipher->flags) { db_cipher->alg != cipher->flags) {
__db_err(dbenv, __db_err(dbenv,
"Environment encrypted using a different algorithm"); "Environment encrypted using a different algorithm");
ret = EINVAL; return (EINVAL);
goto err;
} }
if (F_ISSET(db_cipher, CIPHER_ANY)) if (F_ISSET(db_cipher, CIPHER_ANY))
/* /*
* We have CIPHER_ANY and we are joining the * We have CIPHER_ANY and we are joining the existing
* existing env. Setup our cipher structure * env. Setup our cipher structure for whatever
* for whatever algorithm this env has. * algorithm this env has.
*/ */
if ((ret = __crypto_algsetup(dbenv, db_cipher, if ((ret = __crypto_algsetup(dbenv, db_cipher,
cipher->flags, 0)) != 0) cipher->flags, 0)) != 0)
goto err; return (ret);
} }
MUTEX_UNLOCK(dbenv, &renv->mutex);
ret = db_cipher->init(dbenv, db_cipher); ret = db_cipher->init(dbenv, db_cipher);
/* /*
* On success, no matter if we allocated it or are using the * On success, no matter if we allocated it or are using the already
* already existing one, we are done with the passwd in the dbenv. * existing one, we are done with the passwd in the dbenv. We smash
* We smash N-1 bytes so that we don't overwrite the nul. * N-1 bytes so that we don't overwrite the nul.
*/ */
memset(dbenv->passwd, 0xff, dbenv->passwd_len-1); memset(dbenv->passwd, 0xff, dbenv->passwd_len-1);
__os_free(dbenv, dbenv->passwd); __os_free(dbenv, dbenv->passwd);
dbenv->passwd = NULL; dbenv->passwd = NULL;
dbenv->passwd_len = 0; dbenv->passwd_len = 0;
if (0) {
err: MUTEX_UNLOCK(dbenv, &renv->mutex);
}
return (ret); return (ret);
} }
@ -236,33 +225,54 @@ __crypto_decrypt_meta(dbenv, dbp, mbuf, do_metachk)
u_int8_t *iv; u_int8_t *iv;
/* /*
* If we weren't given a dbp, we just want to decrypt the page * If we weren't given a dbp, we just want to decrypt the page on
* on behalf of some internal subsystem, not on behalf of a user * behalf of some internal subsystem, not on behalf of a user with
* with a dbp. Therefore, set up a dummy dbp so that the call * a dbp. Therefore, set up a dummy dbp so that the call to
* to P_OVERHEAD below works. * P_OVERHEAD below works.
*/ */
if (dbp == NULL) { if (dbp == NULL) {
memset(&dummydb, 0, sizeof(DB)); memset(&dummydb, 0, sizeof(DB));
dbp = &dummydb; 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; ret = 0;
meta = (DBMETA *)mbuf; 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) { if (meta->encrypt_alg != 0) {
db_cipher = (DB_CIPHER *)dbenv->crypto_handle; db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
if (!F_ISSET(dbp, DB_AM_ENCRYPT)) { if (!F_ISSET(dbp, DB_AM_ENCRYPT)) {
@ -272,11 +282,10 @@ __crypto_decrypt_meta(dbenv, dbp, mbuf, do_metachk)
return (EINVAL); return (EINVAL);
} }
/* /*
* User has a correct, secure env, but has * User has a correct, secure env, but has encountered
* encountered a database in that env that is * a database in that env that is secure, but user
* secure, but user didn't dbp->set_flags. Since * didn't dbp->set_flags. Since it is existing, use
* it is existing, use encryption if it is that * encryption if it is that way already.
* way already.
*/ */
F_SET(dbp, DB_AM_ENCRYPT|DB_AM_CHKSUM); 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)); DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM));
iv = ((BTMETA *)mbuf)->iv; iv = ((BTMETA *)mbuf)->iv;
/* /*
* For ALL pages, we do not encrypt the beginning * For ALL pages, we do not encrypt the beginning of the page
* of the page that contains overhead information. * that contains overhead information. This is true of meta
* This is true of meta and all other pages. * and all other pages.
*/ */
pg_off = P_OVERHEAD(dbp); pg_off = P_OVERHEAD(dbp);
alg_retry: alg_retry:
@ -330,10 +339,10 @@ alg_retry:
goto alg_retry; goto alg_retry;
} else if (F_ISSET(dbp, DB_AM_ENCRYPT)) { } else if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
/* /*
* They gave us a passwd, but the database is not * They gave us a passwd, but the database is not encrypted.
* encrypted. This is an error. We do NOT want to * This is an error. We do NOT want to silently allow them
* silently allow them to write data in the clear when * to write data in the clear when the user set up and expects
* the user set up and expects encrypted data. * encrypted data.
* *
* This covers at least the following scenario. * This covers at least the following scenario.
* 1. User creates and sets up an encrypted database. * 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); cipher = R_ADDR(infop, renv->cipher_off);
sh_passwd = R_ADDR(infop, cipher->passwd); 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; 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 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 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> <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 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 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>, <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 we set the encryption, decryption and checksumming methods to the appropriate
functions based on the flags.&nbsp; This function will allocate us a crypto 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 other subsystems.&nbsp; For now, only AES ciphering functions and SHA1
checksumming functions are supported.&nbsp; Also we will copy the password 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 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, 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 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 will allocate a structure that will be used in initialization and set up
the function pointers to point to the algorithm-specific functions. 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 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 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 size.&nbsp; This guarantees sufficient space for storing the password in
shared memory.&nbsp; Then we will call a new function to initialize the 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 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 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 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 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 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 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: structure:
<pre>&nbsp;&nbsp;&nbsp; DB_MUTEX&nbsp;&nbsp;&nbsp; *mt_mutexp;&nbsp;&nbsp; /* Mersenne Twister mutex */ <pre>&nbsp;&nbsp;&nbsp; DB_MUTEX&nbsp;&nbsp;&nbsp; *mt_mutexp;&nbsp;&nbsp; /* Mersenne Twister mutex */
&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *mti;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* MT index */ &nbsp;&nbsp;&nbsp; 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" #include "db_config.h"
@ -69,7 +69,7 @@ __db_generate_iv(dbenv, iv)
ret = 0; ret = 0;
n = DB_IV_BYTES / sizeof(u_int32_t); 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 (dbenv->mt == NULL) {
if ((ret = __os_calloc(dbenv, 1, N*sizeof(unsigned long), if ((ret = __os_calloc(dbenv, 1, N*sizeof(unsigned long),
&dbenv->mt)) != 0) &dbenv->mt)) != 0)
@ -77,17 +77,16 @@ __db_generate_iv(dbenv, iv)
/* mti==N+1 means mt[N] is not initialized */ /* mti==N+1 means mt[N] is not initialized */
dbenv->mti = N + 1; 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. * We do not allow 0. If we get one just try again.
*/ */
do { do {
iv[i] = (u_int32_t)__db_genrand(dbenv); iv[i] = (u_int32_t)__db_genrand(dbenv);
} while (iv[i] == 0); } while (iv[i] == 0);
} }
MUTEX_THREAD_UNLOCK(dbenv, dbenv->mt_mutexp); MUTEX_UNLOCK(dbenv, dbenv->mtx_mt);
return (0); return (0);
} }
@ -137,7 +136,7 @@ __db_lsgenrand(seed_array, mt, mtip)
static unsigned long static unsigned long
__db_genrand(dbenv) __db_genrand(dbenv)
DB_ENV *dbenv; DB_ENV *dbenv;
{ {
unsigned long y; unsigned long y;
static unsigned long mag01[2]={0x0, MATRIX_A}; static unsigned long mag01[2]={0x0, MATRIX_A};
@ -145,7 +144,7 @@ __db_genrand(dbenv)
u_int32_t secs, seed, usecs; 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 */ if (dbenv->mti >= N) { /* generate N words at one time */
int kk; 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 * 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 * rijndael-api-fst.h

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * 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" #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_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 // The following cast implies that Dbc can be no larger than DBC
DB_METHOD(cursor, (DbTxn *txnid, Dbc **cursorp, u_int32_t flags), 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. */ /* The logic here is identical to Db::get - reuse the macro. */
if (!DB_RETOK_DBGET(ret)) { 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()); DB_ERROR_DBT(env_, "Db::pget", value, error_policy());
else else
DB_ERROR(env_, "Db::pget", ret, error_policy()); 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_METHOD(set_bt_compare, (bt_compare_fcn_type func),
(db, func), DB_RETOK_STD) (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_METHOD(get_bt_minkey, (u_int32_t *bt_minkeyp),
(db, bt_minkeyp), DB_RETOK_STD) (db, bt_minkeyp), DB_RETOK_STD)
DB_METHOD(set_bt_minkey, (u_int32_t bt_minkey), DB_METHOD(set_bt_minkey, (u_int32_t bt_minkey),

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * 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" #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); ret = dbc->c_get(dbc, key, data, _flags);
if (!DB_RETOK_DBCGET(ret)) { 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), DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::get", key, ON_ERROR_UNKNOWN); "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), DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::get", data, ON_ERROR_UNKNOWN); "Dbc::get", data, ON_ERROR_UNKNOWN);
else 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. */ /* Logic is the same as for Dbc::get - reusing macro. */
if (!DB_RETOK_DBCGET(ret)) { 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), DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::pget", key, ON_ERROR_UNKNOWN); "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), DB_ERROR_DBT(DbEnv::get_DbEnv(dbc->dbp->dbenv),
"Dbc::pget", data, ON_ERROR_UNKNOWN); "Dbc::pget", data, ON_ERROR_UNKNOWN);
else else

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -17,7 +17,11 @@
#include "dbinc/cxx_int.h" #include "dbinc/cxx_int.h"
#include "db_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/common_ext.h"
#include "dbinc_auto/log_ext.h"
#ifdef HAVE_CXX_STDHEADERS #ifdef HAVE_CXX_STDHEADERS
using std::cerr; using std::cerr;
@ -91,7 +95,7 @@ void _paniccall_intercept_c(DB_ENV *env, int errval)
extern "C" extern "C"
void _stream_error_function_c(const DB_ENV *env, 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); 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" extern "C"
int _app_dispatch_intercept_c(DB_ENV *env, DBT *dbt, int _app_dispatch_intercept_c(DB_ENV *env, DBT *dbt, DB_LSN *lsn, db_recops op)
DB_LSN *lsn, db_recops op)
{ {
return (DbEnv::_app_dispatch_intercept(env, dbt, lsn, op)); return (DbEnv::_app_dispatch_intercept(env, dbt, lsn, op));
} }
extern "C" extern "C"
int _rep_send_intercept_c(DB_ENV *env, const DBT *cntrl, int _rep_send_intercept_c(DB_ENV *env, const DBT *cntrl, const DBT *data,
const DBT *data, const DB_LSN *lsn, int id, const DB_LSN *lsn, int id, u_int32_t flags)
u_int32_t flags)
{ {
return (DbEnv::_rep_send_intercept(env, return (DbEnv::_rep_send_intercept(env,
cntrl, data, lsn, id, flags)); 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) void DbEnv::_feedback_intercept(DB_ENV *env, int opcode, int pct)
{ {
DbEnv *cxxenv = DbEnv::get_DbEnv(env); DbEnv *cxxenv = DbEnv::get_DbEnv(env);
@ -150,8 +171,8 @@ void DbEnv::_paniccall_intercept(DB_ENV *env, int errval)
(*cxxenv->paniccall_callback_)(cxxenv, errval); (*cxxenv->paniccall_callback_)(cxxenv, errval);
} }
int DbEnv::_app_dispatch_intercept(DB_ENV *env, DBT *dbt, int DbEnv::_app_dispatch_intercept(DB_ENV *env, DBT *dbt, DB_LSN *lsn,
DB_LSN *lsn, db_recops op) db_recops op)
{ {
DbEnv *cxxenv = DbEnv::get_DbEnv(env); DbEnv *cxxenv = DbEnv::get_DbEnv(env);
if (cxxenv == 0) { 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)); return ((*cxxenv->app_dispatch_callback_)(cxxenv, cxxdbt, cxxlsn, op));
} }
int DbEnv::_rep_send_intercept(DB_ENV *env, const DBT *cntrl, int DbEnv::_isalive_intercept(DB_ENV *env, pid_t pid, db_threadid_t thrid)
const DBT *data, const DB_LSN *lsn, {
int id, u_int32_t flags) 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); DbEnv *cxxenv = DbEnv::get_DbEnv(env);
if (cxxenv == 0) { if (cxxenv == 0) {
@ -187,6 +218,28 @@ int DbEnv::_rep_send_intercept(DB_ENV *env, const DBT *cntrl,
cxxcntrl, cxxdata, cxxlsn, id, flags)); 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 // A truism for the DbEnv object is that there is a valid
// DB_ENV handle from the constructor until close(). // DB_ENV handle from the constructor until close().
// After the close, the DB_ENV handle is invalid and // After the close, the DB_ENV handle is invalid and
@ -208,8 +261,6 @@ DbEnv::DbEnv(u_int32_t flags)
, app_dispatch_callback_(0) , app_dispatch_callback_(0)
, feedback_callback_(0) , feedback_callback_(0)
, paniccall_callback_(0) , paniccall_callback_(0)
, pgin_callback_(0)
, pgout_callback_(0)
, rep_send_callback_(0) , rep_send_callback_(0)
{ {
if ((construct_error_ = initialize(0)) != 0) if ((construct_error_ = initialize(0)) != 0)
@ -226,8 +277,6 @@ DbEnv::DbEnv(DB_ENV *env, u_int32_t flags)
, app_dispatch_callback_(0) , app_dispatch_callback_(0)
, feedback_callback_(0) , feedback_callback_(0)
, paniccall_callback_(0) , paniccall_callback_(0)
, pgin_callback_(0)
, pgout_callback_(0)
, rep_send_callback_(0) , rep_send_callback_(0)
{ {
if ((construct_error_ = initialize(env)) != 0) if ((construct_error_ = initialize(env)) != 0)
@ -326,10 +375,20 @@ void *DbEnv::get_app_private() const
return unwrapConst(this)->app_private; 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_home, (const char **homep), (dbenv, homep))
DBENV_METHOD(get_open_flags, (u_int32_t *flagsp), (dbenv, flagsp)) DBENV_METHOD(get_open_flags, (u_int32_t *flagsp), (dbenv, flagsp))
DBENV_METHOD(get_data_dirs, (const char ***dirspp), (dbenv, dirspp)) 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 // used internally during constructor
// to associate an existing DB_ENV with this DbEnv, // to associate an existing DB_ENV with this DbEnv,
// or create a new one. // 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_flush, (const DbLsn *lsn), (dbenv, lsn))
DBENV_METHOD(log_put, (DbLsn *lsn, const Dbt *data, u_int32_t flags), DBENV_METHOD(log_put, (DbLsn *lsn, const Dbt *data, u_int32_t flags),
(dbenv, lsn, data, 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_METHOD(log_stat, (DB_LOG_STAT **spp, u_int32_t flags),
(dbenv, spp, flags)) (dbenv, spp, flags))
DBENV_METHOD(log_stat_print, (u_int32_t flags), (dbenv, 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) int DbEnv::memp_fcreate(DbMpoolFile **dbmfp, u_int32_t flags)
{ {
DB_ENV *env = unwrap(this); DB_ENV *env = unwrap(this);
@ -500,6 +576,12 @@ void DbEnv::runtime_error(DbEnv *env,
throw lng_except; throw lng_except;
} }
break; break;
case DB_REP_HANDLE_DEAD:
{
DbRepHandleDeadException dl_except(caller);
dl_except.set_env(env);
throw dl_except;
}
default: default:
{ {
DbException except(caller, error); 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(set_errfile, (FILE *errfile), (dbenv, errfile))
DBENV_METHOD_VOID(get_errpfx, (const char **errpfxp), (dbenv, errpfxp)) DBENV_METHOD_VOID(get_errpfx, (const char **errpfxp), (dbenv, errpfxp))
DBENV_METHOD_VOID(set_errpfx, (const char *errpfx), (dbenv, errpfx)) 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(get_lg_bsize, (u_int32_t *bsizep), (dbenv, bsizep))
DBENV_METHOD(set_lg_bsize, (u_int32_t bsize), (dbenv, bsize)) DBENV_METHOD(set_lg_bsize, (u_int32_t bsize), (dbenv, bsize))
DBENV_METHOD(get_lg_dir, (const char **dirp), (dbenv, dirp)) DBENV_METHOD(get_lg_dir, (const char **dirp), (dbenv, dirp))
DBENV_METHOD(set_lg_dir, (const char *dir), (dbenv, dir)) 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(get_lg_max, (u_int32_t *maxp), (dbenv, maxp))
DBENV_METHOD(set_lg_max, (u_int32_t max), (dbenv, max)) DBENV_METHOD(set_lg_max, (u_int32_t max), (dbenv, max))
DBENV_METHOD(get_lg_regionmax, (u_int32_t *regionmaxp), (dbenv, regionmaxp)) 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_METHOD(get_lk_max_objects, (u_int32_t *max_objectsp),
(dbenv, max_objectsp)) (dbenv, max_objectsp))
DBENV_METHOD(set_lk_max_objects, (u_int32_t max_objects), (dbenv, max_objects)) 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(get_mp_mmapsize, (size_t *mmapsizep), (dbenv, mmapsizep))
DBENV_METHOD(set_mp_mmapsize, (size_t mmapsize), (dbenv, mmapsize)) DBENV_METHOD(set_mp_mmapsize, (size_t mmapsize), (dbenv, mmapsize))
DBENV_METHOD_VOID(get_msgfile, (FILE **msgfilep), (dbenv, msgfilep)) 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(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(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, DBENV_METHOD_QUIET(set_alloc,
(db_malloc_fcn_type malloc_fcn, db_realloc_fcn_type realloc_fcn, (db_malloc_fcn_type malloc_fcn, db_realloc_fcn_type realloc_fcn,
db_free_fcn_type free_fcn), db_free_fcn_type free_fcn),
@ -694,7 +786,8 @@ int DbEnv::set_feedback(void (*arg)(DbEnv *, int, int))
feedback_callback_ = arg; 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)) 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; message_stream_ = 0;
dbenv->set_msgcall(dbenv, (arg == 0) ? 0 : dbenv->set_msgcall(dbenv, (arg == 0) ? 0 :
_stream_message_function_c); _stream_message_function_c);
} }
__DB_STD(ostream) *DbEnv::get_message_stream() __DB_STD(ostream) *DbEnv::get_message_stream()
@ -733,7 +826,8 @@ int DbEnv::set_paniccall(void (*arg)(DbEnv *, int))
paniccall_callback_ = arg; 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, DBENV_METHOD(set_rpc_server,
@ -741,9 +835,6 @@ DBENV_METHOD(set_rpc_server,
(dbenv, cl, host, tsec, ssec, flags)) (dbenv, cl, host, tsec, ssec, flags))
DBENV_METHOD(get_shm_key, (long *shm_keyp), (dbenv, shm_keyp)) DBENV_METHOD(get_shm_key, (long *shm_keyp), (dbenv, shm_keyp))
DBENV_METHOD(set_shm_key, (long shm_key), (dbenv, shm_key)) 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 DbEnv::set_app_dispatch
(int (*arg)(DbEnv *, Dbt *, DbLsn *, db_recops)) (int (*arg)(DbEnv *, Dbt *, DbLsn *, db_recops))
@ -753,18 +844,77 @@ int DbEnv::set_app_dispatch
app_dispatch_callback_ = arg; app_dispatch_callback_ = arg;
if ((ret = dbenv->set_app_dispatch(dbenv, 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()); DB_ERROR(this, "DbEnv::set_app_dispatch", ret, error_policy());
return (ret); 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(get_tx_timestamp, (time_t *timestamp), (dbenv, timestamp))
DBENV_METHOD(set_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_METHOD(get_verbose, (u_int32_t which, int *onoffp),
(dbenv, which, onoffp)) (dbenv, which, onoffp))
DBENV_METHOD(set_verbose, (u_int32_t which, int onoff), (dbenv, which, onoff)) 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) int DbEnv::txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags)
{ {
DB_ENV *env = unwrap(this); 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)) DBENV_METHOD(txn_stat_print, (u_int32_t flags), (dbenv, flags))
int DbEnv::set_rep_transport(int myid, int DbEnv::set_rep_transport(int myid,
int (*f_send)(DbEnv *, const Dbt *, const Dbt *, const DbLsn *, int, int (*arg)(DbEnv *, const Dbt *, const Dbt *, const DbLsn *, int, u_int32_t))
u_int32_t))
{ {
DB_ENV *dbenv = unwrap(this); DB_ENV *dbenv = unwrap(this);
int ret; int ret;
rep_send_callback_ = f_send; rep_send_callback_ = arg;
if ((ret = dbenv->set_rep_transport(dbenv, if ((ret = dbenv->set_rep_transport(dbenv, myid,
myid, _rep_send_intercept_c)) != 0) arg == 0 ? 0 : _rep_send_intercept_c)) != 0)
DB_ERROR(this, "DbEnv::set_rep_transport", ret, error_policy()); DB_ERROR(this, "DbEnv::set_rep_transport", ret, error_policy());
return (ret); return (ret);
@ -849,6 +998,10 @@ DBENV_METHOD(rep_elect,
(int nsites, (int nsites,
int nvotes, int priority, u_int32_t timeout, int *eidp, u_int32_t flags), int nvotes, int priority, u_int32_t timeout, int *eidp, u_int32_t flags),
(dbenv, nsites, nvotes, priority, timeout, eidp, 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, int DbEnv::rep_process_message(Dbt *control,
Dbt *rec, int *idp, DbLsn *ret_lsnp) Dbt *rec, int *idp, DbLsn *ret_lsnp)
@ -864,6 +1017,8 @@ int DbEnv::rep_process_message(Dbt *control,
return (ret); return (ret);
} }
DBENV_METHOD(rep_set_config,
(u_int32_t which, int onoff), (dbenv, which, onoff))
DBENV_METHOD(rep_start, DBENV_METHOD(rep_start,
(Dbt *cookie, u_int32_t flags), (Dbt *cookie, u_int32_t flags),
(dbenv, (DBT *)cookie, 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_METHOD(rep_stat, (DB_REP_STAT **statp, u_int32_t flags),
(dbenv, statp, flags)) (dbenv, statp, flags))
DBENV_METHOD(rep_stat_print, (u_int32_t flags), (dbenv, 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_METHOD(get_rep_limit, (u_int32_t *gbytesp, u_int32_t *bytesp),
(dbenv, gbytesp, bytesp)) (dbenv, gbytesp, bytesp))

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -295,6 +295,35 @@ int DbLockNotGrantedException::get_index() const
return index_; return index_;
} }
////////////////////////////////////////////////////////////////////////
// //
// DbRepHandleDeadException //
// //
////////////////////////////////////////////////////////////////////////
DbRepHandleDeadException::~DbRepHandleDeadException() throw()
{
}
DbRepHandleDeadException::DbRepHandleDeadException(const char *description)
: DbException(description, DB_REP_HANDLE_DEAD)
{
}
DbRepHandleDeadException::DbRepHandleDeadException
(const DbRepHandleDeadException &that)
: DbException(that)
{
}
DbRepHandleDeadException
&DbRepHandleDeadException::operator =(const DbRepHandleDeadException &that)
{
if (this != &that)
DbException::operator=(that);
return (*this);
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// // // //
// DbRunRecoveryException // // DbRunRecoveryException //

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -29,7 +29,7 @@ bool DbMultipleDataIterator::next(Dbt &data)
if (data.get_size() == 0 && data.get_data() == data_) if (data.get_size() == 0 && data.get_data() == data_)
data.set_data(0); data.set_data(0);
} }
return (data.get_data() != 0); return (p_ != 0);
} }
bool DbMultipleKeyDataIterator::next(Dbt &key, Dbt &data) 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_data(data_ + *p_--);
data.set_size(*p_--); data.set_size(*p_--);
} }
return (data.get_data() != 0); return (p_ != 0);
} }
bool DbMultipleRecnoDataIterator::next(db_recno_t &recno, Dbt &data) 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_data(data_ + *p_--);
data.set_size(*p_--); data.set_size(*p_--);
} }
return (recno != 0); return (p_ != 0);
} }

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * 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" #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) DBSEQ_METHOD(set_range, (db_seq_t min, db_seq_t max), (seq, min, max), 0)
Db *DbSequence::get_db() Db *DbSequence::get_db()
{ {
DB_SEQUENCE *seq = unwrap(this); DB_SEQUENCE *seq = unwrap(this);
DB *db; DB *db;
(void)seq->get_db(seq, &db); (void)seq->get_db(seq, &db);
return Db::get_Db(db); return Db::get_Db(db);
} }
Dbt *DbSequence::get_key() Dbt *DbSequence::get_key()
{ {
DB_SEQUENCE *seq = unwrap(this); DB_SEQUENCE *seq = unwrap(this);
memset(&key_, 0, sizeof (DBT)); memset(&key_, 0, sizeof (DBT));
(void)seq->get_key(seq, &key_); (void)seq->get_key(seq, &key_);
return Dbt::get_Dbt(&key_); return Dbt::get_Dbt(&key_);
} }
// static method // static method
DbSequence *DbSequence::wrap_DB_SEQUENCE(DB_SEQUENCE *seq) DbSequence *DbSequence::wrap_DB_SEQUENCE(DB_SEQUENCE *seq)

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -67,7 +67,9 @@ u_int32_t DbTxn::id()
return (txn->id(txn)); // no error 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(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), DBTXN_METHOD(set_timeout, 0, (db_timeout_t timeout, u_int32_t flags),
(txn, timeout, flags)) (txn, timeout, flags))

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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 PREFIX __crdel
@ -41,3 +41,40 @@ PGDBT page DBT s
POINTER lsn DB_LSN * lu POINTER lsn DB_LSN * lu
END 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. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -18,9 +18,11 @@
#include "db_int.h" #include "db_int.h"
#include "dbinc/db_page.h" #include "dbinc/db_page.h"
#include "dbinc/db_shash.h" #include "dbinc/db_shash.h"
#include "dbinc/fop.h"
#include "dbinc/hash.h" #include "dbinc/hash.h"
#include "dbinc/log.h" #include "dbinc/log.h"
#include "dbinc/mp.h" #include "dbinc/mp.h"
#include "dbinc/txn.h"
/* /*
* __crdel_metasub_recover -- * __crdel_metasub_recover --
@ -47,22 +49,39 @@ __crdel_metasub_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__crdel_metasub_print); 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) { if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
*lsnp = argp->prev_lsn; /* If this is an in-memory file, this might be OK. */
ret = 0; if (F_ISSET(file_dbp, DB_AM_INMEM) && (ret = __memp_fget(mpf,
goto out; &argp->pgno, DB_MPOOL_CREATE, &pagep)) == 0)
LSN_NOT_LOGGED(LSN(pagep));
else {
*lsnp = argp->prev_lsn;
ret = 0;
goto out;
}
} }
modified = 0; modified = 0;
cmp_p = log_compare(&LSN(pagep), &argp->lsn); 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)) { if (cmp_p == 0 && DB_REDO(op)) {
memcpy(pagep, argp->page.data, argp->page.size); memcpy(pagep, argp->page.data, argp->page.size);
LSN(pagep) = *lsnp; LSN(pagep) = *lsnp;
modified = 1; 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)) { } else if (DB_UNDO(op)) {
/* /*
* We want to undo this page creation. The page creation * 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 * was logged separately. Then we wrote the meta-data onto
* the page. So long as we restore the LSN, then the recovery * the page. So long as we restore the LSN, then the recovery
* for __bam_new will do everything else. * 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 * Don't bother checking the lsn on the page. If we are
* will get freed. Opening the subdb will have reinitialized * rolling back the next thing is that this page will get
* the page, but not the lsn. * freed. Opening the subdb will have reinitialized the
* page, but not the lsn.
*/ */
LSN(pagep) = argp->lsn; LSN(pagep) = argp->lsn;
modified = 1; modified = 1;
@ -89,3 +109,186 @@ out: if (pagep != NULL)
(void)__memp_fput(mpf, pagep, 0); (void)__memp_fput(mpf, pagep, 0);
REC_CLOSE; 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. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"
@ -52,6 +52,7 @@
#include "dbinc/db_shash.h" #include "dbinc/db_shash.h"
#include "dbinc/db_swap.h" #include "dbinc/db_swap.h"
#include "dbinc/btree.h" #include "dbinc/btree.h"
#include "dbinc/fop.h"
#include "dbinc/hash.h" #include "dbinc/hash.h"
#include "dbinc/lock.h" #include "dbinc/lock.h"
#include "dbinc/log.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) __memp_fget(mdbp->mpf, &sdbp->meta_pgno, 0, &p)) != 0)
goto err; goto err;
/* Free the root on the master db. */ /* Free the root on the master db if it was created. */
if (TYPE(p) == P_BTREEMETA) { if (TYPE(p) == P_BTREEMETA &&
((BTMETA *)p)->root != PGNO_INVALID) {
if ((ret = __memp_fget(mdbp->mpf, if ((ret = __memp_fget(mdbp->mpf,
&((BTMETA *)p)->root, 0, &r)) != 0) &((BTMETA *)p)->root, 0, &r)) != 0)
goto err; goto err;
@ -389,18 +391,17 @@ done: /*
* Set up the underlying environment during a db_open. * Set up the underlying environment during a db_open.
* *
* PUBLIC: int __db_dbenv_setup __P((DB *, * 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 int
__db_dbenv_setup(dbp, txn, fname, id, flags) __db_dbenv_setup(dbp, txn, fname, dname, id, flags)
DB *dbp; DB *dbp;
DB_TXN *txn; DB_TXN *txn;
const char *fname; const char *fname, *dname;
u_int32_t id, flags; u_int32_t id, flags;
{ {
DB *ldbp; DB *ldbp;
DB_ENV *dbenv; DB_ENV *dbenv;
DB_MPOOL *dbmp;
u_int32_t maxid; u_int32_t maxid;
int ret; int ret;
@ -415,25 +416,20 @@ __db_dbenv_setup(dbp, txn, fname, id, flags)
dbenv, 0, dbp->pgsize * DB_MINPAGECACHE, 0)) != 0) dbenv, 0, dbp->pgsize * DB_MINPAGECACHE, 0)) != 0)
return (ret); 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) DB_INIT_MPOOL | DB_PRIVATE | LF_ISSET(DB_THREAD), 0)) != 0)
return (ret); return (ret);
} }
/* Join the underlying cache. */ /* 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); return (ret);
/* /* We may need a per-thread mutex. */
* We may need a per-thread mutex. Allocate it from the mpool if (LF_ISSET(DB_THREAD) && (ret = __mutex_alloc(
* region, there's supposed to be extra space there for that purpose. dbenv, MTX_DB_HANDLE, DB_MUTEX_THREAD, &dbp->mutex)) != 0)
*/ return (ret);
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);
}
/* /*
* Set up a bookkeeping entry for this database in the log region, * 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 * or a replication client, where we won't log registries, we'll
* still need an FNAME struct, so LOGGING_ON is the correct macro. * still need an FNAME struct, so LOGGING_ON is the correct macro.
*/ */
if (LOGGING_ON(dbenv) && if (LOGGING_ON(dbenv) && dbp->log_filename == NULL &&
(ret = __dbreg_setup(dbp, fname, id)) != 0) (ret = __dbreg_setup(dbp,
F_ISSET(dbp, DB_AM_INMEM) ? dname : fname, id)) != 0)
return (ret); return (ret);
/* /*
* If we're actively logging and our caller isn't a recovery function * 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 (DBENV_LOGGING(dbenv) && !F_ISSET(dbp, DB_AM_RECOVER) &&
#if !defined(DEBUG_ROP) #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 * routines, where we don't want to do a lot of ugly and
* expensive memcmps. * expensive memcmps.
*/ */
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (maxid = 0, ldbp = LIST_FIRST(&dbenv->dblist); for (maxid = 0, ldbp = LIST_FIRST(&dbenv->dblist);
ldbp != NULL; ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp != NULL; ldbp = LIST_NEXT(ldbp, dblistlinks)) {
if (fname != NULL && if (!F_ISSET(dbp, DB_AM_INMEM)) {
memcmp(ldbp->fileid, dbp->fileid, DB_FILE_ID_LEN) == 0 && if (memcmp(ldbp->fileid, dbp->fileid, DB_FILE_ID_LEN)
ldbp->meta_pgno == dbp->meta_pgno) == 0 && ldbp->meta_pgno == dbp->meta_pgno)
break; break;
} else if (dname != NULL) {
if (F_ISSET(ldbp, DB_AM_INMEM) &&
strcmp(ldbp->dname, dname) == 0)
break;
}
if (ldbp->adj_fileid > maxid) if (ldbp->adj_fileid > maxid)
maxid = ldbp->adj_fileid; maxid = ldbp->adj_fileid;
} }
@ -493,7 +495,7 @@ __db_dbenv_setup(dbp, txn, fname, id, flags)
dbp->adj_fileid = ldbp->adj_fileid; dbp->adj_fileid = ldbp->adj_fileid;
LIST_INSERT_AFTER(ldbp, dbp, dblistlinks); LIST_INSERT_AFTER(ldbp, dbp, dblistlinks);
} }
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (0); return (0);
} }
@ -514,12 +516,19 @@ __db_dbenv_mpool(dbp, fname, flags)
DBT pgcookie; DBT pgcookie;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
DB_PGINFO pginfo; DB_PGINFO pginfo;
int fidset, ftype, ret;
int32_t lsn_off;
u_int8_t nullfid[DB_FILE_ID_LEN];
u_int32_t clear_len; u_int32_t clear_len;
int ftype, ret;
COMPQUIET(mpf, NULL); COMPQUIET(mpf, NULL);
dbenv = dbp->dbenv; 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 * 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: case DB_RECNO:
ftype = F_ISSET(dbp, DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM) ftype = F_ISSET(dbp, DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM)
? DB_FTYPE_SET : DB_FTYPE_NOTSET; ? 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; break;
case DB_HASH: case DB_HASH:
ftype = DB_FTYPE_SET; 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; break;
case DB_QUEUE: case DB_QUEUE:
ftype = F_ISSET(dbp, ftype = F_ISSET(dbp,
DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM) ? DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM) ?
DB_FTYPE_SET : DB_FTYPE_NOTSET; 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; break;
case DB_UNKNOWN: case DB_UNKNOWN:
/* /*
@ -564,6 +584,18 @@ __db_dbenv_mpool(dbp, fname, flags)
clear_len = DB_PAGE_DB_LEN; clear_len = DB_PAGE_DB_LEN;
break; 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 */ /* FALLTHROUGH */
default: default:
return (__db_unknown_type(dbenv, "DB->open", dbp->type)); return (__db_unknown_type(dbenv, "DB->open", dbp->type));
@ -571,10 +603,14 @@ __db_dbenv_mpool(dbp, fname, flags)
mpf = dbp->mpf; 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_clear_len(mpf, clear_len);
(void)__memp_set_fileid(mpf, dbp->fileid);
(void)__memp_set_ftype(mpf, ftype); (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.db_pagesize = dbp->pgsize;
pginfo.flags = pginfo.flags =
@ -585,12 +621,34 @@ __db_dbenv_mpool(dbp, fname, flags)
(void)__memp_set_pgcookie(mpf, &pgcookie); (void)__memp_set_pgcookie(mpf, &pgcookie);
if ((ret = __memp_fopen(mpf, NULL, fname, if ((ret = __memp_fopen(mpf, NULL, fname,
LF_ISSET(DB_RDONLY | DB_NOMMAP | LF_ISSET(DB_CREATE | DB_DURABLE_UNKNOWN |
DB_ODDFILESIZE | DB_TRUNCATE) | DB_NOMMAP | DB_ODDFILESIZE | DB_RDONLY | DB_TRUNCATE) |
(F_ISSET(dbenv, DB_ENV_DIRECT_DB) ? DB_DIRECT : 0) | (F_ISSET(dbenv, DB_ENV_DIRECT_DB) ? DB_DIRECT : 0) |
(F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_TXN_NOT_DURABLE : 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); 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); return (0);
} }
@ -624,7 +682,7 @@ __db_close(dbp, txn, flags)
(void)__db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0); (void)__db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0);
/* Refresh the structure and close any underlying resources. */ /* 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, * 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 * dbenv, someone's already badly screwed up, so there's no reason
* to bother engineering around this possibility. * to bother engineering around this possibility.
*/ */
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
db_ref = --dbenv->db_ref; 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 && 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; ret = t_ret;
/* Free the database handle. */ /* Free the database handle. */
@ -666,25 +724,32 @@ __db_close(dbp, txn, flags)
* the actual handle) and during abort processing, we may have a * the actual handle) and during abort processing, we may have a
* fully opened handle. * 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 int
__db_refresh(dbp, txn, flags, deferred_closep) __db_refresh(dbp, txn, flags, deferred_closep, reuse)
DB *dbp; DB *dbp;
DB_TXN *txn; DB_TXN *txn;
u_int32_t flags; u_int32_t flags;
int *deferred_closep; int *deferred_closep, reuse;
{ {
DB *sdbp; DB *sdbp;
DBC *dbc; DBC *dbc;
DB_ENV *dbenv; DB_ENV *dbenv;
DB_LOCKREQ lreq; DB_LOCKREQ lreq;
DB_MPOOL *dbmp; REGENV *renv;
REGINFO *infop;
u_int32_t save_flags;
int resync, ret, t_ret; int resync, ret, t_ret;
ret = 0; ret = 0;
dbenv = dbp->dbenv; 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 never opened, or not currently open, it's easy. */
if (!F_ISSET(dbp, DB_AM_OPEN_CALLED)) 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) (t_ret = __memp_fsync(dbp->mpf)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
never_opened:
/* /*
* At this point, we haven't done anything to render the DB * At this point, we haven't done anything to render the DB
* handle unusable, at least by a transaction abort. Take the * 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 * In this case, we put off actually closing the dbp until we've
* performed the abort. * 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 * 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); t_ret = __dbreg_revoke_id(dbp, 0, DB_LOGFILEID_INVALID);
else { else {
if ((t_ret = __dbreg_close_id(dbp, if ((t_ret = __dbreg_close_id(dbp,
@ -808,6 +877,17 @@ __db_refresh(dbp, txn, flags, deferred_closep)
*deferred_closep = 1; *deferred_closep = 1;
return (t_ret); 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) if (ret == 0)
@ -824,7 +904,6 @@ __db_refresh(dbp, txn, flags, deferred_closep)
ret == 0) ret == 0)
ret = t_ret; ret = t_ret;
never_opened:
/* /*
* Remove this DB handle from the DB_ENV's dblist, if it's been added. * 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 * want to race with a thread searching for our underlying cache link
* while opening a DB handle. * while opening a DB handle.
*/ */
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
if (dbp->dblistlinks.le_prev != NULL) { if (!reuse && dbp->dblistlinks.le_prev != NULL) {
LIST_REMOVE(dbp, dblistlinks); LIST_REMOVE(dbp, dblistlinks);
dbp->dblistlinks.le_prev = NULL; dbp->dblistlinks.le_prev = NULL;
} }
@ -845,9 +924,13 @@ never_opened:
ret == 0) ret == 0)
ret = t_ret; ret = t_ret;
dbp->mpf = NULL; 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. * Call the access specific close function.
@ -883,7 +966,7 @@ never_opened:
* access-method specific data. * 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. */ /* We may have pending trade operations on this dbp. */
if (txn != NULL) if (txn != NULL)
__txn_remlock(dbenv, txn, &dbp->handle_lock, dbp->lid); __txn_remlock(dbenv, txn, &dbp->handle_lock, dbp->lid);
@ -901,20 +984,57 @@ never_opened:
LOCK_INIT(dbp->handle_lock); 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 && (t_ret = __lock_id_free(dbenv, *(u_int32_t *)dbp->fileid)) != 0 &&
ret == 0) ret == 0)
ret = t_ret; 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; dbp->type = DB_UNKNOWN;
/* Discard the thread mutex. */ /* Discard the thread mutex. */
if (dbp->mutexp != NULL) { if ((t_ret = __mutex_free(dbenv, &dbp->mutex)) != 0 && ret == 0)
dbmp = dbenv->mp_handle; ret = t_ret;
__db_mutex_free(dbenv, dbmp->reginfo, dbp->mutexp);
dbp->mutexp = NULL;
}
/* Discard any memory allocated for the file and database names. */ /* Discard any memory allocated for the file and database names. */
if (dbp->fname != NULL) { if (dbp->fname != NULL) {
@ -1004,7 +1124,7 @@ __db_log_page(dbp, txn, lsn, pgno, page)
* PUBLIC: const char *, DB_TXN *, char **)); * PUBLIC: const char *, DB_TXN *, char **));
*/ */
#undef BACKUP_PREFIX #undef BACKUP_PREFIX
#define BACKUP_PREFIX "__db." #define BACKUP_PREFIX "__db"
#undef MAX_LSN_TO_TEXT #undef MAX_LSN_TO_TEXT
#define MAX_LSN_TO_TEXT 17 #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 * we allocate enough space for it, even in the case where we don't
* use the entire filename for the backup name. * 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) if ((ret = __os_malloc(dbenv, len, &retp)) != 0)
return (ret); 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) * In a transactional env: __db.LSN(8).LSN(8)
* and * 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 * 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. * 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 * 4. multi-component path + transaction
*/ */
p = __db_rpath(name); 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. */ if (p == NULL) /* Case 1. */
snprintf(retp, len, "%s%s", BACKUP_PREFIX, name); n = snprintf(retp,
else /* Case 3. */ len, "%s%.4s.tmp", BACKUP_PREFIX, name);
snprintf(retp, len, "%.*s%s%s", else /* Case 3. */
n = snprintf(retp, len, "%.*s%s%.4s.tmp",
(int)(p - name) + 1, name, BACKUP_PREFIX, p + 1); (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 * Write dummy log record. The two choices for dummy
* log records are __db_noop_log and __db_debug_log; * 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); __os_free(dbenv, retp);
return (ret); return (ret);
} }
} else }
lsn = txn->last_lsn;
if (p == NULL) /* Case 2. */ if (p == NULL) /* Case 2. */
snprintf(retp, len, snprintf(retp, len,
"%s%x.%x", BACKUP_PREFIX, lsn.file, lsn.offset); "%s.%x.%x", BACKUP_PREFIX, lsn.file, lsn.offset);
else /* Case 4. */ else /* Case 4. */
snprintf(retp, len, "%.*s%x.%x", snprintf(retp, len, "%.*s%x.%x",
(int)(p - name) + 1, name, lsn.file, lsn.offset); (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". * 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) if ((ret = __os_malloc(dbenv, len, &copy)) != 0)
goto err; goto err;
@ -1264,7 +1409,7 @@ __db_testdocopy(dbenv, name)
* files named, say, 'a' and 'abc' we won't match 'abc' when * files named, say, 'a' and 'abc' we won't match 'abc' when
* looking for 'a'. * 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. * We need the directory path to do the __os_dirlist.
@ -1343,10 +1488,10 @@ __db_makecopy(dbenv, src, dest)
return; return;
if (__os_open(dbenv, 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; goto err;
if (__os_open(dbenv, dest, 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; goto err;
for (;;) for (;;)

View file

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

View file

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

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"

View file

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

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -66,7 +66,7 @@ __db_ditem(dbc, pagep, indx, nbytes)
* memmove(3), the regions may overlap. * memmove(3), the regions may overlap.
*/ */
from = (u_int8_t *)pagep + HOFFSET(pagep); 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)); memmove(from + nbytes, from, inp[indx] - HOFFSET(pagep));
HOFFSET(pagep) += nbytes; 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. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1998-2004 * Copyright (c) 1998-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -216,9 +216,9 @@ __db_join(primary, curslist, dbcp, flags)
*dbcp = dbc; *dbcp = dbc;
MUTEX_THREAD_LOCK(dbenv, primary->mutexp); MUTEX_LOCK(dbenv, primary->mutex);
TAILQ_INSERT_TAIL(&primary->join_queue, dbc, links); TAILQ_INSERT_TAIL(&primary->join_queue, dbc, links);
MUTEX_THREAD_UNLOCK(dbenv, primary->mutexp); MUTEX_UNLOCK(dbenv, primary->mutex);
return (0); return (0);
@ -250,24 +250,30 @@ __db_join_close_pp(dbc)
DBC *dbc; DBC *dbc;
{ {
DB_ENV *dbenv; DB_ENV *dbenv;
DB_THREAD_INFO *ip;
DB *dbp; DB *dbp;
int handle_check, ret; int handle_check, ret, t_ret;
dbp = dbc->dbp; dbp = dbc->dbp;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
PANIC_CHECK(dbenv); PANIC_CHECK(dbenv);
handle_check = IS_REPLICATED(dbenv, dbp); ENV_ENTER(dbenv, ip);
handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check && if (handle_check &&
(ret = __db_rep_enter(dbp, 0, 0, dbc->txn != NULL)) != 0) (ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0) {
return (ret); handle_check = 0;
goto err;
}
ret = __db_join_close(dbc); ret = __db_join_close(dbc);
if (handle_check) if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
__env_db_rep_exit(dbenv); ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret); return (ret);
} }
@ -309,8 +315,9 @@ __db_join_get_pp(dbc, key, data, flags)
{ {
DB *dbp; DB *dbp;
DB_ENV *dbenv; DB_ENV *dbenv;
DB_THREAD_INFO *ip;
u_int32_t handle_check, save_flags; u_int32_t handle_check, save_flags;
int ret; int ret, t_ret;
dbp = dbc->dbp; dbp = dbc->dbp;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
@ -320,11 +327,10 @@ __db_join_get_pp(dbc, key, data, flags)
PANIC_CHECK(dbenv); 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)) if (!LOCKING_ON(dbp->dbenv))
return (__db_fnl(dbp->dbenv, "DBcursor->c_get")); return (__db_fnl(dbp->dbenv, "DBcursor->c_get"));
LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW);
LF_CLR(DB_DIRTY_READ | DB_DEGREE_2 | DB_RMW);
} }
switch (flags) { switch (flags) {
@ -352,19 +358,24 @@ __db_join_get_pp(dbc, key, data, flags)
return (EINVAL); return (EINVAL);
} }
handle_check = IS_REPLICATED(dbp->dbenv, dbp); ENV_ENTER(dbenv, ip);
handle_check = IS_ENV_REPLICATED(dbp->dbenv);
if (handle_check && if (handle_check &&
(ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0) (ret = __db_rep_enter(dbp, 1, 0, dbc->txn != NULL)) != 0) {
return (ret); handle_check = 0;
goto err;
}
/* Restore the original flags value. */ /* Restore the original flags value. */
flags = save_flags; flags = save_flags;
ret = __db_join_get(dbc, key, data, flags); ret = __db_join_get(dbc, key, data, flags);
if (handle_check) if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
__env_db_rep_exit(dbenv); ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret); 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 * If the set of flags here changes, check that __db_join_primget
* is updated to handle them properly. * 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, * 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 * must happen before any action that can fail and return, or else
* __db_close may loop indefinitely. * __db_close may loop indefinitely.
*/ */
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
TAILQ_REMOVE(&dbp->join_queue, dbc, links); TAILQ_REMOVE(&dbp->join_queue, dbc, links);
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
PANIC_CHECK(dbenv); PANIC_CHECK(dbenv);
@ -872,28 +883,29 @@ __db_join_primget(dbp, txn, lockerid, key, data, flags)
u_int32_t flags; u_int32_t flags;
{ {
DBC *dbc; DBC *dbc;
int ret, rmw, t_ret; u_int32_t rmw;
int ret, t_ret;
if ((ret = __db_cursor_int(dbp, if ((ret = __db_cursor_int(dbp,
txn, dbp->type, PGNO_INVALID, 0, lockerid, &dbc)) != 0) txn, dbp->type, PGNO_INVALID, 0, lockerid, &dbc)) != 0)
return (ret); return (ret);
/* /*
* The only allowable flags here are the two flags copied into * The only allowable flags here are the two flags copied into "opmods"
* "opmods" in __db_join_get, DB_RMW and DB_DIRTY_READ. The former * in __db_join_get, DB_RMW and DB_READ_UNCOMMITTED. The former is an
* is an op on the c_get call, the latter on the cursor call. * op on the c_get call, the latter on the cursor call. It's a DB bug
* It's a DB bug if we allow any other flags down in here. * if we allow any other flags down in here.
*/ */
rmw = LF_ISSET(DB_RMW); rmw = LF_ISSET(DB_RMW);
if (LF_ISSET(DB_DIRTY_READ) || if (LF_ISSET(DB_READ_UNCOMMITTED) ||
(txn != NULL && F_ISSET(txn, TXN_DIRTY_READ))) (txn != NULL && F_ISSET(txn, TXN_READ_UNCOMMITTED)))
F_SET(dbc, DBC_DIRTY_READ); F_SET(dbc, DBC_READ_UNCOMMITTED);
if (LF_ISSET(DB_DEGREE_2) || if (LF_ISSET(DB_READ_COMMITTED) ||
(txn != NULL && F_ISSET(txn, TXN_DEGREE_2))) (txn != NULL && F_ISSET(txn, TXN_READ_COMMITTED)))
F_SET(dbc, DBC_DEGREE_2); 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); DB_ASSERT(flags == 0);
F_SET(dbc, DBC_TRANSIENT); F_SET(dbc, DBC_TRANSIENT);

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -39,7 +39,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"
@ -47,6 +47,7 @@
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
@ -58,6 +59,12 @@
#include "dbinc/db_am.h" #include "dbinc/db_am.h"
static void __db_init_meta __P((DB *, void *, db_pgno_t, u_int32_t)); 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 -- * __db_init_meta --
@ -104,7 +111,7 @@ __db_new(dbc, type, pagepp)
DB_LSN lsn; DB_LSN lsn;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
PAGE *h; PAGE *h;
db_pgno_t last, pgno, newnext; db_pgno_t last, *list, pgno, newnext;
u_int32_t meta_flags; u_int32_t meta_flags;
int extend, ret, t_ret; int extend, ret, t_ret;
@ -123,6 +130,10 @@ __db_new(dbc, type, pagepp)
goto err; goto err;
last = meta->last_pgno; last = meta->last_pgno;
if (meta->free == PGNO_INVALID) { if (meta->free == PGNO_INVALID) {
if (FLD_ISSET(type, P_DONTEXTEND)) {
*pagepp = NULL;
goto err;
}
last = pgno = meta->last_pgno + 1; last = pgno = meta->last_pgno + 1;
ZERO_LSN(lsn); ZERO_LSN(lsn);
extend = 1; extend = 1;
@ -141,6 +152,8 @@ __db_new(dbc, type, pagepp)
extend = 0; extend = 0;
} }
FLD_CLR(type, P_DONTEXTEND);
/* /*
* Log the allocation before fetching the new page. If we * Log the allocation before fetching the new page. If we
* don't have room in the log then we don't want to tell * don't have room in the log then we don't want to tell
@ -191,19 +204,40 @@ __db_new(dbc, type, pagepp)
break; 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 * If dirty reads are enabled and we are in a transaction, we could
* abort this allocation after the page(s) pointing to this * abort this allocation after the page(s) pointing to this
* one have their locks downgraded. This would permit dirty readers * one have their locks downgraded. This would permit dirty readers
* to access this page which is ok, but they must be off the * to access this page which is ok, but they must be off the
* page when we abort. This will also prevent updates happening * page when we abort. We never lock overflow pages or off page
* to this page until we commit. * 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, if ((ret = __db_lget(dbc, 0,
h->pgno, DB_LOCK_WWRITE, 0, &metalock)) != 0) h->pgno, DB_LOCK_WWRITE, 0, &metalock)) != 0)
goto err; goto err;
} }
*pagepp = h; *pagepp = h;
return (0); return (0);
@ -231,16 +265,29 @@ __db_free(dbc, h)
DBT ddbt, ldbt; DBT ddbt, ldbt;
DB_LOCK metalock; DB_LOCK metalock;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
db_pgno_t pgno; db_pgno_t last_pgno, *lp, next_pgno, pgno, prev_pgno;
u_int32_t dirty_flag; u_int32_t dirty_flag, lflag, nelem;
int ret, t_ret; int do_truncate, ret, t_ret;
#ifdef HAVE_FTRUNCATE
db_pgno_t *list;
u_int32_t position, start;
#endif
dbp = dbc->dbp; dbp = dbc->dbp;
mpf = dbp->mpf; 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 * Retrieve the metadata page. If we are not keeping a sorted
* the free list. If either the lock get or page get routines * 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 * fail, then we need to put the page with which we were called
* back because our caller assumes we take care of it. * back because our caller assumes we take care of it.
*/ */
@ -249,12 +296,76 @@ __db_free(dbc, h)
if ((ret = __db_lget(dbc, if ((ret = __db_lget(dbc,
LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0) LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
goto err; goto err;
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0) { if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0)
(void)__TLPUT(dbc, metalock); 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; 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. */ /* Log the change. */
if (DBC_LOGGING(dbc)) { if (DBC_LOGGING(dbc)) {
memset(&ldbt, 0, sizeof(ldbt)); memset(&ldbt, 0, sizeof(ldbt));
@ -269,47 +380,61 @@ __db_free(dbc, h)
case P_LDUP: case P_LDUP:
if (h->entries > 0) { if (h->entries > 0) {
ldbt.size += h->entries * sizeof(db_indx_t); ldbt.size += h->entries * sizeof(db_indx_t);
ddbt.data = (u_int8_t *)h + h->hf_offset; ddbt.data = (u_int8_t *)h + HOFFSET(h);
ddbt.size = dbp->pgsize - h->hf_offset; ddbt.size = dbp->pgsize - HOFFSET(h);
ret = __db_pg_freedata_log(dbp, dbc->txn, if ((ret = __db_pg_freedata_log(dbp, dbc->txn,
&LSN(meta), 0, h->pgno, &LSN(meta), &LSN(meta), 0, h->pgno, &LSN(meta), pgno,
PGNO_BASE_MD, &ldbt, &ldbt, next_pgno, last_pgno, &ddbt)) != 0)
meta->free, meta->last_pgno, &ddbt); goto err1;
break; goto logged;
} }
goto log; break;
case P_HASHMETA: case P_HASHMETA:
ldbt.size = sizeof(HMETA); ldbt.size = sizeof(HMETA);
goto log; break;
case P_BTREEMETA: case P_BTREEMETA:
ldbt.size = sizeof(BTMETA); ldbt.size = sizeof(BTMETA);
goto log; break;
case P_OVERFLOW: case P_OVERFLOW:
ldbt.size += OV_LEN(h); ldbt.size += OV_LEN(h);
goto log; break;
default: default:
DB_ASSERT(h->type != P_QAMDATA); DB_ASSERT(h->type != P_QAMDATA);
}
log: ret = __db_pg_free_log(dbp, /*
dbc->txn, &LSN(meta), 0, h->pgno, &LSN(meta), * If we are truncating the file, we need to make sure
PGNO_BASE_MD, &ldbt, meta->free, meta->last_pgno); * the logging happens before the truncation. If we
} * are truncating multiple pages we don't need to flush the
if (ret != 0) { * log here as it will be flushed by __db_truncate_freelist.
(void)__memp_fput(mpf, (PAGE *)meta, 0); */
(void)__TLPUT(dbc, metalock); lflag = 0;
goto err; #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 } else
LSN_NOT_LOGGED(LSN(meta)); LSN_NOT_LOGGED(LSN(meta));
LSN(h) = LSN(meta); logged: LSN(h) = LSN(meta);
#ifdef HAVE_FTRUNCATE #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) if ((ret = __memp_fput(mpf, h, DB_MPOOL_DISCARD)) != 0)
goto err; goto err;
/* Give the page back to the OS. */ /* 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; goto err;
DB_ASSERT(meta->pgno == PGNO_BASE_MD);
meta->last_pgno--; meta->last_pgno--;
h = NULL; h = NULL;
} else } else
@ -318,20 +443,23 @@ log: ret = __db_pg_free_log(dbp,
{ {
/* /*
* If we are not truncating the page then we * 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. * the free list.
*/ */
P_INIT(h, dbp->pgsize, 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 #ifdef DIAGNOSTIC
memset((u_int8_t *) h + P_OVERHEAD(dbp), memset((u_int8_t *) h + P_OVERHEAD(dbp),
CLEAR_BYTE, dbp->pgsize - P_OVERHEAD(dbp)); CLEAR_BYTE, dbp->pgsize - P_OVERHEAD(dbp));
#endif #endif
meta->free = h->pgno; if (prev_pgno == PGNO_INVALID)
meta->free = h->pgno;
else
NEXT_PGNO(meta) = h->pgno;
} }
/* Discard the metadata page. */ /* Discard the metadata or previous page. */
if ((t_ret = err1: if (meta != NULL && (t_ret =
__memp_fput(mpf, (PAGE *)meta, DB_MPOOL_DIRTY)) != 0 && ret == 0) __memp_fput(mpf, (PAGE *)meta, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
if ((t_ret = __TLPUT(dbc, metalock)) != 0 && ret == 0) if ((t_ret = __TLPUT(dbc, metalock)) != 0 && ret == 0)
@ -350,6 +478,377 @@ err: if (h != NULL &&
return (ret); 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 #ifdef DEBUG
/* /*
* __db_lprint -- * __db_lprint --
@ -394,9 +893,9 @@ __db_lget(dbc, action, pgno, mode, lkflags, lockp)
{ {
DB *dbp; DB *dbp;
DB_ENV *dbenv; DB_ENV *dbenv;
DB_LOCKREQ couple[2], *reqp; DB_LOCKREQ couple[3], *reqp;
DB_TXN *txn; DB_TXN *txn;
int has_timeout, ret; int has_timeout, i, ret;
dbp = dbc->dbp; dbp = dbc->dbp;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
@ -431,8 +930,8 @@ __db_lget(dbc, action, pgno, mode, lkflags, lockp)
if (DB_NONBLOCK(dbc)) if (DB_NONBLOCK(dbc))
lkflags |= DB_LOCK_NOWAIT; lkflags |= DB_LOCK_NOWAIT;
if (F_ISSET(dbc, DBC_DIRTY_READ) && mode == DB_LOCK_READ) if (F_ISSET(dbc, DBC_READ_UNCOMMITTED) && mode == DB_LOCK_READ)
mode = DB_LOCK_DIRTY; mode = DB_LOCK_READ_UNCOMMITTED;
has_timeout = F_ISSET(dbc, DBC_RECOVER) || has_timeout = F_ISSET(dbc, DBC_RECOVER) ||
(txn != NULL && F_ISSET(txn, TXN_LOCKTIMEOUT)); (txn != NULL && F_ISSET(txn, TXN_LOCKTIMEOUT));
@ -440,8 +939,8 @@ __db_lget(dbc, action, pgno, mode, lkflags, lockp)
/* /*
* Transactional locking. * Transactional locking.
* Hold on to the previous read lock only if we are in full isolation. * Hold on to the previous read lock only if we are in full isolation.
* COUPLE_ALWAYS indicates we are holding an interior node * COUPLE_ALWAYS indicates we are holding an interior node which need
* which need not be isolated. * not be isolated.
* Downgrade write locks if we are supporting dirty readers. * Downgrade write locks if we are supporting dirty readers.
*/ */
if ((action != LCK_COUPLE && action != LCK_COUPLE_ALWAYS) || if ((action != LCK_COUPLE && action != LCK_COUPLE_ALWAYS) ||
@ -449,47 +948,54 @@ __db_lget(dbc, action, pgno, mode, lkflags, lockp)
action = 0; action = 0;
else if (dbc->txn == NULL || action == LCK_COUPLE_ALWAYS) else if (dbc->txn == NULL || action == LCK_COUPLE_ALWAYS)
action = LCK_COUPLE; 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; 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; 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; action = LCK_DOWNGRADE;
else else
action = 0; action = 0;
i = 0;
switch (action) { switch (action) {
case LCK_DOWNGRADE:
if ((ret = __lock_downgrade(
dbenv, lockp, DB_LOCK_WWRITE, 0)) != 0)
return (ret);
/* FALLTHROUGH */
default: default:
if (!has_timeout) { if (has_timeout)
ret = __lock_get(dbenv, goto couple;
dbc->locker, lkflags, &dbc->lock_dbt, mode, lockp); ret = __lock_get(dbenv,
break; 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 */ /* FALLTHROUGH */
case LCK_COUPLE: case LCK_COUPLE:
couple[0].op = has_timeout? DB_LOCK_GET_TIMEOUT : DB_LOCK_GET; couple: couple[i].op = has_timeout? DB_LOCK_GET_TIMEOUT : DB_LOCK_GET;
couple[0].obj = &dbc->lock_dbt; couple[i].obj = &dbc->lock_dbt;
couple[0].mode = mode; couple[i].mode = mode;
UMRW_SET(couple[0].timeout); UMRW_SET(couple[i].timeout);
i++;
if (has_timeout) if (has_timeout)
couple[0].timeout = couple[0].timeout =
F_ISSET(dbc, DBC_RECOVER) ? 0 : txn->lock_timeout; F_ISSET(dbc, DBC_RECOVER) ? 0 : txn->lock_timeout;
if (action == LCK_COUPLE) { if (action == LCK_COUPLE || action == LCK_DOWNGRADE) {
couple[1].op = DB_LOCK_PUT; couple[i].op = DB_LOCK_PUT;
couple[1].lock = *lockp; couple[i].lock = *lockp;
i++;
} }
ret = __lock_vec(dbenv, dbc->locker, ret = __lock_vec(dbenv,
lkflags, couple, action == LCK_COUPLE ? 2 : 1, &reqp); dbc->locker, lkflags, couple, i, &reqp);
if (ret == 0 || reqp == &couple[1]) if (ret == 0 || reqp == &couple[i - 1])
*lockp = couple[0].lock; *lockp = i == 1 ? couple[0].lock : couple[i - 2].lock;
break; break;
} }
@ -511,6 +1017,7 @@ __db_lput(dbc, lockp)
DB_LOCK *lockp; DB_LOCK *lockp;
{ {
DB_ENV *dbenv; DB_ENV *dbenv;
DB_LOCKREQ couple[2], *reqp;
int action, ret; int action, ret;
/* /*
@ -518,13 +1025,16 @@ __db_lput(dbc, lockp)
* Hold on to the read locks only if we are in full isolation. * Hold on to the read locks only if we are in full isolation.
* Downgrade write locks if we are supporting dirty readers. * 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; action = LCK_DOWNGRADE;
else if (dbc->txn == NULL) else if (dbc->txn == NULL)
action = LCK_COUPLE; 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; 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; action = LCK_COUPLE;
else else
action = 0; action = 0;
@ -532,10 +1042,19 @@ __db_lput(dbc, lockp)
dbenv = dbc->dbp->dbenv; dbenv = dbc->dbp->dbenv;
switch (action) { switch (action) {
case LCK_COUPLE: case LCK_COUPLE:
ret = __lock_put(dbenv, lockp, 0); ret = __lock_put(dbenv, lockp);
break; break;
case LCK_DOWNGRADE: 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; break;
default: default:
ret = 0; ret = 0;

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1999-2004 * Copyright (c) 1999-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -32,8 +32,7 @@
#include "dbinc/lock.h" #include "dbinc/lock.h"
#include "dbinc/mp.h" #include "dbinc/mp.h"
#include "dbinc/qam.h" #include "dbinc/qam.h"
#include "dbinc/xa.h" #include "dbinc/txn.h"
#include "dbinc_auto/xa_ext.h"
#ifdef HAVE_RPC #ifdef HAVE_RPC
#include "dbinc_auto/rpc_client_ext.h" #include "dbinc_auto/rpc_client_ext.h"
@ -42,9 +41,10 @@
static int __db_get_byteswapped __P((DB *, int *)); static int __db_get_byteswapped __P((DB *, int *));
static int __db_get_dbname __P((DB *, const char **, const char **)); static int __db_get_dbname __P((DB *, const char **, const char **));
static DB_ENV *__db_get_env __P((DB *)); 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_transactional __P((DB *));
static int __db_get_type __P((DB *, DBTYPE *dbtype)); 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), static int __db_set_alloc __P((DB *, void *(*)(size_t),
void *(*)(void *, size_t), void (*)(void *))); void *(*)(void *, size_t), void (*)(void *)));
static int __db_set_append_recno __P((DB *, int (*)(DB *, DBT *, db_recno_t))); 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_err __P((DB *, int, const char *, ...));
static void __dbh_errx __P((DB *, 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_create --
* DB constructor. * DB constructor.
@ -88,14 +84,14 @@ db_create(dbpp, dbenv, flags)
u_int32_t flags; u_int32_t flags;
{ {
DB *dbp; DB *dbp;
DB_THREAD_INFO *ip;
DB_REP *db_rep;
int ret; int ret;
/* Check for invalid function flags. */ /* Check for invalid function flags. */
switch (flags) { switch (flags) {
case 0: case 0:
break; break;
case DB_REP_CREATE:
break;
case DB_XA_CREATE: case DB_XA_CREATE:
if (dbenv != NULL) { if (dbenv != NULL) {
__db_err(dbenv, __db_err(dbenv,
@ -115,16 +111,17 @@ db_create(dbpp, dbenv, flags)
return (__db_ferr(dbenv, "db_create", 0)); return (__db_ferr(dbenv, "db_create", 0));
} }
ip = NULL;
if (dbenv != NULL)
ENV_ENTER(dbenv, ip);
/* Allocate the DB. */ /* 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); return (ret);
#ifdef HAVE_RPC }
if (dbenv != NULL && RPC_ON(dbenv))
ret = __dbcl_init(dbp, dbenv, flags); if ((ret = __db_init(dbenv, dbp, flags)) != 0)
else
#endif
ret = __db_init(dbp, flags);
if (ret != 0)
goto err; goto err;
/* If we don't have an environment yet, allocate a local one. */ /* 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) if ((ret = db_env_create(&dbenv, 0)) != 0)
goto err; goto err;
F_SET(dbenv, DB_ENV_DBLOCAL); F_SET(dbenv, DB_ENV_DBLOCAL);
ENV_ENTER(dbenv, ip);
} }
dbp->dbenv = dbenv; dbp->dbenv = dbenv;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
++dbenv->db_ref; ++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 * 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 = dbp->timestamp = REP_ON(dbenv) ?
(F_ISSET(dbenv, DB_ENV_DBLOCAL) || !REP_ON(dbenv)) ? 0 : ((REGENV *)((REGINFO *)dbenv->reginfo)->primary)->rep_timestamp : 0;
((REGENV *)((REGINFO *)dbenv->reginfo)->primary)->rep_timestamp; /*
* 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. */ /* If not RPC, open a backing DB_MPOOLFILE handle in the memory pool. */
#ifdef HAVE_RPC if (!RPC_ON(dbenv) &&
if (!RPC_ON(dbenv)) (ret = __memp_fcreate(dbenv, &dbp->mpf)) != 0)
#endif goto err;
if ((ret = __memp_fcreate(dbenv, &dbp->mpf)) != 0)
goto err;
dbp->type = DB_UNKNOWN; dbp->type = DB_UNKNOWN;
@ -161,9 +166,10 @@ db_create(dbpp, dbenv, flags)
err: if (dbp->mpf != NULL) err: if (dbp->mpf != NULL)
(void)__memp_fclose(dbp->mpf, 0); (void)__memp_fclose(dbp->mpf, 0);
if (dbenv != NULL && F_ISSET(dbenv, DB_ENV_DBLOCAL)) if (dbenv != NULL && F_ISSET(dbenv, DB_ENV_DBLOCAL))
(void)__dbenv_close(dbenv, 0); (void)__env_close(dbenv, 0);
__os_free(dbenv, dbp); __os_free(dbenv, dbp);
*dbpp = NULL; *dbpp = NULL;
ENV_LEAVE(dbenv, ip);
return (ret); return (ret);
} }
@ -172,7 +178,8 @@ err: if (dbp->mpf != NULL)
* Initialize a DB structure. * Initialize a DB structure.
*/ */
static int static int
__db_init(dbp, flags) __db_init(dbenv, dbp, flags)
DB_ENV *dbenv;
DB *dbp; DB *dbp;
u_int32_t flags; u_int32_t flags;
{ {
@ -189,8 +196,10 @@ __db_init(dbp, flags)
FLD_SET(dbp->am_ok, FLD_SET(dbp->am_ok,
DB_OK_BTREE | DB_OK_HASH | DB_OK_QUEUE | DB_OK_RECNO); DB_OK_BTREE | DB_OK_HASH | DB_OK_QUEUE | DB_OK_RECNO);
/* DB PUBLIC HANDLE LIST BEGIN */
dbp->associate = __db_associate_pp; dbp->associate = __db_associate_pp;
dbp->close = __db_close_pp; dbp->close = __db_close_pp;
dbp->compact = __db_compact_pp;
dbp->cursor = __db_cursor_pp; dbp->cursor = __db_cursor_pp;
dbp->del = __db_del_pp; dbp->del = __db_del_pp;
dbp->dump = __db_dump_pp; dbp->dump = __db_dump_pp;
@ -199,9 +208,18 @@ __db_init(dbp, flags)
dbp->fd = __db_fd_pp; dbp->fd = __db_fd_pp;
dbp->get = __db_get_pp; dbp->get = __db_get_pp;
dbp->get_byteswapped = __db_get_byteswapped; dbp->get_byteswapped = __db_get_byteswapped;
dbp->get_cachesize = __db_get_cachesize;
dbp->get_dbname = __db_get_dbname; dbp->get_dbname = __db_get_dbname;
dbp->get_encrypt_flags = __db_get_encrypt_flags;
dbp->get_env = __db_get_env; 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_open_flags = __db_get_open_flags;
dbp->get_pagesize = __db_get_pagesize;
dbp->get_transactional = __db_get_transactional; dbp->get_transactional = __db_get_transactional;
dbp->get_type = __db_get_type; dbp->get_type = __db_get_type;
dbp->join = __db_join_pp; dbp->join = __db_join_pp;
@ -211,35 +229,28 @@ __db_init(dbp, flags)
dbp->put = __db_put_pp; dbp->put = __db_put_pp;
dbp->remove = __db_remove_pp; dbp->remove = __db_remove_pp;
dbp->rename = __db_rename_pp; dbp->rename = __db_rename_pp;
dbp->truncate = __db_truncate_pp;
dbp->set_alloc = __db_set_alloc; dbp->set_alloc = __db_set_alloc;
dbp->set_append_recno = __db_set_append_recno; dbp->set_append_recno = __db_set_append_recno;
dbp->get_cachesize = __db_get_cachesize;
dbp->set_cachesize = __db_set_cachesize; dbp->set_cachesize = __db_set_cachesize;
dbp->set_dup_compare = __db_set_dup_compare; dbp->set_dup_compare = __db_set_dup_compare;
dbp->get_encrypt_flags = __db_get_encrypt_flags;
dbp->set_encrypt = __db_set_encrypt; dbp->set_encrypt = __db_set_encrypt;
dbp->set_errcall = __db_set_errcall; dbp->set_errcall = __db_set_errcall;
dbp->get_errfile = __db_get_errfile;
dbp->set_errfile = __db_set_errfile; dbp->set_errfile = __db_set_errfile;
dbp->get_errpfx = __db_get_errpfx;
dbp->set_errpfx = __db_set_errpfx; dbp->set_errpfx = __db_set_errpfx;
dbp->set_feedback = __db_set_feedback; dbp->set_feedback = __db_set_feedback;
dbp->get_flags = __db_get_flags;
dbp->set_flags = __db_set_flags; dbp->set_flags = __db_set_flags;
dbp->get_lorder = __db_get_lorder;
dbp->set_lorder = __db_set_lorder; dbp->set_lorder = __db_set_lorder;
dbp->set_msgcall = __db_set_msgcall; dbp->set_msgcall = __db_set_msgcall;
dbp->get_msgfile = __db_get_msgfile;
dbp->set_msgfile = __db_set_msgfile; dbp->set_msgfile = __db_set_msgfile;
dbp->get_pagesize = __db_get_pagesize;
dbp->set_pagesize = __db_set_pagesize; dbp->set_pagesize = __db_set_pagesize;
dbp->set_paniccall = __db_set_paniccall; dbp->set_paniccall = __db_set_paniccall;
dbp->stat = __db_stat_pp; dbp->stat = __db_stat_pp;
dbp->stat_print = __db_stat_print_pp; dbp->stat_print = __db_stat_print_pp;
dbp->sync = __db_sync_pp; dbp->sync = __db_sync_pp;
dbp->truncate = __db_truncate_pp;
dbp->upgrade = __db_upgrade_pp; dbp->upgrade = __db_upgrade_pp;
dbp->verify = __db_verify_pp; dbp->verify = __db_verify_pp;
/* DB PUBLIC HANDLE LIST END */
/* Access method specific. */ /* Access method specific. */
if ((ret = __bam_db_create(dbp)) != 0) 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) if (LF_ISSET(DB_XA_CREATE) && (ret = __db_xa_create(dbp)) != 0)
return (ret); return (ret);
if (LF_ISSET(DB_REP_CREATE)) #ifdef HAVE_RPC
F_SET(dbp, DB_AM_REPLICATION); /*
* 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); return (0);
} }
@ -370,6 +398,17 @@ __db_get_env(dbp)
return (dbp->dbenv); 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_transactional --
* Get whether this database was created in a transaction. * 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"); 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_IN_ENV(dbp, "DB->set_encrypt");
DB_ILLEGAL_AFTER_OPEN(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); return (ret);
/* /*
@ -517,7 +556,7 @@ __db_set_errcall(dbp, errcall)
DB *dbp; DB *dbp;
void (*errcall) __P((const DB_ENV *, const char *, const char *)); void (*errcall) __P((const DB_ENV *, const char *, const char *));
{ {
__dbenv_set_errcall(dbp->dbenv, errcall); __env_set_errcall(dbp->dbenv, errcall);
} }
static void static void
@ -525,7 +564,7 @@ __db_get_errfile(dbp, errfilep)
DB *dbp; DB *dbp;
FILE **errfilep; FILE **errfilep;
{ {
__dbenv_get_errfile(dbp->dbenv, errfilep); __env_get_errfile(dbp->dbenv, errfilep);
} }
static void static void
@ -533,7 +572,7 @@ __db_set_errfile(dbp, errfile)
DB *dbp; DB *dbp;
FILE *errfile; FILE *errfile;
{ {
__dbenv_set_errfile(dbp->dbenv, errfile); __env_set_errfile(dbp->dbenv, errfile);
} }
static void static void
@ -541,7 +580,7 @@ __db_get_errpfx(dbp, errpfxp)
DB *dbp; DB *dbp;
const char **errpfxp; const char **errpfxp;
{ {
__dbenv_get_errpfx(dbp->dbenv, errpfxp); __env_get_errpfx(dbp->dbenv, errpfxp);
} }
static void static void
@ -549,7 +588,7 @@ __db_set_errpfx(dbp, errpfx)
DB *dbp; DB *dbp;
const char *errpfx; const char *errpfx;
{ {
__dbenv_set_errpfx(dbp->dbenv, errpfx); __env_set_errpfx(dbp->dbenv, errpfx);
} }
static int 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_IN_ENV(dbp, "DB->set_alloc");
DB_ILLEGAL_AFTER_OPEN(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 static void
@ -748,7 +787,7 @@ __db_set_msgcall(dbp, msgcall)
DB *dbp; DB *dbp;
void (*msgcall) __P((const DB_ENV *, const char *)); void (*msgcall) __P((const DB_ENV *, const char *));
{ {
__dbenv_set_msgcall(dbp->dbenv, msgcall); __env_set_msgcall(dbp->dbenv, msgcall);
} }
static void static void
@ -756,7 +795,7 @@ __db_get_msgfile(dbp, msgfilep)
DB *dbp; DB *dbp;
FILE **msgfilep; FILE **msgfilep;
{ {
__dbenv_get_msgfile(dbp->dbenv, msgfilep); __env_get_msgfile(dbp->dbenv, msgfilep);
} }
static void static void
@ -764,7 +803,7 @@ __db_set_msgfile(dbp, msgfile)
DB *dbp; DB *dbp;
FILE *msgfile; FILE *msgfile;
{ {
__dbenv_set_msgfile(dbp->dbenv, msgfile); __env_set_msgfile(dbp->dbenv, msgfile);
} }
static int static int
@ -824,97 +863,5 @@ __db_set_paniccall(dbp, paniccall)
DB *dbp; DB *dbp;
void (*paniccall) __P((DB_ENV *, int)); 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. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -42,12 +42,15 @@
* 2. It can be called to open a subdatabase during normal operation. In * 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 * this case, name and subname will both be non-NULL and meta_pgno will
* be PGNO_BASE_MD (also PGNO_INVALID). * 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 * name will be non-NULL, subname will be NULL, and meta-pgno will be
* PGNO_BASE_MD. * 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 * name will be non-NULL, subname may be NULL and meta-pgno will be
* a valid pgno (i.e., not PGNO_BASE_MD). * 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: int __db_open __P((DB *, DB_TXN *,
* PUBLIC: const char *, const char *, DBTYPE, u_int32_t, int, db_pgno_t)); * 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. */ /* Convert any DB->open flags. */
if (LF_ISSET(DB_RDONLY)) if (LF_ISSET(DB_RDONLY))
F_SET(dbp, DB_AM_RDONLY); F_SET(dbp, DB_AM_RDONLY);
if (LF_ISSET(DB_DIRTY_READ)) if (LF_ISSET(DB_READ_UNCOMMITTED))
F_SET(dbp, DB_AM_DIRTY); F_SET(dbp, DB_AM_READ_UNCOMMITTED);
if (txn != NULL) if (txn != NULL)
F_SET(dbp, DB_AM_TXN); F_SET(dbp, DB_AM_TXN);
@ -95,43 +98,64 @@ __db_open(dbp, txn, fname, dname, type, flags, mode, meta_pgno)
dbp->type = type; dbp->type = type;
/* /*
* If fname is NULL, it's always a create, so make sure that we * If both fname and subname are NULL, it's always a create, so make
* have a type specified. It would be nice if this checking * sure that we have both DB_CREATE and a type specified. It would
* were done in __db_open where most of the interface checking * be nice if this checking were done in __db_open where most of the
* is done, but this interface (__db_dbopen) is used by the * interface checking is done, but this interface (__db_dbopen) is
* recovery and limbo system, so we need to safeguard this * used by the recovery and limbo system, so we need to safeguard
* interface as well. * this interface as well.
*/ */
if (fname == NULL) { 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) { F_SET(dbp, DB_AM_INMEM);
__db_err(dbenv, F_SET(dbp, DB_AM_CREATED);
"DBTYPE of unknown without existing file");
return (EINVAL);
}
if (dbp->pgsize == 0) if (dbp->type == DB_UNKNOWN) {
dbp->pgsize = DB_DEF_IOSIZE; __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, * Normally we would do handle locking here, however, with
* then we have to create a unique file ID. We can't use our * in-memory files, we cannot do any database manipulation
* normal dev/inode pair (or whatever this OS uses in place of * until the mpool is open, so it happens later.
* 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)) != 0)
return (ret);
} else if (dname == NULL && meta_pgno == PGNO_BASE_MD) { } else if (dname == NULL && meta_pgno == PGNO_BASE_MD) {
/* Open/create the underlying file. Acquire locks. */ /* Open/create the underlying file. Acquire locks. */
if ((ret = if ((ret =
@ -161,40 +185,46 @@ __db_open(dbp, txn, fname, dname, type, flags, mode, meta_pgno)
LF_SET(DB_TRUNCATE); LF_SET(DB_TRUNCATE);
/* Set up the underlying environment. */ /* 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); return (ret);
/* /* For in-memory databases, we now need to open/create the database. */
* Set the open flag. We use it to mean that the dbp has gone if (F_ISSET(dbp, DB_AM_INMEM)) {
* through mpf setup, including dbreg_register. Also, below, if (dname == NULL)
* the underlying access method open functions may want to do ret = __db_new_file(dbp, txn, NULL, NULL);
* things like acquire cursors, so the open flag has to be set else {
* before calling them. id = TXN_INVALID;
*/ if ((ret = __fop_file_setup(dbp,
F_SET(dbp, DB_AM_OPEN_CALLED); txn, dname, mode, flags, &id)) == 0 &&
DBENV_LOGGING(dbenv) && !F_ISSET(dbp, DB_AM_RECOVER)
/* #if !defined(DEBUG_ROP)
* For unnamed files, we need to actually create the file now && !F_ISSET(dbp, DB_AM_RDONLY)
* that the mpool is open. #endif
*/ )
if (fname == NULL && (ret = __db_new_file(dbp, txn, NULL, NULL)) != 0) ret = __dbreg_log_id(dbp,
return (ret); txn, dbp->log_filename->id, 1);
}
if (ret != 0)
goto err;
}
switch (dbp->type) { switch (dbp->type) {
case DB_BTREE: case DB_BTREE:
ret = __bam_open(dbp, txn, fname, meta_pgno, flags); ret = __bam_open(dbp, txn, fname, meta_pgno, flags);
break; break;
case DB_HASH: case DB_HASH:
ret = __ham_open(dbp, txn, fname, meta_pgno, flags); ret = __ham_open(dbp, txn, fname, meta_pgno, flags);
break; break;
case DB_RECNO: case DB_RECNO:
ret = __ram_open(dbp, txn, fname, meta_pgno, flags); ret = __ram_open(dbp, txn, fname, meta_pgno, flags);
break; break;
case DB_QUEUE: case DB_QUEUE:
ret = __qam_open(dbp, txn, fname, meta_pgno, mode, flags); ret = __qam_open(
break; dbp, txn, fname, meta_pgno, mode, flags);
case DB_UNKNOWN: break;
return (__db_unknown_type(dbenv, "__db_dbopen", dbp->type)); case DB_UNKNOWN:
return (
__db_unknown_type(dbenv, "__db_dbopen", dbp->type));
} }
if (ret != 0) if (ret != 0)
goto err; 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); 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 * for a handle lock downgrade or lockevent in the case of named
* files. * files.
*/ */
if (!F_ISSET(dbp, DB_AM_RECOVER) && if (!F_ISSET(dbp, DB_AM_RECOVER) && (fname != NULL || dname != NULL)
fname != NULL && LOCK_ISSET(dbp->handle_lock)) { && LOCK_ISSET(dbp->handle_lock)) {
if (txn != NULL) { if (txn != NULL)
ret = __txn_lockevent(dbenv, ret = __txn_lockevent(dbenv,
txn, dbp, &dbp->handle_lock, dbp->lid); 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. */ /* Trade write handle lock for read handle lock. */
ret = __lock_downgrade(dbenv, ret = __lock_downgrade(dbenv,
&dbp->handle_lock, DB_LOCK_READ, 0); &dbp->handle_lock, DB_LOCK_READ, 0);
@ -341,8 +371,8 @@ err: return (ret);
/* /*
* __db_chk_meta -- * __db_chk_meta --
* Take a buffer containing a meta-data page and check it for a checksum * Take a buffer containing a meta-data page and check it for a valid LSN,
* (and verify the checksum if necessary) and possibly decrypt it. * checksum (and verify the checksum if necessary) and possibly decrypt it.
* *
* Return 0 on success, >0 (errno) on error, -1 on checksum mismatch. * 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; DBMETA *meta;
int do_metachk; int do_metachk;
{ {
DB_LSN cur_lsn, swap_lsn;
int is_hmac, ret, swapped; int is_hmac, ret, swapped;
u_int32_t orig_chk; u_int32_t magic, orig_chk;
u_int8_t *chksum; u_int8_t *chksum;
ret = 0; ret = 0;
swapped = 0;
if (FLD_ISSET(meta->metaflags, DBMETA_CHKSUM)) { if (FLD_ISSET(meta->metaflags, DBMETA_CHKSUM)) {
if (dbp != NULL) if (dbp != NULL)
@ -399,6 +431,56 @@ chk_retry: if ((ret = __db_check_chksum(dbenv,
#ifdef HAVE_CRYPTO #ifdef HAVE_CRYPTO
ret = __crypto_decrypt_meta(dbenv, dbp, (u_int8_t *)meta, do_metachk); ret = __crypto_decrypt_meta(dbenv, dbp, (u_int8_t *)meta, do_metachk);
#endif #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); 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 * 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. * 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; magic = meta->magic;
swap_retry: swap_retry:

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -39,7 +39,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"
@ -241,8 +241,6 @@ __db_poff(dbc, dbt, pgnop)
LSN(lastp) = new_lsn; LSN(lastp) = new_lsn;
LSN(pagep) = 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_LEN(pagep) = pagespace;
OV_REF(pagep) = 1; OV_REF(pagep) = 1;
memcpy((u_int8_t *)pagep + P_OVERHEAD(dbp), p, pagespace); memcpy((u_int8_t *)pagep + P_OVERHEAD(dbp), p, pagespace);
@ -288,7 +286,7 @@ __db_ovref(dbc, pgno, adjust)
mpf = dbp->mpf; mpf = dbp->mpf;
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0) if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
return (__db_pgerr(dbp, pgno, ret)); return (ret);
if (DBC_LOGGING(dbc)) { if (DBC_LOGGING(dbc)) {
if ((ret = __db_ovref_log(dbp, if ((ret = __db_ovref_log(dbp,
@ -327,7 +325,7 @@ __db_doff(dbc, pgno)
do { do {
if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0) if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0)
return (__db_pgerr(dbp, pgno, ret)); return (ret);
DB_ASSERT(TYPE(pagep) == P_OVERFLOW); DB_ASSERT(TYPE(pagep) == P_OVERFLOW);
/* /*

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -39,7 +39,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -35,9 +35,10 @@
void void
__db_loadme() __db_loadme()
{ {
u_int32_t id; pid_t pid;
db_threadid_t tid;
__os_id(&id); __os_id(NULL, &pid, &tid);
} }
#ifdef HAVE_STATISTICS #ifdef HAVE_STATISTICS
@ -106,38 +107,37 @@ __db_dumptree(dbp, op, name)
} }
static const FN __db_flags_fn[] = { static const FN __db_flags_fn[] = {
{ DB_AM_CHKSUM, "checksumming" }, { DB_AM_CHKSUM, "checksumming" },
{ DB_AM_CL_WRITER, "client replica writer" }, { DB_AM_CL_WRITER, "client replica writer" },
{ DB_AM_COMPENSATE, "created by compensating transaction" }, { DB_AM_COMPENSATE, "created by compensating transaction" },
{ DB_AM_CREATED, "database created" }, { DB_AM_CREATED, "database created" },
{ DB_AM_CREATED_MSTR, "encompassing file created" }, { DB_AM_CREATED_MSTR, "encompassing file created" },
{ DB_AM_DBM_ERROR, "dbm/ndbm error" }, { DB_AM_DBM_ERROR, "dbm/ndbm error" },
{ DB_AM_DELIMITER, "variable length" }, { DB_AM_DELIMITER, "variable length" },
{ DB_AM_DIRTY, "dirty reads" }, { DB_AM_DISCARD, "discard cached pages" },
{ DB_AM_DISCARD, "discard cached pages" }, { DB_AM_DUP, "duplicates" },
{ DB_AM_DUP, "duplicates" }, { DB_AM_DUPSORT, "sorted duplicates" },
{ DB_AM_DUPSORT, "sorted duplicates" }, { DB_AM_ENCRYPT, "encrypted" },
{ DB_AM_ENCRYPT, "encrypted" }, { DB_AM_FIXEDLEN, "fixed-length records" },
{ DB_AM_FIXEDLEN, "fixed-length records" }, { DB_AM_INMEM, "in-memory" },
{ DB_AM_INMEM, "in-memory" }, { DB_AM_IN_RENAME, "file is being renamed" },
{ DB_AM_IN_RENAME, "file is being renamed" }, { DB_AM_NOT_DURABLE, "changes not logged" },
{ DB_AM_NOT_DURABLE, "changes not logged" }, { DB_AM_OPEN_CALLED, "open called" },
{ DB_AM_OPEN_CALLED, "open called" }, { DB_AM_PAD, "pad value" },
{ DB_AM_PAD, "pad value" }, { DB_AM_PGDEF, "default page size" },
{ DB_AM_PGDEF, "default page size" }, { DB_AM_RDONLY, "read-only" },
{ DB_AM_RDONLY, "read-only" }, { DB_AM_READ_UNCOMMITTED, "read-uncommitted" },
{ DB_AM_RECNUM, "Btree record numbers" }, { DB_AM_RECNUM, "Btree record numbers" },
{ DB_AM_RECOVER, "opened for recovery" }, { DB_AM_RECOVER, "opened for recovery" },
{ DB_AM_RENUMBER, "renumber" }, { DB_AM_RENUMBER, "renumber" },
{ DB_AM_REPLICATION, "replication file" }, { DB_AM_REVSPLITOFF, "no reverse splits" },
{ DB_AM_REVSPLITOFF, "no reverse splits" }, { DB_AM_SECONDARY, "secondary" },
{ DB_AM_SECONDARY, "secondary" }, { DB_AM_SNAPSHOT, "load on open" },
{ DB_AM_SNAPSHOT, "load on open" }, { DB_AM_SUBDB, "subdatabases" },
{ DB_AM_SUBDB, "subdatabases" }, { DB_AM_SWAP, "needswap" },
{ DB_AM_SWAP, "needswap" }, { DB_AM_TXN, "transactional" },
{ DB_AM_TXN, "transactional" }, { DB_AM_VERIFYING, "verifier" },
{ DB_AM_VERIFYING, "verifier" }, { 0, NULL }
{ 0, NULL }
}; };
/* /*
@ -182,8 +182,7 @@ __db_prdb(dbp, flags)
bt = dbp->bt_internal; bt = dbp->bt_internal;
__db_msg(dbenv, "bt_meta: %lu bt_root: %lu", __db_msg(dbenv, "bt_meta: %lu bt_root: %lu",
(u_long)bt->bt_meta, (u_long)bt->bt_root); (u_long)bt->bt_meta, (u_long)bt->bt_root);
__db_msg(dbenv, "bt_maxkey: %lu bt_minkey: %lu", __db_msg(dbenv, "bt_minkey: %lu", (u_long)bt->bt_minkey);
(u_long)bt->bt_maxkey, (u_long)bt->bt_minkey);
if (!LF_ISSET(DB_PR_RECOVERYTEST)) if (!LF_ISSET(DB_PR_RECOVERYTEST))
__db_msg(dbenv, "bt_compare: %#lx bt_prefix: %#lx", __db_msg(dbenv, "bt_compare: %#lx bt_prefix: %#lx",
P_TO_ULONG(bt->bt_compare), 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 * Find out the page number of the last page in the database, then
* dump each page. * dump each page.
*/ */
__memp_last_pgno(mpf, &last); if ((ret = __memp_last_pgno(mpf, &last)) != 0)
return (ret);
for (i = 0; i <= last; ++i) { for (i = 0; i <= last; ++i) {
if ((ret = __memp_fget(mpf, &i, 0, &h)) != 0) if ((ret = __memp_fget(mpf, &i, 0, &h)) != 0)
return (ret); return (ret);
@ -362,8 +362,7 @@ __db_bmeta(dbp, h, flags)
__db_meta(dbp, (DBMETA *)h, fn, flags); __db_meta(dbp, (DBMETA *)h, fn, flags);
__db_msg(dbenv, "\tmaxkey: %lu minkey: %lu", __db_msg(dbenv, "\tminkey: %lu", (u_long)h->minkey);
(u_long)h->maxkey, (u_long)h->minkey);
if (dbp->type == DB_RECNO) if (dbp->type == DB_RECNO)
__db_msg(dbenv, "\tre_len: %#lx re_pad: %#lx", __db_msg(dbenv, "\tre_len: %#lx re_pad: %#lx",
(u_long)h->re_len, (u_long)h->re_pad); (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; pagesize = (u_int32_t)dbp->mpf->mfp->stat.st_pagesize;
/* Page number, page type. */ /* Page number, page type. */
__db_msgadd(dbenv, &mb, "page %lu: %s level: %lu", __db_msgadd(dbenv, &mb, "page %lu: %s:", (u_long)h->pgno, s);
(u_long)h->pgno, s, (u_long)h->level);
/*
* 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. */ /* Record count. */
if (TYPE(h) == P_IBTREE || if (TYPE(h) == P_IBTREE ||
TYPE(h) == P_IRECNO || (TYPE(h) == P_LRECNO && TYPE(h) == P_IRECNO || (TYPE(h) == P_LRECNO &&
h->pgno == ((BTREE *)dbp->bt_internal)->bt_root)) h->pgno == ((BTREE *)dbp->bt_internal)->bt_root))
__db_msgadd(dbenv, &mb, " records: %lu", (u_long)RE_NREC(h)); __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); DB_MSGBUF_FLUSH(dbenv, &mb);
switch (TYPE(h)) { switch (TYPE(h)) {
@ -564,11 +573,6 @@ __db_prpage(dbp, h, flags)
break; 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"; s = "\t";
if (TYPE(h) != P_IBTREE && TYPE(h) != P_IRECNO) { if (TYPE(h) != P_IBTREE && TYPE(h) != P_IRECNO) {
__db_msgadd(dbenv, &mb, "%sprev: %4lu next: %4lu", __db_msgadd(dbenv, &mb, "%sprev: %4lu next: %4lu",
@ -680,7 +684,7 @@ __db_prpage(dbp, h, flags)
case P_IBTREE: case P_IBTREE:
bi = sp; bi = sp;
__db_msgadd(dbenv, &mb, __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->nrecs, (u_long)bi->pgno,
(u_long)bi->type); (u_long)bi->type);
switch (B_TYPE(bi->type)) { switch (B_TYPE(bi->type)) {
@ -867,8 +871,8 @@ __db_lockmode_to_string(mode)
return ("Intent shared/read"); return ("Intent shared/read");
case DB_LOCK_IWR: case DB_LOCK_IWR:
return ("Intent to read/write"); return ("Intent to read/write");
case DB_LOCK_DIRTY: case DB_LOCK_READ_UNCOMMITTED:
return ("Dirty read"); return ("Read uncommitted");
case DB_LOCK_WWRITE: case DB_LOCK_WWRITE:
return ("Was written"); return ("Was written");
default: default:
@ -988,25 +992,31 @@ __db_dump_pp(dbp, subname, callback, handle, pflag, keyflag)
int pflag, keyflag; int pflag, keyflag;
{ {
DB_ENV *dbenv; DB_ENV *dbenv;
int handle_check, ret; DB_THREAD_INFO *ip;
int handle_check, ret, t_ret;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
PANIC_CHECK(dbenv); PANIC_CHECK(dbenv);
DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->dump"); DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->dump");
ENV_ENTER(dbenv, ip);
/* Check for replication block. */ /* Check for replication block. */
handle_check = IS_REPLICATED(dbenv, dbp); handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 1)) != 0) if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 1)) != 0) {
return (ret); handle_check = 0;
goto err;
}
ret = __db_dump(dbp, subname, callback, handle, pflag, keyflag); ret = __db_dump(dbp, subname, callback, handle, pflag, keyflag);
/* Release replication block. */ /* Release replication block. */
if (handle_check) if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
__env_db_rep_exit(dbenv); ret = t_ret;
return (0); err: ENV_LEAVE(dbenv, ip);
return (ret);
} }
/* /*
@ -1088,8 +1098,11 @@ retry: while ((ret =
data.ulen = data.size; data.ulen = data.size;
goto retry; 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) err: if ((t_ret = __db_c_close(dbcp)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
@ -1310,39 +1323,28 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
case DB_BTREE: case DB_BTREE:
if ((ret = callback(handle, "type=btree\n")) != 0) if ((ret = callback(handle, "type=btree\n")) != 0)
goto err; goto err;
if (using_vdp) { if (using_vdp)
if (F_ISSET(pip, VRFY_HAS_RECNUMS)) tmp_int = F_ISSET(pip, VRFY_HAS_RECNUMS) ? 1 : 0;
if ((ret = else {
callback(handle, "recnum=1\n")) != 0) if ((ret = __db_get_flags(dbp, &flags)) != 0) {
goto err; __db_err(dbenv,
if (pip->bt_maxkey != 0) { "DB->get_flags: %s", db_strerror(ret));
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)
goto err; goto err;
if ((ret = __bam_get_bt_minkey(dbp, &tmp_u_int32)) != 0) { }
__db_err(dbenv, tmp_int = F_ISSET(dbp, DB_AM_RECNUM) ? 1 : 0;
"DB->get_bt_minkey: %s", db_strerror(ret));
goto err;
} }
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) { if (tmp_u_int32 != 0 && tmp_u_int32 != DEFMINKEYPAGE) {
snprintf(buf, buflen, snprintf(buf, buflen,
"bt_minkey=%lu\n", (u_long)tmp_u_int32); "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 #ifdef HAVE_HASH
if ((ret = callback(handle, "type=hash\n")) != 0) if ((ret = callback(handle, "type=hash\n")) != 0)
goto err; goto err;
if (using_vdp) { if (using_vdp)
if (pip->h_ffactor != 0) { tmp_u_int32 = pip->h_ffactor;
snprintf(buf, buflen, else
"h_ffactor=%lu\n", (u_long)pip->h_ffactor); if ((ret =
if ((ret = callback(handle, buf)) != 0) __ham_get_h_ffactor(dbp, &tmp_u_int32)) != 0) {
goto err; __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) { if (tmp_u_int32 != 0) {
snprintf(buf, buflen, snprintf(buf, buflen,
"h_ffactor=%lu\n", (u_long)tmp_u_int32); "h_ffactor=%lu\n", (u_long)tmp_u_int32);
if ((ret = callback(handle, buf)) != 0) if ((ret = callback(handle, buf)) != 0)
goto err; goto err;
} }
if ((ret = __ham_get_h_nelem(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv, if (using_vdp)
"DB->get_h_nelem: %s", db_strerror(ret)); tmp_u_int32 = pip->h_nelem;
goto err; else
} if ((ret = __ham_get_h_nelem(dbp, &tmp_u_int32)) != 0) {
if (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, snprintf(buf, buflen,
"h_nelem=%lu\n", (u_long)tmp_u_int32); "h_nelem=%lu\n", (u_long)tmp_u_int32);
if ((ret = callback(handle, buf)) != 0) if ((ret = callback(handle, buf)) != 0)
@ -1400,36 +1399,41 @@ __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
#ifdef HAVE_QUEUE #ifdef HAVE_QUEUE
if ((ret = callback(handle, "type=queue\n")) != 0) if ((ret = callback(handle, "type=queue\n")) != 0)
goto err; goto err;
if (vdp != NULL) { if (using_vdp)
snprintf(buf, tmp_u_int32 = vdp->re_len;
buflen, "re_len=%lu\n", (u_long)vdp->re_len); else
if ((ret = callback(handle, buf)) != 0) if ((ret = __ram_get_re_len(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv,
"DB->get_re_len: %s", db_strerror(ret));
goto err; 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); snprintf(buf, buflen, "re_len=%lu\n", (u_long)tmp_u_int32);
if ((ret = callback(handle, buf)) != 0) if ((ret = callback(handle, buf)) != 0)
goto err; goto err;
if ((ret = __ram_get_re_pad(dbp, &tmp_int)) != 0) {
__db_err(dbenv, if (using_vdp)
"DB->get_re_pad: %s", db_strerror(ret)); tmp_int = (int)vdp->re_pad;
goto err; 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 != ' ') { if (tmp_int != 0 && tmp_int != ' ') {
snprintf(buf, buflen, "re_pad=%#x\n", tmp_int); snprintf(buf, buflen, "re_pad=%#x\n", tmp_int);
if ((ret = callback(handle, buf)) != 0) if ((ret = callback(handle, buf)) != 0)
goto err; goto err;
} }
if ((ret = __qam_get_extentsize(dbp, &tmp_u_int32)) != 0) {
__db_err(dbenv, if (using_vdp)
"DB->get_q_extentsize: %s", db_strerror(ret)); tmp_u_int32 = vdp->page_ext;
goto err; 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) { if (tmp_u_int32 != 0) {
snprintf(buf, buflen, snprintf(buf, buflen,
"extentsize=%lu\n", (u_long)tmp_u_int32); "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: case DB_RECNO:
if ((ret = callback(handle, "type=recno\n")) != 0) if ((ret = callback(handle, "type=recno\n")) != 0)
goto err; goto err;
if (using_vdp) { if (using_vdp)
if (F_ISSET(pip, VRFY_IS_RRECNO)) 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 = 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; 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, snprintf(buf, buflen,
"re_len=%lu\n", (u_long)tmp_u_int32); "re_len=%lu\n", (u_long)tmp_u_int32);
if ((ret = callback(handle, buf)) != 0) if ((ret = callback(handle, buf)) != 0)
goto err; goto err;
if ((ret = __ram_get_re_pad(dbp, &tmp_int)) != 0) { if (using_vdp)
__db_err(dbenv, tmp_int = (int)pip->re_pad;
"DB->get_re_pad: %s", db_strerror(ret)); else
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 (tmp_int != 0 && tmp_int != ' ') { if (tmp_int != 0 && tmp_int != ' ') {
snprintf(buf, snprintf(buf,
buflen, "re_pad=%#x\n", (u_int)tmp_int); 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 (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 (F_ISSET(pip, VRFY_HAS_DUPS))
if ((ret = callback(handle, "duplicates=1\n")) != 0) if ((ret = callback(handle, "duplicates=1\n")) != 0)
goto err; goto err;
if (F_ISSET(pip, VRFY_HAS_DUPSORT)) if (F_ISSET(pip, VRFY_HAS_DUPSORT))
if ((ret = callback(handle, "dupsort=1\n")) != 0) if ((ret = callback(handle, "dupsort=1\n")) != 0)
goto err; 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 { } else {
if (F_ISSET(dbp, DB_AM_CHKSUM)) if (F_ISSET(dbp, DB_AM_CHKSUM))
if ((ret = callback(handle, "chksum=1\n")) != 0) if ((ret = callback(handle, "chksum=1\n")) != 0)

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -51,13 +51,13 @@ __db_addrem_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__db_addrem_print); 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); REC_FGET(mpf, argp->pgno, &pagep, done);
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); 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; change = 0;
if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_DUP) || if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_DUP) ||
(cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_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; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__db_big_print); 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); 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_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); 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; change = 0;
if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) || if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) ||
(cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_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_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->prevlsn); 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) { if (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) {
/* Redo add, undo delete. */ /* Redo add, undo delete. */
@ -202,7 +202,7 @@ npage: if (argp->next_pgno != PGNO_INVALID) {
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->nextlsn); 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)) { if (cmp_p == 0 && DB_REDO(op)) {
PREV_PGNO(pagep) = PGNO_INVALID; PREV_PGNO(pagep) = PGNO_INVALID;
change = DB_MPOOL_DIRTY; change = DB_MPOOL_DIRTY;
@ -250,13 +250,13 @@ __db_ovref_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__db_ovref_print); 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); REC_FGET(mpf, argp->pgno, &pagep, done);
modified = 0; modified = 0;
cmp = log_compare(&LSN(pagep), &argp->lsn); 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)) { if (cmp == 0 && DB_REDO(op)) {
/* Need to redo update described. */ /* Need to redo update described. */
OV_REF(pagep) += argp->adjust; OV_REF(pagep) += argp->adjust;
@ -339,13 +339,13 @@ __db_noop_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__db_noop_print); 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); REC_FGET(mpf, argp->pgno, &pagep, done);
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->prevlsn); 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; change = 0;
if (cmp_p == 0 && DB_REDO(op)) { if (cmp_p == 0 && DB_REDO(op)) {
LSN(pagep) = *lsnp; LSN(pagep) = *lsnp;
@ -391,7 +391,7 @@ __db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
created = meta_modified = modified = 0; created = meta_modified = modified = 0;
REC_PRINT(__db_pg_alloc_print); 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 * 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_n = log_compare(lsnp, &LSN(meta));
cmp_p = log_compare(&LSN(meta), &argp->meta_lsn); 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)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */ /* Need to redo update described. */
LSN(meta) = *lsnp; LSN(meta) = *lsnp;
@ -439,6 +439,29 @@ __db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
meta_modified = 1; 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 * Fix up the allocated page. If the page does not exist
* and we can truncate it then don't create it. * 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)))) (IS_ZERO_LSN(argp->page_lsn) && IS_INIT_LSN(LSN(pagep))))
cmp_p = 0; 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 * 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 * 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; DBMETA *meta;
DB_LSN copy_lsn; DB_LSN copy_lsn;
PAGE *pagep; PAGE *pagep, *prevp;
db_pgno_t pgno; int cmp_n, cmp_p, is_meta, meta_modified, modified, ret;
int cmp_n, cmp_p, meta_modified, modified, ret;
meta = NULL; meta = NULL;
pagep = NULL; pagep = NULL;
prevp = NULL;
meta_modified = modified = 0; 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; is_meta = argp->meta_pgno == PGNO_BASE_MD;
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0) {
/* The metadata page must always exist. */ REC_FGET(mpf, argp->meta_pgno, &meta, check_meta);
ret = __db_pgerr(file_dbp, pgno, ret);
goto out; if (argp->meta_pgno != PGNO_BASE_MD)
} prevp = (PAGE *)meta;
cmp_n = log_compare(lsnp, &LSN(meta)); cmp_n = log_compare(lsnp, &LSN(meta));
cmp_p = log_compare(&LSN(meta), &argp->meta_lsn); 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 * 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) if (argp->pgno == argp->last_pgno)
meta->last_pgno = argp->pgno - 1; meta->last_pgno = argp->pgno - 1;
else else if (prevp == NULL)
meta->free = argp->pgno; meta->free = argp->pgno;
else
NEXT_PGNO(prevp) = argp->pgno;
#else #else
/* Need to redo the deallocation. */ /* 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 * If this was a compensating transaction and
* we are a replica, then we never executed the * we are a replica, then we never executed the
* original allocation which incremented meta->free. * 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; meta->last_pgno = meta->free;
#endif #endif
LSN(meta) = *lsnp; LSN(meta) = *lsnp;
meta_modified = 1; meta_modified = 1;
} else if (cmp_n == 0 && DB_UNDO(op)) { } else if (cmp_n == 0 && DB_UNDO(op)) {
/* Need to undo the deallocation. */ /* 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; 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->last_pgno = argp->pgno;
meta_modified = 1; 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 * Get the freed page. If we support truncate then don't
* create the page if we are going to free it. If we're * 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. * and roll it back.
*/ */
#ifdef HAVE_FTRUNCATE #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 = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (ret == DB_PAGE_NOTFOUND) if (ret == DB_PAGE_NOTFOUND)
goto done; goto done;
@ -687,14 +729,19 @@ __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, data)
cmp_p = 0; cmp_p = 0;
#endif #endif
CHECK_LSN(op, cmp_p, &LSN(pagep), &copy_lsn); CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &copy_lsn);
if (DB_REDO(op) && if (DB_REDO(op) &&
(cmp_p == 0 || (cmp_p == 0 ||
(IS_ZERO_LSN(copy_lsn) && (IS_ZERO_LSN(copy_lsn) &&
log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) { log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
/* Need to redo the deallocation. */ /* Need to redo the deallocation. */
#ifdef HAVE_FTRUNCATE #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 = if ((ret =
__memp_fput(mpf, pagep, DB_MPOOL_DISCARD)) != 0) __memp_fput(mpf, pagep, DB_MPOOL_DISCARD)) != 0)
goto out; goto out;
@ -720,7 +767,7 @@ __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, data)
/* Need to reallocate the page. */ /* Need to reallocate the page. */
memcpy(pagep, argp->header.data, argp->header.size); memcpy(pagep, argp->header.data, argp->header.size);
if (data) if (data)
memcpy((u_int8_t*)pagep + pagep->hf_offset, memcpy((u_int8_t*)pagep + HOFFSET(pagep),
argp->data.data, argp->data.size); argp->data.data, argp->data.size);
modified = 1; modified = 1;
@ -731,9 +778,38 @@ __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, data)
pagep = NULL; pagep = NULL;
#ifdef HAVE_FTRUNCATE #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: done:
#endif #endif
if ((ret = __memp_fput(mpf, if (meta != NULL && (ret = __memp_fput(mpf,
meta, meta_modified ? DB_MPOOL_DIRTY : 0)) != 0) meta, meta_modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out; goto out;
meta = NULL; meta = NULL;
@ -771,7 +847,7 @@ __db_pg_free_recover(dbenv, dbtp, lsnp, op, info)
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__db_pg_free_print); 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, ret = __db_pg_free_recover_int(dbenv,
(__db_pg_freedata_args *)argp, file_dbp, lsnp, mpf, op, 0); (__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; int ret;
REC_PRINT(__db_pg_free_print); 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); COMPQUIET(op, DB_TXN_ABORT);
if ((ret = if ((ret =
@ -848,7 +924,7 @@ __db_pg_freedata_recover(dbenv, dbtp, lsnp, op, info)
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__db_pg_freedata_print); 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); 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; int ret, t_ret;
REC_PRINT(__db_pg_prepare_print); 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; mpf = file_dbp->mpf;
@ -993,11 +1069,11 @@ __db_pg_init_recover(dbenv, dbtp, lsnp, op, info)
DB_LSN copy_lsn; DB_LSN copy_lsn;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
PAGE *pagep; PAGE *pagep;
int cmp_n, cmp_p, modified, ret; int cmp_n, cmp_p, modified, ret, type;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__db_pg_init_print); 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; mpf = file_dbp->mpf;
REC_FGET(mpf, argp->pgno, &pagep, done); 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)); (void)__ua_memcpy(&copy_lsn, &LSN(argp->header.data), sizeof(DB_LSN));
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &copy_lsn); 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 (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, 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; pagep->lsn = *lsnp;
modified = 1; modified = 1;
} else if (cmp_n == 0 && DB_UNDO(op)) { } else if (cmp_n == 0 && DB_UNDO(op)) {
/* Put the data back on the page. */ /* Put the data back on the page. */
memcpy(pagep, argp->header.data, argp->header.size); memcpy(pagep, argp->header.data, argp->header.size);
if (argp->data.size > 0) 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); argp->data.data, argp->data.size);
modified = 1; modified = 1;
@ -1029,3 +1109,158 @@ done: *lsnp = argp->prev_lsn;
out: out:
REC_CLOSE; 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. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -209,8 +209,8 @@ reinit: *putp = 0;
ldbt.data = p; ldbt.data = p;
ldbt.size = P_OVERHEAD(dbp); ldbt.size = P_OVERHEAD(dbp);
ldbt.size += p->entries * sizeof(db_indx_t); ldbt.size += p->entries * sizeof(db_indx_t);
ddbt.data = (u_int8_t *)p + p->hf_offset; ddbt.data = (u_int8_t *)p + HOFFSET(p);
ddbt.size = dbp->pgsize - p->hf_offset; ddbt.size = dbp->pgsize - HOFFSET(p);
if ((ret = __db_pg_init_log(dbp, if ((ret = __db_pg_init_log(dbp,
param->dbc->txn, &LSN(p), 0, param->dbc->txn, &LSN(p), 0,
p->pgno, &ldbt, &ddbt)) != 0) p->pgno, &ldbt, &ddbt)) != 0)

View file

@ -1,16 +1,18 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 2001-2004 * Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <string.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
@ -20,55 +22,70 @@
#include "dbinc/hash.h" #include "dbinc/hash.h"
#include "dbinc/db_shash.h" #include "dbinc/db_shash.h"
#include "dbinc/lock.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 *)); 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. * 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)); * PUBLIC: DB_TXN *, const char *, const char *, u_int32_t));
*/ */
int int
__dbenv_dbremove_pp(dbenv, txn, name, subdb, flags) __env_dbremove_pp(dbenv, txn, name, subdb, flags)
DB_ENV *dbenv; DB_ENV *dbenv;
DB_TXN *txn; DB_TXN *txn;
const char *name, *subdb; const char *name, *subdb;
u_int32_t flags; u_int32_t flags;
{ {
DB *dbp; DB *dbp;
DB_THREAD_INFO *ip;
int handle_check, ret, t_ret, txn_local; int handle_check, ret, t_ret, txn_local;
dbp = NULL;
txn_local = 0;
PANIC_CHECK(dbenv); PANIC_CHECK(dbenv);
ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->dbremove"); 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) if ((ret = __db_fchk(dbenv, "DB->remove", flags, DB_AUTO_COMMIT)) != 0)
return (ret); 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 * Create local transaction as necessary, check for consistent
* transaction usage. * 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) if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
return (ret); goto err;
txn_local = 1; txn_local = 1;
} else { } else
if (txn != NULL && !TXN_ON(dbenv)) if (txn != NULL && !TXN_ON(dbenv)) {
return (__db_not_txn_env(dbenv)); ret = __db_not_txn_env(dbenv);
txn_local = 0; goto err;
} }
LF_CLR(DB_AUTO_COMMIT);
if ((ret = db_create(&dbp, dbenv, 0)) != 0) if ((ret = db_create(&dbp, dbenv, 0)) != 0)
goto err; 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); ret = __db_remove_int(dbp, txn, name, subdb, flags);
if (txn_local) { if (txn_local) {
@ -90,19 +107,27 @@ __dbenv_dbremove_pp(dbenv, txn, name, subdb, flags)
dbp->lid = DB_LOCK_INVALIDID; dbp->lid = DB_LOCK_INVALIDID;
} }
if (handle_check) err: if (txn_local && (t_ret =
__env_db_rep_exit(dbenv); __db_txn_auto_resolve(dbenv, txn, 0, ret)) != 0 && ret == 0)
ret = t_ret;
err: if (txn_local)
ret = __db_txn_auto_resolve(dbenv, txn, 0, ret);
/* /*
* We never opened this dbp for real, so don't include a transaction * We never opened this dbp for real, so don't include a transaction
* handle, and use NOSYNC to avoid calling into mpool. * 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; 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); return (ret);
} }
@ -120,7 +145,8 @@ __db_remove_pp(dbp, name, subdb, flags)
u_int32_t flags; u_int32_t flags;
{ {
DB_ENV *dbenv; DB_ENV *dbenv;
int handle_check, ret; DB_THREAD_INFO *ip;
int handle_check, ret, t_ret;
dbenv = dbp->dbenv; 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) if ((ret = __db_check_txn(dbp, NULL, DB_LOCK_INVALIDID, 0)) != 0)
return (ret); return (ret);
handle_check = IS_REPLICATED(dbenv, dbp); ENV_ENTER(dbenv, ip);
if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, 0)) != 0)
return (ret); 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. */ /* Remove the file. */
ret = __db_remove(dbp, NULL, name, subdb, flags); ret = __db_remove(dbp, NULL, name, subdb, flags);
if (handle_check) if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
__env_db_rep_exit(dbenv); ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret); return (ret);
} }
@ -206,15 +238,23 @@ __db_remove_int(dbp, txn, name, subdb, flags)
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
real_name = tmpname = NULL; real_name = tmpname = NULL;
/* Handle subdatabase removes separately. */ if (name == NULL && subdb == NULL) {
if (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); ret = __db_subdb_remove(dbp, txn, name, subdb);
goto err; goto err;
} }
/* Handle transactional file removes separately. */ /* Handle transactional file removes separately. */
if (txn != NULL) { if (txn != NULL) {
ret = __db_dbtxn_remove(dbp, txn, name); ret = __db_dbtxn_remove(dbp, txn, name, subdb);
goto err; goto err;
} }
@ -223,15 +263,16 @@ __db_remove_int(dbp, txn, name, subdb, flags)
* *
* Find the real name of the file. * Find the real name of the file.
*/ */
if ((ret = __db_appname(dbenv, if (!F_ISSET(dbp, DB_AM_INMEM) && (ret =
DB_APP_DATA, name, 0, NULL, &real_name)) != 0) __db_appname(dbenv, DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
goto err; goto err;
/* /*
* If force is set, remove the temporary file. Ignore errors because * If this is a file and force is set, remove the temporary file, which
* the backup file might not exist. * 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) (ret = __db_backup_name(dbenv, real_name, NULL, &tmpname)) == 0)
(void)__os_unlink(dbenv, tmpname); (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) (ret = dbp->db_am_remove(dbp, NULL, name, subdb)) != 0)
goto err; 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); 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); __os_free(dbenv, real_name);
if (tmpname != NULL) if (tmpname != NULL)
__os_free(dbenv, tmpname); __os_free(dbenv, tmpname);
@ -253,6 +296,78 @@ err: if (real_name != NULL)
return (ret); 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 -- * __db_subdb_remove --
* Remove a subdatabase. * Remove a subdatabase.
@ -323,10 +438,10 @@ err:
} }
static int static int
__db_dbtxn_remove(dbp, txn, name) __db_dbtxn_remove(dbp, txn, name, subdb)
DB *dbp; DB *dbp;
DB_TXN *txn; DB_TXN *txn;
const char *name; const char *name, *subdb;
{ {
DB_ENV *dbenv; DB_ENV *dbenv;
int ret; int ret;
@ -336,27 +451,32 @@ __db_dbtxn_remove(dbp, txn, name)
tmpname = NULL; 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, * of the file locked until the transaction commits. As a result,
* we implement remove by renaming the file to some other name * we implement remove by renaming the file to some other name
* (which creates a dummy named file as a placeholder for the * (which creates a dummy named file as a placeholder for the
* file being rename/dremoved) and then deleting that file as * file being rename/dremoved) and then deleting that file as
* a delayed remove at commit. * 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); return (ret);
DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, name); 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; 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 && if (dbp->db_am_remove != NULL &&
(ret = dbp->db_am_remove(dbp, txn, tmpname, NULL)) != 0) (ret = dbp->db_am_remove(dbp, txn, tmpname, NULL)) != 0)
goto err; 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); F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0);
DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, name); DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, name);

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 2001-2004 * Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -23,74 +23,66 @@
#include "dbinc/log.h" #include "dbinc/log.h"
#include "dbinc/mp.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 *, static int __db_subdb_rename __P((DB *,
DB_TXN *, const char *, const char *, const char *)); DB_TXN *, const char *, const char *, const char *));
/* /*
* __dbenv_dbrename_pp * __env_dbrename_pp
* DB_ENV->dbrename pre/post processing. * 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)); * PUBLIC: const char *, const char *, const char *, u_int32_t));
*/ */
int int
__dbenv_dbrename_pp(dbenv, txn, name, subdb, newname, flags) __env_dbrename_pp(dbenv, txn, name, subdb, newname, flags)
DB_ENV *dbenv; DB_ENV *dbenv;
DB_TXN *txn; DB_TXN *txn;
const char *name, *subdb, *newname; const char *name, *subdb, *newname;
u_int32_t flags; 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); PANIC_CHECK(dbenv);
ENV_ILLEGAL_BEFORE_OPEN(dbenv, "DB_ENV->dbrename"); 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) if ((ret = __db_fchk(dbenv, "DB->rename", flags, DB_AUTO_COMMIT)) != 0)
return (ret); 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 * Create local transaction as necessary, check for consistent
* transaction usage. * 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) if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
return (ret); goto err;
txn_local = 1; txn_local = 1;
} else { } else
if (txn != NULL && !TXN_ON(dbenv)) if (txn != NULL && !TXN_ON(dbenv)) {
return (__db_not_txn_env(dbenv)); ret = __db_not_txn_env(dbenv);
txn_local = 0; goto err;
} }
ret = __dbenv_dbrename(dbenv, txn, name, subdb, newname, txn_local); LF_CLR(DB_AUTO_COMMIT);
return (txn_local ? __db_txn_auto_resolve(dbenv, txn, 0, ret) : ret);
}
/*
* __dbenv_dbrename
* DB_ENV->dbrename.
*/
static int
__dbenv_dbrename(dbenv, txn, name, subdb, newname, txn_local)
DB_ENV *dbenv;
DB_TXN *txn;
const char *name, *subdb, *newname;
int txn_local;
{
DB *dbp;
int handle_check, ret, t_ret;
if ((ret = db_create(&dbp, dbenv, 0)) != 0) 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; goto err;
ret = __db_rename_int(dbp, txn, name, subdb, newname); 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; dbp->lid = DB_LOCK_INVALIDID;
} }
if (handle_check) err: if (txn_local && (t_ret =
__env_db_rep_exit(dbenv); __db_txn_auto_resolve(dbenv, txn, 0, ret)) != 0 && ret == 0)
err:
if ((t_ret = __db_close(dbp, txn, DB_NOSYNC)) != 0 && ret == 0)
ret = t_ret; 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); return (ret);
} }
@ -138,7 +144,8 @@ __db_rename_pp(dbp, name, subdb, newname, flags)
u_int32_t flags; u_int32_t flags;
{ {
DB_ENV *dbenv; DB_ENV *dbenv;
int handle_check, ret; DB_THREAD_INFO *ip;
int handle_check, ret, t_ret;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
handle_check = 0; 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 * a database -- we'll destroy the handle, and the application won't
* ever be able to close the database. * ever be able to close the database.
*/ */
if (F_ISSET(dbp, DB_AM_OPEN_CALLED)) { if (F_ISSET(dbp, DB_AM_OPEN_CALLED))
ret = __db_mi_open(dbenv, "DB->rename", 1); return (__db_mi_open(dbenv, "DB->rename", 1));
goto err;
}
/* Validate arguments. */ /* Validate arguments. */
if ((ret = __db_fchk(dbenv, "DB->rename", flags, 0)) != 0) if ((ret = __db_fchk(dbenv, "DB->rename", flags, 0)) != 0)
goto err; return (ret);
/* Check for consistent transaction usage. */ /* Check for consistent transaction usage. */
if ((ret = __db_check_txn(dbp, NULL, DB_LOCK_INVALIDID, 0)) != 0) 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) { if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, 0)) != 0) {
handle_check = 0; handle_check = 0;
goto err; goto err;
@ -177,9 +184,9 @@ __db_rename_pp(dbp, name, subdb, newname, flags)
/* Rename the file. */ /* Rename the file. */
ret = __db_rename(dbp, NULL, name, subdb, newname); ret = __db_rename(dbp, NULL, name, subdb, newname);
err: if (handle_check) if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
__env_db_rep_exit(dbenv); ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret); return (ret);
} }
@ -222,26 +229,40 @@ __db_rename_int(dbp, txn, name, subdb, newname)
{ {
DB_ENV *dbenv; DB_ENV *dbenv;
int ret; int ret;
char *real_name; char *old, *real_name;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
real_name = NULL; real_name = NULL;
DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, name); 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); ret = __db_subdb_rename(dbp, txn, name, subdb, newname);
goto err; 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. * Find the real name of the file.
*/ */
if ((ret = __db_appname(dbenv, if (F_ISSET(dbp, DB_AM_INMEM)) {
DB_APP_DATA, name, 0, NULL, &real_name)) != 0) old = (char *)subdb;
goto err; 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) if ((ret = __fop_remove_setup(dbp, txn, real_name, 0)) != 0)
goto err; goto err;
@ -259,10 +280,10 @@ __db_rename_int(dbp, txn, name, subdb, newname)
* taken care of in the fop layer. * taken care of in the fop layer.
*/ */
if (txn != NULL) { 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; goto err;
} else { } else {
if ((ret = __fop_dbrename(dbp, name, newname)) != 0) if ((ret = __fop_dbrename(dbp, old, newname)) != 0)
goto err; 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(dbp, DB_TEST_POSTDESTROY, ret, newname);
DB_TEST_RECOVERY_LABEL 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); __os_free(dbenv, real_name);
return (ret); return (ret);

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 2000-2004 * Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -17,20 +17,64 @@
#include "db_int.h" #include "db_int.h"
#include "dbinc/db_page.h" #include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/db_swap.h" #include "dbinc/db_swap.h"
#include "dbinc/db_am.h" #include "dbinc/db_am.h"
#include "dbinc/mp.h"
static int __env_fileid_reset __P((DB_ENV *, const char *, int));
/* /*
* __db_fileid_reset -- * __env_fileid_reset_pp --
* Reset the file IDs for every database in the file. * 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 int
__db_fileid_reset(dbenv, name, passwd) __env_fileid_reset_pp(dbenv, name, flags)
DB_ENV *dbenv; DB_ENV *dbenv;
char *name; const char *name;
int passwd; 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; DB *dbp;
DBC *dbcp; DBC *dbcp;
@ -47,27 +91,21 @@ __db_fileid_reset(dbenv, name, passwd)
real_name = NULL; real_name = NULL;
/* Get the real backing file name. */ /* Get the real backing file name. */
if ((ret = __db_appname(dbenv, if ((ret =
DB_APP_DATA, name, 0, NULL, &real_name)) != 0) __db_appname(dbenv, DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
return (ret); return (ret);
/* Get a new file ID. */ /* Get a new file ID. */
if ((ret = __os_fileid(dbenv, real_name, 1, fileid)) != 0) { if ((ret = __os_fileid(dbenv, real_name, 1, fileid)) != 0)
dbenv->err(dbenv, ret, "unable to get new file ID");
goto err; goto err;
}
/* Create the DB object. */ /* Create the DB object. */
if ((ret = db_create(&dbp, dbenv, 0)) != 0) { if ((ret = db_create(&dbp, dbenv, 0)) != 0)
dbenv->err(dbenv, ret, "db_create");
goto err; goto err;
}
/* If configured with a password, the databases are encrypted. */ /* If configured with a password, the databases are encrypted. */
if (passwd && (ret = dbp->set_flags(dbp, DB_ENCRYPT)) != 0) { if (encrypted && (ret = __db_set_flags(dbp, DB_ENCRYPT)) != 0)
dbp->err(dbp, ret, "DB->set_flags: DB_ENCRYPT");
goto err; goto err;
}
/* /*
* Open the DB file. * 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 * Note DB_RDWRMASTER flag, we need to open the master database file
* for writing in this case. * for writing in this case.
*/ */
if ((ret = dbp->open(dbp, if ((ret = __db_open(dbp, NULL,
NULL, name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0)) != 0) { name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0, PGNO_BASE_MD)) != 0)
dbp->err(dbp, ret, "DB->open: %s", name);
goto err; goto err;
}
mpf = dbp->mpf; mpf = dbp->mpf;
pgno = PGNO_BASE_MD; pgno = PGNO_BASE_MD;
if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0) { if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0)
dbp->err(dbp, ret,
"%s: DB_MPOOLFILE->get: %lu", name, (u_long)pgno);
goto err; goto err;
}
memcpy(((DBMETA *)pagep)->uid, fileid, DB_FILE_ID_LEN); memcpy(((DBMETA *)pagep)->uid, fileid, DB_FILE_ID_LEN);
if ((ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0) { if ((ret = __memp_fput(mpf, pagep, DB_MPOOL_DIRTY)) != 0)
dbp->err(dbp, ret,
"%s: DB_MPOOLFILE->put: %lu", name, (u_long)pgno);
goto err; goto err;
}
/* /*
* If the database file doesn't support subdatabases, we only have * 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(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data)); memset(&data, 0, sizeof(data));
if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { if ((ret = __db_cursor(dbp, NULL, &dbcp, 0)) != 0)
dbp->err(dbp, ret, "DB->cursor");
goto err; goto err;
} while ((ret = __db_c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
/* /*
* XXX * XXX
* We're handling actual data, not on-page meta-data, so it * 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)); memcpy(&pgno, data.data, sizeof(db_pgno_t));
DB_NTOHL(&pgno); DB_NTOHL(&pgno);
if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0) { if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0)
dbp->err(dbp, ret,
"%s: DB_MPOOLFILE->get: %lu", name, (u_long)pgno);
goto err; goto err;
}
memcpy(((DBMETA *)pagep)->uid, fileid, DB_FILE_ID_LEN); memcpy(((DBMETA *)pagep)->uid, fileid, DB_FILE_ID_LEN);
if ((ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0) { if ((ret = __memp_fput(mpf, pagep, DB_MPOOL_DIRTY)) != 0)
dbp->err(dbp, ret,
"%s: DB_MPOOLFILE->put: %lu", name, (u_long)pgno);
goto err; goto err;
}
} }
if (ret == DB_NOTFOUND) if (ret == DB_NOTFOUND)
ret = 0; ret = 0;
else
dbp->err(dbp, ret, "DBcursor->get");
err: if (dbcp != NULL && (t_ret = dbcp->c_close(dbcp)) != 0) { err: if (dbcp != NULL && (t_ret = __db_c_close(dbcp)) != 0 && ret == 0)
dbp->err(dbp, ret, "DBcursor->close"); ret = t_ret;
if (ret == 0) if (dbp != NULL && (t_ret = __db_close(dbp, NULL, 0)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
}
if (dbp != NULL && (t_ret = dbp->close(dbp, 0)) != 0) {
dbenv->err(dbenv, ret, "DB->close");
if (ret == 0)
ret = t_ret;
}
if (real_name != NULL) if (real_name != NULL)
__os_free(dbenv, real_name); __os_free(dbenv, real_name);

View file

@ -1,35 +1,77 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 2000-2004 * Copyright (c) 2000-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES #ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h> #include <sys/types.h>
#include <string.h>
#endif #endif
#include "db_int.h" #include "db_int.h"
#include "dbinc/db_page.h" #include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/db_am.h" #include "dbinc/db_am.h"
#include "dbinc/mp.h"
static int __env_lsn_reset __P((DB_ENV *, const char *, int));
/* /*
* __db_lsn_reset -- * __env_lsn_reset_pp --
* Reset the LSNs for every page in the file. * 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 int
__db_lsn_reset(dbenv, name, passwd) __env_lsn_reset_pp(dbenv, name, flags)
DB_ENV *dbenv; DB_ENV *dbenv;
char *name; const char *name;
int passwd; 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 *dbp;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
@ -38,16 +80,12 @@ __db_lsn_reset(dbenv, name, passwd)
int t_ret, ret; int t_ret, ret;
/* Create the DB object. */ /* Create the DB object. */
if ((ret = db_create(&dbp, dbenv, 0)) != 0) { if ((ret = db_create(&dbp, dbenv, 0)) != 0)
dbenv->err(dbenv, ret, "db_create"); return (ret);
return (1);
}
/* If configured with a password, the databases are encrypted. */ /* If configured with a password, the databases are encrypted. */
if (passwd && (ret = dbp->set_flags(dbp, DB_ENCRYPT)) != 0) { if (encrypted && (ret = __db_set_flags(dbp, DB_ENCRYPT)) != 0)
dbp->err(dbp, ret, "DB->set_flags: DB_ENCRYPT");
goto err; goto err;
}
/* /*
* Open the DB file. * 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 * Note DB_RDWRMASTER flag, we need to open the master database file
* for writing in this case. * for writing in this case.
*/ */
if ((ret = dbp->open(dbp, if ((ret = __db_open(dbp, NULL,
NULL, name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0)) != 0) { name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0, PGNO_BASE_MD)) != 0)
dbp->err(dbp, ret, "DB->open: %s", name);
goto err; goto err;
}
/* Reset the LSN on every page of the database file. */ /* Reset the LSN on every page of the database file. */
mpf = dbp->mpf; 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); LSN_NOT_LOGGED(pagep->lsn);
if ((ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY)) != 0) { if ((ret = __memp_fput(mpf, pagep, DB_MPOOL_DIRTY)) != 0)
dbp->err(dbp, ret, "DB_MPOOLFILE->put: %s", name);
goto err; goto err;
}
} }
if (ret == DB_PAGE_NOTFOUND) if (ret == DB_PAGE_NOTFOUND)
ret = 0; 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; ret = t_ret;
return (ret == 0 ? 0 : 1); return (ret);
} }

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -33,6 +33,7 @@
#include "dbinc/btree.h" #include "dbinc/btree.h"
#include "dbinc/hash.h" #include "dbinc/hash.h"
#include "dbinc/qam.h" #include "dbinc/qam.h"
#include "dbinc/lock.h"
#include "dbinc/log.h" #include "dbinc/log.h"
#include "dbinc/mp.h" #include "dbinc/mp.h"
@ -57,7 +58,8 @@ __db_stat_pp(dbp, txn, spp, flags)
u_int32_t flags; u_int32_t flags;
{ {
DB_ENV *dbenv; DB_ENV *dbenv;
int handle_check, ret; DB_THREAD_INFO *ip;
int handle_check, ret, t_ret;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
@ -67,17 +69,22 @@ __db_stat_pp(dbp, txn, spp, flags)
if ((ret = __db_stat_arg(dbp, flags)) != 0) if ((ret = __db_stat_arg(dbp, flags)) != 0)
return (ret); return (ret);
ENV_ENTER(dbenv, ip);
/* Check for replication block. */ /* Check for replication block. */
handle_check = IS_REPLICATED(dbenv, dbp); handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0) if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0) {
return (ret); handle_check = 0;
goto err;
}
ret = __db_stat(dbp, txn, spp, flags); ret = __db_stat(dbp, txn, spp, flags);
/* Release replication block. */ /* Release replication block. */
if (handle_check) if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
__env_db_rep_exit(dbenv); ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret); return (ret);
} }
@ -102,11 +109,11 @@ __db_stat(dbp, txn, spp, flags)
/* Acquire a cursor. */ /* Acquire a cursor. */
if ((ret = __db_cursor(dbp, txn, 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); return (ret);
DEBUG_LWRITE(dbc, NULL, "DB->stat", NULL, NULL, flags); 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) { switch (dbp->type) {
case DB_BTREE: case DB_BTREE:
@ -145,7 +152,7 @@ __db_stat_arg(dbp, flags)
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
/* Check for invalid function flags. */ /* Check for invalid function flags. */
LF_CLR(DB_DEGREE_2 | DB_DIRTY_READ); LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED);
switch (flags) { switch (flags) {
case 0: case 0:
case DB_FAST_STAT: case DB_FAST_STAT:
@ -176,7 +183,8 @@ __db_stat_print_pp(dbp, flags)
u_int32_t flags; u_int32_t flags;
{ {
DB_ENV *dbenv; DB_ENV *dbenv;
int handle_check, ret; DB_THREAD_INFO *ip;
int handle_check, ret, t_ret;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
@ -187,21 +195,26 @@ __db_stat_print_pp(dbp, flags)
* !!! * !!!
* The actual argument checking is simple, do it inline. * The actual argument checking is simple, do it inline.
*/ */
if ((ret = __db_fchk(dbenv, "DB->stat_print", if ((ret = __db_fchk(dbenv,
flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0) "DB->stat_print", flags, DB_FAST_STAT | DB_STAT_ALL)) != 0)
return (ret); return (ret);
ENV_ENTER(dbenv, ip);
/* Check for replication block. */ /* Check for replication block. */
handle_check = IS_REPLICATED(dbenv, dbp); handle_check = IS_ENV_REPLICATED(dbenv);
if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0) if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0) {
return (ret); handle_check = 0;
goto err;
}
ret = __db_stat_print(dbp, flags); ret = __db_stat_print(dbp, flags);
/* Release replication block. */ /* Release replication block. */
if (handle_check) if (handle_check && (t_ret = __env_db_rep_exit(dbenv)) != 0 && ret == 0)
__env_db_rep_exit(dbenv); ret = t_ret;
err: ENV_LEAVE(dbenv, ip);
return (ret); return (ret);
} }
@ -217,16 +230,17 @@ __db_stat_print(dbp, flags)
u_int32_t flags; u_int32_t flags;
{ {
int ret; int ret;
time_t now;
if (flags == 0 || LF_ISSET(DB_STAT_ALL)) { (void)time(&now);
ret = __db_print_stats(dbp, flags); __db_msg(dbp->dbenv, "%.24s\tLocal time", ctime(&now));
if (flags == 0 || ret != 0)
return (ret);
}
if (LF_ISSET(DB_STAT_ALL) && (ret = __db_print_all(dbp, flags)) != 0) if (LF_ISSET(DB_STAT_ALL) && (ret = __db_print_all(dbp, flags)) != 0)
return (ret); return (ret);
if ((ret = __db_print_stats(dbp, flags)) != 0)
return (ret);
return (0); return (0);
} }
@ -284,38 +298,37 @@ __db_print_all(dbp, flags)
u_int32_t flags; u_int32_t flags;
{ {
static const FN fn[] = { static const FN fn[] = {
{ DB_AM_CHKSUM, "DB_AM_CHKSUM" }, { DB_AM_CHKSUM, "DB_AM_CHKSUM" },
{ DB_AM_CL_WRITER, "DB_AM_CL_WRITER" }, { DB_AM_CL_WRITER, "DB_AM_CL_WRITER" },
{ DB_AM_COMPENSATE, "DB_AM_COMPENSATE" }, { DB_AM_COMPENSATE, "DB_AM_COMPENSATE" },
{ DB_AM_CREATED, "DB_AM_CREATED" }, { DB_AM_CREATED, "DB_AM_CREATED" },
{ DB_AM_CREATED_MSTR, "DB_AM_CREATED_MSTR" }, { DB_AM_CREATED_MSTR, "DB_AM_CREATED_MSTR" },
{ DB_AM_DBM_ERROR, "DB_AM_DBM_ERROR" }, { DB_AM_DBM_ERROR, "DB_AM_DBM_ERROR" },
{ DB_AM_DELIMITER, "DB_AM_DELIMITER" }, { DB_AM_DELIMITER, "DB_AM_DELIMITER" },
{ DB_AM_DIRTY, "DB_AM_DIRTY" }, { DB_AM_DISCARD, "DB_AM_DISCARD" },
{ DB_AM_DISCARD, "DB_AM_DISCARD" }, { DB_AM_DUP, "DB_AM_DUP" },
{ DB_AM_DUP, "DB_AM_DUP" }, { DB_AM_DUPSORT, "DB_AM_DUPSORT" },
{ DB_AM_DUPSORT, "DB_AM_DUPSORT" }, { DB_AM_ENCRYPT, "DB_AM_ENCRYPT" },
{ DB_AM_ENCRYPT, "DB_AM_ENCRYPT" }, { DB_AM_FIXEDLEN, "DB_AM_FIXEDLEN" },
{ DB_AM_FIXEDLEN, "DB_AM_FIXEDLEN" }, { DB_AM_INMEM, "DB_AM_INMEM" },
{ DB_AM_INMEM, "DB_AM_INMEM" }, { DB_AM_IN_RENAME, "DB_AM_IN_RENAME" },
{ DB_AM_IN_RENAME, "DB_AM_IN_RENAME" }, { DB_AM_NOT_DURABLE, "DB_AM_NOT_DURABLE" },
{ DB_AM_NOT_DURABLE, "DB_AM_NOT_DURABLE" }, { DB_AM_OPEN_CALLED, "DB_AM_OPEN_CALLED" },
{ DB_AM_OPEN_CALLED, "DB_AM_OPEN_CALLED" }, { DB_AM_PAD, "DB_AM_PAD" },
{ DB_AM_PAD, "DB_AM_PAD" }, { DB_AM_PGDEF, "DB_AM_PGDEF" },
{ DB_AM_PGDEF, "DB_AM_PGDEF" }, { DB_AM_RDONLY, "DB_AM_RDONLY" },
{ DB_AM_RDONLY, "DB_AM_RDONLY" }, { DB_AM_READ_UNCOMMITTED, "DB_AM_READ_UNCOMMITTED" },
{ DB_AM_RECNUM, "DB_AM_RECNUM" }, { DB_AM_RECNUM, "DB_AM_RECNUM" },
{ DB_AM_RECOVER, "DB_AM_RECOVER" }, { DB_AM_RECOVER, "DB_AM_RECOVER" },
{ DB_AM_RENUMBER, "DB_AM_RENUMBER" }, { DB_AM_RENUMBER, "DB_AM_RENUMBER" },
{ DB_AM_REPLICATION, "DB_AM_REPLICATION" }, { DB_AM_REVSPLITOFF, "DB_AM_REVSPLITOFF" },
{ DB_AM_REVSPLITOFF, "DB_AM_REVSPLITOFF" }, { DB_AM_SECONDARY, "DB_AM_SECONDARY" },
{ DB_AM_SECONDARY, "DB_AM_SECONDARY" }, { DB_AM_SNAPSHOT, "DB_AM_SNAPSHOT" },
{ DB_AM_SNAPSHOT, "DB_AM_SNAPSHOT" }, { DB_AM_SUBDB, "DB_AM_SUBDB" },
{ DB_AM_SUBDB, "DB_AM_SUBDB" }, { DB_AM_SWAP, "DB_AM_SWAP" },
{ DB_AM_SWAP, "DB_AM_SWAP" }, { DB_AM_TXN, "DB_AM_TXN" },
{ DB_AM_TXN, "DB_AM_TXN" }, { DB_AM_VERIFYING, "DB_AM_VERIFYING" },
{ DB_AM_VERIFYING, "DB_AM_VERIFYING" }, { 0, NULL }
{ 0, NULL }
}; };
DB_ENV *dbenv; DB_ENV *dbenv;
@ -331,7 +344,7 @@ __db_print_all(dbp, flags)
STAT_ISSET("DbEnv", dbp->dbenv); STAT_ISSET("DbEnv", dbp->dbenv);
STAT_STRING("Type", __db_dbtype_to_string(dbp->type)); 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("File", dbp->fname);
STAT_STRING("Database", dbp->dname); STAT_STRING("Database", dbp->dname);
@ -389,7 +402,7 @@ __db_print_cursor(dbp)
__db_msg(dbenv, "DB handle cursors:"); __db_msg(dbenv, "DB handle cursors:");
ret = 0; ret = 0;
MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp); MUTEX_LOCK(dbp->dbenv, dbp->mutex);
__db_msg(dbenv, "Active queue:"); __db_msg(dbenv, "Active queue:");
for (dbc = TAILQ_FIRST(&dbp->active_queue); for (dbc = TAILQ_FIRST(&dbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
@ -405,7 +418,7 @@ __db_print_cursor(dbp)
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0) if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp); MUTEX_UNLOCK(dbp->dbenv, dbp->mutex);
return (ret); return (ret);
} }
@ -417,17 +430,17 @@ int __db_print_citem(dbc)
static const FN fn[] = { static const FN fn[] = {
{ DBC_ACTIVE, "DBC_ACTIVE" }, { DBC_ACTIVE, "DBC_ACTIVE" },
{ DBC_COMPENSATE, "DBC_COMPENSATE" }, { DBC_COMPENSATE, "DBC_COMPENSATE" },
{ DBC_DEGREE_2, "DBC_DEGREE_2" }, { DBC_MULTIPLE, "DBC_MULTIPLE" },
{ DBC_DIRTY_READ, "DBC_DIRTY_READ" }, { DBC_MULTIPLE_KEY, "DBC_MULTIPLE_KEY" },
{ DBC_OPD, "DBC_OPD" }, { 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_RECOVER, "DBC_RECOVER" },
{ DBC_RMW, "DBC_RMW" }, { DBC_RMW, "DBC_RMW" },
{ DBC_TRANSIENT, "DBC_TRANSIENT" }, { DBC_TRANSIENT, "DBC_TRANSIENT" },
{ DBC_WRITECURSOR, "DBC_WRITECURSOR" }, { DBC_WRITECURSOR, "DBC_WRITECURSOR" },
{ DBC_WRITER, "DBC_WRITER" }, { DBC_WRITER, "DBC_WRITER" },
{ DBC_MULTIPLE, "DBC_MULTIPLE" },
{ DBC_MULTIPLE_KEY, "DBC_MULTIPLE_KEY" },
{ DBC_OWN_LID, "DBC_OWN_LID" },
{ 0, NULL } { 0, NULL }
}; };
DB *dbp; DB *dbp;
@ -438,16 +451,17 @@ int __db_print_citem(dbc)
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
cp = dbc->internal; cp = dbc->internal;
STAT_HEX("DBC", dbc); STAT_POINTER("DBC", dbc);
STAT_HEX("Associated dbp", dbc->dbp); STAT_POINTER("Associated dbp", dbc->dbp);
STAT_HEX("Associated txn", dbc->txn); STAT_POINTER("Associated txn", dbc->txn);
STAT_HEX("Internal", cp); STAT_POINTER("Internal", cp);
STAT_HEX("Default locker ID", dbc->lid); STAT_HEX("Default locker ID",
dbc->lref == NULL ? 0 : ((DB_LOCKER *)dbc->lref)->id);
STAT_HEX("Locker", dbc->locker); STAT_HEX("Locker", dbc->locker);
STAT_STRING("Type", __db_dbtype_to_string(dbc->dbtype)); STAT_STRING("Type", __db_dbtype_to_string(dbc->dbtype));
STAT_HEX("Off-page duplicate cursor", cp->opd); STAT_POINTER("Off-page duplicate cursor", cp->opd);
STAT_HEX("Referenced page", cp->page); STAT_POINTER("Referenced page", cp->page);
STAT_ULONG("Root", cp->root); STAT_ULONG("Root", cp->root);
STAT_ULONG("Page number", cp->pgno); STAT_ULONG("Page number", cp->pgno);
STAT_ULONG("Page index", cp->indx); STAT_ULONG("Page index", cp->indx);

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 2001-2004 * Copyright (c) 2001-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"
@ -17,10 +17,12 @@
#include "db_int.h" #include "db_int.h"
#include "dbinc/db_page.h" #include "dbinc/db_page.h"
#include "dbinc/log.h" #include "dbinc/db_shash.h"
#include "dbinc/btree.h" #include "dbinc/btree.h"
#include "dbinc/hash.h" #include "dbinc/hash.h"
#include "dbinc/qam.h" #include "dbinc/qam.h"
#include "dbinc/lock.h"
#include "dbinc/log.h"
#include "dbinc/txn.h" #include "dbinc/txn.h"
static int __db_cursor_check __P((DB *)); static int __db_cursor_check __P((DB *));
@ -38,22 +40,27 @@ __db_truncate_pp(dbp, txn, countp, flags)
u_int32_t *countp, flags; u_int32_t *countp, flags;
{ {
DB_ENV *dbenv; DB_ENV *dbenv;
int handle_check, ret, txn_local; DB_THREAD_INFO *ip;
int handle_check, ret, t_ret, txn_local;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
txn_local = 0;
handle_check = 0;
PANIC_CHECK(dbenv); PANIC_CHECK(dbenv);
STRIP_AUTO_COMMIT(flags);
/* Check for invalid flags. */ /* Check for invalid flags. */
if (F_ISSET(dbp, DB_AM_SECONDARY)) { if (F_ISSET(dbp, DB_AM_SECONDARY)) {
__db_err(dbenv, __db_err(dbenv,
"DBP->truncate forbidden on secondary indices"); "DB->truncate forbidden on secondary indices");
return (EINVAL); return (EINVAL);
} }
if ((ret = if ((ret = __db_fchk(dbenv, "DB->truncate", flags, 0)) != 0)
__db_fchk(dbenv, "DB->truncate", flags, DB_AUTO_COMMIT)) != 0)
return (ret); return (ret);
ENV_ENTER(dbenv, ip);
/* /*
* Make sure there are no active cursors on this db. Since we drop * Make sure there are no active cursors on this db. Since we drop
* pages we cannot really adjust cursors. * pages we cannot really adjust cursors.
@ -61,34 +68,57 @@ __db_truncate_pp(dbp, txn, countp, flags)
if (__db_cursor_check(dbp) != 0) { if (__db_cursor_check(dbp) != 0) {
__db_err(dbenv, __db_err(dbenv,
"DB->truncate not permitted with active cursors"); "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 * Create local transaction as necessary, check for consistent
* transaction usage. * transaction usage.
*/ */
txn_local = 0; if (IS_DB_AUTO_COMMIT(dbp, txn)) {
if (IS_AUTO_COMMIT(dbenv, txn, flags)) { if ((ret = __txn_begin(dbenv, NULL, &txn, 0)) != 0)
if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)
goto err; goto err;
txn_local = 1; 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); /* Check for consistent transaction usage. */
if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0) if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)
goto err; goto err;
ret = __db_truncate(dbp, txn, countp); ret = __db_truncate(dbp, txn, countp);
if (handle_check) err: if (txn_local &&
__env_db_rep_exit(dbenv); (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. * processing to truncate so it will update the secondaries normally.
*/ */
if (dbp->type != DB_QUEUE && LIST_FIRST(&dbp->s_secondaries) != NULL) { if (dbp->type != DB_QUEUE && LIST_FIRST(&dbp->s_secondaries) != NULL) {
for (sdbp = __db_s_first(dbp); if ((ret = __db_s_first(dbp, &sdbp)) != 0)
sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) return (ret);
for (; sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp))
if ((ret = __db_truncate(sdbp, txn, &scount)) != 0) if ((ret = __db_truncate(sdbp, txn, &scount)) != 0)
break; break;
if (sdbp != NULL) if (sdbp != NULL)
@ -180,11 +211,11 @@ __db_cursor_check(dbp)
dbenv = dbp->dbenv; 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); for (found = 0, ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (IS_INITIALIZED(dbc)) { if (IS_INITIALIZED(dbc)) {
@ -192,11 +223,11 @@ __db_cursor_check(dbp)
break; break;
} }
} }
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
if (found == 1) if (found == 1)
break; break;
} }
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (found); return (found);
} }

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * 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" #include "db_config.h"

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