Allow to listen to garbage collector events

A new event type is introduced that allows to listen to garbage
collector events. This enables to trigger actions that depend on
changes in the file size footprint of a project such as quota
enforcement or usage data monitoring.

Change-Id: I1eb913a618df5fe972f3f516af504c13871e5fa5
This commit is contained in:
Adrian Görler
2014-08-22 17:09:18 +02:00
parent 3772eb551d
commit f4a4c9a628
4 changed files with 78 additions and 1 deletions

View File

@@ -27,6 +27,7 @@ import com.google.gerrit.extensions.events.HeadUpdatedListener;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.events.NewProjectCreatedListener;
import com.google.gerrit.extensions.events.ProjectDeletedListener;
import com.google.gerrit.extensions.events.GarbageCollectorListener;
import com.google.gerrit.extensions.events.UsageDataPublishedListener;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.extensions.registration.DynamicMap;
@@ -253,6 +254,7 @@ public class GerritGlobalModule extends FactoryModule {
DynamicSet.setOf(binder(), PreUploadHook.class);
DynamicSet.setOf(binder(), NewProjectCreatedListener.class);
DynamicSet.setOf(binder(), ProjectDeletedListener.class);
DynamicSet.setOf(binder(), GarbageCollectorListener.class);
DynamicSet.setOf(binder(), HeadUpdatedListener.class);
DynamicSet.setOf(binder(), UsageDataPublishedListener.class);
DynamicSet.bind(binder(), GitReferenceUpdatedListener.class).to(ReindexAfterUpdate.class);

View File

@@ -16,6 +16,9 @@ package com.google.gerrit.server.git;
import com.google.common.collect.Sets;
import com.google.gerrit.common.data.GarbageCollectionResult;
import com.google.gerrit.extensions.events.GarbageCollectorListener;
import com.google.gerrit.extensions.events.GarbageCollectorListener.Event;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.config.GcConfig;
import com.google.inject.Inject;
@@ -48,6 +51,7 @@ public class GarbageCollection {
private final GitRepositoryManager repoManager;
private final GarbageCollectionQueue gcQueue;
private final GcConfig gcConfig;
private final DynamicSet<GarbageCollectorListener> listeners;
public interface Factory {
GarbageCollection create();
@@ -55,10 +59,12 @@ public class GarbageCollection {
@Inject
GarbageCollection(GitRepositoryManager repoManager,
GarbageCollectionQueue gcQueue, GcConfig config) {
GarbageCollectionQueue gcQueue, GcConfig config,
DynamicSet<GarbageCollectorListener> listeners) {
this.repoManager = repoManager;
this.gcQueue = gcQueue;
this.gcConfig = config;
this.listeners = listeners;
}
public GarbageCollectionResult run(List<Project.NameKey> projectNames) {
@@ -93,6 +99,7 @@ public class GarbageCollection {
Properties statistics = gc.call();
logGcInfo(p, "after: ", statistics);
print(writer, "done.\n\n");
fire(p, statistics);
} catch (RepositoryNotFoundException e) {
logGcError(writer, p, e);
result.addError(new GarbageCollectionResult.Error(
@@ -112,6 +119,27 @@ public class GarbageCollection {
return result;
}
private void fire(final Project.NameKey p, final Properties statistics) {
Event event = new GarbageCollectorListener.Event() {
@Override
public String getProjectName() {
return p.get();
}
@Override
public Properties getStatistics() {
return statistics;
}
};
for (GarbageCollectorListener l : listeners) {
try {
l.onGarbageCollected(event);
} catch (RuntimeException e) {
log.warn("Failure in GarbageCollectorListener", e);
}
}
}
private static void logGcInfo(Project.NameKey projectName, String msg) {
logGcInfo(projectName, msg, null);
}