/** Closes the factory. */
  public void close() {
    InternalIndexReader tmpReader = null;
    tmpReader = _oldReader;

    _oldReader = null;

    try {
      // close the old reader
      if (tmpReader != null) {
        try {
          tmpReader.dispose();
        } catch (IOException e) {
          log.error("Problem closing reader", e);
        }
      }
    } finally {
      // close the current reader
      tmpReader = _currentReader;
      _currentReader = null;

      if (tmpReader != null) {
        try {
          tmpReader.dispose();
        } catch (IOException e) {
          log.error("Problem closing reader", e);
        }
      }
    }
  }
  /**
   * get a fresh new reader instance
   *
   * @return an IndexReader instance, can be null if index does not yet exit
   * @throws IOException
   */
  public ZoieIndexReader getNewReader() throws IOException {
    // wack the old reader
    if (_oldReader != null) {
      try {
        _oldReader.dispose();
      } catch (IOException ioe) {
        log.warn("Problem closing reader", ioe);
      } finally {
        _oldReader = null;
      }
    }

    int numTries = INDEX_OPEN_NUM_RETRIES;
    InternalIndexReader reader = null;

    // try it for a few times, there is a case where lucene is swapping the segment file,
    // or a case where the index directory file is updated, both are legitimate,
    // trying again does not block searchers,
    // the extra time it takes to get the reader, and to sync the index, memory index is collecting
    // docs

    while (reader == null) {
      if (numTries == 0) {
        break;
      }
      numTries--;
      try {
        IndexSignature sig = getCurrentIndexSignature(_indexHome);

        if (sig == null) {
          throw new IOException("no index exist");
        }
        String luceneDir = sig.getIndexPath();

        if (luceneDir == null || luceneDir.trim().length() == 0) {
          throw new IOException(INDEX_DIRECTORY + " contains no data.");
        }

        if (luceneDir != null) {
          reader = newReader(new File(_indexHome, luceneDir), sig);
          break;
        }
      } catch (IOException ioe) {
        try {
          Thread.sleep(100);
        } catch (InterruptedException e) {
          log.warn("thread interrupted.");
          continue;
        }
      }
    }

    // swap the internal readers

    _oldReader = _currentReader;
    _currentReader = reader;

    return reader;
  }
 /** Closes the index reader */
 public void closeReader() {
   if (_currentReader != null) {
     try {
       _currentReader.close();
     } catch (IOException e) {
       log.error("problem closing reader", e);
     }
     _currentReader = null;
   }
 }
  /**
   * get a fresh new reader instance
   *
   * @return an IndexReader instance, can be null if index does not yet exit
   * @throws IOException
   */
  public ZoieIndexReader<R> getNewReader() throws IOException {
    int numTries = INDEX_OPEN_NUM_RETRIES;
    InternalIndexReader<R> reader = null;

    // try it for a few times, there is a case where lucene is swapping the segment file,
    // or a case where the index directory file is updated, both are legitimate,
    // trying again does not block searchers,
    // the extra time it takes to get the reader, and to sync the index, memory index is collecting
    // docs

    while (reader == null) {
      if (numTries == 0) {
        break;
      }
      numTries--;
      try {
        IndexSignature sig = getCurrentIndexSignature(_indexHome);

        if (sig == null) {
          throw new IOException("no index exist");
        }

        if (_currentReader == null) {
          String luceneDir = sig.getIndexPath();

          if (luceneDir == null || luceneDir.trim().length() == 0) {
            throw new IOException(INDEX_DIRECTORY + " contains no data.");
          }

          if (luceneDir != null) {
            reader = newReader(new File(_indexHome, luceneDir), _decorator, sig);
            break;
          }
        } else {
          reader = (InternalIndexReader<R>) _currentReader.reopen(true);
          reader._generation = _generation;
          _currentSignature = sig;
        }
      } catch (IOException ioe) {
        try {
          Thread.sleep(100);
        } catch (InterruptedException e) {
          log.warn("thread interrupted.");
          continue;
        }
      }
    }

    _generation++;
    // swap the internal readers
    _currentReader = reader;

    log.info(
        "collecting and closing old readers...(" + _destroyQueue.size() + "), gen: " + _generation);
    int numReadersCollected = 0;
    Iterator<InternalIndexReader<R>> iter = _destroyQueue.iterator();
    while (iter.hasNext()) {
      InternalIndexReader<R> r = iter.next();
      log.info(r + " - candiate for collection: " + r._generation + "/" + r._refCount.get());
      if (r._generation <= (_generation - NUM_GENERATIONS) && r._refCount.get() == 0) {
        try {
          r.close();

          List<R> decoratedReaders = r.getDecoratedReaders();
          if (decoratedReaders != null) {
            for (R decR : decoratedReaders) {
              try {
                decR.close();
              } catch (AlreadyClosedException ioe) {
                // read already closed
              }
            }
          }

          iter.remove();
          numReadersCollected++;
        } catch (AlreadyClosedException ace) {
          log.error(ace.getMessage(), ace);
        }
      }
    }

    log.info(
        "done collecting and closing old readers... ("
            + numReadersCollected
            + "/"
            + _destroyQueue.size()
            + ")");

    if (_currentReader != null) {
      _destroyQueue.add(_currentReader);
    }

    return reader;
  }