From ad0e5bf4b34705988e23c9ee3f8e4fcbb760c701 Mon Sep 17 00:00:00 2001 From: Tuukka Lehtonen Date: Fri, 3 Jan 2020 13:51:33 +0200 Subject: [PATCH] Added new field TypeId to dependency index for exact type searching The new field is String-valued and contains a concatenation of the resource ids of a resource's type hierarchy, separated by a whitespace, for example `41233 12423 1233`. This field uses the WhitespaceAnalyzer, i.e. its contents are tokenized by whitespace and thus searches like `TypeId:41233` will return exactly those resources that are instances of the type resource `41233`. This commit also simplifies and fixes some of the existing index searching code to use this new field instead of the old `Types` field for type-based searching. If existing product-code uses the indexing facilities directly and not through `QueryIndexUtils` or `Instances`, such code will also require changes to take this new field into use. See `IndexQueries` to form queries related to this field. gitlab #438 Change-Id: I9992ad32a9e6da41c88641e60fed6e1793253738 --- .../org/simantics/db/indexing/IndexUtils.java | 20 +- .../IndexedRelationsMemorySearcher.java | 8 +- .../IndexedRelationsSearcherBase.java | 3 +- .../org/simantics/db/indexing/Queries.java | 25 +- .../layer0/adapter/impl/EntityInstances.java | 9 +- .../layer0/genericrelation/Dependencies.java | 3 +- .../genericrelation/DependenciesRelation.java | 450 +++++++++--------- .../db/layer0/genericrelation/Entry.java | 14 +- .../layer0/genericrelation/IndexQueries.java | 46 ++ .../db/layer0/request/IndexedInstances.java | 31 +- .../debug/ui/SearchResourceDialog.java | 13 +- .../adapters/ExistingInstancesRemover.java | 17 - .../simantics/modeling/adapters/Removers.java | 66 ++- .../synchronization/client/Synchronizer.java | 57 ++- 14 files changed, 376 insertions(+), 386 deletions(-) diff --git a/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexUtils.java b/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexUtils.java index 26a6e68ae..760acd68c 100644 --- a/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexUtils.java +++ b/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexUtils.java @@ -91,7 +91,7 @@ public class IndexUtils { public static Collection findByName(ReadGraph graph, Resource model, String name) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); HashSet results = new HashSet(); - + String search = IndexQueries.quoteTerm(Dependencies.FIELD_NAME, name); for(Resource resource : findResources(graph, model, search)) { @@ -101,29 +101,21 @@ public class IndexUtils { } public static Collection findByType(ReadGraph graph, Resource model, Resource type) throws DatabaseException { - - HashSet results = new HashSet(); - Layer0 L0 = Layer0.getInstance(graph); - String typeName = graph.getRelatedValue(type, L0.HasName, Bindings.STRING); - String search = IndexQueries.quoteTerm(Dependencies.FIELD_TYPES, typeName); + HashSet results = new HashSet<>(); + String search = IndexQueries.resourceIdTerm(Dependencies.FIELD_TYPE_RESOURCE, type); for(Resource resource : findResources(graph, model, search)) { - if(graph.isInstanceOf(resource, type)) results.add(resource); + if(graph.isInstanceOf(resource, type)) results.add(resource); } return results; } public static Collection findByTypeAndName(ReadGraph graph, Resource model, Resource type, String name) throws DatabaseException { - - Layer0 L0 = Layer0.getInstance(graph); - HashSet results = new HashSet(); - String typeName = graph.getRelatedValue(type, L0.HasName, Bindings.STRING); - - String search = IndexQueries.and(IndexQueries.quoteTerm(Dependencies.FIELD_TYPES, typeName), IndexQueries.quoteTerm(Dependencies.FIELD_NAME, name)); + String search = IndexQueries.and(IndexQueries.resourceIdTerm(Dependencies.FIELD_TYPE_RESOURCE, type), IndexQueries.quoteTerm(Dependencies.FIELD_NAME, name)); for(Resource resource : findResources(graph, model, search)) { - if(graph.isInstanceOf(resource, type)) results.add(resource); + if(graph.isInstanceOf(resource, type)) results.add(resource); } return results; } diff --git a/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexedRelationsMemorySearcher.java b/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexedRelationsMemorySearcher.java index d1282c766..0275c2e00 100644 --- a/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexedRelationsMemorySearcher.java +++ b/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexedRelationsMemorySearcher.java @@ -126,9 +126,7 @@ public class IndexedRelationsMemorySearcher extends IndexedRelationsSearcherBase } changeState(monitor, session, State.READY); - -// closeInternal(); - + return result; } @@ -137,10 +135,8 @@ public class IndexedRelationsMemorySearcher extends IndexedRelationsSearcherBase try { if(writer != null) writer.commit(); - } catch (CorruptIndexException e) { - e.printStackTrace(); } catch (IOException e) { - e.printStackTrace(); + getLogger().error("Index commit failed", e); } } diff --git a/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexedRelationsSearcherBase.java b/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexedRelationsSearcherBase.java index afcaafd51..5df5d68c1 100644 --- a/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexedRelationsSearcherBase.java +++ b/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexedRelationsSearcherBase.java @@ -347,6 +347,7 @@ abstract public class IndexedRelationsSearcherBase { removedTerm = new Term(key, (String) keyValue); } else { // FIXME: should throw an exception for illegal input data but this would leave the index in an incoherent state + getLogger().error("Attempting to remove document from index of {} with key {} and unrecognized key value type {} : {}", input, key, keyValue, keyValue != null ? keyValue.getClass() : "null"); continue; } @@ -433,7 +434,7 @@ abstract public class IndexedRelationsSearcherBase { boolean done = false; if(requireChangeInfoOnReplace()) { TopDocs exist = searcher.search(new TermQuery(removedTerm), null, 2); - if(exist.scoreDocs.length == 1 && requireChangeInfoOnReplace()) { + if(exist.scoreDocs.length == 1) { Document doc = reader.document(exist.scoreDocs[0].doc); if(!areSame(doc, document)) { writer.deleteDocuments(removedTerm); diff --git a/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/Queries.java b/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/Queries.java index 21b32fa1e..eab6a7a12 100644 --- a/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/Queries.java +++ b/bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/Queries.java @@ -136,20 +136,21 @@ public class Queries { final static PerFieldAnalyzerWrapper analyzer = createAnalyzer(); static PerFieldAnalyzerWrapper createAnalyzer() { - - Map analyzerPerField = new HashMap<>(); - analyzerPerField.put("Model", new KeywordAnalyzer()); - analyzerPerField.put("Parent", new KeywordAnalyzer()); - analyzerPerField.put("Resource", new KeywordAnalyzer()); - analyzerPerField.put("GUID", new KeywordAnalyzer()); - analyzerPerField.put("Name", new KeywordAnalyzer()); - analyzerPerField.put("Types", new TypeStringAnalyzer(false)); - analyzerPerField.put(Dependencies.FIELD_NAME_SEARCH, new LowerCaseWhitespaceAnalyzer(Version.LUCENE_4_9)); - analyzerPerField.put(Dependencies.FIELD_TYPES_SEARCH, new TypeStringAnalyzer(true)); - + + Map analyzerPerField = new HashMap<>(); + analyzerPerField.put(Dependencies.FIELD_MODEL, new KeywordAnalyzer()); + analyzerPerField.put(Dependencies.FIELD_PARENT, new KeywordAnalyzer()); + analyzerPerField.put(Dependencies.FIELD_RESOURCE, new KeywordAnalyzer()); + analyzerPerField.put(Dependencies.FIELD_GUID, new KeywordAnalyzer()); + analyzerPerField.put(Dependencies.FIELD_NAME, new KeywordAnalyzer()); + analyzerPerField.put(Dependencies.FIELD_TYPES, new TypeStringAnalyzer(false)); + analyzerPerField.put(Dependencies.FIELD_NAME_SEARCH, new LowerCaseWhitespaceAnalyzer(Version.LUCENE_4_9)); + analyzerPerField.put(Dependencies.FIELD_TYPES_SEARCH, new TypeStringAnalyzer(true)); + analyzerPerField.put(Dependencies.FIELD_TYPE_RESOURCE, new WhitespaceAnalyzer(Version.LUCENE_4_9)); + PerFieldAnalyzerWrapper analyzer = new PerFieldAnalyzerWrapper(new LowerCaseWhitespaceAnalyzer(Version.LUCENE_4_9), analyzerPerField); return analyzer; - + } static PerFieldAnalyzerWrapper getAnalyzer() { diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/impl/EntityInstances.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/impl/EntityInstances.java index ffbec2f5e..838728b17 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/impl/EntityInstances.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/impl/EntityInstances.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * Copyright (c) 2007, 2019 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 @@ -17,7 +17,6 @@ import java.util.Collections; import java.util.List; import java.util.Set; -import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.primitiverequest.Adapter; @@ -26,6 +25,7 @@ import org.simantics.db.common.request.ObjectsWithType; import org.simantics.db.common.request.TernaryRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.adapter.Instances; +import org.simantics.db.layer0.genericrelation.Dependencies; import org.simantics.db.layer0.genericrelation.IndexQueries; import org.simantics.db.layer0.util.Layer0Utils; import org.simantics.db.request.ReadExt; @@ -116,10 +116,7 @@ public class EntityInstances implements Instances { StringBuilder sb = new StringBuilder(); boolean emptyFilter = filter.isEmpty(); if (emptyFilter || !type.equals(L0.Entity)) { - String typeName = graph.getPossibleRelatedValue(type, L0.HasName, Bindings.STRING); - if (typeName == null || typeName.isEmpty()) - return null; - sb.append("Types:").append( IndexQueries.quoteTerm(typeName) ); + IndexQueries.appendResourceIdTerm(sb, Dependencies.FIELD_TYPE_RESOURCE, type); } if (!emptyFilter) { if (sb.length() > 0) diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Dependencies.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Dependencies.java index 3ca66ce77..0aa36390b 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Dependencies.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Dependencies.java @@ -38,13 +38,14 @@ public class Dependencies extends FunctionImpl4 typeStrings = cs.createMap(String.class); + Map> typeStrings = cs.createMap(String.class); for(Entry e : result) { if(e.principalType != null) { - String typeString = typeStrings.get(e.principalType); - if(typeString == null) { - typeString = graph.syncRequest(new SuperTypeString(e.principalType)); - if (typeString.isEmpty()) { - LOGGER.error("No name for type", new DatabaseException("No name for type " + NameUtils.getURIOrSafeNameInternal(graph, e.resource) + " (" + e.resource + ")")); - } - typeStrings.put(e.principalType, typeString); - } - e.types = typeString; + Pair typeString = typeStrings.get(e.principalType); + if(typeString == null) { + String superTypeString = graph.syncRequest(new SuperTypeString(e.principalType)); + if (superTypeString.isEmpty()) { + LOGGER.error("No name for type", new DatabaseException("No name for type " + NameUtils.getURIOrSafeNameInternal(graph, e.resource) + " (" + e.resource + ")")); + } + String superTypeIds = IndexQueries.toResourceIdString(e.principalType, graph.getSupertypes(e.principalType)); + typeString = Pair.make(superTypeString, superTypeIds); + typeStrings.put(e.principalType, typeString); + } + e.types = typeString.first; + e.typeId = typeString.second; } else { - e.types = graph.syncRequest(new TypeString(L0, graph.getTypes(e.resource))); + Set typeSet = graph.getTypes(e.resource); + e.types = graph.syncRequest(new TypeString(L0, typeSet)); + e.typeId = IndexQueries.toResourceIdString(typeSet); } - GUID id = graph.getPossibleRelatedValue(e.resource, L0.identifier, GUID.BINDING); - if(id != null) - e.id = id.indexString(); - else - e.id = ""; + e.id = IndexQueries.idFromGUID( graph.getPossibleRelatedValue(e.resource, L0.identifier, GUID.BINDING) ); } //SessionGarbageCollection.gc(null, graph.getSession(), false, null); - + } } @@ -223,10 +226,10 @@ public class DependenciesRelation extends UnsupportedRelation implements Generic long time = System.nanoTime(); - SerialisationSupport ss = graph.getService(SerialisationSupport.class); + SerialisationSupport ss = graph.getService(SerialisationSupport.class); Resource subject = ss.getResource(subjectId); - + Collection entries = find(graph, subject); long time2 = System.nanoTime(); @@ -234,10 +237,10 @@ public class DependenciesRelation extends UnsupportedRelation implements Generic if (PROFILE) LOGGER.info("Found " + entries.size() + " dependencies in " + 1e-6 * (time2 - time) + "ms for " + graph.getPossibleURI(subject) + "."); - ArrayList result = new ArrayList(); + ArrayList result = new ArrayList<>(); for (Entry entry : entries) { if(entry.name == null) continue; - result.add(new Object[] { ss.getRandomAccessId(entry.parent), ss.getRandomAccessId(entry.resource), entry.name, entry.types, entry.id, entry.name, entry.types }); + result.add(new Object[] { ss.getRandomAccessId(entry.parent), ss.getRandomAccessId(entry.resource), entry.name, entry.types, entry.id, entry.name, entry.types, entry.typeId }); } return result; @@ -360,201 +363,204 @@ public class DependenciesRelation extends UnsupportedRelation implements Generic @Override public synchronized void trackAndIndex(RequestProcessor processor, Resource model__) { - if(trackers == 0) { + if(trackers == 0) { - if(listener != null) throw new IllegalStateException("Dependency tracking was active"); - - listener = new GenericChangeListener() { - - @Override - public boolean preEventRequest() { - return !Indexing.isDependenciesIndexingDisabled(); - } - - @Override - public void onEvent(ReadGraph graph, MetadataI metadata, DependencyChanges event) throws DatabaseException { - - TimeLogger.log(DependenciesRelation.class, "trackAndIndex.onEvent: starting index update processing"); - - if(DEBUG) - LOGGER.info("Adding metadata " + event + " in revision " + graph.getService(ManagementSupport.class).getHeadRevisionId()); - - WriteGraph w = (WriteGraph)graph; - if(!event.isEmpty()) - w.addMetadata(event); - - final Session session = graph.getSession(); - final IndexedRelations indexer = session.getService(IndexedRelations.class); - Layer0 L0 = Layer0.getInstance(graph); - SerialisationSupport ss = graph.getService(SerialisationSupport.class); - - for(Map.Entry modelEntry : event.get().entrySet()) { - - final Resource model = modelEntry.getKey(); - final Change[] changes = modelEntry.getValue(); - - boolean linkChange = false; - - Collection _additions = Collections.emptyList(); - Collection _removals = Collections.emptyList(); - Collection _replacementKeys = Collections.emptyList(); - Collection _replacementObjects = Collections.emptyList(); - Collection> _typeChanges = Collections.emptyList(); - - if(DEBUG) LOGGER.info("MODEL: " + NameUtils.getSafeLabel(graph, model)); - // final Change[] changes = event.get(model); - if(DEBUG) LOGGER.info(" CHANGES: " + Arrays.toString(changes)); - if (changes != null) { - _additions = new ArrayList(); - _removals = new ArrayList(); - _replacementKeys = new ArrayList(); - _replacementObjects = new ArrayList(); - _typeChanges = new HashSet>(); - - for (Change _entry : changes) { - if (_entry instanceof ComponentAddition) { - ComponentAddition entry = (ComponentAddition)_entry; - final String name = graph.getPossibleRelatedValue(entry.component, L0.HasName, Bindings.STRING); - final GUID id = graph.getPossibleRelatedValue(entry.component, L0.identifier, GUID.BINDING); - final String types = graph.syncRequest(new TypeString(L0, graph.getTypes(entry.component))); - if (name != null && types != null) { - if(!entry.isValid(graph)) continue; - Resource parent = graph.getPossibleObject(entry.component, L0.PartOf); - if (parent != null) { - _additions.add(new Object[] { ss.getRandomAccessId(parent), ss.getRandomAccessId(entry.component), name, types, id != null ? id.indexString() : "", name, types}); - } else { - //LOGGER.info("resource " + entry.component + ": no parent for entry " + name + " " + types); - } - } else { - //LOGGER.info("resource " + entry.component + ": " + name + " " + types); - } - } else if(_entry instanceof ComponentModification) { - ComponentModification entry = (ComponentModification)_entry; - final String name = graph.getPossibleRelatedValue(entry.component, L0.HasName, Bindings.STRING); - final GUID id = graph.getPossibleRelatedValue(entry.component, L0.identifier, GUID.BINDING); - if(graph.isInstanceOf(entry.component, L0.Type)) { - SerialisationSupport support = session.getService(SerialisationSupport.class); - _typeChanges.add(new Pair(name, String.valueOf(support.getRandomAccessId((Resource) entry.component)))); - } else { - final String types = graph.syncRequest(new TypeString(L0, graph.getTypes(entry.component))); - if (name != null && types != null) { - Resource part = graph.getPossibleObject(entry.component, L0.PartOf); - if(part != null) { - _replacementKeys.add(ss.getRandomAccessId(entry.component)); - _replacementObjects.add(new Object[] { ss.getRandomAccessId(part), - ss.getRandomAccessId(entry.component), name, types, id != null ? id.indexString() : "", name, types}); - } - } - } - } else if (_entry instanceof ComponentRemoval) { - ComponentRemoval entry = (ComponentRemoval)_entry; - if(!entry.isValid(graph)) continue; - _removals.add(ss.getRandomAccessId(((ComponentRemoval)_entry).component)); - } else if (_entry instanceof LinkChange) { - linkChange = true; - } - } - } - - final boolean reset = linkChange || event.hasUnresolved; - //LOGGER.info("dependencies(" + NameUtils.getSafeLabel(graph, model) + "): reset=" + reset + " linkChange=" + linkChange + " unresolved=" + event.hasUnresolved ); - - if (reset || !_additions.isEmpty() || !_removals.isEmpty() || !_replacementKeys.isEmpty() || !_typeChanges.isEmpty()) { - - TimeLogger.log(DependenciesRelation.class, "trackAndIndex.onEvent: starting index update"); - - final Collection additions = _additions; - final Collection removals = _removals; - final Collection replacementKeys = _replacementKeys; - final Collection replacementObjects = _replacementObjects; - final boolean typeNameChanges = typeNameChanges(graph, indexer, model, _typeChanges); - - final UUID pending = Indexing.makeIndexPending(); - - { - { - try { - boolean didChange = false; - // Unresolved and linkChanges are not relevant any more - boolean doReset = typeNameChanges; - - if (doReset) { - - if(DEBUG) { - LOGGER.info("resetIndex " + reset + " " + typeNameChanges); - } - - indexer.removeAll(null, graph, DependenciesRelation.this, resource, model); - didChange = true; - - } else { - - if (!replacementKeys.isEmpty() && (replacementKeys.size() == replacementObjects.size())) { - if(DEBUG) { - LOGGER.info(replacementKeys.size() + " index replacements: " + replacementKeys); - } - didChange |= indexer.replace(null, graph, DependenciesRelation.this, resource, model, Dependencies.FIELD_RESOURCE, replacementKeys, replacementObjects); - } - if (!removals.isEmpty()) { - if(DEBUG) { - LOGGER.info(removals.size() + " index removals: " + removals); - } - indexer.remove(null, graph, DependenciesRelation.this, resource, model, Dependencies.FIELD_RESOURCE, removals); - didChange = true; - } - if (!additions.isEmpty()) { - if(DEBUG) { - for(Object[] os : additions) LOGGER.info("Adding to index " + model + ": " + Arrays.toString(os)); - } - //LOGGER.info(additions.size() + " index insertions"); - indexer.insert(null, graph, DependenciesRelation.this, resource, model, additions); - didChange = true; - } - - } - - if (didChange) - // TODO: because this data is ran with - // ThreadUtils.getBlockingWorkExecutor() - // fireListeners needs to use peekService, - // not getService since there is no - // guarantee that the session isn't being - // disposed while this method is executing. - fireListeners(graph, model); - - } catch (Throwable t) { - // Just to know if something unexpected happens here. - LOGGER.error("Dependencies index update failed for model " - + model + " and relation " + resource + ".", t); - - // NOTE: Last resort: failure to update index - // properly results in removal of the whole index. - // This is the only thing that can be done - // at this point to ensure that the index will - // return correct results in the future, through - // complete reinitialization. - //indexer.removeAll(null, session, DependenciesRelation.this, resource, model); - } finally { - Indexing.releaseIndexPending(pending); - Indexing.clearCaches(model); - } - } - } - - TimeLogger.log(DependenciesRelation.class, "trackAndIndex.onEvent: index update done"); - } - } - - } - - }; + if(listener != null) throw new IllegalStateException("Dependency tracking was active"); - GraphChangeListenerSupport changeSupport = processor.getService(GraphChangeListenerSupport.class); - changeSupport.addMetadataListener(listener); + listener = new GenericChangeListener() { - } + @Override + public boolean preEventRequest() { + return !Indexing.isDependenciesIndexingDisabled(); + } + + @Override + public void onEvent(ReadGraph graph, MetadataI metadata, DependencyChanges event) throws DatabaseException { + + TimeLogger.log(DependenciesRelation.class, "trackAndIndex.onEvent: starting index update processing"); + + if(DEBUG) + LOGGER.info("Adding metadata " + event + " in revision " + graph.getService(ManagementSupport.class).getHeadRevisionId()); + + WriteGraph w = (WriteGraph)graph; + if(!event.isEmpty()) + w.addMetadata(event); + + final Session session = graph.getSession(); + final IndexedRelations indexer = session.getService(IndexedRelations.class); + Layer0 L0 = Layer0.getInstance(graph); + SerialisationSupport ss = graph.getService(SerialisationSupport.class); + + for(Map.Entry modelEntry : event.get().entrySet()) { + + final Resource model = modelEntry.getKey(); + final Change[] changes = modelEntry.getValue(); + + boolean linkChange = false; + + Collection _additions = Collections.emptyList(); + Collection _removals = Collections.emptyList(); + Collection _replacementKeys = Collections.emptyList(); + Collection _replacementObjects = Collections.emptyList(); + Collection> _typeChanges = Collections.emptyList(); + + if(DEBUG) LOGGER.info("MODEL: " + NameUtils.getSafeLabel(graph, model)); + if (changes != null) { + if (DEBUG) { + LOGGER.info(" CHANGE COUNT: " + changes.length); + for (Change c : changes) + LOGGER.info(" CHANGE: " + c.toString(graph)); + } + _additions = new ArrayList<>(); + _removals = new ArrayList<>(); + _replacementKeys = new ArrayList<>(); + _replacementObjects = new ArrayList<>(); + _typeChanges = new HashSet<>(); + + for (Change _entry : changes) { + if (_entry instanceof ComponentAddition) { + ComponentAddition entry = (ComponentAddition)_entry; + final String name = graph.getPossibleRelatedValue(entry.component, L0.HasName, Bindings.STRING); + Set typeSet = graph.getTypes(entry.component); + if (name != null && typeSet != null) { + if (!entry.isValid(graph)) + continue; + Resource parent = graph.getPossibleObject(entry.component, L0.PartOf); + if (parent != null) { + final GUID id = graph.getPossibleRelatedValue(entry.component, L0.identifier, GUID.BINDING); + final String types = graph.syncRequest(new TypeString(L0, typeSet)); + final String typeIds = IndexQueries.toResourceIdString(typeSet); + _additions.add(new Object[] { ss.getRandomAccessId(parent), ss.getRandomAccessId(entry.component), name, types, IndexQueries.idFromGUID(id), name, types, typeIds}); + } else { + //LOGGER.info("resource " + entry.component + ": no parent for entry " + name + " " + types); + } + } else { + //LOGGER.info("resource " + entry.component + ": " + name + " " + types); + } + } else if(_entry instanceof ComponentModification) { + ComponentModification entry = (ComponentModification)_entry; + final String name = graph.getPossibleRelatedValue(entry.component, L0.HasName, Bindings.STRING); + if(graph.isInstanceOf(entry.component, L0.Type)) { + SerialisationSupport support = session.getService(SerialisationSupport.class); + _typeChanges.add(new Pair(name, String.valueOf(support.getRandomAccessId((Resource) entry.component)))); + } else { + Set typeSet = graph.getTypes(entry.component); + if (name != null && !typeSet.isEmpty()) { + Resource part = graph.getPossibleObject(entry.component, L0.PartOf); + if(part != null) { + final GUID id = graph.getPossibleRelatedValue(entry.component, L0.identifier, GUID.BINDING); + final String types = graph.syncRequest(new TypeString(L0, typeSet)); + final String typeIds = IndexQueries.toResourceIdString(typeSet); + _replacementKeys.add(ss.getRandomAccessId(entry.component)); + _replacementObjects.add(new Object[] { ss.getRandomAccessId(part), + ss.getRandomAccessId(entry.component), name, types, IndexQueries.idFromGUID(id), name, types, typeIds}); + } + } + } + } else if (_entry instanceof ComponentRemoval) { + ComponentRemoval entry = (ComponentRemoval)_entry; + if(!entry.isValid(graph)) continue; + _removals.add(ss.getRandomAccessId(((ComponentRemoval)_entry).component)); + } else if (_entry instanceof LinkChange) { + linkChange = true; + } + } + } + + final boolean reset = linkChange || event.hasUnresolved; + //LOGGER.info("dependencies(" + NameUtils.getSafeLabel(graph, model) + "): reset=" + reset + " linkChange=" + linkChange + " unresolved=" + event.hasUnresolved ); + + if (reset || !_additions.isEmpty() || !_removals.isEmpty() || !_replacementKeys.isEmpty() || !_typeChanges.isEmpty()) { + + TimeLogger.log(DependenciesRelation.class, "trackAndIndex.onEvent: starting index update"); + + final Collection additions = _additions; + final Collection removals = _removals; + final Collection replacementKeys = _replacementKeys; + final Collection replacementObjects = _replacementObjects; + final boolean typeNameChanges = typeNameChanges(graph, indexer, model, _typeChanges); + + final UUID pending = Indexing.makeIndexPending(); + try { + boolean didChange = false; + // Unresolved and linkChanges are not relevant any more + boolean doReset = typeNameChanges; + + if (doReset) { + + if(DEBUG) { + LOGGER.info("resetIndex " + reset + " " + typeNameChanges); + } + + indexer.removeAll(null, graph, DependenciesRelation.this, resource, model); + didChange = true; + + } else { + + if (!replacementKeys.isEmpty() && (replacementKeys.size() == replacementObjects.size())) { + if(DEBUG) { + LOGGER.info(replacementKeys.size() + " index replacements: " + replacementKeys); + } + didChange |= indexer.replace(null, graph, DependenciesRelation.this, resource, model, Dependencies.FIELD_RESOURCE, replacementKeys, replacementObjects); + } + if (!removals.isEmpty()) { + if(DEBUG) { + LOGGER.info(removals.size() + " index removals: " + removals); + } + indexer.remove(null, graph, DependenciesRelation.this, resource, model, Dependencies.FIELD_RESOURCE, removals); + didChange = true; + } + if (!additions.isEmpty()) { + if(DEBUG) { + for(Object[] os : additions) LOGGER.info("Adding to index " + model + ": " + Arrays.toString(os)); + } + //LOGGER.info(additions.size() + " index insertions"); + indexer.insert(null, graph, DependenciesRelation.this, resource, model, additions); + didChange = true; + } + + } + + if (didChange) + // TODO: because this data is ran with + // ThreadUtils.getBlockingWorkExecutor() + // fireListeners needs to use peekService, + // not getService since there is no + // guarantee that the session isn't being + // disposed while this method is executing. + fireListeners(graph, model); + + } catch (Throwable t) { + // Just to know if something unexpected happens here. + LOGGER.error("Dependencies index update failed for model " + + model + " and relation " + resource + ".", t); + + // NOTE: Last resort: failure to update index + // properly results in removal of the whole index. + // This is the only thing that can be done + // at this point to ensure that the index will + // return correct results in the future, through + // complete reinitialization. + //indexer.removeAll(null, session, DependenciesRelation.this, resource, model); + } finally { + Indexing.releaseIndexPending(pending); + Indexing.clearCaches(model); + } + + TimeLogger.log(DependenciesRelation.class, "trackAndIndex.onEvent: index update done"); + } + } - trackers++; + } + + }; + + GraphChangeListenerSupport changeSupport = processor.getService(GraphChangeListenerSupport.class); + changeSupport.addMetadataListener(listener); + + } + + trackers++; } @@ -617,22 +623,22 @@ public class DependenciesRelation extends UnsupportedRelation implements Generic } public static void addSubtree(ReadGraph graph, Resource indexRoot, Resource subtreeRoot) throws DatabaseException { - + DependenciesRelation dr = new DependenciesRelation(graph, indexRoot); - SerialisationSupport ss = graph.getService(SerialisationSupport.class); + SerialisationSupport ss = graph.getService(SerialisationSupport.class); - ArrayList entries = dr.find(graph, subtreeRoot); - entries.add(new Entry(graph, subtreeRoot)); + ArrayList entries = dr.find(graph, subtreeRoot); + entries.add(new Entry(graph, subtreeRoot)); ArrayList result = new ArrayList(entries.size()); for (Entry entry : entries) { - result.add(new Object[] { ss.getRandomAccessId(entry.parent), ss.getRandomAccessId(entry.resource), entry.name, entry.types, entry.id, entry.name, entry.types }); + result.add(new Object[] { ss.getRandomAccessId(entry.parent), ss.getRandomAccessId(entry.resource), entry.name, entry.types, entry.id, entry.name, entry.types, entry.typeId }); } Layer0X L0X = Layer0X.getInstance(graph); - IndexedRelations indexer = graph.getService(IndexedRelations.class); - indexer.insert(null, graph, dr, L0X.DependenciesRelation, indexRoot, result); - + IndexedRelations indexer = graph.getService(IndexedRelations.class); + indexer.insert(null, graph, dr, L0X.DependenciesRelation, indexRoot, result); + } - + } diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Entry.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Entry.java index 8da820949..50d723ec9 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Entry.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Entry.java @@ -1,5 +1,7 @@ package org.simantics.db.layer0.genericrelation; +import java.util.Set; + import org.simantics.databoard.Bindings; import org.simantics.datatypes.literal.GUID; import org.simantics.db.ReadGraph; @@ -22,13 +24,10 @@ class Entry implements Comparable { this.parent = graph.getPossibleObject(resource, L0.PartOf); this.resource = resource; this.name = graph.getPossibleRelatedValue(resource, L0.HasName, Bindings.STRING); - this.types = graph.syncRequest(new TypeString(L0, graph.getTypes(resource))); - this.id = idFromGUID(graph.getPossibleRelatedValue(resource, L0.identifier, GUID.BINDING)); - } - - private static String idFromGUID(GUID guid) { - if(guid == null) return ""; - return guid.indexString(); + Set typeSet = graph.getTypes(resource); + this.types = graph.syncRequest(new TypeString(L0, typeSet)); + this.id = IndexQueries.idFromGUID(graph.getPossibleRelatedValue(resource, L0.identifier, GUID.BINDING)); + this.typeId = IndexQueries.toResourceIdString(typeSet); } Entry(ReadGraph graph, Resource resource) throws DatabaseException { @@ -41,6 +40,7 @@ class Entry implements Comparable { String types; String name; String id; + String typeId; Resource principalType; @Override diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/IndexQueries.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/IndexQueries.java index 2be6bf5d0..ee6296fdd 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/IndexQueries.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/IndexQueries.java @@ -1,5 +1,9 @@ package org.simantics.db.layer0.genericrelation; +import java.util.Collection; + +import org.simantics.datatypes.literal.GUID; +import org.simantics.db.Resource; /** * This class contains utilities related to queries made into Lucene indexes, @@ -183,6 +187,22 @@ public class IndexQueries { ).toString(); } + public static StringBuilder appendLongTerm(StringBuilder sb, String field, long term) { + return sb.append(field).append(':').append(term); + } + + public static String longTerm(String field, long term) { + return appendLongTerm(new StringBuilder(), field, term).toString(); + } + + public static StringBuilder appendResourceIdTerm(StringBuilder sb, String field, Resource term) { + return appendLongTerm(sb, field, term.getResourceId()); + } + + public static String resourceIdTerm(String field, Resource term) { + return appendLongTerm(new StringBuilder(), field, term.getResourceId()).toString(); + } + private static String join(String withString, String... exps) { if (exps.length == 0) return ""; @@ -210,6 +230,32 @@ public class IndexQueries { return join(" OR ", exps); } + public static String idFromGUID(GUID guid) { + return guid != null ? guid.indexString() : ""; + } + + public static String toResourceIdString(Resource r, Collection rs) { + StringBuilder sb = new StringBuilder(); + sb.append(r.getResourceId()); + for (Resource rr : rs) + sb.append(' ').append(rr.getResourceId()); + return sb.toString(); + } + + public static String toResourceIdString(Collection rs) { + if (rs.isEmpty()) + return ""; + StringBuilder sb = new StringBuilder(); + boolean first = true; + for (Resource rr : rs) { + if (!first) + sb.append(' '); + first = false; + sb.append(rr.getResourceId()); + } + return sb.toString(); + } + // public static void main(String[] args) { // System.out.println("esc: " + escape("AND01", true, true)); // System.out.println("esc: " + escape("AND 01", true, true)); diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/request/IndexedInstances.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/request/IndexedInstances.java index 09a1fc902..57aefa519 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/request/IndexedInstances.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/request/IndexedInstances.java @@ -1,19 +1,13 @@ package org.simantics.db.layer0.request; -import java.util.Collection; -import java.util.Collections; import java.util.HashSet; -import java.util.Map; import java.util.Set; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.ResourceRead2; import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.genericrelation.IndexQueries; -import org.simantics.layer0.Layer0; -import org.simantics.operation.Layer0X; -import org.simantics.scl.runtime.function.Function; +import org.simantics.db.layer0.QueryIndexUtils; public class IndexedInstances extends ResourceRead2> { @@ -23,28 +17,7 @@ public class IndexedInstances extends ResourceRead2> { @Override public Set perform(ReadGraph graph) throws DatabaseException { - - Layer0 L0 = Layer0.getInstance(graph); - Layer0X L0X = Layer0X.getInstance(graph); - - String typeName = graph.getRelatedValue(resource, L0.HasName); - - Function dependencies = graph.adapt(L0X.Dependencies, Function.class); - - Collection> results = (Collection>)dependencies.apply(graph, resource2, "Types:" + IndexQueries.quoteTerm(typeName)); - if (results == null) - return Collections.emptySet(); - - HashSet result = new HashSet(results.size()); - for(Map entry : results) { - Resource res = (Resource)entry.get("Resource"); - if(res != null) { - if (graph.isInstanceOf(res, resource)) - result.add(res); - } - } - return result; - + return new HashSet<>(QueryIndexUtils.searchByTypeShallow(graph, resource2, resource)); } } diff --git a/bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/SearchResourceDialog.java b/bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/SearchResourceDialog.java index 06710f6e2..591436dc5 100644 --- a/bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/SearchResourceDialog.java +++ b/bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/SearchResourceDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2016 Association for Decentralized Information Management + * Copyright (c) 2007, 2019 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 @@ -311,8 +311,9 @@ public class SearchResourceDialog extends FilteredItemsSelectionDialog { Resource project = Simantics.peekProjectResource(); if (project != null) { + Layer0 L0 = Layer0.getInstance(graph); IResourceFilter rf = resourceFilter; - String filter = getFilterForResourceFilter(rf); + String filter = getFilterForResourceFilter(L0, rf); if (!filter.isEmpty()) filter += " AND "; //$NON-NLS-1$ @@ -320,8 +321,6 @@ public class SearchResourceDialog extends FilteredItemsSelectionDialog { filter += Arrays.stream(terms).map(term -> "+" + IndexQueries.escape(term.toLowerCase(), false) + "*").collect(Collectors.joining(" ")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ filter +=")"; //$NON-NLS-1$ - Layer0 L0 = Layer0.getInstance(graph); - Set indexRoots = new HashSet<>(); indexRoots.addAll(graph.syncRequest(new ObjectsWithType(project, L0.ConsistsOf, L0.IndexRoot))); indexRoots.addAll(graph.syncRequest(new OntologiesFromLibrary(graph.getRootLibrary()))); @@ -472,13 +471,13 @@ public class SearchResourceDialog extends FilteredItemsSelectionDialog { this.resourceFilter = resourceFilter; } - private String getFilterForResourceFilter(IResourceFilter filter) { + private String getFilterForResourceFilter(Layer0 l0, IResourceFilter filter) { if (filter == null || filter == ResourceSearch.FILTER_ALL) return ""; //$NON-NLS-1$ if (filter == ResourceSearch.FILTER_RELATIONS) - return "Types:Relation"; //$NON-NLS-1$ + return IndexQueries.resourceIdTerm(Dependencies.FIELD_TYPE_RESOURCE, l0.Relation); if (filter == ResourceSearch.FILTER_TYPES) - return "Types:Type"; //$NON-NLS-1$ + return IndexQueries.resourceIdTerm(Dependencies.FIELD_TYPE_RESOURCE, l0.Type); return ""; //$NON-NLS-1$ } diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/ExistingInstancesRemover.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/ExistingInstancesRemover.java index 787a400f9..84c0f4151 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/ExistingInstancesRemover.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/ExistingInstancesRemover.java @@ -90,23 +90,6 @@ public class ExistingInstancesRemover extends AbstractRemover { if (indexRoot == null) return Collections.emptySet(); -// @SuppressWarnings("rawtypes") -// Function modules = graph.adapt(Layer0X.getInstance(graph).Dependencies, Function.class); -// @SuppressWarnings("unchecked") -// List> result = (List>) modules.apply(graph, root, "Types:\"" + IndexQueries.escape(componentTypeName) + "\""); -// if (result.isEmpty()) { -// justRemove(graph); -// return; -// } -// -// final Set instances = new HashSet(); -// for (Map entry : result) { -// Resource c = (Resource) entry.get(Dependencies.FIELD_RESOURCE); -// if (c != null && graph.hasStatement(c, L0.InstanceOf, resource)) { -// instances.add(c); -// } -// } - Set result = new THashSet(); Instances search = graph.adapt(type, Instances.class); discoverInstances(graph, type, indexRoot, search, result); diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/Removers.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/Removers.java index 3d0499612..4949793b4 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/Removers.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/Removers.java @@ -11,12 +11,9 @@ *******************************************************************************/ package org.simantics.modeling.adapters; -import gnu.trove.set.hash.THashSet; - import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Map; import java.util.Set; import org.simantics.databoard.Bindings; @@ -28,7 +25,7 @@ import org.simantics.db.common.request.PossibleObjectWithType; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.VariableException; -import org.simantics.db.layer0.genericrelation.IndexQueries; +import org.simantics.db.layer0.QueryIndexUtils; import org.simantics.db.layer0.request.PossibleModel; import org.simantics.db.layer0.variable.RVI; import org.simantics.db.layer0.variable.Variable; @@ -37,11 +34,11 @@ import org.simantics.diagram.content.ConnectionUtil; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.layer0.Layer0; import org.simantics.modeling.ModelingResources; -import org.simantics.operation.Layer0X; -import org.simantics.scl.runtime.function.Function; import org.simantics.structural.stubs.StructuralResource2; import org.simantics.utils.ui.ErrorLogger; +import gnu.trove.set.hash.THashSet; + /** * @author Tuukka Lehtonen */ @@ -121,48 +118,41 @@ final class Removers { return; NamedResource namedRoot = new NamedResource(rootName, root); - @SuppressWarnings("rawtypes") - Function modules = graph.adapt(Layer0X.getInstance(graph).Dependencies, Function.class); - @SuppressWarnings("unchecked") - List> rows = (List>) modules.apply(graph, root, "Types:" + IndexQueries.quoteTerm(result.componentType.getName())); - if (rows.isEmpty()) + List components = QueryIndexUtils.searchByTypeShallow(graph, root, result.componentType.getResource()); + if (components.isEmpty()) return; ModelingResources MOD = ModelingResources.getInstance(graph); StructuralResource2 STR = StructuralResource2.getInstance(graph); - for (Map row : rows) { - Resource component = (Resource) row.get("Resource"); - if (graph.isInstanceOf(component, result.componentType.getResource())) { - String componentName = graph.getPossibleRelatedValue(component, L0.HasName, Bindings.STRING); - next_connection: - for (Resource connection : graph.getObjects(component, connectionRelation)) { - if (graph.isInstanceOf(connection, STR.Connection)) { - - if (diagramConnectionRelation != null) { - // When diagram connection relation is defined, validate that - // exactly the specified diagram connection relation is being - // used and not some other relation from another symbol. - for (Resource element : graph.getObjects(component, MOD.ComponentToElement)) { - for (Resource diagramConnector : graph.getObjects(element, diagramConnectionRelation)) { - Resource diagramConnection = ConnectionUtil.tryGetConnection(graph, diagramConnector); - if (diagramConnection == null) - continue; - Resource correspondingConnection = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnection); - Resource correspondingConnectionSpecial = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnectionSpecial); - if (connection.equals(correspondingConnection) || connection.equals(correspondingConnectionSpecial)) { - addUse(graph, component, componentName, namedRoot, rootURI, result); - continue next_connection; - } + for (Resource component : components) { + String componentName = graph.getPossibleRelatedValue(component, L0.HasName, Bindings.STRING); + next_connection: + for (Resource connection : graph.getObjects(component, connectionRelation)) { + if (graph.isInstanceOf(connection, STR.Connection)) { + + if (diagramConnectionRelation != null) { + // When diagram connection relation is defined, validate that + // exactly the specified diagram connection relation is being + // used and not some other relation from another symbol. + for (Resource element : graph.getObjects(component, MOD.ComponentToElement)) { + for (Resource diagramConnector : graph.getObjects(element, diagramConnectionRelation)) { + Resource diagramConnection = ConnectionUtil.tryGetConnection(graph, diagramConnector); + if (diagramConnection == null) + continue; + Resource correspondingConnection = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnection); + Resource correspondingConnectionSpecial = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnectionSpecial); + if (connection.equals(correspondingConnection) || connection.equals(correspondingConnectionSpecial)) { + addUse(graph, component, componentName, namedRoot, rootURI, result); + continue next_connection; } } - } else { - addUse(graph, component, componentName, namedRoot, rootURI, result); } + } else { + addUse(graph, component, componentName, namedRoot, rootURI, result); } - } - } + } } } diff --git a/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java b/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java index cfd5fe69b..b311aed94 100644 --- a/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java +++ b/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java @@ -1,8 +1,5 @@ package org.simantics.structural.synchronization.client; -import gnu.trove.map.hash.TObjectIntHashMap; -import gnu.trove.set.hash.THashSet; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -28,10 +25,15 @@ import org.simantics.structural.synchronization.protocol.SerializedVariable; import org.simantics.structural.synchronization.protocol.SynchronizationEventHandler; import org.simantics.structural.synchronization.protocol.SynchronizationException; import org.simantics.structural2.variables.VariableConnectionPointDescriptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; public class Synchronizer { - public static boolean TRACE = false; + private static final Logger LOGGER = LoggerFactory.getLogger(Synchronizer.class); ReadGraph graph; Layer0 L0; @@ -152,8 +154,8 @@ public class Synchronizer { */ public void fullSynchronization(Variable variable, SynchronizationEventHandler handler) throws DatabaseException { long duration = 0; - if(TRACE) { - System.out.println("fullSynchronization " + variable.getURI(graph)); + if(LOGGER.isTraceEnabled()) { + LOGGER.trace("fullSynchronization {}", variable.getURI(graph)); duration -= System.nanoTime(); } SCLContext context = SCLContext.getCurrent(); @@ -165,9 +167,9 @@ public class Synchronizer { } finally { context.put("graph", oldGraph); } - if(TRACE) { + if(LOGGER.isTraceEnabled()) { duration += System.nanoTime(); - System.out.println("full sync in " + 1e-9*duration + "s."); + LOGGER.trace("full sync done in {} s", 1e-9*duration); } } @@ -275,8 +277,8 @@ public class Synchronizer { public void partialSynchronization(Variable variable, SynchronizationEventHandler handler, TObjectIntHashMap changeFlags) throws DatabaseException { long duration = 0; - if(TRACE) { - System.out.println("partialSynchronization " + variable.getURI(graph)); + if(LOGGER.isTraceEnabled()) { + LOGGER.trace("partialSynchronization {}", variable.getURI(graph)); duration -= System.nanoTime(); } int changeStatus = changeFlags.get(variable); @@ -290,27 +292,31 @@ public class Synchronizer { } finally { context.put("graph", oldGraph); } - if(TRACE) { + if(LOGGER.isTraceEnabled()) { duration += System.nanoTime(); - System.out.println("partial sync in " + 1e-9*duration + "s."); + LOGGER.trace("partial sync in {} s", 1e-9*duration); } } public void partialSynchronization(Variable variable, SynchronizationEventHandler handler, long fromRevision) throws DatabaseException { + boolean trace = LOGGER.isTraceEnabled(); + if (trace) + LOGGER.trace("Partial synchronization for {} from rev {}", variable.getURI(graph), fromRevision); + TObjectIntHashMap modifiedComponents = StructuralChangeFlattener.getModifiedComponents(graph, variable, fromRevision); - /*System.out.println("----------------"); - modifiedComponents.forEachEntry( - new TObjectIntProcedure() { - @Override - public boolean execute(Variable a, int b) { - try { - System.out.println("Changed: " + a.getURI(graph) + " " + b); - } catch (DatabaseException e) { - e.printStackTrace(); - } - return true; - } - });*/ + + if (trace) { + LOGGER.trace("----------------"); + modifiedComponents.forEachEntry((Variable a, int b) -> { + try { + LOGGER.trace("Changed: " + a.getURI(graph) + " " + b); + } catch (DatabaseException e) { + LOGGER.error("Variable.getURI failed", e); + } + return true; + }); + } + partialSynchronization(variable, handler, modifiedComponents); } @@ -324,5 +330,4 @@ public class Synchronizer { return graph.getService(ManagementSupport.class).getHeadRevisionId()+1; } - } -- 2.47.1