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=77af46d557e740e8d73e4bc9c9252b2adb7e7a98;hb=e10760b08746837538ad4c2b4c37736aa34c7a47;hpb=4c5ff8ec11947aae4d49106365819717cfa43209 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 77af46d55..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 @@ -18,7 +18,6 @@ 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; @@ -46,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; @@ -135,7 +136,6 @@ import org.simantics.db.exception.NoSingleResultException; import org.simantics.db.exception.ResourceNotFoundException; import org.simantics.db.exception.ServiceException; import org.simantics.db.exception.ValidationException; -import org.simantics.db.impl.BlockingAsyncProcedure; import org.simantics.db.impl.RelationContextImpl; import org.simantics.db.impl.ResourceImpl; import org.simantics.db.impl.internal.RandomAccessValueSupport; @@ -1107,9 +1107,10 @@ public class ReadGraphImpl implements AsyncReadGraph { 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); @@ -1119,20 +1120,9 @@ public class ReadGraphImpl implements AsyncReadGraph { 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 @@ -1360,7 +1350,10 @@ public class ReadGraphImpl implements AsyncReadGraph { 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()); } @@ -1522,15 +1515,15 @@ public class ReadGraphImpl implements AsyncReadGraph { 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; + + return processor.querySupport.getResource(result); - } catch (ManyObjectsForFunctionalRelationException e) { + } 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); @@ -1857,13 +1850,42 @@ public class ReadGraphImpl implements AsyncReadGraph { 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); + } } @@ -1931,11 +1953,11 @@ public class ReadGraphImpl implements AsyncReadGraph { * Implementation of the interface RequestProcessor */ - @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(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) @@ -1949,16 +1971,12 @@ public class ReadGraphImpl implements AsyncReadGraph { 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; - - return QueryCache.resultReadEntry(this, request, parent, listener, procedure); - - } + @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, @@ -2034,19 +2052,13 @@ public class ReadGraphImpl implements AsyncReadGraph { return syncRequest(request, new NoneToAsyncListener(procedure)); } - @Override - final public T syncRequest(final AsyncRead request, - final AsyncProcedure procedure) throws DatabaseException { - - assert (request != null); - - ListenerBase listener = getListenerBase(procedure); - -// BlockingAsyncProcedure ap = new BlockingAsyncProcedure<>(this, procedure, request); - return (T)QueryCache.runnerAsyncReadEntry(this, request, parent, listener, procedure, true); -// return ap.get(); - - } + @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, @@ -3544,14 +3556,9 @@ public class ReadGraphImpl implements AsyncReadGraph { // 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 @@ -3571,6 +3578,24 @@ public class ReadGraphImpl implements AsyncReadGraph { }); } + + 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, @@ -4265,14 +4290,9 @@ public class ReadGraphImpl implements AsyncReadGraph { 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 @@ -5154,8 +5174,12 @@ public class ReadGraphImpl implements AsyncReadGraph { assert (request != null); assert (procedure != null); - - processor.schedule(new SessionTask(this) { + + AsyncBarrierImpl barrier = asyncBarrier; + if(barrier != null) + barrier.inc(); + + processor.scheduleNow(new SessionTask(this) { @Override public void run0(int thread) { @@ -5164,6 +5188,9 @@ public class ReadGraphImpl implements AsyncReadGraph { QueryCache.runnerReadEntry(ReadGraphImpl.this, request, parent, listener, procedure, false); } catch (DatabaseException e) { Logger.defaultLogError(e); + } finally { + if(barrier != null) + barrier.dec(); } } @@ -5228,28 +5255,55 @@ public class ReadGraphImpl implements AsyncReadGraph { asyncRequest(request, new NoneToAsyncListener(procedure)); } - @Override - final public void asyncRequest(final AsyncRead request, - final AsyncProcedure procedure) { + @Override + final public void asyncRequest(final AsyncRead request, + final AsyncProcedure procedure) { - assert (request != null); - assert (procedure != null); + assert (request != null); + assert (procedure != null); - processor.schedule(new SessionTask(this) { + AsyncBarrierImpl barrier = asyncBarrier; + if(barrier != null) + barrier.inc(); - @Override - public void run0(int thread) { - try { - final ListenerBase listener = getListenerBase(procedure); - QueryCache.runnerAsyncReadEntry(ReadGraphImpl.this, request, parent, listener, procedure, false); - } catch (DatabaseException e) { - Logger.defaultLogError(e); - } - } - - }); + processor.scheduleNow(new SessionTask(this) { - } + @Override + public void run0(int thread) { + + 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, @@ -5629,28 +5683,44 @@ public class ReadGraphImpl implements AsyncReadGraph { this.parentGraph = parentGraph; this.parent = parent; this.processor = support; - this.asyncBarrier = new AsyncBarrierImpl(parentGraph != null ? parentGraph.asyncBarrier : null, parent); + this.asyncBarrier = prepareBarrier(parentGraph, parent, null, false); } + ReadGraphImpl(ReadGraphImpl parentGraph, CacheEntry parent, QueryProcessor support, AsyncBarrierImpl asyncBarrier) { + this.parentGraph = parentGraph; + this.parent = parent; + this.processor = support; + this.asyncBarrier = asyncBarrier; + } + ReadGraphImpl(ReadGraphImpl graph, CacheEntry parent) { this(graph, parent, graph.processor); } + 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 withParent(CacheEntry parent) { - return new ReadGraphImpl(this, parent); + public ReadGraphImpl withParent(CacheEntry parent, Runnable callback, boolean needsToBlock) { + return new ReadGraphImpl(this, parent, callback, needsToBlock); } public ReadGraphImpl forRecompute(CacheEntry parent) { return new ReadGraphImpl(null, parent, processor); } - public static ReadGraphImpl create(QueryProcessor support) { - return new ReadGraphImpl(null, null, support); - } + public static ReadGraphImpl create(QueryProcessor support) { + ReadGraphImpl result = new ReadGraphImpl(null, null, support); + return result; + } public ReadGraphImpl newRestart(ReadGraphImpl impl) { @@ -5917,6 +5987,8 @@ public class ReadGraphImpl implements AsyncReadGraph { } 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; @@ -6106,12 +6178,18 @@ public class ReadGraphImpl implements AsyncReadGraph { 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 { @@ -6176,11 +6254,12 @@ public class ReadGraphImpl implements AsyncReadGraph { @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); @@ -6189,12 +6268,13 @@ public class ReadGraphImpl implements AsyncReadGraph { @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); } @@ -6305,7 +6385,7 @@ public class ReadGraphImpl implements AsyncReadGraph { public boolean performPending() { return processor.performPending(this); } - + public Set ancestorSet() { HashSet result = new HashSet<>(); ReadGraphImpl g = this; @@ -6315,5 +6395,35 @@ public class ReadGraphImpl implements AsyncReadGraph { } 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(); + } }