From 58c4003c40a63ce57cc587b4651926c3a34c3632 Mon Sep 17 00:00:00 2001 From: Pascal Rigaux Date: Sat, 11 Aug 2007 11:40:43 +0000 Subject: - all tools o new option --wait-lock (#13025) --- NEWS | 3 +++ pod/urpme.8.pod | 4 ++++ pod/urpmf.8.pod | 4 ++++ pod/urpmi.8.pod | 4 ++++ pod/urpmi.addmedia.8.pod | 4 ++++ pod/urpmi.removemedia.8.pod | 4 ++++ pod/urpmi.update.8.pod | 4 ++++ pod/urpmq.8.pod | 4 ++++ urpm/args.pm | 4 ++++ urpm/lock.pm | 43 ++++++++++++++++++++----------------------- urpm/media.pm | 9 +++++---- urpme | 2 +- urpmf | 2 +- urpmi | 4 ++-- urpmi.addmedia | 2 +- urpmi.bash-completion | 2 +- urpmi.removemedia | 2 +- urpmi.update | 2 +- urpmq | 4 ++-- 19 files changed, 70 insertions(+), 37 deletions(-) diff --git a/NEWS b/NEWS index 8f9bc008..6aa466f2 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,6 @@ +- all tools + o new option --wait-lock (#13025) + Version 4.9.30 - 10 August 2007, by Pascal "Pixel" Rigaux - urpmi (thanks to Thierry Vignaud) diff --git a/pod/urpme.8.pod b/pod/urpme.8.pod index e793ec1c..0fa32dcc 100644 --- a/pod/urpme.8.pod +++ b/pod/urpme.8.pod @@ -94,6 +94,10 @@ Use synthesis file (to use with --use-distrib). Use hdlist file (to use with --use-distrib). +=item B<--wait-lock> + +If the urpmi or rpm db is busy, wait until it is available + =back =head1 FILES diff --git a/pod/urpmf.8.pod b/pod/urpmf.8.pod index 897aeabc..f69d375d 100644 --- a/pod/urpmf.8.pod +++ b/pod/urpmf.8.pod @@ -87,6 +87,10 @@ to B<--root>, the urpmi configuration comes from the rooted tree. Verbose mode. urpmf will emit various messages related to the parsing of hdlist files for your media. +=item B<--wait-lock> + +If the urpmi or rpm db is busy, wait until it is available + =item B<-i> Ignore case distinctions in the patterns that follow. diff --git a/pod/urpmi.8.pod b/pod/urpmi.8.pod index 33476963..1d48c47f 100644 --- a/pod/urpmi.8.pod +++ b/pod/urpmi.8.pod @@ -364,6 +364,10 @@ When several packages are found, propose more choices than the default. Don't lock urpmi and rpm db. This can be useful in conjunction with B<--root>. +=item B<--wait-lock> + +If the urpmi or rpm db is busy, wait until it is available + =item B<--strict-arch> Upgrade only packages if the newer version has the same architecture as diff --git a/pod/urpmi.addmedia.8.pod b/pod/urpmi.addmedia.8.pod index 63d95ff6..8b551efb 100644 --- a/pod/urpmi.addmedia.8.pod +++ b/pod/urpmi.addmedia.8.pod @@ -156,6 +156,10 @@ on distributions. Use the file system tree rooted for urpmi database and rpm install. Contrary to B<--root>, the urpmi configuration comes from the rooted tree. +=item B<--wait-lock> + +If the urpmi or rpm db is busy, wait until it is available + =item B<--from> I Use specified URL for list of mirrors. The default is taken from the file diff --git a/pod/urpmi.removemedia.8.pod b/pod/urpmi.removemedia.8.pod index 66ddbb45..d77cba78 100644 --- a/pod/urpmi.removemedia.8.pod +++ b/pod/urpmi.removemedia.8.pod @@ -41,6 +41,10 @@ Be quiet. Use the file system tree rooted for urpmi database and rpm install. Contrary to B<--root>, the urpmi configuration comes from the rooted tree. +=item B<--wait-lock> + +If the urpmi or rpm db is busy, wait until it is available + =back =head1 SEE ALSO diff --git a/pod/urpmi.update.8.pod b/pod/urpmi.update.8.pod index 6df86130..a6434fc0 100644 --- a/pod/urpmi.update.8.pod +++ b/pod/urpmi.update.8.pod @@ -48,6 +48,10 @@ username and a password. Use the file system tree rooted for urpmi database and rpm install. Contrary to B<--root>, the urpmi configuration comes from the rooted tree. +=item B<--wait-lock> + +If the urpmi or rpm db is busy, wait until it is available + =item B<--update> Use only update media. diff --git a/pod/urpmq.8.pod b/pod/urpmq.8.pod index c1904f07..6557cd17 100644 --- a/pod/urpmq.8.pod +++ b/pod/urpmq.8.pod @@ -186,6 +186,10 @@ Use hdlist file (to use with --use-distrib). Use a different environment directly from a bug report to replay a bug. The argument is the same argument given to B<--bug> option. +=item B<--wait-lock> + +If the urpmi or rpm db is busy, wait until it is available + =item B<--changelog> Prints the package changelog. diff --git a/urpm/args.pm b/urpm/args.pm index 68feea57..b5694863 100644 --- a/urpm/args.pm +++ b/urpm/args.pm @@ -52,6 +52,7 @@ my %options_spec_all = ( 'q|quiet' => sub { --$options{verbose} }, 'v|verbose' => sub { ++$options{verbose} }, 'urpmi-root=s' => sub { urpm::set_files($urpm, $_[1]) }, + 'wait-lock' => \$options{wait_lock}, 'use-copied-hdlist' => sub { $urpm->{options}{use_copied_hdlist} = 1 }, ); @@ -422,6 +423,9 @@ sub parse_cmdline { if ($options{probe_with} && $options{probe_with} eq 'rpms' && $options{virtual}) { die N("Can't use %s with %s", "--probe-rpms", "--virtual"); } + if ($options{nolock} && $options{wait_lock}) { + warn N("Can't use %s with %s", "--wait-lock", "--nolock") . "\n"; + } if ($tool eq 'urpmf' && @ARGV && $ARGV[0] eq '--') { if (@ARGV == 2) { my $p = $ARGV[1]; diff --git a/urpm/lock.pm b/urpm/lock.pm index 0b9cf7f7..dbd237ba 100644 --- a/urpm/lock.pm +++ b/urpm/lock.pm @@ -15,22 +15,25 @@ my ($LOCK_SH, $LOCK_EX, $LOCK_NB, $LOCK_UN) = (1, 2, 4, 8); #- lock policy concerning chroot : # - lock rpm db in chroot # - lock urpmi db in / +# (options: nofatal, wait) sub rpm_db { - my ($urpm, $b_exclusive) = @_; + my ($urpm, $b_exclusive, %options) = @_; my $f = ($urpm->{root} && !$urpm->{urpmi_root} ? "$urpm->{root}/" : '') . "$urpm->{statedir}/.RPMLOCK"; - urpm::lock->new($urpm, $f, 'rpm', $b_exclusive); + urpm::lock->new($urpm, $f, 'rpm', $b_exclusive, %options); } +# (options: nofatal, wait) sub urpmi_db { - my ($urpm, $b_exclusive, $b_nofatal) = @_; - urpm::lock->new($urpm, "$urpm->{statedir}/.LOCK", 'urpmi', $b_exclusive, $b_nofatal); + my ($urpm, $b_exclusive, %options) = @_; + urpm::lock->new($urpm, "$urpm->{statedir}/.LOCK", 'urpmi', $b_exclusive, %options); } ################################################################################ #- methods +# (options: nofatal, wait) sub new { - my ($_class, $urpm, $file, $db_name, $b_exclusive, $b_nofatal) = @_; + my ($_class, $urpm, $file, $db_name, $b_exclusive, %options) = @_; my $fh; #- we don't care what the mode is. ">" allow creating the file, but can't be done as user @@ -38,40 +41,34 @@ sub new { my $lock = bless { fh => $fh, db_name => $db_name, - fatal => $b_nofatal ? $urpm->{error} : sub { $urpm->{fatal}(7, $_[0]) }, + fatal => $options{nofatal} ? $urpm->{error} : sub { $urpm->{fatal}(7, $_[0]) }, + info => $urpm->{info}, log => $urpm->{log}, }; - _lock($lock, $b_exclusive); + _lock($lock, $b_exclusive, $options{wait}); $lock; } -sub _flock_failed { - my ($lock) = @_; - $lock->{fatal}(N("%s database locked", $lock->{db_name})); -} - sub _lock { - my ($lock, $b_exclusive) = @_; + my ($lock, $b_exclusive, $b_wait) = @_; $b_exclusive ||= ''; if ($lock->{log}) { my $action = $lock->{exclusive} && !$b_exclusive ? 'releasing exclusive' : $b_exclusive ? 'getting exclusive' : 'getting'; $lock->{log}("$action lock on $lock->{db_name}"); } my $mode = $b_exclusive ? $LOCK_EX : $LOCK_SH; - flock $lock->{fh}, $mode|$LOCK_NB or _flock_failed($lock); + if (!flock($lock->{fh}, $mode | $LOCK_NB)) { + if ($b_wait) { + $lock->{info}(N("%s database locked. waiting...", $lock->{db_name})); + flock($lock->{fh}, $mode) or $lock->{fatal}(N("aborting")); + } else { + $lock->{fatal}(N("%s database locked", $lock->{db_name})); + } + } $lock->{locked} = 1; $lock->{exclusive} = $b_exclusive; } -sub get_exclusive { - my ($lock) = @_; - _lock($lock, 'exclusive'); -} -sub release_exclusive { - my ($lock) = @_; - _lock($lock); -} - sub unlock { my ($lock) = @_; $lock->{fh} or warn "lock $lock->{db_name} already released\n", return; diff --git a/urpm/media.pm b/urpm/media.pm index 16384249..883e5dce 100644 --- a/urpm/media.pm +++ b/urpm/media.pm @@ -1539,12 +1539,12 @@ sub _get_pubkey_and_descriptions { } sub _read_cachedir_pubkey { - my ($urpm, $medium) = @_; + my ($urpm, $medium, $b_wait_lock) = @_; -s "$urpm->{cachedir}/partial/pubkey" or return; $urpm->{log}(N("examining pubkey file of \"%s\"...", $medium->{name})); - my $_rpm_lock = urpm::lock::rpm_db($urpm, 'exclusive'); + my $_rpm_lock = urpm::lock::rpm_db($urpm, 'exclusive', wait => $b_wait_lock); my %key_ids; $urpm->import_needed_pubkeys( @@ -1779,6 +1779,7 @@ sub _update_media__handle_some_flags { #- nopubkey : don't use rpm pubkeys #- probe_with : probe synthesis or hdlist (or none) #- quiet : download hdlists quietly +#- wait_lock : block until lock can be acquired sub update_media { my ($urpm, %options) = @_; @@ -1787,7 +1788,7 @@ sub update_media { $options{nopubkey} ||= $urpm->{options}{nopubkey}; if (!$options{nopubkey} && !$urpm->{keys}) { #- get gpg-pubkey signature. - my $_rpm_lock = urpm::lock::rpm_db($urpm); + my $_rpm_lock = urpm::lock::rpm_db($urpm, '', wait => $options{wait_lock}); $urpm->{log}(qq(getting "gpg-pubkey"s from rpmdb)); $urpm->parse_pubkeys(root => $urpm->{root}); } @@ -1827,7 +1828,7 @@ sub update_media { if ($medium->{really_modified}) { _get_pubkey_and_descriptions($urpm, $medium, $options{nopubkey}); - _read_cachedir_pubkey($urpm, $medium); + _read_cachedir_pubkey($urpm, $medium, $options{wait_lock}); generate_medium_names($urpm, $medium); } } diff --git a/urpme b/urpme index f07eb369..7ab603e1 100644 --- a/urpme +++ b/urpme @@ -83,7 +83,7 @@ unless ($test) { } #- just configure parallel mode if available. -my $_urpmi_lock = urpm::lock::urpmi_db($urpm); +my $_urpmi_lock = urpm::lock::urpmi_db($urpm, '', wait => $options{wait_lock}); urpm::media::configure($urpm, synthesis => ($parallel ? 'none' : ''), parallel => $parallel, diff --git a/urpmf b/urpmf index 8c93f538..cc0e1aca 100755 --- a/urpmf +++ b/urpmf @@ -194,7 +194,7 @@ if ($env) { $urpm->{statedir} = $env; } -my $_lock = urpm::lock::urpmi_db($urpm, '', 'nofatal'); +my $_lock = urpm::lock::urpmi_db($urpm, '', nofatal => 1, wait => $options{wait_lock}); my $need_hdlist = grep { $usedtags{$_} } qw( buildhost buildtime diff --git a/urpmi b/urpmi index 6566781c..e77bb5af 100755 --- a/urpmi +++ b/urpmi @@ -328,7 +328,7 @@ if (exists $urpm->{options}{'priority-upgrade'} && $urpm->{options}{'priority-up unlink glob('/var/lib/rpm/__db.*') unless $urpm->{root}; } -my $urpmi_lock = !$env && !$options{nolock} && urpm::lock::urpmi_db($urpm); +my $urpmi_lock = !$env && !$options{nolock} && urpm::lock::urpmi_db($urpm, '', wait => $options{wait_lock}); #- should we ignore arch compatibility if ($urpm->{options}{ignorearch}) { urpm::shunt_ignorearch() } @@ -394,7 +394,7 @@ if ($bug) { urpm::bug_report::copy_requested($urpm, $bug, \%requested); } -my $rpm_lock = !$env && !$options{nolock} && urpm::lock::rpm_db($urpm, 'exclusive'); +my $rpm_lock = !$env && !$options{nolock} && urpm::lock::rpm_db($urpm, 'exclusive', wait => $options{wait_lock}); #- search the packages according to the selection given by the user. my $search_result = ''; diff --git a/urpmi.addmedia b/urpmi.addmedia index c8bb7076..3a1f6ed1 100755 --- a/urpmi.addmedia +++ b/urpmi.addmedia @@ -115,7 +115,7 @@ if (!-e $urpm->{config}) { $urpm->{log}(N("creating config file [%s]", $urpm->{config})); open my $_f, '>', $urpm->{config} or $urpm->{fatal}(6, N("Can't create config file [%s]", $urpm->{config})); } -my $_urpmi_lock = urpm::lock::urpmi_db($urpm, 'exclusive'); +my $_urpmi_lock = urpm::lock::urpmi_db($urpm, 'exclusive', wait => $options{wait_lock}); urpm::media::read_config($urpm); if ($options{distrib}) { diff --git a/urpmi.bash-completion b/urpmi.bash-completion index 3f67b4c9..c15d84c8 100644 --- a/urpmi.bash-completion +++ b/urpmi.bash-completion @@ -2,7 +2,7 @@ # Copyright (c) 2002-2006 Guillaume Rousse # $Id$ -common_options="-q --quiet -v --verbose --debug -h --help --urpmi-root" +common_options="-q --quiet -v --verbose --debug -h --help --urpmi-root --wait-lock" # utility functions _urpmi_get_medias() diff --git a/urpmi.removemedia b/urpmi.removemedia index a3485282..b60c1f55 100755 --- a/urpmi.removemedia +++ b/urpmi.removemedia @@ -63,7 +63,7 @@ if ($< != 0) { $urpm->{fatal}(1, N("Only superuser is allowed to remove media")); } -my $_urpmi_lock = urpm::lock::urpmi_db($urpm, 'exclusive'); +my $_urpmi_lock = urpm::lock::urpmi_db($urpm, 'exclusive', wait => $options{wait_lock}); urpm::media::read_config($urpm); urpm::download::set_cmdline_proxy(); my @entries = map { $_->{name} } @{$urpm->{media}}; diff --git a/urpmi.update b/urpmi.update index b0993770..257b0198 100755 --- a/urpmi.update +++ b/urpmi.update @@ -68,7 +68,7 @@ urpm::args::parse_cmdline(urpm => $urpm) or exit(1); if ($< != 0) { $urpm->{fatal}(1, N("Only superuser is allowed to update media")); } -my $_urpmi_lock = urpm::lock::urpmi_db($urpm, 'exclusive'); +my $_urpmi_lock = urpm::lock::urpmi_db($urpm, 'exclusive', wait => $options{wait_lock}); urpm::media::read_config($urpm); my @entries = map { $_->{name} } @{$urpm->{media}}; diff --git a/urpmq b/urpmq index ce367196..271ee92c 100755 --- a/urpmq +++ b/urpmq @@ -145,8 +145,8 @@ if ($options{ignorearch}) { urpm::shunt_ignorearch() } my $rpm_lock = $options{upgrade} && !$options{env} && !$options{nolock} - && urpm::lock::rpm_db($urpm); -my $urpmi_lock = !$options{nolock} && urpm::lock::urpmi_db($urpm); + && urpm::lock::rpm_db($urpm, '', wait => $options{wait_lock}); +my $urpmi_lock = !$options{nolock} && urpm::lock::urpmi_db($urpm, '', wait => $options{wait_lock}); urpm::media::configure($urpm, nocheck_access => 1, nodepslist => $options{nodepslist}, -- cgit v1.2.1