Update of /cvsroot/fink/fink/perlmod/Fink
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32234/perlmod/Fink
Modified Files:
ChangeLog Package.pm Services.pm
Log Message:
new multi-dir finkinfodb system
Index: Services.pm
===================================================================
RCS file: /cvsroot/fink/fink/perlmod/Fink/Services.pm,v
retrieving revision 1.163
retrieving revision 1.164
diff -u -d -r1.163 -r1.164
--- Services.pm 28 Apr 2005 05:00:44 -0000 1.163
+++ Services.pm 28 Apr 2005 05:27:01 -0000 1.164
@@ -1486,6 +1486,11 @@
A description of the process that the lock is synchronizing. This is used in
messages printed by this function, eg: "Waiting for $desc to finish".
+=item no_block => $no_block
+
+If present and true, lock_wait will forget the 'wait' part of its name. If the
+lock cannot be acquired immediately, failure will be returned.
+
=back
=cut
@@ -1494,28 +1499,31 @@
my $lockfile = shift;
my %options = @_;
- my $write = $options{exclusive} || 0;
+ my $exclusive = $options{exclusive} || 0;
my $timeout = exists $options{timeout} ? $options{timeout} : 300;
$timeout = $options{root_timeout} if exists $options{root_timeout};
my $root_timeout = $options{root_timeout} || 0;
my $quiet = $options{quiet} || 0;
my $desc = $options{desc} || "another process";
+ my $no_block = $options{no_block} || 0;
my $really_timeout = $> != 0 || $root_timeout;
# Make sure we can access the lock
my $lockfile_FH = Symbol::gensym();
{
- my $mode = $write ? "+>>" : "<";
+ my $mode = ($exclusive || ! -e $lockfile) ? "+>>" : "<";
unless (open $lockfile_FH, "$mode $lockfile") {
return wantarray ? (0, 0) : 0;
}
}
- my $mode = $write ? LOCK_EX : LOCK_SH;
+ my $mode = $exclusive ? LOCK_EX : LOCK_SH;
if (flock $lockfile_FH, $mode | LOCK_NB) {
return wantarray ? ($lockfile_FH, 0) : $lockfile_FH;
} else {
+ return (wantarray ? (0, 0) : 0) if $no_block;
+
# Couldn't get lock, meaning process has it
my $waittime = $really_timeout ? "$timeout seconds " : "";
print STDERR "Waiting ${waittime}for $desc to finish..."
Index: Package.pm
===================================================================
RCS file: /cvsroot/fink/fink/perlmod/Fink/Package.pm,v
retrieving revision 1.135
retrieving revision 1.136
diff -u -d -r1.135 -r1.136
--- Package.pm 28 Apr 2005 01:19:07 -0000 1.135
+++ Package.pm 28 Apr 2005 05:27:01 -0000 1.136
@@ -412,19 +412,129 @@
}
+=private comment
+
+When Fink uses a DB dir, it needs continued access to what's inside (since it
+likely is using 'backed' PkgVersions). So when the DB is invalidated, we can't
+just delete it.
+
+Instead, we mark it as 'old' by creating a brand new DB dir. These dirs all
+look like 'db.#', eg: db.1234, and the one that has the largest # is the
+current one.
+
+But how do we ever delete a DB dir? Each Fink gets a shared lock on its DB
+dir; then if a DB dir is old and has no shared locks, it's no longer in use
+and can be deleted.
+
+=item check_dbdirs
+
+ my ($path, $fh) = Fink::Package->check_dbdirs $write, $force_create;
+
+Process the DB dirs. Returns the good directory found/created, and the lock
+already acquired.
+
+If $write is true, will create a new directory if one does not exist, and will
+delete any old dirs.
+
+If $force_create is true, will always create a new directory (invalidating any
+previous PDB dirs).
+
+=cut
+
+sub check_dbdirs {
+ my ($class, $write, $force_create) = @_;
+
+ # This directory holds multiple 'db.#' dirs
+ my $multidir = "$dbpath/finkinfodb";
+
+ # Special case: If the file "$multidir/invalidate" exists, it means
+ # a shell script wants us to invalidate the DB
+ my $inval = "$multidir/invalidate";
+ if (-e $inval) {
+ $force_create = 1;
+ rm_f($inval) if $write;
+ }
+
+ # Get the db.# numbers in high-to-low order.
+ my @nums;
+ if (opendir MULTI, $multidir) {
+ @nums = sort { $b <=> $a} map { /^db\.(\d+)$/ ? $1 : () }
readdir MULTI;
+ }
+ # Find a number higher than all existing, for new dir
+ my $higher = @nums ? $nums[0] + 1 : 1;
+ my $newdir = "$multidir/db.$higher";
+
+ # Get the current dir
+ my @dirs = grep { -d $_ } map { "$multidir/db.$_" } @nums;
+ my $use_existing = !$force_create && @dirs;
+ my ($current, $fh);
+
+ # Try to lock on an existing dir, if applicable
+ if ($use_existing) {
+ $current = $dirs[0];
+ $fh = lock_wait("$current.lock", exclusive => 0, no_block => 1);
+ # Failure ok, will try a new dir
+ }
+
+ # Use and lock a new dir, if needed
+ if (!$fh) {
+ $current = $newdir;
+ if ($write) { # If non-write, it's just a fake new dir
+ mkdir_p($multidir) unless -d $multidir;
+ $fh = lock_wait("$current.lock", exclusive => 0,
no_block => 1)
+ or die "Can't make new DB dir $current: $!\n";
+ mkdir_p($current);
+ }
+ }
+
+ # Try to delete old dirs
+ my @old = grep { $_ ne $current } @dirs;
+ if ($write) {
+ for my $dir (@old) {
+ if (my $fh = lock_wait("$dir.lock", exclusive => 1,
no_block => 1)) {
+ rm_rf($dir);
+ close $fh;
+ }
+ }
+ }
+
+ return ($current, $fh);
+}
+
=item db_dir
- my $path = Fink::Package->db_dir;
-
+ my $path = Fink::Package->db_dir $write;
+
Get the path to the directory that can store the Fink cached package database.
+Creates it if it does not exist and $write is true.
+
+=item forget_db_dir
+
+ Fink::Package->forget_db_dir;
+
+Forget the current DB directory.
=cut
-sub db_dir {
- my $class = shift;
- return "$dbpath/finkinfodb";
-}
+{
+ my $cache_db_dir = undef;
+ my $cache_db_dir_fh = undef;
+ sub db_dir {
+ my $class = shift;
+ my $write = shift || 0;
+
+ unless (defined $cache_db_dir) {
+ ($cache_db_dir, $cache_db_dir_fh) =
$class->check_dbdirs($write, 0);
+ }
+ return $cache_db_dir;
+ }
+
+ sub forget_db_dir {
+ close $cache_db_dir_fh if $cache_db_dir_fh;
+ ($cache_db_dir, $cache_db_dir_fh) = (undef, undef);
+ }
+}
=item db_index
@@ -532,7 +642,11 @@
if (!$just_memory && $> == 0) { # Only if we're root
my $lock = lock_wait($class->db_lockfile, exclusive =>
1,
desc => "another Fink's indexing");
- rm_rf($class->db_dir);
+
+ # Create a new DB dir (possibly deleting the old one)
+ $class->forget_db_dir();
+ $class->check_dbdirs(1, 1);
+
rm_f($class->db_index);
rm_f($class->db_infolist);
close $lock if $lock;
@@ -645,7 +759,7 @@
my %new_idx = (
inits => { map { $_->get_fullname => $_->get_init_fields } @pvs
},
- cache => $cache
+ cache => $cache,
);
return ($idx->{infos}{$info} = \%new_idx);
@@ -859,8 +973,7 @@
}
# Get the cache dir
- my $dbdir = $class->db_dir;
- mkdir_p($dbdir) if $ops{write} && !-d $dbdir;
+ my $dbdir = $class->db_dir($ops{write});
# Load the index
my $idx = { infos => { }, next => 1 };
Index: ChangeLog
===================================================================
RCS file: /cvsroot/fink/fink/perlmod/Fink/ChangeLog,v
retrieving revision 1.984
retrieving revision 1.985
diff -u -d -r1.984 -r1.985
--- ChangeLog 28 Apr 2005 05:00:38 -0000 1.984
+++ ChangeLog 28 Apr 2005 05:27:01 -0000 1.985
@@ -1,3 +1,9 @@
+2005-04-28 Dave Vasilevsky <[EMAIL PROTECTED]>
+
+ * Services.pm: Add no_block (non-blocking) ability to lock_wait.
+ * Package.pm: Use multi-dir finkinfodb system to avoid accidentally
+ deleting another Fink's DB.
+
2005-04-27 Dave Vasilevsky <[EMAIL PROTECTED]>
* Services.pm: New lockwait_executable (with better PATH
-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start! http://www.idcswdc.com/cgi-bin/survey?id=105hix
_______________________________________________
Fink-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/fink-commits