in src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java [394:493]
private void doRunPushOperation() {
// Lock the queue, and remove ourselves, so we can't be modified once
// we start replication (instead a new instance, with the same URI, is
// created and scheduled for a future point in time.)
//
RunwayStatus status = pool.requestRunway(this);
isCollision = false;
if (!status.isAllowed()) {
if (status.isCanceled()) {
repLog.atInfo().log(
"PushOp for replication to %s was canceled and thus won't be rescheduled", uri);
} else {
repLog.atInfo().log(
"Rescheduling replication to %s to avoid collision with the in-flight push [%s].",
uri, HexFormat.fromInt(status.getInFlightPushId()));
pool.reschedule(this, Destination.RetryReason.COLLISION);
isCollision = true;
}
return;
}
repLog.atInfo().log("Replication to %s started...", uri);
Timer1.Context<String> destinationContext = metrics.start(config.getName());
try {
long startedAt = destinationContext.getStartTime();
long delay = NANOSECONDS.toMillis(startedAt - createdAt);
metrics.record(config.getName(), delay, retryCount);
git = gitManager.openRepository(projectName);
runImpl();
long elapsed = NANOSECONDS.toMillis(destinationContext.stop());
if (elapsed > SECONDS.toMillis(pool.getSlowLatencyThreshold())) {
metrics.recordSlowProjectReplication(
config.getName(), projectName.get(), pool.getSlowLatencyThreshold(), elapsed);
}
retryDone();
repLog.atInfo().log(
"Replication to %s completed in %dms, %dms delay, %d retries",
uri, elapsed, delay, retryCount);
} catch (RepositoryNotFoundException e) {
stateLog.error(
"Cannot replicate " + projectName + "; Local repository error: " + e.getMessage(),
getStatesAsArray());
} catch (RemoteRepositoryException e) {
// Tried to replicate to a remote via anonymous git:// but the repository
// does not exist. In this case NoRemoteRepositoryException is not
// raised.
String msg = e.getMessage();
if (msg.contains("access denied")
|| msg.contains("no such repository")
|| msg.contains("Git repository not found")
|| msg.contains("unavailable")) {
createRepository();
} else {
repLog.atSevere().log("Cannot replicate %s; Remote repository error: %s", projectName, msg);
}
} catch (NoRemoteRepositoryException e) {
createRepository();
} catch (NotSupportedException e) {
stateLog.error("Cannot replicate to " + uri, e, getStatesAsArray());
} catch (TransportException e) {
if (e instanceof UpdateRefFailureException) {
updateRefRetryCount++;
repLog.atSevere().log("Cannot replicate to %s due to a lock or write ref failure", uri);
// The remote push operation should be retried.
if (updateRefRetryCount <= maxUpdateRefRetries) {
if (canceledWhileRunning.get()) {
logCanceledWhileRunningException(e);
} else {
pool.reschedule(this, Destination.RetryReason.TRANSPORT_ERROR);
}
} else {
retryDone();
repLog.atSevere().log(
"Giving up after %d '%s' failures during replication to %s",
updateRefRetryCount, e.getMessage(), uri);
}
} else {
if (canceledWhileRunning.get()) {
logCanceledWhileRunningException(e);
} else {
repLog.atSevere().withCause(e).log("Cannot replicate to %s", uri);
// The remote push operation should be retried.
pool.reschedule(this, Destination.RetryReason.TRANSPORT_ERROR);
}
}
} catch (IOException e) {
stateLog.error("Cannot replicate to " + uri, e, getStatesAsArray());
} catch (PermissionBackendException | RuntimeException | Error e) {
stateLog.error("Unexpected error during replication to " + uri, e, getStatesAsArray());
} finally {
pool.notifyFinished(this);
if (git != null) {
git.close();
}
}
}