X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.structural.synchronization.client%2Fsrc%2Forg%2Fsimantics%2Fstructural%2Fsynchronization%2FSynchronizer.java;fp=bundles%2Forg.simantics.structural.synchronization.client%2Fsrc%2Forg%2Fsimantics%2Fstructural%2Fsynchronization%2FSynchronizer.java;h=9c7428416531a2da02c33d9ac10c895736a4797c;hp=d2738d84444fab9c02739555a676f1bf156d26ee;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/Synchronizer.java b/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/Synchronizer.java index d2738d844..9c7428416 100644 --- a/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/Synchronizer.java +++ b/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/Synchronizer.java @@ -1,325 +1,325 @@ -package org.simantics.structural.synchronization; - -import gnu.trove.map.hash.TObjectIntHashMap; -import gnu.trove.set.hash.THashSet; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; -import org.simantics.db.exception.CancelTransactionException; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.exception.MissingVariableValueException; -import org.simantics.db.layer0.request.ResourceToPossibleVariable; -import org.simantics.db.layer0.variable.RVI; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.db.service.ManagementSupport; -import org.simantics.layer0.Layer0; -import org.simantics.scl.runtime.SCLContext; -import org.simantics.structural.stubs.StructuralResource2; -import org.simantics.structural.synchronization.protocol.ChildInfo; -import org.simantics.structural.synchronization.protocol.Connection; -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; - -public class Synchronizer { - - public static boolean TRACE = false; - - ReadGraph graph; - Layer0 L0; - StructuralResource2 STR; - THashSet visitedTypes = new THashSet(); - IProgressMonitor monitor; - - double workDone = 0.0; - int workDoneInteger; - int maxWork; - - public Synchronizer(ReadGraph graph) { - this.graph = graph; - L0 = Layer0.getInstance(graph); - STR = StructuralResource2.getInstance(graph); - } - - public void setMonitor(IProgressMonitor monitor, int maxWork) { - this.monitor = monitor; - this.maxWork = maxWork; - this.workDoneInteger = 0; - } - - private void didWork(double amount) { - workDone += amount; - //System.out.println(workDone); - if(monitor != null) { - int t = (int)(workDone * maxWork); - if(t > workDoneInteger) { - monitor.worked(t-workDoneInteger); - workDoneInteger = t; - } - } - } - - ChildInfo mapChild(Variable child) throws DatabaseException { - String name = child.getName(graph); - RVI rvi = child.getRVI(graph); - return new ChildInfo(name, rvi.toString()); - } - - Collection mapChildren(SynchronizationEventHandler handler, Collection children) throws DatabaseException { - ArrayList result = new ArrayList(children.size()); - for(Variable child : children) { - if(child.getPossibleType(graph, STR.Component) != null) - try { - result.add(mapChild(child)); - } catch(Exception e) { - handler.reportProblem("Failed to get ChildInfo for " + child + ".", e); - } - } - return result; - } - - Collection mapConnections(SynchronizationEventHandler handler, Variable child) throws DatabaseException { - ArrayList result = new ArrayList(); - for(Variable conn : child.getProperties(graph, StructuralResource2.URIs.SynchronizedConnectionRelation)) { - String name = conn.getName(graph); - org.simantics.structural2.variables.Connection vc = conn.getValue(graph); - Collection connectionPoints = vc.getConnectionPointDescriptors(graph, null); - List cps = new ArrayList(connectionPoints.size()); - for(VariableConnectionPointDescriptor desc : connectionPoints) { - if(desc.isFlattenedFrom(graph, conn)) continue; - if(!desc.hasClassification(graph, StructuralResource2.URIs.ProvidingConnectionRelation)) continue; - String cpRef = desc.getRelativeRVI(graph, child); - cps.add(cpRef); - } - - result.add(new Connection(name, cps)); - - } - - return result; - - } - - private SerializedVariable serialize(SynchronizationEventHandler handler, Variable var, String name) throws DatabaseException { - try { - SerializedVariable result = new SerializedVariable(name, var.getVariantValue(graph)); - for(Variable prop : var.getProperties(graph, StructuralResource2.URIs.SynchronizedRelation)) { - String pName = prop.getName(graph); - SerializedVariable v = serialize(handler, prop, pName); - if(v != null) result.addProperty(pName, v); - } - return result; - } catch (MissingVariableValueException e) { - handler.reportProblem("Failed to read " + name + ". " + e.getMessage()); - - Throwable cur = e; - while((cur = cur.getCause()) != null) { - if(!(cur instanceof MissingVariableValueException)) { - handler.reportProblem(cur.getMessage()); - break; - } - } - } catch (Exception e) { - handler.reportProblem("Failed to serialize " + name + ": " + e.getMessage(), e); - } - - return null; - - } - - Collection mapProperties(SynchronizationEventHandler handler, Variable child) throws DatabaseException { - ArrayList result = new ArrayList(); - for(Variable prop : child.getProperties(graph, StructuralResource2.URIs.SynchronizedRelation)) { - SerializedVariable serialized = serialize(handler, prop, prop.getName(graph)); - if(serialized != null) result.add(serialized); - } - return result; - } - - /** - * Assumes that the variable points to a composite. - */ - public void fullSynchronization(Variable variable, SynchronizationEventHandler handler) throws DatabaseException { - long duration = 0; - if(TRACE) { - System.out.println("fullSynchronization " + variable.getURI(graph)); - duration -= System.nanoTime(); - } - SCLContext context = SCLContext.getCurrent(); - Object oldGraph = context.put("graph", graph); - try { - handler.beginSynchronization(); - synchronizationRec(variable, handler, null, 1.0); - handler.endSynchronization(); - } finally { - context.put("graph", oldGraph); - } - if(TRACE) { - duration += System.nanoTime(); - System.out.println("full sync in " + 1e-9*duration + "s."); - } - } - - /** - * Recursive implementation of partial and full synchronization. If {@code changeFlags} - * is null, this is full synchronization, otherwise partial synchronization. - */ - private void synchronizationRec(Variable variable, SynchronizationEventHandler handler, - TObjectIntHashMap changeFlags, - double proportionOfWork) throws DatabaseException { - String name = variable.getName(graph); - Resource type = variable.getPossibleType(graph, STR.Component); - if(type == null) { - // This same filtering is done separately in mapChildren when beginComponent has been called for the parent. - return; - } - Collection children = variable.getChildren(graph); - if(graph.isInheritedFrom(type, STR.Composite) || graph.isInheritedFrom(type, STR.AbstractDefinedComponentType)) { - String typeId = graph.getPossibleURI(type); - if(typeId == null) - throw new SynchronizationException("User component " + type + " does not have an URI."); - if(visitedTypes.add(typeId)) - visitType(typeId, type, handler); - boolean endComponentNeeded = false; - try { - Collection propertyMap = mapProperties(handler, variable); - Collection childMap = mapChildren(handler, children); - endComponentNeeded = true; - handler.beginComponent(name, typeId, - propertyMap, - Collections.emptyList(), - childMap); - } catch(Exception e) { - handler.reportProblem("Failed to synchronize " + name + ": " + e.getMessage(), e); - if (endComponentNeeded) - handler.endComponent(); - return; - } - } else { - String typeId = graph.getPossibleURI(type); - if(typeId == null) - throw new SynchronizationException("User component " + type + " does not have an URI."); - if(visitedTypes.add(typeId)) - visitType(typeId, type, handler); - boolean endComponentNeeded = false; - try { - Collection propertyMap = mapProperties(handler, variable); - Collection connectionMap = mapConnections(handler, variable); - Collection childMap = mapChildren(handler, children); - endComponentNeeded = true; - handler.beginComponent(name, - typeId, - propertyMap, - connectionMap, - childMap); - } catch(Exception e) { - handler.reportProblem("Failed to synchronize " + name + ": " + e.getMessage(), e); - if (endComponentNeeded) - handler.endComponent(); - return; - } - } - - if(changeFlags == null) { - // Full synchronization, synchronize all children - if(children.size() > 0) { - double proportionOfWorkForChildren = proportionOfWork / children.size(); - for(Variable child : children) - synchronizationRec(child, handler, null, proportionOfWorkForChildren); - } - else { - didWork(proportionOfWork); - // Full synchronization is cancelable - if(monitor != null && monitor.isCanceled()) - throw new CancelTransactionException(); - } - } - else { - // Partial synchronization, synchronize only children with positive changeFlag - int relevantChildCount = 0; - for(final Variable child : children) { - int changeStatus = changeFlags.get(child); - if(changeStatus != 0) - ++relevantChildCount; - } - if(relevantChildCount > 0) { - double proportionOfWorkForChildren = proportionOfWork / relevantChildCount; - for(final Variable child : children) { - int changeStatus = changeFlags.get(child); - if(changeStatus == 0) - continue; - synchronizationRec(child, handler, - // Apply full synchronization for subtree if changeStatus > 1 - changeStatus==1 ? changeFlags : null, - proportionOfWorkForChildren - ); - } - } - else { - didWork(proportionOfWork); - } - } - handler.endComponent(); - } - - public void partialSynchronization(Variable variable, SynchronizationEventHandler handler, TObjectIntHashMap changeFlags) throws DatabaseException { - long duration = 0; - if(TRACE) { - System.out.println("partialSynchronization " + variable.getURI(graph)); - duration -= System.nanoTime(); - } - int changeStatus = changeFlags.get(variable); - if(changeStatus == 0) return; - SCLContext context = SCLContext.getCurrent(); - Object oldGraph = context.put("graph", graph); - try { - handler.beginSynchronization(); - synchronizationRec(variable, handler, changeStatus == 1 ? changeFlags : null, 1.0); - handler.endSynchronization(); - } finally { - context.put("graph", oldGraph); - } - if(TRACE) { - duration += System.nanoTime(); - System.out.println("partial sync in " + 1e-9*duration + "s."); - } - } - - public void partialSynchronization(Variable variable, SynchronizationEventHandler handler, long fromRevision) throws DatabaseException { - 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; - } - });*/ - partialSynchronization(variable, handler, modifiedComponents); - } - - void visitType(String typeId, Resource typeResource, SynchronizationEventHandler handler) throws DatabaseException { - Variable typeVariable = graph.syncRequest(new ResourceToPossibleVariable(typeResource), TransientCacheAsyncListener.instance()); - handler.beginType(typeId, mapProperties(handler, typeVariable)); - handler.endType(); - } - - public long getHeadRevisionId() throws DatabaseException { - return graph.getService(ManagementSupport.class).getHeadRevisionId()+1; - } - - -} +package org.simantics.structural.synchronization; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; +import org.simantics.db.exception.CancelTransactionException; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.exception.MissingVariableValueException; +import org.simantics.db.layer0.request.ResourceToPossibleVariable; +import org.simantics.db.layer0.variable.RVI; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.service.ManagementSupport; +import org.simantics.layer0.Layer0; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.structural.synchronization.protocol.ChildInfo; +import org.simantics.structural.synchronization.protocol.Connection; +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; + +public class Synchronizer { + + public static boolean TRACE = false; + + ReadGraph graph; + Layer0 L0; + StructuralResource2 STR; + THashSet visitedTypes = new THashSet(); + IProgressMonitor monitor; + + double workDone = 0.0; + int workDoneInteger; + int maxWork; + + public Synchronizer(ReadGraph graph) { + this.graph = graph; + L0 = Layer0.getInstance(graph); + STR = StructuralResource2.getInstance(graph); + } + + public void setMonitor(IProgressMonitor monitor, int maxWork) { + this.monitor = monitor; + this.maxWork = maxWork; + this.workDoneInteger = 0; + } + + private void didWork(double amount) { + workDone += amount; + //System.out.println(workDone); + if(monitor != null) { + int t = (int)(workDone * maxWork); + if(t > workDoneInteger) { + monitor.worked(t-workDoneInteger); + workDoneInteger = t; + } + } + } + + ChildInfo mapChild(Variable child) throws DatabaseException { + String name = child.getName(graph); + RVI rvi = child.getRVI(graph); + return new ChildInfo(name, rvi.toString()); + } + + Collection mapChildren(SynchronizationEventHandler handler, Collection children) throws DatabaseException { + ArrayList result = new ArrayList(children.size()); + for(Variable child : children) { + if(child.getPossibleType(graph, STR.Component) != null) + try { + result.add(mapChild(child)); + } catch(Exception e) { + handler.reportProblem("Failed to get ChildInfo for " + child + ".", e); + } + } + return result; + } + + Collection mapConnections(SynchronizationEventHandler handler, Variable child) throws DatabaseException { + ArrayList result = new ArrayList(); + for(Variable conn : child.getProperties(graph, StructuralResource2.URIs.SynchronizedConnectionRelation)) { + String name = conn.getName(graph); + org.simantics.structural2.variables.Connection vc = conn.getValue(graph); + Collection connectionPoints = vc.getConnectionPointDescriptors(graph, null); + List cps = new ArrayList(connectionPoints.size()); + for(VariableConnectionPointDescriptor desc : connectionPoints) { + if(desc.isFlattenedFrom(graph, conn)) continue; + if(!desc.hasClassification(graph, StructuralResource2.URIs.ProvidingConnectionRelation)) continue; + String cpRef = desc.getRelativeRVI(graph, child); + cps.add(cpRef); + } + + result.add(new Connection(name, cps)); + + } + + return result; + + } + + private SerializedVariable serialize(SynchronizationEventHandler handler, Variable var, String name) throws DatabaseException { + try { + SerializedVariable result = new SerializedVariable(name, var.getVariantValue(graph)); + for(Variable prop : var.getProperties(graph, StructuralResource2.URIs.SynchronizedRelation)) { + String pName = prop.getName(graph); + SerializedVariable v = serialize(handler, prop, pName); + if(v != null) result.addProperty(pName, v); + } + return result; + } catch (MissingVariableValueException e) { + handler.reportProblem("Failed to read " + name + ". " + e.getMessage()); + + Throwable cur = e; + while((cur = cur.getCause()) != null) { + if(!(cur instanceof MissingVariableValueException)) { + handler.reportProblem(cur.getMessage()); + break; + } + } + } catch (Exception e) { + handler.reportProblem("Failed to serialize " + name + ": " + e.getMessage(), e); + } + + return null; + + } + + Collection mapProperties(SynchronizationEventHandler handler, Variable child) throws DatabaseException { + ArrayList result = new ArrayList(); + for(Variable prop : child.getProperties(graph, StructuralResource2.URIs.SynchronizedRelation)) { + SerializedVariable serialized = serialize(handler, prop, prop.getName(graph)); + if(serialized != null) result.add(serialized); + } + return result; + } + + /** + * Assumes that the variable points to a composite. + */ + public void fullSynchronization(Variable variable, SynchronizationEventHandler handler) throws DatabaseException { + long duration = 0; + if(TRACE) { + System.out.println("fullSynchronization " + variable.getURI(graph)); + duration -= System.nanoTime(); + } + SCLContext context = SCLContext.getCurrent(); + Object oldGraph = context.put("graph", graph); + try { + handler.beginSynchronization(); + synchronizationRec(variable, handler, null, 1.0); + handler.endSynchronization(); + } finally { + context.put("graph", oldGraph); + } + if(TRACE) { + duration += System.nanoTime(); + System.out.println("full sync in " + 1e-9*duration + "s."); + } + } + + /** + * Recursive implementation of partial and full synchronization. If {@code changeFlags} + * is null, this is full synchronization, otherwise partial synchronization. + */ + private void synchronizationRec(Variable variable, SynchronizationEventHandler handler, + TObjectIntHashMap changeFlags, + double proportionOfWork) throws DatabaseException { + String name = variable.getName(graph); + Resource type = variable.getPossibleType(graph, STR.Component); + if(type == null) { + // This same filtering is done separately in mapChildren when beginComponent has been called for the parent. + return; + } + Collection children = variable.getChildren(graph); + if(graph.isInheritedFrom(type, STR.Composite) || graph.isInheritedFrom(type, STR.AbstractDefinedComponentType)) { + String typeId = graph.getPossibleURI(type); + if(typeId == null) + throw new SynchronizationException("User component " + type + " does not have an URI."); + if(visitedTypes.add(typeId)) + visitType(typeId, type, handler); + boolean endComponentNeeded = false; + try { + Collection propertyMap = mapProperties(handler, variable); + Collection childMap = mapChildren(handler, children); + endComponentNeeded = true; + handler.beginComponent(name, typeId, + propertyMap, + Collections.emptyList(), + childMap); + } catch(Exception e) { + handler.reportProblem("Failed to synchronize " + name + ": " + e.getMessage(), e); + if (endComponentNeeded) + handler.endComponent(); + return; + } + } else { + String typeId = graph.getPossibleURI(type); + if(typeId == null) + throw new SynchronizationException("User component " + type + " does not have an URI."); + if(visitedTypes.add(typeId)) + visitType(typeId, type, handler); + boolean endComponentNeeded = false; + try { + Collection propertyMap = mapProperties(handler, variable); + Collection connectionMap = mapConnections(handler, variable); + Collection childMap = mapChildren(handler, children); + endComponentNeeded = true; + handler.beginComponent(name, + typeId, + propertyMap, + connectionMap, + childMap); + } catch(Exception e) { + handler.reportProblem("Failed to synchronize " + name + ": " + e.getMessage(), e); + if (endComponentNeeded) + handler.endComponent(); + return; + } + } + + if(changeFlags == null) { + // Full synchronization, synchronize all children + if(children.size() > 0) { + double proportionOfWorkForChildren = proportionOfWork / children.size(); + for(Variable child : children) + synchronizationRec(child, handler, null, proportionOfWorkForChildren); + } + else { + didWork(proportionOfWork); + // Full synchronization is cancelable + if(monitor != null && monitor.isCanceled()) + throw new CancelTransactionException(); + } + } + else { + // Partial synchronization, synchronize only children with positive changeFlag + int relevantChildCount = 0; + for(final Variable child : children) { + int changeStatus = changeFlags.get(child); + if(changeStatus != 0) + ++relevantChildCount; + } + if(relevantChildCount > 0) { + double proportionOfWorkForChildren = proportionOfWork / relevantChildCount; + for(final Variable child : children) { + int changeStatus = changeFlags.get(child); + if(changeStatus == 0) + continue; + synchronizationRec(child, handler, + // Apply full synchronization for subtree if changeStatus > 1 + changeStatus==1 ? changeFlags : null, + proportionOfWorkForChildren + ); + } + } + else { + didWork(proportionOfWork); + } + } + handler.endComponent(); + } + + public void partialSynchronization(Variable variable, SynchronizationEventHandler handler, TObjectIntHashMap changeFlags) throws DatabaseException { + long duration = 0; + if(TRACE) { + System.out.println("partialSynchronization " + variable.getURI(graph)); + duration -= System.nanoTime(); + } + int changeStatus = changeFlags.get(variable); + if(changeStatus == 0) return; + SCLContext context = SCLContext.getCurrent(); + Object oldGraph = context.put("graph", graph); + try { + handler.beginSynchronization(); + synchronizationRec(variable, handler, changeStatus == 1 ? changeFlags : null, 1.0); + handler.endSynchronization(); + } finally { + context.put("graph", oldGraph); + } + if(TRACE) { + duration += System.nanoTime(); + System.out.println("partial sync in " + 1e-9*duration + "s."); + } + } + + public void partialSynchronization(Variable variable, SynchronizationEventHandler handler, long fromRevision) throws DatabaseException { + 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; + } + });*/ + partialSynchronization(variable, handler, modifiedComponents); + } + + void visitType(String typeId, Resource typeResource, SynchronizationEventHandler handler) throws DatabaseException { + Variable typeVariable = graph.syncRequest(new ResourceToPossibleVariable(typeResource), TransientCacheAsyncListener.instance()); + handler.beginType(typeId, mapProperties(handler, typeVariable)); + handler.endType(); + } + + public long getHeadRevisionId() throws DatabaseException { + return graph.getService(ManagementSupport.class).getHeadRevisionId()+1; + } + + +}