All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.orientechnologies.lucene.engine.OLuceneStorage Maven / Gradle / Ivy

There is a newer version: 3.2.41
Show newest version
/*
 * Copyright 2014 Orient Technologies.
 *
 * Licensed 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.
 */

package com.orientechnologies.lucene.engine;

import com.orientechnologies.common.concur.resource.OSharedResourceAdaptiveExternal;
import com.orientechnologies.common.io.OFileUtils;
import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.common.serialization.types.OBinarySerializer;
import com.orientechnologies.lucene.analyzer.OLuceneAnalyzerFactory;
import com.orientechnologies.lucene.analyzer.OLucenePerFieldAnalyzerWrapper;
import com.orientechnologies.lucene.builder.DocBuilder;
import com.orientechnologies.lucene.builder.OQueryBuilder;
import com.orientechnologies.lucene.tx.OLuceneTxChanges;
import com.orientechnologies.orient.core.OOrientListener;
import com.orientechnologies.orient.core.Orient;
import com.orientechnologies.orient.core.config.OGlobalConfiguration;
import com.orientechnologies.orient.core.db.ODatabaseDocumentInternal;
import com.orientechnologies.orient.core.db.ODatabaseInternal;
import com.orientechnologies.orient.core.db.ODatabaseRecordThreadLocal;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.index.OIndexCursor;
import com.orientechnologies.orient.core.index.OIndexEngine.ValuesTransformer;
import com.orientechnologies.orient.core.index.OIndexKeyCursor;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.storage.OStorage;
import com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage;
import com.orientechnologies.orient.core.storage.impl.local.paginated.OLocalPaginatedStorage;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TrackingIndexWriter;
import org.apache.lucene.search.ControlledRealTimeReopenThread;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.SearcherManager;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.NIOFSDirectory;
import org.apache.lucene.store.RAMDirectory;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;

import static com.orientechnologies.lucene.engine.OLuceneIndexEngineAbstract.OLUCENE_BASE_DIR;
import static com.orientechnologies.lucene.engine.OLuceneIndexEngineAbstract.RID;

public class OLuceneStorage extends OSharedResourceAdaptiveExternal implements OOrientListener {

  private final String              name;
  private final ODocument           metadata;
  protected     OLuceneFacetManager facetManager;
  protected     TimerTask           commitTask;
  protected AtomicBoolean closed = new AtomicBoolean(true);
  protected TrackingIndexWriter                   mgrWriter;
  protected SearcherManager                       searcherManager;
  protected ControlledRealTimeReopenThread        nrt;
  private   DocBuilder                            builder;
  private   OQueryBuilder                         queryBuilder;
  private   Map oindexes;
  private   long                                  reopenToken;

  private Analyzer indexAnalyzer;
  private Analyzer queryAnalyzer;

  public OLuceneStorage(String name, DocBuilder builder, OQueryBuilder queryBuilder, ODocument metadata) {
    super(OGlobalConfiguration.ENVIRONMENT_CONCURRENT.getValueAsBoolean(),
        OGlobalConfiguration.MVRBTREE_TIMEOUT.getValueAsInteger(), true);
    this.name = name;
    this.builder = builder;
    this.queryBuilder = queryBuilder;
    this.metadata = metadata;

    indexAnalyzer = new OLucenePerFieldAnalyzerWrapper(new StandardAnalyzer());
    queryAnalyzer = new OLucenePerFieldAnalyzerWrapper(new StandardAnalyzer());

    oindexes = new HashMap();
    try {

      reOpen();

    } catch (IOException e) {
      OLogManager.instance().error(this, "Error on initializing Lucene index", e);
    }

    Orient.instance().registerListener(this);

    commitTask = new TimerTask() {
      @Override
      public void run() {
        if (Boolean.FALSE.equals(closed.get())) {
          commit();
        }
      }
    };
    Orient.instance().scheduleTask(commitTask, 10000, 10000);

    OLogManager.instance().info(this, "Index storage CREATED, timerTASK scheduled");

  }

  private void reOpen() throws IOException {

    if (mgrWriter != null) {
      OLogManager.instance().info(this, "index storage is open don't reopen");

      return;
    }
    ODatabaseDocumentInternal database = ODatabaseRecordThreadLocal.INSTANCE.get();

    final OAbstractPaginatedStorage storageLocalAbstract = (OAbstractPaginatedStorage) database.getStorage().getUnderlying();
    Directory dir = null;
    if (storageLocalAbstract instanceof OLocalPaginatedStorage) {
      String pathname = getIndexPath((OLocalPaginatedStorage) storageLocalAbstract);

      OLogManager.instance().info(this, "Opening NIOFS Lucene db=%s, path=%s", database.getName(), pathname);

      dir = NIOFSDirectory.open(new File(pathname).toPath());
    } else {

      OLogManager.instance().info(this, "Opening RAM Lucene index db=%s", database.getName());
      dir = new RAMDirectory();

    }

    final IndexWriter indexWriter = createIndexWriter(dir);

    mgrWriter = new TrackingIndexWriter(indexWriter);
    searcherManager = new SearcherManager(indexWriter, true, null);

    if (nrt != null) {
      nrt.close();
    }

    nrt = new ControlledRealTimeReopenThread(mgrWriter, searcherManager, 60.00, 0.1);
    nrt.setDaemon(true);
    nrt.start();
    flush();

    OLogManager.instance().info(this, "REOPEN DONE");
  }

  public void commit() {
    try {
      OLogManager.instance().info(this, "committing");
      final IndexWriter indexWriter = mgrWriter.getIndexWriter();
      indexWriter.forceMergeDeletes();
      indexWriter.commit();
    } catch (IOException e) {
      OLogManager.instance().error(this, "Error on committing Lucene index", e);
    }
  }

  private String getIndexPath(OLocalPaginatedStorage storageLocalAbstract) {
    return getIndexPath(storageLocalAbstract, "databaseIndex");
  }

  public IndexWriter createIndexWriter(Directory directory) throws IOException {

    OLuceneIndexWriterFactory fc = new OLuceneIndexWriterFactory();
    // TODO: manage taxo
    // facetManager = new OLuceneFacetManager(this, metadata);

    OLogManager.instance().debug(this, "Creating Lucene index in '%s'...", directory);
    return fc.createIndexWriter(directory, metadata, indexAnalyzer());
  }

  public void flush() {
    commit();

  }

  private String getIndexPath(OLocalPaginatedStorage storageLocalAbstract, String indexName) {
    return storageLocalAbstract.getStoragePath() + File.separator + OLUCENE_BASE_DIR + File.separator + indexName;
  }

  public Analyzer indexAnalyzer() {
    return indexAnalyzer;
  }

  public void initIndex(OLuceneClassIndexContext indexContext) {

    OLogManager.instance().info(this, "START INIT initIndex:: name " + indexContext.name + " def :: " + indexContext.definition);
    oindexes.put(indexContext.name, indexContext);

    //    initializerAnalyzers(indexContext.indexClass, indexContext.metadata);

    OLuceneAnalyzerFactory afc = new OLuceneAnalyzerFactory();

    indexContext.metadata.field("prefix_with_class_name", true, OType.BOOLEAN);

    indexAnalyzer = afc.createAnalyzer(indexContext.definition, OLuceneAnalyzerFactory.AnalyzerKind.INDEX, indexContext.metadata);
    queryAnalyzer = afc.createAnalyzer(indexContext.definition, OLuceneAnalyzerFactory.AnalyzerKind.QUERY, indexContext.metadata);

    OLogManager.instance()
        .info(this, "DONE INIT initIndex:: indexAnalyzer::  " + indexAnalyzer + " queryanalzer:: " + queryAnalyzer);

  }

  public boolean remove(Object key, OIdentifiable value) {
    return false;
  }

  public IndexSearcher searcher() throws IOException {
    try {
      nrt.waitForGeneration(reopenToken);
      return searcherManager.acquire();
    } catch (InterruptedException e) {
      OLogManager.instance().error(this, "Error on get searcher from Lucene index", e);
    }
    return null;

  }

  public long size() {

    try {
      return searcher().getIndexReader().numDocs();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return mgrWriter.getIndexWriter().maxDoc();
  }

  public OLuceneTxChanges buildTxChanges() throws IOException {

    throw new RuntimeException("DON'T CALL ME");

  }

  public Query deleteQuery(String indexName, Object key, OIdentifiable value) {

    OLogManager.instance().info(this, "delete with query in index::  " + indexName);
    return null;
  }

  public void init() {
    OLogManager.instance().info(this, "INIT");

  }

  public void create(OBinarySerializer valueSerializer, boolean isAutomatic, OType[] keyTypes, boolean nullPointerSupport,
      OBinarySerializer keySerializer, int keySize) {

    OLogManager.instance().info(this, "CREATE:: ");

  }

  public void delete(String indexName) {
    OLogManager.instance().info(this, "DELETING:: " + indexName);

  }

  public void delete(final ODatabaseInternal database) {
    OLogManager.instance().info(this, "DELETING STORAGE:: ");

    close();

    final OAbstractPaginatedStorage storageLocalAbstract = (OAbstractPaginatedStorage) database.getStorage().getUnderlying();
    if (storageLocalAbstract instanceof OLocalPaginatedStorage) {
      String pathname = getIndexPath((OLocalPaginatedStorage) storageLocalAbstract);

      OFileUtils.deleteRecursively(new File(pathname));

    }
  }

  public void close() {
    OLogManager.instance().info(this, "CLOSING  engine");
    try {
      closeIndex();
    } catch (Throwable e) {
      OLogManager.instance().error(this, "Error on closing Lucene index", e);
    }

  }

  protected void closeIndex() throws IOException {
    OLogManager.instance().debug(this, "Closing Lucene engine'");

    if (nrt != null) {
      nrt.interrupt();
      nrt.close();
    }
    if (commitTask != null) {
      commitTask.cancel();
    }

    if (searcherManager != null)
      searcherManager.close();

    if (mgrWriter != null) {
      mgrWriter.getIndexWriter().forceMergeDeletes();
      mgrWriter.getIndexWriter().commit();
      mgrWriter.getIndexWriter().close();
    }
  }

  public void deleteWithoutLoad(String indexName) {
    OLogManager.instance().info(this, "DELETing withoutLoAD ::: " + indexName);

  }

  public void load(String indexName, OBinarySerializer valueSerializer, boolean isAutomatic, OBinarySerializer keySerializer,
      OType[] keyTypes, boolean nullPointerSupport, int keySize) {

    OLogManager.instance().info(this, "LOAD:: " + indexName);
  }

  public boolean contains(Object key) {
    return false;
  }

  public boolean remove(Object key) {
    return false;
  }

  public void clear(String indexName) {
    OLogManager.instance().info(this, "clear index:: " + indexName);
  }

  public void addDocument(Document doc) {
    try {
      OLogManager.instance().debug(this, "add document::  " + doc);
      final Term term = new Term(RID, doc.get(RID));
      reopenToken = mgrWriter.updateDocument(term, doc);
    } catch (IOException e) {
      OLogManager.instance().error(this, "Error on adding new document '%s' to Lucene index", e, doc);
    }
  }

  public Object getFirstKey() {
    return null;
  }

  public Object getLastKey() {
    return null;
  }

  public OIndexCursor iterateEntriesBetween(Object rangeFrom, boolean fromInclusive, Object rangeTo, boolean toInclusive,
      boolean ascSortOrder, ValuesTransformer transformer) {
    return null;
  }

  public OIndexCursor iterateEntriesMajor(Object fromKey, boolean isInclusive, boolean ascSortOrder,
      ValuesTransformer transformer) {
    return null;
  }

  public OIndexCursor iterateEntriesMinor(Object toKey, boolean isInclusive, boolean ascSortOrder, ValuesTransformer transformer) {
    return null;
  }

  public OIndexCursor cursor(ValuesTransformer valuesTransformer) {
    return null;
  }

  public OIndexCursor descCursor(ValuesTransformer valuesTransformer) {
    return null;
  }

  public OIndexKeyCursor keyCursor() {
    return null;
  }

  public long size(ValuesTransformer transformer) {
    return 0;
  }

  public boolean hasRangeQuerySupport() {
    return false;
  }

  public int getVersion() {
    return 0;
  }

  public String getName() {
    return name;
  }

  public Analyzer queryAnalyzer() {
    return queryAnalyzer;
  }

  @Override
  public void onShutdown() {
    OLogManager.instance().info(this, "ENGINE SHUTDONW");

    close();

  }

  @Override
  public void onStorageRegistered(OStorage storage) {

  }

  @Override
  public void onStorageUnregistered(OStorage storage) {

  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy