[prev in list] [next in list] [prev in thread] [next in thread] 

List:       fink-commits
Subject:    fink/perlmod/Fink ChangeLog,1.1180,1.1181 Engine.pm,1.336,1.337 Package.pm,1.163,1.164 PkgVersion.pm
From:       Daniel Macks <dmacks () users ! sourceforge ! net>
Date:       2005-10-31 20:32:36
Message-ID: E1EWgKf-0000c0-Nw () mail ! sourceforge ! net
[Download RAW message or body]

Update of /cvsroot/fink/fink/perlmod/Fink
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20326

Modified Files:
	ChangeLog Engine.pm Package.pm PkgVersion.pm 
Log Message:
Yet Another rewrite of buildlock mechanism, this time using
semi-autonomous lockpkg interlocking.


Index: PkgVersion.pm
===================================================================
RCS file: /cvsroot/fink/fink/perlmod/Fink/PkgVersion.pm,v
retrieving revision 1.488
retrieving revision 1.489
diff -u -d -r1.488 -r1.489
--- PkgVersion.pm	25 Oct 2005 22:08:16 -0000	1.488
+++ PkgVersion.pm	31 Oct 2005 20:32:34 -0000	1.489
@@ -4116,29 +4116,36 @@
 		return $self->get_parent->set_buildlock();
 	}
 
+	# bootstrapping occurs before we have package-management tools
+	# needed for buildlocking. If you're bootstrapping into a location
+	# that already has a running fink, you already know you're gonne
+	# hose whatever may be running under that fink...
+	return if $self->{_bootstrap};
+
+	# The plan: get an exlusive lock for %n-%v-%r_$timestamp that
+	# automatically goes away when this fink process quit. Install a
+	# %n-%v-%r package that prohibits removal of itself if that lock
+	# is present.  It's always safe to attempt to remove all installed
+	# buildlock pkgs since they can each determine if these locks are
+	# dead.  Attempting to install a lockpkg for the same %n-%v-%r
+	# will cause existing one to attempt to be removed, which will
+	# fail iff its lock is still alive. Fallback to the newer pkg's
+	# prerm is okay because that will also be blocked by its own live
+	# lock.
+
 	print "Setting runtime build-lock...\n";
 
-	# get an exlusive lock for the the %n-%v-%r
-	Fink::Package->control_buildlocks(1);
 	my $lockdir = "$basepath/var/run/fink/buildlock";
 	mkdir_p $lockdir or
 		die "can't create $lockdir directory for buildlocks\n";
-	my $lockfile = $lockdir . '/' . $self->get_fullname() . '.lock';
-	my $lock_FH = lock_wait($lockfile, exclusive => 1);
 
-	$self->{_lockfile} = [ $lockfile, $lock_FH ];
-
-	# bootstrapping occurs before we have package-management tools
-	# needed for buildlock package so don't create one
-	if ($self->{_bootstrap}) {
-		Fink::Package->control_buildlocks(0);
-		return;
-	}
+	my $timestamp = strftime "%Y.%m.%d-%H.%M.%S", localtime;
+	my $lockfile = $lockdir . '/' . $self->get_fullname() . "_$timestamp.lock";
+	my $lock_FH = lock_wait($lockfile, exclusive => 1);
 
 	my $pkgname = $self->get_name();
 	my $pkgvers = $self->get_fullversion();
 	my $lockpkg = 'fink-buildlock-' . $self->get_fullname();
-	my $timestamp = strftime "%Y.%m.%d-%H.%M.%S", localtime;
 
 	my $destdir = $self->get_install_directory($lockpkg);
 
@@ -4167,7 +4174,6 @@
  Maintainer: Fink Core Group <fink-core\@lists.sourceforge.net>
 Maintainer: Fink Core Group <fink-core\@lists.sourceforge.net>
 Provides: fink-buildlock
-Essential: yes
 EOF
 
 	# buildtime (anti)dependencies of pkg are runtime (anti)dependencies of lockpkg
@@ -4182,9 +4188,40 @@
 	}
 
 	### write "control" file
-	open(CONTROL,">$destdir/DEBIAN/control") or die "can't write control file for \
                $lockpkg: $!\n";
-	print CONTROL $control;
-	close(CONTROL) or die "can't write control file for $lockpkg: $!\n";
+	if (open my $controlfh, '>', "$destdir/DEBIAN/control") {
+		print $controlfh $control;
+		close $controlfh or die "can't write control file for $lockpkg: $!\n";
+	} else {
+		die "can't write control file for $lockpkg: $!\n";
+	}
+
+	### set up the lockfile interlocking
+
+	# this is implemented in perl but PreRm is in bash so we gonna in-line it
+	my $prerm = <<EOF;
+#!/bin/bash -e
+
+if perl -Mlib=$basepath/lib/perl5 -MFink::Services=lock_wait -e \
'lock_wait("$lockfile", exclusive => 1, no_block => 1) ? exit 0 : exit 1' ; then +  \
rm -f $lockfile +  exit 0
+else
+  cat <<EOMSG
+There is currently an active buildlock for the package
+     $pkgname ($pkgvers)
+meaning some other fink process is currently building it.
+EOMSG
+  exit 1
+fi
+EOF
+
+	### write prerm file
+	if (open my $prermfh, '>', "$destdir/DEBIAN/prerm") {
+		print $prermfh $prerm;
+		close $prermfh or die "can't write PreRm file for $lockpkg: $!\n";
+		chmod 0755, "$destdir/DEBIAN/prerm";
+	} else {
+		die "can't write PreRm file for $lockpkg: $!\n";
+	}
 
 	### store our PID in a file in the buildlock package
 	my $deb_piddir = "$destdir$lockdir";
@@ -4210,7 +4247,7 @@
 						"the directory manually to save disk space. ".
 						"Continuing with normal procedure.");
 
-	# install lockpkg (== set lockfile for building ourself)
+	# install lockpkg (== set dpkg lock on our deps)
 	print "Installing build-lock package...\n";
 	my $debfile = $buildpath.'/'.$lockpkg.'_'.$timestamp.'_'.$debarch.'.deb';
 	my $lock_failed = &execute(dpkg_lockwait() . " -i $debfile", ignore_INT=>1);
@@ -4237,7 +4274,9 @@
 
 		# Failure due to depenendecy problems leaves lockpkg in an
 		# "unpacked" state, so try to remove it entirely.
-		&execute(dpkg_lockwait() . " --force-remove-essential -r $lockpkg 2>/dev/null", \
ignore_INT=>1); +		unlink $lockfile;
+		close $lock_FH;
+		&execute(dpkg_lockwait() . " -r $lockpkg", ignore_INT=>1);
 	}
 
 	# Even if installation fails, no reason to keep this around
@@ -4250,10 +4289,12 @@
 
 	die "buildlock failure\n" if $lock_failed;
 
-	Fink::Package->control_buildlocks(0);
-
 	# record buildlock package name so we can remove it during clear_buildkock
-	$self->{_lockpkg} = $lockpkg;
+	$self->{_buildlock} = {
+		lockfile => $lockfile,
+		lock_FH  => $lock_FH,
+		lockpkg  => $lockpkg
+	};
 }
 
 # remove the lock created by set_buildlock
@@ -4267,13 +4308,16 @@
 		return $self->get_parent->clear_buildlock();
 	}
 
-	Fink::Package->control_buildlocks(0);
+	if (exists $self->{_buildlock}) {
+		# we were locked...
+		print "Removing runtime build-lock...\n";
+		close $self->{_buildlock}->{lock_FH};
 
-	if (exists $self->{_lockpkg}) {
 		print "Removing build-lock package...\n";
-		my $lockpkg = $self->{_lockpkg};
+		my $lockpkg = $self->{_buildlock}->{lockpkg};
 
-		if (&execute(dpkg_lockwait() . " --force-remove-essential -r $lockpkg \
2>/dev/null", ignore_INT=>1)) { +		# lockpkg's prerm deletes the lockfile
+		if (&execute(dpkg_lockwait() . " -r $lockpkg", ignore_INT=>1)) {
 			&print_breaking("WARNING: Can't remove package ".
 							"$lockpkg. ".
 							"This is not fatal, but you may want to remove ".
@@ -4282,17 +4326,8 @@
 							"Continuing with normal procedure.");
 		}
 		Fink::PkgVersion->dpkg_changed;
-		delete $self->{_lockpkg};
-	}
-
-	if (exists $self->{_lockfile}) {
-		print "Removing runtime build-lock...\n";
-		close $self->{_lockfile}->[1];
-		unlink $self->{_lockfile}->[0];  # try to clean up
-		delete $self->{_lockfile};
+		delete $self->{_buildlock};
 	}
-
-	Fink::Package->control_buildlocks(0);
 }
 
 =item ensure_gpp_prefix

Index: Package.pm
===================================================================
RCS file: /cvsroot/fink/fink/perlmod/Fink/Package.pm,v
retrieving revision 1.163
retrieving revision 1.164
diff -u -d -r1.163 -r1.164
--- Package.pm	12 Oct 2005 05:31:47 -0000	1.163
+++ Package.pm	31 Oct 2005 20:32:34 -0000	1.164
@@ -1240,38 +1240,6 @@
 	}
 }
 
-=item control_buildlocks
-
-	Fink::Package->control_buildlocks(1);
-	# add or remove buildlocks
-	Fink::Package->control_buildlocks(0);
-
-When called with a boolean "true" value, get an exclusive lock on the
-buildlock system. When called with a boolean "false" value, release
-this exclusive lock. You must have this exclusive lock whenever you
-will be setting or clearing buildlocks (or if you want to prevent
-other fink processes from doing so for any reason).
-
-=cut
-
-sub control_buildlocks {
-	my $class = shift;
-	my $lock = shift || 0;
-
-	if ($lock) {
-		if (!defined $buildlock_master) {
-			# no use relocking if we already own the lock
-			my $lockdir = "$basepath/var/run/fink/buildlock";
-			mkdir_p $lockdir or
-				die "can't create $lockdir directory for master buildlock\n";
-			my $lockfile = "$lockdir/MASTER_LOCK";
-			$buildlock_master = lock_wait($lockfile, exclusive => 1);
-		}
-	} else {
-		undef $buildlock_master;
-	}
-}
-
 =back
 
 =cut

Index: Engine.pm
===================================================================
RCS file: /cvsroot/fink/fink/perlmod/Fink/Engine.pm,v
retrieving revision 1.336
retrieving revision 1.337
diff -u -d -r1.336 -r1.337
--- Engine.pm	21 Oct 2005 19:27:54 -0000	1.336
+++ Engine.pm	31 Oct 2005 20:32:34 -0000	1.337
@@ -1336,17 +1336,16 @@
 
 =item cleanup_buildlocks
 
-Check for all processes corresponding to each buildlock pid-file.
-Optionally remove those buildlocks whose processes do not
-exist. Returns a boolean indicating whether there any active
-buildlocks are still present after cleanup. The following option is
-known:
+Search for all present lockfiles and all installed lockpkgs Optionally
+have lockpkgs remove themselves and nuke unlocked lockfiles. Returns a
+boolean indicating whether there any active buildlocks are still
+present after cleanup. The following option is known:
 
 =over 4
 
 =item dryrun
 
-If true, don't actually remove the locks.
+If true, don't actually remove things.
 
 =back
 
@@ -1355,68 +1354,74 @@
 sub cleanup_buildlocks {
 	my %opts = (dryrun => 0, @_);
 
-	Fink::Package->control_buildlocks(1);
-
-	print "Reading buildlocks...\n";
 	my $lockdir = "$basepath/var/run/fink/buildlock";
+	my @locks;
+	my $locks_left = 0;  # return value (set to 1 if an error occurs)
 
-	my @lockfiles = ();
+	print "Reading buildlock packages...\n";
+	@locks = ();
 	if (opendir my $dirhandle, $lockdir) {
-		@lockfiles = grep { /^.+\.lock$/ } readdir $dirhandle;
+		@locks = readdir $dirhandle;
 		close $dirhandle;
 	} else {
 		print "Warning: could not read buildlock directory $lockdir: $!\n";
-		Fink::Package->control_buildlocks(0);
-		return 0;
+		$locks_left = 1;
 	}
+	# lock packages are named fink-buildlock-%n-%v-%r and install %n-%v-%r.pid
+	@locks = grep { s/(.+)\.pid$/fink-buildlock-$1/ } @locks;
 
-	if (!@lockfiles) {
-		print "No buildlocks found\n";
-		Fink::Package->control_buildlocks(0);
-		return 0;
+	if ($opts{dryrun}) {
+		print map "\t$_\n", @locks;
+	} else {
+		print map "\t$_... will remove\n", @locks;
 	}
 
-	my $locks_left = 0;
-	my %lock_FHs = ();
-	my @lock_pkgs = ();
-	foreach my $lockfile (sort @lockfiles) {
-		my ($fullname) = $lockfile =~ /^(.+)\.lock$/;
+	if (@locks) {
+		if ($opts{dryrun}) {
+			$locks_left = 1;
+		} else {
+			if (&execute(dpkg_lockwait() . " -r @locks", ignore_INT=>1)) {
+				print "Warning: could not remove all buildlock packages!\n";
+				$locks_left = 1;
+			}
+			Fink::PkgVersion->dpkg_changed;
+		}
+	}
+
+	print "Reading buildlock lockfiles...\n";
+	@locks = ();
+	if (opendir my $dirhandle, $lockdir) {
+		@locks = readdir $dirhandle;
+		close $dirhandle;
+	} else {
+		print "Warning: could not read buildlock directory $lockdir: $!\n";
+		$locks_left = 1;
+	}
+	# lock lockfiles are named %n-%v-%r_$timestamp.lock
+	@locks = grep { /\.lock$/ } @locks;
+
+	foreach my $lockfile (@locks) {
+		printf "\t$lockfile";
 		my $lock_FH = lock_wait("$lockdir/$lockfile", exclusive => 1, no_block => 1);
 		if ($lock_FH) {
 			# got flock so buildlock is not in use
-			if ($opts{dryrun}) {
-				print "Runtime buildlock for $fullname is dead.\n";
+			print "... dead";
+			if (not $opts{dryrun}) {
+				print "... deleting";
+				if (not unlink "$lockdir/$lockfile") {
+					print "... failed";
+					$locks_left = 1;
+				}
 			} else {
-				print "Runtime buildlock for $fullname is dead...will clear.\n";
-				$lock_FHs{"$lockdir/$lockfile"} = $lock_FH;
-			}
-			if (-e "$lockdir/$fullname.pid") {
-				print "...and its lock package too.\n";
-				push @lock_pkgs, "fink-buildlock-$fullname" if !$opts{dryrun};
+				$locks_left = 1;
 			}
+			print "\n";
 		} else {
-			print "Buildlock for $fullname is still in use.\n";
-			$locks_left = 1;
-		}
-	}
-
-	if (@lock_pkgs) {
-		printf "Removing %i dead buildlock package(s)...\n", scalar @lock_pkgs;
-		if (&execute(dpkg_lockwait() . " --force-remove-essential -r @lock_pkgs \
                2>/dev/null", ignore_INT=>1)) {
-			print "Warning: could not remove all buildlock packages!\n";
+			print "... still in use\n";
 			$locks_left = 1;
 		}
-		Fink::PkgVersion->dpkg_changed;
-	}
-
-	if (%lock_FHs) {
-		printf "Removing %i dead lockfile(s)...\n", scalar keys %lock_FHs;
-		rm_f keys %lock_FHs or $locks_left = 1;
-		%lock_FHs = ();
 	}
 
-	Fink::Package->control_buildlocks(0);
-
 	return $locks_left;
 }
 

Index: ChangeLog
===================================================================
RCS file: /cvsroot/fink/fink/perlmod/Fink/ChangeLog,v
retrieving revision 1.1180
retrieving revision 1.1181
diff -u -d -r1.1180 -r1.1181
--- ChangeLog	27 Oct 2005 12:17:24 -0000	1.1180
+++ ChangeLog	31 Oct 2005 20:32:34 -0000	1.1181
@@ -1,3 +1,11 @@
+2005-10-31  Daniel Macks  <dmacks@netspace.org>
+
+	* PkgVersion.pm: overhaul buildlocks again. Now we set/unset lock
+	on a timestamped lockfile before installing/removing lockpkg;
+	lockpkg prerm fails if lockfile is locked.
+	* Engine.pm: Rewrite cleanup_buildlocks for new implementation.
+	* Package.pm: Remove no-longer-needed control_buildlocks.
+	
 2005-10-27  Benjamin Reed  <rangerrick@users.sourceforge.net>
 
 	* VirtPackage.pm: added proper URL for JavaAI and Java3D



-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.
Get Certified Today * Register for a JBoss Training Course
Free Certification Exam for All Training Attendees Through End of 2005
Visit http://www.jboss.com/services/certification for more information
_______________________________________________
Fink-commits mailing list
Fink-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/fink-commits


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic