diff options
author | Bruce Zu <bruce.zu@sonymobile.com> | 2014-03-28 10:40:50 +0800 |
---|---|---|
committer | Bruce Zu <bruce.zu@sonymobile.com> | 2014-04-03 13:34:15 +0800 |
commit | 4174e56a9a0597a4c5f233ab0f3f28c9faf757ec (patch) | |
tree | 5c8010db3cbe8c605a25264ae31baf47ad520c84 | |
parent | 902686a8d8d1998ca85999835f54f0ee7178c0ef (diff) |
Fix memory leak of SubIndex.NrtFuture objects
The SubIndex.NrtFuture objects are added as listeners of
searchManager who was found to hold on to them forever.
Fixed. There are also some code refactoring in NrtFuture.
Change-Id: If87cb62890a1cfa6c6336f6c7953a1cb56d42937
-rw-r--r-- | gerrit-lucene/src/main/java/com/google/gerrit/lucene/SubIndex.java | 56 |
1 files changed, 27 insertions, 29 deletions
diff --git a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/SubIndex.java b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/SubIndex.java index d9f7fd900e..4233a8fe4b 100644 --- a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/SubIndex.java +++ b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/SubIndex.java @@ -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; @@ -38,13 +38,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 { @@ -54,7 +53,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); @@ -106,7 +105,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 { @@ -114,8 +113,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(); } } }); @@ -171,10 +170,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; @@ -193,9 +190,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); } @@ -204,7 +204,7 @@ class SubIndex { public boolean isDone() { if (super.isDone()) { return true; - } else if (isSearcherCurrent()) { + } else if (isGenAvailableNowForCurrentSearcher()) { set(null); return true; } @@ -213,33 +213,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) { |