roger@mav.com (Roger Droz) (05/07/91)
[Apologies if I'm bugging the net about a long-since fixed problem. I
have a perfectly good Perl 4.0 tar that I've been too busy to unpack...]
Gdbm permits only one writer to a database, so perl programs need to
close databases before requesting input in order to permit concurrent
access to other users.
As a general solution, I wrapped dbmopen in the following perl
subroutine to wait with a timeout for the database to be available.
Sometimes the database would be corrupted when a perl program opened a
database with subroutine wait_dbmopen and closed it with dbmclose
several times:
$foodata{'?'}; # make sure array is defined before passing reference.
.
.
.
&wait_dbmopen(*foodata, "filename", 0444) || die "Can't open.";
.
.
.
dbmclose(foodata);
.
.
.
&wait_dbmopen(*foodata, "filename", 0444);
.
.
.
dbmclose(foodata); # This sometimes corrupts the gdm file.
Issuing another dummy operation on the array before each call to
wait_dbmopen seems to have fixed the problem, but I'd like to ask the
perl wizzards why.
I really do intend to install a later version of perl some day.
Meanwhile, this is either a long fixed bug or more probably yet
another interesting caveat (misunderstanding) of using the *name
production...
$Header: perly.c,v 3.0.1.5 90/03/27 16:20:57 lwall Locked $
Patch level: 18
;#** Header3 *****************************************************
;# Routine: wait_dbmopen(*array, $file, $mode, $quiet) Author: RLD
;# DESCRIPTION
;# Open a dbm database file, waiting if necessary to
;# obtain the requested permissions. (Use regular dbmclose to close
;# the database.)
;#
;# Note: perl only permits one instance of an open database at a time,
;# despite gdbm's ability to have multiple readers.
;#
;# Entry:
;# *array = an associative array to be bound to the keyfile, as in
;# dbmopen.
;# $file = filename, suitable for dbmopen.
;# $mode = open mode.
;# $quiet = a boolean telling the routine to wait quietly. This
;# suppresses "waiting" messages from appearing on STDERR.
;# Exit:
;# boolean value indicating success.
;#** EndHeader **************************************************
sub wait_dbmopen {
local(*array, $file, $mode, $quiet) = @_;
local($proceed) = 0;
local($cnt) = 0;
local($dbmname) = $file . '.pag';
if ( -f $dbmname ) {
$! = 0;
do {
$proceed = dbmopen(array, $file, $mode);
unless ($proceed) {
unless ($quiet) {
printf STDERR "\rWaiting %d seconds to open %s (Err: %d)\r", $cnt, $file, $!;
}
sleep 5;
$cnt += 5;
}
} until ($proceed || $cnt > 3600);
print STDERR "\r", (' ' x 75), "\r" if (!$quiet && $cnt > 0);
} else {
$proceed = dbmopen(array, $file, $mode);
}
$proceed;
}
____________
Roger Droz Domain: roger@mav.COM
() () Maverick International UUCP: uw-beaver!gtisqr!roger
(_______) Mukilteo, WA
( )
| | Disclaimer: "We're all mavericks here:
| | Each of us has our own opinions,
(___) and the company has yet different ones!"