]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/WriteSupportImpl.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.procore / src / fi / vtt / simantics / procore / internal / WriteSupportImpl.java
diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/WriteSupportImpl.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/WriteSupportImpl.java
new file mode 100644 (file)
index 0000000..f0da00f
--- /dev/null
@@ -0,0 +1,517 @@
+package fi.vtt.simantics.procore.internal;\r
+\r
+import java.util.TreeMap;\r
+\r
+import org.simantics.db.Metadata;\r
+import org.simantics.db.Operation;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.VirtualGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.MetadataUtils;\r
+import org.simantics.db.common.exception.DebugException;\r
+import org.simantics.db.common.utils.Logger;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.exception.ImmutableException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.impl.ClusterI;\r
+import org.simantics.db.impl.MemWatch;\r
+import org.simantics.db.impl.ResourceImpl;\r
+import org.simantics.db.impl.VirtualGraphImpl;\r
+import org.simantics.db.impl.graph.ReadGraphImpl;\r
+import org.simantics.db.impl.graph.WriteGraphImpl;\r
+import org.simantics.db.impl.graph.WriteSupport;\r
+import org.simantics.db.impl.query.QueryProcessor;\r
+import org.simantics.db.impl.query.QuerySupport;\r
+import org.simantics.db.procore.cluster.ClusterImpl;\r
+import org.simantics.db.procore.protocol.Constants;\r
+import org.simantics.db.request.Write;\r
+import org.simantics.db.request.WriteOnly;\r
+import org.simantics.db.request.WriteResult;\r
+import org.simantics.db.request.WriteTraits;\r
+import org.simantics.db.service.ByteReader;\r
+\r
+public class WriteSupportImpl implements WriteSupport {\r
+\r
+    final private SessionImplSocket session;\r
+    final private QueryProcessor queryProcessor;\r
+    final private State state;\r
+    final private QuerySupport querySupport;\r
+    final private TreeMap<String, byte[]> metadata;\r
+    \r
+    WriteSupportImpl(SessionImplSocket session) {\r
+        this.session = session;\r
+        this.queryProcessor = session.getQueryProvider2();\r
+        this.state = session.state;\r
+        this.querySupport = session.querySupport;\r
+        this.metadata = new TreeMap<String, byte[]>();\r
+        assert(this.session != null);\r
+        assert(this.queryProcessor != null);\r
+        assert(this.state != null);\r
+        assert(this.querySupport != null);\r
+    }\r
+    \r
+    @Override\r
+    public void flushCluster() {\r
+        session.clusterTable.flushCluster(session.graphSession);\r
+        if(session.defaultClusterSet != null) {\r
+            long resourceId = session.defaultClusterSet.getResourceId();\r
+            session.clusterSetsSupport.put(resourceId, Constants.NewClusterId);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void flushCluster(Resource r) {\r
+        session.clusterStream.reallyFlush();\r
+    }\r
+\r
+    @Override\r
+    public boolean writeOnly() {\r
+        return session.writeOnly;\r
+    }\r
+\r
+    @Override\r
+    public void flush(boolean intermediate) {\r
+\r
+        if (!session.state.isWriteTransaction())\r
+            throw new IllegalStateException("Can only flush during transaction.");\r
+\r
+        gc();\r
+        \r
+    }\r
+    \r
+    final public void claim(VirtualGraph provider, Resource subject, Resource predicate, Resource object) throws ServiceException {\r
+        claim(provider, querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));\r
+    }\r
+\r
+    @Override\r
+    final public void claim(VirtualGraph provider, int subject, int predicate, int object)\r
+    throws ServiceException {\r
+\r
+        provider = session.getProvider(provider); \r
+        if (writeOnly()) {\r
+            if (provider != null) {\r
+                ((VirtualGraphImpl)provider).claim(subject, predicate, object);\r
+                queryProcessor.updateStatements(subject, predicate);\r
+                session.clientChanges.claim(subject, predicate, object);\r
+            } else {\r
+                claimImpl2(subject, predicate, object);\r
+            }\r
+        } else {\r
+//            queryProcessor.acquireWrite(writeState.getGraph());\r
+            if (provider != null) {\r
+                ((VirtualGraphImpl)provider).claim(subject, predicate, object);\r
+                queryProcessor.updateStatements(subject, predicate);\r
+                session.clientChanges.claim(subject, predicate, object);\r
+            } else {\r
+                claimImpl(subject, predicate, object);\r
+            }\r
+            queryProcessor.releaseWrite(session.writeState.getGraph());\r
+        }\r
+        \r
+    }\r
+    \r
+    @Override\r
+    public void setValue(VirtualGraph provider, Resource resource, byte[] value) throws ServiceException {\r
+\r
+        provider = session.getProvider(provider);\r
+        if (writeOnly()) {\r
+            if (provider != null) {\r
+                ((VirtualGraphImpl)provider).claimValue(((ResourceImpl) resource).id, value, value.length);\r
+                queryProcessor.updateValue(querySupport.getId(resource));\r
+                session.clientChanges.claimValue(resource);\r
+            } else {\r
+                try {\r
+                    addSetValue(((ResourceImpl) resource).id, value, value.length);\r
+                } catch (DatabaseException e) {\r
+                    Logger.defaultLogError(e);\r
+                }\r
+            }\r
+        } else {\r
+            if (provider != null) {\r
+                ((VirtualGraphImpl)provider).claimValue(((ResourceImpl) resource).id, value, value.length);\r
+                queryProcessor.updateValue(querySupport.getId(resource));\r
+                session.clientChanges.claimValue(resource);\r
+            } else {\r
+                try {\r
+                    addSetValue(((ResourceImpl) resource).id, value, value.length);\r
+                } catch (DatabaseException e) {\r
+                    Logger.defaultLogError(e);\r
+                }\r
+            }\r
+            queryProcessor.releaseWrite(session.writeState.getGraph());\r
+        }\r
+\r
+    }\r
+\r
+    @Override\r
+    public Resource createResource(VirtualGraph provider) throws DatabaseException {\r
+        if (provider != null) {\r
+            int newId = ((VirtualGraphImpl)provider).newResource(false);\r
+            return new ResourceImpl(session.resourceSupport, newId);\r
+        } else {\r
+            return session.getNewResource();\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public Resource createResource(VirtualGraph provider, long clusterId)\r
+    throws DatabaseException {\r
+        assert (provider == null);\r
+        return session.getNewResource(clusterId);\r
+    }\r
+\r
+    @Override\r
+    public Resource createResource(VirtualGraph provider, Resource clusterSet)\r
+    throws DatabaseException {\r
+        assert(provider == null);\r
+        assert(clusterSet != null);\r
+        return session.getNewResource(clusterSet);\r
+    }\r
+\r
+    @Override\r
+    public void createClusterSet(VirtualGraph provider, Resource clusterSet)\r
+    throws DatabaseException {\r
+        assert(provider == null);\r
+        assert(clusterSet != null);\r
+        session.getNewClusterSet(clusterSet);\r
+    }\r
+\r
+    @Override\r
+    public boolean hasClusterSet(VirtualGraph dummy, Resource clusterSet)\r
+    throws ServiceException {\r
+        return session.containsClusterSet(clusterSet);\r
+    }\r
+\r
+    @Override\r
+    public Resource setDefaultClusterSet(Resource clusterSet)\r
+    throws ServiceException {\r
+        return session.setDefaultClusterSet4NewResource(clusterSet);\r
+    }\r
+    @Override\r
+    public void denyValue(VirtualGraph provider, Resource resource) throws ServiceException {\r
+        provider = session.getProvider(provider);\r
+        if (null == provider) {\r
+            int key = ((ResourceImpl)resource).id;\r
+            ClusterI cluster = session.clusterTable.getClusterByResourceKey(key);\r
+            if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)\r
+               if(key != queryProcessor.getRootLibrary())\r
+                       throw new ImmutableException("Trying to modify immutable resource key=" + key);\r
+\r
+            try { \r
+                cluster.removeValue(key, session.clusterTranslator);\r
+            } catch (DatabaseException e) {\r
+                Logger.defaultLogError(e);\r
+                return;\r
+            }\r
+            queryProcessor.updateValue(key);\r
+            session.clientChanges.claimValue(resource);\r
+        } else {\r
+            ((VirtualGraphImpl)provider).denyValue(((ResourceImpl) resource).id);\r
+            queryProcessor.updateValue(querySupport.getId(resource));\r
+            session.clientChanges.claimValue(resource);\r
+        }\r
+        if (!writeOnly())\r
+            queryProcessor.releaseWrite(session.writeState.getGraph());\r
+    }\r
+\r
+\r
+    @Override\r
+    public boolean removeStatement(VirtualGraph provider, Resource subject, Resource predicate,\r
+            Resource object) throws ServiceException {\r
+        boolean ret = true;\r
+        if (writeOnly()) {\r
+            if (provider != null) {\r
+                ((VirtualGraphImpl)provider).deny(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));\r
+                queryProcessor.updateStatements(querySupport.getId(subject), querySupport.getId(predicate));\r
+            } else {\r
+                ret = removeStatement(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));\r
+            }\r
+        } else {\r
+            if (provider != null) {\r
+//                queryProcessor.acquireWrite(writeState.getGraph());\r
+                ((VirtualGraphImpl)provider).deny(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));\r
+                queryProcessor.updateStatements(querySupport.getId(subject), querySupport.getId(predicate));\r
+                queryProcessor.releaseWrite(session.writeState.getGraph());\r
+            } else {\r
+                int sid = querySupport.getId(subject);\r
+                int pid = querySupport.getId(predicate);\r
+                int oid = querySupport.getId(object);\r
+                if (sid < 0 || pid < 0 || oid < 0) {\r
+                    // One of the resources is virtual, cannot remove such\r
+                    // statement from persistent storage.\r
+                    return false;\r
+                }\r
+//                queryProcessor.acquireWrite(writeState.getGraph());\r
+                ret = removeStatement(sid, pid, oid);\r
+                queryProcessor.releaseWrite(session.writeState.getGraph());\r
+            }\r
+        }\r
+        session.clientChanges.deny(subject, predicate, object);\r
+        return ret;\r
+    }\r
+    \r
+    @Override\r
+    public synchronized void performWriteRequest(WriteGraph graph_, Write request) throws DatabaseException {\r
+        WriteGraphImpl graph = (WriteGraphImpl)graph_;\r
+//        graph.state.barrier.inc();\r
+        try {\r
+            request.perform(graph);\r
+        } catch (Throwable t) {\r
+            t.printStackTrace();\r
+        }\r
+//        graph.state.barrier.dec();\r
+//        graph.waitAsync(request);\r
+        \r
+        queryProcessor.performDirtyUpdates(graph);\r
+        \r
+        // Do not fire metadata listeners for virtual requests\r
+        if(graph.getProvider() == null) {\r
+            //session.fireMetadataListeners(graph, session.clientChanges);\r
+            state.commitAndContinue(graph, session.clusterStream, request);\r
+            //session.clientChanges = new ClientChangesImpl(session);\r
+        }\r
+\r
+//        graph.state.barrier.assertReady();\r
+        \r
+    }\r
+    \r
+    @Override\r
+    public synchronized <T> T performWriteRequest(WriteGraph graph_, WriteResult<T> request) throws DatabaseException {\r
+\r
+        WriteGraphImpl graph = (WriteGraphImpl)graph_;\r
+//        graph.state.barrier.inc();\r
+        T result = null;\r
+        Throwable t = null;\r
+        try {\r
+            result = request.perform(graph);\r
+        } catch (Throwable t2) {\r
+            if(DebugException.DEBUG) new DebugException(t2).printStackTrace();\r
+            t = t2;\r
+        }\r
+        \r
+//        graph.state.barrier.dec();\r
+//        graph.waitAsync(request);\r
+        \r
+        queryProcessor.performDirtyUpdates(graph);\r
+\r
+        // Do not fire metadata listeners for virtual requests\r
+        if(graph.getProvider() == null) {\r
+            //session.fireMetadataListeners((WriteGraphImpl)graph, session.clientChanges);\r
+            state.commitAndContinue(graph, session.clusterStream, request);\r
+            //session.clientChanges = new ClientChangesImpl(session);\r
+        }\r
+        \r
+        if(t != null) {\r
+            if(t instanceof DatabaseException) throw (DatabaseException)t;\r
+            else throw new DatabaseException(t);\r
+        }\r
+        \r
+        return result;\r
+        \r
+    }\r
+\r
+    @Override\r
+    public synchronized void performWriteRequest(WriteGraph graph, WriteOnly request) throws DatabaseException {\r
+\r
+        session.acquireWriteOnly();\r
+        \r
+        request.perform(graph);\r
+        \r
+        ReadGraphImpl impl = (ReadGraphImpl)graph;\r
+        \r
+        queryProcessor.performDirtyUpdates(impl);\r
+\r
+        // Do not fire metadata listeners for virtual requests\r
+        if(graph.getProvider() == null) {\r
+            //session.fireMetadataListeners(impl, session.clientChanges);\r
+            state.commitAndContinue(session.writeState.getGraph(), session.clusterStream, request);\r
+            //session.clientChanges = new ClientChangesImpl(session);\r
+        }        \r
+        session.releaseWriteOnly(impl);\r
+        \r
+    }\r
+\r
+    \r
+    @Override\r
+    public void gc() {\r
+        if (MemWatch.isLowOnMemory()) {\r
+            session.clusterTable.gc();\r
+            queryProcessor.gc(0, Integer.MAX_VALUE);\r
+            System.gc();\r
+        }\r
+    }\r
+    \r
+    @Override\r
+    public void claimValue(VirtualGraph provider, Resource resource, byte[] value) throws DatabaseException {\r
+        claimValue(provider, ((ResourceImpl)resource).id, value, value.length);\r
+    }\r
+\r
+    @Override\r
+    public void claimValue(VirtualGraph provider, int resource, byte[] value, int length) throws DatabaseException {\r
+\r
+        provider = session.getProvider(provider);\r
+        if (writeOnly()) {\r
+            if (provider != null) {\r
+                ((VirtualGraphImpl)provider).claimValue(resource, value, length);\r
+                queryProcessor.updateValue(resource);\r
+                session.clientChanges.claimValue(resource);\r
+            } else {\r
+                addSetValue(resource, value, length);\r
+            }\r
+        } else {\r
+            if (provider != null) {\r
+                ((VirtualGraphImpl)provider).claimValue(resource, value, length);\r
+                queryProcessor.updateValue(resource);\r
+                session.clientChanges.claimValue(resource);\r
+                queryProcessor.releaseWrite(session.writeState.getGraph());\r
+            } else {\r
+                try {\r
+                    addSetValue(resource, value, length);\r
+                } catch (DatabaseException e) {\r
+                    throw e;\r
+                } catch (Throwable t) {\r
+                    throw new DatabaseException(t);\r
+                } finally {\r
+                    queryProcessor.releaseWrite(session.writeState.getGraph());\r
+                }\r
+            }\r
+        }\r
+    }\r
+    \r
+    @Override\r
+    public void claimValue(VirtualGraph provider, Resource resource, ByteReader reader, int amount) throws DatabaseException {\r
+        claimValue(provider, resource, reader.readBytes(null, amount));\r
+    }\r
+\r
+    @Override\r
+    public <T> void addMetadata(Metadata data) throws ServiceException {\r
+       MetadataUtils.addMetadata(session, metadata, data);\r
+    }\r
+\r
+    @SuppressWarnings("unchecked")\r
+    @Override\r
+    public <T extends Metadata> T getMetadata(Class<T> clazz) throws ServiceException {\r
+       return MetadataUtils.getMetadata(session, metadata, clazz);\r
+    }\r
+\r
+    @Override\r
+    public TreeMap<String, byte[]> getMetadata() {\r
+        return metadata;\r
+    }\r
+\r
+    @Override\r
+    public void commitDone(WriteTraits writeTraits, long csid) {\r
+        metadata.clear();\r
+        if (this.writeTraits == writeTraits) {\r
+            session.graphSession.undoContext.clear();\r
+            this.writeTraits = null;\r
+        }\r
+//        if (null != operation)\r
+//            operation = null;\r
+    }\r
+    @Override\r
+    public int clearMetadata() {\r
+        int ret = metadata.size();\r
+        metadata.clear();\r
+        return ret;\r
+    }\r
+    @Override\r
+    public void clearUndoList(WriteTraits writeTraits) {\r
+        this.writeTraits = writeTraits;\r
+    }\r
+    @Override\r
+    public void startUndo() {\r
+       session.state.setCombine(false);\r
+    }\r
+    private WriteTraits writeTraits = null;\r
+    private void addSetValue(int subject, byte[] value, int length)\r
+    throws DatabaseException {\r
+\r
+        ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);\r
+        if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)\r
+               if(subject != queryProcessor.getRootLibrary())\r
+                       throw new ImmutableException("Trying to modify immutable resource key=" + subject);\r
+        \r
+        ClusterI cluster2 = cluster.setValue(subject, value, length, session.clusterTranslator);\r
+        if (cluster2 != cluster)\r
+            session.clusterTable.replaceCluster(cluster2);\r
+        \r
+        session.clientChanges.claimValue(subject);\r
+        \r
+        if (cluster2.isWriteOnly())\r
+            return;\r
+\r
+        queryProcessor.updateValue(subject);\r
+\r
+    }\r
+\r
+    final private void claimImpl(int subject, int predicate, int object)\r
+    throws ServiceException {\r
+\r
+        assert (subject != 0);\r
+        assert (predicate != 0);\r
+        assert (object != 0);\r
+\r
+        ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);\r
+        assert (null != cluster);\r
+        if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)\r
+               if(subject != queryProcessor.getRootLibrary())\r
+                       throw new ImmutableException("Trying to modify immutable resource key=" + subject);\r
+        try {\r
+            ClusterI c = cluster.addRelation(subject, predicate, object, session.clusterTranslator);\r
+            if (null != c && c != cluster)\r
+                session.clusterTable.replaceCluster(c);\r
+        } catch (DatabaseException e) {\r
+            Logger.defaultLogError(e);\r
+            throw new RuntimeException(e);\r
+        }\r
+        queryProcessor.updateStatements(subject, predicate);\r
+        session.clientChanges.claim(subject, predicate, object);\r
+\r
+    }\r
+\r
+    final private void claimImpl2(int subject, int predicate, int object) {\r
+        \r
+        assert (subject != 0);\r
+        assert (predicate != 0);\r
+        assert (object != 0);\r
+\r
+        ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);\r
+        try {\r
+            ClusterI c = cluster.addRelation(subject, predicate, object, session.clusterTranslator);\r
+            if (null != c && c != cluster)\r
+                session.clusterTable.replaceCluster(c);\r
+        } catch (DatabaseException e) {\r
+            Logger.defaultLogError(e);\r
+        }\r
+        if (cluster.isWriteOnly())\r
+            return;\r
+        queryProcessor.updateStatements(subject, predicate);\r
+\r
+    }\r
+    \r
+    private boolean removeStatement(int subject, int predicate, int object) throws ImmutableException {\r
+\r
+        assert (subject != 0);\r
+        assert (predicate != 0);\r
+        assert (object != 0);\r
+\r
+        ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);\r
+        assert (null != cluster);\r
+\r
+        if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)\r
+               if(subject != queryProcessor.getRootLibrary())\r
+                       throw new ImmutableException("Trying to modify immutable resource key=" + subject);\r
+\r
+        try {\r
+            cluster.denyRelation(subject, predicate, object, session.clusterTranslator);\r
+        } catch (DatabaseException e) {\r
+            Logger.defaultLogError(e);\r
+            return false;\r
+        }\r
+        queryProcessor.updateStatements(subject, predicate);\r
+        return true;\r
+\r
+    }\r
+    \r
+}\r