--- /dev/null
+package org.simantics.db.common.procedure.adapter;
+
+import org.simantics.db.AsyncReadGraph;
+import org.simantics.db.DirectStatements;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.procedure.AsyncProcedure;
+
+public class DirectStatementProcedure implements AsyncProcedure<DirectStatements> {
+
+ DirectStatements result = null;
+ DatabaseException exception = null;
+
+ @Override
+ public void execute(AsyncReadGraph graph, final DirectStatements ds) {
+ result = ds;
+ }
+
+ @Override
+ public void exception(AsyncReadGraph graph, Throwable throwable) {
+ if(throwable instanceof DatabaseException) {
+ exception = (DatabaseException)throwable;
+ } else {
+ exception = new DatabaseException(throwable);
+ }
+ }
+
+ public DirectStatements getOrThrow() throws DatabaseException {
+ if(exception != null) throw exception;
+ return result;
+ }
+
+}
\ No newline at end of file
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));
}
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);
+ }
+
+
}
import java.util.Collection;
import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
import org.simantics.db.DirectStatements;
import org.simantics.db.Resource;
final public class DirectStatementsImpl implements DirectStatements {
final ResourceSupport support;
-
- final int subject;
-
- final TIntArrayList statements = new TIntArrayList();
-
+ final int subject;
+ final TIntArrayList statements = new TIntArrayList();
+
DirectStatementsImpl(ResourceSupport support, int subject) {
this.support = support;
this.subject = subject;
}
-
+
void addStatement(int p, int o) {
statements.add(p);
statements.add(o);
}
-
+
@Override
public Resource getSubject() {
return new ResourceImpl(support, subject);
@Override
public boolean contains(Object arg0) {
- Statement stm = (Statement) arg0;
- ResourceImpl p = (ResourceImpl) stm.getPredicate();
- ResourceImpl o = (ResourceImpl) stm.getObject();
- for (int i = 0; i < statements.size(); i += 2) {
+ Statement stm = (Statement)arg0;
+ ResourceImpl p = (ResourceImpl)stm.getPredicate();
+ ResourceImpl o = (ResourceImpl)stm.getObject();
+ for(int i=0;i<statements.size();i+=2) {
int pi = statements.getQuick(i);
- int oi = statements.getQuick(i + 1);
- if (p.id == pi && o.id == oi)
- return true;
+ int oi = statements.getQuick(i+1);
+ if(p.id == pi && o.id == oi) return true;
}
return false;
}
return new Iterator<Statement>() {
int index = 0;
-
- int max = statements.size();
-
+ int max = statements.size();
+
@Override
public boolean hasNext() {
- return index < max;
+ return index < max;
}
@Override
public Statement next() {
- return new DirectStatementImpl(support, subject, statements.getQuick(index++),
- statements.getQuick(index++));
+ return new DirectStatementImpl(support, subject, statements.getQuick(index++), statements.getQuick(index++));
}
@Override
public void remove() {
throw new Error("Not supported");
}
-
+
};
}
throw new Error("Not supported");
}
+ @Override
+ public void add(int index, Statement element) {
+ throw new Error("Not supported");
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends Statement> c) {
+ throw new Error("Not supported");
+ }
+
+ @Override
+ public Statement get(int index_) {
+ int index = 2*index_;
+ return new DirectStatementImpl(support, subject, statements.getQuick(index), statements.getQuick(index+1));
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ throw new Error("Not supported");
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ throw new Error("Not supported");
+ }
+
+ @Override
+ public ListIterator<Statement> listIterator() {
+ throw new Error("Not supported");
+ }
+
+ @Override
+ public ListIterator<Statement> listIterator(int index) {
+ throw new Error("Not supported");
+ }
+
+ @Override
+ public Statement remove(int index) {
+ throw new Error("Not supported");
+ }
+
+ @Override
+ public Statement set(int index, Statement element) {
+ throw new Error("Not supported");
+ }
+
+ @Override
+ public List<Statement> subList(int fromIndex, int toIndex) {
+ throw new Error("Not supported");
+ }
+
}
import org.simantics.db.ResourceSerializer;
import org.simantics.db.common.utils.Logger;
import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.InvalidResourceReferenceException;
import org.simantics.db.impl.ClusterI;
+import org.simantics.db.impl.ClusterI.PredicateProcedure;
import org.simantics.db.impl.ResourceImpl;
import org.simantics.db.procore.cluster.ClusterImpl;
import org.simantics.db.procore.cluster.ClusterTraits;
return cluster.clusterUID.toRID(ClusterTraits.getResourceIndexFromResourceKey(resourceKey));
}
+ static class ExistsPredicateProcedure implements PredicateProcedure<Integer> {
+
+ boolean exists = false;
+
+ @Override
+ public boolean execute(Integer c, final int predicateKey, int objectIndex) {
+ exists = true;
+ return false;
+ }
+
+ }
+
@Override
public Resource getResource(ResourceUID uid) throws DatabaseException {
ClusterI cluster = session.clusterTable.getClusterByClusterUIDOrMakeProxy(uid.asCID());
int key = ClusterTraits.createResourceKey(cluster.getClusterKey(), (int) uid.getIndex());
- return new ResourceImpl(session.resourceSupport, key);
+ if (cluster.hasResource(key, session.clusterTranslator)) {
+ ExistsPredicateProcedure pp = new ExistsPredicateProcedure();
+ cluster.forPredicates(key, pp, 0, session.clusterTranslator);
+ if(pp.exists) {
+ return new ResourceImpl(session.resourceSupport, key);
+ } else if (cluster.hasValue(key, session.clusterTranslator)) {
+ return new ResourceImpl(session.resourceSupport, key);
+ }
+ }
+ throw new InvalidResourceReferenceException("Resource with uid = " + uid + " does not exist.");
}
}
public boolean rolledback() {
return session.graphSession.rolledback();
}
+
+ @Override
+ public boolean isClusterLoaded(ClusterUID clusterUID) throws DatabaseException {
+ ClusterImpl clusterImpl = session.clusterTable.getClusterByClusterUIDOrMakeProxy(clusterUID);
+ return clusterImpl.isLoaded();
+ }
+
}
import org.simantics.db.procedure.AsyncMultiProcedure;
import org.simantics.db.service.ClusterUID;
import org.simantics.db.service.ResourceUID;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import fi.vtt.simantics.procore.DebugPolicy;
import fi.vtt.simantics.procore.internal.ClusterChange;
import gnu.trove.set.hash.TIntHashSet;
final public class ClusterSmall extends ClusterImpl {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ClusterSmall.class);
private static final int TABLE_HEADER_SIZE = TableHeader.HEADER_SIZE + TableHeader.EXTRA_SIZE;
private static final int RESOURCE_TABLE_OFFSET = 0;
if (DEBUG)
System.out.println("ClusterSmall.forPredicates: rk=" + resourceKey );
if (deleted) return false;
+ if(proxy) {
+ ClusterImpl cluster = clusterTable.load2(clusterId, clusterKey);
+ return cluster.forPredicates(resourceKey, procedure, context, support);
+ }
+
final int resourceIndex = getLocalReference(resourceKey);
final int predicateIndex = resourceTable.getPredicateIndex(resourceIndex);
if (0 == predicateIndex)
public boolean hasValue(int resourceKey, ClusterSupport support)
throws DatabaseException {
if (deleted) return false;
+ if(proxy) {
+ ClusterImpl cluster = clusterTable.load2(clusterId, clusterKey);
+ return cluster.hasValue(resourceKey, support);
+ }
int resourceIndex = getLocalReference(resourceKey);
return resourceTable.hasValue(resourceIndex);
}
}
@Override
public boolean hasResource(int resourceKey, ClusterSupport support) {
+ if(proxy) {
+ try {
+ ClusterImpl cluster = clusterTable.load2(clusterId, clusterKey);
+ return cluster.hasResource(resourceKey, support);
+ } catch (DatabaseException e) {
+ LOGGER.error("Failed to load cluster with clusterId " + clusterId);
+ return false;
+ }
+ }
if (deleted) return false;
int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(resourceKey);
if (this.clusterKey != clusterKey) // foreign resource
@Override
public void load() {
if (deleted) return;
- throw new Error("Not supported.");
+ try {
+ clusterTable.load2(clusterId, clusterKey);
+ } catch (DatabaseException e) {
+ LOGGER.error("Failed to load cluster with clusterId " + clusterId, e);
+ }
}
@Override
public void load(Consumer<DatabaseException> r) {
if (deleted) return;
- throw new Error("Not supported.");
+ try {
+ clusterTable.load2(clusterId, clusterKey);
+ } catch (DatabaseException e) {
+ r.accept(e);
+ }
}
public boolean contains(int resourceKey) {
clusterTable.load2(clusterId, clusterKey);
callback.run();
} catch (DatabaseException e) {
- e.printStackTrace();
+ LOGGER.error("Failed to load cluster with clusterId " + clusterId, e);
}
}
*******************************************************************************/
package org.simantics.db;
-import java.util.Collection;
+import java.util.List;
/**
* @author Antti Villberg
*/
-public interface DirectStatements extends Collection<Statement> {
+public interface DirectStatements extends List<Statement> {
Resource getSubject();
public boolean rolledback();
+ public boolean isClusterLoaded(ClusterUID clusterUID) throws DatabaseException;
+
}
@JavaName getPredicates
predicatesOf :: Resource -> <ReadGraph> [Resource]
+
+ isImmutable :: Resource -> <ReadGraph> Boolean
importJava "org.simantics.db.layer0.util.ExtendedUris" where
"Converts an absolute URI to a resource"
import "UI/Progress"
import "Simantics/DB"
+importJava "org.simantics.db.common.utils.CommonDBUtils" where
+
+ listClusters :: <ReadGraph> [ClusterUID]
+ resourcesByCluster :: ClusterUID -> <ReadGraph> [Resource]
+ directStatements :: Resource -> Boolean -> <ReadGraph> [Statement]
+ garbageResources :: <ReadGraph> [Resource]
+ clusterUIDOfResource :: Resource -> <ReadGraph> ClusterUID
+ isClusterLoaded :: ClusterUID -> <ReadGraph> Boolean
+
importJava "org.simantics.scl.db.SCLFunctions" where
collectClusters :: <Proc> ()
countQueries :: <ReadGraph> Integer
//emptyTrashBin :: <Proc> ()
emptyTrashBin = emptyTrashBinWithMonitor $ createNullProgressMonitor ()
+
+importJava "org.simantics.db.service.ClusterUID" where
+ data ClusterUID