5 # Copyright (c) 1997-2011 Paul Marquess. All rights reserved.
6 # This program is free software; you can redistribute it and/or
7 # modify it under the same terms as Perl itself.
10 # The documentation for this module is at the bottom of this file,
11 # after the line __END__.
13 BEGIN { require 5.005 }
17 use vars qw($VERSION @ISA @EXPORT $AUTOLOAD
28 { local $SIG{__DIE__} ; eval { require XSLoader } ; }
33 @ISA = qw(DynaLoader);
37 @ISA = qw(Exporter DynaLoader);
38 # Items to export into callers namespace by default. Note: do not export
39 # names by default without a very good reason. Use EXPORT_OK instead.
40 # Do not simply export all your public functions/methods/constants.
42 # NOTE -- Do not add to @EXPORT directly. It is written by mkconsts
58 DB_ASSOC_IMMUTABLE_KEY
68 DB_BACKUP_WRITE_DIRECT
120 DB_ENV_DATABASE_LOCKING
132 DB_ENV_LOG_AUTOREMOVE
150 DB_ENV_RPCCLIENT_GIVEN
154 DB_ENV_TIME_NOTGRANTED
157 DB_ENV_TXN_NOT_DURABLE
160 DB_ENV_TXN_WRITE_NOSYNC
164 DB_EVENT_NO_SUCH_EVENT
169 DB_EVENT_REP_CONNECT_BROKEN
170 DB_EVENT_REP_CONNECT_ESTD
171 DB_EVENT_REP_CONNECT_TRY_FAILED
172 DB_EVENT_REP_DUPMASTER
174 DB_EVENT_REP_ELECTION_FAILED
175 DB_EVENT_REP_INIT_DONE
176 DB_EVENT_REP_JOIN_FAILURE
177 DB_EVENT_REP_LOCAL_SITE_REMOVED
179 DB_EVENT_REP_MASTER_FAILURE
180 DB_EVENT_REP_NEWMASTER
181 DB_EVENT_REP_PERM_FAILED
182 DB_EVENT_REP_SITE_ADDED
183 DB_EVENT_REP_SITE_REMOVED
184 DB_EVENT_REP_STARTUPDONE
185 DB_EVENT_REP_WOULD_ROLLBACK
186 DB_EVENT_WRITE_FAILED
225 DB_HOTBACKUP_IN_PROGRESS
238 DB_INTERNAL_PERSISTENT_DB
239 DB_INTERNAL_TEMPORARY_DB
290 DB_LOCK_UPGRADE_WRITE
298 DB_LOGVERSION_LATCHING
320 DB_LOG_VERIFY_FORWARD
322 DB_LOG_VERIFY_PARTIAL
323 DB_LOG_VERIFY_VERBOSE
324 DB_LOG_VERIFY_WARNING
357 DB_MUTEX_LOGICAL_LOCK
358 DB_MUTEX_PROCESS_ONLY
410 DB_PRIORITY_UNCHANGED
411 DB_PRIORITY_VERY_HIGH
441 DB_REPMGR_ACKS_ALL_AVAILABLE
442 DB_REPMGR_ACKS_ALL_PEERS
445 DB_REPMGR_ACKS_ONE_PEER
446 DB_REPMGR_ACKS_QUORUM
447 DB_REPMGR_CONF_2SITE_STRICT
448 DB_REPMGR_CONF_ELECTIONS
450 DB_REPMGR_DISCONNECTED
452 DB_REPMGR_NEED_RESPONSE
457 DB_REP_CHECKPOINT_DELAY
460 DB_REP_CONF_AUTOROLLBACK
462 DB_REP_CONF_DELAYCLIENT
465 DB_REP_CONF_NOAUTOINIT
467 DB_REP_CONNECTION_RETRY
469 DB_REP_DEFAULT_PRIORITY
473 DB_REP_ELECTION_RETRY
474 DB_REP_ELECTION_TIMEOUT
476 DB_REP_FULL_ELECTION_TIMEOUT
478 DB_REP_HEARTBEAT_MONITOR
479 DB_REP_HEARTBEAT_SEND
590 DB_TXN_LOCK_OPTIMISTIC
625 DB_VERB_REPMGR_CONNFAIL
640 DB_VERSION_FULL_STRING
675 ($constname = $AUTOLOAD) =~ s/.*:://;
676 my ($error, $val) = constant($constname);
677 Carp::croak $error if $error;
679 *{$AUTOLOAD} = sub { $val };
683 #bootstrap BerkeleyDB $VERSION;
685 { XSLoader::load("BerkeleyDB", $VERSION)}
687 { bootstrap BerkeleyDB $VERSION }
689 # Preloaded methods go here.
692 sub ParseParameters($@)
694 my ($default, @rest) = @_ ;
695 my (%got) = %$default ;
698 my $sub = (caller(1))[3] ;
700 local ($Carp::CarpLevel) = 1 ;
702 # allow the options to be passed as a hash reference or
703 # as the complete hash.
706 croak "$sub: parameter is not a reference to a hash"
707 if ref $rest[0] ne "HASH" ;
709 %options = %{ $rest[0] } ;
711 elsif (@rest >= 2 && @rest % 2 == 0) {
715 croak "$sub: malformed option list";
718 while (($key, $value) = each %options)
722 if (exists $default->{$key})
723 { $got{$key} = $value }
725 { push (@Bad, $key) }
729 my ($bad) = join(", ", @Bad) ;
730 croak "unknown key value(s) $bad" ;
741 if (defined $got->{Encrypt}) {
742 croak("Encrypt parameter must be a hash reference")
743 if !ref $got->{Encrypt} || ref $got->{Encrypt} ne 'HASH' ;
745 my %config = %{ $got->{Encrypt} } ;
747 my $p = BerkeleyDB::ParseParameters({
752 croak("Must specify Password and Flags with Encrypt parameter")
753 if ! (defined $p->{Password} && defined $p->{Flags});
755 $got->{"Enc_Passwd"} = $p->{Password};
756 $got->{"Enc_Flags"} = $p->{Flags};
766 # $env = BerkeleyDB::env_remove
767 # [ -Home => $path, ]
768 # [ -Config => { name => value, name => value }
769 # [ -Flags => DB_INIT_LOCK| ]
772 my $got = BerkeleyDB::ParseParameters({
778 if (defined $got->{Config}) {
779 croak("Config parameter must be a hash reference")
780 if ! ref $got->{Config} eq 'HASH' ;
782 @BerkeleyDB::a = () ;
783 my $k = "" ; my $v = "" ;
784 while (($k, $v) = each %{$got->{Config}}) {
785 push @BerkeleyDB::a, "$k\t$v" ;
788 $got->{"Config"} = pack("p*", @BerkeleyDB::a, undef)
792 return _env_remove($got) ;
797 my $got = BerkeleyDB::ParseParameters(
806 croak("Must specify a filename")
807 if ! defined $got->{Filename} ;
809 croak("Env not of type BerkeleyDB::Env")
810 if defined $got->{Env} and ! UNIVERSAL::isa($got->{Env},'BerkeleyDB::Env');
812 return _db_remove($got);
817 my $got = BerkeleyDB::ParseParameters(
827 croak("Env not of type BerkeleyDB::Env")
828 if defined $got->{Env} and ! UNIVERSAL::isa($got->{Env},'BerkeleyDB::Env');
830 croak("Must specify a filename")
831 if ! defined $got->{Filename} ;
833 #croak("Must specify a Subname")
834 #if ! defined $got->{Subname} ;
836 croak("Must specify a Newname")
837 if ! defined $got->{Newname} ;
839 return _db_rename($got);
844 my $got = BerkeleyDB::ParseParameters(
853 croak("Env not of type BerkeleyDB::Env")
854 if defined $got->{Env} and ! UNIVERSAL::isa($got->{Env},'BerkeleyDB::Env');
856 croak("Must specify a filename")
857 if ! defined $got->{Filename} ;
859 return _db_verify($got);
862 package BerkeleyDB::Env ;
867 use vars qw( %valid_config_keys ) ;
873 return ((UNIVERSAL::isa($fh,'GLOB') or UNIVERSAL::isa(\$fh,'GLOB')) and defined fileno($fh) )
877 %valid_config_keys = map { $_, 1 } qw( DB_DATA_DIR DB_LOG_DIR DB_TEMP_DIR
884 # $env = new BerkeleyDB::Env
885 # [ -Home => $path, ]
887 # [ -Config => { name => value, name => value }
888 # [ -ErrFile => filename, ]
889 # [ -ErrPrefix => "string", ]
890 # [ -Flags => DB_INIT_LOCK| ]
891 # [ -Set_Flags => $flags,]
892 # [ -Cachesize => number ]
894 # [ -Verbose => boolean ]
895 # [ -Encrypt => { Password => string, Flags => value}
900 my $got = BerkeleyDB::ParseParameters({
919 SharedMemKey => undef,
920 Set_Lk_Exclusive => undef,
924 my $errfile = $got->{ErrFile} ;
925 if (defined $got->{ErrFile}) {
926 if (!isaFilehandle($got->{ErrFile})) {
927 my $handle = new IO::File ">$got->{ErrFile}"
928 or croak "Cannot open file $got->{ErrFile}: $!\n" ;
929 $errfile = $got->{ErrFile} = $handle ;
933 if (defined $got->{MsgFile}) {
934 my $msgfile = $got->{MsgFile} ;
935 if (!isaFilehandle($msgfile)) {
936 my $handle = new IO::File ">$msgfile"
937 or croak "Cannot open file $msgfile: $!\n" ;
938 $got->{MsgFile} = $handle ;
943 if (defined $got->{Config}) {
944 croak("Config parameter must be a hash reference")
945 if ! ref $got->{Config} eq 'HASH' ;
947 %config = %{ $got->{Config} } ;
948 @BerkeleyDB::a = () ;
949 my $k = "" ; my $v = "" ;
950 while (($k, $v) = each %config) {
951 if ($BerkeleyDB::db_version >= 3.1 && ! $valid_config_keys{$k} ){
952 $BerkeleyDB::Error = "illegal name-value pair: $k $v\n" ;
953 croak $BerkeleyDB::Error ;
955 push @BerkeleyDB::a, "$k\t$v" ;
959 $got->{"Config"} = pack("p*", @BerkeleyDB::a, undef)
963 BerkeleyDB::parseEncrypt($got);
965 my ($addr) = _db_appinit($pkg, $got, $errfile);
967 $obj = bless [$addr] , $pkg if $addr ;
968 # if ($obj && $BerkeleyDB::db_version >= 3.1 && keys %config) {
970 # while (($k, $v) = each %config) {
971 # if ($k eq 'DB_DATA_DIR')
972 # { $obj->set_data_dir($v) }
973 # elsif ($k eq 'DB_LOG_DIR')
974 # { $obj->set_lg_dir($v) }
975 # elsif ($k eq 'DB_TEMP_DIR' || $k eq 'DB_TMP_DIR')
976 # { $obj->set_tmp_dir($v) }
978 # $BerkeleyDB::Error = "illegal name-value pair: $k $v\n" ;
979 # croak $BerkeleyDB::Error
990 my ($addr) = $env->_TxnMgr() ;
992 $obj = bless [$addr, $env] , "BerkeleyDB::TxnMgr" if $addr ;
999 my ($addr) = $env->_txn_begin(@_) ;
1001 $obj = bless [$addr, $env] , "BerkeleyDB::Txn" if $addr ;
1013 my $type = ref shift;
1014 croak "Cannot freeze $type object\n";
1019 my $type = ref shift;
1020 croak "Cannot thaw $type object\n";
1023 package BerkeleyDB::Hash ;
1026 @ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedHash ) ;
1033 my $got = BerkeleyDB::ParseParameters(
1038 #Flags => BerkeleyDB::DB_CREATE(),
1054 DupCompare => undef,
1056 # BerkeleyDB specific
1060 WriteValue => undef,
1063 croak("Env not of type BerkeleyDB::Env")
1064 if defined $got->{Env} and ! UNIVERSAL::isa($got->{Env},'BerkeleyDB::Env');
1066 croak("Txn not of type BerkeleyDB::Txn")
1067 if defined $got->{Txn} and ! UNIVERSAL::isa($got->{Txn},'BerkeleyDB::Txn');
1069 croak("-Tie needs a reference to a hash")
1070 if defined $got->{Tie} and $got->{Tie} !~ /HASH/ ;
1072 BerkeleyDB::parseEncrypt($got);
1074 my ($addr) = _db_open_hash($self, $got);
1077 $obj = bless [$addr] , $self ;
1078 push @{ $obj }, $got->{Env} if $got->{Env} ;
1079 $obj->Txn($got->{Txn})
1088 package BerkeleyDB::Btree ;
1091 @ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedHash ) ;
1098 my $got = BerkeleyDB::ParseParameters(
1103 #Flags => BerkeleyDB::DB_CREATE(),
1118 DupCompare => undef,
1120 set_bt_compress => undef,
1123 croak("Env not of type BerkeleyDB::Env")
1124 if defined $got->{Env} and ! UNIVERSAL::isa($got->{Env},'BerkeleyDB::Env');
1126 croak("Txn not of type BerkeleyDB::Txn")
1127 if defined $got->{Txn} and ! UNIVERSAL::isa($got->{Txn},'BerkeleyDB::Txn');
1129 croak("-Tie needs a reference to a hash")
1130 if defined $got->{Tie} and $got->{Tie} !~ /HASH/ ;
1132 # if (defined $got->{set_bt_compress} )
1135 # croak("-set_bt_compress needs a reference to a 2-element array")
1136 # if $got->{set_bt_compress} !~ /ARRAY/ ||
1138 # croak("-set_bt_compress needs a reference to a 2-element array")
1139 # if $got->{set_bt_compress} !~ /ARRAY/ ||
1140 # @{ $got->{set_bt_compress} } != 2;
1142 # $got->{"_btcompress1"} = $got->{set_bt_compress}[0]
1143 # if defined $got->{set_bt_compress}[0];
1145 # $got->{"_btcompress2"} = $got->{set_bt_compress}[1]
1146 # if defined $got->{set_bt_compress}[1];
1149 BerkeleyDB::parseEncrypt($got);
1151 my ($addr) = _db_open_btree($self, $got);
1154 $obj = bless [$addr] , $self ;
1155 push @{ $obj }, $got->{Env} if $got->{Env} ;
1156 $obj->Txn($got->{Txn})
1162 *BerkeleyDB::Btree::TIEHASH = \&BerkeleyDB::Btree::new ;
1164 package BerkeleyDB::Heap ;
1167 @ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedHash ) ;
1174 my $got = BerkeleyDB::ParseParameters(
1179 #Flags => BerkeleyDB::DB_CREATE(),
1192 HeapSizeGb => undef,
1195 croak("Env not of type BerkeleyDB::Env")
1196 if defined $got->{Env} and ! UNIVERSAL::isa($got->{Env},'BerkeleyDB::Env');
1198 croak("Txn not of type BerkeleyDB::Txn")
1199 if defined $got->{Txn} and ! UNIVERSAL::isa($got->{Txn},'BerkeleyDB::Txn');
1201 # if (defined $got->{HeapSize} )
1204 # croak("-HeapSize needs a reference to a 2-element array")
1205 # if $got->{HeapSize} !~ /ARRAY/ ||
1207 # croak("-HeapSize needs a reference to a 2-element array")
1208 # if $got->{HeapSize} !~ /ARRAY/ ||
1209 # @{ $got->{set_bt_compress} } != 2;
1211 # $got->{"HeapSize"} = $got->{HeapSize}[0]
1212 # if defined $got->{HeapSize}[0];
1214 # $got->{"HeapSize"} = $got->{HeapSize}[1]
1215 # if defined $got->{HeapSize}[1];
1218 BerkeleyDB::parseEncrypt($got);
1220 my ($addr) = _db_open_heap($self, $got);
1223 $obj = bless [$addr] , $self ;
1224 push @{ $obj }, $got->{Env} if $got->{Env} ;
1225 $obj->Txn($got->{Txn})
1233 die "Tied Hash interface not supported with BerkeleyDB::Heap\n" ;
1237 package BerkeleyDB::Recno ;
1240 @ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedArray ) ;
1247 my $got = BerkeleyDB::ParseParameters(
1252 #Flags => BerkeleyDB::DB_CREATE(),
1269 ArrayBase => 1, # lowest index in array
1272 croak("Env not of type BerkeleyDB::Env")
1273 if defined $got->{Env} and ! UNIVERSAL::isa($got->{Env},'BerkeleyDB::Env');
1275 croak("Txn not of type BerkeleyDB::Txn")
1276 if defined $got->{Txn} and ! UNIVERSAL::isa($got->{Txn},'BerkeleyDB::Txn');
1278 croak("Tie needs a reference to an array")
1279 if defined $got->{Tie} and $got->{Tie} !~ /ARRAY/ ;
1281 croak("ArrayBase can only be 0 or 1, parsed $got->{ArrayBase}")
1282 if $got->{ArrayBase} != 1 and $got->{ArrayBase} != 0 ;
1285 BerkeleyDB::parseEncrypt($got);
1287 $got->{Fname} = $got->{Filename} if defined $got->{Filename} ;
1289 my ($addr) = _db_open_recno($self, $got);
1292 $obj = bless [$addr] , $self ;
1293 push @{ $obj }, $got->{Env} if $got->{Env} ;
1294 $obj->Txn($got->{Txn})
1300 *BerkeleyDB::Recno::TIEARRAY = \&BerkeleyDB::Recno::new ;
1301 *BerkeleyDB::Recno::db_stat = \&BerkeleyDB::Btree::db_stat ;
1303 package BerkeleyDB::Queue ;
1306 @ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedArray ) ;
1313 my $got = BerkeleyDB::ParseParameters(
1318 #Flags => BerkeleyDB::DB_CREATE(),
1333 ArrayBase => 1, # lowest index in array
1334 ExtentSize => undef,
1337 croak("Env not of type BerkeleyDB::Env")
1338 if defined $got->{Env} and ! UNIVERSAL::isa($got->{Env},'BerkeleyDB::Env');
1340 croak("Txn not of type BerkeleyDB::Txn")
1341 if defined $got->{Txn} and ! UNIVERSAL::isa($got->{Txn},'BerkeleyDB::Txn');
1343 croak("Tie needs a reference to an array")
1344 if defined $got->{Tie} and $got->{Tie} !~ /ARRAY/ ;
1346 croak("ArrayBase can only be 0 or 1, parsed $got->{ArrayBase}")
1347 if $got->{ArrayBase} != 1 and $got->{ArrayBase} != 0 ;
1349 BerkeleyDB::parseEncrypt($got);
1351 $got->{Fname} = $got->{Filename} if defined $got->{Filename} ;
1353 my ($addr) = _db_open_queue($self, $got);
1356 $obj = bless [$addr] , $self ;
1357 push @{ $obj }, $got->{Env} if $got->{Env} ;
1358 $obj->Txn($got->{Txn})
1364 *BerkeleyDB::Queue::TIEARRAY = \&BerkeleyDB::Queue::new ;
1369 croak "unshift is unsupported with Queue databases";
1372 ## package BerkeleyDB::Text ;
1374 ## use vars qw(@ISA) ;
1375 ## @ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedArray ) ;
1381 ## my $self = shift ;
1382 ## my $got = BerkeleyDB::ParseParameters(
1385 ## Filename => undef,
1386 ## #Flags => BerkeleyDB::DB_CREATE(),
1404 ## croak("Env not of type BerkeleyDB::Env")
1405 ## if defined $got->{Env} and ! isa($got->{Env},'BerkeleyDB::Env');
1407 ## croak("Txn not of type BerkeleyDB::Txn")
1408 ## if defined $got->{Txn} and ! isa($got->{Txn},'BerkeleyDB::Txn');
1410 ## croak("-Tie needs a reference to an array")
1411 ## if defined $got->{Tie} and $got->{Tie} !~ /ARRAY/ ;
1413 ## # rearange for recno
1414 ## $got->{Source} = $got->{Filename} if defined $got->{Filename} ;
1415 ## delete $got->{Filename} ;
1416 ## $got->{Fname} = $got->{Btree} if defined $got->{Btree} ;
1417 ## return BerkeleyDB::Recno::_db_open_recno($self, $got);
1420 ## *BerkeleyDB::Text::TIEARRAY = \&BerkeleyDB::Text::new ;
1421 ## *BerkeleyDB::Text::db_stat = \&BerkeleyDB::Btree::db_stat ;
1423 package BerkeleyDB::Unknown ;
1426 @ISA = qw( BerkeleyDB::Common BerkeleyDB::_tiedArray ) ;
1433 my $got = BerkeleyDB::ParseParameters(
1438 #Flags => BerkeleyDB::DB_CREATE(),
1452 croak("Env not of type BerkeleyDB::Env")
1453 if defined $got->{Env} and ! UNIVERSAL::isa($got->{Env},'BerkeleyDB::Env');
1455 croak("Txn not of type BerkeleyDB::Txn")
1456 if defined $got->{Txn} and ! UNIVERSAL::isa($got->{Txn},'BerkeleyDB::Txn');
1458 croak("-Tie needs a reference to a hash")
1459 if defined $got->{Tie} and $got->{Tie} !~ /HASH/ ;
1461 BerkeleyDB::parseEncrypt($got);
1463 my ($addr, $type) = _db_open_unknown($got);
1466 $obj = bless [$addr], "BerkeleyDB::$type" ;
1467 push @{ $obj }, $got->{Env} if $got->{Env} ;
1468 $obj->Txn($got->{Txn})
1475 package BerkeleyDB::_tiedHash ;
1481 # my $self = shift ;
1482 # my $db_object = shift ;
1484 #print "Tiehash REF=[$self] [" . (ref $self) . "]\n" ;
1486 # return bless { Obj => $db_object}, $self ;
1498 #print "Tie method REF=[$self] [" . (ref $self) . "]\n" ;
1500 croak("usage \$x->Tie \\%hash\n") unless @_ ;
1503 croak("Tie needs a reference to a hash")
1504 if defined $ref and $ref !~ /HASH/ ;
1506 #tie %{ $ref }, ref($self), $self ;
1507 tie %{ $ref }, "BerkeleyDB::_tiedHash", $self ;
1515 my $db_object = shift ;
1516 #return bless $db_object, 'BerkeleyDB::Common' ;
1526 $self->db_put($key, $value) ;
1534 $self->db_get($key, $value) ;
1544 $self->db_get($key, $value) == 0 ;
1551 $self->db_del($key) ;
1557 my ($key, $value) = (0, 0) ;
1558 my $cursor = $self->_db_write_cursor() ;
1559 while ($cursor->c_get($key, $value, BerkeleyDB::DB_PREV()) == 0)
1560 { $cursor->c_del() }
1566 $self->truncate(my $count);
1569 *CLEAR = $BerkeleyDB::db_version < 4 ? \&CLEAR_old : \&CLEAR_new ;
1573 # my $self = shift ;
1574 # print "BerkeleyDB::_tieHash::DESTROY\n" ;
1575 # $self->{Cursor}->c_close() if $self->{Cursor} ;
1578 package BerkeleyDB::_tiedArray ;
1586 # $db->Tie \@array ;
1591 #print "Tie method REF=[$self] [" . (ref $self) . "]\n" ;
1593 croak("usage \$x->Tie \\%hash\n") unless @_ ;
1596 croak("Tie needs a reference to an array")
1597 if defined $ref and $ref !~ /ARRAY/ ;
1599 #tie %{ $ref }, ref($self), $self ;
1600 tie @{ $ref }, "BerkeleyDB::_tiedArray", $self ;
1607 # my $self = shift ;
1608 # my $db_object = shift ;
1610 #print "Tiearray REF=[$self] [" . (ref $self) . "]\n" ;
1612 # return bless { Obj => $db_object}, $self ;
1618 my $db_object = shift ;
1619 #return bless $db_object, 'BerkeleyDB::Common' ;
1629 $self->db_put($key, $value) ;
1637 $self->db_get($key, $value) ;
1642 *CLEAR = \&BerkeleyDB::_tiedHash::CLEAR ;
1643 *FIRSTKEY = \&BerkeleyDB::_tiedHash::FIRSTKEY ;
1644 *NEXTKEY = \&BerkeleyDB::_tiedHash::NEXTKEY ;
1646 sub EXTEND {} # don't do anything with EXTEND
1652 my ($key, $value) = (0, 0) ;
1653 my $cursor = $self->_db_write_cursor() ;
1654 return undef if $cursor->c_get($key, $value, BerkeleyDB::DB_FIRST()) != 0 ;
1655 return undef if $cursor->c_del() != 0 ;
1666 my ($key, $value) = (0, 0) ;
1667 my $cursor = $self->_db_write_cursor() ;
1668 my $status = $cursor->c_get($key, $value, BerkeleyDB::DB_FIRST()) ;
1671 foreach $value (reverse @_)
1674 $cursor->c_put($key, $value, BerkeleyDB::DB_BEFORE()) ;
1677 elsif ($status == BerkeleyDB::DB_NOTFOUND())
1682 $self->db_put($key++, $value) ;
1693 my ($key, $value) = (-1, 0) ;
1694 my $cursor = $self->_db_write_cursor() ;
1695 my $status = $cursor->c_get($key, $value, BerkeleyDB::DB_LAST()) ;
1696 if ($status == 0 || $status == BerkeleyDB::DB_NOTFOUND())
1698 $key = -1 if $status != 0 and $self->type != BerkeleyDB::DB_RECNO() ;
1702 $status = $self->db_put($key, $value) ;
1706 # can use this when DB_APPEND is fixed.
1707 # foreach $value (@_)
1709 # my $status = $cursor->c_put($key, $value, BerkeleyDB::DB_AFTER()) ;
1710 #print "[$status]\n" ;
1718 my ($key, $value) = (0, 0) ;
1719 my $cursor = $self->_db_write_cursor() ;
1720 return undef if $cursor->c_get($key, $value, BerkeleyDB::DB_LAST()) != 0 ;
1721 return undef if $cursor->c_del() != 0 ;
1729 croak "SPLICE is not implemented yet" ;
1733 *unshift = \&UNSHIFT ;
1737 *length = \&FETCHSIZE ;
1741 croak "STORESIZE is not implemented yet" ;
1742 #print "STORESIZE @_\n" ;
1744 # my $length = shift ;
1745 # my $current_length = $self->FETCHSIZE() ;
1746 #print "length is $current_length\n";
1748 # if ($length < $current_length) {
1749 #print "Make smaller $length < $current_length\n" ;
1751 # for ($key = $current_length - 1 ; $key >= $length ; -- $key)
1752 # { $self->db_del($key) }
1754 # elsif ($length > $current_length) {
1755 #print "Make larger $length > $current_length\n" ;
1756 # $self->db_put($length-1, "") ;
1758 # else { print "stay the same\n" }
1766 # my $self = shift ;
1767 # print "BerkeleyDB::_tieArray::DESTROY\n" ;
1771 package BerkeleyDB::Common ;
1779 my $type = ref shift;
1780 croak "Cannot freeze $type object\n";
1785 my $type = ref shift;
1786 croak "Cannot thaw $type object\n";
1804 #print "BerkeleyDB::Common::Txn db [$self] txn [$txn]\n" ;
1807 push @{ $txn }, $self ;
1812 #print "end BerkeleyDB::Common::Txn \n";
1818 croak "Usage: \$db->get_dup(key [,flag])\n"
1819 unless @_ == 2 or @_ == 3 ;
1825 my $origkey = $key ;
1826 my $wantarray = wantarray ;
1831 my $cursor = $db->db_cursor() ;
1833 # iterate through the database until either EOF ($status == 0)
1834 # or a different key is encountered ($key ne $origkey).
1835 for ($status = $cursor->c_get($key, $value, BerkeleyDB::DB_SET()) ;
1836 $status == 0 and $key eq $origkey ;
1837 $status = $cursor->c_get($key, $value, BerkeleyDB::DB_NEXT()) ) {
1838 # save the value or count number of matches
1841 { ++ $values{$value} }
1843 { push (@values, $value) }
1850 return ($wantarray ? ($flag ? %values : @values) : $counter) ;
1856 my ($addr) = $db->_db_cursor(@_) ;
1858 $obj = bless [$addr, $db] , "BerkeleyDB::Cursor" if $addr ;
1862 sub _db_write_cursor
1865 my ($addr) = $db->__db_write_cursor(@_) ;
1867 $obj = bless [$addr, $db] , "BerkeleyDB::Cursor" if $addr ;
1873 croak 'Usage: $db->BerkeleyDB::db_join([cursors], flags=0)'
1874 if @_ < 2 || @_ > 3 ;
1876 croak 'db_join: first parameter is not an array reference'
1877 if ! ref $_[0] || ref $_[0] ne 'ARRAY';
1878 my ($addr) = $db->_db_join(@_) ;
1880 $obj = bless [$addr, $db, $_[0]] , "BerkeleyDB::Cursor" if $addr ;
1884 package BerkeleyDB::Cursor ;
1888 my $cursor = shift ;
1890 return $cursor->_c_close() ;
1895 my $cursor = shift ;
1896 my ($addr) = $cursor->_c_dup(@_) ;
1898 $obj = bless [$addr, $cursor->[1]] , "BerkeleyDB::Cursor" if $addr ;
1908 package BerkeleyDB::TxnMgr ;
1918 my $txnmgr = shift ;
1919 my ($addr) = $txnmgr->_txn_begin(@_) ;
1921 $obj = bless [$addr, $txnmgr] , "BerkeleyDB::Txn" if $addr ;
1925 package BerkeleyDB::Txn ;
1931 # keep a reference to each db in the txn object
1934 push @{ $self}, $db ;
1941 $self->disassociate() ;
1942 my $status = $self->_txn_commit() ;
1949 $self->disassociate() ;
1950 my $status = $self->_txn_abort() ;
1958 while ( @{ $self } > 2) {
1959 $db = pop @{ $self } ;
1962 #print "end disassociate\n" ;
1970 $self->disassociate() ;
1971 # first close the close the transaction
1975 package BerkeleyDB::CDS::Lock;
1977 use vars qw(%Object %Count);
1980 sub BerkeleyDB::Common::cds_lock
1984 # fatal error if database not opened in CDS mode
1985 croak("CDS not enabled for this database\n")
1986 if ! $db->cds_enabled();
1988 if ( ! defined $Object{"$db"})
1990 $Object{"$db"} = $db->_db_write_cursor()
1996 return bless [$db, 1], "BerkeleyDB::CDS::Lock" ;
2002 my $db = $self->[0] ;
2007 -- $Count{"$db"} if $Count{"$db"} > 0 ;
2009 if ($Count{"$db"} == 0)
2011 $Object{"$db"}->c_close() ;
2012 undef $Object{"$db"};
2024 $self->cds_unlock() ;
2027 package BerkeleyDB::Term ;
2031 close_everything() ;
2035 package BerkeleyDB ;
2039 # Autoload methods go after =cut, and are processed by the autosplit program.