shai, seems like you missed the CHANGES.TXT from branch_3x?

simon

On Tue, Feb 14, 2012 at 4:36 PM,  <sh...@apache.org> wrote:
> Author: shaie
> Date: Tue Feb 14 15:36:14 2012
> New Revision: 1244000
>
> URL: http://svn.apache.org/viewvc?rev=1244000&view=rev
> Log:
> LUCENE-3761: generalize SearcherManager (port to trunk)
>
> Added:
>    
> lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ReferenceManager.java
>      - copied unchanged from r1243906, 
> lucene/dev/branches/branch_3x/lucene/core/src/java/org/apache/lucene/search/ReferenceManager.java
> Modified:
>    lucene/dev/trunk/   (props changed)
>    lucene/dev/trunk/lucene/   (props changed)
>    
> lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManager.java
>    
> lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java
>    
> lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java
>    
> lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/ShardSearchingTestBase.java
>
> Modified: 
> lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManager.java
> URL: 
> http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManager.java?rev=1244000&r1=1243999&r2=1244000&view=diff
> ==============================================================================
> --- 
> lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManager.java
>  (original)
> +++ 
> lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManager.java
>  Tue Feb 14 15:36:14 2012
> @@ -343,7 +343,7 @@ public class NRTManager implements Close
>         }
>         boolean setSearchGen;
>         if (!mgr.isSearcherCurrent()) {
> -          setSearchGen = mgr.maybeReopen();
> +          setSearchGen = mgr.maybeRefresh();
>         } else {
>           setSearchGen = true;
>         }
>
> Modified: 
> lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java
> URL: 
> http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java?rev=1244000&r1=1243999&r2=1244000&view=diff
> ==============================================================================
> --- 
> lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java
>  (original)
> +++ 
> lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java
>  Tue Feb 14 15:36:14 2012
> @@ -17,17 +17,11 @@ package org.apache.lucene.search;
>  * limitations under the License.
>  */
>
> -import java.io.Closeable;
>  import java.io.IOException;
> -import java.util.concurrent.Semaphore;
>
> -import org.apache.lucene.index.CorruptIndexException;
>  import org.apache.lucene.index.IndexReader;
>  import org.apache.lucene.index.DirectoryReader;
>  import org.apache.lucene.index.IndexWriter;
> -import org.apache.lucene.search.NRTManager; // javadocs
> -import org.apache.lucene.search.IndexSearcher; // javadocs
> -import org.apache.lucene.store.AlreadyClosedException;
>  import org.apache.lucene.store.Directory;
>
>  /**
> @@ -51,42 +45,40 @@ import org.apache.lucene.store.Directory
>  * </pre>
>  *
>  * <p>
> - * In addition you should periodically call {@link #maybeReopen}. While it's
> + * In addition you should periodically call {@link #maybeRefresh}. While it's
>  * possible to call this just before running each query, this is discouraged
>  * since it penalizes the unlucky queries that do the reopen. It's better to 
> use
>  * a separate background thread, that periodically calls maybeReopen. Finally,
>  * be sure to call {@link #close} once you are done.
>  *
> - * <p>
> - * <b>NOTE</b>: if you have an {@link IndexWriter}, it's better to use
> - * {@link NRTManager} since that class pulls near-real-time readers from the
> - * IndexWriter.
> - *
>  * @see SearcherFactory
>  *
>  * @lucene.experimental
>  */
> +public final class SearcherManager extends ReferenceManager<IndexSearcher> {
>
> -public final class SearcherManager implements Closeable {
> -
> -  private volatile IndexSearcher currentSearcher;
>   private final SearcherFactory searcherFactory;
> -  private final Semaphore reopenLock = new Semaphore(1);
> -
> +
>   /**
> -   * Creates and returns a new SearcherManager from the given {@link 
> IndexWriter}.
> -   * @param writer the IndexWriter to open the IndexReader from.
> -   * @param applyAllDeletes If <code>true</code>, all buffered deletes will
> -   *        be applied (made visible) in the {@link IndexSearcher} / {@link 
> DirectoryReader}.
> -   *        If <code>false</code>, the deletes may or may not be applied, 
> but remain buffered
> -   *        (in IndexWriter) so that they will be applied in the future.
> -   *        Applying deletes can be costly, so if your app can tolerate 
> deleted documents
> -   *        being returned you might gain some performance by passing 
> <code>false</code>.
> -   *        See {@link DirectoryReader#openIfChanged(DirectoryReader, 
> IndexWriter, boolean)}.
> -   * @param searcherFactory An optional {@link SearcherFactory}. Pass
> -   *        <code>null</code> if you don't require the searcher to be warmed
> -   *        before going live or other custom behavior.
> -   *
> +   * Creates and returns a new SearcherManager from the given
> +   * {@link IndexWriter}.
> +   *
> +   * @param writer
> +   *          the IndexWriter to open the IndexReader from.
> +   * @param applyAllDeletes
> +   *          If <code>true</code>, all buffered deletes will be applied 
> (made
> +   *          visible) in the {@link IndexSearcher} / {@link 
> DirectoryReader}.
> +   *          If <code>false</code>, the deletes may or may not be applied, 
> but
> +   *          remain buffered (in IndexWriter) so that they will be applied 
> in
> +   *          the future. Applying deletes can be costly, so if your app can
> +   *          tolerate deleted documents being returned you might gain some
> +   *          performance by passing <code>false</code>. See
> +   *          {@link DirectoryReader#openIfChanged(DirectoryReader, 
> IndexWriter, boolean)}.
> +   * @param searcherFactory
> +   *          An optional {@link SearcherFactory}. Pass <code>null</code> if 
> you
> +   *          don't require the searcher to be warmed before going live or 
> other
> +   *          custom behavior.
> +   *
>    * @throws IOException
>    */
>   public SearcherManager(IndexWriter writer, boolean applyAllDeletes, 
> SearcherFactory searcherFactory) throws IOException {
> @@ -94,7 +86,29 @@ public final class SearcherManager imple
>       searcherFactory = new SearcherFactory();
>     }
>     this.searcherFactory = searcherFactory;
> -    currentSearcher = 
> searcherFactory.newSearcher(DirectoryReader.open(writer, applyAllDeletes));
> +    current = searcherFactory.newSearcher(DirectoryReader.open(writer, 
> applyAllDeletes));
> +  }
> +
> +  @Override
> +  protected void decRef(IndexSearcher reference) throws IOException {
> +    reference.getIndexReader().decRef();
> +  }
> +
> +  @Override
> +  protected IndexSearcher refreshIfNeeded(IndexSearcher referenceToRefresh) 
> throws IOException {
> +    final IndexReader r = referenceToRefresh.getIndexReader();
> +    final IndexReader newReader = (r instanceof DirectoryReader) ?
> +      DirectoryReader.openIfChanged((DirectoryReader) r) : null;
> +    if (newReader == null) {
> +      return null;
> +    } else {
> +      return searcherFactory.newSearcher(newReader);
> +    }
> +  }
> +
> +  @Override
> +  protected boolean tryIncRef(IndexSearcher reference) {
> +    return reference.getIndexReader().tryIncRef();
>   }
>
>   /**
> @@ -111,75 +125,15 @@ public final class SearcherManager imple
>       searcherFactory = new SearcherFactory();
>     }
>     this.searcherFactory = searcherFactory;
> -    currentSearcher = searcherFactory.newSearcher(DirectoryReader.open(dir));
> +    current = searcherFactory.newSearcher(DirectoryReader.open(dir));
>   }
>
>   /**
> -   * You must call this, periodically, to perform a reopen. This calls
> -   * {@link DirectoryReader#openIfChanged(DirectoryReader)} with the 
> underlying reader, and if that returns a
> -   * new reader, it's warmed (if you provided a {@link SearcherFactory} and 
> then
> -   * swapped into production.
> -   *
> -   * <p>
> -   * <b>Threads</b>: it's fine for more than one thread to call this at once.
> -   * Only the first thread will attempt the reopen; subsequent threads will 
> see
> -   * that another thread is already handling reopen and will return 
> immediately.
> -   * Note that this means if another thread is already reopening then 
> subsequent
> -   * threads will return right away without waiting for the reader reopen to
> -   * complete.
> -   * </p>
> -   *
> -   * <p>
> -   * This method returns true if a new reader was in fact opened or
> -   * if the current searcher has no pending changes.
> -   * </p>
> -   */
> -  public boolean maybeReopen() throws IOException {
> -    ensureOpen();
> -    // Ensure only 1 thread does reopen at once; other
> -    // threads just return immediately:
> -    if (reopenLock.tryAcquire()) {
> -      try {
> -        // IR.openIfChanged preserves NRT and applyDeletes
> -        // in the newly returned reader:
> -        final IndexReader newReader;
> -        final IndexSearcher searcherToReopen = acquire();
> -        try {
> -          final IndexReader r = searcherToReopen.getIndexReader();
> -          newReader = (r instanceof DirectoryReader) ?
> -            DirectoryReader.openIfChanged((DirectoryReader) r) :
> -            null;
> -        } finally {
> -          release(searcherToReopen);
> -        }
> -        if (newReader != null) {
> -          final IndexSearcher newSearcher = 
> searcherFactory.newSearcher(newReader);
> -          boolean success = false;
> -          try {
> -            swapSearcher(newSearcher);
> -            success = true;
> -          } finally {
> -            if (!success) {
> -              release(newSearcher);
> -            }
> -          }
> -        }
> -        return true;
> -      } finally {
> -        reopenLock.release();
> -      }
> -    } else {
> -      return false;
> -    }
> -  }
> -
> -  /**
>    * Returns <code>true</code> if no changes have occured since this searcher
>    * ie. reader was opened, otherwise <code>false</code>.
>    * @see DirectoryReader#isCurrent()
>    */
> -  public boolean isSearcherCurrent() throws CorruptIndexException,
> -      IOException {
> +  public boolean isSearcherCurrent() throws IOException {
>     final IndexSearcher searcher = acquire();
>     try {
>       final IndexReader r = searcher.getIndexReader();
> @@ -190,56 +144,5 @@ public final class SearcherManager imple
>       release(searcher);
>     }
>   }
> -
> -  /**
> -   * Release the searcher previously obtained with {@link #acquire}.
> -   *
> -   * <p>
> -   * <b>NOTE</b>: it's safe to call this after {@link #close}.
> -   */
> -  public void release(IndexSearcher searcher) throws IOException {
> -    assert searcher != null;
> -    searcher.getIndexReader().decRef();
> -  }
> -
> -  /**
> -   * Close this SearcherManager to future searching. Any searches still in
> -   * process in other threads won't be affected, and they should still call
> -   * {@link #release} after they are done.
> -   */
> -  public synchronized void close() throws IOException {
> -    if (currentSearcher != null) {
> -      // make sure we can call this more than once
> -      // closeable javadoc says:
> -      // if this is already closed then invoking this method has no effect.
> -      swapSearcher(null);
> -    }
> -  }
> -
> -  /**
> -   * Obtain the current IndexSearcher. You must match every call to acquire 
> with
> -   * one call to {@link #release}; it's best to do so in a finally clause.
> -   */
> -  public IndexSearcher acquire() {
> -    IndexSearcher searcher;
> -    do {
> -      if ((searcher = currentSearcher) == null) {
> -        throw new AlreadyClosedException("this SearcherManager is closed");
> -      }
> -    } while (!searcher.getIndexReader().tryIncRef());
> -    return searcher;
> -  }
> -
> -  private void ensureOpen() {
> -    if (currentSearcher == null) {
> -      throw new AlreadyClosedException("this SearcherManager is closed");
> -    }
> -  }
> -
> -  private synchronized void swapSearcher(IndexSearcher newSearcher) throws 
> IOException {
> -    ensureOpen();
> -    final IndexSearcher oldSearcher = currentSearcher;
> -    currentSearcher = newSearcher;
> -    release(oldSearcher);
> -  }
> +
>  }
>
> Modified: 
> lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java
> URL: 
> http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java?rev=1244000&r1=1243999&r2=1244000&view=diff
> ==============================================================================
> --- 
> lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java
>  (original)
> +++ 
> lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java
>  Tue Feb 14 15:36:14 2012
> @@ -31,9 +31,9 @@ import org.apache.lucene.document.Docume
>  import org.apache.lucene.index.ConcurrentMergeScheduler;
>  import org.apache.lucene.index.IndexReader;
>  import org.apache.lucene.index.IndexWriter;
> +import org.apache.lucene.index.IndexWriterConfig;
>  import org.apache.lucene.index.Term;
>  import org.apache.lucene.index.ThreadedIndexingAndSearchingTestCase;
> -import org.apache.lucene.search.SearcherFactory;
>  import org.apache.lucene.store.AlreadyClosedException;
>  import org.apache.lucene.store.Directory;
>  import org.apache.lucene.util.LuceneTestCase.UseNoMemoryExpensiveCodec;
> @@ -57,7 +57,7 @@ public class TestSearcherManager extends
>     if (!isNRT) {
>       writer.commit();
>     }
> -    assertTrue(mgr.maybeReopen() || mgr.isSearcherCurrent());
> +    assertTrue(mgr.maybeRefresh() || mgr.isSearcherCurrent());
>     return mgr.acquire();
>   }
>
> @@ -105,7 +105,7 @@ public class TestSearcherManager extends
>             Thread.sleep(_TestUtil.nextInt(random, 1, 100));
>             writer.commit();
>             Thread.sleep(_TestUtil.nextInt(random, 1, 5));
> -            if (mgr.maybeReopen()) {
> +            if (mgr.maybeRefresh()) {
>               lifetimeMGR.prune(pruner);
>             }
>           }
> @@ -134,7 +134,7 @@ public class TestSearcherManager extends
>       // synchronous to your search threads, but still we
>       // test as apps will presumably do this for
>       // simplicity:
> -      if (mgr.maybeReopen()) {
> +      if (mgr.maybeRefresh()) {
>         lifetimeMGR.prune(pruner);
>       }
>     }
> @@ -237,7 +237,7 @@ public class TestSearcherManager extends
>           if (VERBOSE) {
>             System.out.println("NOW call maybeReopen");
>           }
> -          searcherManager.maybeReopen();
> +          searcherManager.maybeRefresh();
>           success.set(true);
>         } catch (AlreadyClosedException e) {
>           // expected
> @@ -280,4 +280,41 @@ public class TestSearcherManager extends
>       es.awaitTermination(1, TimeUnit.SECONDS);
>     }
>   }
> +
> +  public void testCloseTwice() throws Exception {
> +    // test that we can close SM twice (per Closeable's contract).
> +    Directory dir = newDirectory();
> +    new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, 
> null)).close();
> +    SearcherManager sm = new SearcherManager(dir, null);
> +    sm.close();
> +    sm.close();
> +    dir.close();
> +  }
> +
> +  public void testEnsureOpen() throws Exception {
> +    Directory dir = newDirectory();
> +    new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, 
> null)).close();
> +    SearcherManager sm = new SearcherManager(dir, null);
> +    IndexSearcher s = sm.acquire();
> +    sm.close();
> +
> +    // this should succeed;
> +    sm.release(s);
> +
> +    try {
> +      // this should fail
> +      sm.acquire();
> +    } catch (AlreadyClosedException e) {
> +      // ok
> +    }
> +
> +    try {
> +      // this should fail
> +      sm.maybeRefresh();
> +    } catch (AlreadyClosedException e) {
> +      // ok
> +    }
> +    dir.close();
> +  }
> +
>  }
>
> Modified: 
> lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/ShardSearchingTestBase.java
> URL: 
> http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/ShardSearchingTestBase.java?rev=1244000&r1=1243999&r2=1244000&view=diff
> ==============================================================================
> --- 
> lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/ShardSearchingTestBase.java
>  (original)
> +++ 
> lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/ShardSearchingTestBase.java
>  Tue Feb 14 15:36:14 2012
> @@ -485,7 +485,7 @@ public abstract class ShardSearchingTest
>       final IndexSearcher before = mgr.acquire();
>       mgr.release(before);
>
> -      mgr.maybeReopen();
> +      mgr.maybeRefresh();
>       final IndexSearcher after = mgr.acquire();
>       try {
>         if (after != before) {
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@lucene.apache.org
For additional commands, e-mail: dev-h...@lucene.apache.org

Reply via email to