X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.db.impl%2Fsrc%2Forg%2Fsimantics%2Fdb%2Fimpl%2Fgraph%2FReadGraphImpl.java;h=2309af76440b10bc2a3e9d336cf2fc4bdfc14819;hp=b853ed5191e3654f5cfbddea240b33c48b77bff1;hb=e10760b08746837538ad4c2b4c37736aa34c7a47;hpb=56a799c9b7d395cefb59e101cd0f7ce8d68f88e6 diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java index b853ed519..2309af764 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * Copyright (c) 2007, 2018 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -18,14 +18,15 @@ import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; -import java.nio.BufferUnderflowException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; import java.util.ListIterator; +import java.util.Map; import java.util.Set; import java.util.function.Consumer; @@ -44,10 +45,12 @@ import org.simantics.databoard.type.Datatype; import org.simantics.databoard.util.binary.BinaryFile; import org.simantics.databoard.util.binary.RandomAccessBinary; import org.simantics.db.AsyncReadGraph; +import org.simantics.db.ComputationalValue; import org.simantics.db.DevelopmentKeys; import org.simantics.db.ExternalValueSupport; import org.simantics.db.ReadGraph; import org.simantics.db.RelationContext; +import org.simantics.db.RelationInfo; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.Statement; @@ -88,7 +91,9 @@ import org.simantics.db.common.primitiverequest.Value; import org.simantics.db.common.primitiverequest.ValueImplied; import org.simantics.db.common.primitiverequest.VariantValueImplied; import org.simantics.db.common.procedure.adapter.AsyncMultiProcedureAdapter; +import org.simantics.db.common.procedure.adapter.AsyncProcedureAdapter; import org.simantics.db.common.procedure.adapter.ProcedureAdapter; +import org.simantics.db.common.procedure.adapter.SyncMultiProcedureAdapter; import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; import org.simantics.db.common.procedure.adapter.TransientCacheListener; import org.simantics.db.common.procedure.single.SyncReadProcedure; @@ -104,6 +109,8 @@ import org.simantics.db.common.procedure.wrapper.NoneToAsyncMultiListener; import org.simantics.db.common.procedure.wrapper.NoneToAsyncMultiProcedure; import org.simantics.db.common.procedure.wrapper.NoneToAsyncProcedure; import org.simantics.db.common.procedure.wrapper.NoneToAsyncSetProcedure; +import org.simantics.db.common.procedure.wrapper.NoneToSyncMultiListener; +import org.simantics.db.common.procedure.wrapper.NoneToSyncMultiProcedure; import org.simantics.db.common.procedure.wrapper.SyncToAsyncListener; import org.simantics.db.common.procedure.wrapper.SyncToAsyncMultiListener; import org.simantics.db.common.procedure.wrapper.SyncToAsyncMultiProcedure; @@ -133,11 +140,12 @@ import org.simantics.db.impl.RelationContextImpl; import org.simantics.db.impl.ResourceImpl; import org.simantics.db.impl.internal.RandomAccessValueSupport; import org.simantics.db.impl.internal.ResourceData; -import org.simantics.db.impl.procedure.CallWrappedSingleQueryProcedure4; -import org.simantics.db.impl.procedure.ResultCallWrappedQueryProcedure4; -import org.simantics.db.impl.procedure.ResultCallWrappedSingleQueryProcedure4; +import org.simantics.db.impl.procedure.ResultCallWrappedSyncQueryProcedure; import org.simantics.db.impl.query.CacheEntry; +import org.simantics.db.impl.query.QueryCache; +import org.simantics.db.impl.query.QueryCacheBase; import org.simantics.db.impl.query.QueryProcessor; +import org.simantics.db.impl.query.QueryProcessor.SessionTask; import org.simantics.db.impl.query.QuerySupport; import org.simantics.db.impl.query.TripleIntProcedure; import org.simantics.db.impl.support.ResourceSupport; @@ -166,7 +174,6 @@ import org.simantics.db.request.ExternalRead; import org.simantics.db.request.MultiRead; import org.simantics.db.request.Read; import org.simantics.db.request.ReadInterface; -import org.simantics.db.request.RequestFlags; import org.simantics.db.request.Write; import org.simantics.db.request.WriteInterface; import org.simantics.db.request.WriteOnly; @@ -182,16 +189,22 @@ import org.simantics.utils.DataContainer; import org.simantics.utils.Development; import org.simantics.utils.datastructures.Pair; import org.simantics.utils.datastructures.collections.CollectionUtils; +import org.slf4j.LoggerFactory; import gnu.trove.map.hash.TObjectIntHashMap; -public class ReadGraphImpl implements ReadGraph { +public class ReadGraphImpl implements AsyncReadGraph { + + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(ReadGraphImpl.class); final static boolean EMPTY_RESOURCE_CHECK = false; final public CacheEntry parent; + public final ReadGraphImpl parentGraph; final public QueryProcessor processor; + public final AsyncBarrierImpl asyncBarrier; + final static Binding DATA_TYPE_BINDING_INTERNAL = Bindings.getBindingUnchecked(Datatype.class); final static Serializer DATA_TYPE_SERIALIZER = Bindings.getSerializerUnchecked(DATA_TYPE_BINDING_INTERNAL); @@ -278,12 +291,14 @@ public class ReadGraphImpl implements ReadGraph { try { - return syncRequest(new org.simantics.db.common.primitiverequest.Resource( - id)); + Integer rid = QueryCache.resultURIToResource(this, id, parent, null); + // FIXME: stupid to throw this here and catch and wrap it right away + if(rid == 0) throw new ResourceNotFoundException(id); + return processor.querySupport.getResource(rid); } catch (ResourceNotFoundException e) { - throw new ResourceNotFoundException(e); + throw new ResourceNotFoundException(id, e); } catch (ValidationException e) { @@ -309,8 +324,7 @@ public class ReadGraphImpl implements ReadGraph { try { - return syncRequest(new org.simantics.db.common.primitiverequest.Resource( - id)); + return getResource(id); } catch (ResourceNotFoundException e) { @@ -331,6 +345,32 @@ public class ReadGraphImpl implements ReadGraph { } } + + @Override + public Map getChildren(Resource resource) throws ValidationException, ServiceException { + + assert (resource != null); + + try { + + int rId = processor.querySupport.getId(resource); + return QueryCache.resultChildMap(this, rId, parent, null); + + } catch (ValidationException e) { + + throw new ValidationException(e); + + } catch (ServiceException e) { + + throw new ServiceException(e); + + } catch (DatabaseException e) { + + throw new ServiceException(INTERNAL_ERROR_STRING, e); + + } + + } final public Resource getRootLibrary() { return processor.getRootLibraryResource(); @@ -347,7 +387,7 @@ public class ReadGraphImpl implements ReadGraph { } catch (ResourceNotFoundException e) { - throw new ResourceNotFoundException(e); + throw new ResourceNotFoundException(id, e); } catch (ServiceException e) { @@ -900,83 +940,57 @@ public class ReadGraphImpl implements ReadGraph { if( relation == null) throw new IllegalArgumentException("relation can not be null"); try { - int single = processor.getSingleObject(this, subject, relation); - if(single == 0) throw new NoSingleResultException("subject=" + subject + " relation="+relation); + if (single == 0) { + if (EMPTY_RESOURCE_CHECK) { + if (!hasStatement(subject)) { + throw new EmptyResourceException("Resource " + debugString(subject)); + } + } + throw new NoSingleResultException("No single object for subject " + debugString(subject) + + " and relation " + debugString(relation), single); + } return processor.querySupport.getResource(single); - } catch (NoSingleResultException e) { - - if(EMPTY_RESOURCE_CHECK) { - if(!hasStatement(subject)) throw new EmptyResourceException("Resource " + debugString(subject)); - } - - throw new NoSingleResultException("No single object for subject " - + debugString(subject) + " and relation " - + debugString(relation), e); - + throw e; } catch (DatabaseException e) { - throw new ServiceException(e); - } - } @Override - final public Statement getSingleStatement(final Resource subject, - final Resource relation) throws NoSingleResultException, - ManyObjectsForFunctionalRelationException, ServiceException { - + final public Statement getSingleStatement(final Resource subject, final Resource relation) throws NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException { assert (subject != null); assert (relation != null); - try { - Collection statements = getStatements(subject, relation); - if(statements.size() == 1) return statements.iterator().next(); - else throw new NoSingleResultException(""); - - } catch (NoSingleResultException e) { - - if(EMPTY_RESOURCE_CHECK) { - if(!hasStatement(subject)) throw new EmptyResourceException("Resource " + debugString(subject)); - } - - throw new NoSingleResultException("No single statement for subject " - + debugString(subject) + " and relation " - + debugString(relation), e); - - } catch (DatabaseException e) { - - throw new ServiceException(e); - - } - + if (statements.size() == 1) { + return statements.iterator().next(); + } else { + if (EMPTY_RESOURCE_CHECK) + if (!hasStatement(subject)) + throw new EmptyResourceException("Resource " + debugString(subject)); + throw new NoSingleResultException("No single statement for subject " + debugString(subject) + + " and relation " + debugString(relation), statements.size()); + } + } catch (ServiceException e) { + throw new ServiceException(e); + } } @Override - final public Resource getSingleType(final Resource subject) throws NoSingleResultException, - ServiceException { - + final public Resource getSingleType(final Resource subject) throws NoSingleResultException, ServiceException { assert (subject != null); - try { - ArrayList principalTypes = (ArrayList)getPrincipalTypes(subject); - if(principalTypes.size() == 1) return principalTypes.get(0); - else throw new NoSingleResultException(""); - - } catch (NoSingleResultException e) { - - throw new NoSingleResultException(e); - + if (principalTypes.size() == 1) { + return principalTypes.get(0); + } else { + throw new NoSingleResultException("No single type for subject " + debugString(subject), principalTypes.size()); + } } catch (ServiceException e) { - throw new ServiceException(e); - } - } @Override @@ -988,23 +1002,10 @@ public class ReadGraphImpl implements ReadGraph { assert (baseType != null); try { - return syncRequest(new SingleType(subject, baseType)); - - } catch (NoSingleResultException e) { - - throw new NoSingleResultException(new NoSingleResultException("subject=" + subject + ", baseType=" + baseType, e)); - - } catch (ServiceException e) { - - throw new ServiceException(e); - } catch (DatabaseException e) { - - throw new ServiceException(INTERNAL_ERROR_STRING, e); - + throw new NoSingleResultException("subject=" + subject + ", baseType=" + baseType, 0, e); } - } @Override @@ -1106,9 +1107,10 @@ public class ReadGraphImpl implements ReadGraph { assert (subject != null); + byte[] bytes = null; try { - byte[] bytes = processor.getValue(this, subject); + bytes = processor.getValue(this, subject); if (bytes == null) throw new DoesNotContainValueException("No value for resource " + subject); Serializer serializer = getSerializer(binding); @@ -1118,20 +1120,9 @@ public class ReadGraphImpl implements ReadGraph { throw new DoesNotContainValueException(e); - } catch (IOException e) { - - throw new ServiceException(e); - - } catch (DatabaseException e) { - - throw new ServiceException(e); - - } catch (BufferUnderflowException e) { - // This is sometimes thrown when deserialize fails because wrong format. - // For callers of this method this is just an service exception. - throw new ServiceException(e); - } - + } catch (Throwable t) { + throw new ServiceException("Could not getValue for subject " + debugString(subject) + " and binding " + String.valueOf(binding) + " with bytes " + safeArrayToString(bytes), t); + } } @Override @@ -1142,16 +1133,11 @@ public class ReadGraphImpl implements ReadGraph { assert (relation != null); try { - Resource object = getSingleObject(subject, relation); return getValue(object); - } catch (NoSingleResultException e) { - - throw new NoSingleResultException(e); - + throw new NoSingleResultException("No single value found for subject " + debugString(subject) + " and relation " + debugString(relation), e.getResultCount(), e); } catch (DoesNotContainValueException e) { - try { Layer0 L0 = processor.getL0(this); Resource object = getPossibleObject(subject, relation); @@ -1159,23 +1145,19 @@ public class ReadGraphImpl implements ReadGraph { if(isInstanceOf(object, L0.Literal)) { throw new DoesNotContainValueException(e); } else { - throw new InvalidLiteralException("The object " + object + " is not an instance of L0.Literal (use getRelatedValue2 instead)"); + throw new InvalidLiteralException("The object " + object + " is not an instance of L0.Literal (use getRelatedValue2 instead)", e); } } else { - throw new DoesNotContainValueException("The object " + object + " is not an instance of L0.Value"); + throw new DoesNotContainValueException("The object " + object + " is not an instance of L0.Value", e); } } catch (DoesNotContainValueException e2) { throw e2; } catch (DatabaseException e2) { throw new InternalException("The client failed to analyse the cause of the following exception", e); } - } catch (ServiceException e) { - throw new ServiceException(e); - - } - + } } @Override @@ -1186,16 +1168,11 @@ public class ReadGraphImpl implements ReadGraph { assert (relation != null); try { - Resource object = getSingleObject(subject, relation); return getVariantValue(object); - } catch (NoSingleResultException e) { - - throw new NoSingleResultException(e); - + throw new NoSingleResultException("No single object for subject " + debugString(subject) + " and relation " + debugString(relation), e.getResultCount(), e); } catch (DoesNotContainValueException e) { - try { Layer0 L0 = processor.getL0(this); Resource object = getPossibleObject(subject, relation); @@ -1203,23 +1180,19 @@ public class ReadGraphImpl implements ReadGraph { if(isInstanceOf(object, L0.Literal)) { throw new DoesNotContainValueException(e); } else { - throw new InvalidLiteralException("The object " + object + " is not an instance of L0.Literal (use getRelatedValue2 instead)"); + throw new InvalidLiteralException("The object " + object + " is not an instance of L0.Literal (use getRelatedValue2 instead)", e); } } else { - throw new DoesNotContainValueException("The object " + object + " is not an instance of L0.Value"); + throw new DoesNotContainValueException("The object " + object + " is not an instance of L0.Value", e); } } catch (DoesNotContainValueException e2) { throw e2; } catch (DatabaseException e2) { throw new InternalException("The client failed to analyse the cause of the following exception", e); } - } catch (ServiceException e) { - throw new ServiceException(e); - } - } @Override @@ -1230,40 +1203,23 @@ public class ReadGraphImpl implements ReadGraph { assert (relation != null); try { - Resource object = getSingleObject(subject, relation); return getValue(object, binding); - } catch (NoSingleResultException e) { - String message = ""; - try { - String subjectName = NameUtils.getSafeName(this, subject, true); String relationName = NameUtils.getSafeName(this, relation, true); message = "Subject: " + subjectName + ", Relation: " + relationName; - } catch (DatabaseException e2) { } - - throw new NoSingleResultException(message); - + throw new NoSingleResultException(message, e.getResultCount(), e); } catch (DoesNotContainValueException e) { - throw new DoesNotContainValueException(e); - } catch (ServiceException e) { - throw new ServiceException(e); - - } catch (DatabaseException e) { - - throw new ServiceException(INTERNAL_ERROR_STRING, e); - } - } @Override @@ -1394,7 +1350,10 @@ public class ReadGraphImpl implements ReadGraph { Statement stm = getSingleStatement(resource, relation); - return adaptContextual(stm.getObject(), new RelationContextImpl(resource, stm), RelationContext.class, clazz); + Object o = adaptContextual(stm.getObject(), new RelationContextImpl(resource, stm), RelationContext.class, clazz); + if (clazz.isInstance(o)) + return (T)o; + throw new AdaptionException("Returned value is not expected class , got " + o.getClass().getName()+ " , expected " + clazz.getName()); } @@ -1556,15 +1515,15 @@ public class ReadGraphImpl implements ReadGraph { try { - int result = processor.getSingleObject(this, subject, relation); - if(result == 0) return null; - - return processor.querySupport.getResource(result); + int result = processor.getSingleObject(this, subject, relation); + if(result == 0) return null; - } catch (ManyObjectsForFunctionalRelationException e) { + return processor.querySupport.getResource(result); + + } catch (ManyObjectsForFunctionalRelationException e) { + + throw new ManyObjectsForFunctionalRelationException("Many objects in " + subject + " for functional relation " + relation); - throw new ManyObjectsForFunctionalRelationException("subject=" + subject + ", relation=" + relation, e); - } catch (DatabaseException e) { throw new ServiceException(e); @@ -1891,13 +1850,42 @@ public class ReadGraphImpl implements ReadGraph { try { - Collection objects = getObjects(subject, relation); - return !objects.isEmpty(); + RelationInfo rinfo = processor.getRelationInfo(this, relation); + Collection predicates = getPredicates(subject); + + if (rinfo.isFinal) { + + return predicates.contains(relation); + + } else if (rinfo.isFunctional) { + + try { + return processor.getSingleObject(this, subject, relation) != 0; + } catch (ManyObjectsForFunctionalRelationException e) { + return true; + } catch (DatabaseException e) { + throw new ServiceException(e); + } + + } else { + + for (Resource predicate : getPredicates(subject)) { + if (isSubrelationOf(predicate, relation)) + return true; + } + + } + + return false; } catch (ServiceException e) { throw new ServiceException(e); + } catch (DatabaseException e) { + + throw new ServiceException(INTERNAL_ERROR_STRING, e); + } } @@ -1949,7 +1937,7 @@ public class ReadGraphImpl implements ReadGraph { } - final AsyncProcedure NONE = new AsyncProcedure() { + final AsyncProcedure NONE = new AsyncProcedure() { @Override public void execute(AsyncReadGraph graph, Object result) { @@ -1965,42 +1953,11 @@ public class ReadGraphImpl implements ReadGraph { * Implementation of the interface RequestProcessor */ - @Override - public T syncRequest(final Read request) throws DatabaseException { - - assert (request != null); - - if (parent != null) { - - try { - return processor.queryRead(this, request, parent, null, null); - } catch (Throwable e) { - if(e instanceof DatabaseException) throw (DatabaseException)e; - else throw new DatabaseException(e); - } - - } else { - - try { - - return processor.tryQuery(this, request); - - } catch (Throwable throwable) { - - //Logger.defaultLogError("Internal read request failure", throwable); - - if (throwable instanceof DatabaseException) - throw (DatabaseException) throwable; - else - throw new DatabaseException( - "Unexpected exception in ReadGraph.syncRequest(Read,Procedure)", - throwable); - - } - - } - - } + @Override + public T syncRequest(final Read request) throws DatabaseException { + assert (request != null); + return (T)QueryCache.runnerReadEntry(this, request, parent, null, null, true); + } @Override public T syncRequest(Read request, SyncListener procedure) @@ -2014,51 +1971,12 @@ public class ReadGraphImpl implements ReadGraph { return syncRequest(request, new NoneToAsyncListener(procedure)); } - @Override - public T syncRequest(final Read request, final AsyncProcedure procedure) throws DatabaseException { - - assert (request != null); - - ListenerBase listener = procedure != null ? getListenerBase(procedure) : null; - - if (parent != null || listener != null) { - - try { - return processor.queryRead(this, request, parent, procedure, listener); - } catch (Throwable e) { - if(e instanceof DatabaseException) throw (DatabaseException)e; - else throw new DatabaseException(e); - } - - } else { - - try { - - T t = processor.tryQuery(this, request); - if(procedure != null) - procedure.execute(this, t); - - return t; - - } catch (Throwable throwable) { - - Logger.defaultLogError("Internal read request failure", throwable); - - if(procedure != null) - procedure.exception(this, throwable); - - if (throwable instanceof DatabaseException) - throw (DatabaseException) throwable; - else - throw new DatabaseException( - "Unexpected exception in ReadGraph.syncRequest(Read,Procedure)", - throwable); - - } - - } - - } + @Override + public T syncRequest(final Read request, final AsyncProcedure procedure) throws DatabaseException { + assert (request != null); + ListenerBase listener = procedure != null ? getListenerBase(procedure) : null; + return (T)QueryCache.runnerReadEntry(this, request, parent, listener, procedure, true); + } @Override public T syncRequest(final Read request, @@ -2096,7 +2014,7 @@ public class ReadGraphImpl implements ReadGraph { throw (DatabaseException) exception; else throw new DatabaseException( - "Unexpected exception in ReadGraph.syncRequest(AsyncMultiRead)", + "Unexpected exception in ReadGraph.syncRequest(AsyncRead)", exception); } } @@ -2112,12 +2030,7 @@ public class ReadGraphImpl implements ReadGraph { throws DatabaseException { assert (request != null); - AsyncReadProcedure procedure = new AsyncReadProcedure(); - syncRequest(request, procedure); - procedure.checkAndThrow(); - return procedure.result; - -// return syncRequest(request, new AsyncProcedureAdapter()); + return syncRequest(request, new AsyncProcedureAdapter<>() ); } @@ -2139,120 +2052,13 @@ public class ReadGraphImpl implements ReadGraph { return syncRequest(request, new NoneToAsyncListener(procedure)); } - @Override - final public T syncRequest(final AsyncRead request, - final AsyncProcedure procedure) throws DatabaseException { - - assert (request != null); - - // System.out.println("syncRequest " + request + " syncParent=" + - // syncParent); - - ListenerBase listener = getListenerBase(procedure); - - if (parent != null || listener != null || ((request.getFlags() & RequestFlags.SCHEDULE) > 0)) { - - Object syncParent = request; - -// final ReadGraphImpl newGraph = newSync(); - - final ResultCallWrappedSingleQueryProcedure4 wrapper = new ResultCallWrappedSingleQueryProcedure4( - procedure, request); - - processor.query(this, request, parent, wrapper, listener); - -// newGraph.waitAsync(syncParent); - - Throwable e = wrapper.getException(); - if (e != null) { - // The request was async - produce meaningful stack trace by - // wrapping - if (e instanceof DatabaseException) - throw (DatabaseException) e; - else - throw new DatabaseException(e); - } - - return wrapper.getResult(); - - } else { - - // System.out.println("direct call " + request ); - - // Do not set the sync state.parent for external threads - Object syncParent = request; - -// final ReadGraphImpl newGraph = newSync(); - - final ResultCallWrappedSingleQueryProcedure4 wrapper = new ResultCallWrappedSingleQueryProcedure4( - procedure, request); - - try { - - processor.tryQuery(this, request, wrapper); - - } catch (Throwable t) { - - wrapper.exception(this, t); - - } - - Throwable e = wrapper.getException(); - if (e != null) { - // The request was async - produce meaningful stack trace by - // wrapping - if (e instanceof DatabaseException) - throw (DatabaseException) e; - else - throw new DatabaseException(e); - } - - return wrapper.getResult(); - - } - - } - - final private void syncRequest(final AsyncRead request, final AsyncReadProcedure procedure) throws DatabaseException { - - assert (request != null); - - // System.out.println("syncRequest " + request + " syncParent=" + - // syncParent); - - ListenerBase listener = getListenerBase(procedure); - - if (parent != null || listener != null || ((request.getFlags() & RequestFlags.SCHEDULE) > 0)) { - -// final ReadGraphImpl newGraph = newSync(); - - final ResultCallWrappedSingleQueryProcedure4 wrapper = new ResultCallWrappedSingleQueryProcedure4( - procedure, request); - - processor.query(this, request, parent, wrapper, listener); - - } else { - - try { - -// final ReadGraphImpl newGraph = newSync(); - processor.tryQuery(this, request, procedure); -// newGraph.waitAsync(null); - waitAsyncProcedure(procedure); - - } catch (Throwable t) { - if(Development.DEVELOPMENT) { - if(Development.getProperty(DevelopmentKeys.WRITEGRAPH_EXCEPTION_STACKTRACES, Bindings.BOOLEAN)) { - t.printStackTrace(); - } - } - procedure.exception(this, t); - waitAsyncProcedure(procedure); - } - - } - - } + @Override + final public T syncRequest(final AsyncRead request, + final AsyncProcedure procedure) throws DatabaseException { + assert (request != null); + ListenerBase listener = getListenerBase(procedure); + return (T)QueryCache.runnerAsyncReadEntry(this, request, parent, listener, procedure, true); + } @Override public T syncRequest(AsyncRead request, @@ -2275,21 +2081,21 @@ public class ReadGraphImpl implements ReadGraph { final ArrayList result = new ArrayList(); final DataContainer exception = new DataContainer(); - syncRequest(request, new AsyncMultiProcedure() { + syncRequest(request, new SyncMultiProcedure() { @Override - public void execute(AsyncReadGraph graph, T t) { + public void execute(ReadGraph graph, T t) { synchronized (result) { result.add(t); } } @Override - public void finished(AsyncReadGraph graph) { + public void finished(ReadGraph graph) { } @Override - public void exception(AsyncReadGraph graph, Throwable t) { + public void exception(ReadGraph graph, Throwable t) { exception.set(t); } @@ -2314,78 +2120,60 @@ public class ReadGraphImpl implements ReadGraph { } - @Override - public Collection syncRequest(MultiRead request, - AsyncMultiListener procedure) { - return syncRequest(request, (AsyncMultiProcedure) procedure); - } - @Override public Collection syncRequest(MultiRead request, SyncMultiListener procedure) { - return syncRequest(request, new SyncToAsyncMultiListener(procedure)); + return syncRequest(request, (SyncMultiProcedure)procedure); } @Override public Collection syncRequest(MultiRead request, MultiListener procedure) { - return syncRequest(request, new NoneToAsyncMultiListener(procedure)); + return syncRequest(request, new NoneToSyncMultiListener(procedure)); } @Override public Collection syncRequest(MultiRead request, - AsyncMultiProcedure procedure) { + SyncMultiProcedure procedure) { assert (request != null); ListenerBase listener = getListenerBase(procedure); + final ResultCallWrappedSyncQueryProcedure wrapper = new ResultCallWrappedSyncQueryProcedure(procedure); + if (parent != null || listener != null) { - Object syncParent = request; +// Object syncParent = request; // final ReadGraphImpl newGraph = newSync(); - processor.query(this, request, parent, procedure, listener); + processor.query(this, request, parent, wrapper, listener); // newGraph.waitAsync(syncParent); } else { - Object syncParent = request; +// Object syncParent = request; // final ReadGraphImpl newGraph = newSync(); - final ResultCallWrappedQueryProcedure4 wrapper = new ResultCallWrappedQueryProcedure4(procedure); - try { - request.perform(this, wrapper); - } catch (Throwable t) { - wrapper.exception(this, t); -// newGraph.waitAsync(syncParent); - } } - // TODO - return null; - - } + return wrapper.get(); - @Override - public Collection syncRequest(MultiRead request, - SyncMultiProcedure procedure) { - return syncRequest(request, new SyncToAsyncMultiProcedure(procedure)); } @Override public Collection syncRequest(MultiRead request, MultiProcedure procedure) { - return syncRequest(request, new NoneToAsyncMultiProcedure(procedure)); + return syncRequest(request, new NoneToSyncMultiProcedure(procedure)); } static class AsyncMultiReadProcedure extends ArrayList implements AsyncMultiProcedure { @@ -2471,7 +2259,7 @@ public class ReadGraphImpl implements ReadGraph { if (parent != null || listener != null) { - Object syncParent = request; +// Object syncParent = request; // final ReadGraphImpl newGraph = newSync(); @@ -2519,7 +2307,7 @@ public class ReadGraphImpl implements ReadGraph { if (parent != null || listener != null) { - Object syncParent = request; +// Object syncParent = request; // final ReadGraphImpl newGraph = newSync(); @@ -2529,7 +2317,7 @@ public class ReadGraphImpl implements ReadGraph { } else { - Object syncParent = request; +// Object syncParent = request; // final ReadGraphImpl newGraph = newSync(); @@ -2616,70 +2404,10 @@ public class ReadGraphImpl implements ReadGraph { final public T syncRequest(final ExternalRead request, final Procedure procedure) throws DatabaseException { - assert (request != null); - - ListenerBase listener = getListenerBase(procedure); - - final DataContainer exception = new DataContainer(); - final DataContainer result = new DataContainer(); - - if (parent != null || listener != null) { - -// final ReadGraphImpl newGraph = newSync(); - - processor.query(this, request, parent, new Procedure() { - - @Override - public void exception(Throwable throwable) { - exception.set(throwable); - procedure.exception(throwable); - } - - @Override - public void execute(T t) { - result.set(t); - procedure.execute(t); - } - - }, listener); - -// newGraph.waitAsync(request); - - } else { - - try { - - T t = processor.tryQuery(this, request); - result.set(t); - procedure.execute(t); - - } catch (Throwable t) { - - if (t instanceof DatabaseException) { - exception.set((DatabaseException)t); - procedure.exception(exception.get()); - } else { - exception.set(new DatabaseException( - "Unexpected exception in ReadGraph.syncRequest(Read)", - t)); - procedure.exception(exception.get()); - } - - } - - } - - Throwable t = exception.get(); - if (t != null) { - if (t instanceof DatabaseException) - throw (DatabaseException) t; - else - throw new DatabaseException( - "Unexpected exception in ReadGraph.syncRequest(Read)", - t); - } + assert (request != null); - return result.get(); + ListenerBase listener = procedure != null ? getListenerBase(procedure) : null; + return QueryCache.resultExternalReadEntry(this, request, parent, listener, procedure); } @@ -3326,42 +3054,19 @@ public class ReadGraphImpl implements ReadGraph { } -// @Override -// final public void forEachDirectObject(final Resource subject, -// final Resource relation, -// final AsyncMultiProcedure procedure) { -// -// processor.forEachDirectObject(this, subject, relation, procedure); -// -// } -// -// @Override -// public void forEachDirectObject(Resource subject, Resource relation, -// SyncMultiProcedure procedure) { -// forEachDirectObject(subject, relation, -// new SyncToAsyncMultiProcedure(procedure)); -// } -// -// @Override -// public void forEachDirectObject(Resource subject, Resource relation, -// MultiProcedure procedure) { -// forEachDirectObject(subject, relation, -// new NoneToAsyncMultiProcedure(procedure)); -// } - @Override - final public void forEachDirectPredicate(final Resource subject, final AsyncMultiProcedure procedure) { + final public void forEachDirectPredicate(final Resource subject, final AsyncProcedure> procedure) { processor.forEachDirectPredicate(this, subject, procedure); } @Override - public void forEachDirectPredicate(Resource subject, SyncMultiProcedure procedure) { - forEachDirectPredicate(subject, new SyncToAsyncMultiProcedure(procedure)); + final public void forEachDirectPredicate(final Resource subject, final SyncProcedure> procedure) { + forEachDirectPredicate(subject, new SyncToAsyncProcedure>(procedure)); } @Override - public void forEachDirectPredicate(Resource subject, MultiProcedure procedure) { - forEachDirectPredicate(subject, new NoneToAsyncMultiProcedure(procedure)); + public void forEachDirectPredicate(Resource subject, Procedure> procedure) { + forEachDirectPredicate(subject, new NoneToAsyncProcedure>(procedure)); } @Override @@ -3851,14 +3556,9 @@ public class ReadGraphImpl implements ReadGraph { // else procedure.execute(graph, (T) obj); - } catch (IOException e) { - procedure.exception(graph, e); - } catch (BufferUnderflowException e) { - procedure.exception(graph, e); } catch (Throwable t) { - procedure.exception(graph, t); + procedure.exception(graph, new ServiceException("Could not forValue for subject " + debugString(resource) + " and binding " + String.valueOf(binding) + " with bytes " + safeArrayToString(result), t)); } - } @Override @@ -3878,6 +3578,24 @@ public class ReadGraphImpl implements ReadGraph { }); } + + private static String safeArrayToString(byte[] a) { + if (a == null) + return "null"; + int iMax = a.length - 1; + if (iMax == -1) + return "[]"; + + StringBuilder b = new StringBuilder(); + b.append('['); + for (int i = 0; i < 100; i++) { // limit to first 100 items + b.append(a[i]); + if (i == iMax) + return b.append(']').toString(); + b.append(", "); + } + return b.append(", ... (" + a.length + ")]").toString(); + } @Override public void forValue(Resource subject, Binding binding, @@ -4572,14 +4290,9 @@ public class ReadGraphImpl implements ReadGraph { else procedure.execute(graph, (T) obj); - } catch (IOException e) { - procedure.exception(graph, e); - } catch (BufferUnderflowException e) { - procedure.exception(graph, e); } catch (Throwable t) { - procedure.exception(graph, t); + procedure.exception(graph, new ServiceException("Could not forValue for subject " + debugString(resource) + " and binding " + String.valueOf(binding) + " with bytes " + safeArrayToString(result), t)); } - } @Override @@ -4729,14 +4442,6 @@ public class ReadGraphImpl implements ReadGraph { listener); } -// @Override -// final public void forPossibleRelatedValue(final Resource subject, final Resource relation, final Binding binding, -// final AsyncProcedure procedure) { -// -// forPossibleRelatedValue(subject, relation, binding, procedure, false); -// -// } - final public void forPossibleRelatedValue(final Resource subject, final Resource relation, final Binding binding, final AsyncProcedure procedure) { @@ -5425,11 +5130,6 @@ public class ReadGraphImpl implements ReadGraph { return processor.getSession(); } -// @Override -// final public Builtins getBuiltins() { -// return processor.getSession().getBuiltins(); -// } - @Override public void asyncRequest(final Read request) { @@ -5474,55 +5174,32 @@ public class ReadGraphImpl implements ReadGraph { assert (request != null); assert (procedure != null); + + AsyncBarrierImpl barrier = asyncBarrier; + if(barrier != null) + barrier.inc(); + + processor.scheduleNow(new SessionTask(this) { - final ListenerBase listener = getListenerBase(procedure); - - if (parent != null || listener != null) { - - try { - processor.queryRead(this, request, parent, procedure, - listener); - } catch (Throwable e) { - // This throwable has already been transferred to procedure at this point - do nothing about it - //Logger.defaultLogError("Internal error ", e); - } - - } else { - -// final ReadGraphImpl newGraph = newSync(); - - try { - - T result = request.perform(this); - - try { - procedure.execute(this, result); - } catch (Throwable t) { - Logger.defaultLogError(t); - } - - } catch (Throwable t) { - + @Override + public void run0(int thread) { try { - procedure.exception(this, t); - } catch (Throwable t2) { - Logger.defaultLogError(t2); + final ListenerBase listener = getListenerBase(procedure); + QueryCache.runnerReadEntry(ReadGraphImpl.this, request, parent, listener, procedure, false); + } catch (DatabaseException e) { + Logger.defaultLogError(e); + } finally { + if(barrier != null) + barrier.dec(); } - - } finally { - } - - } + + }); } public static ReadGraphImpl createAsync(QueryProcessor support) { - return new ReadGraphImpl(null, support); - } - - public static ReadGraphImpl forRecompute(CacheEntry entry, QueryProcessor support) { - return new ReadGraphImpl(entry, support); + return new ReadGraphImpl(null, null, support); } @Override @@ -5578,42 +5255,55 @@ public class ReadGraphImpl implements ReadGraph { asyncRequest(request, new NoneToAsyncListener(procedure)); } - @Override - final public void asyncRequest(final AsyncRead request, - final AsyncProcedure procedure) { - - assert (request != null); - assert (procedure != null); - - final ListenerBase listener = getListenerBase(procedure); - - if (parent != null || listener != null) { + @Override + final public void asyncRequest(final AsyncRead request, + final AsyncProcedure procedure) { - processor.query(this, request, parent, procedure, listener); + assert (request != null); + assert (procedure != null); - } else { + AsyncBarrierImpl barrier = asyncBarrier; + if(barrier != null) + barrier.inc(); - try { - - request.perform(this, new CallWrappedSingleQueryProcedure4(procedure, request)); + processor.scheduleNow(new SessionTask(this) { - } catch (Throwable t) { + @Override + public void run0(int thread) { - if (t instanceof DatabaseException) - procedure.exception(this, t); - else - procedure - .exception( - this, - new DatabaseException( - "Unexpected exception in ReadGraph.asyncRequest(SingleAsyncRead, SingleProcedure)", - t)); + if(barrier != null) + barrier.inc(); - } + try { + final ListenerBase listener = getListenerBase(procedure); + QueryCache.runnerAsyncReadEntry(ReadGraphImpl.this, request, parent, listener, new AsyncProcedure() { + + @Override + public void execute(AsyncReadGraph graph, T result) { + procedure.execute(graph, result); + if(barrier != null) + barrier.dec(); + } + + @Override + public void exception(AsyncReadGraph graph, Throwable throwable) { + procedure.exception(graph, throwable); + if(barrier != null) + barrier.dec(); + } + + }, false); + } catch (DatabaseException e) { + LOGGER.error("Error while executing async request", e); + } finally { + if(barrier != null) + barrier.dec(); + } + } - } + }); - } + } @Override public void asyncRequest(AsyncRead request, @@ -5632,9 +5322,9 @@ public class ReadGraphImpl implements ReadGraph { assert (request != null); - asyncRequest(request, new AsyncMultiProcedureAdapter() { + asyncRequest(request, new SyncMultiProcedureAdapter() { @Override - public void exception(AsyncReadGraph graph, Throwable t) { + public void exception(ReadGraph graph, Throwable t) { Logger.defaultLogError(t); } @@ -5646,27 +5336,22 @@ public class ReadGraphImpl implements ReadGraph { } - @Override - public void asyncRequest(MultiRead request, - AsyncMultiListener procedure) { - asyncRequest(request, (AsyncMultiProcedure) procedure); - } - @Override public void asyncRequest(MultiRead request, SyncMultiListener procedure) { - asyncRequest(request, new SyncToAsyncMultiListener(procedure)); + asyncRequest(request, (SyncMultiProcedure)procedure); } @Override public void asyncRequest(MultiRead request, MultiListener procedure) { - asyncRequest(request, new NoneToAsyncMultiListener(procedure)); + asyncRequest(request, new NoneToSyncMultiListener(procedure)); } + @Override public void asyncRequest(final MultiRead request, - final AsyncMultiProcedure procedure) { + final SyncMultiProcedure procedure) { assert (request != null); assert (procedure != null); @@ -5688,7 +5373,11 @@ public class ReadGraphImpl implements ReadGraph { } catch (Throwable t) { - procedure.exception(this, t); + try { + procedure.exception(this, t); + } catch (DatabaseException e) { + LOGGER.error("Unexpected exception while handling exception", e); + } } @@ -5696,16 +5385,10 @@ public class ReadGraphImpl implements ReadGraph { } - @Override - public void asyncRequest(MultiRead request, - SyncMultiProcedure procedure) { - asyncRequest(request, new SyncToAsyncMultiProcedure(procedure)); - } - @Override public void asyncRequest(MultiRead request, MultiProcedure procedure) { - asyncRequest(request, new NoneToAsyncMultiProcedure(procedure)); + asyncRequest(request, new NoneToSyncMultiProcedure(procedure)); } @Override @@ -5845,51 +5528,41 @@ public class ReadGraphImpl implements ReadGraph { assert (request != null); assert (procedure != null); - ListenerBase listener = getListenerBase(procedure); + final ListenerBase listener = getListenerBase(procedure); if (parent != null || listener != null) { - processor.query(this, request, parent, procedure, listener); - - } else { - try { + QueryCacheBase.resultExternalReadEntry(this, request, parent, listener, procedure); + } catch (DatabaseException e) { + Logger.defaultLogError(e); + // This throwable has already been transferred to procedure at this point - do nothing about it + } - request.register(this, new Listener() { - - @Override - public void execute(T result) { - procedure.execute(result); - } - - @Override - public void exception(Throwable t) { - procedure.exception(t); - } - - @Override - public String toString() { - return "asyncRequest(PrimitiveRead) -> " + request; - } + } else { - @Override - public boolean isDisposed() { - return true; - } + request.register(this, new Listener() { + @Override + public void execute(T result) { + procedure.execute(result); + } - }); + @Override + public void exception(Throwable t) { + procedure.exception(t); + } - } catch (Throwable t) { + @Override + public String toString() { + return "asyncRequest(PrimitiveRead) -> " + request; + } - if (t instanceof DatabaseException) - procedure.exception(t); - else - procedure - .exception(new DatabaseException( - "Unexpected exception in ReadGraph.asyncRequest(SingleAsyncRead, SingleProcedure)", - t)); + @Override + public boolean isDisposed() { + return true; + } - } + }); } @@ -5999,111 +5672,65 @@ public class ReadGraphImpl implements ReadGraph { * Internal routines */ - protected static String INTERNAL_ERROR_STRING = "Transaction aborted due to internal client error. Contact application support."; + protected static String INTERNAL_ERROR_STRING = "Transaction aborted due to internal client error."; /* * callerThread is the currently running thread state.syncThread is blocking for * this execution state.syncParent is the blocking request */ - final private boolean isExternal(int thread) { - return thread == Integer.MIN_VALUE; - } - -// final private boolean isSync(int thread) { -// return thread < -1 && thread > Integer.MIN_VALUE; -// } - - ReadGraphImpl(ReadGraphImpl graph) { - this(graph.parent, graph.processor); - } - - ReadGraphImpl(CacheEntry parent, QueryProcessor support) { -// this.state = new ReadGraphState(barrier, support); + ReadGraphImpl(ReadGraphImpl parentGraph, CacheEntry parent, QueryProcessor support) { + this.parentGraph = parentGraph; this.parent = parent; this.processor = support; - } - - ReadGraphImpl(final QueryProcessor support) { - -// this.state = state; - this.processor = support; - this.parent = null; - + this.asyncBarrier = prepareBarrier(parentGraph, parent, null, false); } -// public static ReadGraphImpl createSync(int syncThread, Object syncParent, -// ReadGraphSupportImpl support) { -// return new ReadGraphImpl(syncThread, syncThread, syncParent, null, -// support, new AsyncBarrierImpl(null)); -// } + ReadGraphImpl(ReadGraphImpl parentGraph, CacheEntry parent, QueryProcessor support, AsyncBarrierImpl asyncBarrier) { + this.parentGraph = parentGraph; + this.parent = parent; + this.processor = support; + this.asyncBarrier = asyncBarrier; + } - public static ReadGraphImpl create(QueryProcessor support) { - return new ReadGraphImpl(support); + ReadGraphImpl(ReadGraphImpl graph, CacheEntry parent) { + this(graph, parent, graph.processor); } -// public ReadGraphImpl newAsync() { -// return this; -//// if(!state.synchronizedExecution) { -//// return this; -//// } else { -//// return new ReadGraphImpl(false, parent, state.support, state.barrier); -//// } -// } + ReadGraphImpl(ReadGraphImpl parentGraph, CacheEntry parent, Runnable callback, boolean needsToBlock) { + this(parentGraph, parent, parentGraph.processor, prepareBarrier(parentGraph, parent, callback, needsToBlock)); + } + + static AsyncBarrierImpl prepareBarrier(ReadGraphImpl parentGraph, CacheEntry parent, Runnable callback, boolean needsToBlock) { + return new AsyncBarrierImpl(parentGraph != null ? parentGraph.asyncBarrier : null, parent, callback, needsToBlock); + } + + ReadGraphImpl(ReadGraphImpl graph) { + this(graph, graph.parent); + } -// public ReadGraphImpl newSync() { -// return new ReadGraphImpl(parent, processor); -// } + public ReadGraphImpl withParent(CacheEntry parent, Runnable callback, boolean needsToBlock) { + return new ReadGraphImpl(this, parent, callback, needsToBlock); + } - public ReadGraphImpl newSync(CacheEntry parentEntry) { - return new ReadGraphImpl(parentEntry, processor); + public ReadGraphImpl forRecompute(CacheEntry parent) { + return new ReadGraphImpl(null, parent, processor); } + public static ReadGraphImpl create(QueryProcessor support) { + ReadGraphImpl result = new ReadGraphImpl(null, null, support); + return result; + } + public ReadGraphImpl newRestart(ReadGraphImpl impl) { WriteGraphImpl write = processor.getSession().getService( WriteGraphImpl.class); -// if (write.callerThread != impl.callerThread) -// return new WriteGraphImpl(impl.callerThread, parent, state.support, write.writeSupport, write.provider, write.state.barrier); return write; } -// public ReadGraphImpl newSync(Object parentRequest) { -// return new ReadGraphImpl(callerThread, state.parent, state.support, new AsyncBarrierImpl(state.barrier)); -// } - -// public ReadGraphImpl newSync(final int callerThread, Object parentRequest) { -// assert (state.syncThread == callerThread || (state.syncThread == Integer.MIN_VALUE && callerThread != Integer.MIN_VALUE)); -// return new ReadGraphImpl(callerThread, callerThread, parentRequest, -// state.parent, state.support, new AsyncBarrierImpl(state.barrier)); -// } -// -// public ReadGraphImpl newSyncAsync(Object parentRequest) { -//// assert (callerThread < 0); -// return new ReadGraphImpl(callerThread, state.syncThread, parentRequest, -// state.parent, state.support, new AsyncBarrierImpl(state.barrier)); -// } -// -// public ReadGraphImpl newSyncAsync(final int callerThread, -// Object parentRequest) { -//// assert (callerThread < 0); -// // assert(state.syncThread == callerThread || (state.syncThread == Integer.MIN_VALUE -// // && callerThread != Integer.MIN_VALUE) ); -// return new ReadGraphImpl(callerThread, callerThread, parentRequest, -// state.parent, state.support, new AsyncBarrierImpl(state.barrier)); -// } - - public ReadGraphImpl withAsyncParent(CacheEntry parent) { - return new ReadGraphImpl(parent, processor); - } - - public ReadGraphImpl withParent(CacheEntry parent) { - if(parent == this.parent) return this; - else return new ReadGraphImpl(parent, processor); - } - final private ListenerBase getListenerBase(final Object procedure) { if (procedure instanceof ListenerBase) return (ListenerBase) procedure; @@ -6115,56 +5742,13 @@ public class ReadGraphImpl implements ReadGraph { assert(procedure.done()); -// while (!procedure.done()) { -// -// boolean executed = processor.resumeTasks(callerThread, null, null); -// if (!executed) { -// try { -// Thread.sleep(1); -// // sema.tryAcquire(1, TimeUnit.MILLISECONDS); -// } catch (InterruptedException e) { -// e.printStackTrace(); -// } -// } -// -// } - } public void waitAsyncProcedure(AsyncReadProcedure procedure) { assert(procedure.done()); -// while (!procedure.done()) { -// -// boolean executed = processor.processor.resume(this); -// if (!executed) { -// try { -// Thread.sleep(1); -// // sema.tryAcquire(1, TimeUnit.MILLISECONDS); -// } catch (InterruptedException e) { -// e.printStackTrace(); -// } -// } -// -// } - } - -// public void waitAsync(Object request) { -// try { -// state.barrier.waitBarrier(request, this); -// } catch (Throwable t) { -// t.printStackTrace(); -// processor.scanPending(); -// processor.querySupport.checkTasks(); -// throw new RuntimeDatabaseException(t); -// } -// } - -// public void restart() { -// state.barrier.restart(); -// } public boolean resumeTasks() { return processor.resumeTasks(this); @@ -6403,6 +5987,8 @@ public class ReadGraphImpl implements ReadGraph { } Serializer serializer = binding.serializer(); byte[] bytes = serializer.serialize(initialValue); + // In case the file has been previously accessed and was larger we set the correct size now + rd.binaryFile.setLength(bytes.length); rd.binaryFile.write(bytes); ravs.put(resource, rd); return rd; @@ -6470,7 +6056,6 @@ public class ReadGraphImpl implements ReadGraph { } } - @SuppressWarnings("unchecked") @Override public Variant getVariantValue2(Resource r, Object context) throws DatabaseException { Layer0 L0 = processor.getL0(this); @@ -6593,12 +6178,18 @@ public class ReadGraphImpl implements ReadGraph { return getValue(r, binding); } } else if(types.contains(L0.ExternalValue)) { - try { - return (T)ReflectionUtils.getValue(getURI(r)).getValue(); - } catch(ValueNotFoundException e) { - throw new DatabaseException(e); - } catch(ClassCastException e) { - throw new DatabaseException(e); + ComputationalValue cv = syncRequest(new PossibleAdapter(r, ComputationalValue.class), TransientCacheAsyncListener.instance()); + if(cv != null) { + return cv.getValue(this, r); + } else { + // This should not even be possible since L0 defines an adapter for all values + try { + return (T)ReflectionUtils.getValue(getURI(r)).getValue(); + } catch(ValueNotFoundException e) { + throw new DatabaseException(e); + } catch(ClassCastException e) { + throw new DatabaseException(e); + } } } else { @@ -6663,11 +6254,12 @@ public class ReadGraphImpl implements ReadGraph { @Override public T getRelatedValue2(Resource subject, Resource relation, Object context) throws DatabaseException { if(Development.DEVELOPMENT) { - String error = L0Validations.checkValueType(this, subject, relation); - if(error != null) { - Logger.defaultLogError(new ValidationException(error)); - //throw new ValidationException(error); - new ValidationException(error).printStackTrace(); + if(Development.getProperty(DevelopmentKeys.L0_VALIDATION, Bindings.BOOLEAN)) { + String error = L0Validations.checkValueType(this, subject, relation); + if(error != null) { + Logger.defaultLogError(new ValidationException(error)); + throw new ValidationException(error); + } } } return getValue2(getSingleObject(subject, relation), context); @@ -6676,12 +6268,13 @@ public class ReadGraphImpl implements ReadGraph { @Override public Variant getRelatedVariantValue2(Resource subject, Resource relation, Object context) throws DatabaseException { if(Development.DEVELOPMENT) { - String error = L0Validations.checkValueType(this, subject, relation); - if(error != null) { - Logger.defaultLogError(new ValidationException(error)); - //throw new ValidationException(error); - new ValidationException(error).printStackTrace(); - } + if(Development.getProperty(DevelopmentKeys.L0_VALIDATION, Bindings.BOOLEAN)) { + String error = L0Validations.checkValueType(this, subject, relation); + if(error != null) { + Logger.defaultLogError(new ValidationException(error)); + throw new ValidationException(error); + } + } } return getVariantValue2(getSingleObject(subject, relation), context); } @@ -6740,17 +6333,23 @@ public class ReadGraphImpl implements ReadGraph { throw new DatabaseException(e); } } - + + private static ThreadLocal syncGraph = new ThreadLocal() { + protected Boolean initialValue() { + return true; + } + }; + @Override public boolean setSynchronous(boolean value) { - boolean old = processor.synch; - processor.synch = value; + boolean old = getSynchronous(); + syncGraph.set(value); return old; } - + @Override public boolean getSynchronous() { - return processor.synch; + return syncGraph.get(); } public void ensureLoaded(int resource) { @@ -6781,5 +6380,50 @@ public class ReadGraphImpl implements ReadGraph { public Object getModificationCounter() { return processor.getSession().getModificationCounter(); } + + @Override + public boolean performPending() { + return processor.performPending(this); + } + + public Set ancestorSet() { + HashSet result = new HashSet<>(); + ReadGraphImpl g = this; + while(g != null) { + result.add(g); + g = g.parentGraph; + } + return result; + } + + public int getLevel() { + return getLevelStatic(this); + } + + private static int getLevelStatic(ReadGraphImpl impl) { + if(impl == null) return 0; + else return 1 + getLevelStatic(impl.parentGraph); + } + + public boolean isParent(ReadGraphImpl impl) { + if(impl == null) return false; + if(this == impl) return true; + return isParent(impl.parentGraph); + } + public ReadGraphImpl getTopLevelGraph() { + return getTopLevelGraphStatic(this); + } + + private static ReadGraphImpl getTopLevelGraphStatic(ReadGraphImpl impl) { + if(impl.parentGraph == null) return impl; + else return getTopLevelGraphStatic(impl.parentGraph); + } + + @SuppressWarnings("unchecked") + @Override + public T l0() { + return (T) processor.getL0(); + } + }