package proj.zoie.impl.indexing.internal;
/**
* 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 it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import java.io.IOException;
import java.util.Comparator;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.MergeScheduler;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.similarities.Similarity;
import proj.zoie.api.UIDFilter;
import proj.zoie.api.ZoieHealth;
import proj.zoie.api.ZoieMultiReader;
import proj.zoie.api.indexing.ZoieIndexable.IndexingReq;
public abstract class BaseSearchIndex<R extends IndexReader> {
private static final Logger log = Logger.getLogger(BaseSearchIndex.class);
private int _eventsHandled = 0;
protected MergeScheduler _mergeScheduler;
protected IndexWriter _indexWriter = null;
protected volatile LongOpenHashSet _delDocs = new LongOpenHashSet();
protected final SearchIndexManager<R> _idxMgr;
protected boolean _closeWriterAfterUpdate;
protected final Comparator<String> _versionComparator;
protected BaseSearchIndex(SearchIndexManager<R> idxMgr, boolean closeWriterAfterUpdate) {
_idxMgr = idxMgr;
_closeWriterAfterUpdate = closeWriterAfterUpdate;
_versionComparator = idxMgr.getVersionComparator();
}
/**
* gets index version, e.g. SCN
* @return index version
*/
abstract String getVersion();
/**
* gets number of docs in the index, .e.g maxdoc - number of deleted docs
*/
abstract public int getNumdocs();
/**
* Sets the index version
* @param version
* @throws IOException
*/
abstract public void setVersion(String version) throws IOException;
/**
* close and free all resources
*/
public void close() {
closeIndexWriter();
}
abstract public ZoieMultiReader<R> openIndexReader();
abstract public void refresh() throws IOException;
public void updateIndex(LongSet delDocs, List<IndexingReq> insertDocs, Analyzer defaultAnalyzer,
Similarity similarity) throws IOException {
if (delDocs != null && delDocs.size() > 0) {
deleteDocs(delDocs);
}
if (insertDocs == null || insertDocs.size() == 0) {
return;
}
IndexWriter idxMod = null;
try {
idxMod = openIndexWriter(defaultAnalyzer, similarity);
if (idxMod != null) {
for (IndexingReq idxPair : insertDocs) {
Analyzer analyzer = idxPair.getAnalyzer();
Document doc = idxPair.getDocument();
if (analyzer == null) {
idxMod.addDocument(doc);
} else {
idxMod.addDocument(doc, analyzer);
}
}
}
} finally {
if (idxMod != null) {
idxMod.commit();
if (_closeWriterAfterUpdate) {
closeIndexWriter();
}
}
}
}
public LongSet getDelDocs() {
return _delDocs;
}
public synchronized void clearDeletes() {
_delDocs = new LongOpenHashSet();
}
public void markDeletes(LongSet delDocs) throws IOException {
if (delDocs != null && delDocs.size() > 0) {
ZoieMultiReader<R> reader = null;
synchronized (this) {
reader = openIndexReader();
if (reader == null) {
return;
}
reader.incZoieRef();
reader.markDeletes(delDocs, _delDocs);
reader.decZoieRef();
}
}
}
public void commitDeletes() throws IOException {
ZoieMultiReader<R> reader = null;
synchronized (this) {
reader = openIndexReader();
if (reader == null) {
return;
}
reader.incZoieRef();
reader.commitDeletes();
reader.decZoieRef();
}
}
private void deleteDocs(LongSet delDocs) throws IOException {
if (delDocs == null || delDocs.size() == 0) {
return;
}
ZoieMultiReader<R> reader = openIndexReader();
if (reader == null) {
return;
}
UIDFilter uidFilter = new UIDFilter(delDocs.toLongArray(), reader);
IndexWriter writer = null;
try {
writer = openIndexWriter(null, null);
writer.deleteDocuments(new ConstantScoreQuery(uidFilter));
writer.commit();
} finally {
closeIndexWriter();
}
}
public void loadFromIndex(BaseSearchIndex<R> index) throws IOException {
LongSet delDocs = null;
// delete docs in disk index first
synchronized (this) {
if (_delDocs != null && _delDocs.size() > 0) {
delDocs = _delDocs;
clearDeletes();
}
}
deleteDocs(delDocs);
// open readOnly ram index reader
ZoieMultiReader<R> reader = index.openIndexReader();
if (reader == null) {
return;
}
// merge the readOnly ram index with the disk index
IndexWriter writer = null;
try {
writer = openIndexWriter(null, null);
writer.addIndexes(reader.directory());
writer.maybeMerge();
} finally {
closeIndexWriter();
}
}
abstract public IndexWriter openIndexWriter(Analyzer analyzer, Similarity similarity)
throws IOException;
public void closeIndexWriter() {
if (_indexWriter != null) {
try {
_indexWriter.close();
} catch (Exception e) {
ZoieHealth.setFatal();
log.error(e.getMessage(), e);
}
_indexWriter = null;
}
}
public void incrementEventCount(int eventCount) {
_eventsHandled += eventCount;
}
public int getEventsHandled() {
return _eventsHandled;
}
}