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 readers |
# 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 |
|
|
422 |
|
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'"; |
434 |
die "Cannot write table '$file' while it's in use"; |
die "Cannot write table '$file' while it's in use"; |
435 |
} |
} |
436 |
} |
} |
437 |
|
closedir DIR; |
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 |
} |
} |
635 |
} |
} |
636 |
|
|
637 |
sub unpack { |
sub unpack { |
638 |
my $self = shift; |
my($self, $tuple) = @_; |
639 |
my $tuple = shift; |
|
640 |
return unless defined $tuple; |
unless (defined $tuple){ |
641 |
|
# require Carp; # unfortunately gives us "bizarre copy...." :-((((( |
642 |
|
warn("Debug: somebody called unpack without argument tuple!"); |
643 |
|
return; |
644 |
|
} |
645 |
|
|
646 |
my $att; |
my $att; |
647 |
my @result; |
my @result; |
656 |
sub set { |
sub set { |
657 |
my ($self, $iattr, $value) = @_; |
my ($self, $iattr, $value) = @_; |
658 |
|
|
659 |
unless ($self->{write_lock}) { |
unless ($self->{write_lock}){ |
660 |
die "Cannot set attribute $iattr without having a write lock. Nothing done"; |
warn "Cannot set iattr[$iattr] without write lock. Nothing done"; |
661 |
|
return; |
662 |
} |
} |
663 |
for my $att (keys %{$self->{inverted}}) { |
for my $att (keys %{$self->{inverted}}) { |
664 |
if ($] > 5.003) { # avoid bug in perl up to 5.003_05 |
if ($] > 5.003) { # avoid bug in perl up to 5.003_05 |
680 |
if (exists $self->{'access'}) { |
if (exists $self->{'access'}) { |
681 |
eval {$self->{'access'}->close}; # dont bother if not opened |
eval {$self->{'access'}->close}; # dont bother if not opened |
682 |
} |
} |
683 |
for (values %{$self->{indexes}}) { |
if ($WAIT::Index::VERSION) { |
684 |
require WAIT::Index; |
for (values %{$self->{indexes}}) { |
685 |
$_->close(); |
$_->close(); |
686 |
|
} |
687 |
} |
} |
688 |
if (defined $self->{inverted}) { |
if (defined $self->{inverted} && $WAIT::InvertedIndex::VERSION) { |
689 |
require WAIT::InvertedIndex; |
# require WAIT::InvertedIndex; Uli: we can avoid closing indexes: |
690 |
|
# if WAIT::InvertedIndex has not been loaded, they cannot have |
691 |
|
# been altered so far |
692 |
my $att; |
my $att; |
693 |
for $att (keys %{$self->{inverted}}) { |
for $att (keys %{$self->{inverted}}) { |
694 |
if ($] > 5.003) { # avoid bug in perl up to 5.003_05 |
if ($] > 5.003) { # avoid bug in perl up to 5.003_05 |