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=79fe974642d2a71e66054fe6de5d00a60424b7bf;hp=b5da0b92f7bae6521487e2fa0907ca2b96a3c09b;hb=3bcd1023180e2cdc55bc001d0f60075dd7184cfa;hpb=9f0fd59be54719b1fe9322d8fd37e4950857308c 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 b5da0b92f..79fe97464 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,10 +18,10 @@ 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; @@ -45,6 +45,7 @@ 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; @@ -89,6 +90,7 @@ 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; @@ -133,7 +135,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; @@ -198,9 +199,10 @@ public class ReadGraphImpl implements AsyncReadGraph { final static boolean EMPTY_RESOURCE_CHECK = false; final public CacheEntry parent; + public final ReadGraphImpl parentGraph; final public QueryProcessor processor; - public AsyncBarrierImpl asyncBarrier = null; + 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); @@ -1104,9 +1106,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); @@ -1116,20 +1119,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 @@ -1930,11 +1922,8 @@ public class ReadGraphImpl implements AsyncReadGraph { @Override public T syncRequest(final Read request) throws DatabaseException { - assert (request != null); - - return QueryCache.resultReadEntry(this, request, parent, null, null); - + return (T)QueryCache.runnerReadEntry(this, request, parent, null, null, true); } @Override @@ -2012,10 +2001,7 @@ public class ReadGraphImpl implements AsyncReadGraph { throws DatabaseException { assert (request != null); - asyncBarrier = new AsyncBarrierImpl(null); - BlockingAsyncProcedure ap = new BlockingAsyncProcedure<>(this, null, request); - syncRequest(request, ap); - return ap.get(); + return syncRequest(request, new AsyncProcedureAdapter<>() ); } @@ -2045,26 +2031,9 @@ public class ReadGraphImpl implements AsyncReadGraph { ListenerBase listener = getListenerBase(procedure); - BlockingAsyncProcedure ap = new BlockingAsyncProcedure<>(this, procedure, request); - - QueryCache.runnerAsyncReadEntry(this, request, parent, listener, ap, true); - - return ap.get(); - - } - - final private void syncRequest(final AsyncRead request, final AsyncReadProcedure procedure) throws DatabaseException { - - assert (request != null); - - ListenerBase listener = getListenerBase(procedure); - assert(listener == null); - - BlockingAsyncProcedure ap = new BlockingAsyncProcedure<>(this, procedure, request); - - QueryCache.runnerAsyncReadEntry(this, request, parent, listener, ap, true); - - ap.get(); +// BlockingAsyncProcedure ap = new BlockingAsyncProcedure<>(this, procedure, request); + return (T)QueryCache.runnerAsyncReadEntry(this, request, parent, listener, procedure, true); +// return ap.get(); } @@ -3564,14 +3533,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 @@ -3591,6 +3555,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, @@ -4285,14 +4267,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 @@ -5175,10 +5152,10 @@ public class ReadGraphImpl implements AsyncReadGraph { assert (request != null); assert (procedure != null); - processor.schedule(new SessionTask(false) { + processor.schedule(new SessionTask(this) { @Override - public void run(int thread) { + public void run0(int thread) { try { final ListenerBase listener = getListenerBase(procedure); QueryCache.runnerReadEntry(ReadGraphImpl.this, request, parent, listener, procedure, false); @@ -5192,7 +5169,7 @@ public class ReadGraphImpl implements AsyncReadGraph { } public static ReadGraphImpl createAsync(QueryProcessor support) { - return new ReadGraphImpl(null, support); + return new ReadGraphImpl(null, null, support); } @Override @@ -5255,10 +5232,10 @@ public class ReadGraphImpl implements AsyncReadGraph { assert (request != null); assert (procedure != null); - processor.schedule(new SessionTask(false) { + processor.schedule(new SessionTask(this) { @Override - public void run(int thread) { + public void run0(int thread) { try { final ListenerBase listener = getListenerBase(procedure); QueryCache.runnerAsyncReadEntry(ReadGraphImpl.this, request, parent, listener, procedure, false); @@ -5638,34 +5615,38 @@ public class ReadGraphImpl implements AsyncReadGraph { * 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; + ReadGraphImpl(ReadGraphImpl parentGraph, CacheEntry parent, QueryProcessor support) { + this.parentGraph = parentGraph; + this.parent = parent; + this.processor = support; + this.asyncBarrier = new AsyncBarrierImpl(parentGraph != null ? parentGraph.asyncBarrier : null, parent); + } + + ReadGraphImpl(ReadGraphImpl graph, CacheEntry parent) { + this(graph, parent, graph.processor); } ReadGraphImpl(ReadGraphImpl graph) { - this(graph.parent, graph.processor); + this(graph, graph.parent); } - ReadGraphImpl(CacheEntry parent, QueryProcessor support) { - this.parent = parent; - this.processor = support; + public ReadGraphImpl withParent(CacheEntry parent) { + return new ReadGraphImpl(this, parent); } - public static ReadGraphImpl create(QueryProcessor support) { - return new ReadGraphImpl(null, support); + public ReadGraphImpl forRecompute(CacheEntry parent) { + return new ReadGraphImpl(null, parent, processor); } - public static ReadGraphImpl newAsync(ReadGraphImpl parent) { - ReadGraphImpl result = new ReadGraphImpl(parent); - result.asyncBarrier = new AsyncBarrierImpl(parent.asyncBarrier); - return result; + public static ReadGraphImpl create(QueryProcessor support) { + return new ReadGraphImpl(null, null, support); } public ReadGraphImpl newRestart(ReadGraphImpl impl) { @@ -5677,11 +5658,6 @@ public class ReadGraphImpl implements AsyncReadGraph { } - 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; @@ -5938,6 +5914,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; @@ -6127,12 +6105,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 { @@ -6324,7 +6308,17 @@ public class ReadGraphImpl implements AsyncReadGraph { @Override public boolean performPending() { - return processor.performPending(processor.thread.get()); + 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; } }