4 |
# Author : Ulrich Pfeifer |
# Author : Ulrich Pfeifer |
5 |
# Created On : Thu Aug 8 13:05:10 1996 |
# Created On : Thu Aug 8 13:05:10 1996 |
6 |
# Last Modified By: Ulrich Pfeifer |
# Last Modified By: Ulrich Pfeifer |
7 |
# Last Modified On: Fri May 19 14:51:14 2000 |
# Last Modified On: Sun Nov 12 15:21:19 2000 |
8 |
# Language : CPerl |
# Language : CPerl |
9 |
# Update Count : 133 |
# Update Count : 135 |
10 |
# Status : Unknown, Use with caution! |
# Status : Unknown, Use with caution! |
11 |
# |
# |
12 |
# Copyright (c) 1996-1997, Ulrich Pfeifer |
# Copyright (c) 1996-1997, Ulrich Pfeifer |
166 |
} |
} |
167 |
|
|
168 |
my $lockmgr = LockFile::Simple->make(-autoclean => 1); |
my $lockmgr = LockFile::Simple->make(-autoclean => 1); |
169 |
# aquire a write lock |
# Aquire a write lock, since we are creating the table, no readers |
170 |
|
# could possibly be active. |
171 |
$self->{write_lock} = $lockmgr->lock($self->{file} . '/write') |
$self->{write_lock} = $lockmgr->lock($self->{file} . '/write') |
172 |
or die "Can't lock '$self->{file}/write'"; |
or die "Can't lock '$self->{file}/write'"; |
173 |
|
|
387 |
# Locking |
# Locking |
388 |
# |
# |
389 |
# We allow multiple readers to coexists. But write access excludes |
# We allow multiple readers to coexists. But write access excludes |
390 |
# all read access vice versa. In practice read access on tables |
# all read access and vice versa. In practice read access on tables |
391 |
# open for writing will mostly work ;-) |
# open for writing will mostly work ;-) |
392 |
|
|
393 |
my $lockmgr = LockFile::Simple->make(-autoclean => 1); |
my $lockmgr = LockFile::Simple->make(-autoclean => 1); |
394 |
|
|
|
# aquire a write lock. We might hold one acquired in create() already |
|
|
$self->{write_lock} ||= $lockmgr->lock($self->{file} . '/write') |
|
|
or die "Can't lock '$self->{file}/write'"; |
|
|
|
|
395 |
my $lockdir = $self->{file} . '/read'; |
my $lockdir = $self->{file} . '/read'; |
396 |
unless (-d $lockdir) { |
unless (-d $lockdir) { |
397 |
mkdir $lockdir, 0755 or die "Could not mkdir $lockdir: $!"; |
mkdir $lockdir, 0755 or die "Could not mkdir $lockdir: $!"; |
398 |
} |
} |
399 |
|
|
400 |
if ($self->{mode} & O_RDWR) { |
if ($self->{mode} & O_RDWR) { |
401 |
|
# Get a write lock. Release it again and die if there is any |
402 |
|
# valid reader. |
403 |
|
|
404 |
# this is a hack. We do not check for reopening ... |
# this is a hack. We do not check for reopening ... |
405 |
return $self if $self->{write_lock}; |
return $self if $self->{write_lock}; |
406 |
|
|
407 |
|
if ($self->{read_lock}) { |
408 |
|
# We are a becoming a writer now. So we release the read lock to |
409 |
|
# avoid blocking ourselves. |
410 |
|
$self->{read_lock}->release; |
411 |
|
delete $self->{read_lock}; |
412 |
|
} |
413 |
|
|
414 |
|
# Get the preliminary write lock |
415 |
|
$self->{write_lock} = $lockmgr->lock($self->{file} . '/write') |
416 |
|
or die "Can't lock '$self->{file}/write'"; |
417 |
|
|
418 |
|
# If we actually want to write we must check if there are any |
419 |
|
# readers. The write lock is confirmed if wen cannot find any |
420 |
|
# valid readers. |
421 |
|
|
|
# If we actually want to write we must check if there are any readers |
|
422 |
local *DIR; |
local *DIR; |
423 |
opendir DIR, $lockdir or |
opendir DIR, $lockdir or |
424 |
die "Could not opendir '$lockdir': $!"; |
die "Could not opendir '$lockdir': $!"; |
425 |
for my $lockfile (grep { -f "$lockdir/$_" } readdir DIR) { |
for my $lockfile (grep { -f "$lockdir/$_" } readdir DIR) { |
426 |
# check if the locks are still valid. |
# check if the locks are still valid. |
427 |
# Since we are protected by a write lock, we could use a pline file. |
# Since we are protected by a write lock, we could use a plain file. |
428 |
# But we want to use the stale testing from LockFile::Simple. |
# But we want to use the stale testing from LockFile::Simple. |
429 |
if (my $lck = $lockmgr->trylock("$lockdir/$lockfile")) { |
if (my $lck = $lockmgr->trylock("$lockdir/$lockfile")) { |
430 |
warn "Removing stale lockfile '$lockdir/$lockfile'"; |
warn "Removing stale lockfile '$lockdir/$lockfile'"; |
438 |
} else { |
} else { |
439 |
# this is a hack. We do not check for reopening ... |
# this is a hack. We do not check for reopening ... |
440 |
return $self if $self->{read_lock}; |
return $self if $self->{read_lock}; |
441 |
|
|
442 |
|
# Get the preliminary write lock to protect the directory |
443 |
|
# operations. |
444 |
|
|
445 |
|
$self->{write_lock} ||= $lockmgr->lock($self->{file} . '/write') |
446 |
|
or die "Can't lock '$self->{file}/write'"; |
447 |
|
|
448 |
# We are a reader. So we release the write lock |
# find a new read slot |
449 |
my $id = time; |
my $id = time; |
450 |
while (-f "$lockdir/$id.lock") { # here assume ".lock" format! |
while (-f "$lockdir/$id.lock") { # here assume ".lock" format! |
451 |
$id++; |
$id++; |
452 |
} |
} |
453 |
$self->{read_lock} = $lockmgr->lock("$lockdir/$id"); |
|
454 |
|
$self->{read_lock} = $lockmgr->lock("$lockdir/$id") |
455 |
|
or die "Can't lock '$lockdir/$id'"; |
456 |
|
|
457 |
|
# We are a reader now. So we release the write lock |
458 |
$self->{write_lock}->release; |
$self->{write_lock}->release; |
459 |
delete $self->{write_lock}; |
delete $self->{write_lock}; |
460 |
} |
} |