Package proj.zoie.store

Source Code of proj.zoie.store.LuceneStore$ReaderData

package proj.zoie.store;

import it.unimi.dsi.fastutil.longs.Long2IntRBTreeMap;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.index.AtomicReader;
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.NumericDocValues;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.Version;

import proj.zoie.api.ZoieSegmentReader;
import proj.zoie.api.impl.ZoieMergePolicy;
import proj.zoie.api.indexing.AbstractZoieIndexable;

public class LuceneStore extends AbstractZoieStore {

  private static final String VERSION_NAME = "version";
  private static final Logger logger = Logger.getLogger(LuceneStore.class);

  private static class ReaderData {
    final IndexReader reader;
    final Long2IntRBTreeMap uidMap;
    final long _minUID;
    final long _maxUID;

    ReaderData(IndexReader reader) throws IOException {
      this.reader = reader;
      long minUID = Long.MAX_VALUE;
      long maxUID = Long.MIN_VALUE;

      uidMap = new Long2IntRBTreeMap();
      uidMap.defaultReturnValue(-1);
      int maxDoc = reader.maxDoc();
      if (maxDoc == 0) {
        _minUID = Long.MIN_VALUE;
        _maxUID = Long.MIN_VALUE;
        return;
      }

      List<AtomicReaderContext> leaves = reader.getContext().leaves();
      for (AtomicReaderContext context : leaves) {
        AtomicReader atomicReader = context.reader();
        NumericDocValues uidValues = atomicReader
            .getNumericDocValues(AbstractZoieIndexable.DOCUMENT_ID_PAYLOAD_FIELD);
        Bits liveDocs = atomicReader.getLiveDocs();
        for (int i = 0; i < atomicReader.maxDoc(); ++i) {
          if (liveDocs == null || liveDocs.get(i)) {
            long uid = uidValues.get(i);
            if (uid < minUID) minUID = uid;
            if (uid > maxUID) maxUID = uid;
            uidMap.put(uid, i);
          }
        }
      }
      _minUID = minUID;
      _maxUID = maxUID;
    }

    void close() {
      if (this.reader != null) {
        try {
          this.reader.close();
        } catch (IOException e) {
          logger.error(e.getMessage(), e);
        }
      }

    }
  }

  private final String _field;
  private final Directory _dir;
  private IndexWriter _idxWriter;
  private volatile ReaderData _currentReaderData;
  private volatile ReaderData _oldReaderData;
  private volatile boolean _closed = true;

  private LuceneStore(Directory dir, String field) throws IOException {
    _field = field;
    _idxWriter = null;
    _dir = dir;
  }

  @Override
  public void open() throws IOException {
    if (_closed) {
      IndexWriterConfig idxWriterConfig = new IndexWriterConfig(Version.LUCENE_43,
          new StandardAnalyzer(Version.LUCENE_43));
      idxWriterConfig.setMergePolicy(new ZoieMergePolicy());
      idxWriterConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);
      _idxWriter = new IndexWriter(_dir, idxWriterConfig);
      updateReader();
      _closed = false;
    }
  }

  private void updateReader() throws IOException {

    IndexReader oldReader = null;

    if (_currentReaderData != null) {
      oldReader = _currentReaderData.reader;
    }

    IndexReader idxReader = DirectoryReader.open(_idxWriter, true);

    // if reader did not change, no updates were applied, not need to refresh
    if (idxReader == oldReader) return;

    ReaderData readerData = new ReaderData(idxReader);
    _currentReaderData = readerData;
    if (_oldReaderData != null) {
      ReaderData tmpOld = _oldReaderData;
      _oldReaderData = _currentReaderData;
      tmpOld.close();
    }
    _currentReaderData = readerData;
  }

  public static ZoieStore openStore(Directory idxDir, String field, boolean compressionOff)
      throws IOException {
    LuceneStore store = new LuceneStore(idxDir, field);
    store.setDataCompressed(!compressionOff);
    store.open();
    return store;
  }

  private int mapDocId(long uid) {
    if (_currentReaderData != null) {
      if (_currentReaderData._maxUID >= uid && _currentReaderData._minUID <= uid) {
        return _currentReaderData.uidMap.get(uid);
      }
    }
    return -1;
  }

  @Override
  protected void persist(long uid, byte[] data) throws IOException {
    Document doc = new Document();
    doc.add(new StoredField(_field, data));
    ZoieSegmentReader.fillDocumentID(doc, uid);
    _idxWriter.addDocument(doc);
  }

  @Override
  protected void persistDelete(long uid) throws IOException {
    final int docid = mapDocId(uid);
    if (docid < 0) return;

    Query deleteQ = new ConstantScoreQuery(new Filter() {

      @Override
      public DocIdSet getDocIdSet(AtomicReaderContext readerCtx, Bits acceptedDocs)
          throws IOException {
        return new DocIdSet() {

          @Override
          public DocIdSetIterator iterator() throws IOException {
            return new DocIdSetIterator() {
              int currId = -1;

              @Override
              public int nextDoc() throws IOException {
                if (currId == -1) {
                  currId = docid;
                } else {
                  currId = DocIdSetIterator.NO_MORE_DOCS;
                }
                return currId;
              }

              @Override
              public int docID() {
                return currId;
              }

              @Override
              public int advance(int target) throws IOException {
                if (currId != DocIdSetIterator.NO_MORE_DOCS) {
                  if (target < docid) {
                    currId = docid;
                  } else {
                    currId = DocIdSetIterator.NO_MORE_DOCS;
                  }
                }
                return currId;
              }

              @Override
              public long cost() {
                // TODO Auto-generated method stub
                return 0;
              }
            };
          }

        };
      }

    });
    _idxWriter.deleteDocuments(deleteQ);
    if (_currentReaderData != null) {
      _currentReaderData.uidMap.remove(uid);
    }

  }

  @Override
  protected BytesRef getFromStore(long uid) throws IOException {
    int docid = mapDocId(uid);
    if (docid < 0) return null;
    IndexReader reader = null;
    if (_currentReaderData != null) {
      reader = _currentReaderData.reader;
    }
    if (docid >= 0 && reader != null) {
      Document doc = reader.document(docid);
      if (doc != null) {
        return doc.getBinaryValue(_field);
      }
    }
    return null;
  }

  @Override
  protected void commitVersion(String version) throws IOException {
    HashMap<String, String> versionMap = new HashMap<String, String>();
    versionMap.put(VERSION_NAME, version);
    _idxWriter.setCommitData(versionMap);
    _idxWriter.prepareCommit();
    _idxWriter.commit();
    updateReader();
  }

  @Override
  public void close() throws IOException {
    if (!_closed) {
      _idxWriter.close();
      _closed = true;
    }
  }
}
TOP

Related Classes of proj.zoie.store.LuceneStore$ReaderData

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.