blob: 69e0a37b57f4b987c51e1429b5fce8aa8697eb9e [file] [log] [blame]
// Copyright (C) 2016 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.ericsson.gerrit.plugins.gcconductor.evaluator;
import com.ericsson.gerrit.plugins.gcconductor.EvaluationTask;
import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.validators.UploadValidationListener;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.pack.PackStatistics;
import org.eclipse.jgit.transport.PostUploadHook;
import org.eclipse.jgit.transport.UploadPack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
class Evaluator implements UploadValidationListener, PostUploadHook, GitReferenceUpdatedListener {
private static final Logger log = LoggerFactory.getLogger(Evaluator.class);
private static final ThreadLocal<String> uploadRepositoryPath = new ThreadLocal<String>() {};
private final ScheduledThreadPoolExecutor executor;
private final EvaluationTask.Factory evaluationTaskFactory;
private final GitRepositoryManager repoManager;
private final Map<String, Long> timestamps;
private long expireTime;
@Inject
Evaluator(
@EvaluatorExecutor ScheduledThreadPoolExecutor executor,
EvaluationTask.Factory evaluationTaskFactory,
GitRepositoryManager repoManager,
EvaluatorConfig config,
@GerritServerConfig Config gerritConfig) {
this.executor = executor;
this.evaluationTaskFactory = evaluationTaskFactory;
this.repoManager = repoManager;
this.expireTime = config.getExpireTimeRecheck();
int threads =
gerritConfig.getInt(
"receive", null, "threadPoolSize", Runtime.getRuntime().availableProcessors());
timestamps = new ConcurrentHashMap<>(10000, 0.75f, threads);
}
@Override
public void onPreUpload(
Repository repository,
Project project,
String remoteHost,
UploadPack up,
Collection<? extends ObjectId> wants,
Collection<? extends ObjectId> haves) {
uploadRepositoryPath.set(repository.getDirectory().getAbsolutePath());
}
@Override
public void onBeginNegotiate(
Repository repository,
Project project,
String remoteHost,
UploadPack up,
Collection<? extends ObjectId> wants,
int cntOffered) {
// Do nothing
}
@Override
public void onPostUpload(PackStatistics stats) {
String repositoryPath = uploadRepositoryPath.get();
if (repositoryPath != null && needsCheck(repositoryPath)) {
executor.execute(evaluationTaskFactory.create(repositoryPath));
uploadRepositoryPath.remove();
}
}
@Override
public void onGitReferenceUpdated(Event event) {
String projectName = event.getProjectName();
Project.NameKey projectNameKey = new Project.NameKey(projectName);
try (Repository repository = repoManager.openRepository(projectNameKey)) {
String repositoryPath = repository.getDirectory().getAbsolutePath();
if (needsCheck(repositoryPath)) {
executor.execute(evaluationTaskFactory.create(repositoryPath));
}
} catch (RepositoryNotFoundException e) {
log.error("Project not found {}", projectName, e);
} catch (IOException e) {
log.error("Error getting repository for project {}", projectName, e);
}
}
private boolean needsCheck(String repositoryPath) {
long now = System.currentTimeMillis();
if (!timestamps.containsKey(repositoryPath)
|| now >= timestamps.get(repositoryPath) + expireTime) {
timestamps.put(repositoryPath, now);
return true;
}
return false;
}
}