Merge branch 'stable-2.8' into stable-2.9

* stable-2.8:
  SideBySide2: Show [ and ] shortcut keys in nav arrow tooltips
  Always auto confirm adding reviewers for set-reviewers SSH command
  Improve wording of 'parents' field description in CommitInfo
  Fix 'parents' field name of CommitInfo in REST documentation
  Implement pagination in project list screen
  Add option 'S' to projects REST API to support query offset
  Fix: Failure of acceptance tests.
  Do not refresh project list if filter did not change
  Fix inconsistent behavior of diff view when viewing binary files
  Update cookbook plugin to latest revision
  Correct Javadoc of RestReadView in extension API
  Fix memory leak of SubIndex.NrtFuture objects

Conflicts:
	gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
	gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java
	gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java

Change-Id: I4d432c6ce27d3fd76dd9f86b8685be15ec8f123d
This commit is contained in:
David Pursehouse
2014-04-10 16:52:33 +09:00
17 changed files with 220 additions and 61 deletions

View File

@@ -16,7 +16,7 @@ package com.google.gerrit.lucene;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.AbstractFuture;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
@@ -39,13 +39,12 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ConcurrentMap;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
/** Piece of the change index that is implemented as a separate Lucene index. */
class SubIndex {
@@ -55,7 +54,7 @@ class SubIndex {
private final TrackingIndexWriter writer;
private final SearcherManager searcherManager;
private final ControlledRealTimeReopenThread<IndexSearcher> reopenThread;
private final ConcurrentMap<RefreshListener, Boolean> refreshListeners;
private final Set<NrtFuture> notDoneNrtFutures;
SubIndex(File file, GerritIndexWriterConfig writerConfig) throws IOException {
this(FSDirectory.open(file), file.getName(), writerConfig);
@@ -107,7 +106,7 @@ class SubIndex {
searcherManager = new SearcherManager(
writer.getIndexWriter(), true, new SearcherFactory());
refreshListeners = Maps.newConcurrentMap();
notDoneNrtFutures = Sets.newConcurrentHashSet();
searcherManager.addListener(new RefreshListener() {
@Override
public void beforeRefresh() throws IOException {
@@ -115,8 +114,8 @@ class SubIndex {
@Override
public void afterRefresh(boolean didRefresh) throws IOException {
for (RefreshListener l : refreshListeners.keySet()) {
l.afterRefresh(didRefresh);
for (NrtFuture f : notDoneNrtFutures) {
f.removeIfDone();
}
}
});
@@ -176,10 +175,8 @@ class SubIndex {
searcherManager.release(searcher);
}
private final class NrtFuture extends AbstractFuture<Void>
implements RefreshListener {
private final class NrtFuture extends AbstractFuture<Void> {
private final long gen;
private final AtomicBoolean hasListeners = new AtomicBoolean();
NrtFuture(long gen) {
this.gen = gen;
@@ -198,9 +195,12 @@ class SubIndex {
public Void get(long timeout, TimeUnit unit) throws InterruptedException,
TimeoutException, ExecutionException {
if (!isDone()) {
reopenThread.waitForGeneration(gen,
(int) MILLISECONDS.convert(timeout, unit));
set(null);
if (reopenThread.waitForGeneration(gen,
(int) MILLISECONDS.convert(timeout, unit))) {
set(null);
} else {
throw new TimeoutException();
}
}
return super.get(timeout, unit);
}
@@ -209,7 +209,7 @@ class SubIndex {
public boolean isDone() {
if (super.isDone()) {
return true;
} else if (isSearcherCurrent()) {
} else if (isGenAvailableNowForCurrentSearcher()) {
set(null);
return true;
}
@@ -218,33 +218,31 @@ class SubIndex {
@Override
public void addListener(Runnable listener, Executor executor) {
if (hasListeners.compareAndSet(false, true) && !isDone()) {
searcherManager.addListener(this);
if (!isDone()) {
notDoneNrtFutures.add(this);
}
super.addListener(listener, executor);
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
if (hasListeners.get()) {
refreshListeners.put(this, true);
boolean result = super.cancel(mayInterruptIfRunning);
if (result) {
notDoneNrtFutures.remove(this);
}
return super.cancel(mayInterruptIfRunning);
return result;
}
@Override
public void beforeRefresh() throws IOException {
}
@Override
public void afterRefresh(boolean didRefresh) throws IOException {
if (isSearcherCurrent()) {
refreshListeners.remove(this);
set(null);
void removeIfDone() {
if (isGenAvailableNowForCurrentSearcher()) {
notDoneNrtFutures.remove(this);
if (!isCancelled()) {
set(null);
}
}
}
private boolean isSearcherCurrent() {
private boolean isGenAvailableNowForCurrentSearcher() {
try {
return reopenThread.waitForGeneration(gen, 0);
} catch (InterruptedException e) {