*******************************************************************************/
package org.simantics.db.indexing;
-import gnu.trove.map.hash.THashMap;
-
import java.util.Collections;
import java.util.EnumSet;
import java.util.Map;
import org.simantics.db.common.request.UniqueRead;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.exception.RuntimeDatabaseException;
+import org.simantics.db.indexing.exception.IndexingException;
import org.simantics.db.layer0.adapter.GenericRelation;
import org.simantics.utils.datastructures.Pair;
+import gnu.trove.map.hash.THashMap;
+
/**
* @author Tuukka Lehtonen
* @since 1.20.0, 1.18.4
GenericRelation r = graph.adapt(relation, GenericRelation.class);
return new IndexSchema( r.getFields() );
} catch (IllegalArgumentException e) {
- throw new DatabaseException(
- "Failed to read index schema for relation " + relation + ". See cause for reason.", e);
+ throw new IndexingException("Failed to read index schema for relation " + relation + ". See cause for reason.", e);
}
}
package org.simantics.db.indexing;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import org.apache.lucene.util.NumericUtils;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.SubMonitor;
import org.simantics.databoard.Bindings;
import org.simantics.db.ReadGraph;
import org.simantics.db.Resource;
import org.simantics.db.common.procedure.adapter.TransientCacheListener;
import org.simantics.db.common.request.ObjectsWithType;
import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.indexing.exception.IndexCorruptedException;
import org.simantics.db.layer0.genericrelation.IndexQueries;
+import org.simantics.db.layer0.genericrelation.IndexedRelations;
import org.simantics.db.layer0.util.Layer0Utils;
import org.simantics.db.service.CollectionSupport;
import org.simantics.layer0.Layer0;
import org.simantics.operation.Layer0X;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class IndexUtils {
+ private static final Logger LOGGER = LoggerFactory.getLogger(IndexUtils.class);
+
public static Collection<Map<String, Object>> find(ReadGraph graph, Resource index, String filter) throws DatabaseException {
Collection<Map<String, Object>> indexResult = graph.syncRequest(new QueryIndex(index, filter), TransientCacheListener.<Collection<Map<String, Object>>>instance());
mem.flush(progress);
IndexedRelationsSearcher searcher = mem.get(session, L0X.DependenciesRelation, indexRoot);
- return searcher.doList(progress, session);
-
+ List<Object> results;
+ try {
+ results = searcher.doList(progress, session);
+ } catch (IndexCorruptedException e) {
+ LOGGER.error("Index is corrupted for indexRoot {}", indexRoot, e);
+ rebuild(session, progress);
+ // if this fails then no can do
+ searcher = mem.get(session, L0X.DependenciesRelation, indexRoot);
+ results = searcher.doList(progress, session);
+ }
+ return results;
}
+ private static void rebuild(Session session, IProgressMonitor monitor) throws Exception {
+ LOGGER.error("Trying to rebuild index");
+ DatabaseIndexing.deleteAllIndexes();
+ session.getService(IndexedRelations.class).fullRebuild(SubMonitor.convert(monitor, 100), session);
+ }
+
public static Term longTerm(String key, Long value) {
BytesRef ref = new BytesRef();
NumericUtils.longToPrefixCoded( value, 0, ref );
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.exception.InvalidResourceReferenceException;
import org.simantics.db.indexing.IndexedRelationsSearcherBase.State;
+import org.simantics.db.indexing.exception.IndexingException;
import org.simantics.db.layer0.adapter.GenericRelation;
import org.simantics.db.layer0.genericrelation.IndexException;
import org.simantics.db.layer0.genericrelation.IndexedRelations;
searcher.startAccess(null, graph.getSession(), false);
// At this point we have three options:
// 1. we have access
- if(searcher.hasAccess(false)) loaded = true;
+ if(searcher.hasAccess(false))
+ loaded = true;
// 2. something is wrong and the index cannot be cleaned
- if(searcher.checkState(State.PROBLEM)) throw new DatabaseException("Searcher is in problematic state", searcher.getException());
+ if(searcher.checkState(State.PROBLEM))
+ throw new IndexingException("Searcher is in problematic state", searcher.getException());
// 3. something was wrong, but the index has been successfully cleaned
}
if(!loaded) {
if(!searcher.checkState(State.NONE))
- throw new DatabaseException("Illegal searcher state " + searcher.state());
+ throw new IndexingException("Illegal searcher state " + searcher.state());
try {
SerialisationSupport ss = graph.getService(SerialisationSupport.class);
searcher.setReady();
} catch (IOException e) {
searcher.setProblem(e);
- throw new DatabaseException(e);
+ throw new IndexingException(e);
}
}
try {
fullRebuild(monitor, graph);
} catch (IOException e) {
- throw new DatabaseException(e);
+ throw new IndexingException(e);
}
}
});
GenericRelation r = graph.adapt(relation, GenericRelation.class);
if (r == null)
- throw new DatabaseException("Given resource " + relation + "could not be adapted to GenericRelation.");
+ throw new IndexingException("Given resource " + relation + "could not be adapted to GenericRelation.");
Object[] bound = new Object[] { ss.getRandomAccessId(indexRoot) };
GenericRelation selection = r.select(IndexedRelationsSearcherBase.getPattern(r, bound.length), bound);
import org.simantics.db.Resource;
import org.simantics.db.Session;
import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.indexing.exception.IndexingException;
import org.simantics.db.layer0.adapter.GenericRelation;
import org.simantics.utils.datastructures.Pair;
import org.slf4j.Logger;
} else if ("String".equals(fieldClass) || "Text".equals(fieldClass)) {
data[index++] = "";
} else {
- throw new DatabaseException("Can only index Long and String fields, encountered class " + fieldClass);
+ throw new IndexingException("Can only index Long and String fields, encountered class " + fieldClass);
}
}
}
}
List<Map<String, Object>> persistentCachedSearch(IProgressMonitor monitor, RequestProcessor processor, String search,
- int maxResultCount) throws ParseException, IOException, DatabaseException {
+ int maxResultCount) throws ParseException, IOException, IndexingException {
MemoryIndexing mem = MemoryIndexing.getInstance(session.getSession());
}
List<Resource> persistentCachedSearchResources(IProgressMonitor monitor, RequestProcessor processor, String search,
- int maxResultCount) throws ParseException, IOException, DatabaseException {
+ int maxResultCount) throws ParseException, IOException, IndexingException {
MemoryIndexing mem = MemoryIndexing.getInstance(session.getSession());
}
- List<Object> persistentCachedList(IProgressMonitor monitor, RequestProcessor processor) throws ParseException, IOException, DatabaseException {
+ List<Object> persistentCachedList(IProgressMonitor monitor, RequestProcessor processor) throws ParseException, IOException, IndexingException {
startAccess(monitor, processor.getSession(), false);
@Override
List<Map<String, Object>> doSearch(IProgressMonitor monitor, RequestProcessor processor, String search,
- int maxResultCount) throws ParseException, IOException, DatabaseException {
+ int maxResultCount) throws ParseException, IOException, IndexingException {
List<Map<String,Object>> persistent = persistentCachedSearch(monitor, processor, search, maxResultCount);
List<Map<String,Object>> cached = cache.doSearch(monitor, processor, search, maxResultCount);
@Override
List<Resource> doSearchResources(IProgressMonitor monitor, RequestProcessor processor, String search,
- int maxResultCount) throws ParseException, IOException, DatabaseException {
+ int maxResultCount) throws ParseException, IOException, IndexingException {
List<Resource> persistent = persistentCachedSearchResources(monitor, processor, search, maxResultCount);
List<Resource> cached = cache.doSearchResources(monitor, processor, search, maxResultCount);
}
- List<Object> doList(IProgressMonitor monitor, RequestProcessor processor) throws ParseException, IOException, DatabaseException {
+ List<Object> doList(IProgressMonitor monitor, RequestProcessor processor) throws ParseException, IOException, IndexingException {
List<Object> persistent = persistentCachedList(monitor, processor);
import org.simantics.db.common.request.SafeName;
import org.simantics.db.common.utils.NameUtils;
import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.indexing.exception.IndexCorruptedException;
+import org.simantics.db.indexing.exception.IndexingException;
import org.simantics.db.indexing.internal.IndexingJob;
import org.simantics.db.layer0.adapter.GenericRelation;
import org.simantics.db.layer0.genericrelation.IndexException;
STRING_TYPE.freeze();
}
- protected static Field makeField(String fieldName, String fieldClass) throws DatabaseException {
+ protected static Field makeField(String fieldName, String fieldClass) throws IndexingException {
switch (fieldClass) {
case "Long": return new LongField(fieldName, 0L, Field.Store.YES);
case "String": return new Field (fieldName, "", STRING_TYPE);
case "Text": return new TextField(fieldName, "", Field.Store.YES);
default:
- throw new DatabaseException("Can only index Long, String and Text fields, encountered field type " + fieldClass);
+ throw new IndexingException("Can only index Long, String and Text fields, encountered field type " + fieldClass);
}
}
try {
GenericRelation r = graph.adapt(relation, GenericRelation.class);
if (r == null)
- throw new DatabaseException("Given resource " + relation + "could not be adapted to GenericRelation.");
+ throw new IndexingException("Given resource " + relation + "could not be adapted to GenericRelation.");
GenericRelation selection = r.select(getPattern(r, bound.length), bound);
initializeIndexImpl(new CompletableFuture<>(), mon, r, results, bound, overwrite);
} catch (IOException e) {
getLogger().error("Index is in problematic state! {}", this, e);
- throw new DatabaseException(e);
+ throw new IndexingException(e);
}
});
}
}
- public List<Object[]> debugDocs(IProgressMonitor monitor) throws ParseException, IOException, DatabaseException {
+ public List<Object[]> debugDocs(IProgressMonitor monitor) throws ParseException, IOException, IndexingException {
Query query = new MatchAllDocsQuery();
} catch (CorruptIndexException e) {
getLogger().error("Index is corrupted! {}", this, e);
- throw new DatabaseException(e);
+ throw new IndexCorruptedException("Index is corrupted! " + this, e);
} catch (IOException e) {
getLogger().error("Index is in problematic state! {}", this, e);
- throw new DatabaseException(e);
+ throw new IndexingException(e);
}
}
List<Map<String, Object>> doSearch(IProgressMonitor monitor, RequestProcessor processor, String search, int maxResultCount) throws ParseException, IOException,
- DatabaseException {
+ IndexingException {
// An empty search string will crash QueryParser
// Just return no results for empty queries.
return Collections.emptyList();
}
- return processor.syncRequest(new Read<List<Map<String, Object>>>() {
+ try {
+ return processor.syncRequest(new Read<List<Map<String, Object>>>() {
- @Override
- public List<Map<String, Object>> perform(ReadGraph graph) throws DatabaseException {
+ @Override
+ public List<Map<String, Object>> perform(ReadGraph graph) throws DatabaseException {
- GenericRelation r = graph.adapt(relation, GenericRelation.class);
- if (r == null)
- throw new DatabaseException("Given resource " + graph.syncRequest(new SafeName(relation))
- + "could not be adapted to GenericRelation.");
+ GenericRelation r = graph.adapt(relation, GenericRelation.class);
+ if (r == null)
+ throw new IndexingException("Given resource " + graph.syncRequest(new SafeName(relation))
+ + "could not be adapted to GenericRelation.");
- SerialisationSupport support = graph.getService(SerialisationSupport.class);
+ SerialisationSupport support = graph.getService(SerialisationSupport.class);
- List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(docs.scoreDocs.length);
-
- final DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor();
-
- for (ScoreDoc scoreDoc : docs.scoreDocs) {
+ List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(docs.scoreDocs.length);
+
+ final DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor();
+
+ for (ScoreDoc scoreDoc : docs.scoreDocs) {
- try {
+ try {
- reader.document(scoreDoc.doc, visitor);
-
- Document doc = visitor.getDocument();
-
- List<IndexableField> fs = doc.getFields();
- Map<String, Object> entry = new THashMap<String, Object>(fs.size());
- for (IndexableField f : fs) {
- IndexSchema.Type type = schema.typeMap.get(f.name());
- if (type == IndexSchema.Type.LONG) {
- entry.put(f.name(), support.getResource(f.numericValue().longValue()));
- } else {
- entry.put(f.name(), f.stringValue());
+ reader.document(scoreDoc.doc, visitor);
+
+ Document doc = visitor.getDocument();
+
+ List<IndexableField> fs = doc.getFields();
+ Map<String, Object> entry = new THashMap<String, Object>(fs.size());
+ for (IndexableField f : fs) {
+ IndexSchema.Type type = schema.typeMap.get(f.name());
+ if (type == IndexSchema.Type.LONG) {
+ entry.put(f.name(), support.getResource(f.numericValue().longValue()));
+ } else {
+ entry.put(f.name(), f.stringValue());
+ }
}
+
+ result.add(entry);
+
+ } catch (CorruptIndexException e) {
+ getLogger().error("Index is corrupted! {}", this, e);
+ throw new IndexCorruptedException("Index is corrupted! " + " " + this + " " + scoreDoc, e);
+ } catch (IOException e) {
+ getLogger().error("Index is in problematic state! {}", this, e);
+ throw new IndexingException(e);
}
-
- result.add(entry);
-
- } catch (CorruptIndexException e) {
- getLogger().error("Index is corrupted! {}", this, e);
- throw new DatabaseException(e);
- } catch (IOException e) {
- getLogger().error("Index is in problematic state! {}", this, e);
- throw new DatabaseException(e);
}
+ return result;
}
- return result;
+ });
+ } catch (DatabaseException e) {
+ if (e instanceof IndexingException) {
+ throw (IndexingException) e;
+ } else {
+ throw new IndexingException(e);
}
- });
+ }
}
static class ResourceVisitor extends StoredFieldVisitor {
}
List<Resource> doSearchResources(IProgressMonitor monitor, RequestProcessor processor, String search, int maxResultCount) throws ParseException, IOException,
- DatabaseException {
+ IndexingException {
// An empty search string will crash QueryParser
// Just return no results for empty queries.
return Collections.emptyList();
}
- return processor.syncRequest(new Read<List<Resource>>() {
+ try {
+ return processor.syncRequest(new Read<List<Resource>>() {
- @Override
- public List<Resource> perform(ReadGraph graph) throws DatabaseException {
+ @Override
+ public List<Resource> perform(ReadGraph graph) throws DatabaseException {
- CollectionSupport cs = graph.getService(CollectionSupport.class);
- SerialisationSupport support = graph.getService(SerialisationSupport.class);
-
- List<Resource> result = cs.createList();
-
- ResourceVisitor visitor = new ResourceVisitor();
-
- for (ScoreDoc scoreDoc : docs.scoreDocs) {
- try {
- reader.document(scoreDoc.doc, visitor);
- result.add(support.getResource(visitor.id));
- } catch (CorruptIndexException e) {
- getLogger().error("Index is corrupted! {}", this, e);
- throw new DatabaseException(e);
- } catch (IOException e) {
- getLogger().error("Index is in problematic state! {}", this, e);
- throw new DatabaseException(e);
+ CollectionSupport cs = graph.getService(CollectionSupport.class);
+ SerialisationSupport support = graph.getService(SerialisationSupport.class);
+
+ List<Resource> result = cs.createList();
+
+ ResourceVisitor visitor = new ResourceVisitor();
+
+ for (ScoreDoc scoreDoc : docs.scoreDocs) {
+ try {
+ reader.document(scoreDoc.doc, visitor);
+ result.add(support.getResource(visitor.id));
+ } catch (CorruptIndexException e) {
+ getLogger().error("Index is corrupted! {}", this, e);
+ throw new IndexCorruptedException("Index is corrupted! " + " " + this + " " + scoreDoc, e);
+ } catch (IOException e) {
+ getLogger().error("Index is in problematic state! {}", this, e);
+ throw new IndexingException(e);
+ }
}
+ return result;
}
- return result;
+ });
+ } catch (DatabaseException e) {
+ if (e instanceof IndexingException) {
+ throw (IndexingException) e;
+ } else {
+ throw new IndexingException(e);
}
- });
+ }
}
List<Object> doList(IProgressMonitor monitor, RequestProcessor processor) throws ParseException, IOException,
- DatabaseException {
+ IndexingException {
assertAccessOpen(false);
} catch (CorruptIndexException e) {
getLogger().error("Index is corrupted! {}", this, e);
- throw new DatabaseException(e);
+ throw new IndexCorruptedException("Index is corrupted! " + " " + this + " " + scoreDoc, e);
} catch (IOException e) {
getLogger().error("Index is in problematic state! {}", this, e);
- throw new DatabaseException(e);
+ throw new IndexingException(e);
}
}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2018 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.indexing.exception;
+
+import org.apache.lucene.index.CorruptIndexException;
+
+/**
+ * @author Jani Simomaa
+ * @since 1.36.0
+ */
+public class IndexCorruptedException extends IndexingException {
+
+ private static final long serialVersionUID = 6371395124643556058L;
+
+ public IndexCorruptedException(String message, CorruptIndexException cause) {
+ super(message, cause);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2018 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.indexing.exception;
+
+import org.simantics.db.exception.ServiceException;
+
+/**
+ * @author Jani Simomaa
+ * @since 1.36.0
+ */
+public class IndexingException extends ServiceException {
+
+ private static final long serialVersionUID = 8682389500759734302L;
+
+ public IndexingException(ServiceException cause) {
+ super(cause);
+ }
+
+ public IndexingException(Throwable cause) {
+ super(cause);
+ }
+
+ public IndexingException(String message) {
+ super(message);
+ }
+
+ public IndexingException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
import org.eclipse.core.runtime.jobs.Job;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.function.DbConsumer;
+import org.simantics.db.indexing.exception.IndexingException;
/**
* @author Tuukka Lehtonen
try {
barrier.acquire();
if (err[0] != null) {
- if (err[0] instanceof DatabaseException)
+ if (err[0] instanceof IndexingException)
throw (DatabaseException) err[0];
- throw new DatabaseException(err[0]);
+ throw new IndexingException(err[0]);
}
} catch (InterruptedException e) {
- throw new DatabaseException(e);
+ throw new IndexingException(e);
}
}