Sho SHIMIZU

Copy FlowOperationsProcessor defensively for thread safety

Change-Id: Ic5c920b0efc40d472d454b0e1a0305f16b39e98c
......@@ -582,12 +582,20 @@ public class FlowRuleManager
// Mutable
private final List<Set<FlowRuleOperation>> stages;
private final Set<DeviceId> pendingDevices = new HashSet<>();
private final Set<DeviceId> pendingDevices;
private boolean hasFailed = false;
FlowOperationsProcessor(FlowRuleOperations ops) {
this.stages = Lists.newArrayList(ops.stages());
this.fops = ops;
this.pendingDevices = new HashSet<>();
}
FlowOperationsProcessor(FlowOperationsProcessor src) {
this.fops = src.fops;
this.stages = Lists.newArrayList(src.stages);
this.pendingDevices = new HashSet<>(src.pendingDevices);
this.hasFailed = src.hasFailed;
}
@Override
......@@ -620,7 +628,7 @@ public class FlowRuleManager
synchronized void satisfy(DeviceId devId) {
pendingDevices.remove(devId);
if (pendingDevices.isEmpty()) {
operationsService.execute(this);
operationsService.execute(new FlowOperationsProcessor(this));
}
}
......@@ -628,7 +636,7 @@ public class FlowRuleManager
hasFailed = true;
pendingDevices.remove(devId);
if (pendingDevices.isEmpty()) {
operationsService.execute(this);
operationsService.execute(new FlowOperationsProcessor(this));
}
FlowRuleOperations.Builder failedOpsBuilder = FlowRuleOperations.builder();
......