Data-Keys
view release on metacpan or search on metacpan
Revision history for Data::Keys
0.04 27 November 2016
* skip testing on windows
0.03 9 October 2016
* fix test expecting english locale errors (#1, thanks Slaven ReziÄ for reporting)
* fix unknown attributes test (#2, thanks Slaven ReziÄ for reporting)
0.02 15 Oct 2010
* avoid deadlocks in lock dir (key will be locked only once)
* pass all self+key+value to key adapt and (in|de)flate
* allow deleting with uniq set
* added Key::AutoLock
0.01 Date/time
First version, released on an unsuspecting world.
lib/Data/Keys/E/Dir/Lock.pm view on Meta::CPAN
sub lock_ex {
my $self = shift;
my $key = shift;
my $lock_key = $key;
$lock_key =~ s{/}{_}g;
my $lock_filename = File::Spec->catfile($self->lock_dir, $lock_key);
$self->_lock_dir_data->{$key}->{'counter'}++;
# return if already locked
return
if ($self->_lock_dir_data->{$key}->{'counter'} != 1);
my $lock_fh;
my $num_tries = 0;
# try to exclusively open the lock the file, if it fails than wait until another process release the LOCK_EX
while (not sysopen($lock_fh, $lock_filename, O_WRONLY | O_EXCL | O_CREAT, 0644)) {
# wait until lock on that file is released
eval {
my $fh = IO::Any->new([$lock_filename], '+>>', { LOCK_EX => 1 });
lib/Data/Keys/E/Dir/Lock.pm view on Meta::CPAN
Release a lock.
=cut
sub unlock {
my $self = shift;
my $key = shift;
if (not $self->_lock_dir_data->{$key}) {
warn 'unlock("'.$key.'") but is is not locked';
return;
};
$self->_lock_dir_data->{$key}->{'counter'}--;
if ($self->_lock_dir_data->{$key}->{'counter'} <= 0) {
# release+delete lock file
unlink delete $self->_lock_dir_data->{$key}->{'filename'};
close delete $self->_lock_dir_data->{$key}->{'fh'};
delete $self->_lock_dir_data->{$key};
t/03_Data-Keys_locking_dir.t view on Meta::CPAN
);
is($ts->get('abcd'), (), 'get non-existing file');
is($ts->set('abcd', 123), 'abcd', 'set');
is_deeply(IO::Any->slurp([$tmp_folder, 'abcd']), 123, 'read the file directly');
TEST_FILE_LOCKING: {
my $lock_filename = File::Spec->catfile($ts->lock_dir, 'abcd');
my $lock_fh = IO::Any->new([$lock_filename], '+>>', { LOCK_EX => 1 });
my $locked = 1;
local $SIG{'ALRM'} = sub {
$locked = 2;
unlink($lock_filename);
close($lock_fh);
};
alarm(1);
is($ts->get('abcd'), 123, 'get (should be blocked)');
is($locked, 2, 'lock released');
$locked = 1;
$lock_fh = IO::Any->new([$lock_filename], '+>>', { LOCK_EX => 1 });
alarm(1);
is($ts->set('abcd', 1234), 'abcd', 'set (should be blocked)');
is($locked, 2, 'lock released');
is($ts->get('abcd'), 1234, 'verify the value');
}
TEST_SEMAPHORE_FILE_UNLINKING: {
my $sem_lock_filename = File::Spec->catfile($tmp_folder, '.lock', '123');
do {
my $ts2 = Data::Keys->new(
'base_dir' => $tmp_folder,
'extend_with' => ['Store::Dir', 'Dir::Lock', 'Locking'],
);
t/03_Data-Keys_locking_inplace.t view on Meta::CPAN
'extend_with' => ['Store::Dir', 'Dir::LockInPlace', 'Locking'],
);
is($ts->get('abcd'), (), 'get non-existing file');
$ts->set('abcd', 123);
is($ts->set('abcd', 123), 'abcd', 'set');
is_deeply(IO::Any->slurp([$tmp_folder, 'abcd']), 123, 'read the file directly');
SHARED_LOCK: {
my $lock_fh = IO::Any->new([$tmp_folder, 'abcd'], '+>>', { LOCK_SH => 1 });
is($ts->get('abcd'), 123, 'get shared locked file is fine');
my $pid = fork(); die 'fork failed' if not defined $pid;
if (not $pid) {
sleep(1);
close($lock_fh);
exit;
}
close($lock_fh);
throws_ok { IO::Any->new([$tmp_folder, 'abcd'], '+>>', { LOCK_EX => 1, LOCK_NB => 1 }) } qr/flock failed/, 'file locked preventing LOCK_EX';
is($ts->set('abcd', 456), 'abcd', 'set (should be blocked)');
lives_ok { IO::Any->new([$tmp_folder, 'abcd'], '+>>', { LOCK_EX => 1, LOCK_NB => 1 }) } 'and unlocked';
}
EXCLUSIVE_LOCK: {
my $lock_fh = IO::Any->new([$tmp_folder, 'abcdx'], '+>>', { LOCK_EX => 1 });
my $pid = fork(); die 'fork failed' if not defined $pid;
if (not $pid) {
sleep(1);
close($lock_fh);
exit;
}
close($lock_fh);
throws_ok { IO::Any->new([$tmp_folder, 'abcdx'], '+>>', { LOCK_SH => 1, LOCK_NB => 1 }) } qr/flock failed/, 'file locked preventing LOCK_SH';;
is($ts->set('abcdx', 456), 'abcdx', 'set (should be blocked)');
lives_ok { IO::Any->new([$tmp_folder, 'abcdx'], '+>>', { LOCK_EX => 1, LOCK_NB => 1 }) } 'and unlocked';
}
return 0;
}
( run in 0.530 second using v1.01-cache-2.11-cpan-49f99fa48dc )