diff options
3 files changed, 65 insertions, 8 deletions
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java index 5a3b92c..bff96ac 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java @@ -488,18 +488,19 @@ public class Destination { } } - boolean requestRunway(PushOne op) { + RunwayStatus requestRunway(PushOne op) { synchronized (stateLock) { if (op.wasCanceled()) { - return false; + return RunwayStatus.canceled(); } pending.remove(op.getURI()); - if (inFlight.containsKey(op.getURI())) { - return false; + PushOne inFlightOp = inFlight.get(op.getURI()); + if (inFlightOp != null) { + return RunwayStatus.denied(inFlightOp.getId()); } inFlight.put(op.getURI(), op); } - return true; + return RunwayStatus.allowed(); } void notifyFinished(PushOne op) { diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java b/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java index 09187a0..5c24c74 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java @@ -251,6 +251,10 @@ class PushOne implements ProjectRunnable, CanceledWhileRunning { return states.toArray(new ReplicationState[states.size()]); } + public int getId() { + return id; + } + void addStates(ListMultimap<String, ReplicationState> states) { stateMap.putAll(states); } @@ -297,10 +301,13 @@ class PushOne implements ProjectRunnable, CanceledWhileRunning { // created and scheduled for a future point in time.) // MDC.put(ID_MDC_KEY, HexFormat.fromInt(id)); - if (!pool.requestRunway(this)) { - if (!canceled) { + RunwayStatus status = pool.requestRunway(this); + if (!status.isAllowed()) { + if (!status.isCanceled()) { repLog.info( - "Rescheduling replication to {} to avoid collision with an in-flight push.", uri); + "Rescheduling replication to {} to avoid collision with the in-flight push [{}].", + uri, + HexFormat.fromInt(status.getInFlightPushId())); pool.reschedule(this, Destination.RetryReason.COLLISION); } return; diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/RunwayStatus.java b/src/main/java/com/googlesource/gerrit/plugins/replication/RunwayStatus.java new file mode 100644 index 0000000..bcb1e2f --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/RunwayStatus.java @@ -0,0 +1,49 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.googlesource.gerrit.plugins.replication; + +public class RunwayStatus { + public static RunwayStatus allowed() { + return new RunwayStatus(true, 0); + } + + public static RunwayStatus canceled() { + return new RunwayStatus(false, 0); + } + + public static RunwayStatus denied(int inFlightPushId) { + return new RunwayStatus(false, inFlightPushId); + } + + private final boolean allowed; + private final int inFlightPushId; + + private RunwayStatus(boolean allowed, int inFlightPushId) { + this.allowed = allowed; + this.inFlightPushId = inFlightPushId; + } + + public boolean isAllowed() { + return allowed; + } + + public boolean isCanceled() { + return !allowed && inFlightPushId == 0; + } + + public int getInFlightPushId() { + return inFlightPushId; + } +} |