Package org.apache.lucene.search

Source Code of org.apache.lucene.search.TestNRTManager$LatchedIndexWriter

package org.apache.lucene.search;

/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/

import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.CorruptIndexException;
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.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.NRTCachingDirectory;
import org.apache.lucene.util.IOUtils;
import org.apache.lucene.util.ThreadInterruptedException;

public class TestNRTManager extends ThreadedIndexingAndSearchingTestCase {

  private final ThreadLocal<Long> lastGens = new ThreadLocal<Long>();
  private boolean warmCalled;

  public void testNRTManager() throws Exception {
    runTest("TestNRTManager");
  }

  @Override
  protected IndexSearcher getFinalSearcher() throws Exception  {
    if (VERBOSE) {
      System.out.println("TEST: finalSearcher maxGen=" + maxGen);
    }
    final SearcherManager manager = nrt.waitForGeneration(maxGen, true);
    return manager.acquire();
  }

  @Override
  protected Directory getDirectory(Directory in) {
    // Randomly swap in NRTCachingDir
    if (random.nextBoolean()) {
      if (VERBOSE) {
        System.out.println("TEST: wrap NRTCachingDir");
      }

      return new NRTCachingDirectory(in, 5.0, 60.0);
    } else {
      return in;
    }
  }

  @Override
  protected void updateDocuments(Term id, Collection<Document> docs) throws Exception {
    final long gen = nrt.updateDocuments(id, docs);

    // Randomly verify the update "took":
    if (random.nextInt(20) == 2) {
      if (VERBOSE) {
        System.out.println(Thread.currentThread().getName() + ": nrt: verify " + id);
      }
      SearcherManager manager = nrt.waitForGeneration(gen, true);
      final IndexSearcher s = manager.acquire();
      if (VERBOSE) {
        System.out.println(Thread.currentThread().getName() + ": nrt: got searcher=" + s);
      }
      try {
        assertEquals(docs.size(), s.search(new TermQuery(id), 10).totalHits);
      } finally {
        manager.release(s);
      }
    }
   
    lastGens.set(gen);
  }

  @Override
  protected void addDocuments(Term id, Collection<Document> docs) throws Exception {
    final long gen = nrt.addDocuments(docs);
    // Randomly verify the add "took":
    if (random.nextInt(20) == 2) {
      if (VERBOSE) {
        System.out.println(Thread.currentThread().getName() + ": nrt: verify " + id);
      }
      final SearcherManager manager = nrt.waitForGeneration(gen, false);
      final IndexSearcher s = manager.acquire();
      if (VERBOSE) {
        System.out.println(Thread.currentThread().getName() + ": nrt: got searcher=" + s);
      }
      try {
        assertEquals(docs.size(), s.search(new TermQuery(id), 10).totalHits);
      } finally {
        manager.release(s);
      }
    }
    lastGens.set(gen);
  }

  @Override
  protected void addDocument(Term id, Document doc) throws Exception {
    final long gen = nrt.addDocument(doc);

    // Randomly verify the add "took":
    if (random.nextInt(20) == 2) {
      if (VERBOSE) {
        System.out.println(Thread.currentThread().getName() + ": nrt: verify " + id);
      }
      final SearcherManager manager = nrt.waitForGeneration(gen, false);
      final IndexSearcher s = manager.acquire();
      if (VERBOSE) {
        System.out.println(Thread.currentThread().getName() + ": nrt: got searcher=" + s);
      }
      try {
        assertEquals(1, s.search(new TermQuery(id), 10).totalHits);
      } finally {
        manager.release(s);
      }
    }
    lastGens.set(gen);
  }

  @Override
  protected void updateDocument(Term id, Document doc) throws Exception {
    final long gen = nrt.updateDocument(id, doc);
    // Randomly verify the udpate "took":
    if (random.nextInt(20) == 2) {
      if (VERBOSE) {
        System.out.println(Thread.currentThread().getName() + ": nrt: verify " + id);
      }
      final SearcherManager manager = nrt.waitForGeneration(gen, true);
      final IndexSearcher s = manager.acquire();
      if (VERBOSE) {
        System.out.println(Thread.currentThread().getName() + ": nrt: got searcher=" + s);
      }
      try {
        assertEquals(1, s.search(new TermQuery(id), 10).totalHits);
      } finally {
        manager.release(s);
      }
    }
    lastGens.set(gen);
  }

  @Override
  protected void deleteDocuments(Term id) throws Exception {
    final long gen = nrt.deleteDocuments(id);
    // randomly verify the delete "took":
    if (random.nextInt(20) == 7) {
      if (VERBOSE) {
        System.out.println(Thread.currentThread().getName() + ": nrt: verify del " + id);
      }
      final SearcherManager manager = nrt.waitForGeneration(gen, true);
      final IndexSearcher s = manager.acquire();
      if (VERBOSE) {
        System.out.println(Thread.currentThread().getName() + ": nrt: got searcher=" + s);
      }
      try {
        assertEquals(0, s.search(new TermQuery(id), 10).totalHits);
      } finally {
        manager.release(s);
      }
    }
    lastGens.set(gen);
  }

  private NRTManager nrt;
  private NRTManagerReopenThread nrtThread;
  @Override
  protected void doAfterWriter(ExecutorService es) throws Exception {
    final double minReopenSec = 0.01 + 0.05 * random.nextDouble();
    final double maxReopenSec = minReopenSec * (1.0 + 10 * random.nextDouble());

    if (VERBOSE) {
      System.out.println("TEST: make NRTManager maxReopenSec=" + maxReopenSec + " minReopenSec=" + minReopenSec);
    }

    nrt = new NRTManager(writer, es,
                         new SearcherWarmer() {
                           // Not with Java 5: @Override
                           public void warm(IndexSearcher s) throws IOException {
                             TestNRTManager.this.warmCalled = true;
                             s.search(new TermQuery(new Term("body", "united")), 10);
                           }
                         }, false);
                        
    nrtThread = new NRTManagerReopenThread(nrt, maxReopenSec, minReopenSec);
    nrtThread.setName("NRT Reopen Thread");
    nrtThread.setPriority(Math.min(Thread.currentThread().getPriority()+2, Thread.MAX_PRIORITY));
    nrtThread.setDaemon(true);
    nrtThread.start();
  }

  @Override
  protected void doAfterIndexingThreadDone() {
    Long gen = lastGens.get();
    if (gen != null) {
      addMaxGen(gen);
    }
  }

  private long maxGen = -1;

  private synchronized void addMaxGen(long gen) {
    maxGen = Math.max(gen, maxGen);
  }

  @Override
  protected void doSearching(ExecutorService es, long stopTime) throws Exception {
    runSearchThreads(stopTime);
  }

  @Override
  protected IndexSearcher getCurrentSearcher() throws Exception {
    // Test doesn't assert deletions until the end, so we
    // can randomize whether dels must be applied
    return nrt.getSearcherManager(random.nextBoolean()).acquire();
  }

  @Override
  protected void releaseSearcher(IndexSearcher s) throws Exception {
    // Test doesn't assert deletions until the end, so we
    // can randomize whether dels must be applied
    nrt.getSearcherManager(random.nextBoolean()).release(s);
  }

  @Override
  protected void doClose() throws Exception {
    assertTrue(warmCalled);
    if (VERBOSE) {
      System.out.println("TEST: now close NRTManager");
    }
    nrtThread.close();
    nrt.close();
  }
 
  /*
   * LUCENE-3528 - NRTManager hangs in certain situations
   */
  public void testThreadStarvationNoDeleteNRTReader() throws IOException, InterruptedException {
    IndexWriterConfig conf = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random));
    Directory d = newDirectory();
    final CountDownLatch latch = new CountDownLatch(1);
    final CountDownLatch signal = new CountDownLatch(1);

    LatchedIndexWriter writer = new LatchedIndexWriter(d, conf, latch, signal);
    final NRTManager manager = new NRTManager(writer, null, null, false);
    Document doc = new Document();
    doc.add(newField("test","test", Store.YES, Index.ANALYZED));
    long gen = manager.addDocument(doc);
    assertTrue(manager.maybeReopen(false));
    assertFalse(gen < manager.getCurrentSearchingGen(false));
    Thread t = new Thread() {
      public void run() {
        try {
          signal.await();
          assertTrue(manager.maybeReopen(false));
          manager.deleteDocuments(new TermQuery(new Term("foo", "barista")));
          manager.maybeReopen(false); // kick off another reopen so we inc. the internal gen
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
          latch.countDown(); // let the add below finish
        }
      }
    };
    t.start();
    writer.waitAfterUpdate = true; // wait in addDocument to let some reopens go through
    final long lastGen = manager.updateDocument(new Term("foo", "bar"), doc); // once this returns the doc is already reflected in the last reopen
    assertFalse(manager.getSearcherManager(false).isSearcherCurrent()); // false since there is a delete in the queue
   
    IndexSearcher acquire = manager.getSearcherManager(false).acquire();
    try {
      assertEquals(2, acquire.getIndexReader().numDocs());
    } finally {
      acquire.getIndexReader().decRef();
    }
    NRTManagerReopenThread thread = new NRTManagerReopenThread(manager, 0.01, 0.01);
    thread.start(); // start reopening
    if (VERBOSE) {
      System.out.println("waiting now for generation " + lastGen);
    }
   
    final AtomicBoolean finished = new AtomicBoolean(false);
    Thread waiter = new Thread() {
      public void run() {
        manager.waitForGeneration(lastGen, false);
        finished.set(true);
      }
    };
    waiter.start();
    manager.maybeReopen(false);
    waiter.join(1000);
    if (!finished.get()) {
      waiter.interrupt();
      fail("thread deadlocked on waitForGeneration");
    }
    thread.close();
    thread.join();
    IOUtils.close(manager, writer, d);
  }
 
  public static class LatchedIndexWriter extends IndexWriter {

    private CountDownLatch latch;
    boolean waitAfterUpdate = false;
    private CountDownLatch signal;

    public LatchedIndexWriter(Directory d, IndexWriterConfig conf,
        CountDownLatch latch, CountDownLatch signal)
        throws CorruptIndexException, LockObtainFailedException, IOException {
      super(d, conf);
      this.latch = latch;
      this.signal = signal;

    }

    public void updateDocument(Term term,
        Document doc, Analyzer analyzer)
        throws CorruptIndexException, IOException {
      super.updateDocument(term, doc, analyzer);
      try {
        if (waitAfterUpdate) {
          signal.countDown();
          latch.await();
        }
      } catch (InterruptedException e) {
        throw new ThreadInterruptedException(e);
      }
    }
  }
}
TOP

Related Classes of org.apache.lucene.search.TestNRTManager$LatchedIndexWriter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.