diff options
author | unknown <ram@mysql.r18.ru> | 2002-10-30 15:57:05 +0400 |
---|---|---|
committer | unknown <ram@mysql.r18.ru> | 2002-10-30 15:57:05 +0400 |
commit | 155e78f014de1a2e259ae5119f4621fbb210a784 (patch) | |
tree | 6881a3cca88bea0bb9eeffd5aae34be437152786 /bdb/fileops | |
parent | b8798d25ab71436bf690ee8ae48285a655c5487e (diff) | |
download | mariadb-git-155e78f014de1a2e259ae5119f4621fbb210a784.tar.gz |
BDB 4.1.24
BitKeeper/deleted/.del-ex_access.wpj~3df6ae8c99bf7c5f:
Delete: bdb/build_vxworks/ex_access/ex_access.wpj
BitKeeper/deleted/.del-ex_btrec.wpj~a7622f1c6f432dc6:
Delete: bdb/build_vxworks/ex_btrec/ex_btrec.wpj
BitKeeper/deleted/.del-ex_dbclient.wpj~7345440f3b204cdd:
Delete: bdb/build_vxworks/ex_dbclient/ex_dbclient.wpj
BitKeeper/deleted/.del-ex_env.wpj~fbe1ab10b04e8b74:
Delete: bdb/build_vxworks/ex_env/ex_env.wpj
BitKeeper/deleted/.del-ex_mpool.wpj~4479cfd5c45f327d:
Delete: bdb/build_vxworks/ex_mpool/ex_mpool.wpj
BitKeeper/deleted/.del-ex_tpcb.wpj~f78093006e14bf41:
Delete: bdb/build_vxworks/ex_tpcb/ex_tpcb.wpj
BitKeeper/deleted/.del-db_buildall.dsp~bd749ff6da11682:
Delete: bdb/build_win32/db_buildall.dsp
BitKeeper/deleted/.del-cxx_app.cpp~ad8df8e0791011ed:
Delete: bdb/cxx/cxx_app.cpp
BitKeeper/deleted/.del-cxx_log.cpp~a50ff3118fe06952:
Delete: bdb/cxx/cxx_log.cpp
BitKeeper/deleted/.del-cxx_table.cpp~ecd751e79b055556:
Delete: bdb/cxx/cxx_table.cpp
BitKeeper/deleted/.del-namemap.txt~796a3acd3885d8fd:
Delete: bdb/cxx/namemap.txt
BitKeeper/deleted/.del-Design.fileop~3ca4da68f1727373:
Delete: bdb/db/Design.fileop
BitKeeper/deleted/.del-db185_int.h~61bee3736e7959ef:
Delete: bdb/db185/db185_int.h
BitKeeper/deleted/.del-acconfig.h~411e8854d67ad8b5:
Delete: bdb/dist/acconfig.h
BitKeeper/deleted/.del-mutex.m4~a13383cde18a64e1:
Delete: bdb/dist/aclocal/mutex.m4
BitKeeper/deleted/.del-options.m4~b9d0ca637213750a:
Delete: bdb/dist/aclocal/options.m4
BitKeeper/deleted/.del-programs.m4~3ce7890b47732b30:
Delete: bdb/dist/aclocal/programs.m4
BitKeeper/deleted/.del-tcl.m4~f944e2db93c3b6db:
Delete: bdb/dist/aclocal/tcl.m4
BitKeeper/deleted/.del-types.m4~59cae158c9a32cff:
Delete: bdb/dist/aclocal/types.m4
BitKeeper/deleted/.del-script~d38f6d3a4f159cb4:
Delete: bdb/dist/build/script
BitKeeper/deleted/.del-configure.in~ac795a92c8fe049c:
Delete: bdb/dist/configure.in
BitKeeper/deleted/.del-ltconfig~66bbd007d8024af:
Delete: bdb/dist/ltconfig
BitKeeper/deleted/.del-rec_ctemp~a28554362534f00a:
Delete: bdb/dist/rec_ctemp
BitKeeper/deleted/.del-s_tcl~2ffe4326459fcd9f:
Delete: bdb/dist/s_tcl
BitKeeper/deleted/.del-.IGNORE_ME~d8148b08fa7d5d15:
Delete: bdb/dist/template/.IGNORE_ME
BitKeeper/deleted/.del-btree.h~179f2aefec1753d:
Delete: bdb/include/btree.h
BitKeeper/deleted/.del-cxx_int.h~6b649c04766508f8:
Delete: bdb/include/cxx_int.h
BitKeeper/deleted/.del-db.src~6b433ae615b16a8d:
Delete: bdb/include/db.src
BitKeeper/deleted/.del-db_185.h~ad8b373d9391d35c:
Delete: bdb/include/db_185.h
BitKeeper/deleted/.del-db_am.h~a714912b6b75932f:
Delete: bdb/include/db_am.h
BitKeeper/deleted/.del-db_cxx.h~fcafadf45f5d19e9:
Delete: bdb/include/db_cxx.h
BitKeeper/deleted/.del-db_dispatch.h~6844f20f7eb46904:
Delete: bdb/include/db_dispatch.h
BitKeeper/deleted/.del-db_int.src~419a3f48b6a01da7:
Delete: bdb/include/db_int.src
BitKeeper/deleted/.del-db_join.h~76f9747a42c3399a:
Delete: bdb/include/db_join.h
BitKeeper/deleted/.del-db_page.h~e302ca3a4db3abdc:
Delete: bdb/include/db_page.h
BitKeeper/deleted/.del-db_server_int.h~e1d20b6ba3bca1ab:
Delete: bdb/include/db_server_int.h
BitKeeper/deleted/.del-db_shash.h~5fbf2d696fac90f3:
Delete: bdb/include/db_shash.h
BitKeeper/deleted/.del-db_swap.h~1e60887550864a59:
Delete: bdb/include/db_swap.h
BitKeeper/deleted/.del-db_upgrade.h~c644eee73701fc8d:
Delete: bdb/include/db_upgrade.h
BitKeeper/deleted/.del-db_verify.h~b8d6c297c61f342e:
Delete: bdb/include/db_verify.h
BitKeeper/deleted/.del-debug.h~dc2b4f2cf27ccebc:
Delete: bdb/include/debug.h
BitKeeper/deleted/.del-hash.h~2aaa548b28882dfb:
Delete: bdb/include/hash.h
BitKeeper/deleted/.del-lock.h~a761c1b7de57b77f:
Delete: bdb/include/lock.h
BitKeeper/deleted/.del-log.h~ff20184238e35e4d:
Delete: bdb/include/log.h
BitKeeper/deleted/.del-mp.h~7e317597622f3411:
Delete: bdb/include/mp.h
BitKeeper/deleted/.del-mutex.h~d3ae7a2977a68137:
Delete: bdb/include/mutex.h
BitKeeper/deleted/.del-os.h~91867cc8757cd0e3:
Delete: bdb/include/os.h
BitKeeper/deleted/.del-os_jump.h~e1b939fa5151d4be:
Delete: bdb/include/os_jump.h
BitKeeper/deleted/.del-qam.h~6fad0c1b5723d597:
Delete: bdb/include/qam.h
BitKeeper/deleted/.del-queue.h~4c72c0826c123d5:
Delete: bdb/include/queue.h
BitKeeper/deleted/.del-region.h~513fe04d977ca0fc:
Delete: bdb/include/region.h
BitKeeper/deleted/.del-shqueue.h~525fc3e6c2025c36:
Delete: bdb/include/shqueue.h
BitKeeper/deleted/.del-tcl_db.h~c536fd61a844f23f:
Delete: bdb/include/tcl_db.h
BitKeeper/deleted/.del-txn.h~c8d94b221ec147e4:
Delete: bdb/include/txn.h
BitKeeper/deleted/.del-xa.h~ecc466493aae9d9a:
Delete: bdb/include/xa.h
BitKeeper/deleted/.del-DbRecoveryInit.java~756b52601a0b9023:
Delete: bdb/java/src/com/sleepycat/db/DbRecoveryInit.java
BitKeeper/deleted/.del-DbTxnRecover.java~74607cba7ab89d6d:
Delete: bdb/java/src/com/sleepycat/db/DbTxnRecover.java
BitKeeper/deleted/.del-lock_conflict.c~fc5e0f14cf597a2b:
Delete: bdb/lock/lock_conflict.c
BitKeeper/deleted/.del-log.src~53ac9e7b5cb023f2:
Delete: bdb/log/log.src
BitKeeper/deleted/.del-log_findckp.c~24287f008916e81f:
Delete: bdb/log/log_findckp.c
BitKeeper/deleted/.del-log_rec.c~d51711f2cac09297:
Delete: bdb/log/log_rec.c
BitKeeper/deleted/.del-log_register.c~b40bb4efac75ca15:
Delete: bdb/log/log_register.c
BitKeeper/deleted/.del-Design~b3d0f179f2767b:
Delete: bdb/mp/Design
BitKeeper/deleted/.del-os_finit.c~95dbefc6fe79b26c:
Delete: bdb/os/os_finit.c
BitKeeper/deleted/.del-os_abs.c~df95d1e7db81924:
Delete: bdb/os_vxworks/os_abs.c
BitKeeper/deleted/.del-os_finit.c~803b484bdb9d0122:
Delete: bdb/os_vxworks/os_finit.c
BitKeeper/deleted/.del-os_map.c~3a6d7926398b76d3:
Delete: bdb/os_vxworks/os_map.c
BitKeeper/deleted/.del-os_finit.c~19a227c6d3c78ad:
Delete: bdb/os_win32/os_finit.c
BitKeeper/deleted/.del-log-corruption.patch~1cf2ecc7c6408d5d:
Delete: bdb/patches/log-corruption.patch
BitKeeper/deleted/.del-Btree.pm~af6d0c5eaed4a98e:
Delete: bdb/perl.BerkeleyDB/BerkeleyDB/Btree.pm
BitKeeper/deleted/.del-BerkeleyDB.pm~7244036d4482643:
Delete: bdb/perl.BerkeleyDB/BerkeleyDB.pm
BitKeeper/deleted/.del-BerkeleyDB.pod~e7b18fd6132448e3:
Delete: bdb/perl.BerkeleyDB/BerkeleyDB.pod
BitKeeper/deleted/.del-Hash.pm~10292a26c06a5c95:
Delete: bdb/perl.BerkeleyDB/BerkeleyDB/Hash.pm
BitKeeper/deleted/.del-BerkeleyDB.pod.P~79f76a1495eda203:
Delete: bdb/perl.BerkeleyDB/BerkeleyDB.pod.P
BitKeeper/deleted/.del-BerkeleyDB.xs~80c99afbd98e392c:
Delete: bdb/perl.BerkeleyDB/BerkeleyDB.xs
BitKeeper/deleted/.del-Changes~729c1891efa60de9:
Delete: bdb/perl.BerkeleyDB/Changes
BitKeeper/deleted/.del-MANIFEST~63a1e34aecf157a0:
Delete: bdb/perl.BerkeleyDB/MANIFEST
BitKeeper/deleted/.del-Makefile.PL~c68797707d8df87a:
Delete: bdb/perl.BerkeleyDB/Makefile.PL
BitKeeper/deleted/.del-README~5f2f579b1a241407:
Delete: bdb/perl.BerkeleyDB/README
BitKeeper/deleted/.del-Todo~dca3c66c193adda9:
Delete: bdb/perl.BerkeleyDB/Todo
BitKeeper/deleted/.del-config.in~ae81681e450e0999:
Delete: bdb/perl.BerkeleyDB/config.in
BitKeeper/deleted/.del-dbinfo~28ad67d83be4f68e:
Delete: bdb/perl.BerkeleyDB/dbinfo
BitKeeper/deleted/.del-mkconsts~543ab60669c7a04e:
Delete: bdb/perl.BerkeleyDB/mkconsts
BitKeeper/deleted/.del-mkpod~182c0ca54e439afb:
Delete: bdb/perl.BerkeleyDB/mkpod
BitKeeper/deleted/.del-5.004~e008cb5a48805543:
Delete: bdb/perl.BerkeleyDB/patches/5.004
BitKeeper/deleted/.del-irix_6_5.pl~61662bb08afcdec8:
Delete: bdb/perl.BerkeleyDB/hints/irix_6_5.pl
BitKeeper/deleted/.del-solaris.pl~6771e7182394e152:
Delete: bdb/perl.BerkeleyDB/hints/solaris.pl
BitKeeper/deleted/.del-typemap~783b8f5295b05f3d:
Delete: bdb/perl.BerkeleyDB/typemap
BitKeeper/deleted/.del-5.004_01~6081ce2fff7b0bc:
Delete: bdb/perl.BerkeleyDB/patches/5.004_01
BitKeeper/deleted/.del-5.004_02~87214eac35ad9e6:
Delete: bdb/perl.BerkeleyDB/patches/5.004_02
BitKeeper/deleted/.del-5.004_03~9a672becec7cb40f:
Delete: bdb/perl.BerkeleyDB/patches/5.004_03
BitKeeper/deleted/.del-5.004_04~e326cb51af09d154:
Delete: bdb/perl.BerkeleyDB/patches/5.004_04
BitKeeper/deleted/.del-5.004_05~7ab457a1e41a92fe:
Delete: bdb/perl.BerkeleyDB/patches/5.004_05
BitKeeper/deleted/.del-5.005~f9e2d59b5964cd4b:
Delete: bdb/perl.BerkeleyDB/patches/5.005
BitKeeper/deleted/.del-5.005_01~3eb9fb7b5842ea8e:
Delete: bdb/perl.BerkeleyDB/patches/5.005_01
BitKeeper/deleted/.del-5.005_02~67477ce0bef717cb:
Delete: bdb/perl.BerkeleyDB/patches/5.005_02
BitKeeper/deleted/.del-5.005_03~c4c29a1fb21e290a:
Delete: bdb/perl.BerkeleyDB/patches/5.005_03
BitKeeper/deleted/.del-5.6.0~e1fb9897d124ee22:
Delete: bdb/perl.BerkeleyDB/patches/5.6.0
BitKeeper/deleted/.del-btree.t~e4a1a3c675ddc406:
Delete: bdb/perl.BerkeleyDB/t/btree.t
BitKeeper/deleted/.del-db-3.0.t~d2c60991d84558f2:
Delete: bdb/perl.BerkeleyDB/t/db-3.0.t
BitKeeper/deleted/.del-db-3.1.t~6ee88cd13f55e018:
Delete: bdb/perl.BerkeleyDB/t/db-3.1.t
BitKeeper/deleted/.del-db-3.2.t~f73b6461f98fd1cf:
Delete: bdb/perl.BerkeleyDB/t/db-3.2.t
BitKeeper/deleted/.del-destroy.t~cc6a2ae1980a2ecd:
Delete: bdb/perl.BerkeleyDB/t/destroy.t
BitKeeper/deleted/.del-env.t~a8604a4499c4bd07:
Delete: bdb/perl.BerkeleyDB/t/env.t
BitKeeper/deleted/.del-examples.t~2571b77c3cc75574:
Delete: bdb/perl.BerkeleyDB/t/examples.t
BitKeeper/deleted/.del-examples.t.T~8228bdd75ac78b88:
Delete: bdb/perl.BerkeleyDB/t/examples.t.T
BitKeeper/deleted/.del-examples3.t.T~66a186897a87026d:
Delete: bdb/perl.BerkeleyDB/t/examples3.t.T
BitKeeper/deleted/.del-examples3.t~fe3822ba2f2d7f83:
Delete: bdb/perl.BerkeleyDB/t/examples3.t
BitKeeper/deleted/.del-filter.t~f87b045c1b708637:
Delete: bdb/perl.BerkeleyDB/t/filter.t
BitKeeper/deleted/.del-hash.t~616bfb4d644de3a3:
Delete: bdb/perl.BerkeleyDB/t/hash.t
BitKeeper/deleted/.del-join.t~29fc39f74a83ca22:
Delete: bdb/perl.BerkeleyDB/t/join.t
BitKeeper/deleted/.del-mldbm.t~31f5015341eea040:
Delete: bdb/perl.BerkeleyDB/t/mldbm.t
BitKeeper/deleted/.del-queue.t~8f338034ce44a641:
Delete: bdb/perl.BerkeleyDB/t/queue.t
BitKeeper/deleted/.del-recno.t~d4ddbd3743add63e:
Delete: bdb/perl.BerkeleyDB/t/recno.t
BitKeeper/deleted/.del-strict.t~6885cdd2ea71ca2d:
Delete: bdb/perl.BerkeleyDB/t/strict.t
BitKeeper/deleted/.del-subdb.t~aab62a5d5864c603:
Delete: bdb/perl.BerkeleyDB/t/subdb.t
BitKeeper/deleted/.del-txn.t~65033b8558ae1216:
Delete: bdb/perl.BerkeleyDB/t/txn.t
BitKeeper/deleted/.del-unknown.t~f3710458682665e1:
Delete: bdb/perl.BerkeleyDB/t/unknown.t
BitKeeper/deleted/.del-Changes~436f74a5c414c65b:
Delete: bdb/perl.DB_File/Changes
BitKeeper/deleted/.del-DB_File.pm~ae0951c6c7665a82:
Delete: bdb/perl.DB_File/DB_File.pm
BitKeeper/deleted/.del-DB_File.xs~89e49a0b5556f1d8:
Delete: bdb/perl.DB_File/DB_File.xs
BitKeeper/deleted/.del-DB_File_BS~290fad5dbbb87069:
Delete: bdb/perl.DB_File/DB_File_BS
BitKeeper/deleted/.del-MANIFEST~90ee581572bdd4ac:
Delete: bdb/perl.DB_File/MANIFEST
BitKeeper/deleted/.del-Makefile.PL~ac0567bb5a377e38:
Delete: bdb/perl.DB_File/Makefile.PL
BitKeeper/deleted/.del-README~77e924a5a9bae6b3:
Delete: bdb/perl.DB_File/README
BitKeeper/deleted/.del-config.in~ab4c2792b86a810b:
Delete: bdb/perl.DB_File/config.in
BitKeeper/deleted/.del-dbinfo~461c43b30fab2cb:
Delete: bdb/perl.DB_File/dbinfo
BitKeeper/deleted/.del-dynixptx.pl~50dcddfae25d17e9:
Delete: bdb/perl.DB_File/hints/dynixptx.pl
BitKeeper/deleted/.del-typemap~55cffb3288a9e587:
Delete: bdb/perl.DB_File/typemap
BitKeeper/deleted/.del-version.c~a4df0e646f8b3975:
Delete: bdb/perl.DB_File/version.c
BitKeeper/deleted/.del-5.004_01~d6830d0082702af7:
Delete: bdb/perl.DB_File/patches/5.004_01
BitKeeper/deleted/.del-5.004_02~78b082dc80c91031:
Delete: bdb/perl.DB_File/patches/5.004_02
BitKeeper/deleted/.del-5.004~4411ec2e3c9e008b:
Delete: bdb/perl.DB_File/patches/5.004
BitKeeper/deleted/.del-sco.pl~1e795fe14fe4dcfe:
Delete: bdb/perl.DB_File/hints/sco.pl
BitKeeper/deleted/.del-5.004_03~33f274648b160d95:
Delete: bdb/perl.DB_File/patches/5.004_03
BitKeeper/deleted/.del-5.004_04~8f3d1b3cf18bb20a:
Delete: bdb/perl.DB_File/patches/5.004_04
BitKeeper/deleted/.del-5.004_05~9c0f02e7331e142:
Delete: bdb/perl.DB_File/patches/5.004_05
BitKeeper/deleted/.del-5.005~c2108cb2e3c8d951:
Delete: bdb/perl.DB_File/patches/5.005
BitKeeper/deleted/.del-5.005_01~3b45e9673afc4cfa:
Delete: bdb/perl.DB_File/patches/5.005_01
BitKeeper/deleted/.del-5.005_02~9fe5766bb02a4522:
Delete: bdb/perl.DB_File/patches/5.005_02
BitKeeper/deleted/.del-5.005_03~ffa1c38c19ae72ea:
Delete: bdb/perl.DB_File/patches/5.005_03
BitKeeper/deleted/.del-5.6.0~373be3a5ce47be85:
Delete: bdb/perl.DB_File/patches/5.6.0
BitKeeper/deleted/.del-db-btree.t~3231595a1c241eb3:
Delete: bdb/perl.DB_File/t/db-btree.t
BitKeeper/deleted/.del-db-hash.t~7c4ad0c795c7fad2:
Delete: bdb/perl.DB_File/t/db-hash.t
BitKeeper/deleted/.del-db-recno.t~6c2d3d80b9ba4a50:
Delete: bdb/perl.DB_File/t/db-recno.t
BitKeeper/deleted/.del-db_server.sed~cdb00ebcd48a64e2:
Delete: bdb/rpc_server/db_server.sed
BitKeeper/deleted/.del-db_server_proc.c~d46c8f409c3747f4:
Delete: bdb/rpc_server/db_server_proc.c
BitKeeper/deleted/.del-db_server_svc.sed~3f5e59f334fa4607:
Delete: bdb/rpc_server/db_server_svc.sed
BitKeeper/deleted/.del-db_server_util.c~a809f3a4629acda:
Delete: bdb/rpc_server/db_server_util.c
BitKeeper/deleted/.del-log.tcl~ff1b41f1355b97d7:
Delete: bdb/test/log.tcl
BitKeeper/deleted/.del-mpool.tcl~b0df4dc1b04db26c:
Delete: bdb/test/mpool.tcl
BitKeeper/deleted/.del-mutex.tcl~52fd5c73a150565:
Delete: bdb/test/mutex.tcl
BitKeeper/deleted/.del-txn.tcl~c4ff071550b5446e:
Delete: bdb/test/txn.tcl
BitKeeper/deleted/.del-README~e800a12a5392010a:
Delete: bdb/test/upgrade/README
BitKeeper/deleted/.del-pack-2.6.6.pl~89d5076d758d3e98:
Delete: bdb/test/upgrade/generate-2.X/pack-2.6.6.pl
BitKeeper/deleted/.del-test-2.6.patch~4a52dc83d447547b:
Delete: bdb/test/upgrade/generate-2.X/test-2.6.patch
Diffstat (limited to 'bdb/fileops')
-rw-r--r-- | bdb/fileops/fileops.src | 111 | ||||
-rw-r--r-- | bdb/fileops/fileops_auto.c | 1371 | ||||
-rw-r--r-- | bdb/fileops/fop_basic.c | 275 | ||||
-rw-r--r-- | bdb/fileops/fop_rec.c | 308 | ||||
-rw-r--r-- | bdb/fileops/fop_util.c | 928 |
5 files changed, 2993 insertions, 0 deletions
diff --git a/bdb/fileops/fileops.src b/bdb/fileops/fileops.src new file mode 100644 index 00000000000..1fd39dc3c45 --- /dev/null +++ b/bdb/fileops/fileops.src @@ -0,0 +1,111 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001-2002 + * Sleepycat Software. All rights reserved. + * + * $Id: fileops.src,v 1.8 2002/04/06 18:25:55 bostic Exp $ + */ + +PREFIX __fop +DBPRIVATE + +INCLUDE #include "db_config.h" +INCLUDE +INCLUDE #ifndef NO_SYSTEM_INCLUDES +INCLUDE #include <sys/types.h> +INCLUDE +INCLUDE #include <ctype.h> +INCLUDE #include <string.h> +INCLUDE #endif +INCLUDE +INCLUDE #include "db_int.h" +INCLUDE #include "dbinc/crypto.h" +INCLUDE #include "dbinc/db_page.h" +INCLUDE #include "dbinc/db_dispatch.h" +INCLUDE #include "dbinc/db_am.h" +INCLUDE #include "dbinc/log.h" +INCLUDE #include "dbinc/rep.h" +INCLUDE #include "dbinc/txn.h" +INCLUDE #include "dbinc/fop.h" +INCLUDE + +/* + * create -- create a file system object. + * + * name: name in the file system + * appname: indicates if the name needs to go through __db_appname + * mode: file system mode + */ +BEGIN create 143 +DBT name DBT s +ARG appname u_int32_t lu +ARG mode u_int32_t o +END + +/* + * remove -- remove a file system object. + * + * name: name in the file system + * appname: indicates if the name needs to go through __db_appname + */ +BEGIN remove 144 +DBT name DBT s +DBT fid DBT s +ARG appname u_int32_t lu +END + +/* + * write: log the writing of data into an object. + * + * name: file containing the page. + * appname: indicates if the name needs to go through __db_appname + * offset: offset in the file. + * page: the actual meta-data page. + * flag: non-0 indicates that this is a tempfile, so we needn't undo + * these modifications (we'll toss the file). + */ +BEGIN write 145 +DBT name DBT s +ARG appname u_int32_t lu +ARG offset u_int32_t lu +PGDBT page DBT s +ARG flag u_int32_t lu +END + +/* + * rename: move a file from one name to another. + * The appname value indicates if this is a path name that should be used + * directly (i.e., no interpretation) or if it is a pathname that should + * be interpreted via calls to __db_appname. The fileid is the 20-byte + * DB fileid of the file being renamed. We need to check it on recovery + * so that we don't inadvertently overwrite good files. + */ +BEGIN rename 146 +DBT oldname DBT s +DBT newname DBT s +DBT fileid DBT s +ARG appname u_int32_t lu +END + +/* + * File removal record. This is a DB-level log record that indicates + * we've just completed some form of file removal. The purpose of this + * log record is to logically identify the particular instance of the + * named file so that during recovery, in deciding if we should roll-forward + * a remove or a rename, we can make sure that we don't roll one forward and + * delete or overwrite the wrong file. + * real_fid: The 20-byte unique file identifier of the original file being + * removed. + * tmp_fid: The unique fid of the tmp file that is removed. + * name: The pre- __db_appname name of the file + * child: The transaction that removed or renamed the file. + */ + */ +BEGIN file_remove 141 +DBT real_fid DBT s +DBT tmp_fid DBT s +DBT name DBT s +ARG appname u_int32_t lu +ARG child u_int32_t lx +END diff --git a/bdb/fileops/fileops_auto.c b/bdb/fileops/fileops_auto.c new file mode 100644 index 00000000000..f38640b7480 --- /dev/null +++ b/bdb/fileops/fileops_auto.c @@ -0,0 +1,1371 @@ +/* Do not edit: automatically built by gen_rec.awk. */ +#include "db_config.h" + +#ifndef NO_SYSTEM_INCLUDES +#include <sys/types.h> + +#include <ctype.h> +#include <string.h> +#endif + +#include "db_int.h" +#include "dbinc/crypto.h" +#include "dbinc/db_page.h" +#include "dbinc/db_dispatch.h" +#include "dbinc/db_am.h" +#include "dbinc/log.h" +#include "dbinc/rep.h" +#include "dbinc/txn.h" +#include "dbinc/fop.h" + +/* + * PUBLIC: int __fop_create_log __P((DB_ENV *, DB_TXN *, DB_LSN *, + * PUBLIC: u_int32_t, const DBT *, u_int32_t, u_int32_t)); + */ +int +__fop_create_log(dbenv, txnid, ret_lsnp, flags, + name, appname, mode) + DB_ENV *dbenv; + DB_TXN *txnid; + DB_LSN *ret_lsnp; + u_int32_t flags; + const DBT *name; + u_int32_t appname; + u_int32_t mode; +{ + DBT logrec; + DB_LSN *lsnp, null_lsn; + u_int32_t zero; + u_int32_t uinttmp; + u_int32_t npad, rectype, txn_num; + int ret; + u_int8_t *bp; + + rectype = DB___fop_create; + npad = 0; + + if (txnid == NULL) { + txn_num = 0; + null_lsn.file = 0; + null_lsn.offset = 0; + lsnp = &null_lsn; + } else { + if (TAILQ_FIRST(&txnid->kids) != NULL && + (ret = __txn_activekids(dbenv, rectype, txnid)) != 0) + return (ret); + txn_num = txnid->txnid; + lsnp = &txnid->last_lsn; + } + + logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN) + + sizeof(u_int32_t) + (name == NULL ? 0 : name->size) + + sizeof(u_int32_t) + + sizeof(u_int32_t); + if (CRYPTO_ON(dbenv)) { + npad = + ((DB_CIPHER *)dbenv->crypto_handle)->adj_size(logrec.size); + logrec.size += npad; + } + + if ((ret = __os_malloc(dbenv, + logrec.size, &logrec.data)) != 0) + return (ret); + + if (npad > 0) + memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad); + + bp = logrec.data; + + memcpy(bp, &rectype, sizeof(rectype)); + bp += sizeof(rectype); + + memcpy(bp, &txn_num, sizeof(txn_num)); + bp += sizeof(txn_num); + + memcpy(bp, lsnp, sizeof(DB_LSN)); + bp += sizeof(DB_LSN); + + if (name == NULL) { + zero = 0; + memcpy(bp, &zero, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + } else { + memcpy(bp, &name->size, sizeof(name->size)); + bp += sizeof(name->size); + memcpy(bp, name->data, name->size); + bp += name->size; + } + + uinttmp = (u_int32_t)appname; + memcpy(bp, &uinttmp, sizeof(uinttmp)); + bp += sizeof(uinttmp); + + uinttmp = (u_int32_t)mode; + memcpy(bp, &uinttmp, sizeof(uinttmp)); + bp += sizeof(uinttmp); + + DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); + ret = dbenv->log_put(dbenv, + ret_lsnp, (DBT *)&logrec, flags | DB_NOCOPY); + if (txnid != NULL && ret == 0) + txnid->last_lsn = *ret_lsnp; +#ifdef LOG_DIAGNOSTIC + if (ret != 0) + (void)__fop_create_print(dbenv, + (DBT *)&logrec, ret_lsnp, NULL, NULL); +#endif + __os_free(dbenv, logrec.data); + return (ret); +} + +/* + * PUBLIC: int __fop_create_getpgnos __P((DB_ENV *, DBT *, DB_LSN *, + * PUBLIC: db_recops, void *)); + */ +int +__fop_create_getpgnos(dbenv, rec, lsnp, notused1, summary) + DB_ENV *dbenv; + DBT *rec; + DB_LSN *lsnp; + db_recops notused1; + void *summary; +{ + TXN_RECS *t; + int ret; + COMPQUIET(rec, NULL); + COMPQUIET(notused1, DB_TXN_ABORT); + + t = (TXN_RECS *)summary; + + if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0) + return (ret); + + t->array[t->npages].flags = LSN_PAGE_NOLOCK; + t->array[t->npages].lsn = *lsnp; + t->array[t->npages].fid = DB_LOGFILEID_INVALID; + memset(&t->array[t->npages].pgdesc, 0, + sizeof(t->array[t->npages].pgdesc)); + + t->npages++; + + return (0); +} + +/* + * PUBLIC: int __fop_create_print __P((DB_ENV *, DBT *, DB_LSN *, + * PUBLIC: db_recops, void *)); + */ +int +__fop_create_print(dbenv, dbtp, lsnp, notused2, notused3) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops notused2; + void *notused3; +{ + __fop_create_args *argp; + u_int32_t i; + int ch; + int ret; + + notused2 = DB_TXN_ABORT; + notused3 = NULL; + + if ((ret = __fop_create_read(dbenv, dbtp->data, &argp)) != 0) + return (ret); + (void)printf( + "[%lu][%lu]__fop_create: rec: %lu txnid %lx prevlsn [%lu][%lu]\n", + (u_long)lsnp->file, + (u_long)lsnp->offset, + (u_long)argp->type, + (u_long)argp->txnid->txnid, + (u_long)argp->prev_lsn.file, + (u_long)argp->prev_lsn.offset); + (void)printf("\tname: "); + for (i = 0; i < argp->name.size; i++) { + ch = ((u_int8_t *)argp->name.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\tappname: %lu\n", (u_long)argp->appname); + (void)printf("\tmode: %o\n", argp->mode); + (void)printf("\n"); + __os_free(dbenv, argp); + return (0); +} + +/* + * PUBLIC: int __fop_create_read __P((DB_ENV *, void *, __fop_create_args **)); + */ +int +__fop_create_read(dbenv, recbuf, argpp) + DB_ENV *dbenv; + void *recbuf; + __fop_create_args **argpp; +{ + __fop_create_args *argp; + u_int32_t uinttmp; + u_int8_t *bp; + int ret; + + if ((ret = __os_malloc(dbenv, + sizeof(__fop_create_args) + sizeof(DB_TXN), &argp)) != 0) + return (ret); + + argp->txnid = (DB_TXN *)&argp[1]; + + bp = recbuf; + memcpy(&argp->type, bp, sizeof(argp->type)); + bp += sizeof(argp->type); + + memcpy(&argp->txnid->txnid, bp, sizeof(argp->txnid->txnid)); + bp += sizeof(argp->txnid->txnid); + + memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN)); + bp += sizeof(DB_LSN); + + memset(&argp->name, 0, sizeof(argp->name)); + memcpy(&argp->name.size, bp, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + argp->name.data = bp; + bp += argp->name.size; + + memcpy(&uinttmp, bp, sizeof(uinttmp)); + argp->appname = (u_int32_t)uinttmp; + bp += sizeof(uinttmp); + + memcpy(&uinttmp, bp, sizeof(uinttmp)); + argp->mode = (u_int32_t)uinttmp; + bp += sizeof(uinttmp); + + *argpp = argp; + return (0); +} + +/* + * PUBLIC: int __fop_remove_log __P((DB_ENV *, DB_TXN *, DB_LSN *, + * PUBLIC: u_int32_t, const DBT *, const DBT *, u_int32_t)); + */ +int +__fop_remove_log(dbenv, txnid, ret_lsnp, flags, + name, fid, appname) + DB_ENV *dbenv; + DB_TXN *txnid; + DB_LSN *ret_lsnp; + u_int32_t flags; + const DBT *name; + const DBT *fid; + u_int32_t appname; +{ + DBT logrec; + DB_LSN *lsnp, null_lsn; + u_int32_t zero; + u_int32_t uinttmp; + u_int32_t npad, rectype, txn_num; + int ret; + u_int8_t *bp; + + rectype = DB___fop_remove; + npad = 0; + + if (txnid == NULL) { + txn_num = 0; + null_lsn.file = 0; + null_lsn.offset = 0; + lsnp = &null_lsn; + } else { + if (TAILQ_FIRST(&txnid->kids) != NULL && + (ret = __txn_activekids(dbenv, rectype, txnid)) != 0) + return (ret); + txn_num = txnid->txnid; + lsnp = &txnid->last_lsn; + } + + logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN) + + sizeof(u_int32_t) + (name == NULL ? 0 : name->size) + + sizeof(u_int32_t) + (fid == NULL ? 0 : fid->size) + + sizeof(u_int32_t); + if (CRYPTO_ON(dbenv)) { + npad = + ((DB_CIPHER *)dbenv->crypto_handle)->adj_size(logrec.size); + logrec.size += npad; + } + + if ((ret = __os_malloc(dbenv, + logrec.size, &logrec.data)) != 0) + return (ret); + + if (npad > 0) + memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad); + + bp = logrec.data; + + memcpy(bp, &rectype, sizeof(rectype)); + bp += sizeof(rectype); + + memcpy(bp, &txn_num, sizeof(txn_num)); + bp += sizeof(txn_num); + + memcpy(bp, lsnp, sizeof(DB_LSN)); + bp += sizeof(DB_LSN); + + if (name == NULL) { + zero = 0; + memcpy(bp, &zero, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + } else { + memcpy(bp, &name->size, sizeof(name->size)); + bp += sizeof(name->size); + memcpy(bp, name->data, name->size); + bp += name->size; + } + + if (fid == NULL) { + zero = 0; + memcpy(bp, &zero, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + } else { + memcpy(bp, &fid->size, sizeof(fid->size)); + bp += sizeof(fid->size); + memcpy(bp, fid->data, fid->size); + bp += fid->size; + } + + uinttmp = (u_int32_t)appname; + memcpy(bp, &uinttmp, sizeof(uinttmp)); + bp += sizeof(uinttmp); + + DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); + ret = dbenv->log_put(dbenv, + ret_lsnp, (DBT *)&logrec, flags | DB_NOCOPY); + if (txnid != NULL && ret == 0) + txnid->last_lsn = *ret_lsnp; +#ifdef LOG_DIAGNOSTIC + if (ret != 0) + (void)__fop_remove_print(dbenv, + (DBT *)&logrec, ret_lsnp, NULL, NULL); +#endif + __os_free(dbenv, logrec.data); + return (ret); +} + +/* + * PUBLIC: int __fop_remove_getpgnos __P((DB_ENV *, DBT *, DB_LSN *, + * PUBLIC: db_recops, void *)); + */ +int +__fop_remove_getpgnos(dbenv, rec, lsnp, notused1, summary) + DB_ENV *dbenv; + DBT *rec; + DB_LSN *lsnp; + db_recops notused1; + void *summary; +{ + TXN_RECS *t; + int ret; + COMPQUIET(rec, NULL); + COMPQUIET(notused1, DB_TXN_ABORT); + + t = (TXN_RECS *)summary; + + if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0) + return (ret); + + t->array[t->npages].flags = LSN_PAGE_NOLOCK; + t->array[t->npages].lsn = *lsnp; + t->array[t->npages].fid = DB_LOGFILEID_INVALID; + memset(&t->array[t->npages].pgdesc, 0, + sizeof(t->array[t->npages].pgdesc)); + + t->npages++; + + return (0); +} + +/* + * PUBLIC: int __fop_remove_print __P((DB_ENV *, DBT *, DB_LSN *, + * PUBLIC: db_recops, void *)); + */ +int +__fop_remove_print(dbenv, dbtp, lsnp, notused2, notused3) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops notused2; + void *notused3; +{ + __fop_remove_args *argp; + u_int32_t i; + int ch; + int ret; + + notused2 = DB_TXN_ABORT; + notused3 = NULL; + + if ((ret = __fop_remove_read(dbenv, dbtp->data, &argp)) != 0) + return (ret); + (void)printf( + "[%lu][%lu]__fop_remove: rec: %lu txnid %lx prevlsn [%lu][%lu]\n", + (u_long)lsnp->file, + (u_long)lsnp->offset, + (u_long)argp->type, + (u_long)argp->txnid->txnid, + (u_long)argp->prev_lsn.file, + (u_long)argp->prev_lsn.offset); + (void)printf("\tname: "); + for (i = 0; i < argp->name.size; i++) { + ch = ((u_int8_t *)argp->name.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\tfid: "); + for (i = 0; i < argp->fid.size; i++) { + ch = ((u_int8_t *)argp->fid.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\tappname: %lu\n", (u_long)argp->appname); + (void)printf("\n"); + __os_free(dbenv, argp); + return (0); +} + +/* + * PUBLIC: int __fop_remove_read __P((DB_ENV *, void *, __fop_remove_args **)); + */ +int +__fop_remove_read(dbenv, recbuf, argpp) + DB_ENV *dbenv; + void *recbuf; + __fop_remove_args **argpp; +{ + __fop_remove_args *argp; + u_int32_t uinttmp; + u_int8_t *bp; + int ret; + + if ((ret = __os_malloc(dbenv, + sizeof(__fop_remove_args) + sizeof(DB_TXN), &argp)) != 0) + return (ret); + + argp->txnid = (DB_TXN *)&argp[1]; + + bp = recbuf; + memcpy(&argp->type, bp, sizeof(argp->type)); + bp += sizeof(argp->type); + + memcpy(&argp->txnid->txnid, bp, sizeof(argp->txnid->txnid)); + bp += sizeof(argp->txnid->txnid); + + memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN)); + bp += sizeof(DB_LSN); + + memset(&argp->name, 0, sizeof(argp->name)); + memcpy(&argp->name.size, bp, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + argp->name.data = bp; + bp += argp->name.size; + + memset(&argp->fid, 0, sizeof(argp->fid)); + memcpy(&argp->fid.size, bp, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + argp->fid.data = bp; + bp += argp->fid.size; + + memcpy(&uinttmp, bp, sizeof(uinttmp)); + argp->appname = (u_int32_t)uinttmp; + bp += sizeof(uinttmp); + + *argpp = argp; + return (0); +} + +/* + * PUBLIC: int __fop_write_log __P((DB_ENV *, DB_TXN *, DB_LSN *, + * PUBLIC: u_int32_t, const DBT *, u_int32_t, u_int32_t, const DBT *, + * PUBLIC: u_int32_t)); + */ +int +__fop_write_log(dbenv, txnid, ret_lsnp, flags, + name, appname, offset, page, flag) + DB_ENV *dbenv; + DB_TXN *txnid; + DB_LSN *ret_lsnp; + u_int32_t flags; + const DBT *name; + u_int32_t appname; + u_int32_t offset; + const DBT *page; + u_int32_t flag; +{ + DBT logrec; + DB_LSN *lsnp, null_lsn; + u_int32_t zero; + u_int32_t uinttmp; + u_int32_t npad, rectype, txn_num; + int ret; + u_int8_t *bp; + + rectype = DB___fop_write; + npad = 0; + + if (txnid == NULL) { + txn_num = 0; + null_lsn.file = 0; + null_lsn.offset = 0; + lsnp = &null_lsn; + } else { + if (TAILQ_FIRST(&txnid->kids) != NULL && + (ret = __txn_activekids(dbenv, rectype, txnid)) != 0) + return (ret); + txn_num = txnid->txnid; + lsnp = &txnid->last_lsn; + } + + logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN) + + sizeof(u_int32_t) + (name == NULL ? 0 : name->size) + + sizeof(u_int32_t) + + sizeof(u_int32_t) + + sizeof(u_int32_t) + (page == NULL ? 0 : page->size) + + sizeof(u_int32_t); + if (CRYPTO_ON(dbenv)) { + npad = + ((DB_CIPHER *)dbenv->crypto_handle)->adj_size(logrec.size); + logrec.size += npad; + } + + if ((ret = __os_malloc(dbenv, + logrec.size, &logrec.data)) != 0) + return (ret); + + if (npad > 0) + memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad); + + bp = logrec.data; + + memcpy(bp, &rectype, sizeof(rectype)); + bp += sizeof(rectype); + + memcpy(bp, &txn_num, sizeof(txn_num)); + bp += sizeof(txn_num); + + memcpy(bp, lsnp, sizeof(DB_LSN)); + bp += sizeof(DB_LSN); + + if (name == NULL) { + zero = 0; + memcpy(bp, &zero, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + } else { + memcpy(bp, &name->size, sizeof(name->size)); + bp += sizeof(name->size); + memcpy(bp, name->data, name->size); + bp += name->size; + } + + uinttmp = (u_int32_t)appname; + memcpy(bp, &uinttmp, sizeof(uinttmp)); + bp += sizeof(uinttmp); + + uinttmp = (u_int32_t)offset; + memcpy(bp, &uinttmp, sizeof(uinttmp)); + bp += sizeof(uinttmp); + + if (page == NULL) { + zero = 0; + memcpy(bp, &zero, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + } else { + memcpy(bp, &page->size, sizeof(page->size)); + bp += sizeof(page->size); + memcpy(bp, page->data, page->size); + bp += page->size; + } + + uinttmp = (u_int32_t)flag; + memcpy(bp, &uinttmp, sizeof(uinttmp)); + bp += sizeof(uinttmp); + + DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); + ret = dbenv->log_put(dbenv, + ret_lsnp, (DBT *)&logrec, flags | DB_NOCOPY); + if (txnid != NULL && ret == 0) + txnid->last_lsn = *ret_lsnp; +#ifdef LOG_DIAGNOSTIC + if (ret != 0) + (void)__fop_write_print(dbenv, + (DBT *)&logrec, ret_lsnp, NULL, NULL); +#endif + __os_free(dbenv, logrec.data); + return (ret); +} + +/* + * PUBLIC: int __fop_write_getpgnos __P((DB_ENV *, DBT *, DB_LSN *, + * PUBLIC: db_recops, void *)); + */ +int +__fop_write_getpgnos(dbenv, rec, lsnp, notused1, summary) + DB_ENV *dbenv; + DBT *rec; + DB_LSN *lsnp; + db_recops notused1; + void *summary; +{ + TXN_RECS *t; + int ret; + COMPQUIET(rec, NULL); + COMPQUIET(notused1, DB_TXN_ABORT); + + t = (TXN_RECS *)summary; + + if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0) + return (ret); + + t->array[t->npages].flags = LSN_PAGE_NOLOCK; + t->array[t->npages].lsn = *lsnp; + t->array[t->npages].fid = DB_LOGFILEID_INVALID; + memset(&t->array[t->npages].pgdesc, 0, + sizeof(t->array[t->npages].pgdesc)); + + t->npages++; + + return (0); +} + +/* + * PUBLIC: int __fop_write_print __P((DB_ENV *, DBT *, DB_LSN *, + * PUBLIC: db_recops, void *)); + */ +int +__fop_write_print(dbenv, dbtp, lsnp, notused2, notused3) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops notused2; + void *notused3; +{ + __fop_write_args *argp; + u_int32_t i; + int ch; + int ret; + + notused2 = DB_TXN_ABORT; + notused3 = NULL; + + if ((ret = __fop_write_read(dbenv, dbtp->data, &argp)) != 0) + return (ret); + (void)printf( + "[%lu][%lu]__fop_write: rec: %lu txnid %lx prevlsn [%lu][%lu]\n", + (u_long)lsnp->file, + (u_long)lsnp->offset, + (u_long)argp->type, + (u_long)argp->txnid->txnid, + (u_long)argp->prev_lsn.file, + (u_long)argp->prev_lsn.offset); + (void)printf("\tname: "); + for (i = 0; i < argp->name.size; i++) { + ch = ((u_int8_t *)argp->name.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\tappname: %lu\n", (u_long)argp->appname); + (void)printf("\toffset: %lu\n", (u_long)argp->offset); + (void)printf("\tpage: "); + for (i = 0; i < argp->page.size; i++) { + ch = ((u_int8_t *)argp->page.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\tflag: %lu\n", (u_long)argp->flag); + (void)printf("\n"); + __os_free(dbenv, argp); + return (0); +} + +/* + * PUBLIC: int __fop_write_read __P((DB_ENV *, void *, __fop_write_args **)); + */ +int +__fop_write_read(dbenv, recbuf, argpp) + DB_ENV *dbenv; + void *recbuf; + __fop_write_args **argpp; +{ + __fop_write_args *argp; + u_int32_t uinttmp; + u_int8_t *bp; + int ret; + + if ((ret = __os_malloc(dbenv, + sizeof(__fop_write_args) + sizeof(DB_TXN), &argp)) != 0) + return (ret); + + argp->txnid = (DB_TXN *)&argp[1]; + + bp = recbuf; + memcpy(&argp->type, bp, sizeof(argp->type)); + bp += sizeof(argp->type); + + memcpy(&argp->txnid->txnid, bp, sizeof(argp->txnid->txnid)); + bp += sizeof(argp->txnid->txnid); + + memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN)); + bp += sizeof(DB_LSN); + + memset(&argp->name, 0, sizeof(argp->name)); + memcpy(&argp->name.size, bp, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + argp->name.data = bp; + bp += argp->name.size; + + memcpy(&uinttmp, bp, sizeof(uinttmp)); + argp->appname = (u_int32_t)uinttmp; + bp += sizeof(uinttmp); + + memcpy(&uinttmp, bp, sizeof(uinttmp)); + argp->offset = (u_int32_t)uinttmp; + bp += sizeof(uinttmp); + + memset(&argp->page, 0, sizeof(argp->page)); + memcpy(&argp->page.size, bp, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + argp->page.data = bp; + bp += argp->page.size; + + memcpy(&uinttmp, bp, sizeof(uinttmp)); + argp->flag = (u_int32_t)uinttmp; + bp += sizeof(uinttmp); + + *argpp = argp; + return (0); +} + +/* + * PUBLIC: int __fop_rename_log __P((DB_ENV *, DB_TXN *, DB_LSN *, + * PUBLIC: u_int32_t, const DBT *, const DBT *, const DBT *, u_int32_t)); + */ +int +__fop_rename_log(dbenv, txnid, ret_lsnp, flags, + oldname, newname, fileid, appname) + DB_ENV *dbenv; + DB_TXN *txnid; + DB_LSN *ret_lsnp; + u_int32_t flags; + const DBT *oldname; + const DBT *newname; + const DBT *fileid; + u_int32_t appname; +{ + DBT logrec; + DB_LSN *lsnp, null_lsn; + u_int32_t zero; + u_int32_t uinttmp; + u_int32_t npad, rectype, txn_num; + int ret; + u_int8_t *bp; + + rectype = DB___fop_rename; + npad = 0; + + if (txnid == NULL) { + txn_num = 0; + null_lsn.file = 0; + null_lsn.offset = 0; + lsnp = &null_lsn; + } else { + if (TAILQ_FIRST(&txnid->kids) != NULL && + (ret = __txn_activekids(dbenv, rectype, txnid)) != 0) + return (ret); + txn_num = txnid->txnid; + lsnp = &txnid->last_lsn; + } + + logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN) + + sizeof(u_int32_t) + (oldname == NULL ? 0 : oldname->size) + + sizeof(u_int32_t) + (newname == NULL ? 0 : newname->size) + + sizeof(u_int32_t) + (fileid == NULL ? 0 : fileid->size) + + sizeof(u_int32_t); + if (CRYPTO_ON(dbenv)) { + npad = + ((DB_CIPHER *)dbenv->crypto_handle)->adj_size(logrec.size); + logrec.size += npad; + } + + if ((ret = __os_malloc(dbenv, + logrec.size, &logrec.data)) != 0) + return (ret); + + if (npad > 0) + memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad); + + bp = logrec.data; + + memcpy(bp, &rectype, sizeof(rectype)); + bp += sizeof(rectype); + + memcpy(bp, &txn_num, sizeof(txn_num)); + bp += sizeof(txn_num); + + memcpy(bp, lsnp, sizeof(DB_LSN)); + bp += sizeof(DB_LSN); + + if (oldname == NULL) { + zero = 0; + memcpy(bp, &zero, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + } else { + memcpy(bp, &oldname->size, sizeof(oldname->size)); + bp += sizeof(oldname->size); + memcpy(bp, oldname->data, oldname->size); + bp += oldname->size; + } + + if (newname == NULL) { + zero = 0; + memcpy(bp, &zero, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + } else { + memcpy(bp, &newname->size, sizeof(newname->size)); + bp += sizeof(newname->size); + memcpy(bp, newname->data, newname->size); + bp += newname->size; + } + + if (fileid == NULL) { + zero = 0; + memcpy(bp, &zero, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + } else { + memcpy(bp, &fileid->size, sizeof(fileid->size)); + bp += sizeof(fileid->size); + memcpy(bp, fileid->data, fileid->size); + bp += fileid->size; + } + + uinttmp = (u_int32_t)appname; + memcpy(bp, &uinttmp, sizeof(uinttmp)); + bp += sizeof(uinttmp); + + DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); + ret = dbenv->log_put(dbenv, + ret_lsnp, (DBT *)&logrec, flags | DB_NOCOPY); + if (txnid != NULL && ret == 0) + txnid->last_lsn = *ret_lsnp; +#ifdef LOG_DIAGNOSTIC + if (ret != 0) + (void)__fop_rename_print(dbenv, + (DBT *)&logrec, ret_lsnp, NULL, NULL); +#endif + __os_free(dbenv, logrec.data); + return (ret); +} + +/* + * PUBLIC: int __fop_rename_getpgnos __P((DB_ENV *, DBT *, DB_LSN *, + * PUBLIC: db_recops, void *)); + */ +int +__fop_rename_getpgnos(dbenv, rec, lsnp, notused1, summary) + DB_ENV *dbenv; + DBT *rec; + DB_LSN *lsnp; + db_recops notused1; + void *summary; +{ + TXN_RECS *t; + int ret; + COMPQUIET(rec, NULL); + COMPQUIET(notused1, DB_TXN_ABORT); + + t = (TXN_RECS *)summary; + + if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0) + return (ret); + + t->array[t->npages].flags = LSN_PAGE_NOLOCK; + t->array[t->npages].lsn = *lsnp; + t->array[t->npages].fid = DB_LOGFILEID_INVALID; + memset(&t->array[t->npages].pgdesc, 0, + sizeof(t->array[t->npages].pgdesc)); + + t->npages++; + + return (0); +} + +/* + * PUBLIC: int __fop_rename_print __P((DB_ENV *, DBT *, DB_LSN *, + * PUBLIC: db_recops, void *)); + */ +int +__fop_rename_print(dbenv, dbtp, lsnp, notused2, notused3) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops notused2; + void *notused3; +{ + __fop_rename_args *argp; + u_int32_t i; + int ch; + int ret; + + notused2 = DB_TXN_ABORT; + notused3 = NULL; + + if ((ret = __fop_rename_read(dbenv, dbtp->data, &argp)) != 0) + return (ret); + (void)printf( + "[%lu][%lu]__fop_rename: rec: %lu txnid %lx prevlsn [%lu][%lu]\n", + (u_long)lsnp->file, + (u_long)lsnp->offset, + (u_long)argp->type, + (u_long)argp->txnid->txnid, + (u_long)argp->prev_lsn.file, + (u_long)argp->prev_lsn.offset); + (void)printf("\toldname: "); + for (i = 0; i < argp->oldname.size; i++) { + ch = ((u_int8_t *)argp->oldname.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\tnewname: "); + for (i = 0; i < argp->newname.size; i++) { + ch = ((u_int8_t *)argp->newname.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\tfileid: "); + for (i = 0; i < argp->fileid.size; i++) { + ch = ((u_int8_t *)argp->fileid.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\tappname: %lu\n", (u_long)argp->appname); + (void)printf("\n"); + __os_free(dbenv, argp); + return (0); +} + +/* + * PUBLIC: int __fop_rename_read __P((DB_ENV *, void *, __fop_rename_args **)); + */ +int +__fop_rename_read(dbenv, recbuf, argpp) + DB_ENV *dbenv; + void *recbuf; + __fop_rename_args **argpp; +{ + __fop_rename_args *argp; + u_int32_t uinttmp; + u_int8_t *bp; + int ret; + + if ((ret = __os_malloc(dbenv, + sizeof(__fop_rename_args) + sizeof(DB_TXN), &argp)) != 0) + return (ret); + + argp->txnid = (DB_TXN *)&argp[1]; + + bp = recbuf; + memcpy(&argp->type, bp, sizeof(argp->type)); + bp += sizeof(argp->type); + + memcpy(&argp->txnid->txnid, bp, sizeof(argp->txnid->txnid)); + bp += sizeof(argp->txnid->txnid); + + memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN)); + bp += sizeof(DB_LSN); + + memset(&argp->oldname, 0, sizeof(argp->oldname)); + memcpy(&argp->oldname.size, bp, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + argp->oldname.data = bp; + bp += argp->oldname.size; + + memset(&argp->newname, 0, sizeof(argp->newname)); + memcpy(&argp->newname.size, bp, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + argp->newname.data = bp; + bp += argp->newname.size; + + memset(&argp->fileid, 0, sizeof(argp->fileid)); + memcpy(&argp->fileid.size, bp, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + argp->fileid.data = bp; + bp += argp->fileid.size; + + memcpy(&uinttmp, bp, sizeof(uinttmp)); + argp->appname = (u_int32_t)uinttmp; + bp += sizeof(uinttmp); + + *argpp = argp; + return (0); +} + +/* + * PUBLIC: int __fop_file_remove_log __P((DB_ENV *, DB_TXN *, + * PUBLIC: DB_LSN *, u_int32_t, const DBT *, const DBT *, const DBT *, + * PUBLIC: u_int32_t, u_int32_t)); + */ +int +__fop_file_remove_log(dbenv, txnid, ret_lsnp, flags, + real_fid, tmp_fid, name, appname, child) + DB_ENV *dbenv; + DB_TXN *txnid; + DB_LSN *ret_lsnp; + u_int32_t flags; + const DBT *real_fid; + const DBT *tmp_fid; + const DBT *name; + u_int32_t appname; + u_int32_t child; +{ + DBT logrec; + DB_LSN *lsnp, null_lsn; + u_int32_t zero; + u_int32_t uinttmp; + u_int32_t npad, rectype, txn_num; + int ret; + u_int8_t *bp; + + rectype = DB___fop_file_remove; + npad = 0; + + if (txnid == NULL) { + txn_num = 0; + null_lsn.file = 0; + null_lsn.offset = 0; + lsnp = &null_lsn; + } else { + if (TAILQ_FIRST(&txnid->kids) != NULL && + (ret = __txn_activekids(dbenv, rectype, txnid)) != 0) + return (ret); + txn_num = txnid->txnid; + lsnp = &txnid->last_lsn; + } + + logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN) + + sizeof(u_int32_t) + (real_fid == NULL ? 0 : real_fid->size) + + sizeof(u_int32_t) + (tmp_fid == NULL ? 0 : tmp_fid->size) + + sizeof(u_int32_t) + (name == NULL ? 0 : name->size) + + sizeof(u_int32_t) + + sizeof(u_int32_t); + if (CRYPTO_ON(dbenv)) { + npad = + ((DB_CIPHER *)dbenv->crypto_handle)->adj_size(logrec.size); + logrec.size += npad; + } + + if ((ret = __os_malloc(dbenv, + logrec.size, &logrec.data)) != 0) + return (ret); + + if (npad > 0) + memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad); + + bp = logrec.data; + + memcpy(bp, &rectype, sizeof(rectype)); + bp += sizeof(rectype); + + memcpy(bp, &txn_num, sizeof(txn_num)); + bp += sizeof(txn_num); + + memcpy(bp, lsnp, sizeof(DB_LSN)); + bp += sizeof(DB_LSN); + + if (real_fid == NULL) { + zero = 0; + memcpy(bp, &zero, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + } else { + memcpy(bp, &real_fid->size, sizeof(real_fid->size)); + bp += sizeof(real_fid->size); + memcpy(bp, real_fid->data, real_fid->size); + bp += real_fid->size; + } + + if (tmp_fid == NULL) { + zero = 0; + memcpy(bp, &zero, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + } else { + memcpy(bp, &tmp_fid->size, sizeof(tmp_fid->size)); + bp += sizeof(tmp_fid->size); + memcpy(bp, tmp_fid->data, tmp_fid->size); + bp += tmp_fid->size; + } + + if (name == NULL) { + zero = 0; + memcpy(bp, &zero, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + } else { + memcpy(bp, &name->size, sizeof(name->size)); + bp += sizeof(name->size); + memcpy(bp, name->data, name->size); + bp += name->size; + } + + uinttmp = (u_int32_t)appname; + memcpy(bp, &uinttmp, sizeof(uinttmp)); + bp += sizeof(uinttmp); + + uinttmp = (u_int32_t)child; + memcpy(bp, &uinttmp, sizeof(uinttmp)); + bp += sizeof(uinttmp); + + DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size); + ret = dbenv->log_put(dbenv, + ret_lsnp, (DBT *)&logrec, flags | DB_NOCOPY); + if (txnid != NULL && ret == 0) + txnid->last_lsn = *ret_lsnp; +#ifdef LOG_DIAGNOSTIC + if (ret != 0) + (void)__fop_file_remove_print(dbenv, + (DBT *)&logrec, ret_lsnp, NULL, NULL); +#endif + __os_free(dbenv, logrec.data); + return (ret); +} + +/* + * PUBLIC: int __fop_file_remove_getpgnos __P((DB_ENV *, DBT *, + * PUBLIC: DB_LSN *, db_recops, void *)); + */ +int +__fop_file_remove_getpgnos(dbenv, rec, lsnp, notused1, summary) + DB_ENV *dbenv; + DBT *rec; + DB_LSN *lsnp; + db_recops notused1; + void *summary; +{ + TXN_RECS *t; + int ret; + COMPQUIET(rec, NULL); + COMPQUIET(notused1, DB_TXN_ABORT); + + t = (TXN_RECS *)summary; + + if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0) + return (ret); + + t->array[t->npages].flags = LSN_PAGE_NOLOCK; + t->array[t->npages].lsn = *lsnp; + t->array[t->npages].fid = DB_LOGFILEID_INVALID; + memset(&t->array[t->npages].pgdesc, 0, + sizeof(t->array[t->npages].pgdesc)); + + t->npages++; + + return (0); +} + +/* + * PUBLIC: int __fop_file_remove_print __P((DB_ENV *, DBT *, + * PUBLIC: DB_LSN *, db_recops, void *)); + */ +int +__fop_file_remove_print(dbenv, dbtp, lsnp, notused2, notused3) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops notused2; + void *notused3; +{ + __fop_file_remove_args *argp; + u_int32_t i; + int ch; + int ret; + + notused2 = DB_TXN_ABORT; + notused3 = NULL; + + if ((ret = __fop_file_remove_read(dbenv, dbtp->data, &argp)) != 0) + return (ret); + (void)printf( + "[%lu][%lu]__fop_file_remove: rec: %lu txnid %lx prevlsn [%lu][%lu]\n", + (u_long)lsnp->file, + (u_long)lsnp->offset, + (u_long)argp->type, + (u_long)argp->txnid->txnid, + (u_long)argp->prev_lsn.file, + (u_long)argp->prev_lsn.offset); + (void)printf("\treal_fid: "); + for (i = 0; i < argp->real_fid.size; i++) { + ch = ((u_int8_t *)argp->real_fid.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\ttmp_fid: "); + for (i = 0; i < argp->tmp_fid.size; i++) { + ch = ((u_int8_t *)argp->tmp_fid.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\tname: "); + for (i = 0; i < argp->name.size; i++) { + ch = ((u_int8_t *)argp->name.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\tappname: %lu\n", (u_long)argp->appname); + (void)printf("\tchild: 0x%lx\n", (u_long)argp->child); + (void)printf("\n"); + __os_free(dbenv, argp); + return (0); +} + +/* + * PUBLIC: int __fop_file_remove_read __P((DB_ENV *, void *, + * PUBLIC: __fop_file_remove_args **)); + */ +int +__fop_file_remove_read(dbenv, recbuf, argpp) + DB_ENV *dbenv; + void *recbuf; + __fop_file_remove_args **argpp; +{ + __fop_file_remove_args *argp; + u_int32_t uinttmp; + u_int8_t *bp; + int ret; + + if ((ret = __os_malloc(dbenv, + sizeof(__fop_file_remove_args) + sizeof(DB_TXN), &argp)) != 0) + return (ret); + + argp->txnid = (DB_TXN *)&argp[1]; + + bp = recbuf; + memcpy(&argp->type, bp, sizeof(argp->type)); + bp += sizeof(argp->type); + + memcpy(&argp->txnid->txnid, bp, sizeof(argp->txnid->txnid)); + bp += sizeof(argp->txnid->txnid); + + memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN)); + bp += sizeof(DB_LSN); + + memset(&argp->real_fid, 0, sizeof(argp->real_fid)); + memcpy(&argp->real_fid.size, bp, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + argp->real_fid.data = bp; + bp += argp->real_fid.size; + + memset(&argp->tmp_fid, 0, sizeof(argp->tmp_fid)); + memcpy(&argp->tmp_fid.size, bp, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + argp->tmp_fid.data = bp; + bp += argp->tmp_fid.size; + + memset(&argp->name, 0, sizeof(argp->name)); + memcpy(&argp->name.size, bp, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + argp->name.data = bp; + bp += argp->name.size; + + memcpy(&uinttmp, bp, sizeof(uinttmp)); + argp->appname = (u_int32_t)uinttmp; + bp += sizeof(uinttmp); + + memcpy(&uinttmp, bp, sizeof(uinttmp)); + argp->child = (u_int32_t)uinttmp; + bp += sizeof(uinttmp); + + *argpp = argp; + return (0); +} + +/* + * PUBLIC: int __fop_init_print __P((DB_ENV *, int (***)(DB_ENV *, + * PUBLIC: DBT *, DB_LSN *, db_recops, void *), size_t *)); + */ +int +__fop_init_print(dbenv, dtabp, dtabsizep) + DB_ENV *dbenv; + int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + size_t *dtabsizep; +{ + int ret; + + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_create_print, DB___fop_create)) != 0) + return (ret); + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_remove_print, DB___fop_remove)) != 0) + return (ret); + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_write_print, DB___fop_write)) != 0) + return (ret); + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_rename_print, DB___fop_rename)) != 0) + return (ret); + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_file_remove_print, DB___fop_file_remove)) != 0) + return (ret); + return (0); +} + +/* + * PUBLIC: int __fop_init_getpgnos __P((DB_ENV *, int (***)(DB_ENV *, + * PUBLIC: DBT *, DB_LSN *, db_recops, void *), size_t *)); + */ +int +__fop_init_getpgnos(dbenv, dtabp, dtabsizep) + DB_ENV *dbenv; + int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + size_t *dtabsizep; +{ + int ret; + + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_create_getpgnos, DB___fop_create)) != 0) + return (ret); + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_remove_getpgnos, DB___fop_remove)) != 0) + return (ret); + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_write_getpgnos, DB___fop_write)) != 0) + return (ret); + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_rename_getpgnos, DB___fop_rename)) != 0) + return (ret); + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_file_remove_getpgnos, DB___fop_file_remove)) != 0) + return (ret); + return (0); +} + +/* + * PUBLIC: int __fop_init_recover __P((DB_ENV *, int (***)(DB_ENV *, + * PUBLIC: DBT *, DB_LSN *, db_recops, void *), size_t *)); + */ +int +__fop_init_recover(dbenv, dtabp, dtabsizep) + DB_ENV *dbenv; + int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + size_t *dtabsizep; +{ + int ret; + + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_create_recover, DB___fop_create)) != 0) + return (ret); + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_remove_recover, DB___fop_remove)) != 0) + return (ret); + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_write_recover, DB___fop_write)) != 0) + return (ret); + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_rename_recover, DB___fop_rename)) != 0) + return (ret); + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + __fop_file_remove_recover, DB___fop_file_remove)) != 0) + return (ret); + return (0); +} diff --git a/bdb/fileops/fop_basic.c b/bdb/fileops/fop_basic.c new file mode 100644 index 00000000000..08160ab2e1a --- /dev/null +++ b/bdb/fileops/fop_basic.c @@ -0,0 +1,275 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001-2002 + * Sleepycat Software. All rights reserved. + */ + +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: fop_basic.c,v 1.23 2002/08/11 02:11:23 margo Exp $"; +#endif /* not lint */ + +#ifndef NO_SYSTEM_INCLUDES +#include <string.h> +#include <sys/types.h> +#endif + +#include "db_int.h" +#include "dbinc/log.h" +#include "dbinc/db_page.h" +#include "dbinc/fop.h" +#include "dbinc/txn.h" +#include "dbinc/db_am.h" + +/* + * This file implements the basic file-level operations. This code + * ought to be fairly independent of DB, other than through its + * error-reporting mechanism. + */ + +/* + * __fop_create -- + * Create a (transactionally protected) file system object. This is used + * to create DB files now, potentially blobs, queue extents and anything + * else you wish to store in a file system object. + * + * PUBLIC: int __fop_create __P((DB_ENV *, + * PUBLIC: DB_TXN *, DB_FH *, const char *, APPNAME, int)); + */ +int +__fop_create(dbenv, txn, fhp, name, appname, mode) + DB_ENV *dbenv; + DB_TXN *txn; + DB_FH *fhp; + const char *name; + APPNAME appname; + int mode; +{ + DB_FH fh; + DB_LSN lsn; + DBT data; + char *real_name; + int do_close, ret; + + ret = 0; + real_name = NULL; + + if (fhp != NULL) + do_close = 0; + else { + fhp = &fh; + memset(fhp, 0, sizeof(fh)); + do_close = 1; + } + + if (mode == 0) + mode = __db_omode("rw----"); + + if ((ret = + __db_appname(dbenv, appname, name, 0, NULL, &real_name)) != 0) + goto err; + + if (DBENV_LOGGING(dbenv)) { + memset(&data, 0, sizeof(data)); + data.data = (void *)name; + data.size = (u_int32_t)strlen(name) + 1; + if ((ret = __fop_create_log(dbenv, + txn, &lsn, DB_FLUSH, &data, (u_int32_t)appname, mode)) != 0) + goto err; + } + + DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_POSTLOG, ret, name); + + ret = + __os_open(dbenv, real_name, DB_OSO_CREATE | DB_OSO_EXCL, mode, fhp); + +err: +DB_TEST_RECOVERY_LABEL + if (do_close && F_ISSET(fhp, DB_FH_VALID)) + __os_closehandle(dbenv, fhp); + if (real_name != NULL) + __os_free(dbenv, real_name); + return (ret); +} + +/* + * __fop_remove -- + * Remove a file system object. + * + * PUBLIC: int __fop_remove __P((DB_ENV *, + * PUBLIC: DB_TXN *, u_int8_t *, const char *, APPNAME)); + */ +int +__fop_remove(dbenv, txn, fileid, name, appname) + DB_ENV *dbenv; + DB_TXN *txn; + u_int8_t *fileid; + const char *name; + APPNAME appname; +{ + DB_LSN lsn; + DBT fdbt, ndbt; + char *real_name; + int ret; + + real_name = NULL; + + if ((ret = + __db_appname(dbenv, appname, name, 0, NULL, &real_name)) != 0) + goto err; + + if (txn == NULL) { + if (fileid != NULL && (ret = dbenv->memp_nameop( + dbenv, fileid, NULL, real_name, NULL)) != 0) + goto err; + } else { + if (DBENV_LOGGING(dbenv)) { + memset(&fdbt, 0, sizeof(ndbt)); + fdbt.data = fileid; + fdbt.size = fileid == NULL ? 0 : DB_FILE_ID_LEN; + memset(&ndbt, 0, sizeof(ndbt)); + ndbt.data = (void *)name; + ndbt.size = (u_int32_t)strlen(name) + 1; + if ((ret = __fop_remove_log(dbenv, + txn, &lsn, 0, &ndbt, &fdbt, appname)) != 0) + goto err; + } + ret = __txn_remevent(dbenv, txn, real_name, fileid); + } + +err: if (real_name != NULL) + __os_free(dbenv, real_name); + return (ret); +} + +/* + * __fop_write + * + * Write "size" bytes from "buf" to file "name" beginning at offset "off." + * If the file is open, supply a handle in fhp. Istmp indicate if this is + * an operation that needs to be undone in the face of failure (i.e., if + * this is a write to a temporary file, we're simply going to remove the + * file, so don't worry about undoing the write). + * + * Currently, we *only* use this with istmp true. If we need more general + * handling, then we'll have to zero out regions on abort (and possibly + * log the before image of the data in the log record). + * + * PUBLIC: int __fop_write __P((DB_ENV *, DB_TXN *, const char *, APPNAME, + * PUBLIC: DB_FH *, u_int32_t, u_int8_t *, u_int32_t, u_int32_t)); + */ +int +__fop_write(dbenv, txn, name, appname, fhp, off, buf, size, istmp) + DB_ENV *dbenv; + DB_TXN *txn; + const char *name; + APPNAME appname; + DB_FH *fhp; + u_int32_t off; + u_int8_t *buf; + u_int32_t size, istmp; +{ + DB_FH fh; + DB_LSN lsn; + DBT data, namedbt; + char *real_name; + int ret, t_ret, we_opened; + size_t nbytes; + + ret = 0; + we_opened = 0; + real_name = NULL; + + if ((ret = + __db_appname(dbenv, appname, name, 0, NULL, &real_name)) != 0) + goto err; + + if (DBENV_LOGGING(dbenv)) { + memset(&data, 0, sizeof(data)); + data.data = buf; + data.size = size; + memset(&namedbt, 0, sizeof(namedbt)); + namedbt.data = (void *)name; + namedbt.size = (u_int32_t)strlen(name) + 1; + if ((ret = __fop_write_log(dbenv, + txn, &lsn, 0, &namedbt, appname, off, &data, istmp)) != 0) + goto err; + } + + if (fhp == NULL) { + /* File isn't open; we need to reopen it. */ + if ((ret = __os_open(dbenv, real_name, 0, 0, &fh)) != 0) + goto err; + fhp = &fh; + we_opened = 1; + } else + we_opened = 0; + + /* Seek to offset. */ + if ((ret = __os_seek(dbenv, fhp, 0, 0, off, 0, DB_OS_SEEK_SET)) != 0) + goto err; + + /* Now do the write. */ + if ((ret = __os_write(dbenv, fhp, buf, size, &nbytes)) != 0) + goto err; + +err: if (we_opened) + if ((t_ret = __os_closehandle(dbenv, fhp)) != 0 && ret == 0) + ret = t_ret; + + if (real_name != NULL) + __os_free(dbenv, real_name); + return (ret); +} + +/* + * __fop_rename -- + * Change a file's name. + * + * PUBLIC: int __fop_rename __P((DB_ENV *, + * PUBLIC: DB_TXN *, const char *, const char *, u_int8_t *, APPNAME)); + */ +int +__fop_rename(dbenv, txn, oldname, newname, fid, appname) + DB_ENV *dbenv; + DB_TXN *txn; + const char *oldname; + const char *newname; + u_int8_t *fid; + APPNAME appname; +{ + DB_LSN lsn; + DBT fiddbt, new, old; + int ret; + char *n, *o; + + if ((ret = __db_appname(dbenv, appname, oldname, 0, NULL, &o)) != 0) + goto err; + if ((ret = __db_appname(dbenv, appname, newname, 0, NULL, &n)) != 0) + goto err; + + if (DBENV_LOGGING(dbenv)) { + memset(&old, 0, sizeof(old)); + memset(&new, 0, sizeof(new)); + memset(&fiddbt, 0, sizeof(fiddbt)); + old.data = (void *)oldname; + old.size = (u_int32_t)strlen(oldname) + 1; + new.data = (void *)newname; + new.size = (u_int32_t)strlen(newname) + 1; + fiddbt.data = fid; + fiddbt.size = DB_FILE_ID_LEN; + if ((ret = __fop_rename_log(dbenv, txn, &lsn, + DB_FLUSH, &old, &new, &fiddbt, (u_int32_t)appname)) != 0) + goto err; + } + + ret = dbenv->memp_nameop(dbenv, fid, newname, o, n); + +err: if (o != oldname) + __os_free(dbenv, o); + if (n != newname) + __os_free(dbenv, n); + return (ret); +} diff --git a/bdb/fileops/fop_rec.c b/bdb/fileops/fop_rec.c new file mode 100644 index 00000000000..67720e01d13 --- /dev/null +++ b/bdb/fileops/fop_rec.c @@ -0,0 +1,308 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001-2002 + * Sleepycat Software. All rights reserved. + */ + +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: fop_rec.c,v 1.18 2002/08/14 20:27:01 bostic Exp $"; +#endif /* not lint */ + +#ifndef NO_SYSTEM_INCLUDES +#include <sys/types.h> + +#include <string.h> +#endif + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/fop.h" +#include "dbinc/db_am.h" +#include "dbinc/txn.h" + +/* + * __fop_create_recover -- + * Recovery function for create. + * + * PUBLIC: int __fop_create_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__fop_create_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + DB_FH fh; + __fop_create_args *argp; + char *real_name; + int ret; + + real_name = NULL; + COMPQUIET(info, NULL); + REC_PRINT(__fop_create_print); + REC_NOOP_INTRO(__fop_create_read); + + if ((ret = __db_appname(dbenv, (APPNAME)argp->appname, + (const char *)argp->name.data, 0, NULL, &real_name)) != 0) + goto out; + + if (DB_UNDO(op)) + (void)__os_unlink(dbenv, real_name); + else if (DB_REDO(op)) + if ((ret = __os_open(dbenv, real_name, + DB_OSO_CREATE | DB_OSO_EXCL, argp->mode, &fh)) == 0) + __os_closehandle(dbenv, &fh); + + *lsnp = argp->prev_lsn; + +out: if (real_name != NULL) + __os_free(dbenv, real_name); + + REC_NOOP_CLOSE; +} + +/* + * __fop_remove_recover -- + * Recovery function for remove. + * + * PUBLIC: int __fop_remove_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__fop_remove_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + __fop_remove_args *argp; + char *real_name; + int ret; + + real_name = NULL; + COMPQUIET(info, NULL); + REC_PRINT(__fop_remove_print); + REC_NOOP_INTRO(__fop_remove_read); + + if ((ret = __db_appname(dbenv, (APPNAME)argp->appname, + (const char *)argp->name.data, 0, NULL, &real_name)) != 0) + goto out; + + if (DB_REDO(op) && (ret = dbenv->memp_nameop(dbenv, + (u_int8_t *)argp->fid.data, NULL, real_name, NULL)) != 0) + goto out; + + *lsnp = argp->prev_lsn; +out: if (real_name != NULL) + __os_free(dbenv, real_name); + REC_NOOP_CLOSE; +} + +/* + * __fop_write_recover -- + * Recovery function for writechunk. + * + * PUBLIC: int __fop_write_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__fop_write_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + __fop_write_args *argp; + int ret; + + COMPQUIET(info, NULL); + REC_PRINT(__fop_write_print); + REC_NOOP_INTRO(__fop_write_read); + + if (DB_UNDO(op)) + DB_ASSERT(argp->flag != 0); + else if (DB_REDO(op)) + ret = __fop_write(dbenv, + argp->txnid, argp->name.data, argp->appname, NULL, + argp->offset, argp->page.data, argp->page.size, argp->flag); + + *lsnp = argp->prev_lsn; + REC_NOOP_CLOSE; +} + +/* + * __fop_rename_recover -- + * Recovery function for rename. + * + * PUBLIC: int __fop_rename_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__fop_rename_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + __fop_rename_args *argp; + DBMETA *meta; + char *real_new, *real_old, *src; + int ret; + u_int8_t *fileid, mbuf[DBMETASIZE]; + + real_new = NULL; + real_old = NULL; + ret = 0; + meta = (DBMETA *)&mbuf[0]; + + COMPQUIET(info, NULL); + REC_PRINT(__fop_rename_print); + REC_NOOP_INTRO(__fop_rename_read); + fileid = argp->fileid.data; + + if ((ret = __db_appname(dbenv, (APPNAME)argp->appname, + (const char *)argp->newname.data, 0, NULL, &real_new)) != 0) + goto out; + if ((ret = __db_appname(dbenv, (APPNAME)argp->appname, + (const char *)argp->oldname.data, 0, NULL, &real_old)) != 0) + goto out; + + /* + * Verify that we are manipulating the correct file. We should always + * be OK on an ABORT or an APPLY, but during recovery, we have to + * check. + */ + if (op != DB_TXN_ABORT && op != DB_TXN_APPLY) { + src = DB_UNDO(op) ? real_new : real_old; + /* + * Interpret any error as meaning that the file either doesn't + * exist, doesn't have a meta-data page, or is in some other + * way, shape or form, incorrect, so that we should not restore + * it. + */ + if (__fop_read_meta( + dbenv, src, mbuf, DBMETASIZE, NULL, 1, 0) != 0) + goto done; + if (__db_chk_meta(dbenv, NULL, meta, 1) != 0) + goto done; + if (memcmp(argp->fileid.data, meta->uid, DB_FILE_ID_LEN) != 0) + goto done; + } + + if (DB_UNDO(op)) + (void)dbenv->memp_nameop(dbenv, fileid, + (const char *)argp->oldname.data, real_new, real_old); + if (DB_REDO(op)) + (void)dbenv->memp_nameop(dbenv, fileid, + (const char *)argp->newname.data, real_old, real_new); + +done: *lsnp = argp->prev_lsn; +out: if (real_new != NULL) + __os_free(dbenv, real_new); + if (real_old != NULL) + __os_free(dbenv, real_old); + + REC_NOOP_CLOSE; +} + +/* + * __fop_file_remove_recover -- + * Recovery function for file_remove. On the REDO pass, we need to + * make sure no one recreated the file while we weren't looking. On an + * undo pass must check if the file we are interested in is the one that + * exists and then set the status of the child transaction depending on + * what we find out. + * + * PUBLIC: int __fop_file_remove_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__fop_file_remove_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + __fop_file_remove_args *argp; + DBMETA *meta; + char *real_name; + int is_real, is_tmp, ret; + u_int8_t mbuf[DBMETASIZE]; + u_int32_t cstat; + + real_name = NULL; + is_real = is_tmp = 0; + meta = (DBMETA *)&mbuf[0]; + REC_PRINT(__fop_file_remove_print); + REC_NOOP_INTRO(__fop_file_remove_read); + + /* + * This record is only interesting on the backward, forward, and + * apply phases. + */ + if (op != DB_TXN_BACKWARD_ROLL && + op != DB_TXN_FORWARD_ROLL && op != DB_TXN_APPLY) + goto done; + + if ((ret = __db_appname(dbenv, + (APPNAME)argp->appname, argp->name.data, 0, NULL, &real_name)) != 0) + goto out; + + /* Verify that we are manipulating the correct file. */ + if ((ret = __fop_read_meta(dbenv, + real_name, mbuf, DBMETASIZE, NULL, 1, 0)) != 0) { + /* File does not exist. */ + cstat = TXN_EXPECTED; + } else { + /* + * We can ignore errors here since we'll simply fail the + * checks below and assume this is the wrong file. + */ + (void)__db_chk_meta(dbenv, NULL, meta, 1); + is_real = + memcmp(argp->real_fid.data, meta->uid, DB_FILE_ID_LEN) == 0; + is_tmp = + memcmp(argp->tmp_fid.data, meta->uid, DB_FILE_ID_LEN) == 0; + + if (!is_real && !is_tmp) + /* File exists, but isn't what we were removing. */ + cstat = TXN_IGNORE; + else + /* File exists and is the one that we were removing. */ + cstat = TXN_COMMIT; + } + + if (DB_UNDO(op)) { + /* On the backward pass, we leave a note for the child txn. */ + if ((ret = __db_txnlist_update(dbenv, + info, argp->child, cstat, NULL)) == DB_NOTFOUND) + ret = __db_txnlist_add(dbenv, + info, argp->child, cstat, NULL); + } else if (DB_REDO(op)) { + /* + * On the forward pass, check if someone recreated the + * file while we weren't looking. + */ + if (cstat == TXN_COMMIT) + (void)dbenv->memp_nameop(dbenv, + is_real ? argp->real_fid.data : argp->tmp_fid.data, + NULL, real_name, NULL); + } + +done: *lsnp = argp->prev_lsn; + ret = 0; + +out: if (real_name != NULL) + __os_free(dbenv, real_name); + REC_NOOP_CLOSE; +} diff --git a/bdb/fileops/fop_util.c b/bdb/fileops/fop_util.c new file mode 100644 index 00000000000..ea6d86ab08d --- /dev/null +++ b/bdb/fileops/fop_util.c @@ -0,0 +1,928 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001-2002 + * Sleepycat Software. All rights reserved. + */ + +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: fop_util.c,v 1.52 2002/09/10 02:41:42 bostic Exp $"; +#endif /* not lint */ + +#ifndef NO_SYSTEM_INCLUDES +#include <sys/types.h> + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#endif + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_shash.h" +#include "dbinc/db_am.h" +#include "dbinc/fop.h" +#include "dbinc/lock.h" +#include "dbinc/log.h" +#include "dbinc/txn.h" + +static int __fop_set_pgsize __P((DB *, DB_FH *, const char *)); + +/* + * Acquire the environment meta-data lock. The parameters are the + * environment (ENV), the locker id to use in acquiring the lock (ID) + * and a pointer to a DB_LOCK. + */ +#define GET_ENVLOCK(ENV, ID, L) do { \ + DBT __dbt; \ + u_int32_t __lockval; \ + \ + if (LOCKING_ON((ENV))) { \ + __lockval = 0; \ + __dbt.data = &__lockval; \ + __dbt.size = sizeof(__lockval); \ + if ((ret = (ENV)->lock_get((ENV), (ID), \ + 0, &__dbt, DB_LOCK_WRITE, (L))) != 0) \ + goto err; \ + } \ +} while (0) + +#define REL_ENVLOCK(ENV, L) \ + (!LOCK_ISSET(*(L)) ? 0 : (ENV)->lock_put((ENV), (L))) + +/* + * If our caller is doing fcntl(2) locking, then we can't close it + * because that would discard the caller's lock. Otherwise, close + * the handle. + */ +#define CLOSE_HANDLE(D, F) { \ + if (F_ISSET((F), DB_FH_VALID)) { \ + if (LF_ISSET(DB_FCNTL_LOCKING)) \ + (D)->saved_open_fhp = (F); \ + else if ((ret = __os_closehandle((D)->dbenv,(F))) != 0) \ + goto err; \ + } \ +} + +/* + * __fop_lock_handle -- + * + * Get the handle lock for a database. If the envlock is specified, + * do this as a lock_vec call that releases the enviroment lock before + * acquiring the handle lock. + * + * PUBLIC: int __fop_lock_handle __P((DB_ENV *, + * PUBLIC: DB *, u_int32_t, db_lockmode_t, DB_LOCK *, u_int32_t)); + * + */ +int +__fop_lock_handle(dbenv, dbp, locker, mode, elock, flags) + DB_ENV *dbenv; + DB *dbp; + u_int32_t locker; + db_lockmode_t mode; + DB_LOCK *elock; + u_int32_t flags; +{ + DBT fileobj; + DB_LOCKREQ reqs[2], *ereq; + DB_LOCK_ILOCK lock_desc; + int ret; + + if (!LOCKING_ON(dbenv) || F_ISSET(dbp, DB_AM_COMPENSATE)) + return (0); + + /* + * If we are in recovery, the only locking we should be + * doing is on the global environment. + */ + if (IS_RECOVERING(dbenv)) { + if (elock != NULL) + REL_ENVLOCK(dbenv, elock); + return (0); + } + + memcpy(&lock_desc.fileid, &dbp->fileid, DB_FILE_ID_LEN); + lock_desc.pgno = dbp->meta_pgno; + lock_desc.type = DB_HANDLE_LOCK; + + memset(&fileobj, 0, sizeof(fileobj)); + fileobj.data = &lock_desc; + fileobj.size = sizeof(lock_desc); + DB_TEST_SUBLOCKS(dbenv, flags); + if (elock == NULL) + ret = dbenv->lock_get(dbenv, locker, + flags, &fileobj, mode, &dbp->handle_lock); + else { + reqs[0].op = DB_LOCK_PUT; + reqs[0].lock = *elock; + reqs[1].op = DB_LOCK_GET; + reqs[1].mode = mode; + reqs[1].obj = &fileobj; + reqs[1].timeout = 0; + if ((ret = __lock_vec(dbenv, + locker, flags, reqs, 2, &ereq)) == 0) { + dbp->handle_lock = reqs[1].lock; + LOCK_INIT(*elock); + } else if (ereq != reqs) + LOCK_INIT(*elock); + } + + dbp->cur_lid = locker; + return (ret); +} + +/* + * __fop_file_setup -- + * + * Perform all the needed checking and locking to open up or create a + * file. + * + * There's a reason we don't push this code down into the buffer cache. + * The problem is that there's no information external to the file that + * we can use as a unique ID. UNIX has dev/inode pairs, but they are + * not necessarily unique after reboot, if the file was mounted via NFS. + * Windows has similar problems, as the FAT filesystem doesn't maintain + * dev/inode numbers across reboot. So, we must get something from the + * file we can use to ensure that, even after a reboot, the file we're + * joining in the cache is the right file for us to join. The solution + * we use is to maintain a file ID that's stored in the database, and + * that's why we have to open and read the file before calling into the + * buffer cache or obtaining a lock (we use this unique fileid to lock + * as well as to identify like files in the cache). + * + * PUBLIC: int __fop_file_setup __P((DB *, + * PUBLIC: DB_TXN *, const char *, int, u_int32_t, u_int32_t *)); + */ +int +__fop_file_setup(dbp, txn, name, mode, flags, retidp) + DB *dbp; + DB_TXN *txn; + const char *name; + int mode; + u_int32_t flags, *retidp; +{ + DB_ENV *dbenv; + DB_FH fh, *fhp; + DB_LOCK elock, tmp_lock; + DB_TXN *stxn; + db_lockmode_t lmode; + u_int32_t locker, oflags; + u_int8_t mbuf[DBMETASIZE]; + int created_fhp, created_locker, ret, tmp_created, truncating; + char *real_name, *real_tmpname, *tmpname; + + DB_ASSERT(name != NULL); + + *retidp = TXN_INVALID; + + dbenv = dbp->dbenv; + LOCK_INIT(elock); + LOCK_INIT(tmp_lock); + stxn = NULL; + created_fhp = created_locker = 0; + real_name = real_tmpname = tmpname = NULL; + tmp_created = truncating = 0; + + /* + * If we open a file handle and our caller is doing fcntl(2) locking, + * we can't close it because that would discard the caller's lock. + * Save it until we close the DB handle. + */ + if (LF_ISSET(DB_FCNTL_LOCKING)) { + if ((ret = __os_malloc(dbenv, sizeof(*fhp), &fhp)) != 0) + return (ret); + created_fhp = 1; + } else + fhp = &fh; + memset(fhp, 0, sizeof(*fhp)); + + /* + * Get a lockerid for this handle. There are paths through queue + * rename and remove where this dbp already has a locker, so make + * sure we don't clobber it and conflict. + */ + if (LOCKING_ON(dbenv) && + !F_ISSET(dbp, DB_AM_COMPENSATE) && dbp->lid == DB_LOCK_INVALIDID) { + if ((ret = __lock_id(dbenv, &dbp->lid)) != 0) + goto err; + created_locker = 1; + } + + locker = txn == NULL ? dbp->lid : txn->txnid; + + /* Get the real backing file name. */ + if ((ret = __db_appname(dbenv, + DB_APP_DATA, name, 0, NULL, &real_name)) != 0) + goto err; + + /* Fill in the default file mode. */ + if (mode == 0) + mode = __db_omode("rwrw--"); + + oflags = 0; + if (LF_ISSET(DB_RDONLY)) + oflags |= DB_OSO_RDONLY; + +retry: if (!F_ISSET(dbp, DB_AM_COMPENSATE)) + GET_ENVLOCK(dbenv, locker, &elock); + if ((ret = __os_exists(real_name, NULL)) == 0) { + if (LF_ISSET(DB_EXCL)) { + ret = EEXIST; + goto err; + } +reopen: if ((ret = __fop_read_meta(dbenv, real_name, + mbuf, sizeof(mbuf), fhp, 0, oflags)) != 0) + goto err; + + if ((ret = __db_meta_setup(dbenv, + dbp, real_name, (DBMETA *)mbuf, flags, 1)) != 0) + goto err; + + /* Now, get our handle lock. */ + lmode = LF_ISSET(DB_TRUNCATE) ? DB_LOCK_WRITE : DB_LOCK_READ; + if ((ret = __fop_lock_handle(dbenv, + dbp, locker, lmode, NULL, DB_LOCK_NOWAIT)) == 0) { + if ((ret = REL_ENVLOCK(dbenv, &elock)) != 0) + goto err; + } else { + /* Someone else has file locked; need to wait. */ + if ((ret = __os_closehandle(dbenv, fhp)) != 0) + goto err; + ret = __fop_lock_handle(dbenv, + dbp, locker, lmode, &elock, 0); + if (ret == DB_LOCK_NOTEXIST) + goto retry; + if (ret != 0) + goto err; + /* + * XXX I need to convince myself that I don't need + * to re-read the metadata page here. + * XXX If you do need to re-read it you'd better + * decrypt it too... + */ + if ((ret = __os_open(dbenv, real_name, 0, 0, fhp)) != 0) + goto err; + } + + /* + * Check for a truncate which needs to leap over to the + * create case. + */ + if (LF_ISSET(DB_TRUNCATE)) { + /* + * Sadly, we need to close and reopen the handle + * in order to do the actual truncate. We couldn't + * do the truncate on the initial open because we + * needed to read the old file-id in order to lock. + */ + if ((ret = __os_closehandle(dbenv, fhp)) != 0) + goto err; + if ((ret = __os_open(dbenv, + real_name, DB_OSO_TRUNC, 0, fhp)) != 0) + goto err; + /* + * This is not-transactional, so we'll do the + * open/create in-place. + */ + tmp_lock = dbp->handle_lock; + truncating = 1; + tmpname = (char *)name; + goto creat2; + } + + /* + * Check for a file in the midst of a rename + */ + if (F_ISSET(dbp, DB_AM_IN_RENAME)) { + if (LF_ISSET(DB_CREATE)) { + F_CLR(dbp, DB_AM_IN_RENAME); + goto create; + } else { + ret = ENOENT; + goto err; + } + } + + CLOSE_HANDLE(dbp, fhp); + goto done; + } + + /* File does not exist. */ + if (!LF_ISSET(DB_CREATE)) + goto err; + ret = 0; + + /* + * Need to create file; we need to set up the file, + * the fileid and the locks. Then we need to call + * the appropriate routines to create meta-data pages. + */ + if ((ret = REL_ENVLOCK(dbenv, &elock)) != 0) + goto err; + +create: if ((ret = __db_backup_name(dbenv, name, txn, &tmpname)) != 0) + goto err; + if (TXN_ON(dbenv) && txn != NULL && + (ret = dbenv->txn_begin(dbenv, txn, &stxn, 0)) != 0) + goto err; + if ((ret = __fop_create(dbenv, + stxn, fhp, tmpname, DB_APP_DATA, mode)) != 0) + goto err; + tmp_created = 1; +creat2: if ((ret = __db_appname(dbenv, + DB_APP_DATA, tmpname, 0, NULL, &real_tmpname)) != 0) + goto err; + + /* Set the pagesize if it isn't yet set. */ + if (dbp->pgsize == 0 && + (ret = __fop_set_pgsize(dbp, fhp, real_tmpname)) != 0) + goto errmsg; + + /* Construct a file_id. */ + if ((ret = __os_fileid(dbenv, real_tmpname, 1, dbp->fileid)) != 0) + goto errmsg; + + if ((ret = __db_new_file(dbp, stxn, fhp, tmpname)) != 0) + goto err; + CLOSE_HANDLE(dbp, fhp); + + /* Now move the file into place. */ + if (!F_ISSET(dbp, DB_AM_COMPENSATE)) + GET_ENVLOCK(dbenv, locker, &elock); + if (!truncating && __os_exists(real_name, NULL) == 0) { + /* + * Someone managed to create the file; remove our temp + * and try to open the file that now exists. + */ + (void)__fop_remove(dbenv, + NULL, dbp->fileid, tmpname, DB_APP_DATA); + if (LOCKING_ON(dbenv)) + dbenv->lock_put(dbenv, &dbp->handle_lock); + LOCK_INIT(dbp->handle_lock); + + /* If we have a saved handle; close it. */ + if (LF_ISSET(DB_FCNTL_LOCKING)) + (void)__os_closehandle(dbenv, fhp); + if (stxn != NULL) { + ret = stxn->abort(stxn); + stxn = NULL; + } + if (ret != 0) + goto err; + goto reopen; + } + + /* We've successfully created, move the file into place. */ + if ((ret = __fop_lock_handle(dbenv, + dbp, locker, DB_LOCK_WRITE, &elock, 0)) != 0) + goto err; + if (!truncating && (ret = __fop_rename(dbenv, + stxn, tmpname, name, dbp->fileid, DB_APP_DATA)) != 0) + goto err; + + /* If this was a truncate; release lock on the old file. */ + if (LOCK_ISSET(tmp_lock) && (ret = __lock_put(dbenv, &tmp_lock)) != 0) + goto err; + + if (stxn != NULL) { + *retidp = stxn->txnid; + ret = stxn->commit(stxn, 0); + stxn = NULL; + } else + *retidp = TXN_INVALID; + + if (ret != 0) + goto err; + + F_SET(dbp, DB_AM_CREATED); + + if (0) { +errmsg: __db_err(dbenv, "%s: %s", name, db_strerror(ret)); + +err: if (stxn != NULL) + (void)stxn->abort(stxn); + if (tmp_created && txn == NULL) + (void)__fop_remove(dbenv, + NULL, NULL, tmpname, DB_APP_DATA); + if (F_ISSET(fhp, DB_FH_VALID)) + (void)__os_closehandle(dbenv, fhp); + if (LOCK_ISSET(tmp_lock)) + __lock_put(dbenv, &tmp_lock); + if (LOCK_ISSET(dbp->handle_lock) && txn == NULL) + __lock_put(dbenv, &dbp->handle_lock); + if (LOCK_ISSET(elock)) + (void)REL_ENVLOCK(dbenv, &elock); + if (created_locker) { + (void)__lock_id_free(dbenv, dbp->lid); + dbp->lid = DB_LOCK_INVALIDID; + } + if (created_fhp) + __os_free(dbenv, fhp); + } + +done: if (!truncating && tmpname != NULL) + __os_free(dbenv, tmpname); + if (real_name != NULL) + __os_free(dbenv, real_name); + if (real_tmpname != NULL) + __os_free(dbenv, real_tmpname); + + return (ret); +} + +/* + * __fop_set_pgsize -- + * Set the page size based on file information. + */ +static int +__fop_set_pgsize(dbp, fhp, name) + DB *dbp; + DB_FH *fhp; + const char *name; +{ + DB_ENV *dbenv; + u_int32_t iopsize; + int ret; + + dbenv = dbp->dbenv; + + /* + * Use the filesystem's optimum I/O size as the pagesize if a pagesize + * not specified. Some filesystems have 64K as their optimum I/O size, + * but as that results in fairly large default caches, we limit the + * default pagesize to 16K. + */ + if ((ret = __os_ioinfo(dbenv, name, fhp, NULL, NULL, &iopsize)) != 0) { + __db_err(dbenv, "%s: %s", name, db_strerror(ret)); + return (ret); + } + if (iopsize < 512) + iopsize = 512; + if (iopsize > 16 * 1024) + iopsize = 16 * 1024; + + /* + * Sheer paranoia, but we don't want anything that's not a power-of-2 + * (we rely on that for alignment of various types on the pages), and + * we want a multiple of the sector size as well. If the value + * we got out of __os_ioinfo looks bad, use a default instead. + */ + if (!IS_VALID_PAGESIZE(iopsize)) + iopsize = DB_DEF_IOSIZE; + + dbp->pgsize = iopsize; + F_SET(dbp, DB_AM_PGDEF); + + return (0); +} + +/* + * __fop_subdb_setup -- + * + * Subdb setup is significantly simpler than file setup. In terms of + * locking, for the duration of the operation/transaction, the locks on + * the meta-data page will suffice to protect us from simultaneous operations + * on the sub-database. Before we complete the operation though, we'll get a + * handle lock on the subdatabase so that on one else can try to remove it + * while we've got it open. We use an object that looks like the meta-data + * page lock with a different type (DB_HANDLE_LOCK) for the long-term handle. + * locks. + * + * PUBLIC: int __fop_subdb_setup __P((DB *, DB_TXN *, + * PUBLIC: const char *, const char *, int, u_int32_t)); + */ +int +__fop_subdb_setup(dbp, txn, mname, name, mode, flags) + DB *dbp; + DB_TXN *txn; + const char *mname, *name; + int mode; + u_int32_t flags; +{ + DB *mdbp; + DB_ENV *dbenv; + int do_remove, ret; + + mdbp = NULL; + dbenv = dbp->dbenv; + + if ((ret = __db_master_open(dbp, txn, mname, flags, mode, &mdbp)) != 0) + return (ret); + + /* + * We are going to close this instance of the master, so we can + * steal its handle instead of reopening a handle on the database. + */ + if (LF_ISSET(DB_FCNTL_LOCKING)) { + dbp->saved_open_fhp = mdbp->saved_open_fhp; + mdbp->saved_open_fhp = NULL; + } + + /* Now copy the pagesize. */ + dbp->pgsize = mdbp->pgsize; + F_SET(dbp, DB_AM_SUBDB); + + if (name != NULL && (ret = __db_master_update(mdbp, dbp, txn, + name, dbp->type, MU_OPEN, NULL, flags)) != 0) + goto err; + + /* + * Hijack the master's locker ID as well, so that our locks don't + * conflict with the master's. Since we're closing the master, + * that lid would just have been freed anyway. Once we've gotten + * the locker id, we need to acquire the handle lock for this + * subdatabase. + */ + dbp->lid = mdbp->lid; + mdbp->lid = DB_LOCK_INVALIDID; + + DB_TEST_RECOVERY(dbp, DB_TEST_POSTLOG, ret, mname); + + /* + * We copy our fileid from our master so that we all open + * the same file in mpool. We'll use the meta-pgno to lock + * so that we end up with different handle locks. + */ + + memcpy(dbp->fileid, mdbp->fileid, DB_FILE_ID_LEN); + if ((ret = __fop_lock_handle(dbenv, dbp, + txn == NULL ? dbp->lid : txn->txnid, + F_ISSET(dbp, DB_AM_CREATED) || LF_ISSET(DB_WRITEOPEN) ? + DB_LOCK_WRITE : DB_LOCK_READ, NULL, 0)) != 0) + goto err; + + if ((ret = __db_init_subdb(mdbp, dbp, name, txn)) != 0) + goto err; + + /* + * In the file create case, these happen in separate places so we have + * two different tests. They end up in the same place for subdbs, but + * for compatibility with file testing, we put them both here anyway. + */ + DB_TEST_RECOVERY(dbp, DB_TEST_POSTLOGMETA, ret, mname); + DB_TEST_RECOVERY(dbp, DB_TEST_POSTSYNC, ret, mname); + + /* + * File exists and we have the appropriate locks; we should now + * process a normal open. + */ + if (F_ISSET(mdbp, DB_AM_CREATED)) { + F_SET(dbp, DB_AM_CREATED_MSTR); + F_CLR(mdbp, DB_AM_DISCARD); + } + + /* + * The master's handle lock is under the control of the + * subdb (it acquired the master's locker. We want to + * keep the master's handle lock so that no one can remove + * the file while the subdb is open. If we register the + * trade event and then invalidate the copy of the lock + * in the master's handle, that will accomplish this. However, + * before we register this event, we'd better remove any + * events that we've already registered for the master. + */ + + if (!F_ISSET(dbp, DB_AM_RECOVER) && txn != NULL) { + /* Unregister old master events. */ + __txn_remlock(dbenv, + txn, &mdbp->handle_lock, DB_LOCK_INVALIDID); + + /* Now register the new event. */ + if ((ret = __txn_lockevent(dbenv, + txn, dbp, &mdbp->handle_lock, dbp->lid)) != 0) + goto err; + } + LOCK_INIT(mdbp->handle_lock); + return (__db_close_i(mdbp, txn, 0)); + +err: +DB_TEST_RECOVERY_LABEL + if (LOCK_ISSET(dbp->handle_lock) && txn == NULL) + __lock_put(dbenv, &dbp->handle_lock); + + /* If we created the master file then we need to remove it. */ + if (mdbp != NULL) { + do_remove = F_ISSET(mdbp, DB_AM_CREATED) ? 1 : 0; + if (do_remove) + F_SET(mdbp, DB_AM_DISCARD); + (void)__db_close_i(mdbp, txn, 0); + if (do_remove) { + (void)db_create(&mdbp, dbp->dbenv, 0); + (void)__db_remove_i(mdbp, txn, mname, NULL); + } + } + return (ret); +} + +/* + * __fop_remove_setup -- + * Open handle appropriately and lock for removal of a database file. + * + * PUBLIC: int __fop_remove_setup __P((DB *, + * PUBLIC: DB_TXN *, const char *, u_int32_t)); + */ +int +__fop_remove_setup(dbp, txn, name, flags) + DB *dbp; + DB_TXN *txn; + const char *name; + u_int32_t flags; +{ + DB_ENV *dbenv; + DB_LOCK elock; + u_int8_t mbuf[DBMETASIZE]; + int ret; + + COMPQUIET(flags, 0); + dbenv = dbp->dbenv; + PANIC_CHECK(dbenv); + LOCK_INIT(elock); + + /* Create locker if necessary. */ + if (LOCKING_ON(dbenv)) { + if (txn != NULL) + dbp->lid = txn->txnid; + else if (dbp->lid == DB_LOCK_INVALIDID) { + if ((ret = __lock_id(dbenv, &dbp->lid)) != 0) + goto err; + } + } + + /* + * Lock environment to protect file open. That will enable us to + * read the meta-data page and get the fileid so that we can lock + * the handle. + */ + GET_ENVLOCK(dbenv, dbp->lid, &elock); + if ((ret = __fop_read_meta(dbenv, + name, mbuf, sizeof(mbuf), NULL, 0, 0)) != 0) + goto err; + + if ((ret = + __db_meta_setup(dbenv, dbp, name, (DBMETA *)mbuf, flags, 1)) != 0) + goto err; + + /* Now, release the environment and get the handle lock. */ + if ((ret = __fop_lock_handle(dbenv, + dbp, dbp->lid, DB_LOCK_WRITE, &elock, 0)) != 0) + goto err; + + return (0); + +err: (void)REL_ENVLOCK(dbenv, &elock); + return (ret); +} + +/* + * __fop_read_meta -- + * Read the meta-data page from a file and return it in buf. The + * open file handle is returned in fhp. + * + * PUBLIC: int __fop_read_meta __P((DB_ENV *, + * PUBLIC: const char *, u_int8_t *, size_t, DB_FH *, int, u_int32_t)); + */ +int +__fop_read_meta(dbenv, name, buf, size, fhp, errok, flags) + DB_ENV *dbenv; + const char *name; + u_int8_t *buf; + size_t size; + DB_FH *fhp; + int errok; + u_int32_t flags; +{ + DB_FH fh, *lfhp; + size_t nr; + int ret; + + lfhp = fhp == NULL ? &fh : fhp; + memset(lfhp, 0, sizeof(*fhp)); + if ((ret = __os_open(dbenv, name, flags, 0, lfhp)) != 0) + goto err; + if ((ret = __os_read(dbenv, lfhp, buf, size, &nr)) != 0) { + if (!errok) + __db_err(dbenv, "%s: %s", name, db_strerror(ret)); + goto err; + } + + if (nr != size) { + if (!errok) + __db_err(dbenv, + "%s: unexpected file type or format", name); + ret = EINVAL; + goto err; + } + +err: /* + * On error, we always close the handle. If there is no error, + * then we only return the handle if the user didn't pass us + * a handle into which to return it. If fhp is valid, then + * lfhp is the same as fhp. + */ + if (F_ISSET(lfhp, DB_FH_VALID) && (ret != 0 || fhp == NULL)) + __os_closehandle(dbenv, lfhp); + return (ret); +} + +/* + * __fop_dummy -- + * This implements the creation and name swapping of dummy files that + * we use for remove and rename (remove is simply a rename with a delayed + * remove). + * + * PUBLIC: int __fop_dummy __P((DB *, + * PUBLIC: DB_TXN *, const char *, const char *, u_int32_t)); + */ +int +__fop_dummy(dbp, txn, old, new, flags) + DB *dbp; + DB_TXN *txn; + const char *old, *new; + u_int32_t flags; +{ + DB *tmpdbp; + DB_ENV *dbenv; + DB_LOCK elock; + DB_LSN lsn; + DBT fiddbt, namedbt, tmpdbt; + DB_TXN *stxn; + char *back; + char *realback, *realnew, *realold; + int ret, t_ret; + u_int8_t mbuf[DBMETASIZE]; + u_int32_t locker, stxnid; + + dbenv = dbp->dbenv; + LOCK_INIT(elock); + realback = NULL; + realnew = NULL; + realold = NULL; + back = NULL; + stxn = NULL; + tmpdbp = NULL; + + DB_ASSERT(txn != NULL); + locker = txn->txnid; + + /* Begin sub transaction to encapsulate the rename. */ + if (TXN_ON(dbenv) && + (ret = dbenv->txn_begin(dbenv, txn, &stxn, 0)) != 0) + goto err; + + /* We need to create a dummy file as a place holder. */ + if ((ret = __db_backup_name(dbenv, new, stxn, &back)) != 0) + goto err; + if ((ret = __db_appname(dbenv, + DB_APP_DATA, back, flags, NULL, &realback)) != 0) + goto err; + if ((ret = __fop_create(dbenv, stxn, NULL, back, DB_APP_DATA, 0)) != 0) + goto err; + + memset(mbuf, 0, sizeof(mbuf)); + if ((ret = + __os_fileid(dbenv, realback, 1, ((DBMETA *)mbuf)->uid)) != 0) + goto err; + ((DBMETA *)mbuf)->magic = DB_RENAMEMAGIC; + if ((ret = __fop_write(dbenv, + stxn, back, DB_APP_DATA, NULL, 0, mbuf, DBMETASIZE, 1)) != 0) + goto err; + + /* Create a dummy dbp handle. */ + if ((ret = db_create(&tmpdbp, dbenv, 0)) != 0) + goto err; + memcpy(&tmpdbp->fileid, ((DBMETA *)mbuf)->uid, DB_FILE_ID_LEN); + + /* Now, lock the name space while we initialize this file. */ + if ((ret = __db_appname(dbenv, + DB_APP_DATA, new, 0, NULL, &realnew)) != 0) + goto err; + GET_ENVLOCK(dbenv, locker, &elock); + if (__os_exists(realnew, NULL) == 0) { + ret = EEXIST; + goto err; + } + + /* + * While we have the namespace locked, do the renames and then + * swap for the handle lock. + */ + if ((ret = __fop_rename(dbenv, + stxn, old, new, dbp->fileid, DB_APP_DATA)) != 0) + goto err; + if ((ret = __fop_rename(dbenv, + stxn, back, old, tmpdbp->fileid, DB_APP_DATA)) != 0) + goto err; + if ((ret = __fop_lock_handle(dbenv, + tmpdbp, locker, DB_LOCK_WRITE, &elock, 0)) != 0) + goto err; + + /* + * We just acquired a transactional lock on the tmp handle. + * We need to null out the tmp handle's lock so that it + * doesn't create problems for us in the close path. + */ + LOCK_INIT(tmpdbp->handle_lock); + + if (stxn != NULL) { + /* Commit the child. */ + stxnid = stxn->txnid; + ret = stxn->commit(stxn, 0); + stxn = NULL; + + /* Now log the child information in the parent. */ + memset(&fiddbt, 0, sizeof(fiddbt)); + memset(&tmpdbt, 0, sizeof(fiddbt)); + memset(&namedbt, 0, sizeof(namedbt)); + fiddbt.data = dbp->fileid; + fiddbt.size = DB_FILE_ID_LEN; + tmpdbt.data = tmpdbp->fileid; + tmpdbt.size = DB_FILE_ID_LEN; + namedbt.data = (void *)old; + namedbt.size = (u_int32_t)strlen(old) + 1; + if ((t_ret = + __fop_file_remove_log(dbenv, txn, &lsn, 0, &fiddbt, + &tmpdbt, &namedbt, DB_APP_DATA, stxnid)) != 0 && ret == 0) + ret = t_ret; + } + + /* This is a delayed delete of the dummy file. */ + if ((ret = __db_appname(dbenv, + DB_APP_DATA, old, flags, NULL, &realold)) != 0) + goto err; + if ((ret = __txn_remevent(dbenv, txn, realold, NULL)) != 0) + goto err; + +err: (void)REL_ENVLOCK(dbenv, &elock); + if (stxn != NULL) + (void)stxn->abort(stxn); + if (tmpdbp != NULL && + (t_ret = __db_close_i(tmpdbp, NULL, 0)) != 0 && ret == 0) + ret = t_ret; + if (realold != NULL) + __os_free(dbenv, realold); + if (realnew != NULL) + __os_free(dbenv, realnew); + if (realback != NULL) + __os_free(dbenv, realback); + if (back != NULL) + __os_free(dbenv, back); + return (ret); +} + +/* + * __fop_dbrename -- + * Do the appropriate file locking and file system operations + * to effect a dbrename in the absence of transactions (__fop_dummy + * and the subsequent calls in __db_rename do the work for the + * transactional case). + * + * PUBLIC: int __fop_dbrename __P((DB *, const char *, const char *)); + */ +int +__fop_dbrename(dbp, old, new) + DB *dbp; + const char *old, *new; +{ + DB_ENV *dbenv; + DB_LOCK elock; + char *real_new, *real_old; + int ret, tret; + + dbenv = dbp->dbenv; + real_new = NULL; + real_old = NULL; + LOCK_INIT(elock); + + /* Find the real newname of the file. */ + if ((ret = __db_appname(dbenv, + DB_APP_DATA, new, 0, NULL, &real_new)) != 0) + goto err; + + /* + * It is an error to rename a file over one that already exists, + * as that wouldn't be transaction-safe. + */ + GET_ENVLOCK(dbenv, dbp->lid, &elock); + if (__os_exists(real_new, NULL) == 0) { + ret = EEXIST; + __db_err(dbenv, "rename: file %s exists", real_new); + goto err; + } + + if ((ret = __db_appname(dbenv, + DB_APP_DATA, old, 0, NULL, &real_old)) != 0) + goto err; + + ret = dbenv->memp_nameop(dbenv, dbp->fileid, new, real_old, real_new); + +err: if ((tret = REL_ENVLOCK(dbenv, &elock)) != 0 && ret == 0) + ret = tret; + if (real_old != NULL) + __os_free(dbenv, real_old); + if (real_new != NULL) + __os_free(dbenv, real_new); + return (ret); +} |