package Tie::DB_File::SplitHash; use strict; use DB_File; use File::Path; use File::Spec; use Digest::SHA1 qw (sha1_hex); use Fcntl qw (:flock); require Exporter; use vars qw ($VERSION @ISA @EXPORT $DB_HASH); $VERSION = '1.05'; @ISA = qw (Tie::Hash Exporter); @EXPORT = qw( $DB_HASH DB_LOCK DB_SHMEM DB_TXN HASHMAGIC HASHVERSION MAX_PAGE_NUMBER MAX_PAGE_OFFSET MAX_REC_NUMBER RET_ERROR RET_SPECIAL RET_SUCCESS R_CURSOR R_DUP R_FIRST R_FIXEDLEN R_IAFTER R_IBEFORE R_LAST R_NEXT R_NOKEY R_NOOVERWRITE R_PREV R_RECNOSYNC R_SETCURSOR R_SNAPSHOT __R_UNUSED); eval { # Make all Fcntl O_XXX constants available for importing require Fcntl; my @O = grep /^O_/, @Fcntl::EXPORT; Fcntl->import(@O); # first we import what we want to export push(@EXPORT, @O); }; ############################################################################### sub TIEHASH { my $class = shift; my $package = __PACKAGE__; my $self = bless {},$class; my $parms = [@_]; my $vars = {}; $self->{$package} = $vars; $vars->{'-init_parms'} = $parms; my $n_parms = $#$parms + 1; if ($n_parms != 5) { require Carp; Carp::croak($package . "::init_hash() - incorrect number of calling parameters\n"); } my $multi_n = pop @$parms; $vars->{'-multi_n'} = $multi_n; $vars->{'-dirname'} = $parms->[0]; if (not ((-e $vars->{'-dirname'}) or (mkdir ($vars->{'-dirname'},0777)))) { require Carp; Carp::croak($package . '::TIEHASH - datafiles directory ' . $vars->{'-dirname'} . " does not exist and cannot be created.\n$!"); } my $main_index_file = File::Spec->catfile($vars->{'-dirname'}, 'index'); shift @$parms; $multi_n--; my $errors=0; my $error_message = ''; foreach my $f_part (0..$multi_n) { my $tied_hash = {}; my $db_object = tie %$tied_hash,'DB_File',"${main_index_file}_${f_part}.db",@$parms; if (not defined $db_object) { $errors = $f_part + 1; $error_message = $!; last; } $vars->{'db'}->[$f_part]->{-object} = $db_object; } if ($errors) { delete $vars->{'db'}; require Carp; Carp::croak ("Failed to open database: $error_message\n"); } return $self; } ####################################################################### sub STORE { my $self = shift; my $package = __PACKAGE__; my ($key,$value) = @_; my $section = $self->_section_hash($key); my $db_object = $self->{$package}->{'db'}->[$section]->{'-object'}; return $db_object->STORE(@_); } ####################################################################### sub FETCH { my $self = shift; my $package = __PACKAGE__; my ($key) = @_; my $section = $self->_section_hash($key); my $db_object = $self->{$package}->{'db'}->[$section]->{-object}; return $db_object->FETCH(@_); } ####################################################################### sub DELETE { my $self = shift; my $package = __PACKAGE__; my ($key) = @_; my $section = $self->_section_hash($key); my $db_object = $self->{$package}->{'db'}->[$section]->{'-object'}; return $db_object->DELETE(@_); } ####################################################################### sub CLEAR { my $self = shift; my $package = __PACKAGE__; my $list_of_dbs = $self->{$package}->{'db'}; my $counter = 0; foreach my $database (@$list_of_dbs) { my $db_object = $database->{'-object'}; $counter++; $db_object->CLEAR(@_); } } ####################################################################### sub EXISTS { my $self = shift; my $package = __PACKAGE__; my ($key) = @_; my $section = $self->_section_hash($key); my $db_object = $self->{$package}->{'db'}->[$section]->{'-object'}; return $db_object->EXISTS(@_); } ####################################################################### sub DESTROY { my $self = shift; my $package = __PACKAGE__; delete $self->{$package}->{'db'}; } ####################################################################### sub FIRSTKEY { my $self = shift; my $package = __PACKAGE__; my $vars = $self->{$package}; my $db_object = $vars->{'db'}->[0]->{'-object'}; $vars->{-iteration_section} = 0; return $db_object->FIRSTKEY(@_); } ####################################################################### sub NEXTKEY { my $self = shift; my $package = __PACKAGE__; my $vars = $self->{$package}; my ($key) = @_; my $section = $vars->{'-iteration_section'}; my $multi_n = $vars->{'-multi_n'}; my $db_object = $vars->{'db'}->[$section]->{'-object'}; my $next_key; while (not defined $next_key) { $next_key = $db_object->NEXTKEY($key); if (not defined $next_key) { $section++; $vars->{-iteration_section} = $section; my $next_section = $vars->{'db'}->[$section]; last unless (defined $next_section); $db_object = $next_section->{'-object'}; $next_key = $db_object->FIRSTKEY; } } return $next_key; } ####################################################################### sub _section_hash { my $self = shift; my $package = __PACKAGE__; my ($key) = @_; $key = '' unless defined $key; my $sections = $self->{$package}->{'-multi_n'}; my $digest = sha1_hex($key); my $section_n = hex(substr($digest,0,2)) % $sections; return $section_n; } ####################################################################### sub put { my $self = shift; my $package = __PACKAGE__; my $parms = []; @$parms = @_; my $key = shift @$parms; my $section = $self->_section_hash($key); my $db_object = $self->{$package}->{'db'}->[$section]->{'-object'}; return $db_object->put(@_); } ####################################################################### sub get { my $self = shift; my $package = __PACKAGE__; my $parms = [@_]; my $key = shift @$parms; my $section = $self->_section_hash($key); my $db_object = $self->{$package}->{'db'}->[$section]->{'-object'}; return $db_object->get(@_); } ####################################################################### sub seq { my $self = shift; my $package = __PACKAGE__; my $parms = [@_]; my $key = shift @$parms; my $section = $self->_section_hash($key); my $db_object = $self->{$package}->{'db'}->[$section]->{'-object'}; return $db_object->seq(@_); } ####################################################################### sub del { my $self = shift; my $package = __PACKAGE__; my $parms = [@_]; my $key = shift @$parms; my $section = $self->_section_hash($key); my $db_object = $self->{$package}->{'db'}->[$section]->{'-object'}; return $db_object->del(@_); } ####################################################################### sub sync { my $self = shift; my $package = __PACKAGE__; foreach my $db (@{$self->{$package}->{'db'}}) { $db->{'-object'}->sync(@_); } } ####################################################################### sub fd { my $self = shift; my $package = __PACKAGE__; return $self->{$package}->{'db'}->[0]->{'-object'}->fd(@_); } ####################################################################### sub exists { return shift->EXISTS(@_); } ####################################################################### sub clear { return shift->CLEAR(@_); } ####################################################################### 1;