diff options
Diffstat (limited to 'db')
77 files changed, 5187 insertions, 1681 deletions
diff --git a/db/perl/BerkeleyDB/BerkeleyDB.pm b/db/perl/BerkeleyDB/BerkeleyDB.pm index e1ae757f8..9f145af80 100644 --- a/db/perl/BerkeleyDB/BerkeleyDB.pm +++ b/db/perl/BerkeleyDB/BerkeleyDB.pm @@ -2,7 +2,7 @@ package BerkeleyDB; -# Copyright (c) 1997-2001 Paul Marquess. All rights reserved. +# Copyright (c) 1997-2002 Paul Marquess. All rights reserved. # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. # @@ -14,14 +14,25 @@ BEGIN { require 5.004_04 } use strict; use Carp; -use vars qw($VERSION @ISA @EXPORT $AUTOLOAD); +use vars qw($VERSION @ISA @EXPORT $AUTOLOAD + $use_XSLoader); -$VERSION = '0.17'; +$VERSION = '0.19'; require Exporter; -require DynaLoader; +#require DynaLoader; require AutoLoader; -use IO ; + +BEGIN { + $use_XSLoader = 1 ; + { local $SIG{__DIE__} ; eval { require XSLoader } ; } + + if ($@) { + $use_XSLoader = 0 ; + require DynaLoader; + @ISA = qw(DynaLoader); + } +} @ISA = qw(Exporter DynaLoader); # Items to export into callers namespace by default. Note: do not export @@ -39,6 +50,7 @@ use IO ; DB_ARCH_ABS DB_ARCH_DATA DB_ARCH_LOG + DB_AUTO_COMMIT DB_BEFORE DB_BROADCAST_EID DB_BTREE @@ -48,6 +60,7 @@ use IO ; DB_CACHED_COUNTS DB_CDB_ALLDB DB_CHECKPOINT + DB_CHKSUM_SHA1 DB_CLIENT DB_CL_WRITER DB_COMMIT @@ -59,16 +72,26 @@ use IO ; DB_CXX_NO_EXCEPTIONS DB_DELETED DB_DELIMITER + DB_DIRECT + DB_DIRECT_DB + DB_DIRECT_LOG DB_DIRTY_READ DB_DONOTINDEX DB_DUP DB_DUPCURSOR DB_DUPSORT + DB_EID_BROADCAST + DB_EID_INVALID + DB_ENCRYPT + DB_ENCRYPT_AES DB_ENV_APPINIT DB_ENV_CDB DB_ENV_CDB_ALLDB DB_ENV_CREATE DB_ENV_DBLOCAL + DB_ENV_DIRECT_DB + DB_ENV_DIRECT_LOG + DB_ENV_FATAL DB_ENV_LOCKDOWN DB_ENV_LOCKING DB_ENV_LOGGING @@ -76,6 +99,7 @@ use IO ; DB_ENV_NOMMAP DB_ENV_NOPANIC DB_ENV_OPEN_CALLED + DB_ENV_OVERWRITE DB_ENV_PANIC_OK DB_ENV_PRIVATE DB_ENV_REGION_INIT @@ -89,6 +113,7 @@ use IO ; DB_ENV_THREAD DB_ENV_TXN DB_ENV_TXN_NOSYNC + DB_ENV_TXN_WRITE_NOSYNC DB_ENV_USER_ALLOC DB_ENV_YIELDCPU DB_EXCL @@ -105,6 +130,7 @@ use IO ; DB_GET_BOTHC DB_GET_BOTH_RANGE DB_GET_RECNO + DB_HANDLE_LOCK DB_HASH DB_HASHMAGIC DB_HASHOLDVER @@ -141,6 +167,7 @@ use IO ; DB_LOCK_MINLOCKS DB_LOCK_MINWRITE DB_LOCK_NORUN + DB_LOCK_NOTEXIST DB_LOCK_NOTGRANTED DB_LOCK_NOTHELD DB_LOCK_NOWAIT @@ -151,11 +178,13 @@ use IO ; DB_LOCK_PUT_READ DB_LOCK_RANDOM DB_LOCK_RECORD + DB_LOCK_REMOVE DB_LOCK_RIW_N DB_LOCK_RW_N DB_LOCK_SET_TIMEOUT DB_LOCK_SWITCH DB_LOCK_TIMEOUT + DB_LOCK_TRADE DB_LOCK_UPGRADE DB_LOCK_UPGRADE_WRITE DB_LOCK_YOUNGEST @@ -186,6 +215,7 @@ use IO ; DB_NEXT DB_NEXT_DUP DB_NEXT_NODUP + DB_NOCOPY DB_NODUPDATA DB_NOLOCKING DB_NOMMAP @@ -207,15 +237,23 @@ use IO ; DB_OPEN_CALLED DB_OPFLAGS_MASK DB_ORDERCHKONLY + DB_OVERWRITE DB_PAD DB_PAGEYIELD DB_PAGE_LOCK DB_PAGE_NOTFOUND DB_PANIC_ENVIRONMENT + DB_PERMANENT DB_POSITION DB_POSITIONI DB_PREV DB_PREV_NODUP + DB_PRINTABLE + DB_PRIORITY_DEFAULT + DB_PRIORITY_HIGH + DB_PRIORITY_LOW + DB_PRIORITY_VERY_HIGH + DB_PRIORITY_VERY_LOW DB_PRIVATE DB_PR_HEADERS DB_PR_PAGE @@ -237,6 +275,7 @@ use IO ; DB_REGION_MAGIC DB_REGION_NAME DB_REGISTERED + DB_RENAMEMAGIC DB_RENUMBER DB_REP_CLIENT DB_REP_DUPMASTER @@ -283,6 +322,7 @@ use IO ; DB_TEST_PREEXTUNLINK DB_TEST_PREOPEN DB_TEST_PRERENAME + DB_TEST_SUBDB_LOCKS DB_THREAD DB_TIMEOUT DB_TRUNCATE @@ -293,6 +333,8 @@ use IO ; DB_TXN_BACKWARD_ROLL DB_TXN_CKP DB_TXN_FORWARD_ROLL + DB_TXN_GETPGNOS + DB_TXN_LOCK DB_TXN_LOCK_2PL DB_TXN_LOCK_MASK DB_TXN_LOCK_OPTIMIST @@ -305,9 +347,11 @@ use IO ; DB_TXN_NOWAIT DB_TXN_OPENFILES DB_TXN_POPENFILES + DB_TXN_PRINT DB_TXN_REDO DB_TXN_SYNC DB_TXN_UNDO + DB_TXN_WRITE_NOSYNC DB_UNKNOWN DB_UNRESOLVED_CHILD DB_UPDATE_SECONDARY @@ -317,6 +361,7 @@ use IO ; DB_VERB_CHKPOINT DB_VERB_DEADLOCK DB_VERB_RECOVERY + DB_VERB_REPLICATION DB_VERB_WAITSFOR DB_VERIFY DB_VERIFY_BAD @@ -328,6 +373,8 @@ use IO ; DB_VRFY_FLAGMASK DB_WRITECURSOR DB_WRITELOCK + DB_WRITEOPEN + DB_WRNOSYNC DB_XA_CREATE DB_XIDDATASIZE DB_YIELDCPU @@ -343,7 +390,11 @@ sub AUTOLOAD { goto &{$AUTOLOAD}; } -bootstrap BerkeleyDB $VERSION; +#bootstrap BerkeleyDB $VERSION; +if ($use_XSLoader) + { XSLoader::load("BerkeleyDB", $VERSION)} +else + { bootstrap BerkeleyDB $VERSION } # Preloaded methods go here. @@ -407,15 +458,6 @@ sub env_remove Config => undef, }, @_) ; - if (defined $got->{ErrFile}) { - if (!isaFilehandle($got->{ErrFile})) { - my $handle = new IO::File ">$got->{ErrFile}" - or croak "Cannot open file $got->{ErrFile}: $!\n" ; - $got->{ErrFile} = $handle ; - } - } - - if (defined $got->{Config}) { croak("Config parameter must be a hash reference") if ! ref $got->{Config} eq 'HASH' ; @@ -452,6 +494,52 @@ sub db_remove return _db_remove($got); } +sub db_rename +{ + my $got = BerkeleyDB::ParseParameters( + { + Filename => undef, + Subname => undef, + Newname => undef, + Flags => 0, + Env => undef, + }, @_) ; + + croak("Env not of type BerkeleyDB::Env") + if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env'); + + croak("Must specify a filename") + if ! defined $got->{Filename} ; + + croak("Must specify a Subname") + if ! defined $got->{Subname} ; + + croak("Must specify a Newname") + if ! defined $got->{Newname} ; + + return _db_rename($got); +} + +sub db_verify +{ + my $got = BerkeleyDB::ParseParameters( + { + Filename => undef, + Subname => undef, + Outfile => undef, + Flags => 0, + Env => undef, + }, @_) ; + + croak("Env not of type BerkeleyDB::Env") + if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env'); + + croak("Must specify a filename") + if ! defined $got->{Filename} ; + + return _db_verify($got); +} + package BerkeleyDB::Env ; use UNIVERSAL qw( isa ) ; @@ -477,9 +565,10 @@ sub new # [ -Home => $path, ] # [ -Mode => mode, ] # [ -Config => { name => value, name => value } - # [ -ErrFile => filename or filehandle, ] + # [ -ErrFile => filename, ] # [ -ErrPrefix => "string", ] # [ -Flags => DB_INIT_LOCK| ] + # [ -Set_Flags => $flags,] # [ -Cachesize => number ] # [ -LockDetect => ] # [ -Verbose => boolean ] @@ -493,6 +582,7 @@ sub new ErrFile => undef, ErrPrefix => undef, Flags => 0, + SetFlags => 0, Cachesize => 0, LockDetect => 0, Verbose => 0, @@ -500,11 +590,13 @@ sub new }, @_) ; if (defined $got->{ErrFile}) { - if (!isaFilehandle($got->{ErrFile})) { - my $handle = new IO::File ">$got->{ErrFile}" - or croak "Cannot open file $got->{ErrFile}: $!\n" ; - $got->{ErrFile} = $handle ; - } + croak("ErrFile parameter must be a file name") + if ref $got->{ErrFile} ; + #if (!isaFilehandle($got->{ErrFile})) { + # my $handle = new IO::File ">$got->{ErrFile}" +# or croak "Cannot open file $got->{ErrFile}: $!\n" ; +# $got->{ErrFile} = $handle ; +# } } @@ -627,7 +719,8 @@ sub new if ($addr) { $obj = bless [$addr] , $self ; push @{ $obj }, $got->{Env} if $got->{Env} ; - $obj->Txn($got->{Txn}) if $got->{Txn} ; + $obj->Txn($got->{Txn}) + if $got->{Txn} ; } return $obj ; } @@ -682,7 +775,8 @@ sub new if ($addr) { $obj = bless [$addr] , $self ; push @{ $obj }, $got->{Env} if $got->{Env} ; - $obj->Txn($got->{Txn}) if $got->{Txn} ; + $obj->Txn($got->{Txn}) + if $got->{Txn} ; } return $obj ; } @@ -744,7 +838,8 @@ sub new if ($addr) { $obj = bless [$addr] , $self ; push @{ $obj }, $got->{Env} if $got->{Env} ; - $obj->Txn($got->{Txn}) if $got->{Txn} ; + $obj->Txn($got->{Txn}) + if $got->{Txn} ; } return $obj ; } @@ -804,7 +899,8 @@ sub new if ($addr) { $obj = bless [$addr] , $self ; push @{ $obj }, $got->{Env} if $got->{Env} ; - $obj->Txn($got->{Txn}) if $got->{Txn} ; + $obj->Txn($got->{Txn}) + if $got->{Txn} ; } return $obj ; } @@ -910,7 +1006,8 @@ sub new if ($addr) { $obj = bless [$addr], "BerkeleyDB::$type" ; push @{ $obj }, $got->{Env} if $got->{Env} ; - $obj->Txn($got->{Txn}) if $got->{Txn} ; + $obj->Txn($got->{Txn}) + if $got->{Txn} ; } return $obj ; } diff --git a/db/perl/BerkeleyDB/BerkeleyDB.pod b/db/perl/BerkeleyDB/BerkeleyDB.pod index a6c18c82a..60f30e2ab 100644 --- a/db/perl/BerkeleyDB/BerkeleyDB.pod +++ b/db/perl/BerkeleyDB/BerkeleyDB.pod @@ -1,6 +1,6 @@ =head1 NAME -BerkeleyDB - Perl extension for Berkeley DB version 2 or 3 +BerkeleyDB - Perl extension for Berkeley DB version 2, 3 or 4 =head1 SYNOPSIS @@ -23,6 +23,8 @@ BerkeleyDB - Perl extension for Berkeley DB version 2 or 3 $db = new BerkeleyDB::Unknown [OPTIONS] ; $status = BerkeleyDB::db_remove [OPTIONS] + $status = BerkeleyDB::db_rename [OPTIONS] + $status = BerkeleyDB::db_verify [OPTIONS] $hash{$key} = $value ; $value = $hash{$key} ; @@ -35,11 +37,14 @@ BerkeleyDB - Perl extension for Berkeley DB version 2 or 3 $status = $db->db_del() ; $status = $db->db_sync() ; $status = $db->db_close() ; + $status = $db->db_close() ; + $status = $db->db_pget() $hash_ref = $db->db_stat() ; $status = $db->db_key_range(); $type = $db->type() ; $status = $db->status() ; $boolean = $db->byteswapped() ; + $status = $db->truncate($count) ; ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ; ($flag, $old_offset, $old_length) = $db->partial_clear() ; @@ -50,6 +55,7 @@ BerkeleyDB - Perl extension for Berkeley DB version 2 or 3 $status = $cursor->c_put() ; $status = $cursor->c_del() ; $status = $cursor->c_count() ; + $status = $cursor->c_pget() ; $status = $cursor->status() ; $status = $cursor->c_close() ; @@ -60,6 +66,7 @@ BerkeleyDB - Perl extension for Berkeley DB version 2 or 3 $status = $env->txn_checkpoint() $hash_ref = $env->txn_stat() $status = $env->setmutexlocks() + $status = $env->set_flags() $txn = $env->txn_begin() ; $db->Txn($txn); @@ -76,6 +83,7 @@ BerkeleyDB - Perl extension for Berkeley DB version 2 or 3 $status = $env->set_data_dir() ; $status = $env->set_tmp_dir() ; + $status = $env->set_verbose() ; $BerkeleyDB::Error $BerkeleyDB::db_version @@ -98,11 +106,12 @@ B<NOTE: This document is still under construction. Expect it to be incomplete in places.> This Perl module provides an interface to most of the functionality -available in Berkeley DB versions 2 and 3. In general it is safe to assume +available in Berkeley DB versions 2, 3 and 4. In general it is safe to assume that the interface provided here to be identical to the Berkeley DB interface. The main changes have been to make the Berkeley DB API work in a Perl way. Note that if you are using Berkeley DB 2.x, the new -features available in Berkeley DB 3.x are not available via this module. +features available in Berkeley DB 3.x or DB 4.x are not available via +this module. The reader is expected to be familiar with the Berkeley DB documentation. Where the interface provided here is identical to the @@ -118,7 +127,7 @@ classes. The B<BerkeleyDB::Env> class provides an interface to the Berkeley DB function B<db_appinit> in Berkeley DB 2.x or B<db_env_create> and -B<DBENV-E<gt>open> in Berkeley DB 3.x. Its purpose is to initialise a +B<DBENV-E<gt>open> in Berkeley DB 3.x/4.x. Its purpose is to initialise a number of sub-systems that can then be used in a consistent way in all the databases you make use of the environment. @@ -132,9 +141,10 @@ shouldn't need to make use of B<BerkeleyDB::Env>. [ -Server => $name, ] [ -CacheSize => $number, ] [ -Config => { name => value, name => value }, ] - [ -ErrFile => filename or filehandle, ] + [ -ErrFile => filename, ] [ -ErrPrefix => "string", ] [ -Flags => number, ] + [ -SetFlags => bitmask, ] [ -LockDetect => number, ] [ -Verbose => boolean, ] @@ -197,8 +207,8 @@ The code below shows an example of how it can be used. =item -ErrFile -Expects either the name of a file or a reference to a filehandle. Any -errors generated internally by Berkeley DB will be logged to this file. +Expects a filenme. Any errors generated internally by Berkeley DB will +be logged to this file. =item -ErrPrefix @@ -263,6 +273,13 @@ B<DB_USE_ENVIRON> B<DB_USE_ENVIRON_ROOT> +=item -SetFlags + +Calls ENV->set_flags with the supplied bitmask. Use this when you need to make +use of DB_ENV->set_flags before DB_ENV->open is called. + +Only valid when Berkeley DB 3.x or better is used. + =item -LockDetect Specifies what to do when a lock conflict occurs. The value should be one of @@ -292,6 +309,8 @@ The environment class has the following methods: This method is identical to the B<-ErrPrefix> flag. It allows the error prefix string to be changed dynamically. +=item $env->set_flags(bitmask, 1|0); + =item $txn = $env->TxnMgr() Constructor for creating a B<TxnMgr> object. @@ -328,6 +347,12 @@ Berkeley DB 3.0 or 3.2 and better it calls B<DBENV-E<gt>set_mutexlocks>. TODO. +=head1 Global Classes + + $status = BerkeleyDB::db_remove [OPTIONS] + $status = BerkeleyDB::db_rename [OPTIONS] + $status = BerkeleyDB::db_verify [OPTIONS] + =head1 THE DATABASE CLASSES B<BerkeleyDB> supports the following database formats: @@ -381,7 +406,7 @@ the next sections. Equivalent to calling B<db_open> with type B<DB_HASH> in Berkeley DB 2.x and calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_HASH> in -Berkeley DB 3.x. +Berkeley DB 3.x or greater. Two forms of constructor are supported: @@ -690,7 +715,7 @@ TODO Equivalent to calling B<db_open> with type B<DB_BTREE> in Berkeley DB 2.x and calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_BTREE> in -Berkeley DB 3.x. +Berkeley DB 3.x or greater. Two forms of constructor are supported: @@ -938,7 +963,7 @@ TODO Equivalent to calling B<db_open> with type B<DB_RECNO> in Berkeley DB 2.x and calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_RECNO> in -Berkeley DB 3.x. +Berkeley DB 3.x or greater. Two forms of constructor are supported: @@ -1031,8 +1056,8 @@ Here is the output from the script: =head1 BerkeleyDB::Queue Equivalent to calling B<db_create> followed by B<DB-E<gt>open> with -type B<DB_QUEUE> in Berkeley DB 3.x. This database format isn't available if -you use Berkeley DB 2.x. +type B<DB_QUEUE> in Berkeley DB 3.x or greater. This database format +isn't available if you use Berkeley DB 2.x. Two forms of constructor are supported: @@ -1076,7 +1101,7 @@ This class is used to open an existing database. Equivalent to calling B<db_open> with type B<DB_UNKNOWN> in Berkeley DB 2.x and calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_UNKNOWN> in -Berkeley DB 3.x. +Berkeley DB 3.x or greater. The constructor looks like this: @@ -1110,7 +1135,7 @@ be created and removed once the program terminates. =item -Subname Specifies the name of the sub-database to open. -This option is only valid if you are using Berkeley DB 3.x. +This option is only valid if you are using Berkeley DB 3.x or greater. =item -Flags @@ -1286,13 +1311,19 @@ equivalent field would be accessed as follows: $version = $ref->{'bt_version'} ; -If you are using Berkeley DB 3.x, this method will work will all database -formats. When DB 2.x is used, it only works with B<BerkeleyDB::Btree>. +If you are using Berkeley DB 3.x or better, this method will work will +all database formats. When DB 2.x is used, it only works with +B<BerkeleyDB::Btree>. =head2 $status = $db->status() Returns the status of the last C<$db> method called. +=head2 $status = $db->truncate($count) + +Truncates the datatabase and returns the number or records deleted +in C<$count>. + =head1 CURSORS A cursor is used whenever you want to access the contents of a database @@ -1700,10 +1731,10 @@ I get asked. Before Berkeley DB 2.x was written there was only one Perl module that interfaced to Berkeley DB. That module is called B<DB_File>. Although -B<DB_File> can be build with Berkeley DB 1.x, 2.x or 3.x, it only provides +B<DB_File> can be build with Berkeley DB 1.x, 2.x, 3.x or 4.x, it only provides an interface to the functionality available in Berkeley DB 1.x. That means that it doesn't support transactions, locking or any of the other -new features available in DB 2.x or 3.x. +new features available in DB 2.x or better. =head2 How do I store Perl data structures with BerkeleyDB? @@ -1723,7 +1754,7 @@ The official web site for Berkeley DB is F<http://www.sleepycat.com>. =head1 COPYRIGHT -Copyright (c) 1997-2001 Paul Marquess. All rights reserved. This program +Copyright (c) 1997-2002 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. diff --git a/db/perl/BerkeleyDB/BerkeleyDB.pod.P b/db/perl/BerkeleyDB/BerkeleyDB.pod.P index 644cdb931..4a848f538 100644 --- a/db/perl/BerkeleyDB/BerkeleyDB.pod.P +++ b/db/perl/BerkeleyDB/BerkeleyDB.pod.P @@ -1,6 +1,6 @@ =head1 NAME -BerkeleyDB - Perl extension for Berkeley DB version 2 or 3 +BerkeleyDB - Perl extension for Berkeley DB version 2, 3 or 4 =head1 SYNOPSIS @@ -23,6 +23,8 @@ BerkeleyDB - Perl extension for Berkeley DB version 2 or 3 $db = new BerkeleyDB::Unknown [OPTIONS] ; $status = BerkeleyDB::db_remove [OPTIONS] + $status = BerkeleyDB::db_rename [OPTIONS] + $status = BerkeleyDB::db_verify [OPTIONS] $hash{$key} = $value ; $value = $hash{$key} ; @@ -35,11 +37,14 @@ BerkeleyDB - Perl extension for Berkeley DB version 2 or 3 $status = $db->db_del() ; $status = $db->db_sync() ; $status = $db->db_close() ; + $status = $db->db_close() ; + $status = $db->db_pget() $hash_ref = $db->db_stat() ; $status = $db->db_key_range(); $type = $db->type() ; $status = $db->status() ; $boolean = $db->byteswapped() ; + $status = $db->truncate($count) ; ($flag, $old_offset, $old_length) = $db->partial_set($offset, $length) ; ($flag, $old_offset, $old_length) = $db->partial_clear() ; @@ -50,6 +55,7 @@ BerkeleyDB - Perl extension for Berkeley DB version 2 or 3 $status = $cursor->c_put() ; $status = $cursor->c_del() ; $status = $cursor->c_count() ; + $status = $cursor->c_pget() ; $status = $cursor->status() ; $status = $cursor->c_close() ; @@ -60,6 +66,7 @@ BerkeleyDB - Perl extension for Berkeley DB version 2 or 3 $status = $env->txn_checkpoint() $hash_ref = $env->txn_stat() $status = $env->setmutexlocks() + $status = $env->set_flags() $txn = $env->txn_begin() ; $db->Txn($txn); @@ -76,6 +83,7 @@ BerkeleyDB - Perl extension for Berkeley DB version 2 or 3 $status = $env->set_data_dir() ; $status = $env->set_tmp_dir() ; + $status = $env->set_verbose() ; $BerkeleyDB::Error $BerkeleyDB::db_version @@ -98,11 +106,12 @@ B<NOTE: This document is still under construction. Expect it to be incomplete in places.> This Perl module provides an interface to most of the functionality -available in Berkeley DB versions 2 and 3. In general it is safe to assume +available in Berkeley DB versions 2, 3 and 4. In general it is safe to assume that the interface provided here to be identical to the Berkeley DB interface. The main changes have been to make the Berkeley DB API work in a Perl way. Note that if you are using Berkeley DB 2.x, the new -features available in Berkeley DB 3.x are not available via this module. +features available in Berkeley DB 3.x or DB 4.x are not available via +this module. The reader is expected to be familiar with the Berkeley DB documentation. Where the interface provided here is identical to the @@ -118,7 +127,7 @@ classes. The B<BerkeleyDB::Env> class provides an interface to the Berkeley DB function B<db_appinit> in Berkeley DB 2.x or B<db_env_create> and -B<DBENV-E<gt>open> in Berkeley DB 3.x. Its purpose is to initialise a +B<DBENV-E<gt>open> in Berkeley DB 3.x/4.x. Its purpose is to initialise a number of sub-systems that can then be used in a consistent way in all the databases you make use of the environment. @@ -132,9 +141,10 @@ shouldn't need to make use of B<BerkeleyDB::Env>. [ -Server => $name, ] [ -CacheSize => $number, ] [ -Config => { name => value, name => value }, ] - [ -ErrFile => filename or filehandle, ] + [ -ErrFile => filename, ] [ -ErrPrefix => "string", ] [ -Flags => number, ] + [ -SetFlags => bitmask, ] [ -LockDetect => number, ] [ -Verbose => boolean, ] @@ -197,8 +207,8 @@ The code below shows an example of how it can be used. =item -ErrFile -Expects either the name of a file or a reference to a filehandle. Any -errors generated internally by Berkeley DB will be logged to this file. +Expects a filenme. Any errors generated internally by Berkeley DB will +be logged to this file. =item -ErrPrefix @@ -263,6 +273,13 @@ B<DB_USE_ENVIRON> B<DB_USE_ENVIRON_ROOT> +=item -SetFlags + +Calls ENV->set_flags with the supplied bitmask. Use this when you need to make +use of DB_ENV->set_flags before DB_ENV->open is called. + +Only valid when Berkeley DB 3.x or better is used. + =item -LockDetect Specifies what to do when a lock conflict occurs. The value should be one of @@ -292,6 +309,8 @@ The environment class has the following methods: This method is identical to the B<-ErrPrefix> flag. It allows the error prefix string to be changed dynamically. +=item $env->set_flags(bitmask, 1|0); + =item $txn = $env->TxnMgr() Constructor for creating a B<TxnMgr> object. @@ -328,6 +347,12 @@ Berkeley DB 3.0 or 3.2 and better it calls B<DBENV-E<gt>set_mutexlocks>. TODO. +=head1 Global Classes + + $status = BerkeleyDB::db_remove [OPTIONS] + $status = BerkeleyDB::db_rename [OPTIONS] + $status = BerkeleyDB::db_verify [OPTIONS] + =head1 THE DATABASE CLASSES B<BerkeleyDB> supports the following database formats: @@ -381,7 +406,7 @@ the next sections. Equivalent to calling B<db_open> with type B<DB_HASH> in Berkeley DB 2.x and calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_HASH> in -Berkeley DB 3.x. +Berkeley DB 3.x or greater. Two forms of constructor are supported: @@ -582,7 +607,7 @@ TODO Equivalent to calling B<db_open> with type B<DB_BTREE> in Berkeley DB 2.x and calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_BTREE> in -Berkeley DB 3.x. +Berkeley DB 3.x or greater. Two forms of constructor are supported: @@ -777,7 +802,7 @@ TODO Equivalent to calling B<db_open> with type B<DB_RECNO> in Berkeley DB 2.x and calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_RECNO> in -Berkeley DB 3.x. +Berkeley DB 3.x or greater. Two forms of constructor are supported: @@ -837,8 +862,8 @@ Here is the output from the script: =head1 BerkeleyDB::Queue Equivalent to calling B<db_create> followed by B<DB-E<gt>open> with -type B<DB_QUEUE> in Berkeley DB 3.x. This database format isn't available if -you use Berkeley DB 2.x. +type B<DB_QUEUE> in Berkeley DB 3.x or greater. This database format +isn't available if you use Berkeley DB 2.x. Two forms of constructor are supported: @@ -882,7 +907,7 @@ This class is used to open an existing database. Equivalent to calling B<db_open> with type B<DB_UNKNOWN> in Berkeley DB 2.x and calling B<db_create> followed by B<DB-E<gt>open> with type B<DB_UNKNOWN> in -Berkeley DB 3.x. +Berkeley DB 3.x or greater. The constructor looks like this: @@ -916,7 +941,7 @@ be created and removed once the program terminates. =item -Subname Specifies the name of the sub-database to open. -This option is only valid if you are using Berkeley DB 3.x. +This option is only valid if you are using Berkeley DB 3.x or greater. =item -Flags @@ -1092,13 +1117,19 @@ equivalent field would be accessed as follows: $version = $ref->{'bt_version'} ; -If you are using Berkeley DB 3.x, this method will work will all database -formats. When DB 2.x is used, it only works with B<BerkeleyDB::Btree>. +If you are using Berkeley DB 3.x or better, this method will work will +all database formats. When DB 2.x is used, it only works with +B<BerkeleyDB::Btree>. =head2 $status = $db->status() Returns the status of the last C<$db> method called. +=head2 $status = $db->truncate($count) + +Truncates the datatabase and returns the number or records deleted +in C<$count>. + =head1 CURSORS A cursor is used whenever you want to access the contents of a database @@ -1467,10 +1498,10 @@ I get asked. Before Berkeley DB 2.x was written there was only one Perl module that interfaced to Berkeley DB. That module is called B<DB_File>. Although -B<DB_File> can be build with Berkeley DB 1.x, 2.x or 3.x, it only provides +B<DB_File> can be build with Berkeley DB 1.x, 2.x, 3.x or 4.x, it only provides an interface to the functionality available in Berkeley DB 1.x. That means that it doesn't support transactions, locking or any of the other -new features available in DB 2.x or 3.x. +new features available in DB 2.x or better. =head2 How do I store Perl data structures with BerkeleyDB? @@ -1490,7 +1521,7 @@ The official web site for Berkeley DB is F<http://www.sleepycat.com>. =head1 COPYRIGHT -Copyright (c) 1997-2001 Paul Marquess. All rights reserved. This program +Copyright (c) 1997-2002 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. diff --git a/db/perl/BerkeleyDB/BerkeleyDB.xs b/db/perl/BerkeleyDB/BerkeleyDB.xs index 5a26166bd..47ca6165a 100644 --- a/db/perl/BerkeleyDB/BerkeleyDB.xs +++ b/db/perl/BerkeleyDB/BerkeleyDB.xs @@ -6,7 +6,7 @@ All comments/suggestions/problems are welcome - Copyright (c) 1997-2001 Paul Marquess. All rights reserved. + Copyright (c) 1997-2002 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. @@ -23,10 +23,29 @@ #ifdef __cplusplus extern "C" { #endif + #define PERL_POLLUTE #include "EXTERN.h" #include "perl.h" #include "XSUB.h" +#include "ppport.h" + + +/* XSUB.h defines a macro called abort */ +/* This clashes with the txn abort method in Berkeley DB 4.x */ +/* This is a problem with ActivePerl (at least) */ + +#ifdef _WIN32 +# ifdef abort +# undef abort +# endif +# ifdef fopen +# undef fopen +# endif +# ifdef fclose +# undef fclose +# endif +#endif /* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be * shortly #included by the <db.h>) __attribute__ to the possibly @@ -34,28 +53,29 @@ extern "C" { #undef __attribute__ -#ifndef PERL_VERSION -# include "patchlevel.h" -# define PERL_REVISION 5 -# define PERL_VERSION PATCHLEVEL -# define PERL_SUBVERSION SUBVERSION +#ifdef USE_PERLIO +# define GetFILEptr(sv) PerlIO_findFILE(IoOFP(sv_2io(sv))) +#else +# define GetFILEptr(sv) IoOFP(sv_2io(sv)) #endif -#if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 )) +#include <db.h> -# define PL_sv_undef sv_undef -# define PL_na na -# define PL_dirty dirty +/* Check the version of Berkeley DB */ +#ifndef DB_VERSION_MAJOR +#ifdef HASHMAGIC +#error db.h is from Berkeley DB 1.x - need at least Berkeley DB 2.6.4 +#else +#error db.h is not for Berkeley DB at all. +#endif #endif -#ifdef USE_PERLIO -# define GetFILEptr(sv) PerlIO_findFILE(IoOFP(sv_2io(sv))) -#else -# define GetFILEptr(sv) IoOFP(sv_2io(sv)) +#if (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6) ||\ + (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 6 && DB_VERSION_PATCH < 4) +# error db.h is from Berkeley DB 2.0-2.5 - need at least Berkeley DB 2.6.4 #endif -#include <db.h> #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0) # define IS_DB_3_0_x @@ -87,38 +107,10 @@ extern "C" { # define AT_LEAST_DB_4 #endif -/* need to define DEFSV & SAVE_DEFSV for older version of Perl */ -#ifndef DEFSV -# define DEFSV GvSV(defgv) -#endif - -#ifndef SAVE_DEFSV -# define SAVE_DEFSV SAVESPTR(GvSV(defgv)) -#endif - -#ifndef pTHX -# define pTHX -# define pTHX_ -# define aTHX -# define aTHX_ -#endif - -#ifndef dTHR -# define dTHR -#endif - -#ifndef newSVpvn -# define newSVpvn(a,b) newSVpv(a,b) +#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1) +# define AT_LEAST_DB_4_1 #endif -#ifndef PTR2IV -# define PTR2IV(d) (IV)(d) -#endif /* PTR2IV */ - -#ifndef INT2PTR -# define INT2PTR(any,d) (any)(d) -#endif /* INT2PTR */ - #ifdef __cplusplus } #endif @@ -183,7 +175,7 @@ typedef struct { int Status ; /* char ErrBuff[1000] ; */ SV * ErrPrefix ; - SV * ErrHandle ; + FILE * ErrHandle ; DB_ENV * Env ; int open_dbs ; int TxnMgrStatus ; @@ -199,9 +191,17 @@ typedef struct { BerkeleyDB_ENV_type * parent_env ; DB * dbp ; SV * compare ; + bool in_compare ; SV * dup_compare ; + bool in_dup_compare ; SV * prefix ; + bool in_prefix ; SV * hash ; + bool in_hash ; +#ifdef AT_LEAST_DB_3_3 + SV * associated ; + bool secondary_db ; +#endif int Status ; DB_INFO * info ; DBC * cursor ; @@ -233,6 +233,10 @@ typedef struct { SV * dup_compare ; SV * prefix ; SV * hash ; +#ifdef AT_LEAST_DB_3_3 + SV * associated ; + bool secondary_db ; +#endif int Status ; DB_INFO * info ; DBC * cursor ; @@ -333,6 +337,16 @@ hash_delete(char * hash, char * key); # define flagSet(bitmask) ((flags & DB_OPFLAGS_MASK) == (bitmask)) #endif +#if DB_VERSION_MAJOR == 2 +# define BackRef internal +#else +# if DB_VERSION_MAJOR == 3 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0) +# define BackRef cj_internal +# else +# define BackRef api_internal +# endif +#endif + #ifdef DBM_FILTERING #define ckFilter(arg,type,name) \ if (db->type) { \ @@ -472,6 +486,7 @@ hash_delete(char * hash, char * key); static db_recno_t Value ; static db_recno_t zero = 0 ; static BerkeleyDB CurrentDB ; + static DBTKEY empty ; #if 0 static char ErrBuff[1000] ; @@ -685,6 +700,10 @@ destroyDB(BerkeleyDB db) SvREFCNT_dec(db->compare) ; if (db->dup_compare) SvREFCNT_dec(db->dup_compare) ; +#ifdef AT_LEAST_DB_3_3 + if (db->associated && !db->secondary_db) + SvREFCNT_dec(db->associated) ; +#endif if (db->prefix) SvREFCNT_dec(db->prefix) ; #ifdef DBM_FILTERING @@ -847,6 +866,7 @@ btree_compare(DB_callback const DBT * key1, const DBT * key2 ) char * data1, * data2 ; int retval ; int count ; + BerkeleyDB keepDB = CurrentDB ; data1 = (char*) key1->data ; data2 = (char*) key2->data ; @@ -883,6 +903,7 @@ btree_compare(DB_callback const DBT * key1, const DBT * key2 ) PUTBACK ; FREETMPS ; LEAVE ; + CurrentDB = keepDB ; return (retval) ; } @@ -894,6 +915,7 @@ dup_compare(DB_callback const DBT * key1, const DBT * key2 ) char * data1, * data2 ; int retval ; int count ; + BerkeleyDB keepDB = CurrentDB ; Trace(("In dup_compare \n")) ; if (!CurrentDB) @@ -936,6 +958,7 @@ dup_compare(DB_callback const DBT * key1, const DBT * key2 ) PUTBACK ; FREETMPS ; LEAVE ; + CurrentDB = keepDB ; return (retval) ; } @@ -947,6 +970,7 @@ btree_prefix(DB_callback const DBT * key1, const DBT * key2 ) char * data1, * data2 ; int retval ; int count ; + BerkeleyDB keepDB = CurrentDB ; data1 = (char*) key1->data ; data2 = (char*) key2->data ; @@ -983,6 +1007,7 @@ btree_prefix(DB_callback const DBT * key1, const DBT * key2 ) PUTBACK ; FREETMPS ; LEAVE ; + CurrentDB = keepDB ; return (retval) ; } @@ -993,6 +1018,7 @@ hash_cb(DB_callback const void * data, u_int32_t size) dSP ; int retval ; int count ; + BerkeleyDB keepDB = CurrentDB ; #ifndef newSVpvn if (size == 0) @@ -1019,10 +1045,84 @@ hash_cb(DB_callback const void * data, u_int32_t size) PUTBACK ; FREETMPS ; LEAVE ; + CurrentDB = keepDB ; return (retval) ; } +#ifdef AT_LEAST_DB_3_3 + +static int +associate_cb(DB_callback const DBT * pkey, const DBT * pdata, DBT * skey) +{ + dSP ; + char * pk_dat, * pd_dat, *sk_dat ; + int retval ; + int count ; + SV * skey_SV ; + + Trace(("In associate_cb \n")) ; + if (((BerkeleyDB)db->BackRef)->associated == NULL){ + Trace(("No Callback registered\n")) ; + return EINVAL ; + } + + skey_SV = newSVpv("",0); + + + pk_dat = (char*) pkey->data ; + pd_dat = (char*) pdata->data ; + +#ifndef newSVpvn + /* As newSVpv will assume that the data pointer is a null terminated C + string if the size parameter is 0, make sure that data points to an + empty string if the length is 0 + */ + if (pkey->size == 0) + pk_dat = "" ; + if (pdata->size == 0) + pd_dat = "" ; +#endif + + ENTER ; + SAVETMPS; + + PUSHMARK(SP) ; + EXTEND(SP,2) ; + PUSHs(sv_2mortal(newSVpvn(pk_dat,pkey->size))); + PUSHs(sv_2mortal(newSVpvn(pd_dat,pdata->size))); + PUSHs(sv_2mortal(skey_SV)); + PUTBACK ; + + Trace(("calling associated cb\n")); + count = perl_call_sv(((BerkeleyDB)db->BackRef)->associated, G_SCALAR); + Trace(("called associated cb\n")); + + SPAGAIN ; + + if (count != 1) + softCrash ("associate: expected 1 return value from prefix sub, got %d", count) ; + + retval = POPi ; + + PUTBACK ; + + /* retrieve the secondary key */ + DBT_clear(*skey); + skey->flags = DB_DBT_APPMALLOC; + skey->size = SvCUR(skey_SV); + skey->data = (char*)safemalloc(skey->size); + memcpy(skey->data, SvPVX(skey_SV), skey->size); + Trace(("key is %d -- %.*s\n", skey->size, skey->size, skey->data)); + + FREETMPS ; + LEAVE ; + + return (retval) ; +} + +#endif /* AT_LEAST_DB_3_3 */ + static void db_errcall_cb(const char * db_errpfx, char * buffer) { @@ -1089,6 +1189,7 @@ my_db_open( SV * ref, SV * ref_dbenv , BerkeleyDB__Env dbenv , + BerkeleyDB__Txn txn, const char * file, const char * subname, DBTYPE type, @@ -1101,14 +1202,21 @@ my_db_open( BerkeleyDB RETVAL = NULL ; DB * dbp ; int Status ; + DB_TXN* txnid = NULL ; - Trace(("_db_open(dbenv[%lu] ref_dbenv [%lu] file[%s] subname [%s] type[%d] flags[%d] mode[%d]\n", + Trace(("_db_open(dbenv[%p] ref_dbenv [%p] file[%s] subname [%s] type[%d] flags[%d] mode[%d]\n", dbenv, ref_dbenv, file, subname, type, flags, mode)) ; CurrentDB = db ; if (dbenv) env = dbenv->Env ; + if (txn) + txnid = txn->txn; + + Trace(("_db_open(dbenv[%p] ref_dbenv [%p] txn [%p] file[%s] subname [%s] type[%d] flags[%d] mode[%d]\n", + dbenv, ref_dbenv, txn, file, subname, type, flags, mode)) ; + #if DB_VERSION_MAJOR == 2 if (subname) softCrash("Subname needs Berkeley DB 3 or better") ; @@ -1120,6 +1228,13 @@ my_db_open( if (Status) return RETVAL ; +#ifdef AT_LEAST_DB_3_3 + if (! env) { + dbp->set_alloc(dbp, safemalloc, MyRealloc, safefree) ; + dbp->set_errcall(dbp, db_errcall_cb) ; + } +#endif + if (info->re_source) { Status = dbp->set_re_source(dbp, info->re_source) ; Trace(("set_re_source [%s] returned %s\n", @@ -1178,7 +1293,7 @@ my_db_open( if (info->bt_compare) { Status = dbp->set_bt_compare(dbp, info->bt_compare) ; - Trace(("set_bt_compare [%d] returned %s\n", + Trace(("set_bt_compare [%p] returned %s\n", info->bt_compare, my_db_strerror(Status))); if (Status) return RETVAL ; @@ -1252,17 +1367,22 @@ my_db_open( #endif } +#ifdef AT_LEAST_DB_4_1 + if ((Status = (dbp->open)(dbp, txnid, file, subname, type, flags, mode)) == 0) { +#else if ((Status = (dbp->open)(dbp, file, subname, type, flags, mode)) == 0) { +#endif /* AT_LEAST_DB_4_1 */ #else /* DB_VERSION_MAJOR == 2 */ if ((Status = db_open(file, type, flags, mode, env, info, &dbp)) == 0) { #endif /* DB_VERSION_MAJOR == 2 */ Trace(("db_opened ok\n")); - RETVAL = db ; #ifdef AT_LEAST_DB_3_3 - dbp->set_alloc(dbp, safemalloc, MyRealloc, safefree) ; + dbp->BackRef = db; #endif + RETVAL = db ; RETVAL->dbp = dbp ; + RETVAL->txn = txnid ; #if DB_VERSION_MAJOR == 2 RETVAL->type = dbp->type ; #else /* DB_VERSION_MAJOR > 2 */ @@ -1278,7 +1398,7 @@ my_db_open( RETVAL->Status = Status ; RETVAL->active = TRUE ; hash_store_iv("BerkeleyDB::Term::Db", (char *)RETVAL, 1) ; - Trace((" storing %d %d in BerkeleyDB::Term::Db\n", RETVAL, dbp)) ; + Trace((" storing %p %p in BerkeleyDB::Term::Db\n", RETVAL, dbp)) ; if (dbenv) { RETVAL->parent_env = dbenv ; dbenv->Status = Status ; @@ -1355,6 +1475,87 @@ _db_remove(ref) OUTPUT: RETVAL +DualType +_db_verify(ref) + SV * ref + CODE: + { +#ifndef AT_LEAST_DB_3_1 + softCrash("BerkeleyDB::db_verify needs Berkeley DB 3.1.x or better") ; +#else + HV * hash ; + DB * dbp ; + SV * sv ; + const char * db = NULL ; + const char * subdb = NULL ; + const char * outfile = NULL ; + FILE * ofh = NULL; + BerkeleyDB__Env env = NULL ; + DB_ENV * dbenv = NULL ; + u_int32_t flags = 0 ; + + hash = (HV*) SvRV(ref) ; + SetValue_pv(db, "Filename", char *) ; + SetValue_pv(subdb, "Subname", char *) ; + SetValue_pv(outfile, "Outfile", char *) ; + SetValue_iv(flags, "Flags") ; + SetValue_ov(env, "Env", BerkeleyDB__Env) ; + RETVAL = 0; + if (outfile){ + ofh = fopen(outfile, "w"); + if (! ofh) + RETVAL = errno; + } + if (! RETVAL) { + if (env) + dbenv = env->Env ; + RETVAL = db_create(&dbp, dbenv, 0) ; + if (RETVAL == 0) { + RETVAL = dbp->verify(dbp, db, subdb, ofh, flags) ; + } + if (outfile) + fclose(ofh); + } +#endif + } + OUTPUT: + RETVAL + +DualType +_db_rename(ref) + SV * ref + CODE: + { +#ifndef AT_LEAST_DB_3_1 + softCrash("BerkeleyDB::db_rename needs Berkeley DB 3.1.x or better") ; +#else + HV * hash ; + DB * dbp ; + SV * sv ; + const char * db = NULL ; + const char * subdb = NULL ; + const char * newname = NULL ; + BerkeleyDB__Env env = NULL ; + DB_ENV * dbenv = NULL ; + u_int32_t flags = 0 ; + + hash = (HV*) SvRV(ref) ; + SetValue_pv(db, "Filename", char *) ; + SetValue_pv(subdb, "Subname", char *) ; + SetValue_pv(newname, "Newname", char *) ; + SetValue_iv(flags, "Flags") ; + SetValue_ov(env, "Env", BerkeleyDB__Env) ; + if (env) + dbenv = env->Env ; + RETVAL = db_create(&dbp, dbenv, 0) ; + if (RETVAL == 0) { + RETVAL = dbp->rename(dbp, db, subdb, newname, flags) ; + } +#endif + } + OUTPUT: + RETVAL + MODULE = BerkeleyDB::Env PACKAGE = BerkeleyDB::Env PREFIX = env_ @@ -1367,9 +1568,11 @@ _db_appinit(self, ref) HV * hash ; SV * sv ; char * home = NULL ; + char * errfile = NULL ; char * server = NULL ; char ** config = NULL ; int flags = 0 ; + int setflags = 0 ; int cachesize = 0 ; int lk_detect = 0 ; SV * errprefix = NULL; @@ -1382,9 +1585,14 @@ _db_appinit(self, ref) SetValue_pv(config, "Config", char **) ; SetValue_sv(errprefix, "ErrPrefix") ; SetValue_iv(flags, "Flags") ; + SetValue_iv(setflags, "SetFlags") ; SetValue_pv(server, "Server", char *) ; SetValue_iv(cachesize, "Cachesize") ; SetValue_iv(lk_detect, "LockDetect") ; +#ifndef AT_LEAST_DB_3_2 + if (setflags) + softCrash("-SetFlags needs Berkeley DB 3.x or better") ; +#endif /* ! AT_LEAST_DB_3 */ #ifndef AT_LEAST_DB_3_1 if (server) softCrash("-Server needs Berkeley DB 3.1 or better") ; @@ -1419,13 +1627,13 @@ _db_appinit(self, ref) if (RETVAL->ErrPrefix) RETVAL->Env->db_errpfx = SvPVX(RETVAL->ErrPrefix) ; - if ((sv = readHash(hash, "ErrFile")) && sv != &PL_sv_undef) { - env->db_errfile = GetFILEptr(sv); - RETVAL->ErrHandle = newRV(sv) ; + SetValue_pv(errfile, "ErrFile", char *) ; + if (errfile) { + RETVAL->ErrHandle = env->db_errfile = fopen(errfile, "w"); + if (RETVAL->ErrHandle == NULL) + croak("Cannot open file %s: %s\n", errfile, Strerror(errno)); } - /* SetValue_io(RETVAL->Env.db_errfile, "ErrFile") ; */ SetValue_iv(env->db_verbose, "Verbose") ; - /* env->db_errbuf = RETVAL->ErrBuff ; */ env->db_errcall = db_errcall_cb ; RETVAL->active = TRUE ; status = db_appinit(home, config, env, flags) ; @@ -1434,7 +1642,7 @@ _db_appinit(self, ref) hash_store_iv("BerkeleyDB::Term::Env", (char *)RETVAL, 1) ; else { if (RETVAL->ErrHandle) - SvREFCNT_dec(RETVAL->ErrHandle) ; + fclose(RETVAL->ErrHandle) ; if (RETVAL->ErrPrefix) SvREFCNT_dec(RETVAL->ErrPrefix) ; Safefree(RETVAL->Env) ; @@ -1458,7 +1666,7 @@ _db_appinit(self, ref) Trace(("set_cachesize [%d] returned %s\n", cachesize, my_db_strerror(status))); } - + if (status == 0 && lk_detect) { status = env->set_lk_detect(env, lk_detect) ; Trace(("set_lk_detect [%d] returned %s\n", @@ -1483,6 +1691,14 @@ _db_appinit(self, ref) } # endif #endif +#ifdef AT_LEAST_DB_3_2 + if (setflags && status == 0) + { + status = env->set_flags(env, setflags, 1); + Trace(("ENV->set_flags value = %d returned %s\n", setflags, + my_db_strerror(status))) ; + } +#endif if (status == 0) { int mode = 0 ; @@ -1495,13 +1711,15 @@ _db_appinit(self, ref) if (RETVAL->ErrPrefix) env->set_errpfx(env, SvPVX(RETVAL->ErrPrefix)) ; - if ((sv = readHash(hash, "ErrFile")) && sv != &PL_sv_undef) { - env->set_errfile(env, GetFILEptr(sv)) ; - RETVAL->ErrHandle = newRV(sv) ; + SetValue_pv(errfile, "ErrFile", char *) ; + if (errfile) { + RETVAL->ErrHandle = fopen(errfile, "w"); + if (RETVAL->ErrHandle == NULL) + croak("Cannot open file %s: %s\n", errfile, Strerror(errno)); + env->set_errfile(env, RETVAL->ErrHandle) ; } - /* SetValue_iv(RETVAL->Env.db_verbose, "Verbose") ; */ /* TODO */ + SetValue_iv(mode, "Mode") ; - /* RETVAL->Env.db_errbuf = RETVAL->ErrBuff ; */ env->set_errcall(env, db_errcall_cb) ; RETVAL->active = TRUE ; #ifdef IS_DB_3_0_x @@ -1517,7 +1735,7 @@ _db_appinit(self, ref) else { (env->close)(env, 0) ; if (RETVAL->ErrHandle) - SvREFCNT_dec(RETVAL->ErrHandle) ; + fclose(RETVAL->ErrHandle) ; if (RETVAL->ErrPrefix) SvREFCNT_dec(RETVAL->ErrPrefix) ; Safefree(RETVAL) ; @@ -1592,7 +1810,7 @@ _txn_begin(env, pid=NULL, flags=0) ZMALLOC(RETVAL, BerkeleyDB_Txn_type) ; RETVAL->txn = txn ; RETVAL->active = TRUE ; - Trace(("_txn_begin created txn [%d] in [%d]\n", txn, RETVAL)); + Trace(("_txn_begin created txn [%p] in [%p]\n", txn, RETVAL)); hash_store_iv("BerkeleyDB::Term::Txn", (char *)RETVAL, 1) ; } else @@ -1727,6 +1945,7 @@ status(env) DualType db_appexit(env) BerkeleyDB::Env env + ALIAS: close =1 INIT: ckActive_Environment(env->active) ; CODE: @@ -1760,7 +1979,7 @@ _DESTROY(env) (env->Env->close)(env->Env, 0) ; #endif if (env->ErrHandle) - SvREFCNT_dec(env->ErrHandle) ; + fclose(env->ErrHandle) ; if (env->ErrPrefix) SvREFCNT_dec(env->ErrPrefix) ; #if DB_VERSION_MAJOR == 2 @@ -1870,7 +2089,7 @@ set_mutexlocks(env, do_lock) softCrash("$env->set_setmutexlocks needs Berkeley DB 3.0 or better") ; #else # ifdef AT_LEAST_DB_4 - RETVAL = env->Status = env->Env->set_flags(env->Env, DB_NOLOCKING, 1); + RETVAL = env->Status = env->Env->set_flags(env->Env, DB_NOLOCKING, do_lock); # else # if defined(AT_LEAST_DB_3_2_6) || defined(IS_DB_3_0_x) RETVAL = env->Status = env->Env->set_mutexlocks(env->Env, do_lock); @@ -1882,6 +2101,39 @@ set_mutexlocks(env, do_lock) OUTPUT: RETVAL +int +set_verbose(env, which, onoff) + BerkeleyDB::Env env + u_int32_t which + int onoff + INIT: + ckActive_Database(env->active) ; + CODE: +#ifndef AT_LEAST_DB_3 + softCrash("$env->set_verbose needs Berkeley DB 3.x or better") ; +#else + RETVAL = env->Status = env->Env->set_verbose(env->Env, which, onoff); +#endif + OUTPUT: + RETVAL + +int +set_flags(env, flags, onoff) + BerkeleyDB::Env env + u_int32_t flags + int onoff + INIT: + ckActive_Database(env->active) ; + CODE: +#ifndef AT_LEAST_DB_3_2 + softCrash("$env->set_flags needs Berkeley DB 3.2.x or better") ; +#else + RETVAL = env->Status = env->Env->set_flags(env->Env, flags, onoff); +#endif + OUTPUT: + RETVAL + + MODULE = BerkeleyDB::Term PACKAGE = BerkeleyDB::Term void @@ -1910,11 +2162,13 @@ _db_open_hash(self, ref) int flags = 0 ; int mode = 0 ; BerkeleyDB db ; + BerkeleyDB__Txn txn = NULL ; Trace(("_db_open_hash start\n")) ; hash = (HV*) SvRV(ref) ; SetValue_pv(file, "Filename", char *) ; SetValue_pv(subname, "Subname", char *) ; + SetValue_ov(txn, "Txn", BerkeleyDB__Txn) ; SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ; ref_dbenv = sv ; SetValue_iv(flags, "Flags") ; @@ -1942,7 +2196,7 @@ _db_open_hash(self, ref) croak("DupCompare needs Berkeley DB 2.5.9 or later") ; #endif } - RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, file, subname, DB_HASH, flags, mode, &info) ; + RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_HASH, flags, mode, &info) ; Trace(("_db_open_hash end\n")) ; } OUTPUT: @@ -2018,11 +2272,13 @@ _db_open_unknown(ref) int mode = 0 ; BerkeleyDB db ; BerkeleyDB RETVAL ; + BerkeleyDB__Txn txn = NULL ; static char * Names[] = {"", "Btree", "Hash", "Recno"} ; hash = (HV*) SvRV(ref) ; SetValue_pv(file, "Filename", char *) ; SetValue_pv(subname, "Subname", char *) ; + SetValue_ov(txn, "Txn", BerkeleyDB__Txn) ; SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ; ref_dbenv = sv ; SetValue_iv(flags, "Flags") ; @@ -2037,7 +2293,7 @@ _db_open_unknown(ref) SetValue_iv(info.flags, "Property") ; ZMALLOC(db, BerkeleyDB_type) ; - RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, file, subname, DB_UNKNOWN, flags, mode, &info) ; + RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_UNKNOWN, flags, mode, &info) ; XPUSHs(sv_2mortal(newSViv(PTR2IV(RETVAL)))); if (RETVAL) XPUSHs(sv_2mortal(newSVpv(Names[RETVAL->type], 0))) ; @@ -2065,10 +2321,13 @@ _db_open_btree(self, ref) int flags = 0 ; int mode = 0 ; BerkeleyDB db ; + BerkeleyDB__Txn txn = NULL ; + Trace(("In _db_open_btree\n")); hash = (HV*) SvRV(ref) ; SetValue_pv(file, "Filename", char*) ; SetValue_pv(subname, "Subname", char *) ; + SetValue_ov(txn, "Txn", BerkeleyDB__Txn) ; SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ; ref_dbenv = sv ; SetValue_iv(flags, "Flags") ; @@ -2082,12 +2341,14 @@ _db_open_btree(self, ref) SetValue_iv(info.flags, "Property") ; ZMALLOC(db, BerkeleyDB_type) ; if ((sv = readHash(hash, "Compare")) && sv != &PL_sv_undef) { + Trace((" Parsed Compare callback\n")); info.bt_compare = btree_compare ; db->compare = newSVsv(sv) ; } /* DB_DUPSORT was introduced in DB 2.5.9 */ if ((sv = readHash(hash, "DupCompare")) && sv != &PL_sv_undef) { #ifdef DB_DUPSORT + Trace((" Parsed DupCompare callback\n")); info.dup_compare = dup_compare ; db->dup_compare = newSVsv(sv) ; info.flags |= DB_DUP|DB_DUPSORT ; @@ -2096,11 +2357,12 @@ _db_open_btree(self, ref) #endif } if ((sv = readHash(hash, "Prefix")) && sv != &PL_sv_undef) { + Trace((" Parsed Prefix callback\n")); info.bt_prefix = btree_prefix ; db->prefix = newSVsv(sv) ; } - RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, file, subname, DB_BTREE, flags, mode, &info) ; + RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_BTREE, flags, mode, &info) ; } OUTPUT: RETVAL @@ -2189,11 +2451,13 @@ _db_open_recno(self, ref) int flags = 0 ; int mode = 0 ; BerkeleyDB db ; + BerkeleyDB__Txn txn = NULL ; hash = (HV*) SvRV(ref) ; SetValue_pv(file, "Fname", char*) ; SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ; ref_dbenv = sv ; + SetValue_ov(txn, "Txn", BerkeleyDB__Txn) ; SetValue_iv(flags, "Flags") ; SetValue_iv(mode, "Mode") ; @@ -2223,7 +2487,7 @@ _db_open_recno(self, ref) db->array_base = (db->array_base == 0 ? 1 : 0) ; #endif /* ALLOW_RECNO_OFFSET */ - RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, file, subname, DB_RECNO, flags, mode, &info) ; + RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_RECNO, flags, mode, &info) ; } OUTPUT: RETVAL @@ -2250,11 +2514,13 @@ _db_open_queue(self, ref) int flags = 0 ; int mode = 0 ; BerkeleyDB db ; + BerkeleyDB__Txn txn = NULL ; hash = (HV*) SvRV(ref) ; SetValue_pv(file, "Fname", char*) ; SetValue_ov(dbenv, "Env", BerkeleyDB__Env) ; ref_dbenv = sv ; + SetValue_ov(txn, "Txn", BerkeleyDB__Txn) ; SetValue_iv(flags, "Flags") ; SetValue_iv(mode, "Mode") ; @@ -2269,7 +2535,7 @@ _db_open_queue(self, ref) SetValue_iv(info.flags, "Property") ; if ((sv = readHash(hash, "Len")) && sv != &PL_sv_undef) { info.re_len = SvIV(sv) ; ; - flagSet_DB2(info.flags, DB_PAD) ; + flagSet_DB2(info.flags, DB_FIXEDLEN) ; } if ((sv = readHash(hash, "Pad")) && sv != &PL_sv_undef) { info.re_pad = (u_int32_t)SvPOK(sv) ? *SvPV(sv,PL_na) : SvIV(sv) ; ; @@ -2281,7 +2547,7 @@ _db_open_queue(self, ref) db->array_base = (db->array_base == 0 ? 1 : 0) ; #endif /* ALLOW_RECNO_OFFSET */ - RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, file, subname, DB_QUEUE, flags, mode, &info) ; + RETVAL = my_db_open(db, ref, ref_dbenv, dbenv, txn, file, subname, DB_QUEUE, flags, mode, &info) ; #endif } OUTPUT: @@ -2397,11 +2663,16 @@ _db_cursor(db, flags=0) RETVAL->parent_db = db ; RETVAL->cursor = cursor ; RETVAL->dbp = db->dbp ; + RETVAL->txn = db->txn ; RETVAL->type = db->type ; RETVAL->recno_or_queue = db->recno_or_queue ; RETVAL->filename = my_strdup(db->filename) ; RETVAL->compare = db->compare ; RETVAL->dup_compare = db->dup_compare ; +#ifdef AT_LEAST_DB_3_3 + RETVAL->associated = db->associated ; + RETVAL->secondary_db = db->secondary_db; +#endif RETVAL->prefix = db->prefix ; RETVAL->hash = db->hash ; RETVAL->partial = db->partial ; @@ -2467,6 +2738,10 @@ _db_join(db, cursors, flags=0) RETVAL->filename = my_strdup(db->filename) ; RETVAL->compare = db->compare ; RETVAL->dup_compare = db->dup_compare ; +#ifdef AT_LEAST_DB_3_3 + RETVAL->associated = db->associated ; + RETVAL->secondary_db = db->secondary_db; +#endif RETVAL->prefix = db->prefix ; RETVAL->hash = db->hash ; RETVAL->partial = db->partial ; @@ -2642,10 +2917,20 @@ db_del(db, key, flags=0) BerkeleyDB::Common db DBTKEY key INIT: + Trace(("db_del db[%p] in [%p] txn[%p] key[%.*s] flags[%d]\n", db->dbp, db, db->txn, key.size, key.data, flags)) ; ckActive_Database(db->active) ; CurrentDB = db ; +#ifdef AT_LEAST_DB_3 +# ifdef AT_LEAST_DB_3_2 +# define writeToKey() (flagSet(DB_CONSUME)||flagSet(DB_CONSUME_WAIT)||flagSet(DB_GET_BOTH)||flagSet(DB_SET_RECNO)) +# else +# define writeToKey() (flagSet(DB_CONSUME)||flagSet(DB_GET_BOTH)||flagSet(DB_SET_RECNO)) +# endif +#else +#define writeToKey() (flagSet(DB_GET_BOTH)||flagSet(DB_SET_RECNO)) +#endif #define db_get(db, key, data, flags) \ (db->Status = ((db->dbp)->get)(db->dbp, db->txn, &key, &data, flags)) DualType @@ -2654,12 +2939,43 @@ db_get(db, key, data, flags=0) BerkeleyDB::Common db DBTKEY_B key DBT_OPT data - INIT: + CODE: + ckActive_Database(db->active) ; + CurrentDB = db ; + SetPartial(data,db) ; + Trace(("db_get db[%p] in [%p] txn[%p] key [%.*s] flags[%d]\n", db->dbp, db, db->txn, key.size, key.data, flags)) ; + RETVAL = db_get(db, key, data, flags); + Trace((" RETVAL %d\n", RETVAL)); + OUTPUT: + RETVAL + key if (writeToKey()) OutputValue(ST(1), key) ; + data + +#define db_pget(db, key, pkey, data, flags) \ + (db->Status = ((db->dbp)->pget)(db->dbp, db->txn, &key, &pkey, &data, flags)) +DualType +db_pget(db, key, pkey, data, flags=0) + u_int flags + BerkeleyDB::Common db + DBTKEY_B key + DBTKEY_B pkey = NO_INIT + DBT_OPT data + CODE: +#ifndef AT_LEAST_DB_3_3 + softCrash("db_pget needs at least Berkeley DB 3.3"); +#else + Trace(("db_pget db [%p] in [%p] txn [%p] flags [%d]\n", db->dbp, db, db->txn, flags)) ; ckActive_Database(db->active) ; CurrentDB = db ; SetPartial(data,db) ; + DBT_clear(pkey); + RETVAL = db_pget(db, key, pkey, data, flags); + Trace((" RETVAL %d\n", RETVAL)); +#endif OUTPUT: - key if (flagSet(DB_SET_RECNO)) OutputValue(ST(1), key) ; + RETVAL + key if (writeToKey()) OutputValue(ST(1), key) ; + pkey data #define db_put(db,key,data,flag) \ @@ -2670,11 +2986,15 @@ db_put(db, key, data, flags=0) BerkeleyDB::Common db DBTKEY key DBT data - INIT: + CODE: ckActive_Database(db->active) ; CurrentDB = db ; /* SetPartial(data,db) ; */ + Trace(("db_put db[%p] in [%p] txn[%p] key[%.*s] data [%.*s] flags[%d]\n", db->dbp, db, db->txn, key.size, key.data, data.size, data.data, flags)) ; + RETVAL = db_put(db, key, data, flags); + Trace((" RETVAL %d\n", RETVAL)); OUTPUT: + RETVAL key if (flagSet(DB_APPEND)) OutputKey(ST(1), key) ; #define db_key_range(db, key, range, flags) \ @@ -2741,16 +3061,64 @@ _Txn(db, txn=NULL) ckActive_Database(db->active) ; CODE: if (txn) { - Trace(("_Txn(%d in %d) active [%d]\n", txn->txn, txn, txn->active)); + Trace(("_Txn[%p] in[%p] active [%d]\n", txn->txn, txn, txn->active)); ckActive_Transaction(txn->active) ; db->txn = txn->txn ; } else { - Trace(("_Txn(undef) \n")); + Trace(("_Txn[undef] \n")); db->txn = NULL ; } +#define db_truncate(db, countp, flags) \ + (db->Status = ((db->dbp)->truncate)(db->dbp, db->txn, &countp, flags)) +DualType +truncate(db, countp, flags=0) + BerkeleyDB::Common db + u_int32_t countp + u_int32_t flags + INIT: + ckActive_Database(db->active) ; + CODE: +#ifndef AT_LEAST_DB_3_3 + softCrash("truncate needs Berkeley DB 3.3 or later") ; +#else + CurrentDB = db ; + RETVAL = db_truncate(db, countp, flags); +#endif + OUTPUT: + RETVAL + countp + +#ifdef AT_LEAST_DB_4_1 +# define db_associate(db, sec, cb, flags)\ + (db->Status = ((db->dbp)->associate)(db->dbp, NULL, sec->dbp, &cb, flags)) +#else +# define db_associate(db, sec, cb, flags)\ + (db->Status = ((db->dbp)->associate)(db->dbp, sec->dbp, &cb, flags)) +#endif +DualType +associate(db, secondary, callback, flags=0) + BerkeleyDB::Common db + BerkeleyDB::Common secondary + SV* callback + u_int32_t flags + INIT: + ckActive_Database(db->active) ; + CODE: +#ifndef AT_LEAST_DB_3_3 + softCrash("associate needs Berkeley DB 3.3 or later") ; +#else + CurrentDB = db ; + /* db->associated = newSVsv(callback) ; */ + secondary->associated = newSVsv(callback) ; + /* secondary->dbp->app_private = secondary->associated ; */ + secondary->secondary_db = TRUE; + RETVAL = db_associate(db, secondary, associate_cb, flags); +#endif + OUTPUT: + RETVAL MODULE = BerkeleyDB::Cursor PACKAGE = BerkeleyDB::Cursor PREFIX = cu_ @@ -2781,6 +3149,9 @@ _c_dup(db, flags=0) RETVAL->filename = my_strdup(db->filename) ; RETVAL->compare = db->compare ; RETVAL->dup_compare = db->dup_compare ; +#ifdef AT_LEAST_DB_3_3 + RETVAL->associated = db->associated ; +#endif RETVAL->prefix = db->prefix ; RETVAL->hash = db->hash ; RETVAL->partial = db->partial ; @@ -2865,7 +3236,7 @@ cu_c_get(db, key, data, flags=0) DBTKEY_B key DBT_B data INIT: - Trace(("c_get db [%d] flags [%d]\n", db, flags)) ; + Trace(("c_get db [%p] in [%p] flags [%d]\n", db->dbp, db, flags)) ; CurrentDB = db->parent_db ; ckActive_Cursor(db->active) ; SetPartial(data,db) ; @@ -2875,6 +3246,33 @@ cu_c_get(db, key, data, flags=0) key data if (! flagSet(DB_JOIN_ITEM)) OutputValue_B(ST(2), data) ; +#define cu_c_pget(c,k,p,d,f) (c->Status = (c->secondary_db ? (c->cursor->c_pget)(c->cursor,&k,&p,&d,f) : EINVAL)) +DualType +cu_c_pget(db, key, pkey, data, flags=0) + int flags + BerkeleyDB::Cursor db + DBTKEY_B key + DBTKEY_B pkey = NO_INIT + DBT_B data + CODE: +#ifndef AT_LEAST_DB_3_3 + softCrash("db_c_pget needs at least Berkeley DB 3.3"); +#else + Trace(("c_pget db [%d] flags [%d]\n", db, flags)) ; + CurrentDB = db->parent_db ; + ckActive_Cursor(db->active) ; + SetPartial(data,db) ; + DBT_clear(pkey); + RETVAL = cu_c_pget(db, key, pkey, data, flags); + Trace(("c_pget end\n")) ; +#endif + OUTPUT: + RETVAL + key + pkey + data if (! flagSet(DB_JOIN_ITEM)) OutputValue_B(ST(2), data) ; + + #define cu_c_put(c,k,d,f) (c->Status = (c->cursor->c_put)(c->cursor,&k,&d,f)) DualType diff --git a/db/perl/BerkeleyDB/Changes b/db/perl/BerkeleyDB/Changes index 732dbac66..caad63691 100644 --- a/db/perl/BerkeleyDB/Changes +++ b/db/perl/BerkeleyDB/Changes @@ -1,12 +1,36 @@ Revision history for Perl extension BerkeleyDB. -0.17 26 23 September 2001 +0.19 5th June 2002 + * Removed the targets that used mkconsts from Makefile.PL. They relied + on a module that is not available in all versions of Perl. + * added support for env->set_verbose + * added support for db->truncate + * added support for db->rename via BerkeleyDB::db_rename + * added support for db->verify via BerkeleyDB::db_verify + * added support for db->associate, db->pget & cursor->c_pget + * Builds with Berkeley DB 4.1.x + + +0.18 6th January 2002 + * Dropped support for ErrFile as a file handle. It was proving too + difficult to get at the underlying FILE * in XS. + Reported by Jonas Smedegaard (Debian powerpc) & Kenneth Olwing (Win32) + * Fixed problem with abort macro in XSUB.h clashing with txn abort + method in Berkeley DB 4.x -- patch supplied by Kenneth Olwing. + * DB->set_alloc was getting called too late in BerkeleyDB.xs. + This was causing problems with ActivePerl -- problem reported + by Kenneth Olwing. + * When opening a queue, the Len proprty set the DB_PAD flag. + Should have been DB_FIXEDLEN. Fix provided by Kenneth Olwing. + * Test harness fixes from Kenneth Olwing. + +0.17 23 September 2001 * Fixed a bug in BerkeleyDB::Recno - reported by Niklas Paulsson. * Added log_archive - patch supplied by Benjamin Holzman * Added txn_discard * Builds with Berkeley DB 4.0.x -0.16 26 1 August 2001 +0.16 1 August 2001 * added support for Berkeley DB 3.3.x (but no support for any of the new features just yet) diff --git a/db/perl/BerkeleyDB/MANIFEST b/db/perl/BerkeleyDB/MANIFEST index 6e9857be4..7da51ef7d 100644 --- a/db/perl/BerkeleyDB/MANIFEST +++ b/db/perl/BerkeleyDB/MANIFEST @@ -9,17 +9,20 @@ config.in constants.h constants.xs dbinfo +hints/dec_osf.pl hints/solaris.pl hints/irix_6_5.pl Makefile.PL MANIFEST mkconsts mkpod +ppport.h README t/btree.t t/db-3.0.t t/db-3.1.t t/db-3.2.t +t/db-3.3.t t/destroy.t t/env.t t/examples.t @@ -50,3 +53,4 @@ patches/5.005_01 patches/5.005_02 patches/5.005_03 patches/5.6.0 +scan diff --git a/db/perl/BerkeleyDB/Makefile.PL b/db/perl/BerkeleyDB/Makefile.PL index dbf0f2c41..e0e17bb12 100644 --- a/db/perl/BerkeleyDB/Makefile.PL +++ b/db/perl/BerkeleyDB/Makefile.PL @@ -43,7 +43,7 @@ $OS2 = "-DOS2" if $^O eq 'os2' ; WriteMakefile( NAME => 'BerkeleyDB', LIBS => ["-L${LIB_DIR} $LIBS"], - MAN3PODS => ' ', # Pods will be built by installman. + MAN3PODS => {}, # Pods will be built by installman. INC => "-I$INC_DIR", VERSION_FROM => 'BerkeleyDB.pm', XSPROTOARG => '-noprototypes', @@ -63,15 +63,9 @@ sub MY::postamble { $(NAME).pod: $(NAME).pod.P t/examples.t.T t/examples3.t.T mkpod perl ./mkpod -$(NAME).xs: constants.h constants.xs typemap +$(NAME).xs: typemap $(TOUCH) $(NAME).xs -constants.h constants.xs: mkconsts - bleedperl mkconsts xs - -$(NAME).pm: mkconsts - bleedperl mkconsts pm $(NAME).pm > $(NAME).pm.tmp && mv $(NAME).pm.tmp $(NAME).pm - Makefile: config.in diff --git a/db/perl/BerkeleyDB/README b/db/perl/BerkeleyDB/README index 8640949f3..c4ed4dacc 100644 --- a/db/perl/BerkeleyDB/README +++ b/db/perl/BerkeleyDB/README @@ -1,10 +1,10 @@ BerkeleyDB - Version 0.17 + Version 0.19 - 22nd October 2001 + 5th June 2002 - Copyright (c) 1997-2001 Paul Marquess. All rights reserved. This + Copyright (c) 1997-2002 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. @@ -106,37 +106,56 @@ This symptom can imply: Solution: Edit config.in and set the LIB and INCLUDE variables to point to the directories where libdb.a and db.h are installed. -Wrong db.h ----------- +#error db.h is not for Berkeley DB at all. +------------------------------------------ -If you get an error like this when building this module: +If you get the error above when building this module it means that there +is a file called "db.h" on your system that isn't the one that comes +with Berkeley DB. - cc -c -I./libraries/ -Dbool=char -DHAS_BOOL -I/usr/local/include -O2 - -DVERSION=\"0.07\" -DXS_VERSION=\"0.07\" -fpic - -I/usr/local/lib/perl5/5.00503/i586-linux/CORE BerkeleyDB.c - BerkeleyDB.xs:93: parse error before `DB_INFO' - BerkeleyDB.xs:93: warning: no semicolon at end of struct or union - BerkeleyDB.xs:94: warning: data definition has no type or storage class - BerkeleyDB.xs:95: parse error before `0x80000000' - BerkeleyDB.xs:110: parse error before `}' - BerkeleyDB.xs:110: warning: data definition has no type or storage class - BerkeleyDB.xs:117: parse error before `DB_ENV' - ... +Options: + + 1. You don't have Berkeley DB installed on your system at all. + Solution: get & install Berkeley DB. + + 2. Edit config.in and make sure the INCLUDE variable points to the + directory where the Berkeley DB file db.h is installed. + + 3. If option 2 doesn't work, try tempoarily renaming the db.h file + that is causing the error. -This error usually happens when if you only have Berkeley DB version 1 -on your system or you have both version 1 and version 2 (or 3) of Berkeley -DB installed on your system. When building BerkeleyDB it attempts -to use the db.h for Berkeley DB version 1. This perl module can only -be built with Berkeley DB version 2 or 3. +#error db.h is for Berkeley DB 1.x - need at least Berkeley DB 2.6.4 +-------------------------------------------------------------------- + +The error above will occur if there is a copy of the Berkeley DB 1.x +file db.h on your system. + +This error will happen when + + 1. you only have Berkeley DB version 1 on your system. + Solution: get & install a newer version of Berkeley DB. + + 2. you have both version 1 and a later version of Berkeley DB + installed on your system. When building BerkeleyDB it attempts to + use the db.h for Berkeley DB version 1. + Solution: Edit config.in and set the LIB and INCLUDE variables + to point to the directories where libdb.a and db.h are + installed. + + +#error db.h is for Berkeley DB 2.0-2.5 - need at least Berkeley DB 2.6.4 +------------------------------------------------------------------------ + +The error above will occur if there is a copy of the the file db.h for +Berkeley DB 2.0 to 2.5 on your system. This symptom can imply: - 1. You don't have Berkeley DB version 2 or 3 installed on your system - at all. - Solution: get & install Berkeley DB. + 1. You don't have a new enough version of Berkeley DB. + Solution: get & install a newer version of Berkeley DB. - 2. You do have Berkeley DB 2 or 3 installed, but it isn't in a standard - place. + 2. You have the correct version of Berkeley DB installed, but it isn't + in a standard place. Solution: Edit config.in and set the LIB and INCLUDE variables to point to the directories where libdb.a and db.h are installed. @@ -158,11 +177,11 @@ when you run the test harness: at /usr/local/lib/perl5/5.00503/i586-linux/DynaLoader.pm line 169. ... -This error usually happens when you have both version 1 and version -2 (or 3) of Berkeley DB installed on your system and BerkeleyDB attempts -to build using the db.h for Berkeley DB version 2/3 and the version 1 +This error usually happens when you have both version 1 and a newer version +of Berkeley DB installed on your system. BerkeleyDB attempts +to build using the db.h for Berkeley DB version 2/3/4 and the version 1 library. Unfortunately the two versions aren't compatible with each -other. BerkeleyDB can only be built with Berkeley DB version 2 or 3. +other. BerkeleyDB can only be built with Berkeley DB version 2, 3 or 4. Solution: Setting the LIB & INCLUDE variables in config.in to point to the correct directories can sometimes be enough to fix this @@ -302,7 +321,7 @@ be used to build this module. Follow the instructions in "BUILDING THE MODULE", remembering to set the INCLUDE and LIB variables in config.in. -The second approach will work with both Berkeley DB 2.x and 3.x. +The second approach will work with Berkeley DB 2.x or better. Start by building Berkeley DB as a shared library. This is from the Berkeley DB build instructions: @@ -420,7 +439,7 @@ To help me help you, I need of the following information: 2. The version of BerkeleyDB you have. If you have successfully installed BerkeleyDB, this one-liner will tell you: - perl -MBerkeleyDB -e 'print "BerkeleyDB ver $BerkeleyDB::VERSION\n"' + perl -MBerkeleyDB -e 'print qq{BerkeleyDB ver $BerkeleyDB::VERSION\n}' If you haven't installed BerkeleyDB then search BerkeleyDB.pm for a line like this: @@ -430,7 +449,7 @@ To help me help you, I need of the following information: 3. The version of Berkeley DB you have installed. If you have successfully installed BerkeleyDB, this one-liner will tell you: - perl -MBerkeleyDB -e 'print BerkeleyDB::DB_VERSION_STRING."\n"' + perl -MBerkeleyDB -e 'print BerkeleyDB::DB_VERSION_STRING.qq{\n}' If you haven't installed BerkeleyDB then search db.h for a line like this: diff --git a/db/perl/BerkeleyDB/config.in b/db/perl/BerkeleyDB/config.in index ab3c026c1..d5b4c0075 100644 --- a/db/perl/BerkeleyDB/config.in +++ b/db/perl/BerkeleyDB/config.in @@ -7,26 +7,28 @@ # Change the path below to point to the directory where db.h is # installed on your system. -INCLUDE = /usr/local/include -#INCLUDE = /usr/local/BerkeleyDB/include +#INCLUDE = /usr/local/include +INCLUDE = /usr/local/BerkeleyDB/include #INCLUDE = ./libraries/2.7.5/include #INCLUDE = ./libraries/3.0.55/include #INCLUDE = ./libraries/3.1.17/include #INCLUDE = ./libraries/3.3.11/include -#INCLUDE = ./libraries/4.0.7/include +#INCLUDE = ./libraries/4.1.12/include +#INCLUDE = ./libraries/4.0.14/include # 2. Where is libdb? # # Change the path below to point to the directory where libdb is # installed on your system. -LIB = /usr/local/lib -#LIB = /usr/local/BerkeleyDB/lib +#LIB = /usr/local/lib +LIB = /usr/local/BerkeleyDB/lib #LIB = ./libraries/2.7.5/lib #LIB = ./libraries/3.0.55/lib #LIB = ./libraries/3.1.17/lib #LIB = ./libraries/3.3.11/lib -#LIB = ./libraries/4.0.7/lib +#LIB = ./libraries/4.1.12/lib +#LIB = ./libraries/4.0.14/lib # 3. Is the library called libdb? # diff --git a/db/perl/BerkeleyDB/constants.h b/db/perl/BerkeleyDB/constants.h index 83db0fec6..257d5c2a4 100644 --- a/db/perl/BerkeleyDB/constants.h +++ b/db/perl/BerkeleyDB/constants.h @@ -245,77 +245,78 @@ static int constant_9 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. - DB_APPEND DB_BEFORE DB_CLIENT DB_COMMIT DB_CREATE DB_CURLSN DB_EXTENT - DB_GETREC DB_NOMMAP DB_NOSYNC DB_RDONLY DB_RECNUM DB_THREAD DB_VERIFY */ - /* Offset 5 gives the best switch position. */ - switch (name[5]) { - case 'C': - if (memEQ(name, "DB_RECNUM", 9)) { - /* ^ */ -#ifdef DB_RECNUM - *iv_return = DB_RECNUM; + DB_APPEND DB_BEFORE DB_CLIENT DB_COMMIT DB_CREATE DB_CURLSN DB_DIRECT + DB_EXTENT DB_GETREC DB_NOCOPY DB_NOMMAP DB_NOSYNC DB_RDONLY DB_RECNUM + DB_THREAD DB_VERIFY */ + /* Offset 7 gives the best switch position. */ + switch (name[7]) { + case 'A': + if (memEQ(name, "DB_NOMMAP", 9)) { + /* ^ */ +#ifdef DB_NOMMAP + *iv_return = DB_NOMMAP; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - break; - case 'E': - if (memEQ(name, "DB_CREATE", 9)) { - /* ^ */ -#ifdef DB_CREATE - *iv_return = DB_CREATE; + if (memEQ(name, "DB_THREAD", 9)) { + /* ^ */ +#ifdef DB_THREAD + *iv_return = DB_THREAD; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'F': - if (memEQ(name, "DB_BEFORE", 9)) { - /* ^ */ -#ifdef DB_BEFORE - *iv_return = DB_BEFORE; + case 'C': + if (memEQ(name, "DB_DIRECT", 9)) { + /* ^ */ +#ifdef DB_DIRECT + *iv_return = DB_DIRECT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'I': - if (memEQ(name, "DB_CLIENT", 9)) { - /* ^ */ -#ifdef DB_CLIENT - *iv_return = DB_CLIENT; + case 'E': + if (memEQ(name, "DB_GETREC", 9)) { + /* ^ */ +#ifdef DB_GETREC + *iv_return = DB_GETREC; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'M': - if (memEQ(name, "DB_COMMIT", 9)) { - /* ^ */ -#ifdef DB_COMMIT - *iv_return = DB_COMMIT; + case 'F': + if (memEQ(name, "DB_VERIFY", 9)) { + /* ^ */ +#ifdef DB_VERIFY + *iv_return = DB_VERIFY; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_NOMMAP", 9)) { - /* ^ */ -#ifdef DB_NOMMAP - *iv_return = DB_NOMMAP; + break; + case 'I': + if (memEQ(name, "DB_COMMIT", 9)) { + /* ^ */ +#ifdef DB_COMMIT + *iv_return = DB_COMMIT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'O': + case 'L': if (memEQ(name, "DB_RDONLY", 9)) { - /* ^ */ + /* ^ */ #ifdef DB_RDONLY *iv_return = DB_RDONLY; return PERL_constant_ISIV; @@ -324,9 +325,9 @@ constant_9 (pTHX_ const char *name, IV *iv_return) { #endif } break; - case 'P': + case 'N': if (memEQ(name, "DB_APPEND", 9)) { - /* ^ */ + /* ^ */ #ifdef DB_APPEND *iv_return = DB_APPEND; return PERL_constant_ISIV; @@ -334,30 +335,50 @@ constant_9 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } - break; - case 'R': - if (memEQ(name, "DB_CURLSN", 9)) { - /* ^ */ -#ifdef DB_CURLSN - *iv_return = DB_CURLSN; + if (memEQ(name, "DB_CLIENT", 9)) { + /* ^ */ +#ifdef DB_CLIENT + *iv_return = DB_CLIENT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_THREAD", 9)) { - /* ^ */ -#ifdef DB_THREAD - *iv_return = DB_THREAD; + if (memEQ(name, "DB_EXTENT", 9)) { + /* ^ */ +#ifdef DB_EXTENT + *iv_return = DB_EXTENT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_VERIFY", 9)) { - /* ^ */ -#ifdef DB_VERIFY - *iv_return = DB_VERIFY; + if (memEQ(name, "DB_NOSYNC", 9)) { + /* ^ */ +#ifdef DB_NOSYNC + *iv_return = DB_NOSYNC; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; + case 'P': + if (memEQ(name, "DB_NOCOPY", 9)) { + /* ^ */ +#ifdef DB_NOCOPY + *iv_return = DB_NOCOPY; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; + case 'R': + if (memEQ(name, "DB_BEFORE", 9)) { + /* ^ */ +#ifdef DB_BEFORE + *iv_return = DB_BEFORE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; @@ -365,10 +386,10 @@ constant_9 (pTHX_ const char *name, IV *iv_return) { } break; case 'S': - if (memEQ(name, "DB_NOSYNC", 9)) { - /* ^ */ -#ifdef DB_NOSYNC - *iv_return = DB_NOSYNC; + if (memEQ(name, "DB_CURLSN", 9)) { + /* ^ */ +#ifdef DB_CURLSN + *iv_return = DB_CURLSN; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; @@ -376,19 +397,21 @@ constant_9 (pTHX_ const char *name, IV *iv_return) { } break; case 'T': - if (memEQ(name, "DB_EXTENT", 9)) { - /* ^ */ -#ifdef DB_EXTENT - *iv_return = DB_EXTENT; + if (memEQ(name, "DB_CREATE", 9)) { + /* ^ */ +#ifdef DB_CREATE + *iv_return = DB_CREATE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_GETREC", 9)) { - /* ^ */ -#ifdef DB_GETREC - *iv_return = DB_GETREC; + break; + case 'U': + if (memEQ(name, "DB_RECNUM", 9)) { + /* ^ */ +#ifdef DB_RECNUM + *iv_return = DB_RECNUM; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; @@ -403,9 +426,10 @@ static int constant_10 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. - DB_CONSUME DB_CURRENT DB_DELETED DB_DUPSORT DB_ENV_CDB DB_ENV_TXN - DB_JOINENV DB_KEYLAST DB_NOPANIC DB_OK_HASH DB_PRIVATE DB_PR_PAGE - DB_RECOVER DB_SALVAGE DB_TIMEOUT DB_TXN_CKP DB_UNKNOWN DB_UPGRADE */ + DB_CONSUME DB_CURRENT DB_DELETED DB_DUPSORT DB_ENCRYPT DB_ENV_CDB + DB_ENV_TXN DB_JOINENV DB_KEYLAST DB_NOPANIC DB_OK_HASH DB_PRIVATE + DB_PR_PAGE DB_RECOVER DB_SALVAGE DB_TIMEOUT DB_TXN_CKP DB_UNKNOWN + DB_UPGRADE */ /* Offset 8 gives the best switch position. */ switch (name[8]) { case 'D': @@ -521,6 +545,17 @@ constant_10 (pTHX_ const char *name, IV *iv_return) { #endif } break; + case 'P': + if (memEQ(name, "DB_ENCRYPT", 10)) { + /* ^ */ +#ifdef DB_ENCRYPT + *iv_return = DB_ENCRYPT; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; case 'R': if (memEQ(name, "DB_DUPSORT", 10)) { /* ^ */ @@ -611,8 +646,8 @@ constant_11 (pTHX_ const char *name, IV *iv_return) { DB_INIT_LOG DB_INIT_TXN DB_KEYEMPTY DB_KEYEXIST DB_KEYFIRST DB_LOCKDOWN DB_LOCK_GET DB_LOCK_PUT DB_LOGMAGIC DB_LOG_DISK DB_MULTIPLE DB_NEXT_DUP DB_NOSERVER DB_NOTFOUND DB_OK_BTREE DB_OK_QUEUE DB_OK_RECNO DB_POSITION - DB_QAMMAGIC DB_RENUMBER DB_SNAPSHOT DB_TRUNCATE DB_TXNMAGIC DB_TXN_REDO - DB_TXN_SYNC DB_TXN_UNDO DB_YIELDCPU */ + DB_QAMMAGIC DB_RENUMBER DB_SNAPSHOT DB_TRUNCATE DB_TXNMAGIC DB_TXN_LOCK + DB_TXN_REDO DB_TXN_SYNC DB_TXN_UNDO DB_WRNOSYNC DB_YIELDCPU */ /* Offset 8 gives the best switch position. */ switch (name[8]) { case 'A': @@ -855,6 +890,15 @@ constant_11 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } + if (memEQ(name, "DB_TXN_LOCK", 11)) { + /* ^ */ +#ifdef DB_TXN_LOCK + *iv_return = DB_TXN_LOCK; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } break; case 'P': if (memEQ(name, "DB_KEYEMPTY", 11)) { @@ -951,6 +995,15 @@ constant_11 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } + if (memEQ(name, "DB_WRNOSYNC", 11)) { + /* ^ */ +#ifdef DB_WRNOSYNC + *iv_return = DB_WRNOSYNC; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } break; } return PERL_constant_NOTFOUND; @@ -960,13 +1013,14 @@ static int constant_12 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. - DB_ARCH_DATA DB_CDB_ALLDB DB_CL_WRITER DB_DELIMITER DB_DUPCURSOR - DB_FAST_STAT DB_GET_BOTHC DB_GET_RECNO DB_HASHMAGIC DB_INIT_LOCK - DB_JOIN_ITEM DB_LOCKMAGIC DB_LOCK_DUMP DB_LOCK_RW_N DB_LOGOLDVER - DB_MAX_PAGES DB_MPOOL_NEW DB_NEEDSPLIT DB_NODUPDATA DB_NOLOCKING - DB_NORECURSE DB_PAGEYIELD DB_PAGE_LOCK DB_POSITIONI DB_QAMOLDVER + DB_ARCH_DATA DB_CDB_ALLDB DB_CL_WRITER DB_DELIMITER DB_DIRECT_DB + DB_DUPCURSOR DB_ENV_FATAL DB_FAST_STAT DB_GET_BOTHC DB_GET_RECNO + DB_HASHMAGIC DB_INIT_LOCK DB_JOIN_ITEM DB_LOCKMAGIC DB_LOCK_DUMP + DB_LOCK_RW_N DB_LOGOLDVER DB_MAX_PAGES DB_MPOOL_NEW DB_NEEDSPLIT + DB_NODUPDATA DB_NOLOCKING DB_NORECURSE DB_OVERWRITE DB_PAGEYIELD + DB_PAGE_LOCK DB_PERMANENT DB_POSITIONI DB_PRINTABLE DB_QAMOLDVER DB_SET_RANGE DB_SET_RECNO DB_SWAPBYTES DB_TEMPORARY DB_TXN_ABORT - DB_TXN_APPLY DB_WRITELOCK DB_XA_CREATE */ + DB_TXN_APPLY DB_TXN_PRINT DB_WRITELOCK DB_WRITEOPEN DB_XA_CREATE */ /* Offset 3 gives the best switch position. */ switch (name[3]) { case 'A': @@ -1010,6 +1064,15 @@ constant_12 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } + if (memEQ(name, "DB_DIRECT_DB", 12)) { + /* ^ */ +#ifdef DB_DIRECT_DB + *iv_return = DB_DIRECT_DB; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } if (memEQ(name, "DB_DUPCURSOR", 12)) { /* ^ */ #ifdef DB_DUPCURSOR @@ -1020,6 +1083,17 @@ constant_12 (pTHX_ const char *name, IV *iv_return) { #endif } break; + case 'E': + if (memEQ(name, "DB_ENV_FATAL", 12)) { + /* ^ */ +#ifdef DB_ENV_FATAL + *iv_return = DB_ENV_FATAL; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; case 'F': if (memEQ(name, "DB_FAST_STAT", 12)) { /* ^ */ @@ -1183,6 +1257,17 @@ constant_12 (pTHX_ const char *name, IV *iv_return) { #endif } break; + case 'O': + if (memEQ(name, "DB_OVERWRITE", 12)) { + /* ^ */ +#ifdef DB_OVERWRITE + *iv_return = DB_OVERWRITE; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; case 'P': if (memEQ(name, "DB_PAGEYIELD", 12)) { /* ^ */ @@ -1202,6 +1287,15 @@ constant_12 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } + if (memEQ(name, "DB_PERMANENT", 12)) { + /* ^ */ +#ifdef DB_PERMANENT + *iv_return = DB_PERMANENT; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } if (memEQ(name, "DB_POSITIONI", 12)) { /* ^ */ #ifdef DB_POSITIONI @@ -1211,6 +1305,15 @@ constant_12 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } + if (memEQ(name, "DB_PRINTABLE", 12)) { + /* ^ */ +#ifdef DB_PRINTABLE + *iv_return = DB_PRINTABLE; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } break; case 'Q': if (memEQ(name, "DB_QAMOLDVER", 12)) { @@ -1286,6 +1389,18 @@ constant_12 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } + if (memEQ(name, "DB_TXN_PRINT", 12)) { + /* ^ */ +#if (DB_VERSION_MAJOR > 4) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \ + DB_VERSION_PATCH >= 12) + *iv_return = DB_TXN_PRINT; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } break; case 'W': if (memEQ(name, "DB_WRITELOCK", 12)) { @@ -1297,6 +1412,15 @@ constant_12 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } + if (memEQ(name, "DB_WRITEOPEN", 12)) { + /* ^ */ +#ifdef DB_WRITEOPEN + *iv_return = DB_WRITEOPEN; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } break; case 'X': if (memEQ(name, "DB_XA_CREATE", 12)) { @@ -1317,13 +1441,14 @@ static int constant_13 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. - DB_AGGRESSIVE DB_BTREEMAGIC DB_CHECKPOINT DB_DIRTY_READ DB_DONOTINDEX - DB_ENV_CREATE DB_ENV_NOMMAP DB_ENV_THREAD DB_HASHOLDVER DB_INCOMPLETE - DB_INIT_MPOOL DB_LOCK_NORUN DB_LOCK_RIW_N DB_LOGVERSION DB_LOG_LOCKED - DB_MPOOL_LAST DB_MUTEXDEBUG DB_MUTEXLOCKS DB_NEXT_NODUP DB_NOORDERCHK - DB_PREV_NODUP DB_PR_HEADERS DB_QAMVERSION DB_RDWRMASTER DB_REGISTERED - DB_REP_CLIENT DB_REP_MASTER DB_SEQUENTIAL DB_STAT_CLEAR DB_SYSTEM_MEM - DB_TXNVERSION DB_TXN_NOSYNC DB_TXN_NOWAIT DB_VERIFY_BAD */ + DB_AGGRESSIVE DB_BTREEMAGIC DB_CHECKPOINT DB_DIRECT_LOG DB_DIRTY_READ + DB_DONOTINDEX DB_ENV_CREATE DB_ENV_NOMMAP DB_ENV_THREAD DB_HASHOLDVER + DB_INCOMPLETE DB_INIT_MPOOL DB_LOCK_NORUN DB_LOCK_RIW_N DB_LOCK_TRADE + DB_LOGVERSION DB_LOG_LOCKED DB_MPOOL_LAST DB_MUTEXDEBUG DB_MUTEXLOCKS + DB_NEXT_NODUP DB_NOORDERCHK DB_PREV_NODUP DB_PR_HEADERS DB_QAMVERSION + DB_RDWRMASTER DB_REGISTERED DB_REP_CLIENT DB_REP_MASTER DB_SEQUENTIAL + DB_STAT_CLEAR DB_SYSTEM_MEM DB_TXNVERSION DB_TXN_NOSYNC DB_TXN_NOWAIT + DB_VERIFY_BAD */ /* Offset 5 gives the best switch position. */ switch (name[5]) { case 'A': @@ -1365,6 +1490,18 @@ constant_13 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } + if (memEQ(name, "DB_LOCK_TRADE", 13)) { + /* ^ */ +#if (DB_VERSION_MAJOR > 4) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \ + DB_VERSION_PATCH >= 12) + *iv_return = DB_LOCK_TRADE; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } break; case 'E': if (memEQ(name, "DB_CHECKPOINT", 13)) { @@ -1545,6 +1682,15 @@ constant_13 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } + if (memEQ(name, "DB_DIRECT_LOG", 13)) { + /* ^ */ +#ifdef DB_DIRECT_LOG + *iv_return = DB_DIRECT_LOG; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } if (memEQ(name, "DB_DIRTY_READ", 13)) { /* ^ */ #ifdef DB_DIRTY_READ @@ -1674,14 +1820,16 @@ static int constant_14 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. - DB_BTREEOLDVER DB_ENV_APPINIT DB_ENV_DBLOCAL DB_ENV_LOCKING DB_ENV_LOGGING - DB_ENV_NOPANIC DB_ENV_PRIVATE DB_FILE_ID_LEN DB_HASHVERSION DB_INVALID_EID + DB_AUTO_COMMIT DB_BTREEOLDVER DB_CHKSUM_SHA1 DB_EID_INVALID DB_ENCRYPT_AES + DB_ENV_APPINIT DB_ENV_DBLOCAL DB_ENV_LOCKING DB_ENV_LOGGING DB_ENV_NOPANIC + DB_ENV_PRIVATE DB_FILE_ID_LEN DB_HANDLE_LOCK DB_HASHVERSION DB_INVALID_EID DB_JOIN_NOSORT DB_LOCKVERSION DB_LOCK_EXPIRE DB_LOCK_NOWAIT DB_LOCK_OLDEST - DB_LOCK_RANDOM DB_LOCK_RECORD DB_LOCK_SWITCH DB_MAX_RECORDS DB_MPOOL_CLEAN - DB_MPOOL_DIRTY DB_NOOVERWRITE DB_NOSERVER_ID DB_ODDFILESIZE DB_OLD_VERSION - DB_OPEN_CALLED DB_RECORDCOUNT DB_RECORD_LOCK DB_REGION_ANON DB_REGION_INIT - DB_REGION_NAME DB_REP_NEWSITE DB_REP_UNAVAIL DB_REVSPLITOFF DB_RUNRECOVERY - DB_SET_TXN_NOW DB_USE_ENVIRON DB_WRITECURSOR DB_XIDDATASIZE */ + DB_LOCK_RANDOM DB_LOCK_RECORD DB_LOCK_REMOVE DB_LOCK_SWITCH DB_MAX_RECORDS + DB_MPOOL_CLEAN DB_MPOOL_DIRTY DB_NOOVERWRITE DB_NOSERVER_ID DB_ODDFILESIZE + DB_OLD_VERSION DB_OPEN_CALLED DB_RECORDCOUNT DB_RECORD_LOCK DB_REGION_ANON + DB_REGION_INIT DB_REGION_NAME DB_RENAMEMAGIC DB_REP_NEWSITE DB_REP_UNAVAIL + DB_REVSPLITOFF DB_RUNRECOVERY DB_SET_TXN_NOW DB_USE_ENVIRON DB_WRITECURSOR + DB_XIDDATASIZE */ /* Offset 9 gives the best switch position. */ switch (name[9]) { case 'A': @@ -1799,6 +1947,15 @@ constant_14 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } + if (memEQ(name, "DB_LOCK_REMOVE", 14)) { + /* ^ */ +#ifdef DB_LOCK_REMOVE + *iv_return = DB_LOCK_REMOVE; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } if (memEQ(name, "DB_NOSERVER_ID", 14)) { /* ^ */ #ifdef DB_NOSERVER_ID @@ -1878,6 +2035,17 @@ constant_14 (pTHX_ const char *name, IV *iv_return) { #endif } break; + case 'M': + if (memEQ(name, "DB_RENAMEMAGIC", 14)) { + /* ^ */ +#ifdef DB_RENAMEMAGIC + *iv_return = DB_RENAMEMAGIC; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; case 'N': if (memEQ(name, "DB_SET_TXN_NOW", 14)) { /* ^ */ @@ -1890,6 +2058,15 @@ constant_14 (pTHX_ const char *name, IV *iv_return) { } break; case 'O': + if (memEQ(name, "DB_AUTO_COMMIT", 14)) { + /* ^ */ +#ifdef DB_AUTO_COMMIT + *iv_return = DB_AUTO_COMMIT; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } if (memEQ(name, "DB_JOIN_NOSORT", 14)) { /* ^ */ #ifdef DB_JOIN_NOSORT @@ -1967,6 +2144,17 @@ constant_14 (pTHX_ const char *name, IV *iv_return) { #endif } break; + case 'T': + if (memEQ(name, "DB_ENCRYPT_AES", 14)) { + /* ^ */ +#ifdef DB_ENCRYPT_AES + *iv_return = DB_ENCRYPT_AES; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; case 'U': if (memEQ(name, "DB_WRITECURSOR", 14)) { /* ^ */ @@ -1979,6 +2167,15 @@ constant_14 (pTHX_ const char *name, IV *iv_return) { } break; case 'V': + if (memEQ(name, "DB_EID_INVALID", 14)) { + /* ^ */ +#ifdef DB_EID_INVALID + *iv_return = DB_EID_INVALID; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } if (memEQ(name, "DB_USE_ENVIRON", 14)) { /* ^ */ #ifdef DB_USE_ENVIRON @@ -2030,6 +2227,24 @@ constant_14 (pTHX_ const char *name, IV *iv_return) { } break; case '_': + if (memEQ(name, "DB_CHKSUM_SHA1", 14)) { + /* ^ */ +#ifdef DB_CHKSUM_SHA1 + *iv_return = DB_CHKSUM_SHA1; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + if (memEQ(name, "DB_HANDLE_LOCK", 14)) { + /* ^ */ +#ifdef DB_HANDLE_LOCK + *iv_return = DB_HANDLE_LOCK; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } if (memEQ(name, "DB_RECORD_LOCK", 14)) { /* ^ */ #ifdef DB_RECORD_LOCK @@ -2079,10 +2294,10 @@ constant_15 (pTHX_ const char *name, IV *iv_return) { DB_ENV_PANIC_OK DB_ENV_YIELDCPU DB_LOCK_DEFAULT DB_LOCK_INHERIT DB_LOCK_NOTHELD DB_LOCK_PUT_ALL DB_LOCK_PUT_OBJ DB_LOCK_TIMEOUT DB_LOCK_UPGRADE DB_MPOOL_CREATE DB_MPOOL_EXTENT DB_MULTIPLE_KEY - DB_OPFLAGS_MASK DB_ORDERCHKONLY DB_REGION_MAGIC DB_REP_LOGSONLY - DB_REP_OUTDATED DB_SURPRISE_KID DB_TEST_POSTLOG DB_TEST_PREOPEN - DB_TXN_LOCK_2PL DB_TXN_LOG_MASK DB_TXN_LOG_REDO DB_TXN_LOG_UNDO - DB_VERIFY_FATAL */ + DB_OPFLAGS_MASK DB_ORDERCHKONLY DB_PRIORITY_LOW DB_REGION_MAGIC + DB_REP_LOGSONLY DB_REP_OUTDATED DB_SURPRISE_KID DB_TEST_POSTLOG + DB_TEST_PREOPEN DB_TXN_GETPGNOS DB_TXN_LOCK_2PL DB_TXN_LOG_MASK + DB_TXN_LOG_REDO DB_TXN_LOG_UNDO DB_VERIFY_FATAL */ /* Offset 10 gives the best switch position. */ switch (name[10]) { case 'D': @@ -2255,6 +2470,20 @@ constant_15 (pTHX_ const char *name, IV *iv_return) { #endif } break; + case 'P': + if (memEQ(name, "DB_TXN_GETPGNOS", 15)) { + /* ^ */ +#if (DB_VERSION_MAJOR > 4) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \ + DB_VERSION_PATCH >= 12) + *iv_return = DB_TXN_GETPGNOS; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; case 'R': if (memEQ(name, "DB_BTREEVERSION", 15)) { /* ^ */ @@ -2341,6 +2570,20 @@ constant_15 (pTHX_ const char *name, IV *iv_return) { #endif } break; + case 'Y': + if (memEQ(name, "DB_PRIORITY_LOW", 15)) { + /* ^ */ +#if (DB_VERSION_MAJOR > 4) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \ + DB_VERSION_PATCH >= 12) + *iv_return = DB_PRIORITY_LOW; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; case '_': if (memEQ(name, "DB_CONSUME_WAIT", 15)) { /* ^ */ @@ -2396,49 +2639,53 @@ static int constant_16 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. - DB_BROADCAST_EID DB_CACHED_COUNTS DB_ENV_CDB_ALLDB DB_ENV_NOLOCKING - DB_ENV_RPCCLIENT DB_FCNTL_LOCKING DB_JAVA_CALLBACK DB_LOCK_CONFLICT - DB_LOCK_DEADLOCK DB_LOCK_MAXLOCKS DB_LOCK_MINLOCKS DB_LOCK_MINWRITE + DB_BROADCAST_EID DB_CACHED_COUNTS DB_EID_BROADCAST DB_ENV_CDB_ALLDB + DB_ENV_DIRECT_DB DB_ENV_NOLOCKING DB_ENV_OVERWRITE DB_ENV_RPCCLIENT + DB_FCNTL_LOCKING DB_JAVA_CALLBACK DB_LOCK_CONFLICT DB_LOCK_DEADLOCK + DB_LOCK_MAXLOCKS DB_LOCK_MINLOCKS DB_LOCK_MINWRITE DB_LOCK_NOTEXIST DB_LOCK_PUT_READ DB_LOCK_YOUNGEST DB_LOGC_BUF_SIZE DB_MPOOL_DISCARD - DB_MPOOL_PRIVATE DB_NOSERVER_HOME DB_PAGE_NOTFOUND DB_RECOVER_FATAL - DB_REP_DUPMASTER DB_REP_NEWMASTER DB_REP_PERMANENT DB_SECONDARY_BAD - DB_TEST_POSTOPEN DB_TEST_POSTSYNC DB_TXN_LOCK_MASK DB_TXN_OPENFILES - DB_VERB_CHKPOINT DB_VERB_DEADLOCK DB_VERB_RECOVERY DB_VERB_WAITSFOR - DB_VERSION_MAJOR DB_VERSION_MINOR DB_VERSION_PATCH DB_VRFY_FLAGMASK */ - /* Offset 11 gives the best switch position. */ - switch (name[11]) { + DB_MPOOL_PRIVATE DB_NOSERVER_HOME DB_PAGE_NOTFOUND DB_PRIORITY_HIGH + DB_RECOVER_FATAL DB_REP_DUPMASTER DB_REP_NEWMASTER DB_REP_PERMANENT + DB_SECONDARY_BAD DB_TEST_POSTOPEN DB_TEST_POSTSYNC DB_TXN_LOCK_MASK + DB_TXN_OPENFILES DB_VERB_CHKPOINT DB_VERB_DEADLOCK DB_VERB_RECOVERY + DB_VERB_WAITSFOR DB_VERSION_MAJOR DB_VERSION_MINOR DB_VERSION_PATCH + DB_VRFY_FLAGMASK */ + /* Offset 12 gives the best switch position. */ + switch (name[12]) { case 'A': - if (memEQ(name, "DB_ENV_CDB_ALLDB", 16)) { - /* ^ */ -#ifdef DB_ENV_CDB_ALLDB - *iv_return = DB_ENV_CDB_ALLDB; + if (memEQ(name, "DB_RECOVER_FATAL", 16)) { + /* ^ */ +#ifdef DB_RECOVER_FATAL + *iv_return = DB_RECOVER_FATAL; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_REP_DUPMASTER", 16)) { - /* ^ */ -#ifdef DB_REP_DUPMASTER - *iv_return = DB_REP_DUPMASTER; + if (memEQ(name, "DB_VERSION_MAJOR", 16)) { + /* ^ */ +#ifdef DB_VERSION_MAJOR + *iv_return = DB_VERSION_MAJOR; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_REP_NEWMASTER", 16)) { - /* ^ */ -#ifdef DB_REP_NEWMASTER - *iv_return = DB_REP_NEWMASTER; + if (memEQ(name, "DB_VERSION_PATCH", 16)) { + /* ^ */ +#ifdef DB_VERSION_PATCH + *iv_return = DB_VERSION_PATCH; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_REP_PERMANENT", 16)) { - /* ^ */ -#ifdef DB_REP_PERMANENT - *iv_return = DB_REP_PERMANENT; + break; + case 'B': + if (memEQ(name, "DB_JAVA_CALLBACK", 16)) { + /* ^ */ +#ifdef DB_JAVA_CALLBACK + *iv_return = DB_JAVA_CALLBACK; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; @@ -2446,75 +2693,71 @@ constant_16 (pTHX_ const char *name, IV *iv_return) { } break; case 'C': - if (memEQ(name, "DB_ENV_NOLOCKING", 16)) { - /* ^ */ -#ifdef DB_ENV_NOLOCKING - *iv_return = DB_ENV_NOLOCKING; + if (memEQ(name, "DB_EID_BROADCAST", 16)) { + /* ^ */ +#ifdef DB_EID_BROADCAST + *iv_return = DB_EID_BROADCAST; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_FCNTL_LOCKING", 16)) { - /* ^ */ -#ifdef DB_FCNTL_LOCKING - *iv_return = DB_FCNTL_LOCKING; + if (memEQ(name, "DB_MPOOL_DISCARD", 16)) { + /* ^ */ +#ifdef DB_MPOOL_DISCARD + *iv_return = DB_MPOOL_DISCARD; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'D': - if (memEQ(name, "DB_LOCK_DEADLOCK", 16)) { - /* ^ */ -#ifdef DB_LOCK_DEADLOCK - *iv_return = DB_LOCK_DEADLOCK; - return PERL_constant_ISIV; -#else - return PERL_constant_NOTDEF; -#endif - } - if (memEQ(name, "DB_VERB_DEADLOCK", 16)) { - /* ^ */ -#ifdef DB_VERB_DEADLOCK - *iv_return = DB_VERB_DEADLOCK; + case 'G': + if (memEQ(name, "DB_LOCK_YOUNGEST", 16)) { + /* ^ */ +#ifdef DB_LOCK_YOUNGEST + *iv_return = DB_LOCK_YOUNGEST; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'F': - if (memEQ(name, "DB_LOCK_CONFLICT", 16)) { - /* ^ */ -#ifdef DB_LOCK_CONFLICT - *iv_return = DB_LOCK_CONFLICT; + case 'H': + if (memEQ(name, "DB_NOSERVER_HOME", 16)) { + /* ^ */ +#ifdef DB_NOSERVER_HOME + *iv_return = DB_NOSERVER_HOME; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_PAGE_NOTFOUND", 16)) { - /* ^ */ -#ifdef DB_PAGE_NOTFOUND - *iv_return = DB_PAGE_NOTFOUND; + if (memEQ(name, "DB_PRIORITY_HIGH", 16)) { + /* ^ */ +#if (DB_VERSION_MAJOR > 4) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \ + DB_VERSION_PATCH >= 12) + *iv_return = DB_PRIORITY_HIGH; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_RECOVER_FATAL", 16)) { - /* ^ */ -#ifdef DB_RECOVER_FATAL - *iv_return = DB_RECOVER_FATAL; + break; + case 'I': + if (memEQ(name, "DB_ENV_RPCCLIENT", 16)) { + /* ^ */ +#ifdef DB_ENV_RPCCLIENT + *iv_return = DB_ENV_RPCCLIENT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } if (memEQ(name, "DB_TXN_OPENFILES", 16)) { - /* ^ */ + /* ^ */ #if (DB_VERSION_MAJOR > 3) || \ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \ (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \ @@ -2525,23 +2768,30 @@ constant_16 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } - break; - case 'G': - if (memEQ(name, "DB_VRFY_FLAGMASK", 16)) { - /* ^ */ -#ifdef DB_VRFY_FLAGMASK - *iv_return = DB_VRFY_FLAGMASK; + if (memEQ(name, "DB_VERSION_MINOR", 16)) { + /* ^ */ +#ifdef DB_VERSION_MINOR + *iv_return = DB_VERSION_MINOR; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'I': - if (memEQ(name, "DB_MPOOL_PRIVATE", 16)) { - /* ^ */ -#ifdef DB_MPOOL_PRIVATE - *iv_return = DB_MPOOL_PRIVATE; + case 'K': + if (memEQ(name, "DB_ENV_NOLOCKING", 16)) { + /* ^ */ +#ifdef DB_ENV_NOLOCKING + *iv_return = DB_ENV_NOLOCKING; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + if (memEQ(name, "DB_FCNTL_LOCKING", 16)) { + /* ^ */ +#ifdef DB_FCNTL_LOCKING + *iv_return = DB_FCNTL_LOCKING; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; @@ -2549,37 +2799,37 @@ constant_16 (pTHX_ const char *name, IV *iv_return) { } break; case 'L': - if (memEQ(name, "DB_ENV_RPCCLIENT", 16)) { - /* ^ */ -#ifdef DB_ENV_RPCCLIENT - *iv_return = DB_ENV_RPCCLIENT; + if (memEQ(name, "DB_ENV_CDB_ALLDB", 16)) { + /* ^ */ +#ifdef DB_ENV_CDB_ALLDB + *iv_return = DB_ENV_CDB_ALLDB; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_JAVA_CALLBACK", 16)) { - /* ^ */ -#ifdef DB_JAVA_CALLBACK - *iv_return = DB_JAVA_CALLBACK; + if (memEQ(name, "DB_LOCK_CONFLICT", 16)) { + /* ^ */ +#ifdef DB_LOCK_CONFLICT + *iv_return = DB_LOCK_CONFLICT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_LOCK_MAXLOCKS", 16)) { - /* ^ */ -#ifdef DB_LOCK_MAXLOCKS - *iv_return = DB_LOCK_MAXLOCKS; + if (memEQ(name, "DB_LOCK_DEADLOCK", 16)) { + /* ^ */ +#ifdef DB_LOCK_DEADLOCK + *iv_return = DB_LOCK_DEADLOCK; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_LOCK_MINLOCKS", 16)) { - /* ^ */ -#ifdef DB_LOCK_MINLOCKS - *iv_return = DB_LOCK_MINLOCKS; + if (memEQ(name, "DB_VERB_DEADLOCK", 16)) { + /* ^ */ +#ifdef DB_VERB_DEADLOCK + *iv_return = DB_VERB_DEADLOCK; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; @@ -2587,19 +2837,19 @@ constant_16 (pTHX_ const char *name, IV *iv_return) { } break; case 'M': - if (memEQ(name, "DB_VERSION_MAJOR", 16)) { - /* ^ */ -#ifdef DB_VERSION_MAJOR - *iv_return = DB_VERSION_MAJOR; + if (memEQ(name, "DB_TXN_LOCK_MASK", 16)) { + /* ^ */ +#ifdef DB_TXN_LOCK_MASK + *iv_return = DB_TXN_LOCK_MASK; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_VERSION_MINOR", 16)) { - /* ^ */ -#ifdef DB_VERSION_MINOR - *iv_return = DB_VERSION_MINOR; + if (memEQ(name, "DB_VRFY_FLAGMASK", 16)) { + /* ^ */ +#ifdef DB_VRFY_FLAGMASK + *iv_return = DB_VRFY_FLAGMASK; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; @@ -2607,10 +2857,10 @@ constant_16 (pTHX_ const char *name, IV *iv_return) { } break; case 'N': - if (memEQ(name, "DB_LOCK_YOUNGEST", 16)) { - /* ^ */ -#ifdef DB_LOCK_YOUNGEST - *iv_return = DB_LOCK_YOUNGEST; + if (memEQ(name, "DB_REP_PERMANENT", 16)) { + /* ^ */ +#ifdef DB_REP_PERMANENT + *iv_return = DB_REP_PERMANENT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; @@ -2618,28 +2868,44 @@ constant_16 (pTHX_ const char *name, IV *iv_return) { } break; case 'O': - if (memEQ(name, "DB_CACHED_COUNTS", 16)) { - /* ^ */ -#ifdef DB_CACHED_COUNTS - *iv_return = DB_CACHED_COUNTS; + if (memEQ(name, "DB_LOCK_MAXLOCKS", 16)) { + /* ^ */ +#ifdef DB_LOCK_MAXLOCKS + *iv_return = DB_LOCK_MAXLOCKS; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_VERB_RECOVERY", 16)) { - /* ^ */ -#ifdef DB_VERB_RECOVERY - *iv_return = DB_VERB_RECOVERY; + if (memEQ(name, "DB_LOCK_MINLOCKS", 16)) { + /* ^ */ +#ifdef DB_LOCK_MINLOCKS + *iv_return = DB_LOCK_MINLOCKS; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + if (memEQ(name, "DB_PAGE_NOTFOUND", 16)) { + /* ^ */ +#ifdef DB_PAGE_NOTFOUND + *iv_return = DB_PAGE_NOTFOUND; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + if (memEQ(name, "DB_TEST_POSTOPEN", 16)) { + /* ^ */ +#ifdef DB_TEST_POSTOPEN + *iv_return = DB_TEST_POSTOPEN; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - break; - case 'P': if (memEQ(name, "DB_VERB_CHKPOINT", 16)) { - /* ^ */ + /* ^ */ #ifdef DB_VERB_CHKPOINT *iv_return = DB_VERB_CHKPOINT; return PERL_constant_ISIV; @@ -2647,10 +2913,33 @@ constant_16 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_VERSION_PATCH", 16)) { - /* ^ */ -#ifdef DB_VERSION_PATCH - *iv_return = DB_VERSION_PATCH; + break; + case 'R': + if (memEQ(name, "DB_ENV_OVERWRITE", 16)) { + /* ^ */ +#ifdef DB_ENV_OVERWRITE + *iv_return = DB_ENV_OVERWRITE; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + if (memEQ(name, "DB_LOCK_MINWRITE", 16)) { + /* ^ */ +#ifdef DB_LOCK_MINWRITE + *iv_return = DB_LOCK_MINWRITE; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + if (memEQ(name, "DB_LOCK_PUT_READ", 16)) { + /* ^ */ +#if (DB_VERSION_MAJOR > 4) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \ + DB_VERSION_PATCH >= 7) + *iv_return = DB_LOCK_PUT_READ; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; @@ -2658,37 +2947,35 @@ constant_16 (pTHX_ const char *name, IV *iv_return) { } break; case 'S': - if (memEQ(name, "DB_MPOOL_DISCARD", 16)) { - /* ^ */ -#ifdef DB_MPOOL_DISCARD - *iv_return = DB_MPOOL_DISCARD; + if (memEQ(name, "DB_LOGC_BUF_SIZE", 16)) { + /* ^ */ +#ifdef DB_LOGC_BUF_SIZE + *iv_return = DB_LOGC_BUF_SIZE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - break; - case 'T': - if (memEQ(name, "DB_BROADCAST_EID", 16)) { - /* ^ */ -#ifdef DB_BROADCAST_EID - *iv_return = DB_BROADCAST_EID; + if (memEQ(name, "DB_REP_DUPMASTER", 16)) { + /* ^ */ +#ifdef DB_REP_DUPMASTER + *iv_return = DB_REP_DUPMASTER; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_TEST_POSTOPEN", 16)) { - /* ^ */ -#ifdef DB_TEST_POSTOPEN - *iv_return = DB_TEST_POSTOPEN; + if (memEQ(name, "DB_REP_NEWMASTER", 16)) { + /* ^ */ +#ifdef DB_REP_NEWMASTER + *iv_return = DB_REP_NEWMASTER; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } if (memEQ(name, "DB_TEST_POSTSYNC", 16)) { - /* ^ */ + /* ^ */ #ifdef DB_TEST_POSTSYNC *iv_return = DB_TEST_POSTSYNC; return PERL_constant_ISIV; @@ -2697,7 +2984,7 @@ constant_16 (pTHX_ const char *name, IV *iv_return) { #endif } if (memEQ(name, "DB_VERB_WAITSFOR", 16)) { - /* ^ */ + /* ^ */ #ifdef DB_VERB_WAITSFOR *iv_return = DB_VERB_WAITSFOR; return PERL_constant_ISIV; @@ -2706,63 +2993,73 @@ constant_16 (pTHX_ const char *name, IV *iv_return) { #endif } break; - case 'W': - if (memEQ(name, "DB_LOCK_MINWRITE", 16)) { - /* ^ */ -#ifdef DB_LOCK_MINWRITE - *iv_return = DB_LOCK_MINWRITE; + case 'T': + if (memEQ(name, "DB_ENV_DIRECT_DB", 16)) { + /* ^ */ +#ifdef DB_ENV_DIRECT_DB + *iv_return = DB_ENV_DIRECT_DB; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'Y': - if (memEQ(name, "DB_SECONDARY_BAD", 16)) { - /* ^ */ -#ifdef DB_SECONDARY_BAD - *iv_return = DB_SECONDARY_BAD; + case 'U': + if (memEQ(name, "DB_CACHED_COUNTS", 16)) { + /* ^ */ +#ifdef DB_CACHED_COUNTS + *iv_return = DB_CACHED_COUNTS; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case '_': - if (memEQ(name, "DB_LOCK_PUT_READ", 16)) { - /* ^ */ -#if (DB_VERSION_MAJOR > 4) || \ - (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \ - (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \ - DB_VERSION_PATCH >= 7) - *iv_return = DB_LOCK_PUT_READ; + case 'V': + if (memEQ(name, "DB_MPOOL_PRIVATE", 16)) { + /* ^ */ +#ifdef DB_MPOOL_PRIVATE + *iv_return = DB_MPOOL_PRIVATE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_LOGC_BUF_SIZE", 16)) { - /* ^ */ -#ifdef DB_LOGC_BUF_SIZE - *iv_return = DB_LOGC_BUF_SIZE; + if (memEQ(name, "DB_VERB_RECOVERY", 16)) { + /* ^ */ +#ifdef DB_VERB_RECOVERY + *iv_return = DB_VERB_RECOVERY; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_NOSERVER_HOME", 16)) { - /* ^ */ -#ifdef DB_NOSERVER_HOME - *iv_return = DB_NOSERVER_HOME; + break; + case 'X': + if (memEQ(name, "DB_LOCK_NOTEXIST", 16)) { + /* ^ */ +#ifdef DB_LOCK_NOTEXIST + *iv_return = DB_LOCK_NOTEXIST; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_TXN_LOCK_MASK", 16)) { - /* ^ */ -#ifdef DB_TXN_LOCK_MASK - *iv_return = DB_TXN_LOCK_MASK; + break; + case '_': + if (memEQ(name, "DB_BROADCAST_EID", 16)) { + /* ^ */ +#ifdef DB_BROADCAST_EID + *iv_return = DB_BROADCAST_EID; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + if (memEQ(name, "DB_SECONDARY_BAD", 16)) { + /* ^ */ +#ifdef DB_SECONDARY_BAD + *iv_return = DB_SECONDARY_BAD; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; @@ -2777,10 +3074,10 @@ static int constant_17 (pTHX_ const char *name, IV *iv_return, const char **pv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. - DB_ENV_REP_CLIENT DB_ENV_REP_MASTER DB_ENV_STANDALONE DB_ENV_SYSTEM_MEM - DB_ENV_TXN_NOSYNC DB_ENV_USER_ALLOC DB_GET_BOTH_RANGE DB_LOG_SILENT_ERR - DB_RPC_SERVERPROG DB_RPC_SERVERVERS DB_TEST_PRERENAME DB_TXN_POPENFILES - DB_VERSION_STRING */ + DB_ENV_DIRECT_LOG DB_ENV_REP_CLIENT DB_ENV_REP_MASTER DB_ENV_STANDALONE + DB_ENV_SYSTEM_MEM DB_ENV_TXN_NOSYNC DB_ENV_USER_ALLOC DB_GET_BOTH_RANGE + DB_LOG_SILENT_ERR DB_RPC_SERVERPROG DB_RPC_SERVERVERS DB_TEST_PRERENAME + DB_TXN_POPENFILES DB_VERSION_STRING */ /* Offset 14 gives the best switch position. */ switch (name[14]) { case 'A': @@ -2835,6 +3132,15 @@ constant_17 (pTHX_ const char *name, IV *iv_return, const char **pv_return) { } break; case 'L': + if (memEQ(name, "DB_ENV_DIRECT_LOG", 17)) { + /* ^ */ +#ifdef DB_ENV_DIRECT_LOG + *iv_return = DB_ENV_DIRECT_LOG; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } if (memEQ(name, "DB_ENV_USER_ALLOC", 17)) { /* ^ */ #ifdef DB_ENV_USER_ALLOC @@ -3054,27 +3360,59 @@ constant_19 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. DB_ENV_REP_LOGSONLY DB_LOCK_FREE_LOCKER DB_LOCK_GET_TIMEOUT - DB_LOCK_SET_TIMEOUT DB_REP_HOLDELECTION DB_SET_LOCK_TIMEOUT - DB_TEST_POSTDESTROY DB_TEST_POSTEXTOPEN DB_TEST_POSTLOGMETA - DB_TXN_FORWARD_ROLL DB_TXN_LOG_UNDOREDO DB_UNRESOLVED_CHILD - DB_UPDATE_SECONDARY DB_USE_ENVIRON_ROOT */ - /* Offset 13 gives the best switch position. */ - switch (name[13]) { - case 'D': - if (memEQ(name, "DB_TXN_FORWARD_ROLL", 19)) { - /* ^ */ -#if (DB_VERSION_MAJOR > 3) || \ - (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \ - (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \ - DB_VERSION_PATCH >= 12) - *iv_return = DB_TXN_FORWARD_ROLL; + DB_LOCK_SET_TIMEOUT DB_PRIORITY_DEFAULT DB_REP_HOLDELECTION + DB_SET_LOCK_TIMEOUT DB_TEST_POSTDESTROY DB_TEST_POSTEXTOPEN + DB_TEST_POSTLOGMETA DB_TEST_SUBDB_LOCKS DB_TXN_FORWARD_ROLL + DB_TXN_LOG_UNDOREDO DB_TXN_WRITE_NOSYNC DB_UNRESOLVED_CHILD + DB_UPDATE_SECONDARY DB_USE_ENVIRON_ROOT DB_VERB_REPLICATION */ + /* Offset 9 gives the best switch position. */ + switch (name[9]) { + case 'C': + if (memEQ(name, "DB_SET_LOCK_TIMEOUT", 19)) { + /* ^ */ +#ifdef DB_SET_LOCK_TIMEOUT + *iv_return = DB_SET_LOCK_TIMEOUT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } + break; + case 'E': + if (memEQ(name, "DB_LOCK_GET_TIMEOUT", 19)) { + /* ^ */ +#if (DB_VERSION_MAJOR > 4) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \ + DB_VERSION_PATCH >= 7) + *iv_return = DB_LOCK_GET_TIMEOUT; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + if (memEQ(name, "DB_LOCK_SET_TIMEOUT", 19)) { + /* ^ */ +#ifdef DB_LOCK_SET_TIMEOUT + *iv_return = DB_LOCK_SET_TIMEOUT; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + if (memEQ(name, "DB_VERB_REPLICATION", 19)) { + /* ^ */ +#ifdef DB_VERB_REPLICATION + *iv_return = DB_VERB_REPLICATION; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; + case 'G': if (memEQ(name, "DB_TXN_LOG_UNDOREDO", 19)) { - /* ^ */ + /* ^ */ #ifdef DB_TXN_LOG_UNDOREDO *iv_return = DB_TXN_LOG_UNDOREDO; return PERL_constant_ISIV; @@ -3083,9 +3421,20 @@ constant_19 (pTHX_ const char *name, IV *iv_return) { #endif } break; - case 'E': + case 'I': + if (memEQ(name, "DB_TXN_WRITE_NOSYNC", 19)) { + /* ^ */ +#ifdef DB_TXN_WRITE_NOSYNC + *iv_return = DB_TXN_WRITE_NOSYNC; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; + case 'L': if (memEQ(name, "DB_REP_HOLDELECTION", 19)) { - /* ^ */ + /* ^ */ #ifdef DB_REP_HOLDELECTION *iv_return = DB_REP_HOLDELECTION; return PERL_constant_ISIV; @@ -3093,62 +3442,59 @@ constant_19 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_TEST_POSTDESTROY", 19)) { - /* ^ */ -#ifdef DB_TEST_POSTDESTROY - *iv_return = DB_TEST_POSTDESTROY; + if (memEQ(name, "DB_UNRESOLVED_CHILD", 19)) { + /* ^ */ +#ifdef DB_UNRESOLVED_CHILD + *iv_return = DB_UNRESOLVED_CHILD; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'G': - if (memEQ(name, "DB_ENV_REP_LOGSONLY", 19)) { - /* ^ */ -#ifdef DB_ENV_REP_LOGSONLY - *iv_return = DB_ENV_REP_LOGSONLY; + case 'O': + if (memEQ(name, "DB_TEST_POSTDESTROY", 19)) { + /* ^ */ +#ifdef DB_TEST_POSTDESTROY + *iv_return = DB_TEST_POSTDESTROY; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - break; - case 'I': - if (memEQ(name, "DB_LOCK_GET_TIMEOUT", 19)) { - /* ^ */ -#if (DB_VERSION_MAJOR > 4) || \ - (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \ - (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \ - DB_VERSION_PATCH >= 7) - *iv_return = DB_LOCK_GET_TIMEOUT; + if (memEQ(name, "DB_TEST_POSTEXTOPEN", 19)) { + /* ^ */ +#ifdef DB_TEST_POSTEXTOPEN + *iv_return = DB_TEST_POSTEXTOPEN; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_LOCK_SET_TIMEOUT", 19)) { - /* ^ */ -#ifdef DB_LOCK_SET_TIMEOUT - *iv_return = DB_LOCK_SET_TIMEOUT; + if (memEQ(name, "DB_TEST_POSTLOGMETA", 19)) { + /* ^ */ +#ifdef DB_TEST_POSTLOGMETA + *iv_return = DB_TEST_POSTLOGMETA; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_SET_LOCK_TIMEOUT", 19)) { - /* ^ */ -#ifdef DB_SET_LOCK_TIMEOUT - *iv_return = DB_SET_LOCK_TIMEOUT; + break; + case 'P': + if (memEQ(name, "DB_ENV_REP_LOGSONLY", 19)) { + /* ^ */ +#ifdef DB_ENV_REP_LOGSONLY + *iv_return = DB_ENV_REP_LOGSONLY; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'L': + case 'R': if (memEQ(name, "DB_LOCK_FREE_LOCKER", 19)) { - /* ^ */ + /* ^ */ #ifdef DB_LOCK_FREE_LOCKER *iv_return = DB_LOCK_FREE_LOCKER; return PERL_constant_ISIV; @@ -3156,43 +3502,49 @@ constant_19 (pTHX_ const char *name, IV *iv_return) { return PERL_constant_NOTDEF; #endif } - break; - case 'N': - if (memEQ(name, "DB_USE_ENVIRON_ROOT", 19)) { - /* ^ */ -#ifdef DB_USE_ENVIRON_ROOT - *iv_return = DB_USE_ENVIRON_ROOT; + if (memEQ(name, "DB_TXN_FORWARD_ROLL", 19)) { + /* ^ */ +#if (DB_VERSION_MAJOR > 3) || \ + (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \ + (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \ + DB_VERSION_PATCH >= 12) + *iv_return = DB_TXN_FORWARD_ROLL; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'O': - if (memEQ(name, "DB_TEST_POSTLOGMETA", 19)) { - /* ^ */ -#ifdef DB_TEST_POSTLOGMETA - *iv_return = DB_TEST_POSTLOGMETA; + case 'T': + if (memEQ(name, "DB_PRIORITY_DEFAULT", 19)) { + /* ^ */ +#if (DB_VERSION_MAJOR > 4) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \ + DB_VERSION_PATCH >= 12) + *iv_return = DB_PRIORITY_DEFAULT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - if (memEQ(name, "DB_UPDATE_SECONDARY", 19)) { - /* ^ */ -#ifdef DB_UPDATE_SECONDARY - *iv_return = DB_UPDATE_SECONDARY; + break; + case 'U': + if (memEQ(name, "DB_TEST_SUBDB_LOCKS", 19)) { + /* ^ */ +#ifdef DB_TEST_SUBDB_LOCKS + *iv_return = DB_TEST_SUBDB_LOCKS; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'X': - if (memEQ(name, "DB_TEST_POSTEXTOPEN", 19)) { - /* ^ */ -#ifdef DB_TEST_POSTEXTOPEN - *iv_return = DB_TEST_POSTEXTOPEN; + case 'V': + if (memEQ(name, "DB_USE_ENVIRON_ROOT", 19)) { + /* ^ */ +#ifdef DB_USE_ENVIRON_ROOT + *iv_return = DB_USE_ENVIRON_ROOT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; @@ -3200,10 +3552,10 @@ constant_19 (pTHX_ const char *name, IV *iv_return) { } break; case '_': - if (memEQ(name, "DB_UNRESOLVED_CHILD", 19)) { - /* ^ */ -#ifdef DB_UNRESOLVED_CHILD - *iv_return = DB_UNRESOLVED_CHILD; + if (memEQ(name, "DB_UPDATE_SECONDARY", 19)) { + /* ^ */ +#ifdef DB_UPDATE_SECONDARY + *iv_return = DB_UPDATE_SECONDARY; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; @@ -3219,60 +3571,58 @@ constant_20 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. DB_CXX_NO_EXCEPTIONS DB_LOGFILEID_INVALID DB_PANIC_ENVIRONMENT - DB_TEST_PREEXTDELETE DB_TEST_PREEXTUNLINK DB_TXN_BACKWARD_ROLL - DB_TXN_LOCK_OPTIMIST */ - /* Offset 19 gives the best switch position. */ - switch (name[19]) { + DB_PRIORITY_VERY_LOW DB_TEST_PREEXTDELETE DB_TEST_PREEXTUNLINK + DB_TXN_BACKWARD_ROLL DB_TXN_LOCK_OPTIMIST */ + /* Offset 14 gives the best switch position. */ + switch (name[14]) { case 'D': - if (memEQ(name, "DB_LOGFILEID_INVALID", 20)) { - /* ^ */ -#ifdef DB_LOGFILEID_INVALID - *iv_return = DB_LOGFILEID_INVALID; + if (memEQ(name, "DB_TEST_PREEXTDELETE", 20)) { + /* ^ */ +#ifdef DB_TEST_PREEXTDELETE + *iv_return = DB_TEST_PREEXTDELETE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } - break; - case 'E': - if (memEQ(name, "DB_TEST_PREEXTDELETE", 20)) { - /* ^ */ -#ifdef DB_TEST_PREEXTDELETE - *iv_return = DB_TEST_PREEXTDELETE; + if (memEQ(name, "DB_TXN_BACKWARD_ROLL", 20)) { + /* ^ */ +#if (DB_VERSION_MAJOR > 3) || \ + (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \ + (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \ + DB_VERSION_PATCH >= 12) + *iv_return = DB_TXN_BACKWARD_ROLL; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'K': - if (memEQ(name, "DB_TEST_PREEXTUNLINK", 20)) { - /* ^ */ -#ifdef DB_TEST_PREEXTUNLINK - *iv_return = DB_TEST_PREEXTUNLINK; + case 'N': + if (memEQ(name, "DB_LOGFILEID_INVALID", 20)) { + /* ^ */ +#ifdef DB_LOGFILEID_INVALID + *iv_return = DB_LOGFILEID_INVALID; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'L': - if (memEQ(name, "DB_TXN_BACKWARD_ROLL", 20)) { - /* ^ */ -#if (DB_VERSION_MAJOR > 3) || \ - (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \ - (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \ - DB_VERSION_PATCH >= 12) - *iv_return = DB_TXN_BACKWARD_ROLL; + case 'O': + if (memEQ(name, "DB_PANIC_ENVIRONMENT", 20)) { + /* ^ */ +#ifdef DB_PANIC_ENVIRONMENT + *iv_return = DB_PANIC_ENVIRONMENT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; - case 'S': + case 'P': if (memEQ(name, "DB_CXX_NO_EXCEPTIONS", 20)) { - /* ^ */ + /* ^ */ #ifdef DB_CXX_NO_EXCEPTIONS *iv_return = DB_CXX_NO_EXCEPTIONS; return PERL_constant_ISIV; @@ -3281,18 +3631,23 @@ constant_20 (pTHX_ const char *name, IV *iv_return) { #endif } break; - case 'T': - if (memEQ(name, "DB_PANIC_ENVIRONMENT", 20)) { - /* ^ */ -#ifdef DB_PANIC_ENVIRONMENT - *iv_return = DB_PANIC_ENVIRONMENT; + case 'R': + if (memEQ(name, "DB_PRIORITY_VERY_LOW", 20)) { + /* ^ */ +#if (DB_VERSION_MAJOR > 4) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \ + DB_VERSION_PATCH >= 12) + *iv_return = DB_PRIORITY_VERY_LOW; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } + break; + case 'T': if (memEQ(name, "DB_TXN_LOCK_OPTIMIST", 20)) { - /* ^ */ + /* ^ */ #ifdef DB_TXN_LOCK_OPTIMIST *iv_return = DB_TXN_LOCK_OPTIMIST; return PERL_constant_ISIV; @@ -3301,6 +3656,17 @@ constant_20 (pTHX_ const char *name, IV *iv_return) { #endif } break; + case 'U': + if (memEQ(name, "DB_TEST_PREEXTUNLINK", 20)) { + /* ^ */ +#ifdef DB_TEST_PREEXTUNLINK + *iv_return = DB_TEST_PREEXTUNLINK; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; } return PERL_constant_NOTFOUND; } @@ -3309,7 +3675,8 @@ static int constant_21 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. - DB_LOCK_UPGRADE_WRITE DB_TEST_POSTEXTDELETE DB_TEST_POSTEXTUNLINK */ + DB_LOCK_UPGRADE_WRITE DB_PRIORITY_VERY_HIGH DB_TEST_POSTEXTDELETE + DB_TEST_POSTEXTUNLINK */ /* Offset 16 gives the best switch position. */ switch (name[16]) { case 'E': @@ -3348,6 +3715,20 @@ constant_21 (pTHX_ const char *name, IV *iv_return) { #endif } break; + case '_': + if (memEQ(name, "DB_PRIORITY_VERY_HIGH", 21)) { + /* ^ */ +#if (DB_VERSION_MAJOR > 4) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \ + (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \ + DB_VERSION_PATCH >= 12) + *iv_return = DB_PRIORITY_VERY_HIGH; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; } return PERL_constant_NOTFOUND; } @@ -3365,57 +3746,62 @@ constant (pTHX_ const char *name, STRLEN len, IV *iv_return, const char **pv_ret Regenerate these constant functions by feeding this entire source file to perl -x -#!bleedperl -w +#!/home/paul/perl/install/redhat6.1/5.8.0/bin/perl5.8.0 -w use ExtUtils::Constant qw (constant_types C_constant XS_constant); my $types = {map {($_, 1)} qw(IV PV)}; my @names = (qw(DB_AFTER DB_AGGRESSIVE DB_ALREADY_ABORTED DB_APPEND DB_APPLY_LOGREG DB_APP_INIT DB_ARCH_ABS DB_ARCH_DATA DB_ARCH_LOG - DB_BEFORE DB_BROADCAST_EID DB_BTREEMAGIC DB_BTREEOLDVER - DB_BTREEVERSION DB_CACHED_COUNTS DB_CDB_ALLDB DB_CHECKPOINT - DB_CLIENT DB_CL_WRITER DB_COMMIT DB_CONSUME DB_CONSUME_WAIT - DB_CREATE DB_CURLSN DB_CURRENT DB_CXX_NO_EXCEPTIONS DB_DELETED - DB_DELIMITER DB_DIRTY_READ DB_DONOTINDEX DB_DUP DB_DUPCURSOR - DB_DUPSORT DB_ENV_APPINIT DB_ENV_CDB DB_ENV_CDB_ALLDB - DB_ENV_CREATE DB_ENV_DBLOCAL DB_ENV_LOCKDOWN DB_ENV_LOCKING + DB_AUTO_COMMIT DB_BEFORE DB_BROADCAST_EID DB_BTREEMAGIC + DB_BTREEOLDVER DB_BTREEVERSION DB_CACHED_COUNTS DB_CDB_ALLDB + DB_CHECKPOINT DB_CHKSUM_SHA1 DB_CLIENT DB_CL_WRITER DB_COMMIT + DB_CONSUME DB_CONSUME_WAIT DB_CREATE DB_CURLSN DB_CURRENT + DB_CXX_NO_EXCEPTIONS DB_DELETED DB_DELIMITER DB_DIRECT + DB_DIRECT_DB DB_DIRECT_LOG DB_DIRTY_READ DB_DONOTINDEX DB_DUP + DB_DUPCURSOR DB_DUPSORT DB_EID_BROADCAST DB_EID_INVALID + DB_ENCRYPT DB_ENCRYPT_AES DB_ENV_APPINIT DB_ENV_CDB + DB_ENV_CDB_ALLDB DB_ENV_CREATE DB_ENV_DBLOCAL DB_ENV_DIRECT_DB + DB_ENV_DIRECT_LOG DB_ENV_FATAL DB_ENV_LOCKDOWN DB_ENV_LOCKING DB_ENV_LOGGING DB_ENV_NOLOCKING DB_ENV_NOMMAP DB_ENV_NOPANIC - DB_ENV_OPEN_CALLED DB_ENV_PANIC_OK DB_ENV_PRIVATE - DB_ENV_REGION_INIT DB_ENV_REP_CLIENT DB_ENV_REP_LOGSONLY - DB_ENV_REP_MASTER DB_ENV_RPCCLIENT DB_ENV_RPCCLIENT_GIVEN - DB_ENV_STANDALONE DB_ENV_SYSTEM_MEM DB_ENV_THREAD DB_ENV_TXN - DB_ENV_TXN_NOSYNC DB_ENV_USER_ALLOC DB_ENV_YIELDCPU DB_EXCL - DB_EXTENT DB_FAST_STAT DB_FCNTL_LOCKING DB_FILE_ID_LEN DB_FIRST - DB_FIXEDLEN DB_FLUSH DB_FORCE DB_GETREC DB_GET_BOTH DB_GET_BOTHC - DB_GET_BOTH_RANGE DB_GET_RECNO DB_HASHMAGIC DB_HASHOLDVER - DB_HASHVERSION DB_INCOMPLETE DB_INIT_CDB DB_INIT_LOCK - DB_INIT_LOG DB_INIT_MPOOL DB_INIT_TXN DB_INVALID_EID - DB_JAVA_CALLBACK DB_JOINENV DB_JOIN_ITEM DB_JOIN_NOSORT - DB_KEYEMPTY DB_KEYEXIST DB_KEYFIRST DB_KEYLAST DB_LAST - DB_LOCKDOWN DB_LOCKMAGIC DB_LOCKVERSION DB_LOCK_CONFLICT + DB_ENV_OPEN_CALLED DB_ENV_OVERWRITE DB_ENV_PANIC_OK + DB_ENV_PRIVATE DB_ENV_REGION_INIT DB_ENV_REP_CLIENT + DB_ENV_REP_LOGSONLY DB_ENV_REP_MASTER DB_ENV_RPCCLIENT + DB_ENV_RPCCLIENT_GIVEN DB_ENV_STANDALONE DB_ENV_SYSTEM_MEM + DB_ENV_THREAD DB_ENV_TXN DB_ENV_TXN_NOSYNC + DB_ENV_TXN_WRITE_NOSYNC DB_ENV_USER_ALLOC DB_ENV_YIELDCPU + DB_EXCL DB_EXTENT DB_FAST_STAT DB_FCNTL_LOCKING DB_FILE_ID_LEN + DB_FIRST DB_FIXEDLEN DB_FLUSH DB_FORCE DB_GETREC DB_GET_BOTH + DB_GET_BOTHC DB_GET_BOTH_RANGE DB_GET_RECNO DB_HANDLE_LOCK + DB_HASHMAGIC DB_HASHOLDVER DB_HASHVERSION DB_INCOMPLETE + DB_INIT_CDB DB_INIT_LOCK DB_INIT_LOG DB_INIT_MPOOL DB_INIT_TXN + DB_INVALID_EID DB_JAVA_CALLBACK DB_JOINENV DB_JOIN_ITEM + DB_JOIN_NOSORT DB_KEYEMPTY DB_KEYEXIST DB_KEYFIRST DB_KEYLAST + DB_LAST DB_LOCKDOWN DB_LOCKMAGIC DB_LOCKVERSION DB_LOCK_CONFLICT DB_LOCK_DEADLOCK DB_LOCK_DEFAULT DB_LOCK_EXPIRE DB_LOCK_FREE_LOCKER DB_LOCK_MAXLOCKS DB_LOCK_MINLOCKS - DB_LOCK_MINWRITE DB_LOCK_NORUN DB_LOCK_NOTGRANTED - DB_LOCK_NOTHELD DB_LOCK_NOWAIT DB_LOCK_OLDEST DB_LOCK_RANDOM - DB_LOCK_RECORD DB_LOCK_RIW_N DB_LOCK_RW_N DB_LOCK_SET_TIMEOUT - DB_LOCK_SWITCH DB_LOCK_UPGRADE DB_LOCK_YOUNGEST DB_LOGC_BUF_SIZE - DB_LOGFILEID_INVALID DB_LOGMAGIC DB_LOGOLDVER DB_LOGVERSION - DB_LOG_DISK DB_LOG_LOCKED DB_LOG_SILENT_ERR DB_MAX_PAGES - DB_MAX_RECORDS DB_MPOOL_CLEAN DB_MPOOL_CREATE DB_MPOOL_DIRTY - DB_MPOOL_DISCARD DB_MPOOL_EXTENT DB_MPOOL_LAST DB_MPOOL_NEW - DB_MPOOL_NEW_GROUP DB_MPOOL_PRIVATE DB_MULTIPLE DB_MULTIPLE_KEY - DB_MUTEXDEBUG DB_MUTEXLOCKS DB_NEEDSPLIT DB_NEXT DB_NEXT_DUP - DB_NEXT_NODUP DB_NODUPDATA DB_NOLOCKING DB_NOMMAP DB_NOORDERCHK - DB_NOOVERWRITE DB_NOPANIC DB_NORECURSE DB_NOSERVER - DB_NOSERVER_HOME DB_NOSERVER_ID DB_NOSYNC DB_NOTFOUND - DB_ODDFILESIZE DB_OK_BTREE DB_OK_HASH DB_OK_QUEUE DB_OK_RECNO - DB_OLD_VERSION DB_OPEN_CALLED DB_OPFLAGS_MASK DB_ORDERCHKONLY - DB_PAD DB_PAGEYIELD DB_PAGE_LOCK DB_PAGE_NOTFOUND - DB_PANIC_ENVIRONMENT DB_POSITION DB_POSITIONI DB_PREV - DB_PREV_NODUP DB_PRIVATE DB_PR_HEADERS DB_PR_PAGE - DB_PR_RECOVERYTEST DB_QAMMAGIC DB_QAMOLDVER DB_QAMVERSION - DB_RDONLY DB_RDWRMASTER DB_RECNUM DB_RECORDCOUNT DB_RECORD_LOCK - DB_RECOVER DB_RECOVER_FATAL DB_REGION_ANON DB_REGION_INIT - DB_REGION_MAGIC DB_REGION_NAME DB_REGISTERED DB_RENUMBER + DB_LOCK_MINWRITE DB_LOCK_NORUN DB_LOCK_NOTEXIST + DB_LOCK_NOTGRANTED DB_LOCK_NOTHELD DB_LOCK_NOWAIT DB_LOCK_OLDEST + DB_LOCK_RANDOM DB_LOCK_RECORD DB_LOCK_REMOVE DB_LOCK_RIW_N + DB_LOCK_RW_N DB_LOCK_SET_TIMEOUT DB_LOCK_SWITCH DB_LOCK_UPGRADE + DB_LOCK_YOUNGEST DB_LOGC_BUF_SIZE DB_LOGFILEID_INVALID + DB_LOGMAGIC DB_LOGOLDVER DB_LOGVERSION DB_LOG_DISK DB_LOG_LOCKED + DB_LOG_SILENT_ERR DB_MAX_PAGES DB_MAX_RECORDS DB_MPOOL_CLEAN + DB_MPOOL_CREATE DB_MPOOL_DIRTY DB_MPOOL_DISCARD DB_MPOOL_EXTENT + DB_MPOOL_LAST DB_MPOOL_NEW DB_MPOOL_NEW_GROUP DB_MPOOL_PRIVATE + DB_MULTIPLE DB_MULTIPLE_KEY DB_MUTEXDEBUG DB_MUTEXLOCKS + DB_NEEDSPLIT DB_NEXT DB_NEXT_DUP DB_NEXT_NODUP DB_NOCOPY + DB_NODUPDATA DB_NOLOCKING DB_NOMMAP DB_NOORDERCHK DB_NOOVERWRITE + DB_NOPANIC DB_NORECURSE DB_NOSERVER DB_NOSERVER_HOME + DB_NOSERVER_ID DB_NOSYNC DB_NOTFOUND DB_ODDFILESIZE DB_OK_BTREE + DB_OK_HASH DB_OK_QUEUE DB_OK_RECNO DB_OLD_VERSION DB_OPEN_CALLED + DB_OPFLAGS_MASK DB_ORDERCHKONLY DB_OVERWRITE DB_PAD DB_PAGEYIELD + DB_PAGE_LOCK DB_PAGE_NOTFOUND DB_PANIC_ENVIRONMENT DB_PERMANENT + DB_POSITION DB_POSITIONI DB_PREV DB_PREV_NODUP DB_PRINTABLE + DB_PRIVATE DB_PR_HEADERS DB_PR_PAGE DB_PR_RECOVERYTEST + DB_QAMMAGIC DB_QAMOLDVER DB_QAMVERSION DB_RDONLY DB_RDWRMASTER + DB_RECNUM DB_RECORDCOUNT DB_RECORD_LOCK DB_RECOVER + DB_RECOVER_FATAL DB_REGION_ANON DB_REGION_INIT DB_REGION_MAGIC + DB_REGION_NAME DB_REGISTERED DB_RENAMEMAGIC DB_RENUMBER DB_REP_CLIENT DB_REP_DUPMASTER DB_REP_HOLDELECTION DB_REP_LOGSONLY DB_REP_MASTER DB_REP_NEWMASTER DB_REP_NEWSITE DB_REP_OUTDATED DB_REP_PERMANENT DB_REP_UNAVAIL DB_REVSPLITOFF @@ -3428,17 +3814,19 @@ my @names = (qw(DB_AFTER DB_AGGRESSIVE DB_ALREADY_ABORTED DB_APPEND DB_TEST_POSTLOG DB_TEST_POSTLOGMETA DB_TEST_POSTOPEN DB_TEST_POSTRENAME DB_TEST_POSTSYNC DB_TEST_PREDESTROY DB_TEST_PREEXTDELETE DB_TEST_PREEXTOPEN DB_TEST_PREEXTUNLINK - DB_TEST_PREOPEN DB_TEST_PRERENAME DB_THREAD DB_TIMEOUT - DB_TRUNCATE DB_TXNMAGIC DB_TXNVERSION DB_TXN_CKP DB_TXN_LOCK_2PL - DB_TXN_LOCK_MASK DB_TXN_LOCK_OPTIMIST DB_TXN_LOCK_OPTIMISTIC - DB_TXN_LOG_MASK DB_TXN_LOG_REDO DB_TXN_LOG_UNDO - DB_TXN_LOG_UNDOREDO DB_TXN_NOSYNC DB_TXN_NOWAIT DB_TXN_REDO - DB_TXN_SYNC DB_TXN_UNDO DB_UNRESOLVED_CHILD DB_UPDATE_SECONDARY + DB_TEST_PREOPEN DB_TEST_PRERENAME DB_TEST_SUBDB_LOCKS DB_THREAD + DB_TIMEOUT DB_TRUNCATE DB_TXNMAGIC DB_TXNVERSION DB_TXN_CKP + DB_TXN_LOCK DB_TXN_LOCK_2PL DB_TXN_LOCK_MASK + DB_TXN_LOCK_OPTIMIST DB_TXN_LOCK_OPTIMISTIC DB_TXN_LOG_MASK + DB_TXN_LOG_REDO DB_TXN_LOG_UNDO DB_TXN_LOG_UNDOREDO + DB_TXN_NOSYNC DB_TXN_NOWAIT DB_TXN_REDO DB_TXN_SYNC DB_TXN_UNDO + DB_TXN_WRITE_NOSYNC DB_UNRESOLVED_CHILD DB_UPDATE_SECONDARY DB_UPGRADE DB_USE_ENVIRON DB_USE_ENVIRON_ROOT DB_VERB_CHKPOINT - DB_VERB_DEADLOCK DB_VERB_RECOVERY DB_VERB_WAITSFOR DB_VERIFY - DB_VERIFY_BAD DB_VERIFY_FATAL DB_VERSION_MAJOR DB_VERSION_MINOR - DB_VERSION_PATCH DB_VRFY_FLAGMASK DB_WRITECURSOR DB_WRITELOCK - DB_XA_CREATE DB_XIDDATASIZE DB_YIELDCPU), + DB_VERB_DEADLOCK DB_VERB_RECOVERY DB_VERB_REPLICATION + DB_VERB_WAITSFOR DB_VERIFY DB_VERIFY_BAD DB_VERIFY_FATAL + DB_VERSION_MAJOR DB_VERSION_MINOR DB_VERSION_PATCH + DB_VRFY_FLAGMASK DB_WRITECURSOR DB_WRITELOCK DB_WRITEOPEN + DB_WRNOSYNC DB_XA_CREATE DB_XIDDATASIZE DB_YIELDCPU), {name=>"DB_BTREE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]}, {name=>"DB_HASH", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]}, {name=>"DB_LOCK_DUMP", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]}, @@ -3450,15 +3838,23 @@ my @names = (qw(DB_AFTER DB_AGGRESSIVE DB_ALREADY_ABORTED DB_APPEND {name=>"DB_LOCK_PUT_OBJ", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]}, {name=>"DB_LOCK_PUT_READ", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 7)\n", "#endif\n"]}, {name=>"DB_LOCK_TIMEOUT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 7)\n", "#endif\n"]}, + {name=>"DB_LOCK_TRADE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]}, {name=>"DB_LOCK_UPGRADE_WRITE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \\\n DB_VERSION_PATCH >= 4)\n", "#endif\n"]}, + {name=>"DB_PRIORITY_DEFAULT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]}, + {name=>"DB_PRIORITY_HIGH", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]}, + {name=>"DB_PRIORITY_LOW", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]}, + {name=>"DB_PRIORITY_VERY_HIGH", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]}, + {name=>"DB_PRIORITY_VERY_LOW", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]}, {name=>"DB_QUEUE", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 55)\n", "#endif\n"]}, {name=>"DB_RECNO", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]}, {name=>"DB_TXN_ABORT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]}, {name=>"DB_TXN_APPLY", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 7)\n", "#endif\n"]}, {name=>"DB_TXN_BACKWARD_ROLL", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]}, {name=>"DB_TXN_FORWARD_ROLL", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]}, + {name=>"DB_TXN_GETPGNOS", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]}, {name=>"DB_TXN_OPENFILES", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]}, {name=>"DB_TXN_POPENFILES", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 3) || \\\n (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && \\\n DB_VERSION_PATCH >= 4)\n", "#endif\n"]}, + {name=>"DB_TXN_PRINT", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 4) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1) || \\\n (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && \\\n DB_VERSION_PATCH >= 12)\n", "#endif\n"]}, {name=>"DB_UNKNOWN", type=>"IV", macro=>["#if (DB_VERSION_MAJOR > 2) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 0) || \\\n (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 0 && \\\n DB_VERSION_PATCH >= 0)\n", "#endif\n"]}, {name=>"DB_VERSION_STRING", type=>"PV"}); @@ -3549,6 +3945,16 @@ __END__ break; } break; + case 23: + if (memEQ(name, "DB_ENV_TXN_WRITE_NOSYNC", 23)) { +#ifdef DB_ENV_TXN_WRITE_NOSYNC + *iv_return = DB_ENV_TXN_WRITE_NOSYNC; + return PERL_constant_ISIV; +#else + return PERL_constant_NOTDEF; +#endif + } + break; } return PERL_constant_NOTFOUND; } diff --git a/db/perl/BerkeleyDB/dbinfo b/db/perl/BerkeleyDB/dbinfo index 415411aff..af2c45fac 100755 --- a/db/perl/BerkeleyDB/dbinfo +++ b/db/perl/BerkeleyDB/dbinfo @@ -7,7 +7,7 @@ # Version: 1.03 # Date 17th September 2000 # -# Copyright (c) 1998-2001 Paul Marquess. All rights reserved. +# Copyright (c) 1998-2002 Paul Marquess. All rights reserved. # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. @@ -29,7 +29,8 @@ my %Data = 5 => "2.0.0 -> 2.3.0", 6 => "2.3.1 -> 2.7.7", 7 => "3.0.x", - 8 => "3.1.x or greater", + 8 => "3.1.x -> 4.0.x", + 9 => "4.1.x or greater", } }, 0x061561 => { @@ -42,7 +43,8 @@ my %Data = 4 => "2.0.0 -> 2.1.0", 5 => "2.2.6 -> 2.7.7", 6 => "3.0.x", - 7 => "3.1.x or greater", + 7 => "3.1.x -> 4.0.x", + 8 => "4.1.x or greater", } }, 0x042253 => { @@ -51,7 +53,8 @@ my %Data = { 1 => "3.0.x", 2 => "3.1.x", - 3 => "3.2.x or greater", + 3 => "3.2.x -> 4.0.x", + 4 => "4.1.x or greater", } }, ) ; diff --git a/db/perl/BerkeleyDB/mkconsts b/db/perl/BerkeleyDB/mkconsts index dc90ea970..8f194662c 100644 --- a/db/perl/BerkeleyDB/mkconsts +++ b/db/perl/BerkeleyDB/mkconsts @@ -597,6 +597,78 @@ use constant IGNORE => 'ignore' ; # enum db_status_t DB_LSTAT_EXPIRED => IGNORE, # 4.0.7 + ######### + # 4.0.14 + ######### + + DB_EID_BROADCAST => DEFINE, + DB_EID_INVALID => DEFINE, + DB_VERB_REPLICATION => DEFINE, + + ######### + # 4.1.12 + ######### + + DBC_OWN_LID => IGNORE, + DB_AM_CHKSUM => IGNORE, + DB_AM_CL_WRITER => IGNORE, + DB_AM_COMPENSATE => IGNORE, + DB_AM_CREATED => IGNORE, + DB_AM_CREATED_MSTR => IGNORE, + DB_AM_DBM_ERROR => IGNORE, + DB_AM_DELIMITER => IGNORE, + DB_AM_ENCRYPT => IGNORE, + DB_AM_FIXEDLEN => IGNORE, + DB_AM_IN_RENAME => IGNORE, + DB_AM_OPEN_CALLED => IGNORE, + DB_AM_PAD => IGNORE, + DB_AM_RECNUM => IGNORE, + DB_AM_RENUMBER => IGNORE, + DB_AM_REVSPLITOFF => IGNORE, + DB_AM_SNAPSHOT => IGNORE, + DB_AUTO_COMMIT => DEFINE, + DB_CHKSUM_SHA1 => DEFINE, + DB_DIRECT => DEFINE, + DB_DIRECT_DB => DEFINE, + DB_DIRECT_LOG => DEFINE, + DB_ENCRYPT => DEFINE, + DB_ENCRYPT_AES => DEFINE, + DB_ENV_DIRECT_DB => DEFINE, + DB_ENV_DIRECT_LOG => DEFINE, + DB_ENV_FATAL => DEFINE, + DB_ENV_OVERWRITE => DEFINE, + DB_ENV_TXN_WRITE_NOSYNC => DEFINE, + DB_HANDLE_LOCK => DEFINE, + DB_LOCK_NOTEXIST => DEFINE, + DB_LOCK_REMOVE => DEFINE, + DB_NOCOPY => DEFINE, + DB_OVERWRITE => DEFINE, + DB_PERMANENT => DEFINE, + DB_PRINTABLE => DEFINE, + DB_RENAMEMAGIC => DEFINE, + DB_TEST_SUBDB_LOCKS => DEFINE, + DB_TXN_LOCK => DEFINE, + DB_TXN_WRITE_NOSYNC => DEFINE, + DB_WRITEOPEN => DEFINE, + DB_WRNOSYNC => DEFINE, + _DB_EXT_PROT_IN_ => IGNORE, + + # enum db_lockop_t + DB_LOCK_TRADE => '4.1.12', + + # enum db_status_t + DB_LSTAT_NOTEXIST => IGNORE, # 4.1.12 + + # enum DB_CACHE_PRIORITY + DB_PRIORITY_VERY_LOW => '4.1.12', + DB_PRIORITY_LOW => '4.1.12', + DB_PRIORITY_DEFAULT => '4.1.12', + DB_PRIORITY_HIGH => '4.1.12', + DB_PRIORITY_VERY_HIGH => '4.1.12', + + # enum db_recops + DB_TXN_GETPGNOS => '4.1.12', + DB_TXN_PRINT => '4.1.12', ) ; sub enum_Macro @@ -632,6 +704,7 @@ sub OutputXS { push @names, { name => $key, macro => [enum_Macro($val), "#endif\n"] } } } + warn "Updating constants.xs & constants.h...\n"; WriteConstants( NAME => BerkeleyDB, NAMES => \@names, @@ -642,37 +715,47 @@ sub OutputXS sub OutputPM { + my $filename = 'BerkeleyDB.pm'; + warn "Updating $filename...\n"; + open IN, "<$filename" || die "Cannot open $filename: $!\n"; + open OUT, ">$filename.tmp" || die "Cannot open $filename.tmp: $!\n"; + my $START = '@EXPORT = qw(' ; my $START_re = quotemeta $START ; my $END = ');'; my $END_re = quotemeta $END ; # skip to the @EXPORT declaration - OUTER: while (<>) + OUTER: while (<IN>) { if ( /^\s*$START_re/ ) { # skip to the end marker. - while (<>) + while (<IN>) { last OUTER if /^\s*$END_re/ } } - print ; + print OUT ; } - print "$START\n"; + print OUT "$START\n"; foreach my $key (sort keys %constants) { next if $constants{$key} eq IGNORE; - print "\t$key\n"; + print OUT "\t$key\n"; } - print "\t$END\n"; + print OUT "\t$END\n"; - while (<>) + while (<IN>) { - print ; + print OUT ; } + + close IN; + close OUT; + + rename $filename, "$filename.bak" || die "Cannot rename $filename: $!\n" ; + rename "$filename.tmp", $filename || die "Cannot rename $filename.tmp: $!\n" ; } -my $opt = shift ; -OutputXS() if $opt =~ /^xs/i ; -OutputPM() if $opt =~ /^pm/i ; +OutputXS() ; +OutputPM() ; diff --git a/db/perl/DB_File/Changes b/db/perl/DB_File/Changes index b0068feac..0922227e4 100644 --- a/db/perl/DB_File/Changes +++ b/db/perl/DB_File/Changes @@ -395,3 +395,24 @@ * Added "clean" attribute to Makefile.PL +1.802 6th January 2002 + + * The message about some test failing in db-recno.t had the wrong test + numbers. Fixed. + + * merged core patch 13942. + +1.803 1st March 2002 + + * Fixed a problem with db-btree.t where it complained about an "our" + variable redeclaation. + + * FETCH, STORE & DELETE don't map the flags parameter into the + equivalent Berkeley DB function anymore. + +1.804 2nd June 2002 + + * Perl core patch 14939 added a new warning to "splice". This broke the + db-recno test harness. Fixed. + + * merged core patches 16502 & 16540. diff --git a/db/perl/DB_File/DB_File.pm b/db/perl/DB_File/DB_File.pm index b83877f0c..ff3c05947 100644 --- a/db/perl/DB_File/DB_File.pm +++ b/db/perl/DB_File/DB_File.pm @@ -1,10 +1,10 @@ # DB_File.pm -- Perl 5 interface to Berkeley DB # # written by Paul Marquess (Paul.Marquess@btinternet.com) -# last modified 26th Nov 2001 -# version 1.801 +# last modified 2nd June 2002 +# version 1.804 # -# Copyright (c) 1995-2001 Paul Marquess. All rights reserved. +# Copyright (c) 1995-2002 Paul Marquess. All rights reserved. # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. @@ -146,11 +146,18 @@ package DB_File ; use warnings; use strict; our ($VERSION, @ISA, @EXPORT, $AUTOLOAD, $DB_BTREE, $DB_HASH, $DB_RECNO); -our ($db_version, $use_XSLoader); +our ($db_version, $use_XSLoader, $splice_end_array); use Carp; -$VERSION = "1.801" ; +$VERSION = "1.804" ; + +{ + local $SIG{__WARN__} = sub {$splice_end_array = "@_";}; + my @a =(1); splice(@a, 3); + $splice_end_array = + ($splice_end_array =~ /^splice\(\) offset past end of array at /); +} #typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE; $DB_BTREE = new DB_File::BTREEINFO ; @@ -303,7 +310,7 @@ sub SPLICE my $self = shift; my $offset = shift; if (not defined $offset) { - carp 'Use of uninitialized value in splice'; + warnings::warnif('uninitialized', 'Use of uninitialized value in splice'); $offset = 0; } @@ -328,15 +335,17 @@ sub SPLICE $offset = $new_offset; } - if ($offset > $size) { - $offset = $size; - } - if (not defined $length) { - carp 'Use of uninitialized value in splice'; + warnings::warnif('uninitialized', 'Use of uninitialized value in splice'); $length = 0; } + if ($offset > $size) { + $offset = $size; + warnings::warnif('misc', 'splice() offset past end of array') + if $splice_end_array; + } + # 'If LENGTH is omitted, removes everything from OFFSET onward.' if (not defined $length) { $length = $size - $offset; @@ -978,7 +987,7 @@ code: use strict ; use DB_File ; - our ($filename, %h) ; + my ($filename, %h) ; $filename = "tree" ; unlink $filename ; @@ -1033,7 +1042,7 @@ Here is the script above rewritten using the C<seq> API method. use strict ; use DB_File ; - our ($filename, $x, %h, $status, $key, $value) ; + my ($filename, $x, %h, $status, $key, $value) ; $filename = "tree" ; unlink $filename ; @@ -1105,7 +1114,7 @@ this: use strict ; use DB_File ; - our ($filename, $x, %h) ; + my ($filename, $x, %h) ; $filename = "tree" ; @@ -1155,7 +1164,7 @@ Assuming the database from the previous example: use strict ; use DB_File ; - our ($filename, $x, %h, $found) ; + my ($filename, $x, %h, $found) ; $filename = "tree" ; @@ -1194,7 +1203,7 @@ Again assuming the existence of the C<tree> database use strict ; use DB_File ; - our ($filename, $x, %h, $found) ; + my ($filename, $x, %h, $found) ; $filename = "tree" ; @@ -1240,7 +1249,7 @@ and print the first matching key/value pair given a partial key. use DB_File ; use Fcntl ; - our ($filename, $x, %h, $st, $key, $value) ; + my ($filename, $x, %h, $st, $key, $value) ; sub match { @@ -1439,7 +1448,7 @@ L<THE API INTERFACE>). use warnings ; use strict ; - our (@h, $H, $file, $i) ; + my (@h, $H, $file, $i) ; use DB_File ; use Fcntl ; @@ -2004,7 +2013,7 @@ F<authors/id/TOMC/scripts/nshist.gz>). use DB_File ; use Fcntl ; - our ($dotdir, $HISTORY, %hist_db, $href, $binary_time, $date) ; + my ($dotdir, $HISTORY, %hist_db, $href, $binary_time, $date) ; $dotdir = $ENV{HOME} || $ENV{LOGNAME}; $HISTORY = "$dotdir/.netscape/history.db"; @@ -2225,7 +2234,7 @@ compile properly on IRIX 5.3. =head1 COPYRIGHT -Copyright (c) 1995-2001 Paul Marquess. All rights reserved. This program +Copyright (c) 1995-2002 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. diff --git a/db/perl/DB_File/DB_File.xs b/db/perl/DB_File/DB_File.xs index c788b987f..6882491e4 100644 --- a/db/perl/DB_File/DB_File.xs +++ b/db/perl/DB_File/DB_File.xs @@ -3,12 +3,12 @@ DB_File.xs -- Perl 5 interface to Berkeley DB written by Paul Marquess <Paul.Marquess@btinternet.com> - last modified 26th Nov 2001 - version 1.801 + last modified 2nd June 2002 + version 1.804 All comments/suggestions/problems are welcome - Copyright (c) 1995-2001 Paul Marquess. All rights reserved. + Copyright (c) 1995-2002 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. @@ -98,7 +98,9 @@ 1.800 - Moved backward compatability code into ppport.h. Use the new constants code. 1.801 - No change to DB_File.xs - + 1.802 - No change to DB_File.xs + 1.803 - FETCH, STORE & DELETE don't map the flags parameter + into the equivalent Berkeley DB function anymore. */ #define PERL_NO_GET_CONTEXT @@ -122,8 +124,6 @@ # undef __attribute__ #endif - - #ifdef COMPAT185 # include <db_185.h> #else @@ -326,9 +326,9 @@ typedef union INFO { -#define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, flags) -#define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, flags) -#define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) +#define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, 0) +#define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, 0) +#define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, 0) #define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags) #define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags) diff --git a/db/perl/DB_File/Makefile.PL b/db/perl/DB_File/Makefile.PL index 7f4537269..d38a42edd 100644 --- a/db/perl/DB_File/Makefile.PL +++ b/db/perl/DB_File/Makefile.PL @@ -41,7 +41,7 @@ $OS2 = "-DOS2" if $Config{'osname'} eq 'os2' ; WriteMakefile( NAME => 'DB_File', LIBS => ["-L${LIB_DIR} $LIBS"], - MAN3PODS => ' ', # Pods will be built by installman. + MAN3PODS => {}, # Pods will be built by installman. INC => "-I$INC_DIR", VERSION_FROM => 'DB_File.pm', XSPROTOARG => '-noprototypes', @@ -254,16 +254,29 @@ sub UpDowngrade if ($] < 5.006001) { # From: use|no warnings "blah" # To: local ($^W) = 1; # use|no warnings "blah" + # + # and + # + # From: warnings::warnif(x,y); + # To: $^W && carp(y); # warnif -- x $warn_sub = sub { s/^(\s*)(no\s+warnings)/${1}local (\$^W) = 0; #$2/ ; s/^(\s*)(use\s+warnings)/${1}local (\$^W) = 1; #$2/ ; + + s/^(\s*)warnings::warnif\s*\((.*?)\s*,\s*(.*?)\)\s*;/${1}\$^W && carp($3); # warnif - $2/ ; }; } else { # From: local ($^W) = 1; # use|no warnings "blah" # To: use|no warnings "blah" + # + # and + # + # From: $^W && carp(y); # warnif -- x + # To: warnings::warnif(x,y); $warn_sub = sub { s/^(\s*)local\s*\(\$\^W\)\s*=\s*\d+\s*;\s*#\s*((no|use)\s+warnings.*)/$1$2/ ; + s/^(\s*)\$\^W\s+\&\&\s*carp\s*\((.*?)\)\s*;\s*#\s*warnif\s*-\s*(.*)/${1}warnings::warnif($3, $2);/ ; }; } diff --git a/db/perl/DB_File/README b/db/perl/DB_File/README index b3eaf266a..1505f7385 100644 --- a/db/perl/DB_File/README +++ b/db/perl/DB_File/README @@ -1,10 +1,10 @@ DB_File - Version 1.801 + Version 1.804 - 26th Nov 2001 + 2nd June 2002 - Copyright (c) 1995-2001 Paul Marquess. All rights reserved. This + Copyright (c) 1995-2002 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. @@ -22,7 +22,7 @@ DESCRIPTION DB_File is a module which allows Perl programs to make use of the facilities provided by Berkeley DB version 1. (DB_File can be built -version 2,i 3 or 4 of Berkeley DB, but it will only support the 1.x +version 2, 3 or 4 of Berkeley DB, but it will only support the 1.x features), If you want to make use of the new features available in Berkeley DB @@ -298,8 +298,8 @@ To find out if you have the patch installed, the command "showrev -p" will display the patches that are currently installed on your system. -HP-UX Notes ------------ +HP-UX 10 Notes +-------------- Some people running HP-UX 10 have reported getting an error like this when building DB_File with the native HP-UX compiler. @@ -324,6 +324,22 @@ following steps should do the trick: 3: Build and install the Berkeley DB distribution as usual. +HP-UX 11 Notes +-------------- + +Some people running the combination of HP-UX 11 and Berkeley DB 2.7.7 have +reported getting this error when the run the test harness for DB_File + + ... + lib/db-btree.........Can't call method "DELETE" on an undefined value at lib/db-btree.t line 216. + FAILED at test 26 + lib/db-hash..........Can't call method "DELETE" on an undefined value at lib/db-hash.t line 183. + FAILED at test 22 + ... + +The fix for this is to rebuild and install Berkeley DB with the bigfile +option disabled. + IRIX NOTES ---------- @@ -338,21 +354,23 @@ FEEDBACK How to report a problem with DB_File. -To help me help you, I need the following information: +When reporting any problem, I need the information requested below. + + 1. The *complete* output from running this - 1. The version of Perl and the operating system name and version you - are running. The *complete* output from running "perl -V" will - tell me all I need to know. Don't edit the output in any way. Note, - I want you to run "perl -V" and NOT "perl -v". + perl -V - If your perl does not understand the "-V" option it is too old. DB_File - needs Perl version 5.004 or better. + Do not edit the output in any way. + Note, I want you to run "perl -V" and NOT "perl -v". + + If your perl does not understand the "-V" option it is too + old. DB_File needs Perl version 5.00405 or better. 2. The version of DB_File you have. If you have successfully installed DB_File, this one-liner will tell you: - perl -e 'use DB_File; print "DB_File ver $DB_File::VERSION\n"' + perl -e 'use DB_File; print qq{DB_File ver $DB_File::VERSION\n}' If you haven't installed DB_File then search DB_File.pm for a line like this: @@ -367,12 +385,27 @@ To help me help you, I need the following information: If you have successfully installed DB_File, this command will display the version of Berkeley DB it was built with: - perl -e 'use DB_File; print "Berkeley DB ver $DB_File::db_ver\n"' + perl -e 'use DB_File; print qq{Berkeley DB ver $DB_File::db_ver\n}' + + 4. A copy the file config.in from the DB_File main source directory. + + 5. A listing of directories where Berkeley DB is installed. + For example, if Berkeley DB is installed in /usr/BerkeleDB/lib and + /usr/BerkeleyDB/include, I need the output from running this + + ls -l /usr/BerkeleyDB/lib + ls -l /usr/BerkeleyDB/include + + 6. If you are having problems building DB_File, send me a complete log + of what happened. Start by unpacking the DB_File module into a fresh + directory and keep a log of all the steps - 4. If you are having problems building DB_File, send me a complete log - of what happened. + [edit config.in, if necessary] + perl Makefile.PL + make + make test TEST_VERBOSE=1 - 5. Now the difficult one. If you think you have found a bug in DB_File + 7. Now the difficult one. If you think you have found a bug in DB_File and you want me to fix it, you will *greatly* enhance the chances of me being able to track it down by sending me a small self-contained Perl script that illustrates the problem you are diff --git a/db/perl/DB_File/config.in b/db/perl/DB_File/config.in index dfd46bc59..127b810d5 100644 --- a/db/perl/DB_File/config.in +++ b/db/perl/DB_File/config.in @@ -12,7 +12,8 @@ INCLUDE = /usr/local/BerkeleyDB/include #INCLUDE = /usr/local/include #INCLUDE = /usr/include -#INCLUDE = ./libraries/3.2.9 +#INCLUDE = ./libraries/4.0.14/include +#INCLUDE = ./libraries/2.7.7/include # 2. Where is libdb? # @@ -22,7 +23,8 @@ INCLUDE = /usr/local/BerkeleyDB/include LIB = /usr/local/BerkeleyDB/lib #LIB = /usr/local/lib #LIB = /usr/lib -#LIB = ./libraries/3.2.9 +#LIB = ./libraries/4.0.14/lib +#LIB = ./libraries/2.7.7/lib # 3. What version of Berkely DB have you got? # diff --git a/db/perl/DB_File/dbinfo b/db/perl/DB_File/dbinfo index 5a4df1590..d349d07ee 100644 --- a/db/perl/DB_File/dbinfo +++ b/db/perl/DB_File/dbinfo @@ -7,7 +7,7 @@ # Version: 1.03 # Date 17th September 2000 # -# Copyright (c) 1998-2000 Paul Marquess. All rights reserved. +# Copyright (c) 1998-2002 Paul Marquess. All rights reserved. # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. diff --git a/db/perl/DB_File/t/db-btree.t b/db/perl/DB_File/t/db-btree.t index 326b8d9ad..16ee276c8 100644 --- a/db/perl/DB_File/t/db-btree.t +++ b/db/perl/DB_File/t/db-btree.t @@ -1,8 +1,5 @@ #!./perl -w -use warnings; -use strict; - BEGIN { unless(grep /blib/, @INC) { chdir 't' if -d 't'; @@ -10,21 +7,34 @@ BEGIN { } } +use warnings; +use strict; use Config; BEGIN { if(-d "lib" && -f "TEST") { if ($Config{'extensions'} !~ /\bDB_File\b/ ) { - print "1..157\n"; + print "1..0 # Skip: DB_File was not built\n"; exit 0; } } + if ($^O eq 'darwin' + && $Config{db_version_major} == 1 + && $Config{db_version_minor} == 0 + && $Config{db_version_patch} == 0) { + warn <<EOM; +# +# This test is known to crash in Mac OS X versions 10.1.4 (or earlier) +# because of the buggy Berkeley DB version included with the OS. +# +EOM + } } use DB_File; use Fcntl; -print "1..157\n"; +print "1..163\n"; sub ok { @@ -75,24 +85,32 @@ sub lexical sub docat { my $file = shift; - #local $/ = undef unless wantarray ; + local $/ = undef ; open(CAT,$file) || die "Cannot open $file: $!"; - my @result = <CAT>; + my $result = <CAT>; close(CAT); - wantarray ? @result : join("", @result) ; + $result = normalise($result) ; + return $result ; } sub docat_del { my $file = shift; - #local $/ = undef unless wantarray ; - open(CAT,$file) || die "Cannot open $file: $!"; - my @result = <CAT>; - close(CAT); + my $result = docat($file); unlink $file ; - wantarray ? @result : join("", @result) ; + return $result ; } +sub normalise +{ + my $data = shift ; + $data =~ s#\r\n#\n#g + if $^O eq 'cygwin' ; + + return $data ; +} + + my $db185mode = ($DB_File::db_version == 1 && ! $DB_File::db_185_compat) ; my $null_keys_allowed = ($DB_File::db_ver < 2.004010 @@ -149,11 +167,15 @@ ok(18, $@ =~ /^DB_File::BTREEINFO::FETCH - Unknown element 'fred' at/ ) ; my ($X, %h) ; ok(19, $X = tie(%h, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE )) ; +die "Could not tie: $!" unless $X; my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, $blksize,$blocks) = stat($Dfile); + +my %noMode = map { $_, 1} qw( amigaos MSWin32 NetWare cygwin ) ; + ok(20, ($mode & 0777) == (($^O eq 'os2' || $^O eq 'MacOS') ? 0666 : 0640) - || $^O eq 'amigaos' || $^O eq 'MSWin32' || $^O eq 'NetWare'); + || $noMode{$^O} ); my ($key, $value, $i); while (($key,$value) = each(%h)) { @@ -515,9 +537,9 @@ $dbh3->{compare} = sub { length $_[0] <=> length $_[1] } ; my (%g, %k); -tie(%h, 'DB_File',$Dfile1, O_RDWR|O_CREAT, 0640, $dbh1 ) ; -tie(%g, 'DB_File',$Dfile2, O_RDWR|O_CREAT, 0640, $dbh2 ) ; -tie(%k, 'DB_File',$Dfile3, O_RDWR|O_CREAT, 0640, $dbh3 ) ; +tie(%h, 'DB_File',$Dfile1, O_RDWR|O_CREAT, 0640, $dbh1 ) or die $!; +tie(%g, 'DB_File',$Dfile2, O_RDWR|O_CREAT, 0640, $dbh2 ) or die $!; +tie(%k, 'DB_File',$Dfile3, O_RDWR|O_CREAT, 0640, $dbh3 ) or die $!; my @Keys = qw( 0123 12 -1234 9 987654321 def ) ; my (@srt_1, @srt_2, @srt_3); @@ -609,7 +631,7 @@ unlink $Dfile1 ; use warnings ; use strict ; - use vars qw( @ISA @EXPORT) ; + our (@ISA, @EXPORT); require Exporter ; use DB_File; @@ -947,7 +969,7 @@ EOM use strict ; use DB_File ; - use vars qw($filename %h ) ; + my ($filename, %h); $filename = "tree" ; unlink $filename ; @@ -999,7 +1021,7 @@ EOM use strict ; use DB_File ; - use vars qw($filename $x %h $status $key $value) ; + my ($filename, $x, %h, $status, $key, $value); $filename = "tree" ; unlink $filename ; @@ -1055,7 +1077,7 @@ EOM use strict ; use DB_File ; - use vars qw($filename $x %h ) ; + my ($filename, $x, %h); $filename = "tree" ; @@ -1104,9 +1126,9 @@ EOM use strict ; use DB_File ; - use vars qw($filename $x %h $found) ; + my ($filename, $x, %h, $found); - my $filename = "tree" ; + $filename = "tree" ; # Enable duplicate records $DB_BTREE->{'flags'} = R_DUP ; @@ -1139,9 +1161,9 @@ EOM use strict ; use DB_File ; - use vars qw($filename $x %h $found) ; + my ($filename, $x, %h, $found); - my $filename = "tree" ; + $filename = "tree" ; # Enable duplicate records $DB_BTREE->{'flags'} = R_DUP ; @@ -1175,7 +1197,7 @@ EOM use DB_File ; use Fcntl ; - use vars qw($filename $x %h $st $key $value) ; + my ($filename, $x, %h, $st, $key, $value); sub match { @@ -1304,4 +1326,46 @@ EOM unlink $Dfile; } +{ + # When iterating over a tied hash using "each", the key passed to FETCH + # will be recycled and passed to NEXTKEY. If a Source Filter modifies the + # key in FETCH via a filter_fetch_key method we need to check that the + # modified key doesn't get passed to NEXTKEY. + # Also Test "keys" & "values" while we are at it. + + use warnings ; + use strict ; + use DB_File ; + + unlink $Dfile; + my $bad_key = 0 ; + my %h = () ; + my $db ; + ok(158, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_BTREE ) ); + $db->filter_fetch_key (sub { $_ =~ s/^Beta_/Alpha_/ if defined $_}) ; + $db->filter_store_key (sub { $bad_key = 1 if /^Beta_/ ; $_ =~ s/^Alpha_/Beta_/}) ; + + $h{'Alpha_ABC'} = 2 ; + $h{'Alpha_DEF'} = 5 ; + + ok(159, $h{'Alpha_ABC'} == 2); + ok(160, $h{'Alpha_DEF'} == 5); + + my ($k, $v) = ("",""); + while (($k, $v) = each %h) {} + ok(161, $bad_key == 0); + + $bad_key = 0 ; + foreach $k (keys %h) {} + ok(162, $bad_key == 0); + + $bad_key = 0 ; + foreach $v (values %h) {} + ok(163, $bad_key == 0); + + undef $db ; + untie %h ; + unlink $Dfile; +} + exit ; diff --git a/db/perl/DB_File/t/db-hash.t b/db/perl/DB_File/t/db-hash.t index daf0ea81a..931b03c96 100644 --- a/db/perl/DB_File/t/db-hash.t +++ b/db/perl/DB_File/t/db-hash.t @@ -1,8 +1,5 @@ #!./perl -use warnings ; -use strict ; - BEGIN { unless(grep /blib/, @INC) { chdir 't' if -d 't'; @@ -10,23 +7,23 @@ BEGIN { } } +use warnings; +use strict; use Config; BEGIN { if(-d "lib" && -f "TEST") { if ($Config{'extensions'} !~ /\bDB_File\b/ ) { - print "1..111\n"; + print "1..0 # Skip: DB_File was not built\n"; exit 0; } } } -use strict; -use warnings; use DB_File; use Fcntl; -print "1..111\n"; +print "1..117\n"; sub ok { @@ -66,10 +63,21 @@ sub docat_del open(CAT,$file) || die "Cannot open $file: $!"; my $result = <CAT>; close(CAT); + $result = normalise($result) ; unlink $file ; return $result; } +sub normalise +{ + my $data = shift ; + $data =~ s#\r\n#\n#g + if $^O eq 'cygwin' ; + return $data ; +} + + + my $Dfile = "dbhash.tmp"; my $null_keys_allowed = ($DB_File::db_ver < 2.004010 || $DB_File::db_ver >= 3.1 ); @@ -117,11 +125,15 @@ ok(14, $@ =~ /^DB_File::HASHINFO::FETCH - Unknown element 'fred' at/ ); # Now check the interface to HASH my ($X, %h); ok(15, $X = tie(%h, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) ); +die "Could not tie: $!" unless $X; my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, $blksize,$blocks) = stat($Dfile); + +my %noMode = map { $_, 1} qw( amigaos MSWin32 NetWare cygwin ) ; + ok(16, ($mode & 0777) == (($^O eq 'os2' || $^O eq 'MacOS') ? 0666 : 0640) || - $^O eq 'amigaos' || $^O eq 'MSWin32' || $^O eq 'NetWare'); + $noMode{$^O} ); my ($key, $value, $i); while (($key,$value) = each(%h)) { @@ -396,7 +408,7 @@ untie %h ; use warnings ; use strict ; - use vars qw( @ISA @EXPORT) ; + our (@ISA, @EXPORT); require Exporter ; use DB_File; @@ -676,7 +688,7 @@ EOM use warnings FATAL => qw(all); use strict ; use DB_File ; - use vars qw( %h $k $v ) ; + our (%h, $k, $v); unlink "fruit" ; tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0640, $DB_HASH @@ -753,4 +765,46 @@ EOM unlink $Dfile; } +{ + # When iterating over a tied hash using "each", the key passed to FETCH + # will be recycled and passed to NEXTKEY. If a Source Filter modifies the + # key in FETCH via a filter_fetch_key method we need to check that the + # modified key doesn't get passed to NEXTKEY. + # Also Test "keys" & "values" while we are at it. + + use warnings ; + use strict ; + use DB_File ; + + unlink $Dfile; + my $bad_key = 0 ; + my %h = () ; + my $db ; + ok(112, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) ); + $db->filter_fetch_key (sub { $_ =~ s/^Beta_/Alpha_/ if defined $_}) ; + $db->filter_store_key (sub { $bad_key = 1 if /^Beta_/ ; $_ =~ s/^Alpha_/Beta_/}) ; + + $h{'Alpha_ABC'} = 2 ; + $h{'Alpha_DEF'} = 5 ; + + ok(113, $h{'Alpha_ABC'} == 2); + ok(114, $h{'Alpha_DEF'} == 5); + + my ($k, $v) = ("",""); + while (($k, $v) = each %h) {} + ok(115, $bad_key == 0); + + $bad_key = 0 ; + foreach $k (keys %h) {} + ok(116, $bad_key == 0); + + $bad_key = 0 ; + foreach $v (values %h) {} + ok(117, $bad_key == 0); + + undef $db ; + untie %h ; + unlink $Dfile; +} + exit ; diff --git a/db/perl/DB_File/t/db-recno.t b/db/perl/DB_File/t/db-recno.t index f02991560..8576b3010 100644 --- a/db/perl/DB_File/t/db-recno.t +++ b/db/perl/DB_File/t/db-recno.t @@ -1,8 +1,5 @@ #!./perl -w -use warnings; -use strict ; - BEGIN { unless(grep /blib/, @INC) { chdir 't' if -d 't'; @@ -10,12 +7,14 @@ BEGIN { } } +use warnings; +use strict; use Config; BEGIN { if(-d "lib" && -f "TEST") { if ($Config{'extensions'} !~ /\bDB_File\b/ ) { - print "1..138\n"; + print "1..0 # Skip: DB_File was not built\n"; exit 0; } } @@ -23,7 +22,7 @@ BEGIN { use DB_File; use Fcntl; -use vars qw($dbh $Dfile $bad_ones $FA) ; +our ($dbh, $Dfile, $bad_ones, $FA); # full tied array support started in Perl 5.004_57 # Double check to see if it is available. @@ -78,26 +77,38 @@ sub docat open(CAT,$file) || die "Cannot open $file:$!"; my $result = <CAT>; close(CAT); + normalise($result) ; return $result; } sub docat_del { my $file = shift; - local $/ = undef; - open(CAT,$file) || die "Cannot open $file: $!"; - my $result = <CAT>; - close(CAT); + my $result = docat($file); unlink $file ; return $result; } sub bad_one { - print STDERR <<EOM unless $bad_ones++ ; + unless ($bad_ones++) { + print STDERR <<EOM ; +# +# Some older versions of Berkeley DB version 1 will fail db-recno +# tests 61, 63 and 65. +EOM + if ($^O eq 'darwin' + && $Config{db_version_major} == 1 + && $Config{db_version_minor} == 0 + && $Config{db_version_patch} == 0) { + print STDERR <<EOM ; # -# Some older versions of Berkeley DB version 1 will fail tests 51, -# 53 and 55. +# For example Mac OS X 10.1.4 (or earlier) has such an old +# version of Berkeley DB. +EOM + } + + print STDERR <<EOM ; # # You can safely ignore the errors if you're never going to use the # broken functionality (recno databases with a modified bval). @@ -108,21 +119,41 @@ sub bad_one # being updated -- Check out http://www.sleepycat.com/ for more details. # EOM + } +} + +sub normalise +{ + return unless $^O eq 'cygwin' ; + foreach (@_) + { s#\r\n#\n#g } +} + +BEGIN +{ + { + local $SIG{__DIE__} ; + eval { require Data::Dumper ; import Data::Dumper } ; + } + + if ($@) { + *Dumper = sub { my $a = shift; return "[ @{ $a } ]" } ; + } } -my $splice_tests = 10 + 1; # ten regressions, plus the randoms +my $splice_tests = 10 + 11 + 1; # ten regressions, 11 warnings, plus the randoms my $total_tests = 138 ; $total_tests += $splice_tests if $FA ; print "1..$total_tests\n"; -my $Dfile = "recno.tmp"; +$Dfile = "recno.tmp"; unlink $Dfile ; umask(0); # Check the interface to RECNOINFO -my $dbh = new DB_File::RECNOINFO ; +$dbh = new DB_File::RECNOINFO ; ok(1, ! defined $dbh->{bval}) ; ok(2, ! defined $dbh->{cachesize}) ; ok(3, ! defined $dbh->{psize}) ; @@ -165,8 +196,10 @@ my $X ; my @h ; ok(17, $X = tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) ; +my %noMode = map { $_, 1} qw( amigaos MSWin32 NetWare cygwin ) ; + ok(18, ((stat($Dfile))[2] & 0777) == (($^O eq 'os2' || $^O eq 'MacOS') ? 0666 : 0640) - || $^O eq 'MSWin32' || $^O eq 'NetWare' || $^O eq 'amigaos') ; + || $noMode{$^O} ); #my $l = @h ; my $l = $X->length ; @@ -382,7 +415,7 @@ unlink $Dfile; use warnings ; use strict ; - use vars qw( @ISA @EXPORT) ; + our (@ISA, @EXPORT); require Exporter ; use DB_File; @@ -426,7 +459,7 @@ unlink $Dfile; 1 ; EOM - close FILE ; + close FILE or die "Could not close: $!"; BEGIN { push @INC, '.'; } eval 'use SubDB ; '; @@ -436,6 +469,7 @@ EOM eval ' $X = tie(@h, "SubDB","recno.tmp", O_RDWR|O_CREAT, 0640, $DB_RECNO ); ' ; + die "Could not tie: $!" unless $X; main::ok(68, $@ eq "") ; @@ -774,7 +808,7 @@ EOM use warnings FATAL => qw(all); use strict ; - use vars qw(@h $H $file $i) ; + our (@h, $H, $file, $i); use DB_File ; use Fcntl ; @@ -921,6 +955,81 @@ EOM exit unless $FA ; # Test SPLICE + +{ + # check that the splice warnings are under the same lexical control + # as their non-tied counterparts. + + use warnings; + use strict; + + my $a = ''; + my @a = (1); + local $SIG{__WARN__} = sub {$a = $_[0]} ; + + unlink $Dfile; + my @tied ; + + tie @tied, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0664, $DB_RECNO + or die "Can't open file: $!\n" ; + + # uninitialized offset + use warnings; + my $offset ; + $a = ''; + splice(@a, $offset); + ok(139, $a =~ /^Use of uninitialized value /); + $a = ''; + splice(@tied, $offset); + ok(140, $a =~ /^Use of uninitialized value in splice/); + + no warnings 'uninitialized'; + $a = ''; + splice(@a, $offset); + ok(141, $a eq ''); + $a = ''; + splice(@tied, $offset); + ok(142, $a eq ''); + + # uninitialized length + use warnings; + my $length ; + $a = ''; + splice(@a, 0, $length); + ok(143, $a =~ /^Use of uninitialized value /); + $a = ''; + splice(@tied, 0, $length); + ok(144, $a =~ /^Use of uninitialized value in splice/); + + no warnings 'uninitialized'; + $a = ''; + splice(@a, 0, $length); + ok(145, $a eq ''); + $a = ''; + splice(@tied, 0, $length); + ok(146, $a eq ''); + + # offset past end of array + use warnings; + $a = ''; + splice(@a, 3); + my $splice_end_array = ($a =~ /^splice\(\) offset past end of array/); + $a = ''; + splice(@tied, 3); + ok(147, !$splice_end_array || $a =~ /^splice\(\) offset past end of array/); + + no warnings 'misc'; + $a = ''; + splice(@a, 3); + ok(148, $a eq ''); + $a = ''; + splice(@tied, 3); + ok(149, $a eq ''); + + untie @tied; + unlink $Dfile; +} + # # These are a few regression tests: bundles of five arguments to pass # to test_splice(). The first four arguments correspond to those @@ -978,15 +1087,14 @@ my @tests = ([ [ 'falsely', 'dinosaur', 'remedy', 'commotion', 'void' ], ); -my $testnum = 139; +my $testnum = 150; my $failed = 0; require POSIX; my $tmp = POSIX::tmpnam(); foreach my $test (@tests) { my $err = test_splice(@$test); if (defined $err) { - require Data::Dumper; - print STDERR "failed: ", Data::Dumper::Dumper($test); - print STDERR "error: $err\n"; + print STDERR "# failed: ", Dumper($test); + print STDERR "# error: $err\n"; $failed = 1; ok($testnum++, 0); } @@ -995,7 +1103,7 @@ foreach my $test (@tests) { if ($failed) { # Not worth running the random ones - print STDERR 'skipping ', $testnum++, "\n"; + print STDERR '# skipping ', $testnum++, "\n"; } else { # A thousand randomly-generated tests @@ -1005,11 +1113,10 @@ else { my $test = rand_test(); my $err = test_splice(@$test); if (defined $err) { - require Data::Dumper; - print STDERR "failed: ", Data::Dumper::Dumper($test); - print STDERR "error: $err\n"; + print STDERR "# failed: ", Dumper($test); + print STDERR "# error: $err\n"; $failed = 1; - print STDERR "skipping any remaining random tests\n"; + print STDERR "# skipping any remaining random tests\n"; last; } } @@ -1045,13 +1152,14 @@ sub test_splice { my @array = @$array; my @list = @$list; - open(TEXT, ">$tmp") or die "cannot write to $tmp: $!"; - foreach (@array) { print TEXT "$_\n" } - close TEXT or die "cannot close $tmp: $!"; + unlink $tmp; my @h; - my $H = tie @h, 'DB_File', $tmp, O_RDWR, 0644, $DB_RECNO + my $H = tie @h, 'DB_File', $tmp, O_CREAT|O_RDWR, 0644, $DB_RECNO or die "cannot open $tmp: $!"; + + my $i = 0; + foreach ( @array ) { $h[$i++] = $_ } return "basic DB_File sanity check failed" if list_diff(\@array, \@h); @@ -1132,7 +1240,7 @@ sub test_splice { foreach ($ms_error, @ms_warnings) { chomp; - s/ at \S+ line \d+\.?$//; + s/ at \S+ line \d+\.?.*//s; } return "different errors: '$s_error' vs '$ms_error'" @@ -1169,7 +1277,7 @@ sub test_splice { untie @h; open(TEXT, $tmp) or die "cannot open $tmp: $!"; - @h = <TEXT>; chomp @h; + @h = <TEXT>; normalise @h; chomp @h; close TEXT or die "cannot close $tmp: $!"; return('list is different when re-read from disk: ' . Dumper(\@array) . ' vs ' . Dumper(\@h)) diff --git a/db/perl/DB_File/version.c b/db/perl/DB_File/version.c index 0997db101..03b17c18e 100644 --- a/db/perl/DB_File/version.c +++ b/db/perl/DB_File/version.c @@ -3,12 +3,12 @@ version.c -- Perl 5 interface to Berkeley DB written by Paul Marquess <Paul.Marquess@btinternet.com> - last modified 22nd Oct 2001 - version 1.79 + last modified 2nd Jan 2002 + version 1.802 All comments/suggestions/problems are welcome - Copyright (c) 1995-2001 Paul Marquess. All rights reserved. + Copyright (c) 1995-2002 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. diff --git a/db/rep/rep_method.c b/db/rep/rep_method.c index 3b8bfac31..f605ccde2 100644 --- a/db/rep/rep_method.c +++ b/db/rep/rep_method.c @@ -1,40 +1,52 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2001 + * Copyright (c) 2001-2002 * Sleepycat Software. All rights reserved. */ #include "db_config.h" #ifndef lint -static const char revid[] = "Id: rep_method.c,v 1.37 2001/11/16 16:29:10 bostic Exp "; +static const char revid[] = "Id: rep_method.c,v 1.69 2002/08/06 04:50:36 bostic Exp "; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES #include <sys/types.h> +#ifdef HAVE_RPC +#include <rpc/rpc.h> +#endif + #include <stdlib.h> #include <string.h> #include <unistd.h> #endif -#ifdef HAVE_RPC -#include "db_server.h" -#endif - #include "db_int.h" -#include "log.h" -#include "rep.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/log.h" +#include "dbinc/rep.h" +#include "dbinc/txn.h" #ifdef HAVE_RPC -#include "rpc_client_ext.h" +#include "dbinc_auto/db_server.h" +#include "dbinc_auto/rpc_client_ext.h" #endif +static int __rep_abort_prepared __P((DB_ENV *)); +static int __rep_bt_cmp __P((DB *, const DBT *, const DBT *)); +static int __rep_client_dbinit __P((DB_ENV *, int)); static int __rep_elect __P((DB_ENV *, int, int, u_int32_t, int *)); -static int __rep_elect_init __P((DB_ENV *, DB_LSN *, int, int, int *)); +static int __rep_elect_init __P((DB_ENV *, DB_LSN *, int, int, int, int *)); +static int __rep_flush __P((DB_ENV *)); +static int __rep_restore_prepared __P((DB_ENV *)); +static int __rep_set_limit __P((DB_ENV *, u_int32_t, u_int32_t)); +static int __rep_set_request __P((DB_ENV *, u_int32_t, u_int32_t)); static int __rep_set_rep_transport __P((DB_ENV *, int, int (*)(DB_ENV *, const DBT *, const DBT *, int, u_int32_t))); static int __rep_start __P((DB_ENV *, DBT *, u_int32_t)); +static int __rep_stat __P((DB_ENV *, DB_REP_STAT **, u_int32_t)); static int __rep_wait __P((DB_ENV *, u_int32_t, int *, u_int32_t)); /* @@ -50,33 +62,43 @@ __rep_dbenv_create(dbenv) DB_REP *db_rep; int ret; - /* - * !!! - * Our caller has not yet had the opportunity to reset the panic - * state or turn off mutex locking, and so we can neither check - * the panic state or acquire a mutex in the DB_ENV create path. - */ - - if ((ret = __os_calloc(dbenv, 1, sizeof(DB_REP), &db_rep)) != 0) - return (ret); - dbenv->rep_handle = db_rep; - - /* Initialize the per-process replication structure. */ - db_rep->rep_send = NULL; - #ifdef HAVE_RPC if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) { + COMPQUIET(db_rep, NULL); + COMPQUIET(ret, 0); dbenv->rep_elect = __dbcl_rep_elect; - dbenv->rep_start = __dbcl_rep_start; + dbenv->rep_flush = __dbcl_rep_flush; dbenv->rep_process_message = __dbcl_rep_process_message; + dbenv->rep_start = __dbcl_rep_start; + dbenv->rep_stat = __dbcl_rep_stat; + dbenv->set_rep_limit = __dbcl_rep_set_limit; + dbenv->set_rep_request = __dbcl_rep_set_request; dbenv->set_rep_transport = __dbcl_rep_set_rep_transport; + } else #endif { dbenv->rep_elect = __rep_elect; + dbenv->rep_flush = __rep_flush; dbenv->rep_process_message = __rep_process_message; dbenv->rep_start = __rep_start; + dbenv->rep_stat = __rep_stat; + dbenv->set_rep_limit = __rep_set_limit; + dbenv->set_rep_request = __rep_set_request; dbenv->set_rep_transport = __rep_set_rep_transport; + /* + * !!! + * Our caller has not yet had the opportunity to reset the panic + * state or turn off mutex locking, and so we can neither check + * the panic state or acquire a mutex in the DB_ENV create path. + */ + + if ((ret = __os_calloc(dbenv, 1, sizeof(DB_REP), &db_rep)) != 0) + return (ret); + dbenv->rep_handle = db_rep; + + /* Initialize the per-process replication structure. */ + db_rep->rep_send = NULL; } return (0); @@ -98,10 +120,11 @@ __rep_start(dbenv, dbt, flags) DB_LSN lsn; DB_REP *db_rep; REP *rep; - int announce, init_db, ret; + int announce, init_db, redo_prepared, ret; - ENV_ILLEGAL_BEFORE_OPEN(dbenv, "rep_start"); PANIC_CHECK(dbenv); + ENV_ILLEGAL_BEFORE_OPEN(dbenv, "rep_start"); + ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_stat", DB_INIT_TXN); db_rep = dbenv->rep_handle; rep = db_rep->region; @@ -114,9 +137,9 @@ __rep_start(dbenv, dbt, flags) if ((ret = __db_fcchk(dbenv, "DB_ENV->rep_start", flags, DB_REP_CLIENT, DB_REP_MASTER)) != 0) return (ret); - if (!LF_ISSET(DB_REP_CLIENT | DB_REP_MASTER)) { + if (!LF_ISSET(DB_REP_CLIENT | DB_REP_MASTER | DB_REP_LOGSONLY)) { __db_err(dbenv, - "DB_ENV->rep_start: either DB_CLIENT or DB_MASTER must be specified."); + "DB_ENV->rep_start: replication mode must be specified"); return (EINVAL); } @@ -132,25 +155,39 @@ __rep_start(dbenv, dbt, flags) return (EINVAL); } - MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); + MUTEX_LOCK(dbenv, db_rep->mutexp); if (rep->eid == DB_EID_INVALID) rep->eid = dbenv->rep_eid; if (LF_ISSET(DB_REP_MASTER)) { - if (db_rep->rep_db != NULL) { - ret = db_rep->rep_db->close(db_rep->rep_db, DB_NOSYNC); - db_rep->rep_db = NULL; - } + if (F_ISSET(dbenv, DB_ENV_REP_CLIENT)) + /* + * If we're upgrading from having been a client, + * preclose, so that we close our temporary database. + * + * Do not close files that we may have opened while + * doing a rep_apply; they'll get closed when we + * finally close the environment, but for now, leave + * them open, as we don't want to recycle their + * fileids, and we may need the handles again if + * we become a client and the original master + * that opened them becomes a master again. + */ + if ((ret = __rep_preclose(dbenv, 0)) != 0) + return (ret); F_CLR(dbenv, DB_ENV_REP_CLIENT); + redo_prepared = 0; if (!F_ISSET(rep, REP_F_MASTER)) { /* Master is not yet set. */ if (F_ISSET(rep, REP_ISCLIENT)) { F_CLR(rep, REP_ISCLIENT); rep->gen = ++rep->w_gen; + redo_prepared = 1; } else if (rep->gen == 0) rep->gen = 1; } + F_SET(rep, REP_F_MASTER); F_SET(dbenv, DB_ENV_REP_MASTER); MUTEX_UNLOCK(dbenv, db_rep->mutexp); @@ -158,8 +195,15 @@ __rep_start(dbenv, dbt, flags) R_LOCK(dbenv, &dblp->reginfo); lsn = ((LOG *)dblp->reginfo.primary)->lsn; R_UNLOCK(dbenv, &dblp->reginfo); - ret = __rep_send_message(dbenv, - DB_EID_BROADCAST, REP_NEWMASTER, &lsn, NULL, 0); + + /* + * Send the NEWMASTER message, then restore prepared txns + * if and only if we just upgraded from being a client. + */ + if ((ret = __rep_send_message(dbenv, + DB_EID_BROADCAST, REP_NEWMASTER, &lsn, NULL, 0)) == 0 && + redo_prepared) + ret = __rep_restore_prepared(dbenv); } else { F_CLR(dbenv, DB_ENV_REP_MASTER); F_SET(dbenv, DB_ENV_REP_CLIENT); @@ -188,6 +232,17 @@ __rep_start(dbenv, dbt, flags) } MUTEX_UNLOCK(dbenv, db_rep->mutexp); + /* + * Abort any prepared transactions that were restored + * by recovery. We won't be able to create any txns of + * our own until they're resolved, but we can't resolve + * them ourselves; the master has to. If any get + * resolved as commits, we'll redo them when commit + * records come in. Aborts will simply be ignored. + */ + if ((ret = __rep_abort_prepared(dbenv)) != 0) + return (ret); + if ((ret = __rep_client_dbinit(dbenv, init_db)) != 0) return (ret); @@ -207,6 +262,435 @@ __rep_start(dbenv, dbt, flags) } /* + * __rep_client_dbinit -- + * + * Initialize the LSN database on the client side. This is called from the + * client initialization code. The startup flag value indicates if + * this is the first thread/process starting up and therefore should create + * the LSN database. This routine must be called once by each process acting + * as a client. + */ +static int +__rep_client_dbinit(dbenv, startup) + DB_ENV *dbenv; + int startup; +{ + DB_REP *db_rep; + DB *rep_db; + int ret, t_ret; + u_int32_t flags; + + PANIC_CHECK(dbenv); + db_rep = dbenv->rep_handle; + rep_db = NULL; + +#define REPDBNAME "__db.rep.db" + + /* Check if this has already been called on this environment. */ + if (db_rep->rep_db != NULL) + return (0); + + MUTEX_LOCK(dbenv, db_rep->db_mutexp); + + if (startup) { + if ((ret = db_create(&rep_db, dbenv, 0)) != 0) + goto err; + /* + * Ignore errors, because if the file doesn't exist, this + * is perfectly OK. + */ + (void)rep_db->remove(rep_db, REPDBNAME, NULL, 0); + } + + if ((ret = db_create(&rep_db, dbenv, 0)) != 0) + goto err; + if ((ret = rep_db->set_bt_compare(rep_db, __rep_bt_cmp)) != 0) + goto err; + + /* Allow writes to this database on a client. */ + F_SET(rep_db, DB_AM_CL_WRITER); + + flags = (F_ISSET(dbenv, DB_ENV_THREAD) ? DB_THREAD : 0) | + (startup ? DB_CREATE : 0); + if ((ret = rep_db->open(rep_db, NULL, + "__db.rep.db", NULL, DB_BTREE, flags, 0)) != 0) + goto err; + + db_rep->rep_db = rep_db; + + if (0) { +err: if (rep_db != NULL && + (t_ret = rep_db->close(rep_db, DB_NOSYNC)) != 0 && ret == 0) + ret = t_ret; + db_rep->rep_db = NULL; + } + + MUTEX_UNLOCK(dbenv, db_rep->db_mutexp); + + return (ret); +} + +/* + * __rep_bt_cmp -- + * + * Comparison function for the LSN table. We use the entire control + * structure as a key (for simplicity, so we don't have to merge the + * other fields in the control with the data field), but really only + * care about the LSNs. + */ +static int +__rep_bt_cmp(dbp, dbt1, dbt2) + DB *dbp; + const DBT *dbt1, *dbt2; +{ + DB_LSN lsn1, lsn2; + REP_CONTROL *rp1, *rp2; + + COMPQUIET(dbp, NULL); + + rp1 = dbt1->data; + rp2 = dbt2->data; + + __ua_memcpy(&lsn1, &rp1->lsn, sizeof(DB_LSN)); + __ua_memcpy(&lsn2, &rp2->lsn, sizeof(DB_LSN)); + + if (lsn1.file > lsn2.file) + return (1); + + if (lsn1.file < lsn2.file) + return (-1); + + if (lsn1.offset > lsn2.offset) + return (1); + + if (lsn1.offset < lsn2.offset) + return (-1); + + return (0); +} + +/* + * __rep_abort_prepared -- + * Abort any prepared transactions that recovery restored. + * + * This is used by clients that have just run recovery, since + * they cannot/should not call txn_recover and handle prepared transactions + * themselves. + */ +static int +__rep_abort_prepared(dbenv) + DB_ENV *dbenv; +{ +#define PREPLISTSIZE 50 + DB_PREPLIST prep[PREPLISTSIZE], *p; + DB_TXNMGR *mgr; + DB_TXNREGION *region; + int do_aborts, ret; + long count, i; + u_int32_t op; + + mgr = dbenv->tx_handle; + region = mgr->reginfo.primary; + + do_aborts = 0; + R_LOCK(dbenv, &mgr->reginfo); + if (region->stat.st_nrestores != 0) + do_aborts = 1; + R_UNLOCK(dbenv, &mgr->reginfo); + + if (do_aborts) { + op = DB_FIRST; + do { + if ((ret = dbenv->txn_recover(dbenv, + prep, PREPLISTSIZE, &count, op)) != 0) + return (ret); + for (i = 0; i < count; i++) { + p = &prep[i]; + if ((ret = p->txn->abort(p->txn)) != 0) + return (ret); + } + op = DB_NEXT; + } while (count == PREPLISTSIZE); + } + + return (0); +} + +/* + * __rep_restore_prepared -- + * Restore to a prepared state any prepared but not yet committed + * transactions. + * + * This performs, in effect, a "mini-recovery"; it is called from + * __rep_start by newly upgraded masters. There may be transactions that an + * old master prepared but did not resolve, which we need to restore to an + * active state. + */ +static int +__rep_restore_prepared(dbenv) + DB_ENV *dbenv; +{ + DB_LOGC *logc; + DB_LSN ckp_lsn, lsn; + DBT rec; + __txn_ckp_args *ckp_args; + __txn_regop_args *regop_args; + __txn_xa_regop_args *prep_args; + int ret, t_ret; + u_int32_t hi_txn, low_txn, rectype; + void *txninfo; + + txninfo = NULL; + ckp_args = NULL; + prep_args = NULL; + regop_args = NULL; + ZERO_LSN(ckp_lsn); + ZERO_LSN(lsn); + + if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0) + return (ret); + + /* + * We need to consider the set of records between the most recent + * checkpoint LSN and the end of the log; any txn in that + * range, and only txns in that range, could still have been + * active, and thus prepared but not yet committed (PBNYC), + * when the old master died. + * + * Find the most recent checkpoint LSN, and get the record there. + * If there is no checkpoint in the log, start off by getting + * the very first record in the log instead. + */ + memset(&rec, 0, sizeof(DBT)); + if ((ret = __txn_getckp(dbenv, &lsn)) == 0) { + if ((ret = logc->get(logc, &lsn, &rec, DB_SET)) != 0) { + __db_err(dbenv, + "Checkpoint record at LSN [%ld][%ld] not found", + (u_long)lsn.file, (u_long)lsn.offset); + goto err; + } + + if ((ret = __txn_ckp_read(dbenv, rec.data, &ckp_args)) != 0) { + __db_err(dbenv, + "Invalid checkpoint record at [%ld][%ld]", + (u_long)lsn.file, (u_long)lsn.offset); + goto err; + } + + ckp_lsn = ckp_args->ckp_lsn; + + if ((ret = logc->get(logc, &ckp_lsn, &rec, DB_SET)) != 0) { + __db_err(dbenv, + "Checkpoint LSN record [%ld][%ld] not found", + (u_long)ckp_lsn.file, (u_long)ckp_lsn.offset); + goto err; + } + } else if ((ret = logc->get(logc, &lsn, &rec, DB_FIRST)) != 0) { + if (ret == DB_NOTFOUND) { + /* An empty log means no PBNYC txns. */ + ret = 0; + goto done; + } + __db_err(dbenv, "Attempt to get first log record failed"); + goto err; + } + + /* + * We use the same txnlist infrastructure that recovery does; + * it demands an estimate of the high and low txnids for + * initialization. + * + * First, the low txnid. + */ + do { + /* txnid is after rectype, which is a u_int32. */ + memcpy(&low_txn, + (u_int8_t *)rec.data + sizeof(u_int32_t), sizeof(low_txn)); + if (low_txn != 0) + break; + } while ((ret = logc->get(logc, &lsn, &rec, DB_NEXT)) == 0); + + /* If there are no txns, there are no PBNYC txns. */ + if (ret == DB_NOTFOUND) { + ret = 0; + goto done; + } else if (ret != 0) + goto err; + + /* Now, the high txnid. */ + if ((ret = logc->get(logc, &lsn, &rec, DB_LAST)) != 0) { + /* + * Note that DB_NOTFOUND is unacceptable here because we + * had to have looked at some log record to get this far. + */ + __db_err(dbenv, "Final log record not found"); + goto err; + } + do { + /* txnid is after rectype, which is a u_int32. */ + memcpy(&hi_txn, + (u_int8_t *)rec.data + sizeof(u_int32_t), sizeof(hi_txn)); + if (hi_txn != 0) + break; + } while ((ret = logc->get(logc, &lsn, &rec, DB_PREV)) == 0); + if (ret == DB_NOTFOUND) { + ret = 0; + goto done; + } else if (ret != 0) + goto err; + + /* We have a high and low txnid. Initialise the txn list. */ + if ((ret = + __db_txnlist_init(dbenv, low_txn, hi_txn, NULL, &txninfo)) != 0) + goto err; + + /* + * Now, walk backward from the end of the log to ckp_lsn. Any + * prepares that we hit without first hitting a commit or + * abort belong to PBNYC txns, and we need to apply them and + * restore them to a prepared state. + * + * Note that we wind up applying transactions out of order. + * Since all PBNYC txns still held locks on the old master and + * were isolated, this should be safe. + */ + for (ret = logc->get(logc, &lsn, &rec, DB_LAST); + ret == 0 && log_compare(&lsn, &ckp_lsn) > 0; + ret = logc->get(logc, &lsn, &rec, DB_PREV)) { + memcpy(&rectype, rec.data, sizeof(rectype)); + switch (rectype) { + case DB___txn_regop: + /* + * It's a commit or abort--but we don't care + * which! Just add it to the list of txns + * that are resolved. + */ + if ((ret = __txn_regop_read(dbenv, rec.data, + ®op_args)) != 0) + goto err; + + ret = __db_txnlist_find(dbenv, + txninfo, regop_args->txnid->txnid); + if (ret == DB_NOTFOUND) + ret = __db_txnlist_add(dbenv, txninfo, + regop_args->txnid->txnid, + regop_args->opcode, &lsn); + break; + case DB___txn_xa_regop: + /* + * It's a prepare. If we haven't put the + * txn on our list yet, it hasn't been + * resolved, so apply and restore it. + */ + if ((ret = __txn_xa_regop_read(dbenv, rec.data, + &prep_args)) != 0) + goto err; + ret = __db_txnlist_find(dbenv, txninfo, + prep_args->txnid->txnid); + if (ret == DB_NOTFOUND) + if ((ret = __rep_process_txn(dbenv, &rec)) == 0) + ret = __txn_restore_txn(dbenv, + &lsn, prep_args); + break; + default: + continue; + } + } + + /* It's not an error to have hit the beginning of the log. */ + if (ret == DB_NOTFOUND) + ret = 0; + +done: +err: t_ret = logc->close(logc, 0); + + if (txninfo != NULL) + __db_txnlist_end(dbenv, txninfo); + if (ckp_args != NULL) + __os_free(dbenv, ckp_args); + if (prep_args != NULL) + __os_free(dbenv, prep_args); + if (regop_args != NULL) + __os_free(dbenv, regop_args); + + return (ret == 0 ? t_ret : ret); +} + +/* + * __rep_set_limit -- + * Set a limit on the amount of data that will be sent during a single + * invocation of __rep_process_message. + */ +static int +__rep_set_limit(dbenv, gbytes, bytes) + DB_ENV *dbenv; + u_int32_t gbytes; + u_int32_t bytes; +{ + DB_REP *db_rep; + REP *rep; + + PANIC_CHECK(dbenv); + + if ((db_rep = dbenv->rep_handle) == NULL) { + __db_err(dbenv, + "DB_ENV->set_rep_limit: database environment not properly initialized"); + return (__db_panic(dbenv, EINVAL)); + } + rep = db_rep->region; + MUTEX_LOCK(dbenv, db_rep->mutexp); + if (bytes > GIGABYTE) { + gbytes += bytes / GIGABYTE; + bytes = bytes % GIGABYTE; + } + rep->gbytes = gbytes; + rep->bytes = bytes; + MUTEX_UNLOCK(dbenv, db_rep->mutexp); + + return (0); +} + +/* + * __rep_set_request -- + * Set the minimum and maximum number of log records that we wait + * before retransmitting. + * UNDOCUMENTED. + */ +static int +__rep_set_request(dbenv, min, max) + DB_ENV *dbenv; + u_int32_t min; + u_int32_t max; +{ + LOG *lp; + DB_LOG *dblp; + DB_REP *db_rep; + REP *rep; + + PANIC_CHECK(dbenv); + + if ((db_rep = dbenv->rep_handle) == NULL) { + __db_err(dbenv, + "DB_ENV->set_rep_request: database environment not properly initialized"); + return (__db_panic(dbenv, EINVAL)); + } + rep = db_rep->region; + MUTEX_LOCK(dbenv, db_rep->mutexp); + rep->request_gap = min; + rep->max_gap = max; + MUTEX_UNLOCK(dbenv, db_rep->mutexp); + dblp = dbenv->lg_handle; + if (dblp != NULL && (lp = dblp->reginfo.primary) != NULL) { + R_LOCK(dbenv, &dblp->reginfo); + lp->wait_recs = 0; + lp->rcvd_recs = 0; + R_UNLOCK(dbenv, &dblp->reginfo); + } + + return (0); +} + +/* * __rep_set_transport -- * Set the transport function for replication. */ @@ -218,10 +702,12 @@ __rep_set_rep_transport(dbenv, eid, f_send) { DB_REP *db_rep; + PANIC_CHECK(dbenv); + if ((db_rep = dbenv->rep_handle) == NULL) { __db_err(dbenv, "DB_ENV->set_rep_transport: database environment not properly initialized"); - return (DB_RUNRECOVERY); + return (__db_panic(dbenv, EINVAL)); } if (f_send == NULL) { @@ -258,7 +744,11 @@ __rep_elect(dbenv, nsites, priority, timeout, eidp) DB_LSN lsn; DB_REP *db_rep; REP *rep; - int in_progress, ret, send_vote; + int in_progress, ret, send_vote, tiebreaker; + u_int32_t pid, sec, usec; + + PANIC_CHECK(dbenv); + ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_elect", DB_INIT_TXN); /* Error checking. */ if (nsites <= 0) { @@ -272,15 +762,22 @@ __rep_elect(dbenv, nsites, priority, timeout, eidp) return (EINVAL); } + db_rep = dbenv->rep_handle; + rep = db_rep->region; dblp = dbenv->lg_handle; + R_LOCK(dbenv, &dblp->reginfo); lsn = ((LOG *)dblp->reginfo.primary)->lsn; R_UNLOCK(dbenv, &dblp->reginfo); - db_rep = dbenv->rep_handle; - rep = db_rep->region; + /* Generate a randomized tiebreaker value. */ + __os_id(&pid); + if ((ret = __os_clock(dbenv, &sec, &usec)) != 0) + return (ret); + tiebreaker = (int)pid ^ (int)sec ^ (int)usec ^ rand() ^ (int)&pid; + if ((ret = __rep_elect_init(dbenv, - &lsn, nsites, priority, &in_progress)) != 0) { + &lsn, nsites, priority, tiebreaker, &in_progress)) != 0) { if (ret == DB_REP_NEWMASTER) { ret = 0; *eidp = dbenv->rep_eid; @@ -296,13 +793,17 @@ __rep_elect(dbenv, nsites, priority, timeout, eidp) if ((ret = __rep_send_message(dbenv, DB_EID_BROADCAST, REP_ELECT, NULL, NULL, 0)) != 0) goto err; + DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTSEND, ret, NULL); } /* Now send vote */ - if ((ret = __rep_send_vote(dbenv, &lsn, nsites, priority)) != 0) + if ((ret = + __rep_send_vote(dbenv, &lsn, nsites, priority, tiebreaker)) != 0) goto err; + DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTVOTE1, ret, NULL); ret = __rep_wait(dbenv, timeout, eidp, REP_F_EPHASE1); + DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTWAIT1, ret, NULL); switch (ret) { case 0: /* Check if election complete or phase complete. */ @@ -320,7 +821,7 @@ __rep_elect(dbenv, nsites, priority, timeout, eidp) * votes to pick a winner and if so, to send out a vote to * the winner. */ - MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); + MUTEX_LOCK(dbenv, db_rep->mutexp); send_vote = DB_EID_INVALID; if (rep->sites > rep->nsites / 2) { /* We think we've seen enough to cast a vote. */ @@ -352,8 +853,10 @@ __rep_elect(dbenv, nsites, priority, timeout, eidp) if (send_vote != rep->eid && (ret = __rep_send_message(dbenv, send_vote, REP_VOTE2, NULL, NULL, 0)) != 0) goto err; + DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTVOTE2, ret, NULL); phase2: ret = __rep_wait(dbenv, timeout, eidp, REP_F_EPHASE2); + DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTWAIT2, ret, NULL); switch (ret) { case 0: return (0); @@ -364,7 +867,8 @@ phase2: ret = __rep_wait(dbenv, timeout, eidp, REP_F_EPHASE2); goto err; } -err: MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); +DB_TEST_RECOVERY_LABEL +err: MUTEX_LOCK(dbenv, db_rep->mutexp); ELECTION_DONE(rep); MUTEX_UNLOCK(dbenv, db_rep->mutexp); @@ -381,10 +885,10 @@ err: MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); * already in progress; makes it 0 otherwise. */ static int -__rep_elect_init(dbenv, lsnp, nsites, priority, beginp) +__rep_elect_init(dbenv, lsnp, nsites, priority, tiebreaker, beginp) DB_ENV *dbenv; DB_LSN *lsnp; - int nsites, priority, *beginp; + int nsites, priority, tiebreaker, *beginp; { DB_REP *db_rep; REP *rep; @@ -395,14 +899,18 @@ __rep_elect_init(dbenv, lsnp, nsites, priority, beginp) ret = 0; + /* We may miscount, as we don't hold the replication mutex here. */ + rep->stat.st_elections++; + /* If we are already a master; simply broadcast that fact and return. */ if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) { - ret = __rep_send_message(dbenv, + (void)__rep_send_message(dbenv, DB_EID_BROADCAST, REP_NEWMASTER, lsnp, NULL, 0); + rep->stat.st_elections_won++; return (DB_REP_NEWMASTER); } - MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); + MUTEX_LOCK(dbenv, db_rep->mutexp); *beginp = IN_ELECTION(rep); if (!*beginp) { F_SET(rep, REP_F_EPHASE1); @@ -410,6 +918,7 @@ __rep_elect_init(dbenv, lsnp, nsites, priority, beginp) if (nsites > rep->asites && (ret = __rep_grow_sites(dbenv, nsites)) != 0) goto err; + DB_ENV_TEST_RECOVERY(dbenv, DB_TEST_ELECTINIT, ret, NULL); rep->nsites = nsites; rep->priority = priority; rep->votes = 0; @@ -425,13 +934,16 @@ __rep_elect_init(dbenv, lsnp, nsites, priority, beginp) rep->w_priority = priority; rep->w_gen = rep->gen; rep->w_lsn = *lsnp; + rep->w_tiebreaker = tiebreaker; } else { rep->winner = DB_EID_INVALID; rep->w_priority = 0; rep->w_gen = 0; ZERO_LSN(rep->w_lsn); + rep->w_tiebreaker = 0; } } +DB_TEST_RECOVERY_LABEL err: MUTEX_UNLOCK(dbenv, db_rep->mutexp); return (ret); } @@ -458,10 +970,12 @@ __rep_wait(dbenv, timeout, eidp, flags) * Sleep repeatedly for the smaller of .5s and timeout/10. */ sleeptime = (timeout > 5000000) ? 500000 : timeout / 10; + if (sleeptime == 0) + sleeptime++; while (timeout > 0) { if ((ret = __os_sleep(dbenv, 0, sleeptime)) != 0) return (ret); - MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); + MUTEX_LOCK(dbenv, db_rep->mutexp); done = !F_ISSET(rep, flags) && rep->master_id != DB_EID_INVALID; *eidp = rep->master_id; @@ -477,3 +991,136 @@ __rep_wait(dbenv, timeout, eidp, flags) } return (DB_TIMEOUT); } + +/* + * __rep_flush -- + * Re-push the last log record to all clients, in case they've lost + * messages and don't know it. + */ +static int +__rep_flush(dbenv) + DB_ENV *dbenv; +{ + DBT rec; + DB_LOGC *logc; + DB_LSN lsn; + int ret, t_ret; + + PANIC_CHECK(dbenv); + ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_stat", DB_INIT_TXN); + + if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0) + return (ret); + + memset(&rec, 0, sizeof(rec)); + memset(&lsn, 0, sizeof(lsn)); + + if ((ret = logc->get(logc, &lsn, &rec, DB_LAST)) != 0) + goto err; + + ret = __rep_send_message(dbenv, + DB_EID_BROADCAST, REP_LOG, &lsn, &rec, 0); + +err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) + ret = t_ret; + return (ret); +} + +/* + * __rep_stat -- + * Fetch replication statistics. + */ +static int +__rep_stat(dbenv, statp, flags) + DB_ENV *dbenv; + DB_REP_STAT **statp; + u_int32_t flags; +{ + DB_LOG *dblp; + DB_REP *db_rep; + DB_REP_STAT *stats; + LOG *lp; + REP *rep; + u_int32_t queued; + int ret; + + PANIC_CHECK(dbenv); + ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_stat", DB_INIT_TXN); + + db_rep = dbenv->rep_handle; + rep = db_rep->region; + dblp = dbenv->lg_handle; + lp = dblp->reginfo.primary; + + *statp = NULL; + if ((ret = __db_fchk(dbenv, + "DB_ENV->rep_stat", flags, DB_STAT_CLEAR)) != 0) + return (ret); + + /* Allocate a stat struct to return to the user. */ + if ((ret = __os_umalloc(dbenv, sizeof(DB_REP_STAT), &stats)) != 0) + return (ret); + + MUTEX_LOCK(dbenv, db_rep->mutexp); + memcpy(stats, &rep->stat, sizeof(*stats)); + + /* Copy out election stats. */ + if (IN_ELECTION(rep)) { + if (F_ISSET(rep, REP_F_EPHASE1)) + stats->st_election_status = 1; + else if (F_ISSET(rep, REP_F_EPHASE2)) + stats->st_election_status = 2; + + stats->st_election_nsites = rep->sites; + stats->st_election_cur_winner = rep->winner; + stats->st_election_priority = rep->w_priority; + stats->st_election_gen = rep->w_gen; + stats->st_election_lsn = rep->w_lsn; + stats->st_election_votes = rep->votes; + stats->st_election_tiebreaker = rep->w_tiebreaker; + } + + /* Copy out other info that's protected by the rep mutex. */ + stats->st_env_id = rep->eid; + stats->st_env_priority = rep->priority; + stats->st_nsites = rep->nsites; + stats->st_master = rep->master_id; + stats->st_gen = rep->gen; + + if (F_ISSET(rep, REP_F_MASTER)) + stats->st_status = DB_REP_MASTER; + else if (F_ISSET(rep, REP_F_LOGSONLY)) + stats->st_status = DB_REP_LOGSONLY; + else if (F_ISSET(rep, REP_F_UPGRADE)) + stats->st_status = DB_REP_CLIENT; + else + stats->st_status = 0; + + if (LF_ISSET(DB_STAT_CLEAR)) { + queued = rep->stat.st_log_queued; + memset(&rep->stat, 0, sizeof(rep->stat)); + rep->stat.st_log_queued = rep->stat.st_log_queued_total = + rep->stat.st_log_queued_max = queued; + } + MUTEX_UNLOCK(dbenv, db_rep->mutexp); + + /* + * Log-related replication info is stored in the log system and + * protected by the log region lock. + */ + R_LOCK(dbenv, &dblp->reginfo); + if (F_ISSET(rep, REP_ISCLIENT)) { + stats->st_next_lsn = lp->ready_lsn; + stats->st_waiting_lsn = lp->waiting_lsn; + } else { + if (F_ISSET(rep, REP_F_MASTER)) + stats->st_next_lsn = lp->lsn; + else + ZERO_LSN(stats->st_next_lsn); + ZERO_LSN(stats->st_waiting_lsn); + } + R_UNLOCK(dbenv, &dblp->reginfo); + + *statp = stats; + return (0); +} diff --git a/db/rep/rep_record.c b/db/rep/rep_record.c index dd4d870b4..f2b6b7ed8 100644 --- a/db/rep/rep_record.c +++ b/db/rep/rep_record.c @@ -1,67 +1,35 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2001 + * Copyright (c) 2001-2002 * Sleepycat Software. All rights reserved. */ #include "db_config.h" #ifndef lint -static const char revid[] = "Id: rep_record.c,v 1.64 2001/11/16 16:29:10 bostic Exp "; +static const char revid[] = "Id: rep_record.c,v 1.108 2002/08/09 02:17:41 margo Exp "; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES +#include <stdlib.h> #include <string.h> #endif #include "db_int.h" -#include "log.h" -#include "txn.h" -#include "rep.h" -#include "db_page.h" -#include "db_am.h" -#include "db_shash.h" -#include "lock.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/log.h" +#include "dbinc/rep.h" +#include "dbinc/txn.h" static int __rep_apply __P((DB_ENV *, REP_CONTROL *, DBT *)); -static int __rep_bt_cmp __P((DB *, const DBT *, const DBT *)); -static int __rep_process_txn __P((DB_ENV *, DBT *)); +static int __rep_collect_txn __P((DB_ENV *, DB_LSN *, LSN_COLLECTION *)); +static int __rep_lsn_cmp __P((const void *, const void *)); +static int __rep_newfile __P((DB_ENV *, REP_CONTROL *, DBT *, DB_LSN *)); -#define IS_SIMPLE(R) \ - ((R) != DB_txn_regop && (R) != DB_txn_ckp && (R) != DB_log_register) - -/* - * This is a bit of a hack. If we set the offset to be the sizeof the - * persistent log structure, then we'll match the correct LSN on the - * next log write. - * - * If lp->ready_lsn is [1][0], we need to "change" to the first log - * file (we currently have none). However, in this situation, we - * don't want to wind up at LSN [2][whatever], we want to wind up at - * LSN [1][whatever], so don't set LOG_NEWFILE. The guts of the log - * system will take care of actually writing the persistent header, - * since we're doing a log_put to an empty log. - * - * If lp->ready_lsn is [m-1][n] for some m > 1, n > 0, we really do need to - * change to the first log file. Not only do we need to jump to lsn - * [m][0], we need to write out a persistent header there, so set - * LOG_NEWFILE so the right stuff happens in the bowels of log_put. - * Note that we could dispense with LOG_NEWFILE by simply relying upon - * the log system to decide to switch files at the same time the - * master did--lg_max should be the same in both places--but this is - * scary. - */ -#define CHANGE_FILES do { \ - if (!(lp->ready_lsn.file == 1 && lp->ready_lsn.offset == 0)) { \ - lp->ready_lsn.file++; \ - F_SET(lp, LOG_NEWFILE); \ - } \ - lp->ready_lsn.offset = sizeof(struct __log_persist) + \ - sizeof(struct __hdr); \ - /* Make this evaluate to a simple rectype. */ \ - rectype = 0; \ -} while (0) +#define IS_SIMPLE(R) ((R) != DB___txn_regop && \ + (R) != DB___txn_ckp && (R) != DB___dbreg_register) /* * __rep_process_message -- @@ -82,19 +50,21 @@ __rep_process_message(dbenv, control, rec, eidp) DBT *control, *rec; int *eidp; { - DBT *d, data_dbt, lsndbt, mylog; DB_LOG *dblp; DB_LOGC *logc; - DB_LSN lsn, newfilelsn, oldfilelsn; + DB_LSN init_lsn, lsn, newfilelsn, oldfilelsn; DB_REP *db_rep; + DBT *d, data_dbt, lsndbt, mylog; LOG *lp; REP *rep; REP_CONTROL *rp; REP_VOTE_INFO *vi; - u_int32_t gen, type; - int done, i, master, old, recovering, ret, t_ret, *tally; + u_int32_t bytes, gen, gbytes, type, unused; + int check_limit, cmp, done, do_req, i; + int master, old, recovering, ret, t_ret, *tally; PANIC_CHECK(dbenv); + ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "rep_stat", DB_INIT_TXN); /* Control argument must be non-Null. */ if (control == NULL || control->size == 0) { @@ -109,17 +79,19 @@ __rep_process_message(dbenv, control, rec, eidp) dblp = dbenv->lg_handle; lp = dblp->reginfo.primary; - MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); + MUTEX_LOCK(dbenv, db_rep->mutexp); gen = rep->gen; recovering = F_ISSET(rep, REP_F_RECOVER); + + rep->stat.st_msgs_processed++; MUTEX_UNLOCK(dbenv, db_rep->mutexp); - /* - * dbenv->rep_db is the handle for the repository used for applying log - * records. - */ rp = (REP_CONTROL *)control->data; +#if 0 + __rep_print_message(rep->eid, rp, "rep_process_message"); +#endif + /* Complain if we see an improper version number. */ if (rp->rep_version != DB_REPVERSION) { __db_err(dbenv, @@ -136,13 +108,17 @@ __rep_process_message(dbenv, control, rec, eidp) /* * Check for generation number matching. Ignore any old messages - * except requests for ALIVE since the sender needs those to - * sync back up. If the message is newer, then we are out of - * sync and need to catch up with the rest of the system. + * except requests that are indicative of a new client that needs + * to get in sync. */ if (rp->gen < gen && rp->rectype != REP_ALIVE_REQ && - rp->rectype != REP_NEWCLIENT) + rp->rectype != REP_NEWCLIENT && rp->rectype != REP_MASTER_REQ) { + /* + * We don't hold the rep mutex, and could miscount if we race. + */ + rep->stat.st_msgs_badgen++; return (0); + } if (rp->gen > gen && rp->rectype != REP_ALIVE && rp->rectype != REP_NEWMASTER) return (__rep_send_message(dbenv, @@ -163,11 +139,39 @@ __rep_process_message(dbenv, control, rec, eidp) case REP_NEWMASTER: case REP_NEWSITE: case REP_VERIFY: + R_LOCK(dbenv, &dblp->reginfo); + cmp = log_compare(&lp->verify_lsn, &rp->lsn); + R_UNLOCK(dbenv, &dblp->reginfo); + if (cmp != 0) + goto skip; + /* FALLTHROUGH */ case REP_VOTE1: case REP_VOTE2: break; default: - return (0); +skip: /* + * We don't hold the rep mutex, and could + * miscount if we race. + */ + rep->stat.st_msgs_recover++; + + /* Check for need to retransmit. */ + R_LOCK(dbenv, &dblp->reginfo); + do_req = *eidp == rep->master_id && + ++lp->rcvd_recs >= lp->wait_recs; + if (do_req) { + lp->wait_recs *= 2; + if (lp->wait_recs + rep->max_gap) + lp->wait_recs = rep->max_gap; + lp->rcvd_recs = 0; + lsn = lp->verify_lsn; + } + R_UNLOCK(dbenv, &dblp->reginfo); + if (do_req) + ret = __rep_send_message(dbenv, *eidp, + REP_VERIFY_REQ, &lsn, NULL, 0); + + return (ret); } switch(rp->rectype) { @@ -187,12 +191,19 @@ __rep_process_message(dbenv, control, rec, eidp) F_ISSET(dbenv, DB_ENV_REP_MASTER) ? 1 : 0)); case REP_ALL_REQ: MASTER_ONLY(dbenv); + gbytes = bytes = 0; + MUTEX_LOCK(dbenv, db_rep->mutexp); + gbytes = rep->gbytes; + bytes = rep->bytes; + MUTEX_UNLOCK(dbenv, db_rep->mutexp); + check_limit = gbytes != 0 || bytes != 0; if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0) - goto err; + return (ret); memset(&data_dbt, 0, sizeof(data_dbt)); oldfilelsn = lsn = rp->lsn; + type = REP_LOG; for (ret = logc->get(logc, &rp->lsn, &data_dbt, DB_SET); - ret == 0; + ret == 0 && type == REP_LOG; ret = logc->get(logc, &lsn, &data_dbt, DB_NEXT)) { /* * lsn.offset will only be 0 if this is the @@ -226,8 +237,35 @@ __rep_process_message(dbenv, control, rec, eidp) &lsndbt, 0)) != 0) break; } - ret = __rep_send_message(dbenv, *eidp, - REP_LOG, &lsn, &data_dbt, 0); + if (check_limit) { + /* + * data_dbt.size is only the size of + * the log record; it doesn't count + * the size of the control structure. + * Factor that in as well so we're + * not off by a lot if our log + * records are small. + */ + while (bytes < data_dbt.size + + sizeof(REP_CONTROL)) { + if (gbytes > 0) { + bytes += GIGABYTE; + --gbytes; + continue; + } + /* + * We don't hold the rep mutex, + * and may miscount. + */ + rep->stat.st_nthrottles++; + type = REP_LOG_MORE; + goto send; + } + bytes -= (data_dbt.size + + sizeof(REP_CONTROL)); + } +send: ret = __rep_send_message(dbenv, *eidp, + type, &lsn, &data_dbt, 0); } /* @@ -250,7 +288,7 @@ __rep_process_message(dbenv, control, rec, eidp) return (__rep_send_message(dbenv, *eidp, REP_NEWMASTER, &lsn, NULL, 0)); } - MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); + MUTEX_LOCK(dbenv, db_rep->mutexp); ret = IN_ELECTION(rep) ? 0 : DB_REP_HOLDELECTION; MUTEX_UNLOCK(dbenv, db_rep->mutexp); return (ret); @@ -264,33 +302,55 @@ __rep_process_message(dbenv, control, rec, eidp) break; #endif case REP_LOG: + case REP_LOG_MORE: CLIENT_ONLY(dbenv); - return (__rep_apply(dbenv, rp, rec)); + if ((ret = __rep_apply(dbenv, rp, rec)) != 0) + return (ret); + if (rp->rectype == REP_LOG_MORE) { + MUTEX_LOCK(dbenv, db_rep->db_mutexp); + master = rep->master_id; + MUTEX_UNLOCK(dbenv, db_rep->db_mutexp); + R_LOCK(dbenv, &dblp->reginfo); + lsn = lp->lsn; + R_UNLOCK(dbenv, &dblp->reginfo); + ret = __rep_send_message(dbenv, master, + REP_ALL_REQ, &lsn, NULL, 0); + } + return (ret); case REP_LOG_REQ: MASTER_ONLY(dbenv); if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0) - goto err; + return (ret); memset(&data_dbt, 0, sizeof(data_dbt)); lsn = rp->lsn; - if ((ret = logc->get(logc, &rp->lsn, &data_dbt, DB_SET)) == 0) { - /* - * If the log file has changed, we may get back a - * log record with a later LSN than we requested. - * This most likely means that the log file - * changed, so we need to send a NEWFILE message. - */ - if (log_compare(&lsn, &rp->lsn) < 0 && - rp->lsn.offset == 0) - ret = __rep_send_message(dbenv, *eidp, - REP_NEWFILE, &lsn, NULL, 0); - else - ret = __rep_send_message(dbenv, *eidp, + + /* + * There are three different cases here. + * 1. We asked for a particular LSN and got it. + * 2. We asked for an LSN of X,0 which is invalid and got the + * first log record in a particular file. + * 3. We asked for an LSN and it's not found because it is + * beyond the end of a log file and we need a NEWFILE msg. + */ + ret = logc->get(logc, &rp->lsn, &data_dbt, DB_SET); + cmp = log_compare(&lsn, &rp->lsn); + + if (ret == 0 && cmp == 0) /* Case 1 */ + ret = __rep_send_message(dbenv, *eidp, REP_LOG, &rp->lsn, &data_dbt, 0); - } + else if (ret == DB_NOTFOUND || + (ret == 0 && cmp < 0 && rp->lsn.offset == 0)) + /* Cases 2 and 3: Send a NEWFILE message. */ + ret = __rep_send_message(dbenv, *eidp, + REP_NEWFILE, &lsn, NULL, 0); + if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) ret = t_ret; return (ret); case REP_NEWSITE: + /* We don't hold the rep mutex, and may miscount. */ + rep->stat.st_newsites++; + /* This is a rebroadcast; simply tell the application. */ if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) { dblp = dbenv->lg_handle; @@ -312,14 +372,16 @@ __rep_process_message(dbenv, control, rec, eidp) */ if ((ret = __rep_send_message(dbenv, DB_EID_BROADCAST, REP_NEWSITE, &rp->lsn, rec, 0)) != 0) - goto err; + return (ret); if (F_ISSET(dbenv, DB_ENV_REP_CLIENT)) return (0); /* FALLTHROUGH */ case REP_MASTER_REQ: - MASTER_ONLY(dbenv); + ANYSITE(dbenv); + if (F_ISSET(dbenv, DB_ENV_REP_CLIENT)) + return (0); dblp = dbenv->lg_handle; lp = dblp->reginfo.primary; R_LOCK(dbenv, &dblp->reginfo); @@ -333,8 +395,11 @@ __rep_process_message(dbenv, control, rec, eidp) case REP_NEWMASTER: ANYSITE(dbenv); if (F_ISSET(dbenv, DB_ENV_REP_MASTER) && - *eidp != dbenv->rep_eid) + *eidp != dbenv->rep_eid) { + /* We don't hold the rep mutex, and may miscount. */ + rep->stat.st_dupmasters++; return (DB_REP_DUPMASTER); + } return (__rep_new_master(dbenv, rp, *eidp)); case REP_PAGE: /* TODO */ CLIENT_ONLY(dbenv); @@ -350,36 +415,109 @@ __rep_process_message(dbenv, control, rec, eidp) break; case REP_VERIFY: CLIENT_ONLY(dbenv); + DB_ASSERT((F_ISSET(rep, REP_F_RECOVER) && + !IS_ZERO_LSN(lp->verify_lsn)) || + (!F_ISSET(rep, REP_F_RECOVER) && + IS_ZERO_LSN(lp->verify_lsn))); + if (IS_ZERO_LSN(lp->verify_lsn)) + return (0); + if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0) - goto err; + return (ret); memset(&mylog, 0, sizeof(mylog)); if ((ret = logc->get(logc, &rp->lsn, &mylog, DB_SET)) != 0) goto rep_verify_err; - db_rep = dbenv->rep_handle; - rep = db_rep->region; if (mylog.size == rec->size && memcmp(mylog.data, rec->data, rec->size) == 0) { - ret = __db_apprec(dbenv, &rp->lsn, 0); - MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); + /* + * If we're a logs-only client, we can simply truncate + * the log to the point where it last agreed with the + * master's; otherwise, recover to that point. + */ + R_LOCK(dbenv, &dblp->reginfo); + ZERO_LSN(lp->verify_lsn); + R_UNLOCK(dbenv, &dblp->reginfo); + if (F_ISSET(dbenv, DB_ENV_REP_LOGSONLY)) { + INIT_LSN(init_lsn); + if ((ret = dbenv->log_flush(dbenv, + &rp->lsn)) != 0 || + (ret = __log_vtruncate(dbenv, + &rp->lsn, &init_lsn)) != 0) + goto rep_verify_err; + } else if ((ret = __db_apprec(dbenv, &rp->lsn, 0)) != 0) + goto rep_verify_err; + + /* + * The log has been truncated (either by __db_apprec or + * directly). We want to make sure we're waiting for + * the LSN at the new end-of-log, not some later point. + */ + R_LOCK(dbenv, &dblp->reginfo); + lp->ready_lsn = lp->lsn; + ZERO_LSN(lp->waiting_lsn); + R_UNLOCK(dbenv, &dblp->reginfo); + + /* + * Discard any log records we have queued; we're + * about to re-request them, and can't trust the + * ones in the queue. + */ + MUTEX_LOCK(dbenv, db_rep->db_mutexp); + if ((ret = db_rep->rep_db->truncate(db_rep->rep_db, + NULL, &unused, 0)) != 0) { + MUTEX_UNLOCK(dbenv, db_rep->db_mutexp); + goto rep_verify_err; + } + rep->stat.st_log_queued = 0; + MUTEX_UNLOCK(dbenv, db_rep->db_mutexp); + + MUTEX_LOCK(dbenv, db_rep->mutexp); F_CLR(rep, REP_F_RECOVER); - MUTEX_UNLOCK(dbenv, db_rep->mutexp); - ret = __rep_send_message(dbenv, rep->master_id, - REP_ALL_REQ, &rp->lsn, NULL, 0); - } else if ((ret = logc->get(logc, &lsn, &mylog, DB_PREV)) == 0) + + /* + * If the master_id is invalid, this means that since + * the last record was sent, somebody declared an + * election and we may not have a master to request + * things of. + * + * This is not an error; when we find a new master, + * we'll re-negotiate where the end of the log is and + * try to bring ourselves up to date again anyway. + */ + if ((master = rep->master_id) == DB_EID_INVALID) { + DB_ASSERT(IN_ELECTION(rep)); + MUTEX_UNLOCK(dbenv, db_rep->mutexp); + ret = 0; + } else { + MUTEX_UNLOCK(dbenv, db_rep->mutexp); + ret = __rep_send_message(dbenv, master, + REP_ALL_REQ, &rp->lsn, NULL, 0); + } + } else if ((ret = + logc->get(logc, &lsn, &mylog, DB_PREV)) == 0) { + R_LOCK(dbenv, &dblp->reginfo); + lp->verify_lsn = lsn; + lp->rcvd_recs = 0; + lp->wait_recs = rep->request_gap; + R_UNLOCK(dbenv, &dblp->reginfo); ret = __rep_send_message(dbenv, *eidp, REP_VERIFY_REQ, &lsn, NULL, 0); + } + rep_verify_err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) ret = t_ret; - goto err; + return (ret); case REP_VERIFY_FAIL: + rep->stat.st_outdated++; return (DB_REP_OUTDATED); case REP_VERIFY_REQ: MASTER_ONLY(dbenv); type = REP_VERIFY; if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0) - goto err; + return (ret); d = &data_dbt; memset(d, 0, sizeof(data_dbt)); + F_SET(logc, DB_LOG_SILENT_ERR); ret = logc->get(logc, &rp->lsn, d, DB_SET); /* * If the LSN was invalid, then we might get a not @@ -400,7 +538,7 @@ rep_verify_err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) ret = __rep_send_message(dbenv, *eidp, type, &rp->lsn, d, 0); if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) ret = t_ret; - goto err; + return (ret); case REP_VOTE1: if (F_ISSET(dbenv, DB_ENV_REP_MASTER)) { #ifdef DIAGNOSTIC @@ -415,7 +553,7 @@ rep_verify_err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) } vi = (REP_VOTE_INFO *)rec->data; - MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); + MUTEX_LOCK(dbenv, db_rep->mutexp); /* * If you get a vote and you're not in an election, simply @@ -462,7 +600,8 @@ rep_verify_err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) /* * Change winners if the incoming record has a higher - * priority, or an equal priority but a larger LSN. + * priority, or an equal priority but a larger LSN, or + * an equal priority and LSN but higher "tiebreaker" value. */ #ifdef DIAGNOSTIC if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION)) { @@ -476,10 +615,12 @@ rep_verify_err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) rp->lsn.offset); } #endif + cmp = log_compare(&rp->lsn, &rep->w_lsn); if (vi->priority > rep->w_priority || (vi->priority != 0 && vi->priority == rep->w_priority && - log_compare(&rp->lsn, &rep->w_lsn) > 0)) { -#ifdef DIABNOSTIC + (cmp > 0 || + (cmp == 0 && vi->tiebreaker > rep->w_tiebreaker)))) { +#ifdef DIAGNOSTIC if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION)) __db_err(dbenv, "Accepting new vote"); #endif @@ -528,11 +669,12 @@ rep_verify_err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) R_LOCK(dbenv, &dblp->reginfo); lsn = lp->lsn; R_UNLOCK(dbenv, &dblp->reginfo); + rep->stat.st_elections_won++; return (__rep_send_message(dbenv, *eidp, REP_NEWMASTER, &lsn, NULL, 0)); } - MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); + MUTEX_LOCK(dbenv, db_rep->mutexp); /* If we have priority 0, we should never get a vote. */ DB_ASSERT(rep->priority != 0); @@ -573,6 +715,7 @@ rep_verify_err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) if (FLD_ISSET(dbenv->verbose, DB_VERB_REPLICATION)) __db_err(dbenv, "I won, sending NEWMASTER"); #endif + rep->stat.st_elections_won++; if ((ret = __rep_send_message(dbenv, DB_EID_BROADCAST, REP_NEWMASTER, &lsn, NULL, 0)) != 0) break; @@ -589,7 +732,7 @@ rep_verify_err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) return (0); unlock: MUTEX_UNLOCK(dbenv, db_rep->mutexp); -err: return (ret); + return (ret); } /* @@ -606,24 +749,27 @@ __rep_apply(dbenv, rp, rec) REP_CONTROL *rp; DBT *rec; { + __dbreg_register_args dbreg_args; __txn_ckp_args ckp_args; DB_REP *db_rep; - DBT data_dbt, key_dbt; + DBT control_dbt, key_dbt, lsn_dbt, nextrec_dbt, rec_dbt; DB *dbp; DBC *dbc; DB_LOG *dblp; - DB_LSN ckp_lsn, lsn, next_lsn; + DB_LSN ckp_lsn, lsn, newfile_lsn, next_lsn, waiting_lsn; LOG *lp; - int cmp, eid, ret, retry_count, t_ret; - u_int32_t rectype; + REP *rep; + REP_CONTROL lsn_rc; + u_int32_t rectype, txnid; + int cmp, do_req, eid, have_mutex, newfile, ret, t_ret; db_rep = dbenv->rep_handle; + rep = db_rep->region; dbp = db_rep->rep_db; dbc = NULL; - ret = 0; - retry_count = 0; - memset(&key_dbt, 0, sizeof(key_dbt)); - memset(&data_dbt, 0, sizeof(data_dbt)); + have_mutex = newfile = ret = 0; + memset(&control_dbt, 0, sizeof(control_dbt)); + memset(&rec_dbt, 0, sizeof(rec_dbt)); /* * If this is a log record and it's the next one in line, simply @@ -651,12 +797,23 @@ __rep_apply(dbenv, rp, rec) * log mutex, so the synchronization here is tricky. */ if (cmp == 0) { + /* We got the log record that we are expecting. */ if (rp->rectype == REP_NEWFILE) { -newfile: CHANGE_FILES; +newfile: ret = __rep_newfile(dbenv, rp, rec, &lp->ready_lsn); + + /* Make this evaluate to a simple rectype. */ + rectype = 0; } else { - ret = __log_put_int(dbenv, &rp->lsn, rec, rp->flags); + DB_ASSERT(log_compare(&rp->lsn, &lp->lsn) == 0); + ret = __log_rep_put(dbenv, &rp->lsn, rec); lp->ready_lsn = lp->lsn; memcpy(&rectype, rec->data, sizeof(rectype)); + if (ret == 0) + /* + * We may miscount if we race, since we + * don't currently hold the rep mutex. + */ + rep->stat.st_log_records++; } while (ret == 0 && IS_SIMPLE(rectype) && log_compare(&lp->ready_lsn, &lp->waiting_lsn) == 0) { @@ -664,14 +821,26 @@ newfile: CHANGE_FILES; * We just filled in a gap in the log record stream. * Write subsequent records to the log. */ -gap_check: R_UNLOCK(dbenv, &dblp->reginfo); - if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) +gap_check: lp->wait_recs = 0; + lp->rcvd_recs = 0; + R_UNLOCK(dbenv, &dblp->reginfo); + if (have_mutex == 0) { + MUTEX_LOCK(dbenv, db_rep->db_mutexp); + have_mutex = 1; + } + if (dbc == NULL && + (ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) goto err; + + /* The DBTs need to persist through another call. */ + F_SET(&control_dbt, DB_DBT_REALLOC); + F_SET(&rec_dbt, DB_DBT_REALLOC); if ((ret = dbc->c_get(dbc, - &key_dbt, &data_dbt, DB_RMW | DB_FIRST)) != 0) + &control_dbt, &rec_dbt, DB_RMW | DB_FIRST)) != 0) goto err; - rp = (REP_CONTROL *)key_dbt.data; - rec = &data_dbt; + + rp = (REP_CONTROL *)control_dbt.data; + rec = &rec_dbt; memcpy(&rectype, rec->data, sizeof(rectype)); R_LOCK(dbenv, &dblp->reginfo); /* @@ -681,41 +850,195 @@ gap_check: R_UNLOCK(dbenv, &dblp->reginfo); */ if (log_compare(&lp->ready_lsn, &rp->lsn) == 0) { if (rp->rectype != REP_NEWFILE) { - ret = __log_put_int(dbenv, - &rp->lsn, &data_dbt, rp->flags); + DB_ASSERT(log_compare + (&rp->lsn, &lp->lsn) == 0); + ret = __log_rep_put(dbenv, + &rp->lsn, rec); lp->ready_lsn = lp->lsn; - } else - CHANGE_FILES; + + /* + * We may miscount if we race, since we + * don't currently hold the rep mutex. + */ + if (ret == 0) + rep->stat.st_log_records++; + } else { + ret = __rep_newfile(dbenv, + rp, rec, &lp->ready_lsn); + rectype = 0; + } + waiting_lsn = lp->waiting_lsn; R_UNLOCK(dbenv, &dblp->reginfo); if ((ret = dbc->c_del(dbc, 0)) != 0) goto err; /* - * If the current rectype is simple, we're - * ready for another record; otherwise, - * don't get one, because we need to - * process the current one now. + * We may miscount, as we don't hold the rep + * mutex. */ - if (IS_SIMPLE(rectype)) { - ret = dbc->c_get(dbc, - &key_dbt, &data_dbt, DB_NEXT); - if (ret != DB_NOTFOUND && ret != 0) - goto err; - lsn = - ((REP_CONTROL *)key_dbt.data)->lsn; - if ((ret = dbc->c_close(dbc)) != 0) - goto err; - R_LOCK(dbenv, &dblp->reginfo); - if (ret == DB_NOTFOUND) { - ZERO_LSN(lp->waiting_lsn); - break; - } else - lp->waiting_lsn = lsn; - } else { - R_LOCK(dbenv, &dblp->reginfo); - lp->waiting_lsn = lp->ready_lsn; + --rep->stat.st_log_queued; + + /* + * Update waiting_lsn. We need to move it + * forward to the LSN of the next record + * in the queue. + */ + memset(&lsn_dbt, 0, sizeof(lsn_dbt)); + F_SET(&lsn_dbt, DB_DBT_USERMEM); + lsn_dbt.data = &lsn_rc; + lsn_dbt.ulen = sizeof(lsn_rc); + memset(&lsn_rc, 0, sizeof(lsn_rc)); + + /* + * If the next item in the database is a log + * record--the common case--we're not + * interested in its contents, just in its LSN. + * If it's a newfile message, though, the + * data field may be the LSN of the last + * record in the old file, and we need to use + * that to determine whether or not there's + * a gap. + * + * Optimize both these cases by doing a partial + * get of the data item. If it's a newfile + * record, we'll get the whole LSN, and if + * it's not, we won't waste time allocating. + */ + memset(&nextrec_dbt, 0, sizeof(nextrec_dbt)); + F_SET(&nextrec_dbt, + DB_DBT_USERMEM | DB_DBT_PARTIAL); + nextrec_dbt.ulen = + nextrec_dbt.dlen = sizeof(newfile_lsn); + ZERO_LSN(newfile_lsn); + nextrec_dbt.data = &newfile_lsn; + + ret = dbc->c_get(dbc, + &lsn_dbt, &nextrec_dbt, DB_NEXT); + if (ret != DB_NOTFOUND && ret != 0) + goto err; + + R_LOCK(dbenv, &dblp->reginfo); + if (ret == DB_NOTFOUND) { + /* + * Do a quick double-check to make + * sure waiting_lsn hasn't changed. + * It's possible that between the + * DB_NOTFOUND return and the R_LOCK, + * some record was added to the + * database, and we don't want to lose + * sight of the fact that it's there. + */ + if (log_compare(&waiting_lsn, + &lp->waiting_lsn) == 0) + ZERO_LSN( + lp->waiting_lsn); + + /* + * Whether or not the current record is + * simple, there's no next one, and + * therefore we haven't got anything + * else to do right now. Break out. + */ break; } + + DB_ASSERT(lsn_dbt.size == sizeof(lsn_rc)); + + /* + * NEWFILE records have somewhat convoluted + * semantics, so there are five cases + * pertaining to what the newly-gotten record + * is and what we want to do about it. + * + * 1) This isn't a NEWFILE record. Advance + * waiting_lsn and proceed. + * + * 2) NEWFILE, no LSN stored as the datum, + * lsn_rc.lsn == ready_lsn. The NEWFILE + * record is next, so set waiting_lsn = + * ready_lsn. + * + * 3) NEWFILE, no LSN stored as the datum, but + * lsn_rc.lsn > ready_lsn. There's still a + * gap; set waiting_lsn = lsn_rc.lsn. + * + * 4) NEWFILE, newfile_lsn in datum, and it's < + * ready_lsn. (If the datum is non-empty, + * it's the LSN of the last record in a log + * file, not the end of the log, and + * lsn_rc.lsn is the LSN of the start of + * the new file--we didn't have the end of + * the old log handy when we sent the + * record.) No gap--we're ready to + * proceed. Set both waiting and ready_lsn + * to lsn_rc.lsn. + * + * 5) NEWFILE, newfile_lsn in datum, and it's >= + * ready_lsn. We're still missing at + * least one record; set waiting_lsn, + * but not ready_lsn, to lsn_rc.lsn. + */ + if (lsn_rc.rectype == REP_NEWFILE && + nextrec_dbt.size > 0 && log_compare( + &newfile_lsn, &lp->ready_lsn) < 0) + /* Case 4. */ + lp->ready_lsn = + lp->waiting_lsn = lsn_rc.lsn; + else { + /* Cases 1, 2, 3, and 5. */ + DB_ASSERT(log_compare(&lsn_rc.lsn, + &lp->ready_lsn) >= 0); + lp->waiting_lsn = lsn_rc.lsn; + } + + /* + * If the current rectype is simple, we're + * done with it, and we should check and see + * whether the next record queued is the next + * one we're ready for. This is just the loop + * condition, so we continue. + * + * Otherwise, we need to break out of this loop + * and process this record first. + */ + if (!IS_SIMPLE(rectype)) + break; + } + } + + /* + * Check if we're at a gap in the table and if so, whether we + * need to ask for any records. + */ + do_req = 0; + if (!IS_ZERO_LSN(lp->waiting_lsn) && + log_compare(&lp->ready_lsn, &lp->waiting_lsn) != 0) { + next_lsn = lp->ready_lsn; + do_req = ++lp->rcvd_recs >= lp->wait_recs; + if (do_req) { + lp->wait_recs = rep->request_gap; + lp->rcvd_recs = 0; + } + } + + R_UNLOCK(dbenv, &dblp->reginfo); + if (dbc != NULL) { + if ((ret = dbc->c_close(dbc)) != 0) + goto err; + MUTEX_UNLOCK(dbenv, db_rep->db_mutexp); + have_mutex = 0; + } + dbc = NULL; + + if (do_req) { + MUTEX_LOCK(dbenv, db_rep->mutexp); + eid = db_rep->region->master_id; + MUTEX_UNLOCK(dbenv, db_rep->mutexp); + if (eid != DB_EID_INVALID) { + rep->stat.st_log_requested++; + if ((ret = __rep_send_message(dbenv, + eid, REP_LOG_REQ, &next_lsn, NULL, 0)) != 0) + goto err; } } } else if (cmp > 0) { @@ -749,61 +1072,143 @@ gap_check: R_UNLOCK(dbenv, &dblp->reginfo); * This record isn't in sequence; add it to the table and * update waiting_lsn if necessary. */ + memset(&key_dbt, 0, sizeof(key_dbt)); key_dbt.data = rp; key_dbt.size = sizeof(*rp); next_lsn = lp->lsn; + do_req = 0; + if (lp->wait_recs == 0) { + /* + * This is a new gap. Initialize the number of + * records that we should wait before requesting + * that it be resent. We grab the limits out of + * the rep without the mutex. + */ + lp->wait_recs = rep->request_gap; + lp->rcvd_recs = 0; + } + + if (++lp->rcvd_recs >= lp->wait_recs) { + /* + * If we've waited long enough, request the record + * and double the wait interval. + */ + do_req = 1; + lp->wait_recs <<= 1; + lp->rcvd_recs = 0; + if (lp->wait_recs > rep->max_gap) + lp->wait_recs = rep->max_gap; + } R_UNLOCK(dbenv, &dblp->reginfo); + + MUTEX_LOCK(dbenv, db_rep->db_mutexp); ret = dbp->put(dbp, NULL, &key_dbt, rec, 0); + rep->stat.st_log_queued++; + rep->stat.st_log_queued_total++; + if (rep->stat.st_log_queued_max < rep->stat.st_log_queued) + rep->stat.st_log_queued_max = rep->stat.st_log_queued; + MUTEX_UNLOCK(dbenv, db_rep->db_mutexp); + + if (ret != 0) + return (ret); - /* Request the LSN we are still waiting for. */ - MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); - eid = db_rep->region->master_id; - MUTEX_UNLOCK(dbenv, db_rep->mutexp); - ret = __rep_send_message(dbenv, eid, REP_LOG_REQ, - &next_lsn, NULL, 0); R_LOCK(dbenv, &dblp->reginfo); - if (ret == 0) - if (IS_ZERO_LSN(lp->waiting_lsn) || - log_compare(&rp->lsn, &lp->waiting_lsn) < 0) - lp->waiting_lsn = rp->lsn; + if (IS_ZERO_LSN(lp->waiting_lsn) || + log_compare(&rp->lsn, &lp->waiting_lsn) < 0) + lp->waiting_lsn = rp->lsn; R_UNLOCK(dbenv, &dblp->reginfo); + + if (do_req) { + /* Request the LSN we are still waiting for. */ + MUTEX_LOCK(dbenv, db_rep->mutexp); + + /* May as well do this after we grab the mutex. */ + eid = db_rep->region->master_id; + + /* + * If the master_id is invalid, this means that since + * the last record was sent, somebody declared an + * election and we may not have a master to request + * things of. + * + * This is not an error; when we find a new master, + * we'll re-negotiate where the end of the log is and + * try to to bring ourselves up to date again anyway. + */ + if (eid != DB_EID_INVALID) { + rep->stat.st_log_requested++; + MUTEX_UNLOCK(dbenv, db_rep->mutexp); + ret = __rep_send_message(dbenv, + eid, REP_LOG_REQ, &next_lsn, NULL, 0); + } else + MUTEX_UNLOCK(dbenv, db_rep->mutexp); + } return (ret); + } else { + R_UNLOCK(dbenv, &dblp->reginfo); + + /* + * We may miscount if we race, since we + * don't currently hold the rep mutex. + */ + rep->stat.st_log_duplicated++; } - R_UNLOCK(dbenv, &dblp->reginfo); - if (ret != 0 || cmp < 0 || (cmp == 0 && IS_SIMPLE(rectype))) - return (ret); + if (ret != 0 || cmp < 0 || (cmp == 0 && IS_SIMPLE(rectype))) + goto done; /* * If we got here, then we've got a log record in rp and rec that * we need to process. */ switch(rectype) { - case DB_txn_ckp: - /* Sync the memory pool and write the log record. */ + case DB___dbreg_register: + /* + * DB opens occur in the context of a transaction, so we can + * simply handle them when we process the transaction. Closes, + * however, are not transaction-protected, so we have to + * handle them here. + * + * Note that it should be unsafe for the master to do a close + * of a file that was opened in an active transaction, so we + * should be guaranteed to get the ordering right. + */ + memcpy(&txnid, (u_int8_t *)rec->data + + ((u_int8_t *)&dbreg_args.txnid - (u_int8_t *)&dbreg_args), + sizeof(u_int32_t)); + if (txnid == TXN_INVALID && + !F_ISSET(dbenv, DB_ENV_REP_LOGSONLY)) + ret = __db_dispatch(dbenv, dbenv->recover_dtab, + dbenv->recover_dtab_size, rec, &rp->lsn, + DB_TXN_APPLY, NULL); + break; + case DB___txn_ckp: + /* Sync the memory pool. */ memcpy(&ckp_lsn, (u_int8_t *)rec->data + ((u_int8_t *)&ckp_args.ckp_lsn - (u_int8_t *)&ckp_args), sizeof(DB_LSN)); -retry: if (!F_ISSET(dbenv, DB_ENV_REP_LOGSONLY)) { - ret = dbenv->memp_sync(dbenv, &ckp_lsn); - if (ret == DB_INCOMPLETE && retry_count < 4) { - (void)__os_sleep(dbenv, 1 << retry_count, 0); - retry_count++; - goto retry; - } - } - if (ret == 0) { - ret = dbenv->log_put(dbenv, &lsn, rec, rp->flags); - } - break; - case DB_log_register: - /* Simply redo the operation. */ if (!F_ISSET(dbenv, DB_ENV_REP_LOGSONLY)) - ret = __db_dispatch(dbenv, - NULL, rec, &rp->lsn, DB_TXN_APPLY, NULL); + ret = dbenv->memp_sync(dbenv, &ckp_lsn); + else + /* + * We ought to make sure the logs on a logs-only + * replica get flushed now and again. + */ + ret = dbenv->log_flush(dbenv, &ckp_lsn); break; - case DB_txn_regop: + case DB___txn_regop: if (!F_ISSET(dbenv, DB_ENV_REP_LOGSONLY)) - ret = __rep_process_txn(dbenv, rec); + do { + /* + * If an application is doing app-specific + * recovery and acquires locks while applying + * a transaction, it can deadlock. Any other + * locks held by this thread should have been + * discarded in the __rep_process_txn error + * path, so if we simply retry, we should + * eventually succeed. + */ + ret = __rep_process_txn(dbenv, rec); + } while (ret == DB_LOCK_DEADLOCK); break; default: goto err; @@ -817,8 +1222,16 @@ retry: if (!F_ISSET(dbenv, DB_ENV_REP_LOGSONLY)) { R_UNLOCK(dbenv, &dblp->reginfo); } +done: err: if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0) ret = t_ret; + if (have_mutex) + MUTEX_UNLOCK(dbenv, db_rep->db_mutexp); + + if (control_dbt.data != NULL) + __os_ufree(dbenv, control_dbt.data); + if (rec_dbt.data != NULL) + __os_ufree(dbenv, rec_dbt.data); return (ret); } @@ -828,196 +1241,266 @@ err: if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0) * * This is the routine that actually gets a transaction ready for * processing. + * + * PUBLIC: int __rep_process_txn __P((DB_ENV *, DBT *)); */ -static int -__rep_process_txn(dbenv, commit_rec) +int +__rep_process_txn(dbenv, rec) DB_ENV *dbenv; - DBT *commit_rec; + DBT *rec; { DBT data_dbt; DB_LOCKREQ req, *lvp; DB_LOGC *logc; - DB_LSN prev_lsn; - LSN_PAGE *ap; - TXN_RECS recs; + DB_LSN prev_lsn, *lsnp; + DB_REP *db_rep; + LSN_COLLECTION lc; + REP *rep; __txn_regop_args *txn_args; - u_int32_t op; + __txn_xa_regop_args *prep_args; + u_int32_t lockid, op, rectype; int i, ret, t_ret; int (**dtab)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); size_t dtabsize; + void *txninfo; + + db_rep = dbenv->rep_handle; + rep = db_rep->region; + + logc = NULL; + txninfo = NULL; + memset(&data_dbt, 0, sizeof(data_dbt)); + if (F_ISSET(dbenv, DB_ENV_THREAD)) + F_SET(&data_dbt, DB_DBT_REALLOC); /* - * There are three phases: First, we have to traverse + * There are two phases: First, we have to traverse * backwards through the log records gathering the list - * of all the pages accessed. Once we have this information - * we can acquire all the locks we need. Finally, we apply - * all the records in the transaction and release the locks. + * of all LSNs in the transaction. Once we have this information, + * we can loop through, acquire the locks we need for each record, + * and then apply it. */ dtab = NULL; - /* Make sure this is really a commit and not an abort! */ - if ((ret = __txn_regop_read(dbenv, commit_rec->data, &txn_args)) != 0) - return (ret); - op = txn_args->opcode; - prev_lsn = txn_args->prev_lsn; - __os_free(dbenv, txn_args, 0); - if (op != TXN_COMMIT) - return (0); + /* + * We may be passed a prepare (if we're restoring a prepare + * on upgrade) instead of a commit (the common case). + * Check which and behave appropriately. + */ + memcpy(&rectype, rec->data, sizeof(rectype)); + memset(&lc, 0, sizeof(lc)); + if (rectype == DB___txn_regop) { + /* + * We're the end of a transaction. Make sure this is + * really a commit and not an abort! + */ + if ((ret = __txn_regop_read(dbenv, rec->data, &txn_args)) != 0) + return (ret); + op = txn_args->opcode; + prev_lsn = txn_args->prev_lsn; + __os_free(dbenv, txn_args); + if (op != TXN_COMMIT) + return (0); + } else { + /* We're a prepare. */ + DB_ASSERT(rectype == DB___txn_xa_regop); + + if ((ret = + __txn_xa_regop_read(dbenv, rec->data, &prep_args)) != 0) + return (ret); + prev_lsn = prep_args->prev_lsn; + __os_free(dbenv, prep_args); + } - memset(&recs, 0, sizeof(recs)); - recs.txnid = txn_args->txnid->txnid; - if ((ret = dbenv->lock_id(dbenv, &recs.lockid)) != 0) + /* Phase 1. Get a list of the LSNs in this transaction, and sort it. */ + if ((ret = __rep_collect_txn(dbenv, &prev_lsn, &lc)) != 0) return (ret); + qsort(lc.array, lc.nlsns, sizeof(DB_LSN), __rep_lsn_cmp); + + if ((ret = dbenv->lock_id(dbenv, &lockid)) != 0) + goto err; /* Initialize the getpgno dispatch table. */ if ((ret = __rep_lockpgno_init(dbenv, &dtab, &dtabsize)) != 0) goto err; - if ((ret = __rep_lockpages(dbenv, - dtab, NULL, &prev_lsn, &recs, recs.lockid)) != 0) - goto err; - if (recs.nalloc == 0) + /* + * The set of records for a transaction may include dbreg_register + * records. Create a txnlist so that they can keep track of file + * state between records. + */ + if ((ret = __db_txnlist_init(dbenv, 0, 0, NULL, &txninfo)) != 0) goto err; - /* Phase 3: Apply updates and release locks. */ + /* Phase 2: Apply updates. */ if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0) goto err; - memset(&data_dbt, 0, sizeof(data_dbt)); - for (ap = &recs.array[0], i = 0; i < recs.npages; i++, ap++) { - if ((ret = logc->get(logc, &ap->lsn, &data_dbt, DB_SET)) != 0) + for (lsnp = &lc.array[0], i = 0; i < lc.nlsns; i++, lsnp++) { + if ((ret = __rep_lockpages(dbenv, + dtab, dtabsize, lsnp, NULL, NULL, lockid)) != 0) + goto err; + if ((ret = logc->get(logc, lsnp, &data_dbt, DB_SET)) != 0) goto err; - if ((ret = __db_dispatch(dbenv, NULL, - &data_dbt, &ap->lsn, DB_TXN_APPLY, NULL)) != 0) + if ((ret = __db_dispatch(dbenv, dbenv->recover_dtab, + dbenv->recover_dtab_size, &data_dbt, lsnp, + DB_TXN_APPLY, txninfo)) != 0) goto err; } -err: if (recs.nalloc != 0) { - req.op = DB_LOCK_PUT_ALL; - if ((t_ret = dbenv->lock_vec(dbenv, recs.lockid, - DB_LOCK_FREE_LOCKER, &req, 1, &lvp)) != 0 && ret == 0) - ret = t_ret; - __os_free(dbenv, recs.array, recs.nalloc * sizeof(LSN_PAGE)); - } +err: memset(&req, 0, sizeof(req)); + req.op = DB_LOCK_PUT_ALL; + if ((t_ret = dbenv->lock_vec(dbenv, lockid, + DB_LOCK_FREE_LOCKER, &req, 1, &lvp)) != 0 && ret == 0) + ret = t_ret; + + if (lc.nalloc != 0) + __os_free(dbenv, lc.array); if ((t_ret = - dbenv->lock_id_free(dbenv, recs.lockid)) != 0 && ret == 0) + dbenv->lock_id_free(dbenv, lockid)) != 0 && ret == 0) ret = t_ret; - if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) + if (logc != NULL && (t_ret = logc->close(logc, 0)) != 0 && ret == 0) ret = t_ret; + if (txninfo != NULL) + __db_txnlist_end(dbenv, txninfo); + if (F_ISSET(&data_dbt, DB_DBT_REALLOC) && data_dbt.data != NULL) - __os_free(dbenv, data_dbt.data, 0); + __os_ufree(dbenv, data_dbt.data); if (dtab != NULL) - __os_free(dbenv, dtab, 0); + __os_free(dbenv, dtab); + + if (ret == 0) + /* + * We don't hold the rep mutex, and could miscount if we race. + */ + rep->stat.st_txns_applied++; return (ret); } /* - * __rep_client_dbinit -- - * - * Initialize the LSN database on the client side. This is called from the - * client initialization code. The startup flag value indicates if - * this is the first thread/process starting up and therefore should create - * the LSN database. This routine must be called once by each process acting - * as a client. - * - * PUBLIC: int __rep_client_dbinit __P((DB_ENV *, int)); + * __rep_collect_txn + * Recursive function that will let us visit every entry in a transaction + * chain including all child transactions so that we can then apply + * the entire transaction family at once. */ -int -__rep_client_dbinit(dbenv, startup) +static int +__rep_collect_txn(dbenv, lsnp, lc) DB_ENV *dbenv; - int startup; + DB_LSN *lsnp; + LSN_COLLECTION *lc; { - DB_REP *db_rep; - DB *rep_db; - int ret, t_ret; - u_int32_t flags; + __txn_child_args *argp; + DB_LOGC *logc; + DB_LSN c_lsn; + DBT data; + u_int32_t rectype; + int nalloc, ret, t_ret; - PANIC_CHECK(dbenv); - db_rep = dbenv->rep_handle; - rep_db = NULL; + memset(&data, 0, sizeof(data)); + F_SET(&data, DB_DBT_REALLOC); -#define REPDBNAME "__db.rep.db" + if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0) + return (ret); - /* Check if this has already been called on this environment. */ - if (db_rep->rep_db != NULL) - return (0); + while (!IS_ZERO_LSN(*lsnp) && + (ret = logc->get(logc, lsnp, &data, DB_SET)) == 0) { + memcpy(&rectype, data.data, sizeof(rectype)); + if (rectype == DB___txn_child) { + if ((ret = __txn_child_read(dbenv, + data.data, &argp)) != 0) + goto err; + c_lsn = argp->c_lsn; + *lsnp = argp->prev_lsn; + __os_free(dbenv, argp); + ret = __rep_collect_txn(dbenv, &c_lsn, lc); + } else { + if (lc->nalloc < lc->nlsns + 1) { + nalloc = lc->nalloc == 0 ? 20 : lc->nalloc * 2; + if ((ret = __os_realloc(dbenv, + nalloc * sizeof(DB_LSN), &lc->array)) != 0) + goto err; + lc->nalloc = nalloc; + } + lc->array[lc->nlsns++] = *lsnp; + + /* + * Explicitly copy the previous lsn. The record + * starts with a u_int32_t record type, a u_int32_t + * txn id, and then the DB_LSN (prev_lsn) that we + * want. We copy explicitly because we have no idea + * what kind of record this is. + */ + memcpy(lsnp, (u_int8_t *)data.data + + sizeof(u_int32_t) + sizeof(u_int32_t), + sizeof(DB_LSN)); + } - if (startup) { - if ((ret = db_create(&rep_db, dbenv, 0)) != 0) + if (ret != 0) goto err; - /* - * Ignore errors, because if the file doesn't exist, this - * is perfectly OK. - */ - (void)rep_db->remove(rep_db, REPDBNAME, NULL, 0); } - if ((ret = db_create(&rep_db, dbenv, 0)) != 0) - goto err; - if ((ret = rep_db->set_bt_compare(rep_db, __rep_bt_cmp)) != 0) - goto err; - - flags = (F_ISSET(dbenv, DB_ENV_THREAD) ? DB_THREAD : 0) | - (startup ? DB_CREATE : 0); - if ((ret = rep_db->open(rep_db, - "__db.rep.db", NULL, DB_BTREE, flags, 0)) != 0) - goto err; - - /* Allow writes to this database on a client. */ - F_SET(rep_db, DB_CL_WRITER); - - db_rep->rep_db = rep_db; - - return (0); -err: - if (rep_db != NULL && - (t_ret = rep_db->close(rep_db, DB_NOSYNC)) != 0 && ret == 0) +err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) ret = t_ret; - db_rep->rep_db = NULL; - + if (data.data != NULL) + __os_ufree(dbenv, data.data); return (ret); } /* - * __rep_bt_cmp -- - * - * Comparison function for the LSN table. We use the entire control - * structure as a key (for simplicity, so we don't have to merge the - * other fields in the control with the data field), but really only - * care about the LSNs. + * __rep_lsn_cmp -- + * qsort-type-compatible wrapper for log_compare. */ static int -__rep_bt_cmp(dbp, dbt1, dbt2) - DB *dbp; - const DBT *dbt1, *dbt2; +__rep_lsn_cmp(lsn1, lsn2) + const void *lsn1, *lsn2; { - DB_LSN lsn1, lsn2; - REP_CONTROL *rp1, *rp2; - - COMPQUIET(dbp, NULL); - - rp1 = dbt1->data; - rp2 = dbt2->data; - - __ua_memcpy(&lsn1, &rp1->lsn, sizeof(DB_LSN)); - __ua_memcpy(&lsn2, &rp2->lsn, sizeof(DB_LSN)); - - if (lsn1.file > lsn2.file) - return (1); - if (lsn1.file < lsn2.file) - return (-1); + return (log_compare((DB_LSN *)lsn1, (DB_LSN *)lsn2)); +} - if (lsn1.offset > lsn2.offset) - return (1); +/* + * __rep_newfile -- + * NEWFILE messages can contain either the last LSN of the old file + * or the first LSN of the new one, depending on which we have available + * when the message is sent. When applying a NEWFILE message, make sure + * we haven't already swapped files, as it's possible (given the right sequence + * of out-of-order messages) to wind up with a NEWFILE message of each + * variety, and __rep_apply won't detect the two as duplicates of each other. + */ +static int +__rep_newfile(dbenv, rc, msgdbt, lsnp) + DB_ENV *dbenv; + REP_CONTROL *rc; + DBT *msgdbt; + DB_LSN *lsnp; +{ + DB_LOG *dblp; + LOG *lp; + u_int32_t newfile; - if (lsn1.offset < lsn2.offset) - return (-1); + dblp = dbenv->lg_handle; + lp = dblp->reginfo.primary; - return (0); + /* + * A NEWFILE message containing the old file's LSN will be + * accompanied by a NULL rec DBT; one containing the new one's LSN + * will need to supply the last record in the old file by + * sending it in the rec DBT. + */ + if (msgdbt == NULL || msgdbt->size == 0) + newfile = rc->lsn.file + 1; + else + newfile = rc->lsn.file; + + if (newfile > lp->lsn.file) + return (__log_newfile(dblp, lsnp)); + else { + /* We've already applied this NEWFILE. Just ignore it. */ + *lsnp = lp->lsn; + return (0); + } } - diff --git a/db/rep/rep_region.c b/db/rep/rep_region.c index 895a8f741..38b3d1791 100644 --- a/db/rep/rep_region.c +++ b/db/rep/rep_region.c @@ -1,13 +1,13 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2001 + * Copyright (c) 2001-2002 * Sleepycat Software. All rights reserved. */ #include "db_config.h" #ifndef lint -static const char revid[] = "Id: rep_region.c,v 1.14 2001/10/25 14:08:49 bostic Exp "; +static const char revid[] = "Id: rep_region.c,v 1.29 2002/08/06 04:50:36 bostic Exp "; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -16,8 +16,8 @@ static const char revid[] = "Id: rep_region.c,v 1.14 2001/10/25 14:08:49 bostic #include <string.h> #include "db_int.h" -#include "rep.h" -#include "log.h" +#include "dbinc/rep.h" +#include "dbinc/log.h" /* * __rep_region_init -- @@ -31,6 +31,7 @@ __rep_region_init(dbenv) { REGENV *renv; REGINFO *infop; + DB_MUTEX *db_mutexp; DB_REP *db_rep; REP *rep; int ret; @@ -40,7 +41,7 @@ __rep_region_init(dbenv) renv = infop->primary; ret = 0; - MUTEX_LOCK(dbenv, &renv->mutex, dbenv->lockfhp); + MUTEX_LOCK(dbenv, &renv->mutex); if (renv->rep_off == INVALID_ROFF) { /* Must create the region. */ if ((ret = __db_shalloc(infop->addr, @@ -49,19 +50,50 @@ __rep_region_init(dbenv) memset(rep, 0, sizeof(*rep)); rep->tally_off = INVALID_ROFF; renv->rep_off = R_OFFSET(infop, rep); - if ((ret = __db_mutex_init(dbenv, - &rep->mutex, renv->rep_off, 0)) != 0) + + if ((ret = __db_mutex_setup(dbenv, infop, &rep->mutex, + MUTEX_NO_RECORD)) != 0) + goto err; + + /* + * We must create a place for the db_mutex separately; + * mutexes have to be aligned to MUTEX_ALIGN, and the only way + * to guarantee that is to make sure they're at the beginning + * of a shalloc'ed chunk. + */ + if ((ret = __db_shalloc(infop->addr, sizeof(DB_MUTEX), + MUTEX_ALIGN, &db_mutexp)) != 0) + goto err; + rep->db_mutex_off = R_OFFSET(infop, db_mutexp); + + /* + * Because we have no way to prevent deadlocks and cannot log + * changes made to it, we single-thread access to the client + * bookkeeping database. This is suboptimal, but it only gets + * accessed when messages arrive out-of-order, so it should + * stay small and not be used in a high-performance app. + */ + if ((ret = __db_mutex_setup(dbenv, infop, db_mutexp, + MUTEX_NO_RECORD)) != 0) goto err; /* We have the region; fill in the values. */ rep->eid = DB_EID_INVALID; rep->master_id = DB_EID_INVALID; rep->gen = 0; + + /* + * Set default values for the min and max log records that we + * wait before requesting a missing log record. + */ + rep->request_gap = DB_REP_REQUEST_GAP; + rep->max_gap = DB_REP_MAX_GAP; } else rep = R_ADDR(infop, renv->rep_off); MUTEX_UNLOCK(dbenv, &renv->mutex); db_rep->mutexp = &rep->mutex; + db_rep->db_mutexp = R_ADDR(infop, rep->db_mutex_off); db_rep->region = rep; return (0); @@ -81,15 +113,19 @@ __rep_region_destroy(dbenv) DB_ENV *dbenv; { DB_REP *db_rep; - int ret; + int ret, t_ret; - ret = 0; + ret = t_ret = 0; db_rep = (DB_REP *)dbenv->rep_handle; - if (db_rep != NULL && db_rep->mutexp != NULL) - ret = __db_mutex_destroy(db_rep->mutexp); + if (db_rep != NULL) { + if (db_rep->mutexp != NULL) + ret = __db_mutex_destroy(db_rep->mutexp); + if (db_rep->db_mutexp != NULL) + t_ret = __db_mutex_destroy(db_rep->db_mutexp); + } - return (ret); + return (ret == 0 ? t_ret : ret); } /* @@ -107,7 +143,7 @@ __rep_dbenv_close(dbenv) db_rep = (DB_REP *)dbenv->rep_handle; if (db_rep != NULL) { - __os_free(dbenv, db_rep, sizeof(DB_REP)); + __os_free(dbenv, db_rep); dbenv->rep_handle = NULL; } @@ -116,32 +152,36 @@ __rep_dbenv_close(dbenv) /* * __rep_preclose -- - * If we are a client, shut down our client database. Remember that the - * client database was opened in its own environment, not the environment - * for which it keeps track of information. Also, if we have a client - * database (i.e., rep_handle->rep_db) that means we were a client and - * could have applied file opens that need to be closed now. This could - * also mask errors where dbp's that weren't opened by us are still open, - * but we have no way of distingushing the two. + * If we are a client, shut down our client database and, if we're + * actually closing the environment, close all databases we've opened + * while applying messages. * - * PUBLIC: int __rep_preclose __P((DB_ENV *)); + * PUBLIC: int __rep_preclose __P((DB_ENV *, int)); */ int -__rep_preclose(dbenv) +__rep_preclose(dbenv, do_closefiles) DB_ENV *dbenv; + int do_closefiles; { DB *dbp; DB_REP *db_rep; - int ret; + int ret, t_ret; - ret = 0; - db_rep = (DB_REP *)dbenv->rep_handle; + ret = t_ret = 0; + + /* If replication is not initialized, we have nothing to do. */ + if ((db_rep = (DB_REP *)dbenv->rep_handle) == NULL) + return (0); - if (db_rep != NULL && (dbp = db_rep->rep_db) != NULL) { - __log_close_files(dbenv); + if ((dbp = db_rep->rep_db) != NULL) { + MUTEX_LOCK(dbenv, db_rep->db_mutexp); ret = dbp->close(dbp, 0); db_rep->rep_db = NULL; + MUTEX_UNLOCK(dbenv, db_rep->db_mutexp); } - return (ret); + if (do_closefiles) + t_ret = __dbreg_close_files(dbenv); + + return (ret == 0 ? t_ret : ret); } diff --git a/db/rep/rep_util.c b/db/rep/rep_util.c index 2b7d9572e..e561f58d2 100644 --- a/db/rep/rep_util.c +++ b/db/rep/rep_util.c @@ -1,14 +1,14 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2001 + * Copyright (c) 2001-2002 * Sleepycat Software. All rights reserved. */ #include "db_config.h" #ifndef lint -static const char revid[] = "Id: rep_util.c,v 1.29 2001/11/16 10:57:51 krinsky Exp "; +static const char revid[] = "Id: rep_util.c,v 1.50 2002/08/06 04:50:36 bostic Exp "; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -17,28 +17,27 @@ static const char revid[] = "Id: rep_util.c,v 1.29 2001/11/16 10:57:51 krinsky E #endif #include "db_int.h" -#include "log.h" -#include "rep.h" -#include "txn.h" -#include "db_page.h" -#include "db_am.h" -#include "btree.h" -#include "hash.h" -#include "qam.h" -#include "db_shash.h" -#include "lock.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/fop.h" +#include "dbinc/hash.h" +#include "dbinc/log.h" +#include "dbinc/qam.h" +#include "dbinc/rep.h" +#include "dbinc/txn.h" /* * rep_util.c: * Miscellaneous replication-related utility functions, including * those called by other subsystems. */ -static int __rep_apply_thread __P((DB_ENV *, - int (**)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *), - DBT *, DB_LSN *, TXN_RECS *)); static int __rep_cmp_bylsn __P((const void *, const void *)); static int __rep_cmp_bypage __P((const void *, const void *)); +#ifdef REP_DIAGNOSTIC +static void __rep_print_logmsg __P((DB_ENV *, const DBT *, DB_LSN *)); +#endif + /* * __rep_check_alloc -- * Make sure the array of TXN_REC entries is of at least size n. @@ -90,6 +89,7 @@ __rep_send_message(dbenv, eid, rtype, lsnp, dbtp, flags) DBT cdbt, scrap_dbt; REP_CONTROL cntrl; u_int32_t send_flags; + int ret; db_rep = dbenv->rep_handle; rep = db_rep->region; @@ -104,7 +104,7 @@ __rep_send_message(dbenv, eid, rtype, lsnp, dbtp, flags) cntrl.flags = flags; cntrl.rep_version = DB_REPVERSION; cntrl.log_version = DB_LOGVERSION; - MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); + MUTEX_LOCK(dbenv, db_rep->mutexp); cntrl.gen = rep->gen; MUTEX_UNLOCK(dbenv, db_rep->mutexp); @@ -118,11 +118,66 @@ __rep_send_message(dbenv, eid, rtype, lsnp, dbtp, flags) dbtp = &scrap_dbt; } - send_flags = (LF_ISSET(DB_FLUSH) ? DB_REP_PERMANENT : 0); + send_flags = (LF_ISSET(DB_PERMANENT) ? DB_REP_PERMANENT : 0); - return (db_rep->rep_send(dbenv, &cdbt, dbtp, eid, send_flags)); +#if 0 + __rep_print_message(eid, &cntrl, "rep_send_message"); +#endif +#ifdef REP_DIAGNOSTIC + if (rtype == REP_LOG) + __rep_print_logmsg(dbenv, dbtp, lsnp); +#endif + ret = db_rep->rep_send(dbenv, &cdbt, dbtp, eid, send_flags); + + /* + * We don't hold the rep lock, so this could miscount if we race. + * I don't think it's worth grabbing the mutex for that bit of + * extra accuracy. + */ + if (ret == 0) + rep->stat.st_msgs_sent++; + else + rep->stat.st_msgs_send_failures++; + + return (ret); } +#ifdef REP_DIAGNOSTIC + +/* + * __rep_print_logmsg -- + * This is a debugging routine for printing out log records that + * we are about to transmit to a client. + */ + +static void +__rep_print_logmsg(dbenv, logdbt, lsnp) + DB_ENV *dbenv; + const DBT *logdbt; + DB_LSN *lsnp; +{ + /* Static structures to hold the printing functions. */ + static int (**ptab)__P((DB_ENV *, + DBT *, DB_LSN *, db_recops, void *)) = NULL; + size_t ptabsize = 0; + + if (ptabsize == 0) { + /* Initialize the table. */ + (void)__bam_init_print(dbenv, &ptab, &ptabsize); + (void)__crdel_init_print(dbenv, &ptab, &ptabsize); + (void)__db_init_print(dbenv, &ptab, &ptabsize); + (void)__dbreg_init_print(dbenv, &ptab, &ptabsize); + (void)__fop_init_print(dbenv, &ptab, &ptabsize); + (void)__qam_init_print(dbenv, &ptab, &ptabsize); + (void)__ham_init_print(dbenv, &ptab, &ptabsize); + (void)__txn_init_print(dbenv, &ptab, &ptabsize); + } + + (void)__db_dispatch(dbenv, + ptab, ptabsize, (DBT *)logdbt, lsnp, DB_TXN_PRINT, NULL); +} + +#endif /* * __rep_new_master -- * Called after a master election to sync back up with a new master. @@ -152,13 +207,14 @@ __rep_new_master(dbenv, cntrl, eid) db_rep = dbenv->rep_handle; rep = db_rep->region; - MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); + MUTEX_LOCK(dbenv, db_rep->mutexp); ELECTION_DONE(rep); change = rep->gen != cntrl->gen || rep->master_id != eid; if (change) { rep->gen = cntrl->gen; rep->master_id = eid; F_SET(rep, REP_F_RECOVER); + rep->stat.st_master_changes++; } MUTEX_UNLOCK(dbenv, db_rep->mutexp); @@ -180,8 +236,8 @@ __rep_new_master(dbenv, cntrl, eid) if (last_lsn.offset > sizeof(LOGP)) last_lsn.offset -= lp->len; R_UNLOCK(dbenv, &dblp->reginfo); - if (IS_INIT_LSN(lsn)) { -empty: MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); + if (IS_INIT_LSN(lsn) || IS_ZERO_LSN(lsn)) { +empty: MUTEX_LOCK(dbenv, db_rep->mutexp); F_CLR(rep, REP_F_RECOVER); MUTEX_UNLOCK(dbenv, db_rep->mutexp); @@ -211,6 +267,9 @@ empty: MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); return (ret); } + R_LOCK(dbenv, &dblp->reginfo); + lp->verify_lsn = last_lsn; + R_UNLOCK(dbenv, &dblp->reginfo); if ((ret = __rep_send_message(dbenv, eid, REP_VERIFY_REQ, &last_lsn, NULL, 0)) != 0) return (ret); @@ -240,9 +299,10 @@ __rep_lockpgno_init(dbenv, dtabp, dtabsizep) if ((ret = __bam_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 || (ret = __crdel_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 || (ret = __db_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 || + (ret = __dbreg_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 || + (ret = __fop_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 || (ret = __qam_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 || (ret = __ham_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 || - (ret = __log_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0 || (ret = __txn_init_getpgnos(dbenv, dtabp, dtabsizep)) != 0) return (ret); @@ -277,12 +337,13 @@ __rep_unlockpages(dbenv, lid) * * PUBLIC: int __rep_lockpages __P((DB_ENV *, * PUBLIC: int (**)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *), - * PUBLIC: DB_LSN *, DB_LSN *, TXN_RECS *, u_int32_t)); + * PUBLIC: size_t, DB_LSN *, DB_LSN *, TXN_RECS *, u_int32_t)); */ int -__rep_lockpages(dbenv, dtab, key_lsn, max_lsn, recs, lid) +__rep_lockpages(dbenv, dtab, dtabsize, key_lsn, max_lsn, recs, lid) DB_ENV *dbenv; int (**dtab)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + size_t dtabsize; DB_LSN *key_lsn, *max_lsn; TXN_RECS *recs; u_int32_t lid; @@ -328,10 +389,13 @@ __rep_lockpages(dbenv, dtab, key_lsn, max_lsn, recs, lid) /* Single transaction apply. */ if (max_lsn != NULL) { + DB_ASSERT(0); /* XXX */ + /* tmp_lsn = *max_lsn; - if ((ret = __rep_apply_thread(dbenv, dtab, + if ((ret = __rep_apply_thread(dbenv, dtab, dtabsize, &data_dbt, &tmp_lsn, t)) != 0) goto err; + */ } /* In recovery. */ @@ -343,11 +407,19 @@ __rep_lockpages(dbenv, dtab, key_lsn, max_lsn, recs, lid) /* Save lsn values, since dispatch functions can change them. */ tmp_lsn = *key_lsn; ret = __db_dispatch(dbenv, - dtab, &data_dbt, &tmp_lsn, DB_TXN_APPLY, t); + dtab, dtabsize, &data_dbt, &tmp_lsn, DB_TXN_GETPGNOS, t); if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) ret = t_ret; - if (ret != 0) + + /* + * If ret == DB_DELETED, this record refers to a temporary + * file and there's nothing to apply. + */ + if (ret == DB_DELETED) { + ret = 0; + goto out; + } else if (ret != 0) goto err; } @@ -380,8 +452,8 @@ __rep_lockpages(dbenv, dtab, key_lsn, max_lsn, recs, lid) /* Handle single lock case specially, else allocate space for locks. */ if (unique == 1) { memset(&lo, 0, sizeof(lo)); - lo.data = &t->array[i].pgdesc; - lo.size = sizeof(&t->array[0].pgdesc); + lo.data = &t->array[0].pgdesc; + lo.size = sizeof(t->array[0].pgdesc); ret = dbenv->lock_get(dbenv, lid, 0, &lo, DB_LOCK_WRITE, &l); goto out2; } @@ -408,30 +480,26 @@ __rep_lockpages(dbenv, dtab, key_lsn, max_lsn, recs, lid) locks.reqs[unique].mode = DB_LOCK_WRITE; locks.reqs[unique].obj = &locks.objs[unique]; locks.objs[unique].data = &t->array[i].pgdesc; - locks.objs[unique].size = sizeof(&t->array[i].pgdesc); + locks.objs[unique].size = sizeof(t->array[i].pgdesc); unique++; } } /* Finally, get the locks. */ if ((ret = - dbenv->lock_vec(dbenv, lid, 0, locks.reqs, unique, &lvp)) != 0) - goto err; - - if (0) { + dbenv->lock_vec(dbenv, lid, 0, locks.reqs, unique, &lvp)) != 0) { /* - * If we finished successfully, then we need to retain - * the locks, but we can free everything else up, because - * we can do a release by locker-id. + * If we were unsuccessful, unlock any locks we acquired before + * the error and return the original error value. */ -err: if ((t_ret = __rep_unlockpages(dbenv, lid)) != 0 && ret == 0) - ret = t_ret; + (void)__rep_unlockpages(dbenv, lid); } +err: out: if (locks.objs != NULL) - __os_free(dbenv, locks.objs, locks.n * sizeof(DBT)); + __os_free(dbenv, locks.objs); if (locks.reqs != NULL) - __os_free(dbenv, locks.reqs, locks.n * sizeof(DB_LOCKREQ)); + __os_free(dbenv, locks.reqs); /* * Before we return, sort by LSN so that we apply records in the @@ -439,11 +507,14 @@ out: if (locks.objs != NULL) */ qsort(t->array, t->npages, sizeof(LSN_PAGE), __rep_cmp_bylsn); -out2: if ((ret != 0 || recs == NULL) && t->nalloc != 0) - __os_free(dbenv, t->array, t->nalloc * sizeof(LSN_PAGE)); +out2: if ((ret != 0 || recs == NULL) && t->nalloc != 0) { + __os_free(dbenv, t->array); + t->array = NULL; + t->npages = t->nalloc = 0; + } if (F_ISSET(&data_dbt, DB_DBT_REALLOC) && data_dbt.data != NULL) - __os_free(dbenv, data_dbt.data, 0); + __os_ufree(dbenv, data_dbt.data); return (ret); } @@ -526,62 +597,6 @@ __rep_cmp_bylsn(a, b) } /* - * __rep_apply_thread - * Recursive function that will let us visit every entry in a transaction - * chain including all child transactions so that we can then apply - * the entire transaction family at once. - */ -static int -__rep_apply_thread(dbenv, dtab, datap, lsnp, recp) - DB_ENV *dbenv; - int (**dtab) __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); - DBT *datap; - DB_LSN *lsnp; - TXN_RECS *recp; -{ - __txn_child_args *argp; - DB_LOGC *logc; - DB_LSN c_lsn; - u_int32_t rectype; - int ret, t_ret; - - if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0) - return (ret); - - while (!IS_ZERO_LSN(*lsnp) && - (ret = logc->get(logc, lsnp, datap, DB_SET)) == 0) { - memcpy(&rectype, datap->data, sizeof(rectype)); - if (rectype == DB_txn_child) { - if ((ret = __txn_child_read(dbenv, - datap->data, &argp)) != 0) - goto err; - c_lsn = argp->c_lsn; - *lsnp = argp->prev_lsn; - __os_free(dbenv, argp, 0); - ret = __rep_apply_thread(dbenv, - dtab, datap, &c_lsn, recp); - } else { - ret = __db_dispatch(dbenv, dtab, - datap, lsnp, DB_TXN_APPLY, recp); - /* - * Explicitly copy the previous lsn since the - * page gathering routines don't modify it for you. - */ - memcpy(lsnp, (u_int8_t *)datap->data + - sizeof(u_int32_t) + sizeof (DB_TXN *), - sizeof(DB_LSN)); - } - - if (ret != 0) - goto err; - } - -err: if ((t_ret = logc->close(logc, 0)) != 0 && ret == 0) - ret = t_ret; - return (ret); -} - -/* * __rep_is_client * Used by other subsystems to figure out if this is a replication * client sites. @@ -600,7 +615,7 @@ __rep_is_client(dbenv) return (0); rep = db_rep->region; - MUTEX_LOCK(dbenv, db_rep->mutexp, dbenv->lockfhp); + MUTEX_LOCK(dbenv, db_rep->mutexp); ret = F_ISSET(rep, REP_F_UPGRADE | REP_F_LOGSONLY); MUTEX_UNLOCK(dbenv, db_rep->mutexp); return (ret); @@ -610,19 +625,22 @@ __rep_is_client(dbenv) * __rep_send_vote * Send this site's vote for the election. * - * PUBLIC: int __rep_send_vote __P((DB_ENV *, DB_LSN *, int, int)); + * PUBLIC: int __rep_send_vote __P((DB_ENV *, DB_LSN *, int, int, int)); */ int -__rep_send_vote(dbenv, lsnp, nsites, pri) +__rep_send_vote(dbenv, lsnp, nsites, pri, tiebreaker) DB_ENV *dbenv; DB_LSN *lsnp; - int nsites, pri; + int nsites, pri, tiebreaker; { DBT vote_dbt; REP_VOTE_INFO vi; + memset(&vi, 0, sizeof(vi)); + vi.priority = pri; vi.nsites = nsites; + vi.tiebreaker = tiebreaker; memset(&vote_dbt, 0, sizeof(vote_dbt)); vote_dbt.data = &vi; @@ -664,7 +682,7 @@ __rep_grow_sites(dbenv, nsites) infop = dbenv->reginfo; renv = infop->primary; - MUTEX_LOCK(dbenv, &renv->mutex, dbenv->lockfhp); + MUTEX_LOCK(dbenv, &renv->mutex); if ((ret = __db_shalloc(infop->addr, sizeof(nalloc * sizeof(int)), sizeof(int), &tally)) == 0) { if (rep->tally_off != INVALID_ROFF) @@ -755,3 +773,93 @@ err: if (LOCK_ISSET(lk) && (t_ret = __LPUT(dbc, lk)) != 0 && ret == 0) return (ret); } #endif + +#if 0 +/* + * PUBLIC: void __rep_print_message __P((int, REP_CONTROL *, char *)); + */ +void +__rep_print_message(eid, rp, str) + int eid; + REP_CONTROL *rp; + char *str; +{ + char *type; + switch (rp->rectype) { + case REP_ALIVE: + type = "alive"; + break; + case REP_ALIVE_REQ: + type = "alive_req"; + break; + case REP_ALL_REQ: + type = "all_req"; + break; + case REP_ELECT: + type = "elect"; + break; + case REP_FILE: + type = "file"; + break; + case REP_FILE_REQ: + type = "file_req"; + break; + case REP_LOG: + type = "log"; + break; + case REP_LOG_MORE: + type = "log_more"; + break; + case REP_LOG_REQ: + type = "log_req"; + break; + case REP_MASTER_REQ: + type = "master_req"; + break; + case REP_NEWCLIENT: + type = "newclient"; + break; + case REP_NEWFILE: + type = "newfile"; + break; + case REP_NEWMASTER: + type = "newmaster"; + break; + case REP_NEWSITE: + type = "newsite"; + break; + case REP_PAGE: + type = "page"; + break; + case REP_PAGE_REQ: + type = "page_req"; + break; + case REP_PLIST: + type = "plist"; + break; + case REP_PLIST_REQ: + type = "plist_req"; + break; + case REP_VERIFY: + type = "verify"; + break; + case REP_VERIFY_FAIL: + type = "verify_fail"; + break; + case REP_VERIFY_REQ: + type = "verify_req"; + break; + case REP_VOTE1: + type = "vote1"; + break; + case REP_VOTE2: + type = "vote2"; + break; + default: + type = "NOTYPE"; + break; + } + printf("%s: eid %d, type %s, LSN [%u][%u]\n", str, eid, + type, rp->lsn.file, rp->lsn.offset); +} +#endif diff --git a/db/tcl/docs/rep.html b/db/tcl/docs/rep.html index fb29579ad..079fe443a 100644 --- a/db/tcl/docs/rep.html +++ b/db/tcl/docs/rep.html @@ -1,4 +1,5 @@ -<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> +<!--Copyright 1999-2002 by Sleepycat Software, Inc.--> +<!--All rights reserved.--> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> diff --git a/db/test/bigfile002.tcl b/db/test/bigfile002.tcl index 395535e02..36e21933c 100644 --- a/db/test/bigfile002.tcl +++ b/db/test/bigfile002.tcl @@ -1,14 +1,14 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 2001 +# Copyright (c) 2001-2002 # Sleepycat Software. All rights reserved. # -# Id: bigfile002.tcl,v 11.4 2001/08/03 18:31:15 sandstro Exp +# Id: bigfile002.tcl,v 11.7 2002/08/10 13:39:26 bostic Exp # # TEST bigfile002 # TEST This one should be faster and not require so much disk space, -# although it doesn't test as extensively. Create an mpool file -# with 1K pages. Dirty page 6000000. Sync. +# TEST although it doesn't test as extensively. Create an mpool file +# TEST with 1K pages. Dirty page 6000000. Sync. proc bigfile002 { args } { source ./include.tcl @@ -19,7 +19,7 @@ proc bigfile002 { args } { env_cleanup $testdir # Create env. - set env [berkdb env -create -home $testdir] + set env [berkdb_env -create -home $testdir] error_check_good valid_env [is_valid_env $env] TRUE # Create the file. diff --git a/db/test/dead006.tcl b/db/test/dead006.tcl index d6ede9cb4..456ec6efb 100644 --- a/db/test/dead006.tcl +++ b/db/test/dead006.tcl @@ -1,9 +1,9 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 1996-2001 +# Copyright (c) 1996-2002 # Sleepycat Software. All rights reserved. # -# Id: dead006.tcl,v 1.3 2001/10/11 16:15:30 sandstro Exp +# Id: dead006.tcl,v 1.4 2002/01/11 15:53:21 bostic Exp # # TEST dead006 # TEST use timeouts rather than the normal dd algorithm. diff --git a/db/test/dead007.tcl b/db/test/dead007.tcl index 9f58c019a..c729454ec 100644 --- a/db/test/dead007.tcl +++ b/db/test/dead007.tcl @@ -1,9 +1,9 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 1996-2001 +# Copyright (c) 1996-2002 # Sleepycat Software. All rights reserved. # -# Id: dead007.tcl,v 1.2 2001/10/20 14:21:08 bostic Exp +# Id: dead007.tcl,v 1.3 2002/01/11 15:53:22 bostic Exp # # TEST dead007 # TEST use timeouts rather than the normal dd algorithm. diff --git a/db/test/env009.tcl b/db/test/env009.tcl index 40dba3770..818763929 100644 --- a/db/test/env009.tcl +++ b/db/test/env009.tcl @@ -1,9 +1,9 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 1999-2001 +# Copyright (c) 1999-2002 # Sleepycat Software. All rights reserved. # -# Id: env009.tcl,v 11.2 2001/08/03 16:39:24 bostic Exp +# Id: env009.tcl,v 11.5 2002/08/12 20:40:36 sandstro Exp # # TEST env009 # TEST Test calls to all the various stat functions. We have several @@ -17,7 +17,7 @@ proc env009 { } { env_cleanup $testdir puts "\tEnv009.a: Setting up env and a database." - set e [berkdb env -create -home $testdir -txn] + set e [berkdb_env -create -home $testdir -txn] error_check_good dbenv [is_valid_env $e] TRUE set dbbt [berkdb_open -create -btree $testdir/env009bt.db] error_check_good dbopen [is_valid_db $dbbt] TRUE @@ -27,7 +27,7 @@ proc env009 { } { error_check_good dbopen [is_valid_db $dbq] TRUE set rlist { - { "lock_stat" "Max locks" "Env009.b"} + { "lock_stat" "Maximum locks" "Env009.b"} { "log_stat" "Magic" "Env009.c"} { "mpool_stat" "Number of caches" "Env009.d"} { "txn_stat" "Max Txns" "Env009.e"} diff --git a/db/test/env010.tcl b/db/test/env010.tcl index 18bf1a717..76d6731b9 100644 --- a/db/test/env010.tcl +++ b/db/test/env010.tcl @@ -1,9 +1,9 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 1999-2001 +# Copyright (c) 1999-2002 # Sleepycat Software. All rights reserved. # -# Id: env010.tcl,v 1.2 2001/08/03 16:39:24 bostic Exp +# Id: env010.tcl,v 1.4 2002/02/20 17:08:21 sandstro Exp # # TEST env010 # TEST Run recovery in an empty directory, and then make sure we can still @@ -28,7 +28,7 @@ proc env010 { } { puts "\tEnv010: Creating env for $rmethod test." env_cleanup $testdir/EMPTYDIR - set e [berkdb env -create -home $testdir/EMPTYDIR -$rmethod] + set e [berkdb_env -create -home $testdir/EMPTYDIR -$rmethod] error_check_good dbenv [is_valid_env $e] TRUE # Open and close a database diff --git a/db/test/lock004.tcl b/db/test/lock004.tcl index fcbdf25a7..bef1700a4 100644 --- a/db/test/lock004.tcl +++ b/db/test/lock004.tcl @@ -1,9 +1,9 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 1996-2001 +# Copyright (c) 1996-2002 # Sleepycat Software. All rights reserved. # -# Id: lock004.tcl,v 11.2 2001/10/20 14:24:34 bostic Exp +# Id: lock004.tcl,v 11.5 2002/04/25 19:30:30 sue Exp # # TEST lock004 # TEST Test locker ids wraping around. @@ -13,37 +13,17 @@ proc lock004 {} { global lock_curid global lock_maxid - puts "Lock004.a -- locker id wrapping" - locktest -S [expr $lock_maxid - 1] $lock_maxid + set save_curid $lock_curid + set save_maxid $lock_maxid - puts "Lock004.b -- test out of locker ids" - env_cleanup $testdir + set lock_curid [expr $lock_maxid - 1] + puts "Lock004: Locker id wraparound test" + puts "\tLock004.a: repeat lock001-lock003 with wraparound lockids" - # Open/create the lock region - set e [berkdb env -create -lock -home $testdir] - error_check_good env_open [is_substr $e env] 1 + lock001 + lock002 + lock003 - catch { $e lock_id } locker1 - error_check_good locker1 [is_valid_locker $locker1] TRUE - error_check_good lock_id_set \ - [$e lock_id_set [expr $lock_maxid - 1] $lock_maxid] 0 - - catch { $e lock_id } locker2 - error_check_good locker2 [is_valid_locker $locker2] TRUE - catch { $e lock_id } locker3 - error_check_bad locker3 [is_valid_locker $locker3] TRUE - error_check_good locker3 [string match "*wrapped*" $locker3] 1 - - catch { $e lock_id_free $locker1 } ret - error_check_good free $ret 0 - catch { $e lock_id } locker4 - error_check_good locker4 [is_valid_locker $locker4] TRUE - - catch { $e lock_id_free $locker2 } ret - error_check_good free $ret 0 - catch { $e lock_id_free $locker4 } ret - error_check_good free $ret 0 - - catch {$e close} ret - error_check_good close $ret 0 + set lock_curid $save_curid + set lock_maxid $save_maxid } diff --git a/db/test/lock005.tcl b/db/test/lock005.tcl index 3f54745d3..33032afcc 100644 --- a/db/test/lock005.tcl +++ b/db/test/lock005.tcl @@ -1,12 +1,12 @@ # See the file LICENSE for redistribution information. # # Copyright (c) 1996-2001 -# Sleepycat Software. All rights reserved. +# Sleepycat Software. All rights reserved. # -# Id: lock005.tcl,v 1.1 2001/11/16 20:13:04 sandstro Exp +# Id: lock005.tcl,v 1.7 2002/08/08 15:38:07 bostic Exp # -# TEST lock005 -# TEST Check that page locks are being released properly. +# TEST lock005 +# TEST Check that page locks are being released properly. proc lock005 { } { source ./include.tcl @@ -17,31 +17,161 @@ proc lock005 { } { env_cleanup $testdir # Open/create the lock region - set e [berkdb env -create -lock -home $testdir -txn -log] + set e [berkdb_env -create -lock -home $testdir -txn -log] error_check_good env_open [is_valid_env $e] TRUE # Open/create the database - set db [berkdb open -create -env $e -len 10 -queue q.db] + set db [berkdb open -create -auto_commit -env $e -len 10 -queue q.db] error_check_good dbopen [is_valid_db $db] TRUE + # Check that records are locking by trying to + # fetch a record on the wrong transaction. + puts "\tLock005.a: Verify that we are locking" + # Start the first transaction set txn1 [$e txn -nowait] error_check_good txn_begin [is_valid_txn $txn1 $e] TRUE - set ret [$db put -txn $txn1 -append record1] - error_check_good dbput_txn1 $ret 1 + set ret [catch {$db put -txn $txn1 -append record1} recno1] + error_check_good dbput_txn1 $ret 0 - # Start a second transaction while first is still running + # Start second txn while the first is still running ... set txn2 [$e txn -nowait] - error_check_good txn_begin [is_valid_txn $txn2 $e] TRUE - set ret [catch {$db put -txn $txn2 -append record2} res] - error_check_good dbput_txn2 $ret 0 - error_check_good dbput_txn2recno $res 2 + error_check_good txn_begin [is_valid_txn $txn2 $e] TRUE - # Clean up + # ... and try to get a record from the first txn (should fail) + set ret [catch {$db get -txn $txn2 $recno1} res] + error_check_good dbget_wrong_record \ + [is_substr $res "Lock not granted"] 1 + + # End transactions error_check_good txn1commit [$txn1 commit] 0 + how_many_locks 1 $e error_check_good txn2commit [$txn2 commit] 0 + # The number of locks stays the same here because the first + # lock is released and the second lock was never granted. + how_many_locks 1 $e + + # Test lock behavior for both abort and commit + puts "\tLock005.b: Verify locks after abort or commit" + foreach endorder {forward reverse} { + end_order_test $db $e commit abort $endorder + end_order_test $db $e abort commit $endorder + end_order_test $db $e commit commit $endorder + end_order_test $db $e abort abort $endorder + } + + # Clean up error_check_good db_close [$db close] 0 error_check_good env_close [$e close] 0 +} +proc end_order_test { db e txn1end txn2end endorder } { + # Start one transaction + set txn1 [$e txn -nowait] + error_check_good txn_begin [is_valid_txn $txn1 $e] TRUE + set ret [catch {$db put -txn $txn1 -append record1} recno1] + error_check_good dbput_txn1 $ret 0 + + # Check number of locks + how_many_locks 2 $e + + # Start a second transaction while first is still running + set txn2 [$e txn -nowait] + error_check_good txn_begin [is_valid_txn $txn2 $e] TRUE + set ret [catch {$db put -txn $txn2 -append record2} recno2] + error_check_good dbput_txn2 $ret 0 + how_many_locks 3 $e + + # Now commit or abort one txn and make sure the other is okay + if {$endorder == "forward"} { + # End transaction 1 first + puts "\tLock005.b.1: $txn1end txn1 then $txn2end txn2" + error_check_good txn_$txn1end [$txn1 $txn1end] 0 + how_many_locks 2 $e + + # txn1 is now ended, but txn2 is still running + set ret1 [catch {$db get -txn $txn2 $recno1} res1] + set ret2 [catch {$db get -txn $txn2 $recno2} res2] + if { $txn1end == "commit" } { + error_check_good txn2_sees_txn1 $ret1 0 + error_check_good txn2_sees_txn2 $ret2 0 + } else { + # transaction 1 was aborted + error_check_good txn2_cantsee_txn1 [llength $res1] 0 + } + + # End transaction 2 second + error_check_good txn_$txn2end [$txn2 $txn2end] 0 + how_many_locks 1 $e + + # txn1 and txn2 should both now be invalid + # The get no longer needs to be transactional + set ret3 [catch {$db get $recno1} res3] + set ret4 [catch {$db get $recno2} res4] + + if { $txn2end == "commit" } { + error_check_good txn2_sees_txn1 $ret3 0 + error_check_good txn2_sees_txn2 $ret4 0 + error_check_good txn2_has_record2 \ + [is_substr $res4 "record2"] 1 + } else { + # transaction 2 was aborted + error_check_good txn2_cantsee_txn1 $ret3 0 + error_check_good txn2_aborted [llength $res4] 0 + } + + } elseif { $endorder == "reverse" } { + # End transaction 2 first + puts "\tLock005.b.2: $txn2end txn2 then $txn1end txn1" + error_check_good txn_$txn2end [$txn2 $txn2end] 0 + how_many_locks 2 $e + + # txn2 is ended, but txn1 is still running + set ret1 [catch {$db get -txn $txn1 $recno1} res1] + set ret2 [catch {$db get -txn $txn1 $recno2} res2] + if { $txn2end == "commit" } { + error_check_good txn1_sees_txn1 $ret1 0 + error_check_good txn1_sees_txn2 $ret2 0 + } else { + # transaction 2 was aborted + error_check_good txn1_cantsee_txn2 [llength $res2] 0 + } + + # End transaction 1 second + error_check_good txn_$txn1end [$txn1 $txn1end] 0 + how_many_locks 1 $e + + # txn1 and txn2 should both now be invalid + # The get no longer needs to be transactional + set ret3 [catch {$db get $recno1} res3] + set ret4 [catch {$db get $recno2} res4] + + if { $txn1end == "commit" } { + error_check_good txn1_sees_txn1 $ret3 0 + error_check_good txn1_sees_txn2 $ret4 0 + error_check_good txn1_has_record1 \ + [is_substr $res3 "record1"] 1 + } else { + # transaction 1 was aborted + error_check_good txn1_cantsee_txn2 $ret4 0 + error_check_good txn1_aborted [llength $res3] 0 + } + } } +proc how_many_locks { expected env } { + set stat [$env lock_stat] + set str "Current number of locks" + set checked 0 + foreach statpair $stat { + if { $checked == 1 } { + break + } + if { [is_substr [lindex $statpair 0] $str] != 0} { + set checked 1 + set nlocks [lindex $statpair 1] + error_check_good expected_nlocks $nlocks $expected + } + } + error_check_good checked $checked 1 +} diff --git a/db/test/parallel.tcl b/db/test/parallel.tcl index fdfc95d87..9080b2b0d 100644 --- a/db/test/parallel.tcl +++ b/db/test/parallel.tcl @@ -1,16 +1,16 @@ # Code to load up the tests in to the Queue database -# Id: parallel.tcl,v 11.9 2001/10/03 20:48:51 sandstro Exp +# Id: parallel.tcl,v 11.23 2002/08/08 19:25:39 sue Exp proc load_queue { file {dbdir RUNQUEUE} nitems } { puts -nonewline "Loading run queue with $nitems items..." flush stdout - set env [berkdb env -create -lock -home $dbdir] - error_check_good dbenv [is_valid_widget $env env] TRUE + set env [berkdb_env -create -lock -home $dbdir] + error_check_good dbenv [is_valid_env $env] TRUE set db [eval {berkdb_open -env $env -create -truncate \ - -mode 0644 -len 100 -queue queue.db} ] - error_check_good dbopen [is_valid_widget $db db] TRUE + -mode 0644 -len 120 -queue queue.db} ] + error_check_good dbopen [is_valid_db $db] TRUE set fid [open $file] @@ -54,29 +54,32 @@ proc load_queue { file {dbdir RUNQUEUE} nitems } { $env close } -proc init_runqueue { {dbdir RUNQUEUE} nitems } { +proc init_runqueue { {dbdir RUNQUEUE} nitems list} { if { [file exists $dbdir] != 1 } { file mkdir $dbdir } puts "Creating test list..." - run_all -n + $list -n load_queue ALL.OUT $dbdir $nitems - file delete ALL.OUT + file delete TEST.LIST + file rename ALL.OUT TEST.LIST +# file delete ALL.OUT } -proc run_parallel { nprocs {nitems ALL} } { +proc run_parallel { nprocs {list run_all} {nitems ALL} } { set basename ./PARALLEL_TESTDIR set queuedir ./RUNQUEUE source ./include.tcl mkparalleldirs $nprocs $basename $queuedir - init_runqueue $queuedir $nitems + init_runqueue $queuedir $nitems $list set basedir [pwd] set pidlist {} - set queuedir ../../[string range $basedir [string last "/" $basedir] end]/$queuedir + set queuedir ../../[string range $basedir \ + [string last "/" $basedir] end]/$queuedir for { set i 1 } { $i <= $nprocs } { incr i } { fileremove -f ALL.OUT.$i @@ -112,12 +115,12 @@ proc run_queue { i rundir queuedir nitems } { source ./include.tcl global env - set dbenv [berkdb env -create -lock -home $queuedir] - error_check_good dbenv [is_valid_widget $dbenv env] TRUE + set dbenv [berkdb_env -create -lock -home $queuedir] + error_check_good dbenv [is_valid_env $dbenv] TRUE set db [eval {berkdb_open -env $dbenv \ - -mode 0644 -len 80 -queue queue.db} ] - error_check_good dbopen [is_valid_widget $db db] TRUE + -mode 0644 -len 120 -queue queue.db} ] + error_check_good dbopen [is_valid_db $db] TRUE set dbc [eval $db cursor] error_check_good cursor [is_valid_cursor $dbc $db] TRUE @@ -131,7 +134,9 @@ proc run_queue { i rundir queuedir nitems } { set cmd [lindex [lindex $line 0] 1] set num [lindex [lindex $line 0] 0] set o [open $builddir/ALL.OUT.$i a] - puts $o "\nExecuting record $num:\n" + puts $o "\nExecuting record $num ([timestamp -w]):\n" + set tdir "TESTDIR.$i" + regsub {TESTDIR} $cmd $tdir cmd puts $o $cmd close $o if { [expr {$num % 10} == 0] } { @@ -179,6 +184,7 @@ proc mkparalleldirs { nprocs basename queuedir } { for { set i 1 } { $i <= $nprocs } { incr i } { set destdir $basename.$i catch {file mkdir $destdir} + puts "Created $destdir" if { $is_windows_test == 1 } { catch {file mkdir $destdir/Debug} catch {eval file copy \ @@ -202,13 +208,18 @@ proc mkparalleldirs { nprocs basename queuedir } { regsub {test_path } $d {test_path ../} d regsub {src_root } $d {src_root ../} d + set tdir "testdir ./TESTDIR.$i" + regsub {testdir \./TESTDIR} $d $tdir d regsub {KILL \.} $d {KILL ..} d set outfile [open $destdir/include.tcl w] puts $outfile $d close $outfile - if { [file exists $dir/berkeley_db_svc$EXE] } { - catch {eval file copy $dir/berkeley_db_svc$EXE $destdir} + global svc_list + foreach svc_exe $svc_list { + if { [file exists $dir/$svc_exe] } { + catch {eval file copy $dir/$svc_exe $destdir} + } } } } diff --git a/db/test/recd016.tcl b/db/test/recd016.tcl index 0513d1d18..1b50f2169 100644 --- a/db/test/recd016.tcl +++ b/db/test/recd016.tcl @@ -1,9 +1,9 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 1999-2001 +# Copyright (c) 1999-2002 # Sleepycat Software. All rights reserved. # -# Id: recd016.tcl,v 11.1 2001/11/07 18:45:02 sue Exp +# Id: recd016.tcl,v 11.6 2002/05/24 16:14:15 sue Exp # # TEST recd016 # TEST This is a recovery test for testing running recovery while @@ -39,12 +39,17 @@ proc recd016 { method args } { set t3 $testdir/t3 set t4 $testdir/t4 set t5 $testdir/t5 + # Since we are using txns, we need at least 1 lock per + # record (for queue). So set lock_max accordingly. + set lkmax [expr $nentries * 2] puts "\tRecd016.a: Create environment and database" - set env_cmd "berkdb env -create -log_max $log_max -txn -home $testdir" + set env_cmd "berkdb_env -create -log_max $log_max \ + -lock_max $lkmax -txn -home $testdir" set env [eval $env_cmd] error_check_good dbenv [is_valid_env $env] TRUE - set db [eval {berkdb_open -create} $omethod -env $env $args $testfile] + set db [eval {berkdb_open -create} \ + $omethod -auto_commit -env $env $args $testfile] error_check_good dbopen [is_valid_db $db] TRUE set did [open $dict] set abid [open $t4 w] @@ -149,8 +154,7 @@ proc recd016 { method args } { set env [eval $env_cmd] error_check_good dbenv [is_valid_env $env] TRUE - set txn "" - open_and_dump_file $testfile $env $txn $t1 $checkfunc \ + open_and_dump_file $testfile $env $t1 $checkfunc \ dump_file_direction "-first" "-next" filesort $t1 $t3 error_check_good envclose [$env close] 0 diff --git a/db/test/recd15scr.tcl b/db/test/recd15scr.tcl index 53760e635..a4039d31b 100644 --- a/db/test/recd15scr.tcl +++ b/db/test/recd15scr.tcl @@ -1,9 +1,9 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 1996-2001 +# Copyright (c) 1996-2002 # Sleepycat Software. All rights reserved. # -# Id: recd15scr.tcl,v 1.3 2001/05/10 15:22:18 sue Exp +# Id: recd15scr.tcl,v 1.5 2002/01/30 13:18:04 margo Exp # # Recd15 - lots of txns - txn prepare script # Usage: recd15script envcmd dbcmd gidf numtxns @@ -37,7 +37,7 @@ error_check_good envopen [is_valid_env $dbenv] TRUE set usedb 0 if { $dbfile != "NULL" } { set usedb 1 - set db [berkdb_open -env $dbenv $dbfile] + set db [berkdb_open -auto_commit -env $dbenv $dbfile] error_check_good dbopen [is_valid_db $db] TRUE } diff --git a/db/test/rep001.tcl b/db/test/rep001.tcl index f524bfcc9..b89cef418 100644 --- a/db/test/rep001.tcl +++ b/db/test/rep001.tcl @@ -1,51 +1,96 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 2001 +# Copyright (c) 2001-2002 # Sleepycat Software. All rights reserved. # -# Id: rep001.tcl,v 11.3 2001/11/16 10:50:12 krinsky Exp +# Id: rep001.tcl,v 1.14 2002/08/08 18:13:12 sue Exp # # TEST rep001 -# TEST Replication smoke test. +# TEST Replication rename and forced-upgrade test. # TEST # TEST Run a modified version of test001 in a replicated master environment; # TEST verify that the database on the client is correct. +# TEST Next, remove the database, close the master, upgrade the +# TEST client, reopen the master, and make sure the new master can correctly +# TEST run test001 and propagate it in the other direction. +proc rep001 { method { niter 1000 } { tnum "01" } args } { + global passwd -proc rep001 { method args } { + puts "Rep0$tnum: Replication sanity test." + + set envargs "" + rep001_sub $method $niter $tnum $envargs $args + + puts "Rep0$tnum: Replication and security sanity test." + append envargs " -encryptaes $passwd " + append args " -encrypt " + rep001_sub $method $niter $tnum $envargs $args +} + +proc rep001_sub { method niter tnum envargs largs } { source ./include.tcl global testdir + global encrypt env_cleanup $testdir - replsetup $testdir/REPDIR_MSGQUEUE + replsetup $testdir/MSGQUEUEDIR - set masterdir $testdir/REPDIR_MASTER - set clientdir $testdir/REPDIR_CLIENT + set masterdir $testdir/MASTERDIR + set clientdir $testdir/CLIENTDIR file mkdir $masterdir file mkdir $clientdir - puts "Rep001: Replication sanity test." + if { [is_record_based $method] == 1 } { + set checkfunc test001_recno.check + } else { + set checkfunc test001.check + } # Open a master. repladd 1 - set masterenv [berkdb env -create -log_max 1000000 \ - -home $masterdir -txn -rep_master -rep_transport [list 1 replsend]] + set masterenv \ + [eval {berkdb_env -create -lock_max 2500 -log_max 1000000} \ + $envargs {-home $masterdir -txn -rep_master -rep_transport \ + [list 1 replsend]}] error_check_good master_env [is_valid_env $masterenv] TRUE # Open a client repladd 2 - set clientenv [berkdb env -create \ - -home $clientdir -txn -rep_client -rep_transport [list 2 replsend]] + set clientenv [eval {berkdb_env -create} $envargs -txn -lock_max 2500 \ + {-home $clientdir -rep_client -rep_transport [list 2 replsend]}] error_check_good client_env [is_valid_env $clientenv] TRUE - # Run a modified test001 in the master. - puts "\tRep001.a: Running test001 in replicated env." - eval rep_test001 $method 10000 "01" -env $masterenv $args + # Bring the client online by processing the startup messages. + set donenow 0 + while { 1 } { + set nproced 0 + + incr nproced [replprocessqueue $masterenv 1] + incr nproced [replprocessqueue $clientenv 2] - # Loop, processing first the master's messages, then the client's, - # until both queues are empty. + if { $nproced == 0 } { + break + } + } + + # Open a test database on the master (so we can test having handles + # open across an upgrade). + puts "\tRep0$tnum.a:\ + Opening test database for post-upgrade client logging test." + set master_upg_db [berkdb_open \ + -create -auto_commit -btree -env $masterenv rep0$tnum-upg.db] + set puttxn [$masterenv txn] + error_check_good master_upg_db_put \ + [$master_upg_db put -txn $puttxn hello world] 0 + error_check_good puttxn_commit [$puttxn commit] 0 + error_check_good master_upg_db_close [$master_upg_db close] 0 + + # Run a modified test001 in the master (and update client). + puts "\tRep0$tnum.b: Running test001 in replicated env." + eval test001 $method $niter 0 $tnum 1 -env $masterenv $largs set donenow 0 while { 1 } { set nproced 0 @@ -58,157 +103,147 @@ proc rep001 { method args } { } } + # Open the cross-upgrade database on the client and check its contents. + set client_upg_db [berkdb_open \ + -create -auto_commit -btree -env $clientenv rep0$tnum-upg.db] + error_check_good client_upg_db_get [$client_upg_db get hello] \ + [list [list hello world]] + # !!! We use this handle later. Don't close it here. + # Verify the database in the client dir. - puts "\tRep001.b: Verifying client database contents." + puts "\tRep0$tnum.c: Verifying client database contents." + set testdir [get_home $masterenv] set t1 $testdir/t1 set t2 $testdir/t2 set t3 $testdir/t3 - open_and_dump_file test001.db $clientenv "" $testdir/t1 test001.check \ - dump_file_direction "-first" "-next" - filesort $t1 $t3 - error_check_good diff_files($t2,$t3) [filecmp $t2 $t3] 0 - - verify_dir $clientdir "\tRep001.c:" 0 0 1 -} + open_and_dump_file test0$tnum.db $clientenv $t1 \ + $checkfunc dump_file_direction "-first" "-next" + + # Remove the file (and update client). + puts "\tRep0$tnum.d: Remove the file on the master and close master." + error_check_good remove \ + [$masterenv dbremove -auto_commit test0$tnum.db] 0 + error_check_good masterenv_close [$masterenv close] 0 + set donenow 0 + while { 1 } { + set nproced 0 -proc rep_test001 { method {nentries 10000} {tnum "01"} args } { - source ./include.tcl + incr nproced [replprocessqueue $masterenv 1] + incr nproced [replprocessqueue $clientenv 2] - set args [convert_args $method $args] - set omethod [convert_method $method] - - puts "\tRep0$tnum: $method ($args) $nentries equal key/data pairs" - - # Create the database and open the dictionary - set eindex [lsearch -exact $args "-env"] - # - # If we are using an env, then testfile should just be the db name. - # Otherwise it is the test directory and the name. - # If we are not using an external env, then test setting - # the database cache size and using multiple caches. - if { $eindex == -1 } { - set testfile $testdir/test0$tnum.db - append args " -cachesize {0 1048576 3} " - set env NULL - } else { - set testfile test0$tnum.db - incr eindex - set env [lindex $args $eindex] + if { $nproced == 0 } { + break + } } - set t1 $testdir/t1 - set t2 $testdir/t2 - set t3 $testdir/t3 - set db [eval {berkdb_open \ - -create -mode 0644} $args $omethod $testfile] - error_check_good dbopen [is_valid_db $db] TRUE - set did [open $dict] - set pflags "" - set gflags "" - set txn "" + # Don't get confused in Tcl. + puts "\tRep0$tnum.e: Upgrade client." + set newmasterenv $clientenv + error_check_good upgrade_client [$newmasterenv rep_start -master] 0 - if { [is_record_based $method] == 1 } { - set checkfunc test001_recno.check - append gflags " -recno" - } else { - set checkfunc test001.check + # Run test001 in the new master + puts "\tRep0$tnum.f: Running test001 in new master." + eval test001 $method $niter 0 $tnum 1 -env $newmasterenv $largs + set donenow 0 + while { 1 } { + set nproced 0 + + incr nproced [replprocessqueue $newmasterenv 2] + + if { $nproced == 0 } { + break + } } - puts "\t\tRep0$tnum.a: put/get loop" - # Here is the loop where we put and get each key/data pair - set count 0 - while { [gets $did str] != -1 && $count < $nentries } { - if { [is_record_based $method] == 1 } { - global kvals - - set key [expr $count + 1] - if { 0xffffffff > 0 && $key > 0xffffffff } { - set key [expr $key - 0x100000000] - } - if { $key == 0 || $key - 0xffffffff == 1 } { - incr key - incr count - } - set kvals($key) [pad_data $method $str] - } else { - set key $str - set str [reverse $str] + + puts "\tRep0$tnum.g: Reopen old master as client and catch up." + # Throttle master so it can't send everything at once + $newmasterenv rep_limit 0 [expr 64 * 1024] + set newclientenv [eval {berkdb_env -create -recover} $envargs \ + -txn -lock_max 2500 \ + {-home $masterdir -rep_client -rep_transport [list 1 replsend]}] + error_check_good newclient_env [is_valid_env $newclientenv] TRUE + set donenow 0 + while { 1 } { + set nproced 0 + + incr nproced [replprocessqueue $newclientenv 1] + incr nproced [replprocessqueue $newmasterenv 2] + + if { $nproced == 0 } { + break } - set curtxn [$env txn] - set ret [eval {$db put} \ - -txn $curtxn $pflags {$key [chop_data $method $str]}] - error_check_good put $ret 0 - error_check_good txn_commit($key) [$curtxn commit] 0 - - set ret [eval {$db get} $gflags {$key}] - error_check_good \ - get $ret [list [list $key [pad_data $method $str]]] - - # Test DB_GET_BOTH for success - set ret [$db get -get_both $key [pad_data $method $str]] - error_check_good \ - getboth $ret [list [list $key [pad_data $method $str]]] - - # Test DB_GET_BOTH for failure - set ret [$db get -get_both $key [pad_data $method BAD$str]] - error_check_good getbothBAD [llength $ret] 0 - - incr count } - close $did - # Now we will get each key from the DB and compare the results - # to the original. - puts "\t\tRep0$tnum.b: dump file" - dump_file $db $txn $t1 $checkfunc - error_check_good db_close [$db close] 0 - - # Now compare the keys to see if they match the dictionary (or ints) - if { [is_record_based $method] == 1 } { - set oid [open $t2 w] - for {set i 1} {$i <= $nentries} {incr i} { - set j [expr $i] - if { 0xffffffff > 0 && $j > 0xffffffff } { - set j [expr $j - 0x100000000] - } - if { $j == 0 } { - incr i - incr j - } - puts $oid $j + set stats [$newmasterenv rep_stat] + set nthrottles [getstats $stats {Transmission limited}] + error_check_bad nthrottles $nthrottles -1 + error_check_bad nthrottles $nthrottles 0 + + # Run a modified test001 in the new master (and update client). + puts "\tRep0$tnum.h: Running test001 in new master." + eval test001 $method \ + $niter $niter $tnum 1 -env $newmasterenv $largs + set donenow 0 + while { 1 } { + set nproced 0 + + incr nproced [replprocessqueue $newclientenv 1] + incr nproced [replprocessqueue $newmasterenv 2] + + if { $nproced == 0 } { + break } - close $oid - } else { - set q q - filehead $nentries $dict $t2 } - filesort $t2 $t3 - file rename -force $t3 $t2 - filesort $t1 $t3 - - error_check_good \tRep0$tnum:diff($t3,$t2) \ - [filecmp $t3 $t2] 0 - - puts "\t\tRep0$tnum.c: close, open, and dump file" - # Now, reopen the file and run the last test again. - open_and_dump_file $testfile $env $txn $t1 $checkfunc \ - dump_file_direction "-first" "-next" - if { [string compare $omethod "-recno"] != 0 } { - filesort $t1 $t3 + + # Test put to the database handle we opened back when the new master + # was a client. + puts "\tRep0$tnum.i: Test put to handle opened before upgrade." + set puttxn [$newmasterenv txn] + error_check_good client_upg_db_put \ + [$client_upg_db put -txn $puttxn hello there] 0 + error_check_good puttxn_commit [$puttxn commit] 0 + set donenow 0 + while { 1 } { + set nproced 0 + + incr nproced [replprocessqueue $newclientenv 1] + incr nproced [replprocessqueue $newmasterenv 2] + + if { $nproced == 0 } { + break + } } - error_check_good \tRep0$tnum:diff($t2,$t3) \ - [filecmp $t2 $t3] 0 + # Close the new master's handle for the upgrade-test database; we + # don't need it. Then check to make sure the client did in fact + # update the database. + error_check_good client_upg_db_close [$client_upg_db close] 0 + set newclient_upg_db [berkdb_open -env $newclientenv rep0$tnum-upg.db] + error_check_good newclient_upg_db_get [$newclient_upg_db get hello] \ + [list [list hello there]] + error_check_good newclient_upg_db_close [$newclient_upg_db close] 0 - # Now, reopen the file and run the last test again in the - # reverse direction. - puts "\t\tRep0$tnum.d: close, open, and dump file in reverse direction" - open_and_dump_file $testfile $env $txn $t1 $checkfunc \ - dump_file_direction "-last" "-prev" + # Verify the database in the client dir. + puts "\tRep0$tnum.j: Verifying new client database contents." + set testdir [get_home $newmasterenv] + set t1 $testdir/t1 + set t2 $testdir/t2 + set t3 $testdir/t3 + open_and_dump_file test0$tnum.db $newclientenv $t1 \ + $checkfunc dump_file_direction "-first" "-next" - if { [string compare $omethod "-recno"] != 0 } { + if { [string compare [convert_method $method] -recno] != 0 } { filesort $t1 $t3 } + error_check_good diff_files($t2,$t3) [filecmp $t2 $t3] 0 - error_check_good \tRep0$tnum:diff($t3,$t2) \ - [filecmp $t3 $t2] 0 -} + error_check_good newmasterenv_close [$newmasterenv close] 0 + error_check_good newclientenv_close [$newclientenv close] 0 + + if { [lsearch $envargs "-encrypta*"] !=-1 } { + set encrypt 1 + } + error_check_good verify \ + [verify_dir $clientdir "\tRep0$tnum.k: " 0 0 1] 0 + replclose $testdir/MSGQUEUEDIR +} diff --git a/db/test/reputils.tcl b/db/test/reputils.tcl index d41886a80..ed0aa786d 100644 --- a/db/test/reputils.tcl +++ b/db/test/reputils.tcl @@ -1,14 +1,32 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 2001 +# Copyright (c) 2001-2002 # Sleepycat Software. All rights reserved. # -# Id: reputils.tcl,v 11.3 2001/11/16 00:36:20 krinsky Exp +# Id: reputils.tcl,v 11.34 2002/08/12 17:54:18 sandstro Exp # # Replication testing utilities # Environment handle for the env containing the replication "communications # structure" (really a CDB environment). + +# The test environment consists of a queue and a # directory (environment) +# per replication site. The queue is used to hold messages destined for a +# particular site and the directory will contain the environment for the +# site. So the environment looks like: +# $testdir +# ___________|______________________________ +# / | \ \ +# MSGQUEUEDIR MASTERDIR CLIENTDIR.0 ... CLIENTDIR.N-1 +# | | ... | +# 1 2 .. N+1 +# +# The master is site 1 in the MSGQUEUEDIR and clients 1-N map to message +# queues 2 - N+1. +# +# The globals repenv(1-N) contain the environment handles for the sites +# with a given id (i.e., repenv(1) is the master's environment. + global queueenv # Array of DB handles, one per machine ID, for the databases that contain @@ -16,13 +34,347 @@ global queueenv global queuedbs global machids +global elect_timeout +set elect_timeout 50000000 +set drop 0 + +# Create the directory structure for replication testing. +# Open the master and client environments; store these in the global repenv +# Return the master's environment: "-env masterenv" +# +proc repl_envsetup { envargs largs tnum {nclients 1} {droppct 0} { oob 0 } } { + source ./include.tcl + global clientdir + global drop drop_msg + global masterdir + global repenv + global testdir + + env_cleanup $testdir + + replsetup $testdir/MSGQUEUEDIR + + set masterdir $testdir/MASTERDIR + file mkdir $masterdir + if { $droppct != 0 } { + set drop 1 + set drop_msg [expr 100 / $droppct] + } else { + set drop 0 + } + + for { set i 0 } { $i < $nclients } { incr i } { + set clientdir($i) $testdir/CLIENTDIR.$i + file mkdir $clientdir($i) + } + + # Open a master. + repladd 1 + # + # Set log smaller than default to force changing files, + # but big enough so that the tests that use binary files + # as keys/data can run. + # + set lmax [expr 3 * 1024 * 1024] + set masterenv [eval {berkdb_env -create -log_max $lmax} $envargs \ + {-home $masterdir -txn -rep_master -rep_transport \ + [list 1 replsend]}] + error_check_good master_env [is_valid_env $masterenv] TRUE + set repenv(master) $masterenv + + # Open clients + for { set i 0 } { $i < $nclients } { incr i } { + set envid [expr $i + 2] + repladd $envid + set clientenv [eval {berkdb_env -create} $envargs -txn \ + {-cachesize { 0 10000000 0 }} -lock_max 10000 \ + {-home $clientdir($i) -rep_client -rep_transport \ + [list $envid replsend]}] + error_check_good client_env [is_valid_env $clientenv] TRUE + set repenv($i) $clientenv + } + set repenv($i) NULL + append largs " -env $masterenv " + + # Process startup messages + repl_envprocq $tnum $nclients $oob + + return $largs +} + +# Process all incoming messages. Iterate until there are no messages left +# in anyone's queue so that we capture all message exchanges. We verify that +# the requested number of clients matches the number of client environments +# we have. The oob parameter indicates if we should process the queue +# with out-of-order delivery. The replprocess procedure actually does +# the real work of processing the queue -- this routine simply iterates +# over the various queues and does the initial setup. + +proc repl_envprocq { tnum { nclients 1 } { oob 0 }} { + global repenv + global drop + + set masterenv $repenv(master) + for { set i 0 } { 1 } { incr i } { + if { $repenv($i) == "NULL"} { + break + } + } + error_check_good i_nclients $nclients $i + + set name [format "Repl%03d" $tnum] + berkdb debug_check + puts -nonewline "\t$name: Processing master/$i client queues" + set rand_skip 0 + if { $oob } { + puts " out-of-order" + } else { + puts " in order" + } + set do_check 1 + set droprestore $drop + while { 1 } { + set nproced 0 + + if { $oob } { + set rand_skip [berkdb random_int 2 10] + } + incr nproced [replprocessqueue $masterenv 1 $rand_skip] + for { set i 0 } { $i < $nclients } { incr i } { + set envid [expr $i + 2] + if { $oob } { + set rand_skip [berkdb random_int 2 10] + } + set n [replprocessqueue $repenv($i) \ + $envid $rand_skip] + incr nproced $n + } + + if { $nproced == 0 } { + # Now that we delay requesting records until + # we've had a few records go by, we should always + # see that the number of requests is lower than the + # number of messages that were enqueued. + for { set i 0 } { $i < $nclients } { incr i } { + set clientenv $repenv($i) + set stats [$clientenv rep_stat] + set queued [getstats $stats \ + {Total log records queued}] + error_check_bad queued_stats \ + $queued -1 + set requested [getstats $stats \ + {Log records requested}] + error_check_bad requested_stats \ + $requested -1 + if { $queued != 0 && $do_check != 0 } { + error_check_good num_requested \ + [expr $requested < $queued] 1 + } + + $clientenv rep_request 1 1 + } + + # If we were dropping messages, we might need + # to flush the log so that we get everything + # and end up in the right state. + if { $drop != 0 } { + set drop 0 + set do_check 0 + $masterenv rep_flush + berkdb debug_check + puts "\t$name: Flushing Master" + } else { + break + } + } + } + + # Reset the clients back to the default state in case we + # have more processing to do. + for { set i 0 } { $i < $nclients } { incr i } { + set clientenv $repenv($i) + $clientenv rep_request 4 128 + } + set drop $droprestore +} + +# Verify that the directories in the master are exactly replicated in +# each of the client environments. + +proc repl_envver0 { tnum method { nclients 1 } } { + global clientdir + global masterdir + global repenv + + # Verify the database in the client dir. + # First dump the master. + set t1 $masterdir/t1 + set t2 $masterdir/t2 + set t3 $masterdir/t3 + set omethod [convert_method $method] + set name [format "Repl%03d" $tnum] + + # + # We are interested in the keys of whatever databases are present + # in the master environment, so we just call a no-op check function + # since we have no idea what the contents of this database really is. + # We just need to walk the master and the clients and make sure they + # have the same contents. + # + set cwd [pwd] + cd $masterdir + set stat [catch {glob test*.db} dbs] + cd $cwd + if { $stat == 1 } { + return + } + foreach testfile $dbs { + open_and_dump_file $testfile $repenv(master) $masterdir/t2 \ + repl_noop dump_file_direction "-first" "-next" + + if { [string compare [convert_method $method] -recno] != 0 } { + filesort $t2 $t3 + file rename -force $t3 $t2 + } + for { set i 0 } { $i < $nclients } { incr i } { + puts "\t$name: Verifying client $i database \ + $testfile contents." + open_and_dump_file $testfile $repenv($i) \ + $t1 repl_noop dump_file_direction "-first" "-next" + + if { [string compare $omethod "-recno"] != 0 } { + filesort $t1 $t3 + } else { + catch {file copy -force $t1 $t3} ret + } + error_check_good diff_files($t2,$t3) [filecmp $t2 $t3] 0 + } + } +} + +# Remove all the elements from the master and verify that these +# deletions properly propagated to the clients. + +proc repl_verdel { tnum method { nclients 1 } } { + global clientdir + global masterdir + global repenv + + # Delete all items in the master. + set name [format "Repl%03d" $tnum] + set cwd [pwd] + cd $masterdir + set stat [catch {glob test*.db} dbs] + cd $cwd + if { $stat == 1 } { + return + } + foreach testfile $dbs { + puts "\t$name: Deleting all items from the master." + set txn [$repenv(master) txn] + error_check_good txn_begin [is_valid_txn $txn \ + $repenv(master)] TRUE + set db [berkdb_open -txn $txn -env $repenv(master) $testfile] + error_check_good reopen_master [is_valid_db $db] TRUE + set dbc [$db cursor -txn $txn] + error_check_good reopen_master_cursor \ + [is_valid_cursor $dbc $db] TRUE + for { set dbt [$dbc get -first] } { [llength $dbt] > 0 } \ + { set dbt [$dbc get -next] } { + error_check_good del_item [$dbc del] 0 + } + error_check_good dbc_close [$dbc close] 0 + error_check_good txn_commit [$txn commit] 0 + error_check_good db_close [$db close] 0 + + repl_envprocq $tnum $nclients + + # Check clients. + for { set i 0 } { $i < $nclients } { incr i } { + puts "\t$name: Verifying emptiness of client database $i." + + set db [berkdb_open -env $repenv($i) $testfile] + error_check_good reopen_client($i) \ + [is_valid_db $db] TRUE + set dbc [$db cursor] + error_check_good reopen_client_cursor($i) \ + [is_valid_cursor $dbc $db] TRUE + + error_check_good client($i)_empty \ + [llength [$dbc get -first]] 0 + + error_check_good dbc_close [$dbc close] 0 + error_check_good db_close [$db close] 0 + } + } +} + +# Replication "check" function for the dump procs that expect to +# be able to verify the keys and data. +proc repl_noop { k d } { + return +} + +# Close all the master and client environments in a replication test directory. +proc repl_envclose { tnum envargs } { + source ./include.tcl + global clientdir + global encrypt + global masterdir + global repenv + global testdir + + if { [lsearch $envargs "-encrypta*"] !=-1 } { + set encrypt 1 + } + + # In order to make sure that we have fully-synced and ready-to-verify + # databases on all the clients, do a checkpoint on the master and + # process messages in order to flush all the clients. + set drop 0 + set do_check 0 + set name [format "Repl%03d" $tnum] + berkdb debug_check + puts "\t$name: Checkpointing master." + error_check_good masterenv_ckp [$repenv(master) txn_checkpoint] 0 + + # Count clients. + for { set ncli 0 } { 1 } { incr ncli } { + if { $repenv($ncli) == "NULL" } { + break + } + } + repl_envprocq $tnum $ncli + + error_check_good masterenv_close [$repenv(master) close] 0 + verify_dir $masterdir "\t$name: " 0 0 1 + for { set i 0 } { $i < $ncli } { incr i } { + error_check_good client($i)_close [$repenv($i) close] 0 + verify_dir $clientdir($i) "\t$name: " 0 0 1 + } + replclose $testdir/MSGQUEUEDIR + +} + +# Close up a replication group +proc replclose { queuedir } { + global queueenv queuedbs machids + + foreach m $machids { + set db $queuedbs($m) + error_check_good dbr_close [$db close] 0 + } + error_check_good qenv_close [$queueenv close] 0 + set machids {} +} + # Create a replication group for testing. proc replsetup { queuedir } { global queueenv queuedbs machids file mkdir $queuedir set queueenv \ - [berkdb env -create -cdb -home $queuedir] + [berkdb_env -create -txn -lock_max 20000 -home $queuedir] error_check_good queueenv [is_valid_env $queueenv] TRUE if { [info exists queuedbs] } { @@ -33,18 +385,30 @@ proc replsetup { queuedir } { return $queueenv } +# Send function for replication. proc replsend { control rec fromid toid } { - global queuedbs machids - + global queuedbs queueenv machids + global drop drop_msg + # + # If we are testing with dropped messages, then we drop every + # $drop_msg time. If we do that just return 0 and don't do + # anything. + # + if { $drop != 0 } { + incr drop + if { $drop == $drop_msg } { + set drop 1 + return 0 + } + } # XXX # -1 is DB_BROADCAST_MID if { $toid == -1 } { set machlist $machids } else { if { [info exists queuedbs($toid)] != 1 } { - puts stderr "FAIL: replsend: machid $toid not found" - return -1 + error "replsend: machid $toid not found" } set machlist [list $toid] } @@ -56,13 +420,34 @@ proc replsend { control rec fromid toid } { } set db $queuedbs($m) - - $db put -append [list $control $rec $fromid] + set txn [$queueenv txn] + $db put -txn $txn -append [list $control $rec $fromid] + error_check_good replsend_commit [$txn commit] 0 } return 0 } +# Nuke all the pending messages for a particular site. +proc replclear { machid } { + global queuedbs queueenv + + if { [info exists queuedbs($machid)] != 1 } { + error "FAIL: replclear: machid $machid not found" + } + + set db $queuedbs($machid) + set txn [$queueenv txn] + set dbc [$db cursor -txn $txn] + for { set dbt [$dbc get -rmw -first] } { [llength $dbt] > 0 } \ + { set dbt [$dbc get -rmw -next] } { + error_check_good replclear($machid)_del [$dbc del] 0 + } + error_check_good replclear($machid)_dbc_close [$dbc close] 0 + error_check_good replclear($machid)_txn_commit [$txn commit] 0 +} + +# Add a machine to a replication environment. proc repladd { machid } { global queueenv queuedbs machids @@ -70,19 +455,41 @@ proc repladd { machid } { error "FAIL: repladd: machid $machid already exists" } - set queuedbs($machid) \ - [berkdb open -env $queueenv -create -recno repqueue$machid.db] + set queuedbs($machid) [berkdb open -auto_commit \ + -env $queueenv -create -recno -renumber repqueue$machid.db] error_check_good repqueue_create [is_valid_db $queuedbs($machid)] TRUE lappend machids $machid } -proc replprocessqueue { dbenv machid } { - global queuedbs +# Process a queue of messages, skipping every "skip_interval" entry. +# We traverse the entire queue, but since we skip some messages, we +# may end up leaving things in the queue, which should get picked up +# on a later run. + +proc replprocessqueue { dbenv machid { skip_interval 0 } \ + { hold_electp NONE } { newmasterp NONE } } { + global queuedbs queueenv errorCode + + # hold_electp is a call-by-reference variable which lets our caller + # know we need to hold an election. + if { [string compare $hold_electp NONE] != 0 } { + upvar $hold_electp hold_elect + } + set hold_elect 0 + + # newmasterp is the same idea, only returning the ID of a master + # given in a DB_REP_NEWMASTER return. + if { [string compare $newmasterp NONE] != 0 } { + upvar $newmasterp newmaster + } + set newmaster 0 set nproced 0 - set dbc [$queuedbs($machid) cursor -update] + set txn [$queueenv txn] + set dbc [$queuedbs($machid) cursor -txn $txn] + error_check_good process_dbc($machid) \ [is_valid_cursor $dbc $queuedbs($machid)] TRUE @@ -91,18 +498,162 @@ proc replprocessqueue { dbenv machid } { { set dbt [$dbc get -next] } { set data [lindex [lindex $dbt 0] 1] - # XXX - # It would be nice to make sure that NEWMASTER messages - # indicate the right master. We don't have the necessary - # info in here, though. - $dbenv rep_process_message \ - [lindex $data 2] [lindex $data 0] [lindex $data 1] + # If skip_interval is nonzero, we want to process messages + # out of order. We do this in a simple but slimy way-- + # continue walking with the cursor without processing the + # message or deleting it from the queue, but do increment + # "nproced". The way this proc is normally used, the + # precise value of nproced doesn't matter--we just don't + # assume the queues are empty if it's nonzero. Thus, + # if we contrive to make sure it's nonzero, we'll always + # come back to records we've skipped on a later call + # to replprocessqueue. (If there really are no records, + # we'll never get here.) + # + # Skip every skip_interval'th record (and use a remainder other + # than zero so that we're guaranteed to really process at least + # one record on every call). + if { $skip_interval != 0 } { + if { $nproced % $skip_interval == 1 } { + incr nproced + continue + } + } + + # We have to play an ugly cursor game here: we currently + # hold a lock on the page of messages, but rep_process_message + # might need to lock the page with a different cursor in + # order to send a response. So save our recno, close + # the cursor, and then reopen and reset the cursor. + set recno [lindex [lindex $dbt 0] 0] + error_check_good dbc_process_close [$dbc close] 0 + error_check_good txn_commit [$txn commit] 0 + set ret [catch {$dbenv rep_process_message \ + [lindex $data 2] [lindex $data 0] [lindex $data 1]} res] + set txn [$queueenv txn] + set dbc [$queuedbs($machid) cursor -txn $txn] + set dbt [$dbc get -set $recno] + + if { $ret != 0 } { + if { [is_substr $res DB_REP_HOLDELECTION] } { + set hold_elect 1 + } else { + error "FAIL:[timestamp]\ + rep_process_message returned $res" + } + } incr nproced $dbc del + + if { $ret == 0 && $res != 0 } { + if { [is_substr $res DB_REP_NEWSITE] } { + # NEWSITE; do nothing. + } else { + set newmaster $res + # Break as soon as we get a NEWMASTER message; + # our caller needs to handle it. + break + } + } + + if { $hold_elect == 1 } { + # Break also on a HOLDELECTION, for the same reason. + break + } + } + error_check_good dbc_close [$dbc close] 0 + error_check_good txn_commit [$txn commit] 0 + # Return the number of messages processed. return $nproced } + +set run_repl_flag "-run_repl" + +proc extract_repl_args { args } { + global run_repl_flag + + for { set arg [lindex $args [set i 0]] } \ + { [string length $arg] > 0 } \ + { set arg [lindex $args [incr i]] } { + if { [string compare $arg $run_repl_flag] == 0 } { + return [lindex $args [expr $i + 1]] + } + } + return "" +} + +proc delete_repl_args { args } { + global run_repl_flag + + set ret {} + + for { set arg [lindex $args [set i 0]] } \ + { [string length $arg] > 0 } \ + { set arg [lindex $args [incr i]] } { + if { [string compare $arg $run_repl_flag] != 0 } { + lappend ret $arg + } else { + incr i + } + } + return $ret +} + +global elect_serial +global elections_in_progress +set elect_serial 0 + +# Start an election in a sub-process. +proc start_election { qdir envstring nsites pri timeout {err "none"}} { + source ./include.tcl + global elect_serial elect_timeout elections_in_progress machids + + incr elect_serial + + set t [open "|$tclsh_path >& $testdir/ELECTION_OUTPUT.$elect_serial" w] + + puts $t "source $test_path/test.tcl" + puts $t "replsetup $qdir" + foreach i $machids { puts $t "repladd $i" } + puts $t "set env_cmd \{$envstring\}" + puts $t "set dbenv \[eval \$env_cmd -errfile \ + $testdir/ELECTION_ERRFILE.$elect_serial -errpfx FAIL: \]" +# puts "Start election err $err, env $envstring" + puts $t "\$dbenv test abort $err" + puts $t "set res \[catch \{\$dbenv rep_elect $nsites $pri \ + $elect_timeout\} ret\]" + if { $err != "none" } { + puts $t "\$dbenv test abort none" + puts $t "set res \[catch \{\$dbenv rep_elect $nsites $pri \ + $elect_timeout\} ret\]" + } + flush $t + + set elections_in_progress($elect_serial) $t + return $elect_serial +} + +proc close_election { i } { + global elections_in_progress + set t $elections_in_progress($i) + puts $t "\$dbenv close" + close $t + unset elections_in_progress($i) +} + +proc cleanup_elections { } { + global elect_serial elections_in_progress + + for { set i 0 } { $i <= $elect_serial } { incr i } { + if { [info exists elections_in_progress($i)] != 0 } { + close_election $i + } + } + + set elect_serial 0 +} diff --git a/db/test/rpc003.tcl b/db/test/rpc003.tcl index e5ad7d40b..9b462fa63 100644 --- a/db/test/rpc003.tcl +++ b/db/test/rpc003.tcl @@ -1,14 +1,15 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 1996-2003 +# Copyright (c) 2001-2002 # Sleepycat Software. All rights reserved. # -# Id: rpc003.tcl,v 11.5 2001/08/29 19:07:42 sue Exp +# Id: rpc003.tcl,v 11.9 2002/07/16 20:53:03 bostic Exp # # Test RPC and secondary indices. proc rpc003 { } { source ./include.tcl global dict nsecondaries + global rpc_svc # # First set up the files. Secondary indices only work readonly @@ -39,7 +40,7 @@ proc rpc003 { } { # Open an environment # XXX if one is not supplied! - set env [berkdb env -create -home $testdir] + set env [berkdb_env -create -home $testdir] error_check_good env_open [is_valid_env $env] TRUE # Open the primary. @@ -84,12 +85,12 @@ proc rpc003 { } { # We have set up our databases, so now start the server and # read them over RPC. # - set dpid [exec $util_path/berkeley_db_svc -h $rpc_testdir &] + set dpid [exec $util_path/$rpc_svc -h $rpc_testdir &] puts "\tRpc003.c: Started server, pid $dpid" tclsleep 2 set home [file tail $rpc_testdir] - set env [eval {berkdb env -create -mode 0644 -home $home \ + set env [eval {berkdb_env_noerr -create -mode 0644 -home $home \ -server $rpc_server}] error_check_good lock_env:open [is_valid_env $env] TRUE @@ -141,11 +142,9 @@ proc rpc003 { } { error_check_good primary_close [$pdb close] 0 error_check_good env_close [$env close] 0 - exec $KILL $dpid - return + tclkill $dpid } - proc rpc003_assoc_err { popen sopen msg } { set pdb [eval $popen] error_check_good assoc_err_popen [is_valid_db $pdb] TRUE diff --git a/db/test/rsrc004.tcl b/db/test/rsrc004.tcl index 32c0cb738..1ee3d836d 100644 --- a/db/test/rsrc004.tcl +++ b/db/test/rsrc004.tcl @@ -1,9 +1,9 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 2001 +# Copyright (c) 2001-2002 # Sleepycat Software. All rights reserved. # -# Id: rsrc004.tcl,v 11.2 2001/08/03 16:39:29 bostic Exp +# Id: rsrc004.tcl,v 11.3 2002/01/11 15:53:33 bostic Exp # # TEST rsrc004 # TEST Recno backing file test for EOF-terminated records. diff --git a/db/test/scr001/chk.code b/db/test/scr001/chk.code index 00197e954..f520491cd 100644 --- a/db/test/scr001/chk.code +++ b/db/test/scr001/chk.code @@ -1,6 +1,6 @@ #!/bin/sh - # -# Id: chk.code,v 1.9 2001/10/17 16:15:22 bostic Exp +# Id: chk.code,v 1.10 2002/02/04 16:03:26 bostic Exp # # Check to make sure that the code samples in the documents build. @@ -26,7 +26,7 @@ for i in `find $d/docs_src -name '*.cs'`; do -e 's/__LB__/[/g' \ -e 's/__LT__/</g' \ -e 's/__RB__/]/g' < $i > t.c - if cc -Wall -I.. t.c ../libdb.a -o t; then + if cc -Wall -Werror -I.. t.c ../libdb.a -o t; then : else echo "FAIL: unable to compile $i" diff --git a/db/test/scr002/chk.def b/db/test/scr002/chk.def index 508a69bb3..2a8a88c44 100644 --- a/db/test/scr002/chk.def +++ b/db/test/scr002/chk.def @@ -1,6 +1,6 @@ #!/bin/sh - # -# Id: chk.def,v 1.7 2001/10/12 17:55:31 bostic Exp +# Id: chk.def,v 1.9 2002/03/27 04:32:57 bostic Exp # # Check to make sure we haven't forgotten to add any interfaces # to the Win32 libdb.def file. @@ -26,7 +26,7 @@ sed '/; /d' $f | -e '/^__/d' -e '/^;/d' | sort > $t1 -egrep __P $d/include_auto/global_ext.in | +egrep __P $d/dbinc_auto/ext_prot.in | sed '/^[a-z]/!d' | awk '{print $2}' | sed 's/^\*//' | diff --git a/db/test/scr003/chk.define b/db/test/scr003/chk.define index ea47734c8..b4c4e4b10 100644 --- a/db/test/scr003/chk.define +++ b/db/test/scr003/chk.define @@ -1,6 +1,6 @@ #!/bin/sh - # -# Id: chk.define,v 1.15 2001/10/12 17:55:32 bostic Exp +# Id: chk.define,v 1.21 2002/03/27 04:32:58 bostic Exp # # Check to make sure that all #defines are actually used. @@ -14,61 +14,62 @@ d=../.. exitv=0 t1=__1 t2=__2 +t3=__3 -egrep '^#define' $d/include/*.h $d/include/*.in | +egrep '^#define' $d/dbinc/*.h $d/dbinc/*.in | sed -e '/db_185.in/d' -e '/xa.h/d' | awk '{print $2}' | - sed -e '/^ALIGNP/d' \ - -e '/^B_DELETE/d' \ + sed -e '/^B_DELETE/d' \ -e '/^B_MAX/d' \ - -e '/^CIRCLEQ/d' \ - -e '/^DB_AM_TXN/d' \ + -e '/^CIRCLEQ_/d' \ -e '/^DB_BTREEOLDVER/d' \ -e '/^DB_HASHOLDVER/d' \ -e '/^DB_LOCKVERSION/d' \ -e '/^DB_MAX_PAGES/d' \ -e '/^DB_QAMOLDVER/d' \ - -e '/^DB_RO_ACCESS/d' \ -e '/^DB_TXNVERSION/d' \ + -e '/^DB_UNUSED/d' \ -e '/^DEFINE_DB_CLASS/d' \ - -e '/^LIST/d' \ + -e '/^HASH_UNUSED/d' \ + -e '/^LIST_/d' \ -e '/^LOG_OP/d' \ -e '/^MINFILL/d' \ -e '/^MUTEX_FIELDS/d' \ -e '/^NCACHED2X/d' \ -e '/^NCACHED30/d' \ -e '/^PAIR_MASK/d' \ - -e '/^POWER_OF_TWO/d' \ -e '/^P_16_COPY/d' \ -e '/^P_32_COPY/d' \ -e '/^P_32_SWAP/d' \ - -e '/^SH_CIRCLEQ/d' \ - -e '/^SH_LIST/d' \ - -e '/^SH_TAILQ/d' \ - -e '/^TAILQ/d' \ + -e '/^P_TO_UINT16/d' \ + -e '/^QPAGE_CHKSUM/d' \ + -e '/^QPAGE_NORMAL/d' \ + -e '/^QPAGE_SEC/d' \ + -e '/^SH_CIRCLEQ_/d' \ + -e '/^SH_LIST_/d' \ + -e '/^SH_TAILQ_/d' \ + -e '/^SIZEOF_PAGE/d' \ + -e '/^TAILQ_/d' \ -e '/^WRAPPED_CLASS/d' \ - -e '/^XA_$/d' \ -e '/^__BIT_TYPES_DEFINED__/d' \ -e '/^__DBC_INTERNAL/d' \ - -e '/_AUTO_H$/d' \ - -e '/_H_$/d' \ - -e '/_UNUSED/d' \ - -e '/^i_/d' \ - -e '/ext_h_/d' \ + -e '/^i_/d' \ + -e '/_H_/d' \ -e 's/(.*//' | sort > $t1 +find $d -name '*.c' -o -name '*.cpp' > $t2 for i in `cat $t1`; do - if egrep -w $i $d/*/*.c $d/*/*.cpp > /dev/null; then + if egrep -w $i `cat $t2` > /dev/null; then :; else - f=`egrep -l "#define.*$i" $d/include/*.h $d/include/*.in | - sed 's;\.\.\/\.\.\/include/;;' | tr -s "[:space:]" " "` + f=`egrep -l "#define.*$i" $d/dbinc/*.h $d/dbinc/*.in | + sed 's;\.\.\/\.\.\/dbinc/;;' | tr -s "[:space:]" " "` echo "FAIL: $i: $f" fi -done | sort +1 > $t2 +done | sort -k 2 > $t3 -test -s $t2 && { - cat $t2 +test -s $t3 && { + cat $t3 echo "FAIL: found unused #defines" exit 1 } diff --git a/db/test/scr004/chk.javafiles b/db/test/scr004/chk.javafiles index 248b5570b..c85a35604 100644 --- a/db/test/scr004/chk.javafiles +++ b/db/test/scr004/chk.javafiles @@ -1,6 +1,6 @@ #!/bin/sh - # -# Id: chk.javafiles,v 1.4 2001/10/12 17:55:33 bostic Exp +# Id: chk.javafiles,v 1.5 2002/01/30 19:50:52 bostic Exp # # Check to make sure we haven't forgotten to add any Java files to the list # of source files in the Makefile. @@ -13,14 +13,14 @@ d=../.. } f=$d/dist/Makefile.in -d=$d/java/src/com/sleepycat +j=$d/java/src/com/sleepycat t1=__1 t2=__2 -find ${d}/db/ $d/examples -name \*.java -print | +find $j/db/ $j/examples $d/rpc_server/java -name \*.java -print | sed -e 's/^.*\///' | sort > $t1 -tr ' \t' '\n' < ${f} | sed -e '/\.java$/!d' -e 's/^.*\///' | sort > $t2 +tr ' \t' '\n' < $f | sed -e '/\.java$/!d' -e 's/^.*\///' | sort > $t2 cmp $t1 $t2 > /dev/null || { echo "<<< java source files >>> Makefile" diff --git a/db/test/scr005/chk.nl b/db/test/scr005/chk.nl index 876be2f94..4ad1b3c7c 100644 --- a/db/test/scr005/chk.nl +++ b/db/test/scr005/chk.nl @@ -1,6 +1,6 @@ #!/bin/sh - # -# Id: chk.nl,v 1.5 2001/10/12 17:55:33 bostic Exp +# Id: chk.nl,v 1.6 2002/01/07 15:12:12 bostic Exp # # Check to make sure that there are no trailing newlines in __db_err calls. @@ -68,12 +68,23 @@ chk(fp, name) if (ch == '\n') ++line; } - while ((ch = getc(fp)) != '"') { - if (ch == EOF) + while ((ch = getc(fp)) != '"') + switch (ch) { + case EOF: return (exitv); - if (ch == '\n') + case '\\n': ++line; - if (ch == '\\\\') + break; + case '.': + if ((ch = getc(fp)) != '"') + ungetc(ch, fp); + else { + fprintf(stderr, + "%s: <period> at line %d\n", name, line); + exitv = 1; + } + break; + case '\\\\': if ((ch = getc(fp)) != 'n') ungetc(ch, fp); else if ((ch = getc(fp)) != '"') @@ -83,7 +94,8 @@ chk(fp, name) "%s: <newline> at line %d\n", name, line); exitv = 1; } - } + break; + } } return (exitv); } @@ -93,7 +105,7 @@ cc t.c -o t if ./t $d/*/*.[ch] $d/*/*.cpp $d/*/*.in ; then : else - echo "FAIL: found __db_err calls with newline strings." + echo "FAIL: found __db_err calls ending with periods/newlines." exit 1 fi diff --git a/db/test/scr007/chk.proto b/db/test/scr007/chk.proto index 74ce6875b..043f7176e 100644 --- a/db/test/scr007/chk.proto +++ b/db/test/scr007/chk.proto @@ -1,6 +1,6 @@ #!/bin/sh - # -# Id: chk.proto,v 1.6 2001/10/12 17:55:34 bostic Exp +# Id: chk.proto,v 1.8 2002/03/27 04:32:59 bostic Exp # # Check to make sure that prototypes are actually needed. @@ -13,8 +13,9 @@ d=../.. t1=__1 t2=__2 +t3=__3 -egrep '__P' $d/include_auto/*.h | +egrep '__P' $d/dbinc_auto/*.h | sed -e 's/[ ][ ]*__P.*//' \ -e 's/^.*[ *]//' \ -e '/__db_cprint/d' \ @@ -29,14 +30,14 @@ egrep '__P' $d/include_auto/*.h | -e '/_print$/d' \ -e '/_read$/d' > $t1 +find $d -name '*.in' -o -name '*.[ch]' -o -name '*.cpp' > $t2 for i in `cat $t1`; do - c=`egrep -low $i $d/include/*.in \ - $d/include/*.h $d/*/*.c $d/*/*.cpp | wc -l` + c=$(egrep -low $i $(cat $t2) | wc -l) echo "$i: $c" -done | egrep ' 1$' > $t2 +done | egrep ' 1$' > $t3 -test -s $t2 && { - cat $t2 +test -s $t3 && { + cat $t3 echo "FAIL: found unnecessary prototypes." exit 1 } diff --git a/db/test/scr008/chk.pubdef b/db/test/scr008/chk.pubdef index 95a30ca12..4f59e831b 100644 --- a/db/test/scr008/chk.pubdef +++ b/db/test/scr008/chk.pubdef @@ -45,9 +45,9 @@ while read name isdoc isinc isjava; do done # Check that pubdef.in has everything listed in db.in. -f=$d/include/db.in +f=$d/dbinc/db.in sed -n \ - -e 's/^#define[ ]*\(DB_[A-Z_]*\).*/\1/p' \ + -e 's/^#define[ ]*\(DB_[A-Z_0-9]*\).*/\1/p' \ -e 's/^[ ]*\(DB_[A-Z_]*\)=[0-9].*/\1/p' \ -e d < $f | while read name; do @@ -60,10 +60,10 @@ while read name; do done # Check that db.in has everything listed in pubdef.in. -f=$d/include/db.in +f=$d/dbinc/db.in sed '/^#/d' $p | while read name isdoc isinc isjava; do - if `egrep -w "#define[ ]$name|[ ][ ]*$name=[0-9]" \ + if `egrep -w "#define[ ]$name|[ ][ ]*$name=[0-9][0-9]*" \ $f > /dev/null`; then [ "X$isinc" != "XI" ] && { echo "$name should not appear in $f" diff --git a/db/test/scr009/chk.srcfiles b/db/test/scr009/chk.srcfiles index c9e6bff40..c2cb3990f 100644 --- a/db/test/scr009/chk.srcfiles +++ b/db/test/scr009/chk.srcfiles @@ -1,6 +1,6 @@ #!/bin/sh - # -# Id: chk.srcfiles,v 1.9 2001/10/12 17:55:35 bostic Exp +# Id: chk.srcfiles,v 1.10 2002/02/04 22:25:33 bostic Exp # # Check to make sure we haven't forgotten to add any files to the list # of source files Win32 uses to build its dsp files. @@ -21,8 +21,11 @@ sed -e '/^[ #]/d' \ awk '{print $1}' > $t1 find $d -type f | sed -e 's/^\.\.\/\.\.\///' \ - -e '/^test/d' \ - -e '/^build[^_]/d' | + -e '/^build[^_]/d' \ + -e '/^test\//d' \ + -e '/^test_server/d' \ + -e '/^test_thread/d' \ + -e '/^test_vxworks/d' | egrep '\.c$|\.cpp$|\.def$|\.rc$' | sed -e '/perl.DB_File\/version.c/d' | sort > $t2 diff --git a/db/test/scr010/spell.ok b/db/test/scr010/spell.ok index b3fd9cfbf..2211d46b8 100644 --- a/db/test/scr010/spell.ok +++ b/db/test/scr010/spell.ok @@ -1,10 +1,14 @@ +AES AJVX ALLDB API APP AccessExample Acflmo +Aclmop Ahlm +Ahm +BCFILprRsvVxX BCc BDBXXXXXX BH @@ -12,16 +16,23 @@ BI BII BINTERNAL BTREE +Bc BerkeleyDB BtRecExample Btree +CD CDB CDS CDdFILTVvX CFILpRsv +CFLprsvVxX CFh +CHKSUM +CLpsvxX CONFIG CdFILTvX +ClassNotFoundException +Config DBC DBENV DBS @@ -36,6 +47,7 @@ DUPMASTER DUPSORT Db DbAppendRecno +DbAttachImpl DbBtreeCompare DbBtreePrefix DbBtreeStat @@ -63,12 +75,16 @@ DbMpoolStat DbPreplist DbQueueStat DbRecoveryInit +DbRepStat DbRepTransport DbRunRecoveryException DbSecondaryKeyCreate DbTxn DbTxnRecover DbTxnStat +DbUtil +DbXAResource +DbXid Dbc Dbt Dde @@ -83,10 +99,16 @@ Exp FIXEDLEN Fd Ff +Fh FileNotFoundException +GetFileInformationByHandle +GetJavaVM GetJoin HOFFSET HOLDELECTION +Hashtable +ILo +ILprR INDX INIT IREAD @@ -137,6 +159,11 @@ NOSERVER NOSYNC NOTFOUND NOTGRANTED +NOTYPE +NOWAIT +NP +NoP +NoqV NqV NrV NsV @@ -145,6 +172,7 @@ ORDERCHKONLY Offpage OpenFileMapping OutputStream +PGNO PID PREV RECNO @@ -161,9 +189,11 @@ RepProcessMessage SERVERPROG SERVERVERS SETFD +SHA SS Shm Sleepycat +Subdatabase TDS TESTDIR TID @@ -179,11 +209,13 @@ TempFolder TestKeyRange TestLogc TpcbExample +Tt Txn Txns UID UNAVAIL USERMEM +Unencrypted UnmapViewOfFile VM VX @@ -195,9 +227,13 @@ Vx VxWorks Waitsfor XA +XAException +Xid XxZ YIELDCPU YY +abc +abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq abcdef abs addpage @@ -212,6 +248,7 @@ alsVv amx anum appl +appname archivedir arg args @@ -244,6 +281,7 @@ cdb cdel ceVv ceh +celmNrtVZ celmNtV celmNtVZ cget @@ -254,6 +292,7 @@ chkpoint chkpt chksum ckp +cksum clearerr clientrun cmdargs @@ -282,6 +321,7 @@ dbminit dbobj dbopen dbp +dbreg dbremove dbrename dbs @@ -293,6 +333,7 @@ def del delext delim +dev df dh dir @@ -310,6 +351,12 @@ dupset dupsort efh eid +electinit +electsend +electvote +electwait +encryptaes +encryptany endian env envid @@ -330,6 +377,7 @@ ff ffactor fget fh +fid fileid fileopen firstkey @@ -344,10 +392,14 @@ fset fstat fsync ftype +func fv gbytes gc'ed gen +getBranchQualifier +getFormatId +getGlobalTransactionId gettime gettimeofday gettype @@ -374,6 +426,7 @@ inlen inp insdel int +intValue io iread isdeleted @@ -381,6 +434,7 @@ itemorder iter iwr iwrite +javax kb kbyte kbytes @@ -393,10 +447,12 @@ keyrange killinterval killiteration killtest +klNpP klNprRV klNprRs krinsky lM +lP lang lastid ld @@ -413,6 +469,7 @@ logc logclean logfile logflush +logsonly lorder lpgno lsVv @@ -428,6 +485,7 @@ luM luMB luMb lx +mNP mNs machid makedup @@ -483,6 +541,7 @@ mvptr mydrive mydrivexxx nO +nP nTV nTt naborts @@ -500,10 +559,14 @@ needswap nelem nevict newalloc +newclient +newfile newitem +newmaster newname newpage newpgno +newsite nextdup nextkey nextlsn @@ -531,6 +594,7 @@ nopanic nosort nosync notfound +notgranted nowait nowaits npages @@ -547,10 +611,13 @@ num numdup obj offpage +ok olddata olditem +oldname opd opflags +opmods orig os osynch @@ -569,6 +636,7 @@ panic'ing paniccall panicstate parentid +passwd perf perfdb pflag @@ -583,12 +651,15 @@ pgnum pgout pgsize pid +pkey +plist pn postdestroy postlog postlogmeta postopen postsync +prR prec predestroy preopen @@ -604,9 +675,13 @@ pthread pthreads ptype pv +qV qam qs qtest +rRV +rRs +rV rand rcuradj rdonly @@ -618,6 +693,7 @@ reclength recno recnum recnums +recs refcount regionmax regop @@ -629,16 +705,22 @@ rf rkey rlsn rm +rmid rmw ro rootent rootlsn rpc +rpcid +rs rsplit runlog rw rwrw rwrwrw +sS +sV +sVv scount secon secs @@ -661,6 +743,7 @@ splitmeta srand stat str +strcmp strdup strerror strlen @@ -673,8 +756,10 @@ tVZ tas tcl tcp +thr threadID tid +tiebreaker timestamp tlen tm @@ -708,6 +793,8 @@ upi usec usecs usr +util +vVxXZ vZ val var @@ -727,6 +814,7 @@ wc wcount wordlist writeable +wrnosync wt xa xid diff --git a/db/test/scr012/chk.vx_code b/db/test/scr012/chk.vx_code index 19250480d..64413b884 100644 --- a/db/test/scr012/chk.vx_code +++ b/db/test/scr012/chk.vx_code @@ -1,6 +1,6 @@ #!/bin/sh - # -# Id: chk.vx_code,v 1.3 2001/10/12 17:55:37 bostic Exp +# Id: chk.vx_code,v 1.6 2002/03/27 20:20:25 bostic Exp # # Check to make sure the auto-generated utility code in the VxWorks build # directory compiles. @@ -30,13 +30,16 @@ header() echo "{" echo "int i;") > t1.c -for i in db_archive db_checkpoint db_deadlock \ - db_dump db_load db_printlog db_recover db_stat db_upgrade db_verify; do +for i in db_archive db_checkpoint db_deadlock db_dump db_load \ + db_printlog db_recover db_stat db_upgrade db_verify dbdemo; do echo " compiling build_vxworks/$i" (cat $d/build_vxworks/$i/$i.c; header $i) > t.c - if cc -Wall -I.. -I$d/include -I$d/include_auto \ - t.c $d/clib/getopt.c $d/common/util_arg.c \ - $d/common/util_log.c $d/common/util_sig.c ../libdb.a -o t; then + if cc -Wall -I.. -I$d t.c \ + $d/clib/getopt.c \ + $d/common/util_arg.c \ + $d/common/util_cache.c \ + $d/common/util_log.c \ + $d/common/util_sig.c ../libdb.a -o t; then : else echo "FAIL: unable to compile $i" @@ -50,9 +53,12 @@ done (cat t2.c t1.c; echo "return (0); }") > t.c echo " compiling build_vxworks utility composite" -if cc -Dlint -Wall -I.. -I$d/include -I$d/include_auto \ - t.c $d/clib/getopt.c $d/common/util_arg.c \ - $d/common/util_log.c $d/common/util_sig.c ../libdb.a -o t; then +if cc -Dlint -Wall -I.. -I$d t.c \ + $d/clib/getopt.c \ + $d/common/util_arg.c \ + $d/common/util_cache.c \ + $d/common/util_log.c \ + $d/common/util_sig.c ../libdb.a -o t; then : else echo "FAIL: unable to compile utility composite" diff --git a/db/test/scr013/chk.stats b/db/test/scr013/chk.stats index 9b9299710..db87ec3c5 100644 --- a/db/test/scr013/chk.stats +++ b/db/test/scr013/chk.stats @@ -1,6 +1,6 @@ #!/bin/sh - # -# Id: chk.stats,v 1.4 2001/10/12 17:55:37 bostic Exp +# Id: chk.stats,v 1.5 2002/03/27 04:33:04 bostic Exp # # Check to make sure all of the stat structure members are included in # all of the possible formats. @@ -21,7 +21,7 @@ t=__tmp inc_fields() { sed -e "/struct $1 {/,/^};$/p" \ - -e d < $d/include/db.in | + -e d < $d/dbinc/db.in | sed -e 1d \ -e '$d' \ -e '/;/!d' \ @@ -80,7 +80,7 @@ man() echo " $1: ignoring $i" continue fi - if egrep -w $i $d/include/db.in > /dev/null; then + if egrep -w $i $d/dbinc/db.in > /dev/null; then :; else echo " $1: $i not found in db.h." diff --git a/db/test/scr014/chk.err b/db/test/scr014/chk.err index e43e9206c..88f5a5459 100644 --- a/db/test/scr014/chk.err +++ b/db/test/scr014/chk.err @@ -1,6 +1,6 @@ #!/bin/sh - # -# Id: chk.err,v 1.2 2001/10/12 17:55:38 bostic Exp +# Id: chk.err,v 1.3 2002/03/27 04:33:05 bostic Exp # # Check to make sure all of the error values have corresponding error # message strings in db_strerror(). @@ -17,7 +17,7 @@ d=../.. t1=__tmp1 t2=__tmp2 -egrep -- "define.*DB_.*-309" $d/include/db.in | awk '{print $2}' > $t1 +egrep -- "define.*DB_.*-309" $d/dbinc/db.in | awk '{print $2}' > $t1 sed -e '/^db_strerror/,/^}/{' \ -e '/ case DB_/{' \ -e 's/:.*//' \ diff --git a/db/test/scr015/TestConstruct01.cpp b/db/test/scr015/TestConstruct01.cpp index 56c595f8d..602ce67c2 100644 --- a/db/test/scr015/TestConstruct01.cpp +++ b/db/test/scr015/TestConstruct01.cpp @@ -1,10 +1,10 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2000 + * Copyright (c) 2000-2002 * Sleepycat Software. All rights reserved. * - * Id: TestConstruct01.cpp,v 1.3 2001/10/05 01:50:17 bostic Exp + * Id: TestConstruct01.cpp,v 1.5 2002/01/23 14:26:40 bostic Exp */ /* @@ -109,8 +109,7 @@ void rundb(Db *db, int count, int has_env) // opening the db. // CHK(db->set_pagesize(1024)); - CHK(db->open(name, NULL, DB_BTREE, - count ? 0 : DB_CREATE, 0664)); + CHK(db->open(NULL, name, NULL, DB_BTREE, count ? 0 : DB_CREATE, 0664)); // The bit map of keys we've seen long bitmap = 0; diff --git a/db/test/scr015/TestExceptInclude.cpp b/db/test/scr015/TestExceptInclude.cpp index 8f0c142e3..a6fcb9018 100644 --- a/db/test/scr015/TestExceptInclude.cpp +++ b/db/test/scr015/TestExceptInclude.cpp @@ -1,19 +1,21 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997-2001 + * Copyright (c) 1997-2002 * Sleepycat Software. All rights reserved. * - * Id: TestExceptInclude.cpp,v 1.1 2001/05/31 23:09:12 dda Exp + * Id: TestExceptInclude.cpp,v 1.4 2002/07/05 22:17:59 dda Exp */ /* We should be able to include cxx_except.h without db_cxx.h, - * and use the DbException class. + * and use the DbException class. We do need db.h to get a few + * typedefs defined that the DbException classes use. * * This program does nothing, it's just here to make sure * the compilation works. */ -#include "cxx_except.h" +#include <db.h> +#include <cxx_except.h> int main(int argc, char *argv[]) { diff --git a/db/test/scr015/TestGetSetMethods.cpp b/db/test/scr015/TestGetSetMethods.cpp index f6d66dcee..cb5cb1ed1 100644 --- a/db/test/scr015/TestGetSetMethods.cpp +++ b/db/test/scr015/TestGetSetMethods.cpp @@ -1,10 +1,10 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2000 + * Copyright (c) 2000-2002 * Sleepycat Software. All rights reserved. * - * Id: TestGetSetMethods.cpp,v 1.3 2001/10/05 01:50:17 bostic Exp + * Id: TestGetSetMethods.cpp,v 1.4 2002/01/11 15:53:59 bostic Exp */ /* diff --git a/db/test/scr015/TestKeyRange.cpp b/db/test/scr015/TestKeyRange.cpp index 62592aee3..3a296c703 100644 --- a/db/test/scr015/TestKeyRange.cpp +++ b/db/test/scr015/TestKeyRange.cpp @@ -6,10 +6,10 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 1998, 1999, 2000 + * Copyright (c) 1997-2002 * Sleepycat Software. All rights reserved. * - * Id: TestKeyRange.cpp,v 1.2 2001/10/09 20:58:35 dda Exp + * Id: TestKeyRange.cpp,v 1.4 2002/01/23 14:26:41 bostic Exp */ #ifndef NO_SYSTEM_INCLUDES @@ -90,7 +90,7 @@ void TestKeyRange::run() db.set_errpfx("TestKeyRange"); db.set_pagesize(1024); /* Page size: 1K. */ db.set_cachesize(0, 32 * 1024, 0); - db.open(FileName, NULL, DB_BTREE, DB_CREATE, 0664); + db.open(NULL, FileName, NULL, DB_BTREE, DB_CREATE, 0664); // // Insert records into the database, where the key is the user diff --git a/db/test/scr015/TestLogc.cpp b/db/test/scr015/TestLogc.cpp index 3a2521ef1..3ea36e884 100644 --- a/db/test/scr015/TestLogc.cpp +++ b/db/test/scr015/TestLogc.cpp @@ -1,10 +1,10 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2000 + * Copyright (c) 2000-2002 * Sleepycat Software. All rights reserved. * - * Id: TestLogc.cpp,v 1.4 2001/10/16 15:40:53 dda Exp + * Id: TestLogc.cpp,v 1.6 2002/01/23 14:26:41 bostic Exp */ /* @@ -36,7 +36,7 @@ int main(int argc, char *argv[]) // Do some database activity to get something into the log. Db *db1 = new Db(env, 0); - db1->open("first.db", NULL, DB_BTREE, DB_CREATE, 0); + db1->open(NULL, "first.db", NULL, DB_BTREE, DB_CREATE, 0); Dbt *key = new Dbt((char *)"a", 1); Dbt *data = new Dbt((char *)"b", 1); db1->put(NULL, key, data, 0); @@ -46,7 +46,7 @@ int main(int argc, char *argv[]) db1->close(0); Db *db2 = new Db(env, 0); - db2->open("second.db", NULL, DB_BTREE, DB_CREATE, 0); + db2->open(NULL, "second.db", NULL, DB_BTREE, DB_CREATE, 0); key->set_data((char *)"w"); data->set_data((char *)"x"); db2->put(NULL, key, data, 0); diff --git a/db/test/scr015/TestSimpleAccess.cpp b/db/test/scr015/TestSimpleAccess.cpp index fb8714cff..fbb8d9136 100644 --- a/db/test/scr015/TestSimpleAccess.cpp +++ b/db/test/scr015/TestSimpleAccess.cpp @@ -1,10 +1,10 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2000 + * Copyright (c) 2000-2002 * Sleepycat Software. All rights reserved. * - * Id: TestSimpleAccess.cpp,v 1.3 2001/10/05 01:50:17 bostic Exp + * Id: TestSimpleAccess.cpp,v 1.5 2002/01/23 14:26:41 bostic Exp */ /* @@ -21,7 +21,7 @@ int main(int argc, char *argv[]) { try { Db *db = new Db(NULL, 0); - db->open("my.db", NULL, DB_BTREE, DB_CREATE, 0644); + db->open(NULL, "my.db", NULL, DB_BTREE, DB_CREATE, 0644); // populate our massive database. // all our strings include null for convenience. diff --git a/db/test/scr015/TestTruncate.cpp b/db/test/scr015/TestTruncate.cpp index 49024299f..6faa8f604 100644 --- a/db/test/scr015/TestTruncate.cpp +++ b/db/test/scr015/TestTruncate.cpp @@ -1,10 +1,10 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2000 + * Copyright (c) 2000-2002 * Sleepycat Software. All rights reserved. * - * Id: TestTruncate.cpp,v 1.3 2001/10/05 01:50:17 bostic Exp + * Id: TestTruncate.cpp,v 1.5 2002/01/23 14:26:41 bostic Exp */ /* @@ -21,7 +21,7 @@ int main(int argc, char *argv[]) { try { Db *db = new Db(NULL, 0); - db->open("my.db", NULL, DB_BTREE, DB_CREATE, 0644); + db->open(NULL, "my.db", NULL, DB_BTREE, DB_CREATE, 0644); // populate our massive database. // all our strings include null for convenience. diff --git a/db/test/scr015/chk.cxxtests b/db/test/scr015/chk.cxxtests index 702ee5710..fbc5f9197 100644 --- a/db/test/scr015/chk.cxxtests +++ b/db/test/scr015/chk.cxxtests @@ -1,6 +1,6 @@ #!/bin/sh - # -# Id: chk.cxxtests,v 1.3 2001/10/23 21:23:04 dda Exp +# Id: chk.cxxtests,v 1.5 2002/07/05 22:17:59 dda Exp # # Check to make sure that regression tests for C++ run. @@ -8,7 +8,7 @@ TEST_CXX_SRCDIR=../test/scr015 # must be a relative directory # All paths must be relative to a subdirectory of the build directory LIBS="-L.. -ldb -ldb_cxx" -CXXFLAGS="-I.. -I../../include" +CXXFLAGS="-I.. -I../../dbinc" # Test must be run from a local build directory, not from a test # directory. @@ -43,6 +43,7 @@ for testname in $testnames; do rm -rf TESTCXX; mkdir TESTCXX cd ./TESTCXX testprefix=../$TEST_CXX_SRCDIR/$testname + ${CXX} ${CXXFLAGS} -o $testname $testprefix.cpp ${LIBS} > ../$testname.compileout 2>&1 || { echo "FAIL: compilation of $testname failed, see ../$testname.compileout" exit 1 diff --git a/db/test/scr016/CallbackTest.java b/db/test/scr016/CallbackTest.java index 587e6840e..eede964a0 100644 --- a/db/test/scr016/CallbackTest.java +++ b/db/test/scr016/CallbackTest.java @@ -8,7 +8,7 @@ public class CallbackTest try { Db db = new Db(null, 0); db.set_bt_compare(new BtreeCompare()); - db.open("test.db", "", Db.DB_BTREE, Db.DB_CREATE, 0666); + db.open(null, "test.db", "", Db.DB_BTREE, Db.DB_CREATE, 0666); StringDbt[] keys = new StringDbt[10]; StringDbt[] datas = new StringDbt[10]; for (int i = 0; i<10; i++) { diff --git a/db/test/scr016/TestClosedDb.java b/db/test/scr016/TestClosedDb.java index 67703f040..efd6938a9 100644 --- a/db/test/scr016/TestClosedDb.java +++ b/db/test/scr016/TestClosedDb.java @@ -1,10 +1,10 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 1998, 1999, 2000 + * Copyright (c) 1997-2002 * Sleepycat Software. All rights reserved. * - * Id: TestClosedDb.java,v 1.2 2001/10/05 02:36:08 bostic Exp + * Id: TestClosedDb.java,v 1.4 2002/01/23 14:29:51 bostic Exp */ /* @@ -22,7 +22,7 @@ public class TestClosedDb { try { Db db = new Db(null, 0); - db.open("my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644); + db.open(null, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644); // populate our massive database. Dbt keydbt = new Dbt("key".getBytes()); diff --git a/db/test/scr016/TestConstruct01.java b/db/test/scr016/TestConstruct01.java index e4d97f1d9..0d207f886 100644 --- a/db/test/scr016/TestConstruct01.java +++ b/db/test/scr016/TestConstruct01.java @@ -1,10 +1,10 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2000 + * Copyright (c) 2000-2002 * Sleepycat Software. All rights reserved. * - * Id: TestConstruct01.java,v 1.4 2001/10/05 02:36:08 bostic Exp + * Id: TestConstruct01.java,v 1.6 2002/01/23 14:29:51 bostic Exp */ /* @@ -96,7 +96,7 @@ public class TestConstruct01 // opening the db. // db.set_pagesize(1024); - db.open(name, null, Db.DB_BTREE, + db.open(null, name, null, Db.DB_BTREE, (count != 0) ? 0 : Db.DB_CREATE, 0664); diff --git a/db/test/scr016/TestConstruct02.java b/db/test/scr016/TestConstruct02.java index d4442ce73..91c47a3ca 100644 --- a/db/test/scr016/TestConstruct02.java +++ b/db/test/scr016/TestConstruct02.java @@ -1,10 +1,10 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2000 + * Copyright (c) 2000-2002 * Sleepycat Software. All rights reserved. * - * Id: TestConstruct02.java,v 1.3 2001/10/05 02:36:09 bostic Exp + * Id: TestConstruct02.java,v 1.5 2002/01/23 14:29:51 bostic Exp */ /* @@ -185,7 +185,7 @@ public class TestConstruct02 Db db = new Db(dbenv, 0); db.set_error_stream(System.err); db.set_pagesize(1024); - db.open(CONSTRUCT02_DBNAME, null, Db.DB_BTREE, + db.open(null, CONSTRUCT02_DBNAME, null, Db.DB_BTREE, Db.DB_CREATE, 0664); rundb(db, itemcount++); @@ -200,7 +200,7 @@ public class TestConstruct02 db = new Db(dbenv, 0); db.set_error_stream(System.err); db.set_pagesize(1024); - db.open(CONSTRUCT02_DBNAME, null, Db.DB_BTREE, + db.open(null, CONSTRUCT02_DBNAME, null, Db.DB_BTREE, Db.DB_CREATE, 0664); rundb(db, itemcount++); rundb(db, itemcount++); diff --git a/db/test/scr016/TestReplication.java b/db/test/scr016/TestReplication.java index 2b3780770..3716b28b5 100644 --- a/db/test/scr016/TestReplication.java +++ b/db/test/scr016/TestReplication.java @@ -1,10 +1,10 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 1998, 1999, 2000 + * Copyright (c) 1997-2002 * Sleepycat Software. All rights reserved. * - * Id: TestReplication.java,v 1.1 2001/10/12 13:02:33 dda Exp + * Id: TestReplication.java,v 1.3 2002/01/23 14:29:51 bostic Exp */ /* @@ -117,7 +117,7 @@ public class TestReplication extends Thread } System.err.println("c70"); Db db = new Db(client_env, 0); - db.open("x.db", null, Db.DB_BTREE, 0, 0); + db.open(null, "x.db", null, Db.DB_BTREE, 0, 0); Dbt data = new Dbt(); System.err.println("c80"); db.get(null, new Dbt("Hello".getBytes()), data, 0); @@ -204,7 +204,7 @@ public class TestReplication extends Thread System.err.println("10"); Db db = new Db(master_env, 0); System.err.println("20"); - db.open("x.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644); + db.open(null, "x.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644); System.err.println("30"); db.put(null, new Dbt("Hello".getBytes()), new Dbt("world".getBytes()), 0); diff --git a/db/test/scr016/TestSameDbt.java b/db/test/scr016/TestSameDbt.java index d4024b12b..e9bb3d40f 100644 --- a/db/test/scr016/TestSameDbt.java +++ b/db/test/scr016/TestSameDbt.java @@ -1,10 +1,10 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 1998, 1999, 2000 + * Copyright (c) 1997-2002 * Sleepycat Software. All rights reserved. * - * Id: TestSameDbt.java,v 1.2 2001/10/05 02:36:10 bostic Exp + * Id: TestSameDbt.java,v 1.4 2002/01/23 14:29:51 bostic Exp */ /* @@ -22,7 +22,7 @@ public class TestSameDbt { try { Db db = new Db(null, 0); - db.open("my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644); + db.open(null, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644); // try reusing the dbt Dbt keydatadbt = new Dbt("stuff".getBytes()); diff --git a/db/test/scr016/TestSimpleAccess.java b/db/test/scr016/TestSimpleAccess.java index 7b2cf61c4..4a3c6898e 100644 --- a/db/test/scr016/TestSimpleAccess.java +++ b/db/test/scr016/TestSimpleAccess.java @@ -1,10 +1,10 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 1998, 1999, 2000 + * Copyright (c) 1997-2002 * Sleepycat Software. All rights reserved. * - * Id: TestSimpleAccess.java,v 1.2 2001/10/05 02:36:10 bostic Exp + * Id: TestSimpleAccess.java,v 1.4 2002/01/23 14:29:52 bostic Exp */ /* @@ -22,7 +22,7 @@ public class TestSimpleAccess { try { Db db = new Db(null, 0); - db.open("my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644); + db.open(null, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644); // populate our massive database. Dbt keydbt = new Dbt("key".getBytes()); diff --git a/db/test/scr016/TestTruncate.java b/db/test/scr016/TestTruncate.java index 3f74e8cd5..387899841 100644 --- a/db/test/scr016/TestTruncate.java +++ b/db/test/scr016/TestTruncate.java @@ -1,10 +1,10 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1997, 1998, 1999, 2000 + * Copyright (c) 1997-2002 * Sleepycat Software. All rights reserved. * - * Id: TestTruncate.java,v 1.2 2001/10/05 02:36:11 bostic Exp + * Id: TestTruncate.java,v 1.4 2002/01/23 14:29:52 bostic Exp */ /* @@ -22,7 +22,7 @@ public class TestTruncate { try { Db db = new Db(null, 0); - db.open("my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644); + db.open(null, "my.db", null, Db.DB_BTREE, Db.DB_CREATE, 0644); // populate our massive database. Dbt keydbt = new Dbt("key".getBytes()); diff --git a/db/test/scr016/chk.javatests b/db/test/scr016/chk.javatests index df845f522..51b55f8fd 100644 --- a/db/test/scr016/chk.javatests +++ b/db/test/scr016/chk.javatests @@ -1,6 +1,6 @@ #!/bin/sh - # -# Id: chk.javatests,v 1.2 2001/10/12 13:02:34 dda Exp +# Id: chk.javatests,v 1.4 2002/03/27 04:33:08 bostic Exp # # Check to make sure that regression tests for Java run. @@ -17,7 +17,7 @@ export LD_LIBRARY_PATH="../.libs" # All paths must be relative to a subdirectory of the build directory LIBS="-L.. -ldb -ldb_cxx" -CXXFLAGS="-I.. -I../../include" +CXXFLAGS="-I.. -I../../dbinc" # Test must be run from a local build directory, not from a test # directory. @@ -30,7 +30,7 @@ cd .. echo 'FAIL: chk.javatests must be run from a local build directory.' exit 1 } -version=`head -1 ../README | sed -e 's/.* \([0-9]*\.[0-9]*\)\..*/\1/'` +version=`sed -e 's/.* \([0-9]*\.[0-9]*\)\..*/\1/' -e q ../README ` [ -f libdb_java-$version.la ] || make libdb_java-$version.la || { echo "FAIL: unable to build libdb_java-$version.la" exit 1 diff --git a/db/test/shelltest.tcl b/db/test/shelltest.tcl index ad3c88086..7d6e9f0ee 100644 --- a/db/test/shelltest.tcl +++ b/db/test/shelltest.tcl @@ -1,9 +1,9 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 2001 +# Copyright (c) 2001-2002 # Sleepycat Software. All rights reserved. # -# Id: shelltest.tcl,v 1.15 2001/11/03 18:43:48 bostic Exp +# Id: shelltest.tcl,v 1.20 2002/04/19 15:42:20 bostic Exp # # TEST scr### # TEST The scr### directories are shell scripts that test a variety of @@ -82,3 +82,7 @@ proc scr015 {} { shelltest 15 } proc scr016 {} { shelltest 16 } proc scr017 {} { shelltest 17 } proc scr018 {} { shelltest 18 } +proc scr019 {} { shelltest 19 } +proc scr020 {} { shelltest 20 } +proc scr021 {} { shelltest 21 } +proc scr022 {} { shelltest 22 } diff --git a/db/test/si005.tcl b/db/test/si005.tcl index e6c241fe9..0cde6f539 100644 --- a/db/test/si005.tcl +++ b/db/test/si005.tcl @@ -1,10 +1,10 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 2001 +# Copyright (c) 2001-2002 # Sleepycat Software. All rights reserved. # -# Id: si005.tcl,v 11.2 2001/07/02 01:08:46 bostic Exp +# Id: si005.tcl,v 11.4 2002/04/29 17:12:03 sandstro Exp # # Sindex005: Secondary index and join test. proc sindex005 { methods {nitems 1000} {tnum 5} args } { @@ -46,7 +46,7 @@ proc sindex005 { methods {nitems 1000} {tnum 5} args } { # Open an environment # XXX if one is not supplied! - set env [berkdb env -create -home $testdir] + set env [berkdb_env -create -home $testdir] error_check_good env_open [is_valid_env $env] TRUE # Open the databases. diff --git a/db/test/test095.tcl b/db/test/test095.tcl index da6334c71..61d20f05e 100644 --- a/db/test/test095.tcl +++ b/db/test/test095.tcl @@ -1,9 +1,9 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 2000-2001 +# Copyright (c) 2000-2002 # Sleepycat Software. All rights reserved. # -# Id: test095.tcl,v 11.13 2001/10/11 18:08:40 sandstro Exp +# Id: test095.tcl,v 11.16 2002/08/08 15:38:12 bostic Exp # # TEST test095 # TEST Bulk get test. [#2934] @@ -12,6 +12,7 @@ proc test095 { method {nsets 1000} {noverflows 25} {tnum 95} args } { set args [convert_args $method $args] set omethod [convert_method $method] + set txnenv 0 set eindex [lsearch -exact $args "-env"] # # If we are using an env, then testfile should just be the db name. @@ -26,6 +27,12 @@ proc test095 { method {nsets 1000} {noverflows 25} {tnum 95} args } { set basename test0$tnum incr eindex set env [lindex $args $eindex] + set txnenv [is_txnenv $env] + if { $txnenv == 1 } { + puts "Skipping for environment with txns" + return + } + set testdir [get_home $env] set carg {} } cleanup $testdir $env @@ -266,6 +273,7 @@ proc t95_verify { res multiple_keys } { # Add nsets dup sets, each consisting of {word$ndups word$n} pairs, # with "word" having (i * pad_bytes) bytes extra padding. proc t95_populate { db did nsets pad_bytes } { + set txn "" for { set i 1 } { $i <= $nsets } { incr i } { # basekey is a padded dictionary word gets $did basekey @@ -278,7 +286,7 @@ proc t95_populate { db did nsets pad_bytes } { for { set j 0 } { $j < $i } { incr j } { set data $basekey.[format %4u $j] error_check_good db_put($key,$data) \ - [$db put $key $data] 0 + [eval {$db put} $txn {$key $data}] 0 } } diff --git a/db/test/test096.tcl b/db/test/test096.tcl index aff00901f..84bd6dd35 100644 --- a/db/test/test096.tcl +++ b/db/test/test096.tcl @@ -1,18 +1,20 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 1999-2001 +# Copyright (c) 1999-2002 # Sleepycat Software. All rights reserved. # -# Id: test096.tcl,v 11.9 2001/08/03 16:39:49 bostic Exp +# Id: test096.tcl,v 11.18 2002/07/22 16:53:00 sue Exp # # TEST test096 # TEST Db->truncate test. -proc test096 { method {pagesize 512} {nentries 1000} {ndups 19} args} { +proc test096 { method {pagesize 512} {nentries 50} {ndups 4} args} { global fixed_len source ./include.tcl set orig_fixed_len $fixed_len - set opts [convert_args $method $args] + set args [convert_args $method $args] + set encargs "" + set args [split_encargs $args encargs] set omethod [convert_method $method] puts "Test096: $method db truncate method test" @@ -33,22 +35,23 @@ proc test096 { method {pagesize 512} {nentries 1000} {ndups 19} args} { if { $eindex != -1 } { incr eindex set env [lindex $args $eindex] - # - # Make sure the env we were given supports txns. - # - set stat [catch {$env txn} txn] - if { $stat != 0 } { + set txnenv [is_txnenv $env] + if { $txnenv == 0 } { puts "Environment w/o txns specified; skipping." return } - error_check_good txnabort [$txn abort] 0 + if { $nentries == 1000 } { + set nentries 100 + } + reduce_dups nentries ndups + set testdir [get_home $env] set closeenv 0 } else { env_cleanup $testdir # # We need an env for exclusive-use testing. - set env [berkdb env -create -home $testdir -txn] + set env [eval {berkdb_env -create -home $testdir -txn} $encargs] error_check_good env_create [is_valid_env $env] TRUE set closeenv 1 } @@ -56,7 +59,7 @@ proc test096 { method {pagesize 512} {nentries 1000} {ndups 19} args} { set t1 $testdir/t1 puts "\tTest096.a: Create $nentries entries" - set db [eval {berkdb_open_noerr -create \ + set db [eval {berkdb_open -create -auto_commit \ -env $env $omethod -mode 0644} $args $testfile] error_check_good db_open [is_valid_db $db] TRUE @@ -68,9 +71,13 @@ proc test096 { method {pagesize 512} {nentries 1000} {ndups 19} args} { while { [gets $did str] != -1 && $count < $nentries } { set key $str set datastr [reverse $str] + set t [$env txn] + error_check_good txn [is_valid_txn $t $env] TRUE + set txn "-txn $t" set ret [eval {$db put} \ $txn $pflags {$key [chop_data $method $datastr]}] error_check_good put $ret 0 + error_check_good txn [$t commit] 0 set ret [eval {$db get} $gflags {$key}] error_check_good $key:dbget [llength $ret] 1 @@ -81,15 +88,15 @@ proc test096 { method {pagesize 512} {nentries 1000} {ndups 19} args} { puts "\tTest096.b: Truncate database" error_check_good dbclose [$db close] 0 - set dbtr [eval {berkdb_open_noerr -create \ + set dbtr [eval {berkdb_open -create -auto_commit \ -env $env $omethod -mode 0644} $args $testfile] error_check_good db_open [is_valid_db $dbtr] TRUE - set ret [$dbtr truncate] + set ret [$dbtr truncate -auto_commit] error_check_good dbtrunc $ret $nentries error_check_good db_close [$dbtr close] 0 - set db [berkdb_open -env $env $testfile] + set db [eval {berkdb_open -env $env} $args $testfile] error_check_good dbopen [is_valid_db $db] TRUE set ret [$db get -glob *] error_check_good dbget [llength $ret] 0 @@ -101,8 +108,8 @@ proc test096 { method {pagesize 512} {nentries 1000} {ndups 19} args} { # puts "\tTest096.d: Create $nentries entries with $ndups duplicates" set ret [berkdb dbremove -env $env $testfile] - set db [eval {berkdb_open_noerr -pagesize $pagesize -dup -create \ - -env $env $omethod -mode 0644} $args $testfile] + set db [eval {berkdb_open -pagesize $pagesize -dup -auto_commit \ + -create -env $env $omethod -mode 0644} $args $testfile] error_check_good db_open [is_valid_db $db] TRUE set did [open $dict] set count 0 @@ -113,9 +120,13 @@ proc test096 { method {pagesize 512} {nentries 1000} {ndups 19} args} { set key $str for { set i 1 } { $i <= $ndups } { incr i } { set datastr $i:$str + set t [$env txn] + error_check_good txn [is_valid_txn $t $env] TRUE + set txn "-txn $t" set ret [eval {$db put} \ $txn $pflags {$key [chop_data $method $datastr]}] error_check_good put $ret 0 + error_check_good txn [$t commit] 0 } set ret [eval {$db get} $gflags {$key}] @@ -129,7 +140,11 @@ proc test096 { method {pagesize 512} {nentries 1000} {ndups 19} args} { for { set i 1 } {$i <= $ndups} {incr i} { lappend dlist $i } + set t [$env txn] + error_check_good txn [is_valid_txn $t $env] TRUE + set txn "-txn $t" dup_check $db $txn $t1 $dlist + error_check_good txn [$t commit] 0 puts "\tTest096.e: Verify off page duplicates status" set stat [$db stat] error_check_bad stat:offpage [is_substr $stat \ @@ -141,7 +156,7 @@ proc test096 { method {pagesize 512} {nentries 1000} {ndups 19} args} { puts "\tTest096.f: Truncate database in a txn then abort" set txn [$env txn] - set dbtr [eval {berkdb_open_noerr -create \ + set dbtr [eval {berkdb_open -auto_commit -create \ -env $env $omethod -mode 0644} $args $testfile] error_check_good db_open [is_valid_db $dbtr] TRUE error_check_good txnbegin [is_valid_txn $txn $env] TRUE @@ -152,7 +167,7 @@ proc test096 { method {pagesize 512} {nentries 1000} {ndups 19} args} { error_check_good txnabort [$txn abort] 0 error_check_good db_close [$dbtr close] 0 - set db [berkdb_open -env $env $testfile] + set db [eval {berkdb_open -auto_commit -env $env} $args $testfile] error_check_good dbopen [is_valid_db $db] TRUE set ret [$db get -glob *] error_check_good dbget [llength $ret] $recs @@ -162,22 +177,23 @@ proc test096 { method {pagesize 512} {nentries 1000} {ndups 19} args} { set txn [$env txn] error_check_good txnbegin [is_valid_txn $txn $env] TRUE - set dbtr [eval {berkdb_open_noerr -create \ + set dbtr [eval {berkdb_open -auto_commit -create \ -env $env $omethod -mode 0644} $args $testfile] error_check_good db_open [is_valid_db $dbtr] TRUE set ret [$dbtr truncate -txn $txn] error_check_good dbtrunc $ret $recs - error_check_good db_close [$dbtr close] 0 error_check_good txncommit [$txn commit] 0 + error_check_good db_close [$dbtr close] 0 - set db [berkdb_open -env $env $testfile] + set db [berkdb_open -auto_commit -env $env $testfile] error_check_good dbopen [is_valid_db $db] TRUE set ret [$db get -glob *] error_check_good dbget [llength $ret] 0 error_check_good dbclose [$db close] 0 + set testdir [get_home $env] error_check_good dbverify [verify_dir $testdir "\tTest096.h: "] 0 if { $closeenv == 1 } { diff --git a/db/test/txnscript.tcl b/db/test/txnscript.tcl index 8739b1da0..66be1e9a1 100644 --- a/db/test/txnscript.tcl +++ b/db/test/txnscript.tcl @@ -1,9 +1,9 @@ # See the file LICENSE for redistribution information. # -# Copyright (c) 1996-2001 +# Copyright (c) 1996-2002 # Sleepycat Software. All rights reserved. # -# Id: txnscript.tcl,v 11.1 2001/05/31 18:12:45 sue Exp +# Id: txnscript.tcl,v 11.3 2002/01/23 15:33:40 bostic Exp # # Txn003 script - outstanding child prepare script # Usage: txnscript envcmd dbcmd gidf key data @@ -36,7 +36,7 @@ set dbenv [eval $envcmd] error_check_good envopen [is_valid_env $dbenv] TRUE set usedb 1 -set db [berkdb_open -env $dbenv $dbfile] +set db [berkdb_open -auto_commit -env $dbenv $dbfile] error_check_good dbopen [is_valid_db $db] TRUE puts "\tTxnscript.a: begin parent and child txn" diff --git a/db/txn/txn_method.c b/db/txn/txn_method.c index 8207acb05..d15a8894c 100644 --- a/db/txn/txn_method.c +++ b/db/txn/txn_method.c @@ -1,38 +1,35 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996-2001 + * Copyright (c) 1996-2002 * Sleepycat Software. All rights reserved. */ #include "db_config.h" #ifndef lint -static const char revid[] = "Id: txn_method.c,v 11.55 2001/10/08 16:04:37 bostic Exp "; +static const char revid[] = "Id: txn_method.c,v 11.62 2002/05/09 20:09:35 bostic Exp "; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES #include <sys/types.h> -#include <string.h> +#ifdef HAVE_RPC +#include <rpc/rpc.h> #endif -#ifdef HAVE_RPC -#include "db_server.h" +#include <string.h> #endif #include "db_int.h" -#include "db_page.h" -#include "log.h" -#include "txn.h" +#include "dbinc/txn.h" #ifdef HAVE_RPC -#include "rpc_client_ext.h" +#include "dbinc_auto/db_server.h" +#include "dbinc_auto/rpc_client_ext.h" #endif static int __txn_set_tx_max __P((DB_ENV *, u_int32_t)); -static int __txn_set_tx_recover __P((DB_ENV *, - int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops))); static int __txn_set_tx_timestamp __P((DB_ENV *, time_t *)); /* @@ -57,7 +54,6 @@ __txn_dbenv_create(dbenv) #ifdef HAVE_RPC if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) { dbenv->set_tx_max = __dbcl_set_tx_max; - dbenv->set_tx_recover = __dbcl_set_tx_recover; dbenv->set_tx_timestamp = __dbcl_set_tx_timestamp; dbenv->txn_checkpoint = __dbcl_txn_checkpoint; dbenv->txn_recover = __dbcl_txn_recover; @@ -67,7 +63,6 @@ __txn_dbenv_create(dbenv) #endif { dbenv->set_tx_max = __txn_set_tx_max; - dbenv->set_tx_recover = __txn_set_tx_recover; dbenv->set_tx_timestamp = __txn_set_tx_timestamp; dbenv->txn_checkpoint = __txn_checkpoint; #ifdef CONFIG_TEST @@ -95,21 +90,6 @@ __txn_set_tx_max(dbenv, tx_max) } /* - * __txn_set_tx_recover -- - * Set the transaction abort recover function. - */ -static int -__txn_set_tx_recover(dbenv, tx_recover) - DB_ENV *dbenv; - int (*tx_recover) __P((DB_ENV *, DBT *, DB_LSN *, db_recops)); -{ - ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_tx_recover"); - - dbenv->tx_recover = tx_recover; - return (0); -} - -/* * __txn_set_tx_timestamp -- * Set the transaction recovery timestamp. */ |