]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.common/src/org/simantics/db/common/utils/CommonDBUtils.java
Utilities for listing of statements in DB
[simantics/platform.git] / bundles / org.simantics.db.common / src / org / simantics / db / common / utils / CommonDBUtils.java
index ed09abb54cf7266afd95d6c1dfd158164bf80b24..2e16b284903997a204f1c229f3a1adc83df10a96 100644 (file)
@@ -13,17 +13,31 @@ import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.Statement;
 import org.simantics.db.WriteGraph;
+import org.simantics.db.common.procedure.adapter.DirectStatementProcedure;
 import org.simantics.db.common.request.IsParent;
 import org.simantics.db.common.request.ObjectsWithType;
 import org.simantics.db.common.request.PossibleObjectWithType;
 import org.simantics.db.common.request.PossibleOwner;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.InvalidResourceReferenceException;
+import org.simantics.db.service.ClusterUID;
 import org.simantics.db.service.ClusteringSupport;
+import org.simantics.db.service.DirectQuerySupport;
+import org.simantics.db.service.SerialisationSupport;
+import org.simantics.db.service.XSupport;
 import org.simantics.layer0.Layer0;
 import org.simantics.utils.datastructures.collections.CollectionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.procedure.TIntProcedure;
+import gnu.trove.set.hash.TIntHashSet;
 
 public class CommonDBUtils {
 
+       private static final Logger LOGGER = LoggerFactory.getLogger(CommonDBUtils.class);
+
        public static boolean isParent(ReadGraph graph, Resource possibleParent, Resource possibleChild) throws DatabaseException {
                return graph.sync(new IsParent(possibleParent, possibleChild));
        }
@@ -193,4 +207,125 @@ public class CommonDBUtils {
        return graph.syncRequest(new PossibleObjectWithType(subject, relation, type));
     }
 
+       public static List<ClusterUID> listClusters(ReadGraph graph) throws DatabaseException {
+       XSupport xs = graph.getService(XSupport.class);
+       ClusterUID uids[] = xs.listClusters();
+       ArrayList<ClusterUID> result = new ArrayList<>(uids.length);
+       for(ClusterUID uid : uids) result.add(uid);
+       return result;
+    }
+       
+       public static List<Resource> resourcesByCluster(ReadGraph graph, ClusterUID uid) throws DatabaseException {
+       SerialisationSupport ss = graph.getService(SerialisationSupport.class);
+       ArrayList<Resource> result = new ArrayList<Resource>();
+       // Index 0 is illegal
+               for(int i=1;i<1<<12;i++) {
+                       try {
+                               result.add(ss.getResource(uid.toRID(i)));
+                       } catch (InvalidResourceReferenceException e) {
+                       }
+               }
+               return result;
+       }
+       
+       public static List<Statement> directStatements(ReadGraph graph, Resource resource, boolean ignoreVirtual) throws DatabaseException {
+               
+               DirectQuerySupport dqs = graph.getService(DirectQuerySupport.class);
+               DirectStatementProcedure proc = new DirectStatementProcedure();
+
+               if (ignoreVirtual) {
+                       dqs.forEachDirectPersistentStatement(graph, resource, proc);
+               } else {
+                       dqs.forEachDirectStatement(graph, resource, proc);
+               }
+               
+               return proc.getOrThrow();
+
+       }
+       
+    public static List<Resource> garbageResources(ReadGraph graph) throws DatabaseException {
+       
+       SerialisationSupport ss = graph.getService(SerialisationSupport.class);
+       
+       TIntArrayList refs = new TIntArrayList();
+       TIntArrayList res = new TIntArrayList();
+       
+       // Find all statements in the database
+       for(ClusterUID uid : listClusters(graph)) {
+               for(Resource r : resourcesByCluster(graph, uid)) {
+                       int sid = ss.getTransientId(r);
+                       for(Statement stm : directStatements(graph, r, true)) {
+                               int oid = ss.getTransientId(stm.getObject());
+                               refs.add(sid);
+                               refs.add(oid);
+                       }
+                       res.add(sid);
+               }
+       }
+
+       TIntHashSet reached = new TIntHashSet();
+       
+       // Initialize root
+       int root = ss.getTransientId(graph.getRootLibrary());
+       reached.add(root);
+       
+       int[] refArray = refs.toArray();
+       
+       boolean changes = true;
+       
+       while(changes) {
+               changes = false;
+               for(int i=0;i<refArray.length;i+=2) {
+                       int s = refArray[i];
+                       int o = refArray[i+1];
+                       if(reached.contains(s)) {
+                               if(reached.add(o)) {
+                                       changes = true;
+                               }
+                       }
+               }
+               
+               System.err.println("Reachability iteration, changes = " + changes);
+       }
+       
+       ArrayList<Resource> result = new ArrayList<>();
+               for(int i=0;i<refArray.length;i+=2) {
+                       int s = refArray[i];
+                       if(reached.contains(s)) {
+                               if(reached.add(refArray[i+1]))
+                                       changes = true;
+                       }
+               }
+
+               res.forEach(new TIntProcedure() {
+                       
+                       @Override
+                       public boolean execute(int r) {
+                               if(!reached.contains(r)) {
+                                       try {
+                                               result.add(ss.getResource(r));
+                                       } catch (DatabaseException e) {
+                                               LOGGER.error("Unexpected error while resolving garbage resources.", e);
+                                       }
+                               }
+                               return true;
+                       }
+                       
+               });
+               
+       return result;
+       
+    }
+
+    public static ClusterUID clusterUIDOfResource(ReadGraph graph, Resource resource) throws DatabaseException {
+       SerialisationSupport ss = graph.getService(SerialisationSupport.class);
+       return ss.getUID(resource).asCID();
+    }
+    
+    public static boolean isClusterLoaded(ReadGraph graph, ClusterUID clusterUID) throws DatabaseException {
+       XSupport xs = graph.getService(XSupport.class);
+       return xs.isClusterLoaded(clusterUID);
+    }
+    
+    
 }