[pve-devel] [Patch V5 guest-common 7/7] Add lock to pervent lost update.

Wolfgang Link w.link at proxmox.com
Wed May 9 14:48:27 CEST 2018


---
 PVE/ReplicationState.pm | 102 +++++++++++++++++++++++++-----------------------
 1 file changed, 53 insertions(+), 49 deletions(-)

diff --git a/PVE/ReplicationState.pm b/PVE/ReplicationState.pm
index 2851b62..1613e8f 100644
--- a/PVE/ReplicationState.pm
+++ b/PVE/ReplicationState.pm
@@ -240,67 +240,71 @@ sub job_status {
 
     my $vms = PVE::Cluster::get_vmlist();
 
-    foreach my $jobid (sort keys %{$cfg->{ids}}) {
-	my $jobcfg = $cfg->{ids}->{$jobid};
-	my $vmid = $jobcfg->{guest};
-
-	die "internal error - not implemented" if $jobcfg->{type} ne 'local';
+    my $func = sub {
+	foreach my $jobid (sort keys %{$cfg->{ids}}) {
+	    my $jobcfg = $cfg->{ids}->{$jobid};
+	    my $vmid = $jobcfg->{guest};
 
-	# skip non existing vms
-	next if !$vms->{ids}->{$vmid};
+	    die "internal error - not implemented" if $jobcfg->{type} ne 'local';
+
+	    # skip non existing vms
+	    next if !$vms->{ids}->{$vmid};
+
+	    # only consider guest on local node
+	    next if $vms->{ids}->{$vmid}->{node} ne $local_node;
+
+	    my $target = $jobcfg->{target};
+	    if (!$jobcfg->{remove_job}) {
+		# check if vm was stolen (swapped source target)
+		if ($target eq $local_node) {
+		    my $source = $jobcfg->{source};
+		    if (defined($source) && $source ne $target) {
+			$jobcfg = PVE::ReplicationConfig::swap_source_target_nolock($jobid);
+			$cfg->{ids}->{$jobid} = $jobcfg;
+		    } else {
+			# never sync to local node
+			next;
+		    }
+		}
 
-	# only consider guest on local node
-	next if $vms->{ids}->{$vmid}->{node} ne $local_node;
+		next if !$get_disabled && $jobcfg->{disable};
+	    }
 
-	my $target = $jobcfg->{target};
-	if (!$jobcfg->{remove_job}) {
-	    # check if vm was stolen (swapped source target)
-	    if ($target eq $local_node) {
-		my $source = $jobcfg->{source};
-		if (defined($source) && $source ne $target) {
-		    $jobcfg = PVE::ReplicationConfig::swap_source_target_nolock($jobid);
-		    $cfg->{ids}->{$jobid} = $jobcfg;
+	    my $state = extract_job_state($stateobj, $jobcfg);
+	    $jobcfg->{state} = $state;
+	    $jobcfg->{id} = $jobid;
+	    $jobcfg->{vmtype} = $vms->{ids}->{$vmid}->{type};
+
+	    my $next_sync = 0;
+
+	    if ($jobcfg->{remove_job}) {
+		$next_sync = 1; # lowest possible value
+		# todo: consider fail_count? How many retries?
+	    } else  {
+		if (my $fail_count = $state->{fail_count}) {
+		    my $members = PVE::Cluster::get_members();
+		    if (!$fail_count || ($members->{$target} && $members->{$target}->{online})) {
+			$next_sync = $state->{last_try} + 60*($fail_count < 3 ? 5*$fail_count : 30);
+		    }
 		} else {
-		    # never sync to local node
-		    next;
+		    my $schedule =  $jobcfg->{schedule} || '*/15';
+		    my $calspec = PVE::CalendarEvent::parse_calendar_event($schedule);
+		    $next_sync = PVE::CalendarEvent::compute_next_event($calspec, $state->{last_try}) // 0;
 		}
 	    }
 
-	    next if !$get_disabled && $jobcfg->{disable};
-	}
-
-	my $state = extract_job_state($stateobj, $jobcfg);
-	$jobcfg->{state} = $state;
-	$jobcfg->{id} = $jobid;
-	$jobcfg->{vmtype} = $vms->{ids}->{$vmid}->{type};
-
-	my $next_sync = 0;
+	    $jobcfg->{next_sync} = $next_sync;
 
-	if ($jobcfg->{remove_job}) {
-	    $next_sync = 1; # lowest possible value
-	    # todo: consider fail_count? How many retries?
-	} else  {
-	    if (my $fail_count = $state->{fail_count}) {
-		my $members = PVE::Cluster::get_members();
-		if (!$fail_count || ($members->{$target} && $members->{$target}->{online})) {
-		    $next_sync = $state->{last_try} + 60*($fail_count < 3 ? 5*$fail_count : 30);
-		}
-	    } else {
-		my $schedule =  $jobcfg->{schedule} || '*/15';
-		my $calspec = PVE::CalendarEvent::parse_calendar_event($schedule);
-		$next_sync = PVE::CalendarEvent::compute_next_event($calspec, $state->{last_try}) // 0;
+	    if (!defined($jobcfg->{source}) || $jobcfg->{source} ne $local_node) {
+		$jobcfg->{source} = $cfg->{ids}->{$jobid}->{source} = $local_node;
+		PVE::ReplicationConfig::write($cfg);
 	    }
-	}
-
-	$jobcfg->{next_sync} = $next_sync;
 
-	if (!defined($jobcfg->{source}) || $jobcfg->{source} ne $local_node) {
-	    $jobcfg->{source} = $cfg->{ids}->{$jobid}->{source} = $local_node;
-	    PVE::ReplicationConfig::write($cfg);
+	    $jobs->{$jobid} = $jobcfg;
 	}
+    };
 
-	$jobs->{$jobid} = $jobcfg;
-    }
+    PVE::ReplicationConfig::lock($func);
 
     return $jobs;
 }
-- 
2.11.0




More information about the pve-devel mailing list