Extract a non-caching ChangeKindCache implementation for tests
Change-Id: I061e1eb96d167750af8b7fa533d6f8f5722bfc8f
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java
index 1807e73..be2e563 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java
@@ -43,7 +43,7 @@
import com.google.gerrit.server.account.GroupIncludeCacheImpl;
import com.google.gerrit.server.cache.CacheRemovalListener;
import com.google.gerrit.server.cache.h2.DefaultCacheFactory;
-import com.google.gerrit.server.change.ChangeKindCache;
+import com.google.gerrit.server.change.ChangeKindCacheImpl;
import com.google.gerrit.server.change.MergeabilityChecker;
import com.google.gerrit.server.change.MergeabilityChecksExecutor;
import com.google.gerrit.server.change.MergeabilityChecksExecutor.Priority;
@@ -298,7 +298,7 @@
DynamicSet.setOf(binder(), CommitValidationListener.class);
factory(CommitValidators.Factory.class);
- install(ChangeKindCache.module());
+ install(ChangeKindCacheImpl.module());
install(new GitModule());
install(new NoteDbModule());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeKindCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeKindCache.java
index b778a8b..0e0984d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeKindCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeKindCache.java
@@ -1,4 +1,4 @@
-// Copyright (C) 2013 The Android Open Source Project
+// Copyright (C) 2014 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.
@@ -14,37 +14,10 @@
package com.google.gerrit.server.change;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.eclipse.jgit.lib.ObjectIdSerialization.readNotNull;
-import static org.eclipse.jgit.lib.ObjectIdSerialization.writeNotNull;
-
-import com.google.common.base.Objects;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.cache.Weigher;
-import com.google.gerrit.server.cache.CacheModule;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.git.MergeUtil;
import com.google.gerrit.server.project.ProjectState;
-import com.google.inject.Inject;
-import com.google.inject.Module;
-import com.google.inject.Singleton;
-import com.google.inject.name.Named;
-import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.merge.ThreeWayMerger;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.util.concurrent.ExecutionException;
/**
* Cache of {@link ChangeKind} per commit.
@@ -52,169 +25,7 @@
* This is immutable conditioned on the merge strategy (unless the JGit strategy
* implementation changes, which might invalidate old entries).
*/
-public class ChangeKindCache {
- private static final Logger log =
- LoggerFactory.getLogger(ChangeKindCache.class);
-
- private static final String ID_CACHE = "change_kind";
-
- public static Module module() {
- return new CacheModule() {
- @Override
- protected void configure() {
- persist(ID_CACHE, Key.class, ChangeKind.class)
- .maximumWeight(2 << 20)
- .weigher(ChangeKindWeigher.class)
- .loader(Loader.class);
- }
- };
- }
-
- public static class Key implements Serializable {
- private static final long serialVersionUID = 1L;
-
- private transient ObjectId prior;
- private transient ObjectId next;
- private transient String strategyName;
-
- private transient Repository repo; // Passed through to loader on miss.
-
- private Key(ObjectId prior, ObjectId next, String strategyName,
- Repository repo) {
- this.prior = prior.copy();
- this.next = next.copy();
- this.strategyName = strategyName;
- this.repo = repo;
- }
-
- public ObjectId getPrior() {
- return prior;
- }
-
- public ObjectId getNext() {
- return next;
- }
-
- public String getStrategyName() {
- return strategyName;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof Key) {
- Key k = (Key) o;
- return Objects.equal(prior, k.prior)
- && Objects.equal(next, k.next)
- && Objects.equal(strategyName, k.strategyName);
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(prior, next, strategyName);
- }
-
- private void writeObject(ObjectOutputStream out) throws IOException {
- writeNotNull(out, prior);
- writeNotNull(out, next);
- out.writeUTF(strategyName);
- }
-
- private void readObject(ObjectInputStream in) throws IOException {
- prior = readNotNull(in);
- next = readNotNull(in);
- strategyName = in.readUTF();
- }
- }
-
- @Singleton
- private static class Loader extends CacheLoader<Key, ChangeKind> {
- @Override
- public ChangeKind load(Key key) throws IOException {
- RevWalk walk = new RevWalk(key.repo);
- try {
- RevCommit prior = walk.parseCommit(key.prior);
- walk.parseBody(prior);
- RevCommit next = walk.parseCommit(key.next);
- walk.parseBody(next);
-
- if (!next.getFullMessage().equals(prior.getFullMessage())) {
- if (next.getTree() == prior.getTree() && isSameParents(prior, next)) {
- return ChangeKind.NO_CODE_CHANGE;
- } else {
- return ChangeKind.REWORK;
- }
- }
-
- if (prior.getParentCount() != 1 || next.getParentCount() != 1) {
- // Trivial rebases done by machine only work well on 1 parent.
- return ChangeKind.REWORK;
- }
-
- if (next.getTree() == prior.getTree() &&
- isSameParents(prior, next)) {
- return ChangeKind.TRIVIAL_REBASE;
- }
-
- // A trivial rebase can be detected by looking for the next commit
- // having the same tree as would exist when the prior commit is
- // cherry-picked onto the next commit's new first parent.
- ThreeWayMerger merger = MergeUtil.newThreeWayMerger(
- key.repo, MergeUtil.createDryRunInserter(), key.strategyName);
- merger.setBase(prior.getParent(0));
- if (merger.merge(next.getParent(0), prior)
- && merger.getResultTreeId().equals(next.getTree())) {
- return ChangeKind.TRIVIAL_REBASE;
- } else {
- return ChangeKind.REWORK;
- }
- } finally {
- key.repo = null;
- walk.release();
- }
- }
-
- private static boolean isSameParents(RevCommit prior, RevCommit next) {
- if (prior.getParentCount() != next.getParentCount()) {
- return false;
- } else if (prior.getParentCount() == 0) {
- return true;
- }
- return prior.getParent(0).equals(next.getParent(0));
- }
- }
-
- public static class ChangeKindWeigher implements Weigher<Key, ChangeKind> {
- @Override
- public int weigh(Key key, ChangeKind changeKind) {
- return 16 + 2*36 + 2*key.strategyName.length() // Size of Key, 64 bit JVM
- + 2*changeKind.name().length(); // Size of ChangeKind, 64 bit JVM
- }
- }
-
- private final LoadingCache<Key, ChangeKind> cache;
- private final boolean useRecursiveMerge;
-
- @Inject
- ChangeKindCache(
- @GerritServerConfig Config serverConfig,
- @Named(ID_CACHE) LoadingCache<Key, ChangeKind> cache) {
- this.cache = cache;
- this.useRecursiveMerge = MergeUtil.useRecursiveMerge(serverConfig);
- }
-
+public interface ChangeKindCache {
public ChangeKind getChangeKind(ProjectState project, Repository repo,
- ObjectId prior, ObjectId next) {
- checkNotNull(next, "next");
- String strategyName = MergeUtil.mergeStrategyName(
- project.isUseContentMerge(), useRecursiveMerge);
- try {
- return cache.get(new Key(prior, next, strategyName, repo));
- } catch (ExecutionException e) {
- log.warn("Cannot check trivial rebase of new patch set " + next.name()
- + " in " + project.getProject().getName(), e);
- return ChangeKind.REWORK;
- }
- }
+ ObjectId prior, ObjectId next);
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java
new file mode 100644
index 0000000..7e87937
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java
@@ -0,0 +1,229 @@
+// Copyright (C) 2013 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.google.gerrit.server.change;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.eclipse.jgit.lib.ObjectIdSerialization.readNotNull;
+import static org.eclipse.jgit.lib.ObjectIdSerialization.writeNotNull;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Objects;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.cache.Weigher;
+import com.google.gerrit.server.cache.CacheModule;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.git.MergeUtil;
+import com.google.gerrit.server.project.ProjectState;
+import com.google.inject.Inject;
+import com.google.inject.Module;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.merge.ThreeWayMerger;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.concurrent.ExecutionException;
+
+public class ChangeKindCacheImpl implements ChangeKindCache {
+ private static final Logger log =
+ LoggerFactory.getLogger(ChangeKindCacheImpl.class);
+
+ private static final String ID_CACHE = "change_kind";
+
+ public static Module module() {
+ return new CacheModule() {
+ @Override
+ protected void configure() {
+ bind(ChangeKindCache.class).to(ChangeKindCacheImpl.class);
+ persist(ID_CACHE, Key.class, ChangeKind.class)
+ .maximumWeight(2 << 20)
+ .weigher(ChangeKindWeigher.class)
+ .loader(Loader.class);
+ }
+ };
+ }
+
+ @VisibleForTesting
+ public static class NoCache implements ChangeKindCache {
+ private final boolean useRecursiveMerge;
+
+ @Inject
+ NoCache(
+ @GerritServerConfig Config serverConfig) {
+ this.useRecursiveMerge = MergeUtil.useRecursiveMerge(serverConfig);
+ }
+
+ @Override
+ public ChangeKind getChangeKind(ProjectState project, Repository repo,
+ ObjectId prior, ObjectId next) {
+ try {
+ return new Loader().load(
+ new Key(project, repo, prior, next, useRecursiveMerge));
+ } catch (IOException e) {
+ log.warn("Cannot check trivial rebase of new patch set " + next.name()
+ + " in " + project.getProject().getName(), e);
+ return ChangeKind.REWORK;
+ }
+ }
+ }
+
+ private static class Key implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private transient ObjectId prior;
+ private transient ObjectId next;
+ private transient String strategyName;
+
+ private transient Repository repo; // Passed through to loader on miss.
+
+ private Key(ProjectState project, Repository repo, ObjectId prior,
+ ObjectId next, boolean useRecursiveMerge) {
+ checkNotNull(next, "next");
+ String strategyName = MergeUtil.mergeStrategyName(
+ project.isUseContentMerge(), useRecursiveMerge);
+ this.prior = prior.copy();
+ this.next = next.copy();
+ this.strategyName = strategyName;
+ this.repo = repo;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Key) {
+ Key k = (Key) o;
+ return Objects.equal(prior, k.prior)
+ && Objects.equal(next, k.next)
+ && Objects.equal(strategyName, k.strategyName);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(prior, next, strategyName);
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ writeNotNull(out, prior);
+ writeNotNull(out, next);
+ out.writeUTF(strategyName);
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException {
+ prior = readNotNull(in);
+ next = readNotNull(in);
+ strategyName = in.readUTF();
+ }
+ }
+
+ @Singleton
+ private static class Loader extends CacheLoader<Key, ChangeKind> {
+ @Override
+ public ChangeKind load(Key key) throws IOException {
+ RevWalk walk = new RevWalk(key.repo);
+ try {
+ RevCommit prior = walk.parseCommit(key.prior);
+ walk.parseBody(prior);
+ RevCommit next = walk.parseCommit(key.next);
+ walk.parseBody(next);
+
+ if (!next.getFullMessage().equals(prior.getFullMessage())) {
+ if (next.getTree() == prior.getTree() && isSameParents(prior, next)) {
+ return ChangeKind.NO_CODE_CHANGE;
+ } else {
+ return ChangeKind.REWORK;
+ }
+ }
+
+ if (prior.getParentCount() != 1 || next.getParentCount() != 1) {
+ // Trivial rebases done by machine only work well on 1 parent.
+ return ChangeKind.REWORK;
+ }
+
+ if (next.getTree() == prior.getTree() &&
+ isSameParents(prior, next)) {
+ return ChangeKind.TRIVIAL_REBASE;
+ }
+
+ // A trivial rebase can be detected by looking for the next commit
+ // having the same tree as would exist when the prior commit is
+ // cherry-picked onto the next commit's new first parent.
+ ThreeWayMerger merger = MergeUtil.newThreeWayMerger(
+ key.repo, MergeUtil.createDryRunInserter(), key.strategyName);
+ merger.setBase(prior.getParent(0));
+ if (merger.merge(next.getParent(0), prior)
+ && merger.getResultTreeId().equals(next.getTree())) {
+ return ChangeKind.TRIVIAL_REBASE;
+ } else {
+ return ChangeKind.REWORK;
+ }
+ } finally {
+ key.repo = null;
+ walk.release();
+ }
+ }
+
+ private static boolean isSameParents(RevCommit prior, RevCommit next) {
+ if (prior.getParentCount() != next.getParentCount()) {
+ return false;
+ } else if (prior.getParentCount() == 0) {
+ return true;
+ }
+ return prior.getParent(0).equals(next.getParent(0));
+ }
+ }
+
+ public static class ChangeKindWeigher implements Weigher<Key, ChangeKind> {
+ @Override
+ public int weigh(Key key, ChangeKind changeKind) {
+ return 16 + 2*36 + 2*key.strategyName.length() // Size of Key, 64 bit JVM
+ + 2*changeKind.name().length(); // Size of ChangeKind, 64 bit JVM
+ }
+ }
+
+ private final LoadingCache<Key, ChangeKind> cache;
+ private final boolean useRecursiveMerge;
+
+ @Inject
+ ChangeKindCacheImpl(
+ @GerritServerConfig Config serverConfig,
+ @Named(ID_CACHE) LoadingCache<Key, ChangeKind> cache) {
+ this.cache = cache;
+ this.useRecursiveMerge = MergeUtil.useRecursiveMerge(serverConfig);
+ }
+
+ @Override
+ public ChangeKind getChangeKind(ProjectState project, Repository repo,
+ ObjectId prior, ObjectId next) {
+ try {
+ return cache.get(new Key(project, repo, prior, next, useRecursiveMerge));
+ } catch (ExecutionException e) {
+ log.warn("Cannot check trivial rebase of new patch set " + next.name()
+ + " in " + project.getProject().getName(), e);
+ return ChangeKind.REWORK;
+ }
+ }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
index f09cd7c..d0abfcb 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
@@ -68,7 +68,7 @@
import com.google.gerrit.server.auth.UniversalAuthBackend;
import com.google.gerrit.server.avatar.AvatarProvider;
import com.google.gerrit.server.cache.CacheRemovalListener;
-import com.google.gerrit.server.change.ChangeKindCache;
+import com.google.gerrit.server.change.ChangeKindCacheImpl;
import com.google.gerrit.server.change.MergeabilityChecker;
import com.google.gerrit.server.events.EventFactory;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
@@ -155,7 +155,7 @@
install(AccountByEmailCacheImpl.module());
install(AccountCacheImpl.module());
install(ChangeCache.module());
- install(ChangeKindCache.module());
+ install(ChangeKindCacheImpl.module());
install(ConflictsCacheImpl.module());
install(GroupCacheImpl.module());
install(GroupIncludeCacheImpl.module());