From: Don Armstrong Date: Fri, 1 Aug 2008 04:21:04 +0000 (-0700) Subject: * Add lock support to read_bug X-Git-Tag: release/2.6.0~488^2~23^2~3 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=c7c042859262e3598d3b0892f78c9088fa4ac520;p=debbugs.git * Add lock support to read_bug * Add new function to lock and read all merged bugs --- diff --git a/Debbugs/Status.pm b/Debbugs/Status.pm index 55b29d5..8536328 100644 --- a/Debbugs/Status.pm +++ b/Debbugs/Status.pm @@ -32,6 +32,7 @@ status of a particular bug use warnings; use strict; + use vars qw($VERSION $DEBUG %EXPORT_TAGS @EXPORT_OK @EXPORT); use base qw(Exporter); @@ -129,6 +130,10 @@ path to the summary file instead of the bug number and/or location. =item summary -- complete path to the .summary file which will be read +=item lock -- whether to obtain a lock for the bug to prevent +something modifying it while the bug has been read. You B call +C if something not undef is returned from read_bug. + =back One of C or C must be passed. This function will return @@ -154,6 +159,9 @@ sub read_bug{ summary => {type => SCALAR, optional => 1, }, + lock => {type => BOOLEAN, + optional => 1, + }, }, ); die "One of bug or summary must be passed to read_bug" @@ -178,8 +186,17 @@ sub read_bug{ $log =~ s/\.summary$/.log/; ($location) = $status =~ m/(db-h|db|archive)/; } - my $status_fh = IO::File->new($status, 'r') or - warn "Unable to open $status for reading: $!" and return undef; + if ($param{lock}) { + filelock("$config{spool_dir}/lock/$param{bug}"); + } + my $status_fh = IO::File->new($status, 'r'); + if (not defined $status_fh) { + warn "Unable to open $status for reading: $!"; + if ($param{lock}) { + unfilelock(); + } + return undef; + } my %data; my @lines; @@ -195,6 +212,9 @@ sub read_bug{ # Version 3 is the latest format version currently supported. if ($version > 3) { warn "Unsupported status version '$version'"; + if ($param{lock}) { + unfilelock(); + } return undef; } @@ -248,10 +268,7 @@ See readbug above for information on what this returns sub lockreadbug { my ($lref, $location) = @_; - &filelock("$config{spool_dir}/lock/$lref"); - my $data = read_bug(bug => $lref, location => $location); - &unfilelock unless defined $data; - return $data; + return read_bug(bug => $lref, location => $location, lock => 1); } =head2 lockreadbugmerge @@ -283,6 +300,67 @@ sub lockreadbugmerge { return (2,$data); } +=head2 lock_read_all_merged_bugs + + my ($locks,@bug_data) = lock_read_all_merged_bugs($bug_num,$location); + +Performs a filelock, then reads the bug passed. If the bug is merged, +locks the merge lock, then reads and locks all of the other merged +bugs. Returns a list of the number of locks and the bug data for all +of the merged bugs. + +Will also return undef if any of the merged bugs failed to be read, +even if all of the others were read properly. + +=cut + +sub lock_read_all_merged_bugs { + my ($bug_num,$location) = @_; + my @data = (lockreadbug(@_)); + if (not @data and not defined $data[0]) { + return (0,undef); + } + if (not length $data[0]->{mergedwith}) { + return (1,@data); + } + unfilelock(); + filelock("$config{spool_dir}/lock/merge"); + my $locks = 0; + @data = (lockreadbug(@_)); + if (not @data and not defined $data[0]) { + unfilelock(); #for merge lock above + return (0,undef); + } + $locks++; + my @bugs = split / /, $data[0]->{mergedwith}; + for my $bug (@bugs) { + my $newdata = undef; + if ($bug ne $bug_num) { + $newdata = lockreadbug($bug,$location); + if (not defined $newdata) { + for (1..$locks) { + unfilelock(); + } + $locks = 0; + warn "Unable to read bug: $bug while handling merged bug: $bug_num"; + return ($locks,undef); + } + $locks++; + push @data,$newdata; + } + # perform a sanity check to make sure that the merged bugs are + # all merged with eachother + my $expectmerge= join(' ',grep($_ != $bug, sort { $a <=> $b } @bugs)); + if ($newdata->{mergedwith} ne $expectmerge) { + for (1..$locks) { + unfilelock(); + } + die "Bug $bug_num differs from bug $bug: ($newdata->{mergedwith}) vs. ($expectmerge) (".join(' ',@bugs).")"; + } + } + return (2,@data); +} + my @v1fieldorder = qw(originator date subject msgid package keywords done forwarded mergedwith severity);