view release on metacpan or search on metacpan
- Thanks to our new co-maintainer, SPROUT! :)
- Had to turn off singleton support in the File backend because the caching
was causing havoc with transactions. Turning on fatal warnings does give
apparently important information.
- Oh - forgot to mention that fatal warnings are now on in all files.
1.0019_002 Jan 05 22:30:00 2010 EST
(This is the second developer release for 1.0020.)
(This version is compatible with 1.0014)
- Fixed bug where attempting to store a value tied to something other than
DBM::Deep would leave the file flocked.
- Added support for DBD::SQLite
- Build.PL has been extended to support sqlite vs. mysql
- Storage::DBI now detects between the two DBDs
- (RT #51888) Applied POD patch (Thanks, FWIE!)
- (RT #44981) Added VERSION to ::Array, ::Engine, and ::Hash
- Removed extraneous slashes from POD links (Thanks ilmari!)
- (RT #50541) Fixed bug in clear() for hashes in the File backend.
- This has caused a regression in speed for clear() when clearing
large hashes using running with the File backend. ->clear() (on my
machine) now takes ( N / 40 ) ** (1.66) seconds. So, clearing 4000
locking => 1
);
This causes DBM::Deep to "flock()" the underlying filehandle with
exclusive mode for writes, and shared mode for reads. This is required
if you have multiple processes accessing the same database file, to
avoid file corruption. Please note that "flock()" does NOT work for
files over NFS. See "DB over NFS" below for more.
Explicit Locking
You can explicitly lock a database, so it remains locked for multiple
actions. This is done by calling the "lock_exclusive()" method (for when
you want to write) or the "lock_shared()" method (for when you want to
read). This is particularly useful for things like counters, where the
current value needs to be fetched, then incremented, then stored again.
$db->lock_exclusive();
my $counter = $db->get("counter");
$counter++;
$db->put("counter", $counter);
$db->unlock();
lib/DBM/Deep.pod view on Meta::CPAN
);
This causes DBM::Deep to C<flock()> the underlying filehandle with exclusive
mode for writes, and shared mode for reads. This is required if you have
multiple processes accessing the same database file, to avoid file corruption.
Please note that C<flock()> does NOT work for files over NFS. See L</DB over
NFS> below for more.
=head2 Explicit Locking
You can explicitly lock a database, so it remains locked for multiple
actions. This is done by calling the C<lock_exclusive()> method (for when you
want to write) or the C<lock_shared()> method (for when you want to read).
This is particularly useful for things like counters, where the current value
needs to be fetched, then incremented, then stored again.
$db->lock_exclusive();
my $counter = $db->get("counter");
$counter++;
$db->put("counter", $counter);
$db->unlock();
lib/DBM/Deep/Storage.pm view on Meta::CPAN
Take a lock usable for writing.
=item * lock_shared( $obj )
Take a lock usable for reading.
=item * unlock( $obj )
Releases the last lock taken. If this is the outermost lock, then the
object is actually unlocked.
=back
=cut
sub lock_exclusive { die "lock_exclusive must be implemented in a child class" }
sub lock_shared { die "lock_shared must be implemented in a child class" }
sub unlock { die "unlock must be implemented in a child class" }
1;
lib/DBM/Deep/Storage/File.pm view on Meta::CPAN
my ($args) = @_;
my $self = bless {
autobless => 1,
autoflush => 1,
end => 0,
fh => undef,
file => undef,
file_offset => 0,
locking => 1,
locked => 0,
#XXX Migrate this to the engine, where it really belongs.
filter_store_key => undef,
filter_store_value => undef,
filter_fetch_key => undef,
filter_fetch_value => undef,
}, $class;
# Grab the parameters we want to use
foreach my $param ( keys %$self ) {
next unless exists $args->{$param};
lib/DBM/Deep/Storage/File.pm view on Meta::CPAN
if ( $^O eq 'MSWin32' || $^O eq 'cygwin' ) {
$type = LOCK_EX;
}
if (!defined($self->{fh})) { return; }
#XXX This either needs to allow for upgrading a shared lock to an
# exclusive lock or something else with autovivification.
# -RobK, 2008-03-09
if ($self->{locking}) {
if (!$self->{locked}) {
flock($self->{fh}, $type);
# refresh end counter in case file has changed size
my @stats = stat($self->{fh});
$self->{end} = $stats[7];
# double-check file inode, in case another process
# has optimize()d our file while we were waiting.
if (defined($self->{inode}) && $stats[1] != $self->{inode}) {
$self->close;
lib/DBM/Deep/Storage/File.pm view on Meta::CPAN
#XXX This needs work
$obj->{engine}->setup( $obj );
flock($self->{fh}, $type); # re-lock
# This may not be necessary after re-opening
$self->{end} = (stat($self->{fh}))[7]; # re-end
}
}
$self->{locked}++;
return 1;
}
return;
}
sub unlock {
my $self = shift;
if (!defined($self->{fh})) { return; }
if ($self->{locking} && $self->{locked} > 0) {
$self->{locked}--;
if (!$self->{locked}) {
flock($self->{fh}, LOCK_UN);
return 1;
}
return;
}
return;
}
t/07_locking.t view on Meta::CPAN
use common qw( new_dbm );
use_ok( 'DBM::Deep' );
my $dbm_factory = new_dbm( locking => 1 );
while ( my $dbm_maker = $dbm_factory->() ) {
my $db = $dbm_maker->();
lives_ok {
$db->unlock;
} "Can call unlock on an unlocked DB.";
##
# basic put/get
##
$db->{key1} = "value1";
is( $db->{key1}, "value1", "key1 is set" );
$db->{key2} = [ 1 .. 3 ];
is( $db->{key2}[1], 2, "The value is set properly" );
t/11_optimize.t view on Meta::CPAN
ok( $result, "optimize succeeded" );
cmp_ok( $after, '<', $before, "file size has shrunk" ); # make sure file shrunk
is( $db->{key1}, 'value1', "key1's value is still there after optimize" );
is( $db->{a}{c}, 'value2', "key2's value is still there after optimize" );
$db->_get_self->_engine->storage->close( $db->_get_self );
##
# now for the tricky one -- try to store a new key while file is being
# optimized and locked by another process. filehandle should be invalidated,
# and automatically re-opened transparently. Cannot test on Win32, due to
# problems with fork()ing, flock()ing, etc. Win32 very bad.
##
SKIP: {
skip "Fork tests skipped until fh/filename question solved.", 4;
skip "Fork tests skipped on Win32", 4
if $^O eq 'MSWin32' || $^O eq 'cygwin';
##
utils/lib/DBM/Deep/09830.pm view on Meta::CPAN
# times before unlock(), then the same number of unlocks() must
# be called before the lock is released.
##
my $self = $_[0]->_get_self;
my $type = $_[1];
$type = LOCK_EX unless defined $type;
if (!defined($self->_fh)) { return; }
if ($self->_root->{locking}) {
if (!$self->_root->{locked}) {
flock($self->_fh, $type);
# refresh end counter in case file has changed size
my @stats = stat($self->_root->{file});
$self->_root->{end} = $stats[7];
# double-check file inode, in case another process
# has optimize()d our file while we were waiting.
if ($stats[1] != $self->_root->{inode}) {
$self->_open(); # re-open
flock($self->_fh, $type); # re-lock
$self->_root->{end} = (stat($self->_fh))[7]; # re-end
}
}
$self->_root->{locked}++;
return 1;
}
return;
}
sub unlock {
##
# If db locking is set, unlock the db file. See note in lock()
# regarding calling lock() multiple times.
##
my $self = $_[0]->_get_self;
if (!defined($self->_fh)) { return; }
if ($self->_root->{locking} && $self->_root->{locked} > 0) {
$self->_root->{locked}--;
if (!$self->_root->{locked}) { flock($self->_fh, LOCK_UN); }
return 1;
}
return;
}
sub _copy_value {
my $self = shift->_get_self;
my ($spot, $value) = @_;
utils/lib/DBM/Deep/09830.pm view on Meta::CPAN
file_offset => 0,
end => 0,
autoflush => undef,
locking => undef,
debug => undef,
filter_store_key => undef,
filter_store_value => undef,
filter_fetch_key => undef,
filter_fetch_value => undef,
autobless => undef,
locked => 0,
%$args,
}, $class;
if ( $self->{fh} && !$self->{file_offset} ) {
$self->{file_offset} = tell( $self->{fh} );
}
return $self;
}
utils/lib/DBM/Deep/10002.pm view on Meta::CPAN
my ($args) = @_;
my $self = bless {
autobless => 1,
autoflush => 1,
end => 0,
fh => undef,
file => undef,
file_offset => 0,
locking => 1,
locked => 0,
#XXX Migrate this to the engine, where it really belongs.
filter_store_key => undef,
filter_store_value => undef,
filter_fetch_key => undef,
filter_fetch_value => undef,
}, $class;
# Grab the parameters we want to use
foreach my $param ( keys %$self ) {
next unless exists $args->{$param};
utils/lib/DBM/Deep/10002.pm view on Meta::CPAN
##
sub lock {
my $self = shift;
my ($obj, $type) = @_;
$type = LOCK_EX unless defined $type;
if (!defined($self->{fh})) { return; }
if ($self->{locking}) {
if (!$self->{locked}) {
flock($self->{fh}, $type);
# refresh end counter in case file has changed size
my @stats = stat($self->{fh});
$self->{end} = $stats[7];
# double-check file inode, in case another process
# has optimize()d our file while we were waiting.
if (defined($self->{inode}) && $stats[1] != $self->{inode}) {
$self->close;
utils/lib/DBM/Deep/10002.pm view on Meta::CPAN
#XXX This needs work
$obj->{engine}->setup_fh( $obj );
flock($self->{fh}, $type); # re-lock
# This may not be necessary after re-opening
$self->{end} = (stat($self->{fh}))[7]; # re-end
}
}
$self->{locked}++;
return 1;
}
return;
}
##
# If db locking is set, unlock the db file. See note in lock()
# regarding calling lock() multiple times.
##
sub unlock {
my $self = shift;
if (!defined($self->{fh})) { return; }
if ($self->{locking} && $self->{locked} > 0) {
$self->{locked}--;
if (!$self->{locked}) { flock($self->{fh}, LOCK_UN); }
return 1;
}
return;
}
sub flush {
my $self = shift;