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