X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.db.layer0%2Fsrc%2Forg%2Fsimantics%2Fdb%2Flayer0%2Fgenericrelation%2FDependenciesRelation.java;h=771bf8649df554121b0af9e86405d538b89422d0;hp=6f310120bc6f5c5cc6eb9bbf0469199091a471ac;hb=ad0e5bf4b34705988e23c9ee3f8e4fcbb760c701;hpb=0f2d6b33db9eabe0c1b142f6d0197a5d1446c3b1 diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependenciesRelation.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependenciesRelation.java index 6f310120b..771bf8649 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependenciesRelation.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependenciesRelation.java @@ -18,6 +18,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import org.simantics.databoard.Bindings; @@ -79,7 +80,8 @@ public class DependenciesRelation extends UnsupportedRelation implements Generic Pair.make(Dependencies.FIELD_TYPES, "Text"), Pair.make(Dependencies.FIELD_GUID, "Text"), Pair.make(Dependencies.FIELD_NAME_SEARCH, "Text"), - Pair.make(Dependencies.FIELD_TYPES_SEARCH, "Text") + Pair.make(Dependencies.FIELD_TYPES_SEARCH, "Text"), + Pair.make(Dependencies.FIELD_TYPE_RESOURCE, "Text") }; final Resource resource; @@ -175,30 +177,31 @@ public class DependenciesRelation extends UnsupportedRelation implements Generic }); - Map 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); + } - + }