From 95f0ceb6dcbfe82e69bf2af0f5b0a5ac0ae9cbb0 Mon Sep 17 00:00:00 2001 From: Antti Villberg Date: Tue, 17 Jul 2018 12:09:14 +0300 Subject: [PATCH] Better emptying of trash bin Statement removal was broken in write only request. TG remover did not correctly manage internal resources. Added hardening against errors. gitlab #32 Change-Id: I120fcbdb7077e0f037104331480a2b1ab090d798 --- .../adapter/DirectStatementProcedure.java | 32 + .../db/layer0/adapter/impl/TGRemover.java | 122 +- .../simantics/db/layer0/util/Layer0Utils.java | 49 +- .../util/ModelTransferableGraphSource.java | 1124 +++++++++-------- .../procore/internal/ClusterChange.java | 13 +- .../procore/internal/ClusterChange2.java | 3 +- .../procore/internal/ClusterTable.java | 22 +- .../internal/DirectStatementsImpl.java | 223 ++-- .../procore/internal/SessionImplSocket.java | 6 +- 9 files changed, 902 insertions(+), 692 deletions(-) create mode 100644 bundles/org.simantics.db.layer0/src/org/simantics/db/common/procedure/adapter/DirectStatementProcedure.java diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/common/procedure/adapter/DirectStatementProcedure.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/common/procedure/adapter/DirectStatementProcedure.java new file mode 100644 index 000000000..398b1851a --- /dev/null +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/common/procedure/adapter/DirectStatementProcedure.java @@ -0,0 +1,32 @@ +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 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 diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/impl/TGRemover.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/impl/TGRemover.java index 885948834..be34bb9ba 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/impl/TGRemover.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/impl/TGRemover.java @@ -11,15 +11,25 @@ *******************************************************************************/ package org.simantics.db.layer0.adapter.impl; +import java.util.ArrayList; +import java.util.List; + import org.eclipse.core.runtime.IProgressMonitor; 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.exception.DatabaseException; import org.simantics.db.layer0.util.ModelTransferableGraphSource; import org.simantics.db.layer0.util.ModelTransferableGraphSourceRequest; import org.simantics.db.layer0.util.TransferableGraphConfiguration2; +import org.simantics.db.service.DirectQuerySupport; import org.simantics.db.service.SerialisationSupport; import org.simantics.graph.db.TransferableGraphSource.TransferableGraphSourceProcedure; +import org.simantics.graph.representation.Identity; +import org.simantics.graph.representation.Internal; +import org.simantics.graph.representation.Root; +import org.simantics.layer0.Layer0; /** * @author Tuukka Lehtonen @@ -27,7 +37,9 @@ import org.simantics.graph.db.TransferableGraphSource.TransferableGraphSourcePro public class TGRemover extends AbstractRemover { @SuppressWarnings("unused") - private IProgressMonitor monitor; + private IProgressMonitor monitor; + + private ArrayList roots = new ArrayList<>(); public TGRemover(Resource resource) { super(resource); @@ -38,46 +50,78 @@ public class TGRemover extends AbstractRemover { this.monitor = monitor; } + public List getRoots() { + return roots; + } + @Override public void remove(final WriteGraph graph) throws DatabaseException { - - TransferableGraphConfiguration2 conf = new TransferableGraphConfiguration2(graph, resource); - conf.values = false; - final SerialisationSupport ss = graph.getService(SerialisationSupport.class); - - try (ModelTransferableGraphSource source = graph.syncRequest(new ModelTransferableGraphSourceRequest(conf))) { - source.forResourceStatements(graph, new TransferableGraphSourceProcedure() { - - @Override - public void execute(int[] value) throws Exception { - Resource s = ss.getResource(value[0]); - Resource p = ss.getResource(value[1]); - Resource i = null; - if(value[2] != -1) i = ss.getResource(value[2]); - Resource o = ss.getResource(value[3]); - -// System.err.println("s=" + s + " p=" + graph.getPossibleURI(p) + " o=" + o + " p:" + p + " i:" + i); - - graph.deny(s,p,i,o); - } - - }); - - source.forValueResources(graph, new TransferableGraphSourceProcedure() { - - @Override - public void execute(int[] value) throws Exception { - Resource s = ss.getResource(value[0]); -// System.err.println("s=" + s + " p=" + graph.getPossibleURI(p) + " o=" + o + " " + i); - graph.denyValue(s); - } - - }); - - } catch (Exception e) { - throw new DatabaseException(e); - } - + + Layer0 L0 = Layer0.getInstance(graph); + + TransferableGraphConfiguration2 conf = new TransferableGraphConfiguration2(graph, resource); + conf.values = false; + final SerialisationSupport ss = graph.getService(SerialisationSupport.class); + final DirectQuerySupport dqs = graph.getService(DirectQuerySupport.class); + + try (ModelTransferableGraphSource source = graph.syncRequest(new ModelTransferableGraphSourceRequest(conf))) { + + long[] rev = source.getResourceArray(graph); + + source.forIdentities(graph, new TransferableGraphSourceProcedure() { + + @Override + public void execute(Identity value) throws Exception { + if (value.definition instanceof Internal) { + long res = rev[value.resource]; + Resource r = ss.getResource(res); + Resource name = graph.getPossibleObject(r, L0.HasName); + if (name != null) { + graph.deny(r, L0.HasName, L0.NameOf, name); + graph.denyValue(name); + DirectStatementProcedure proc = new DirectStatementProcedure(); + dqs.forEachDirectPersistentStatement(graph, name, proc); + for (Statement stm : proc.getOrThrow()) { + graph.deny(name, stm.getPredicate(), stm.getObject()); + } + } + } else if (value.definition instanceof Root) { + long res = rev[value.resource]; + Resource r = ss.getResource(res); + roots.add(r); + } + } + + }); + + source.forResourceStatements(graph, new TransferableGraphSourceProcedure() { + + @Override + public void execute(int[] value) throws Exception { + Resource s = ss.getResource(value[0]); + Resource p = ss.getResource(value[1]); + Resource i = null; + if (value[2] != -1) + i = ss.getResource(value[2]); + Resource o = ss.getResource(value[3]); + graph.deny(s, p, i, o); + } + + }); + + source.forValueResources(graph, new TransferableGraphSourceProcedure() { + + @Override + public void execute(int[] value) throws Exception { + graph.denyValue(ss.getResource(value[0])); + } + + }); + + } catch (Exception e) { + throw new DatabaseException(e); + } + } } diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java index 6b9b2fc65..56e1e11f2 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java @@ -73,6 +73,7 @@ import org.simantics.db.common.request.DelayedWriteRequest; import org.simantics.db.common.request.ObjectsWithType; import org.simantics.db.common.request.PossibleChild; import org.simantics.db.common.request.PossibleIndexRoot; +import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.event.ChangeListener; import org.simantics.db.exception.CancelTransactionException; @@ -83,6 +84,7 @@ import org.simantics.db.layer0.adapter.CopyHandler2; import org.simantics.db.layer0.adapter.GenericRelationIndex; import org.simantics.db.layer0.adapter.PasteHandler; import org.simantics.db.layer0.adapter.impl.DefaultPasteHandler; +import org.simantics.db.layer0.adapter.impl.EntityRemover; import org.simantics.db.layer0.adapter.impl.TGRemover; import org.simantics.db.layer0.genericrelation.IndexedRelations; import org.simantics.db.layer0.internal.SimanticsInternal; @@ -1247,9 +1249,11 @@ public class Layer0Utils { emptyTrashBin(monitor, SimanticsInternal.getSession(), SimanticsInternal.getProject()); } - public static void emptyTrashBin(final IProgressMonitor monitor, Session session, final Resource project) throws ServiceException { + public static void emptyTrashBin(final IProgressMonitor monitor, Session session, final Resource project) + throws ServiceException { final SubMonitor mon = SubMonitor.convert(monitor, "Emptying Trash Bin...", 10000); try { + ArrayList unhandled = new ArrayList(); session.syncRequest(new DelayedWriteRequest() { @Override public void perform(WriteGraph graph) throws DatabaseException { @@ -1258,26 +1262,34 @@ public class Layer0Utils { Layer0X L0X = Layer0X.getInstance(graph); Resource parent = graph.getSingleObject(project, L0.PartOf); Resource trashBin = Layer0Utils.getPossibleChild(graph, parent, "TrashBin"); - Collection trashes = trashBin != null - ? graph.getObjects(trashBin, L0.ConsistsOf) - : Collections.emptyList(); + Collection trashes = trashBin != null ? graph.getObjects(trashBin, L0.ConsistsOf) + : Collections. emptyList(); if (trashes.isEmpty()) throw new CancelTransactionException(); mon.setWorkRemaining((2 + trashes.size()) * 1000); - for(Resource trash : trashes) { + for (Resource trash : trashes) { if (mon.isCanceled()) throw new CancelTransactionException(); mon.subTask(NameUtils.getSafeName(graph, trash)); + boolean isIndexRoot = graph.isInstanceOf(trash, L0.IndexRoot); TGRemover remo = new TGRemover(mon.newChild(1000, SubMonitor.SUPPRESS_ALL_LABELS), trash); - remo.remove(graph); - if(graph.isInstanceOf(trash, L0.IndexRoot)) { - // TODO: this should be an utility - GenericRelationIndex index = graph.adapt(L0X.DependenciesRelation, GenericRelationIndex.class); - IndexedRelations ir = graph.getService(IndexedRelations.class); - // Deletes index files - ir.reset(null, graph, L0X.DependenciesRelation, trash); - // Notifies DB listeners - index.reset(graph, trash); + try { + remo.remove(graph); + unhandled.addAll(remo.getRoots()); + } catch (DatabaseException e) { + // Something went wrong - try to remove this later + // with EntityRemover + unhandled.add(trash); + } + if (isIndexRoot) { + // TODO: this should be an utility + GenericRelationIndex index = graph.adapt(L0X.DependenciesRelation, + GenericRelationIndex.class); + IndexedRelations ir = graph.getService(IndexedRelations.class); + // Deletes index files + ir.reset(null, graph, L0X.DependenciesRelation, trash); + // Notifies DB listeners + index.reset(graph, trash); } } if (mon.isCanceled()) @@ -1286,6 +1298,15 @@ public class Layer0Utils { mon.newChild(1000); } }); + + session.syncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + for (Resource r : unhandled) + EntityRemover.remove(graph, r); + } + }); + if (mon.isCanceled()) return; mon.subTask("Purging Database"); diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/ModelTransferableGraphSource.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/ModelTransferableGraphSource.java index 95923c799..b0922dd1c 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/ModelTransferableGraphSource.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/ModelTransferableGraphSource.java @@ -38,6 +38,8 @@ import org.simantics.graph.representation.Internal; import org.simantics.graph.representation.Root; import org.simantics.graph.representation.Value; import org.simantics.layer0.Layer0; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import gnu.trove.list.array.TIntArrayList; import gnu.trove.map.TIntObjectMap; @@ -46,552 +48,638 @@ import gnu.trove.procedure.TIntIntProcedure; public class ModelTransferableGraphSource implements TransferableGraphSource { - final private TransferableGraphConfiguration2 configuration; - final private DomainProcessorState state; - final private int externalBase; - final private int resourceCount; - final private File[] files; - final private TGValueModifier valueModifier; - - private volatile boolean closed = false; - - TIntArrayList externalParents = new TIntArrayList(); - ArrayList externalNames = new ArrayList<>(); - TreeMap downloads = new TreeMap(); - - public ModelTransferableGraphSource(final ReadGraph graph, TransferableGraphConfiguration2 configuration, final DomainProcessorState state, File ... fs) throws DatabaseException { - - this.configuration = configuration; - this.state = state; - this.files = fs; - this.valueModifier = state.valueModifier; - - SerialisationSupport ss = graph.getService(SerialisationSupport.class); - - // At this point ids contains all internal resources. Now add roots and externals. - - // Root Library - state.ids.put(ss.getTransientId(graph.getRootLibrary()), state.id++); - - // External roots - internal roots were already processed as internal resources by domain processor - for(SeedSpec spec : configuration.seeds) { - if(SeedSpecType.SPECIAL_ROOT.equals(spec.specType)) { - int resourceId = ss.getTransientId(spec.resource); - state.ids.put(resourceId, state.id++); - // The fixed roots have been seen as externals by domain processor. Now remove them from external set. - state.externals.remove(resourceId); - } - } - - this.externalBase = state.id; - - final Collection errors = new HashSet<>(); - - // All resource considered as not internal by domain processor. Can also contain roots. - int[] externals = state.externals.toArray(); - - // Build up the state.externals, externalNames and externalParents - for(int i=0;i sorted = new ArrayList<>(errors); - Collections.sort(sorted); - StringBuilder message = new StringBuilder(); - message.append("Errors in exported model:\n"); - for(String error : sorted) { - message.append(error); - message.append("\n"); - } - throw new DatabaseException(message.toString()); - } - - this.resourceCount = state.id; - - state.extensions.put(ExternalDownloadBean.EXTENSION_KEY, new Variant(ExternalDownloadBean.BINDING, new ExternalDownloadBean(downloads))); - - } - - int indent = 0; - - public boolean validateExternal(Resource ext) { - if(configuration.validate) { - ExtentStatus status = configuration.preStatus.get(ext); - if(status != null) { - if(ExtentStatus.INTERNAL.equals(status)) return false; - else if(ExtentStatus.EXCLUDED.equals(status)) return false; - } - } - return true; - } - - private Resource getResource(ReadGraph graph, int r) throws DatabaseException { - SerialisationSupport ss = graph.getService(SerialisationSupport.class); - return ss.getResource(r); - } - - final public int getExistingId(ReadGraph graph, int r) throws DatabaseException { - - int ret = state.ids.get(r); - if(ret != -1) { - return ret; - } else { - SerialisationSupport ss = graph.getService(SerialisationSupport.class); - throw new DatabaseException("Id has not been created for " + NameUtils.getSafeName(graph, ss.getResource(r))); - } - - } - - /* - * - * @return -2 if r is not really external and the statement should be excluded - * - */ - public int getId(ReadGraph graph, int r, Collection errors) throws DatabaseException { + private static final Logger LOGGER = LoggerFactory + .getLogger(ModelTransferableGraphSource.class); + + final private TransferableGraphConfiguration2 configuration; + + final private DomainProcessorState state; + + final private int externalBase; + + final private int resourceCount; + + final private File[] files; + + final private TGValueModifier valueModifier; + + private volatile boolean closed = false; + + TIntArrayList externalParents = new TIntArrayList(); + + ArrayList externalNames = new ArrayList<>(); + + TreeMap downloads = new TreeMap(); + + public ModelTransferableGraphSource(final ReadGraph graph, TransferableGraphConfiguration2 configuration, + final DomainProcessorState state, File... fs) throws DatabaseException { + + this.configuration = configuration; + this.state = state; + this.files = fs; + this.valueModifier = state.valueModifier; + + SerialisationSupport ss = graph.getService(SerialisationSupport.class); + + // At this point ids contains all internal resources. Now add roots and + // externals. + + // Root Library + state.ids.put(ss.getTransientId(graph.getRootLibrary()), state.id++); + + // External roots - internal roots were already processed as internal + // resources by domain processor + for (SeedSpec spec : configuration.seeds) { + if (SeedSpecType.SPECIAL_ROOT.equals(spec.specType)) { + int resourceId = ss.getTransientId(spec.resource); + state.ids.put(resourceId, state.id++); + // The fixed roots have been seen as externals by domain + // processor. Now remove them from external set. + state.externals.remove(resourceId); + } + } + + this.externalBase = state.id; + + final Collection errors = new HashSet<>(); + + // All resource considered as not internal by domain processor. Can also + // contain roots. + int[] externals = state.externals.toArray(); + + // Build up the state.externals, externalNames and externalParents + for (int i = 0; i < externals.length; i++) { + getId(graph, externals[i], errors); + } + + state.inverses.forEachEntry(new TIntIntProcedure() { + + @Override + public boolean execute(int predicate, int inverse) { + try { + getId(graph, predicate, errors); + if (inverse != 0) + getId(graph, inverse, errors); + } catch (DatabaseException e) { + throw new RuntimeDatabaseException(e); + } + return true; + } + + }); + + if (!errors.isEmpty()) { + ArrayList sorted = new ArrayList<>(errors); + Collections.sort(sorted); + StringBuilder message = new StringBuilder(); + message.append("Errors in exported model:\n"); + for (String error : sorted) { + message.append(error); + message.append("\n"); + } + throw new DatabaseException(message.toString()); + } + + this.resourceCount = state.id; + + state.extensions.put(ExternalDownloadBean.EXTENSION_KEY, + new Variant(ExternalDownloadBean.BINDING, new ExternalDownloadBean(downloads))); + + } + + int indent = 0; + + public boolean validateExternal(Resource ext) { + if (configuration.validate) { + ExtentStatus status = configuration.preStatus.get(ext); + if (status != null) { + if (ExtentStatus.INTERNAL.equals(status)) + return false; + else if (ExtentStatus.EXCLUDED.equals(status)) + return false; + } + } + return true; + } + + private Resource getResource(ReadGraph graph, int r) throws DatabaseException { + SerialisationSupport ss = graph.getService(SerialisationSupport.class); + return ss.getResource(r); + } + + final public int getExistingId(ReadGraph graph, int r) throws DatabaseException { + + int ret = state.ids.get(r); + if (ret != -1) { + return ret; + } else { + SerialisationSupport ss = graph.getService(SerialisationSupport.class); + throw new DatabaseException( + "Id has not been created for " + NameUtils.getSafeName(graph, ss.getResource(r))); + } + + } + + /* + * + * @return -2 if r is not really external and the statement should be + * excluded + * + */ + public int getId(ReadGraph graph, int r, Collection errors) throws DatabaseException { // // First external is root library // if(r == rootId) return internalCount; - SerialisationSupport ss = graph.getService(SerialisationSupport.class); - Layer0 L0 = Layer0.getInstance(graph); - - if(state.ids.containsKey(r)) { - int ret = state.ids.get(r); - if(ret == -1) { - for(int i=0;i<=indent;++i) - System.out.print(" "); - System.out.println("Cycle!!!"); // with " + GraphUtils.getReadableName(g, r)); - } - return ret; - } - else { - Resource res = getResource(graph, r); - if(!validateExternal(res)) { - errors.add("Illegal reference to " + graph.getPossibleURI(getResource(graph, r))); - return -2; + SerialisationSupport ss = graph.getService(SerialisationSupport.class); + Layer0 L0 = Layer0.getInstance(graph); + + if (state.ids.containsKey(r)) { + int ret = state.ids.get(r); + if (ret == -1) { + for (int i = 0; i <= indent; ++i) + System.out.print(" "); + System.out.println("Cycle!!!"); // with " + + // GraphUtils.getReadableName(g, + // r)); + } + return ret; + } else { + Resource res = getResource(graph, r); + if (!validateExternal(res)) { + errors.add("Illegal reference to " + graph.getPossibleURI(getResource(graph, r))); + return -2; + } + Collection parents = graph.getObjects(res, L0.PartOf); + if (parents.size() != 1) { + throw new ValidationException( + "Reference to external resource " + NameUtils.getSafeName(graph, getResource(graph, r), true) + + " without unique uri (" + parents.size() + " parents)."); } - Collection parents = graph.getObjects(res, L0.PartOf); - if(parents.size() != 1) { - throw new ValidationException("Reference to external resource " - + NameUtils.getSafeName(graph, getResource(graph, r), true) + " without unique uri (" + parents.size() + " parents)."); - } - int pid = 0; - for(Resource p : parents) { - ++indent; - pid = getId(graph, ss.getTransientId(p), errors); - if(pid == -2) { - errors.add("Illegal reference to " + graph.getPossibleURI(getResource(graph, r))); - return -2; - } - } - --indent; - String name = graph.getRelatedValue(res, L0.HasName); - // Record the external entry - externalParents.add(pid); + int pid = 0; + for (Resource p : parents) { + ++indent; + pid = getId(graph, ss.getTransientId(p), errors); + if (pid == -2) { + errors.add("Illegal reference to " + graph.getPossibleURI(getResource(graph, r))); + return -2; + } + } + --indent; + String name = graph.getRelatedValue(res, L0.HasName); + // Record the external entry + externalParents.add(pid); externalNames.add(name); - state.ids.put(r, state.id); - // Ensure that this resource is included into the set of externals to maintain the total number of externals - state.externals.add(r); - String download = graph.getPossibleRelatedValue(res, L0.Ontology_download, Bindings.STRING); - if(download != null) { - String uri = graph.getURI(res); - downloads.put(uri, download); - } - return state.id++; - } - } - - @Override - public DataContainer getHeader() throws Exception { - return null; - } - - @Override - public int getResourceCount() { - return resourceCount; - } - - private int countRootSeeds() { - int result = 0; - for(SeedSpec spec : configuration.seeds) { - if(SeedSpecType.INTERNAL.equals(spec.specType)) continue; - result++; - } - return result; - } - - @Override - public int getIdentityCount() { - return countRootSeeds() + state.externals.size() + state.internalEntries.size() + 1; - } - - @Override - public int getStatementCount() { - return state.statementCount; - } - - @Override - public int getValueCount() { - return state.valueCount; - } - - @Override - public void forStatements(ReadGraph graph, TransferableGraphSourceProcedure procedure) throws Exception { - - int[] value = new int[4]; - long length = state.otherStatementsInput.length(); - state.otherStatementsInput.position(0); - - while(state.otherStatementsInput.position() < length && !state.monitor.isCanceled()) { - - int s = state.otherStatementsInput.readInt(); - int subjectId = state.ids.get(s); - - boolean exclude = subjectId == -1; - - int size = state.otherStatementsInput.readInt(); - for(int i=0;i procedure) throws Exception { - - Serializer variantSerializer = graph.getService(Databoard.class).getSerializerUnchecked(Bindings.VARIANT); - List idContext = new ArrayList<>(); - long length = state.valueInput.length(); - state.valueInput.position(0); - - while(state.valueInput.position() < length && !state.monitor.isCanceled()) { - - // Ignore value type tag - int s = state.valueInput.readInt(); - byte valueType = state.valueInput.readByte(); - switch (valueType) { - case TAG_RAW_COPY_VARIANT_VALUE: - state.valueInput.readInt(); - // Intentional fallthrough. - - case TAG_POTENTIALLY_MODIFIED_VARIANT_VALUE: { - idContext.clear(); - Variant variant = (Variant) variantSerializer.deserialize((DataInput)state.valueInput, idContext); - if (valueModifier.mayNeedModification(variant.type())) { - Object currentObject = variant.getValue(); - Object newObject = valueModifier.modify(state, variant.getBinding(), currentObject); - if (newObject != currentObject) - variant = new Variant(variant.getBinding(), newObject); - } - procedure.execute(new Value(state.ids.get(s), variant)); - break; - } - - default: - throw new IllegalArgumentException("Unrecognized variant value type encountered: " + valueType); - } - } - } + state.ids.put(r, state.id); + // Ensure that this resource is included into the set of externals + // to maintain the total number of externals + state.externals.add(r); + String download = graph.getPossibleRelatedValue(res, L0.Ontology_download, Bindings.STRING); + if (download != null) { + String uri = graph.getURI(res); + downloads.put(uri, download); + } + return state.id++; + } + } + + @Override + public DataContainer getHeader() throws Exception { + return null; + } + + @Override + public int getResourceCount() { + return resourceCount; + } + + private int countRootSeeds() { + int result = 0; + for (SeedSpec spec : configuration.seeds) { + if (SeedSpecType.INTERNAL.equals(spec.specType)) + continue; + result++; + } + return result; + } + + @Override + public int getIdentityCount() { + return countRootSeeds() + state.externals.size() + state.internalEntries.size() + 1; + } + + @Override + public int getStatementCount() { + return state.statementCount; + } + + @Override + public int getValueCount() { + return state.valueCount; + } + + @Override + public void forStatements(ReadGraph graph, TransferableGraphSourceProcedure procedure) throws Exception { + + int[] value = new int[4]; + long length = state.otherStatementsInput.length(); + state.otherStatementsInput.position(0); + + while (state.otherStatementsInput.position() < length && !state.monitor.isCanceled()) { + + int s = state.otherStatementsInput.readInt(); + int subjectId = state.ids.get(s); + + boolean exclude = subjectId == -1; + + int size = state.otherStatementsInput.readInt(); + for (int i = 0; i < size; i++) { + int p = state.otherStatementsInput.readInt(); + int o = state.otherStatementsInput.readInt(); + if (!exclude) { + if (state.pending.contains(o)) { + System.err.println("excluding garbage statement " + s + " " + p + " " + o + + ", object resource is garbage"); + } else if (state.excludedShared.contains(o)) { + System.err.println("excluding shared " + s + " " + p + " " + o); + } else { + + int objectId = getExistingId(graph, o); + // The statement can be denied still + if (objectId != -2) { + value[0] = subjectId; + value[1] = getExistingId(graph, p); + int inverse = state.inverses.get(p); + if (inverse != 0) { + value[2] = getExistingId(graph, inverse); + } else { + value[2] = -1; + } + value[3] = objectId; + + try { + procedure.execute(value); + } catch (Exception e) { + LOGGER.error("Error while processing a statement in transferable graph source", e); + } + + } else { + System.err.println("Denied (" + NameUtils.getSafeName(graph, getResource(graph, s)) + ", " + + NameUtils.getSafeName(graph, getResource(graph, p)) + "," + + NameUtils.getSafeName(graph, getResource(graph, o)) + ")"); + } + + } + } else { + System.err.println("excluding shared " + s); + } + } + } + } + + @Override + public void forValues(ReadGraph graph, TransferableGraphSourceProcedure procedure) throws Exception { + + Serializer variantSerializer = graph.getService(Databoard.class).getSerializerUnchecked(Bindings.VARIANT); + List idContext = new ArrayList<>(); + long length = state.valueInput.length(); + state.valueInput.position(0); + + while (state.valueInput.position() < length && !state.monitor.isCanceled()) { + + // Ignore value type tag + int s = state.valueInput.readInt(); + byte valueType = state.valueInput.readByte(); + switch (valueType) { + case TAG_RAW_COPY_VARIANT_VALUE: + state.valueInput.readInt(); + // Intentional fallthrough. + + case TAG_POTENTIALLY_MODIFIED_VARIANT_VALUE: { + idContext.clear(); + Variant variant = (Variant) variantSerializer.deserialize((DataInput) state.valueInput, idContext); + if (valueModifier.mayNeedModification(variant.type())) { + Object currentObject = variant.getValue(); + Object newObject = valueModifier.modify(state, variant.getBinding(), currentObject); + if (newObject != currentObject) + variant = new Variant(variant.getBinding(), newObject); + } + try { + procedure.execute(new Value(state.ids.get(s), variant)); + } catch (Exception e) { + LOGGER.error("Error while processing a value in transferable graph source", e); + } + break; + } + + default: + throw new IllegalArgumentException("Unrecognized variant value type encountered: " + valueType); + } + } + } @Override public void forValues2(ReadGraph graph, TransferableGraphSourceValueProcedure procedure) throws Exception { - Serializer datatypeSerializer = graph.getService(Databoard.class).getSerializerUnchecked(Bindings.getBindingUnchecked(Datatype.class)); + Serializer datatypeSerializer = graph.getService(Databoard.class) + .getSerializerUnchecked(Bindings.getBindingUnchecked(Datatype.class)); List idContext = new ArrayList<>(); long length = state.valueInput.length(); state.valueInput.position(0); - while(state.valueInput.position() < length && !state.monitor.isCanceled()) { + while (state.valueInput.position() < length && !state.monitor.isCanceled()) { int s = state.valueInput.readInt(); byte valueType = state.valueInput.readByte(); switch (valueType) { - case TAG_RAW_COPY_VARIANT_VALUE: { - // Variant data could be copied raw, no need for modifications - // Note that the variant data is a concatenation of the - // variant datatype serialization and the value serialization. - // variantLength contains both datatype and value data. - int variantLength = state.valueInput.readInt(); - procedure.rawCopy(state.ids.get(s), variantLength, state.valueInput); - break; + case TAG_RAW_COPY_VARIANT_VALUE: { + // Variant data could be copied raw, no need for + // modifications + // Note that the variant data is a concatenation of the + // variant datatype serialization and the value + // serialization. + // variantLength contains both datatype and value data. + int variantLength = state.valueInput.readInt(); + try { + procedure.rawCopy(state.ids.get(s), variantLength, state.valueInput); + } catch (Exception e) { + LOGGER.error("Error while processing a raw value in transferable graph source", e); + } + break; + } + + case TAG_POTENTIALLY_MODIFIED_VARIANT_VALUE: { + // Variant data may need to be modified. + // Cannot optimize this case with raw copying. + idContext.clear(); + Datatype type = (Datatype) datatypeSerializer.deserialize((DataInput) state.valueInput, idContext); + + if (valueModifier.mayNeedModification(type)) { + Binding binding = Bindings.getBinding(type); + Serializer serializer = Bindings.getSerializerUnchecked(binding); + Object value = serializer.deserialize((DataInput) state.valueInput); + value = valueModifier.modify(state, binding, value); + byte[] bytes = serializer.serialize(value); + try { + procedure.execute(state.ids.get(s), type, new ByteBufferReadable(bytes)); + } catch (Exception e) { + LOGGER.error("Error while processing a data type in transferable graph source", e); + } + } else { + try { + procedure.execute(state.ids.get(s), type, state.valueInput); + } catch (Exception e) { + LOGGER.error("Error while processing a raw value in transferable graph source", e); + } + } + break; + } + + default: + throw new IllegalArgumentException("Unrecognized variant value type encountered: " + valueType); } + } + } + + protected Identity getRootIdentity(DomainProcessorState state, SerialisationSupport support, Resource rootLibrary) + throws DatabaseException { + return new Identity(state.ids.get(support.getTransientId(rootLibrary)), new External(-1, "")); + } + + @Override + public void forIdentities(ReadGraph graph, TransferableGraphSourceProcedure procedure) throws Exception { + + SerialisationSupport support = graph.getService(SerialisationSupport.class); + Layer0 L0 = Layer0.getInstance(graph); + + // TODO: this should be Root with name "" + try { + procedure.execute(getRootIdentity(state, support, graph.getRootLibrary())); + } catch (Exception e) { + LOGGER.error("Error while processing a root identity in transferable graph source", e); + } + + TIntObjectMap internalMap = new TIntObjectHashMap<>(100, 0.5f, Integer.MIN_VALUE); - case TAG_POTENTIALLY_MODIFIED_VARIANT_VALUE: { - // Variant data may need to be modified. - // Cannot optimize this case with raw copying. - idContext.clear(); - Datatype type = (Datatype)datatypeSerializer.deserialize((DataInput)state.valueInput, idContext); - - if (valueModifier.mayNeedModification(type)) { - Binding binding = Bindings.getBinding(type); - Serializer serializer = Bindings.getSerializerUnchecked(binding); - Object value = serializer.deserialize((DataInput)state.valueInput); - value = valueModifier.modify(state, binding, value); - byte[] bytes = serializer.serialize(value); - procedure.execute(state.ids.get(s), type, new ByteBufferReadable(bytes)); + // Declare internal and external roots + for (SeedSpec r : configuration.seeds) { + if (SeedSpecType.INTERNAL.equals(r.specType)) + continue; + String typeId = r.type; + if (typeId == null) { + Resource type = graph.getPossibleType(r.resource, L0.Entity); + typeId = type != null ? graph.getURI(type) : Layer0.URIs.Entity; + } + int id = state.ids.get(support.getTransientId(r.resource)); + Root root = new Root(r.name, typeId); + Identity rootId = new Identity(id, root); + internalMap.put(id, rootId); + try { + procedure.execute(rootId); + } catch (Exception e) { + LOGGER.error("Error while processing a root in transferable graph source", e); + } + } + + for (int i = 0; i < state.externals.size(); i++) { + int parent = externalParents.get(i); + String name = externalNames.get(i); + try { + procedure.execute(new Identity(externalBase + i, new External(parent, name))); + } catch (Exception e) { + LOGGER.error("Error while processing a an external identity in transferable graph source", e); + } + } + + if (state.internalEntries != null) { + for (ConsistsOfProcessEntry ie : state.internalEntries) { + if (ie.parent != null) { + if (ie.name != null) { + try { + procedure.execute(resolveInternal(graph, support, ie, internalMap)); + } catch (Exception e) { + LOGGER.error("Error while processing an internal identity in transferable graph source", e); + } + } else { + // In this case there is a child that has no HasName => + // this should be treated as a blank + } } else { - procedure.execute(state.ids.get(s), type, state.valueInput); + try { + procedure.execute(resolveInternal(graph, support, ie, internalMap)); + } catch (Exception e) { + LOGGER.error("Error while processing an internal identity in transferable graph source", e); + } } - break; } + } + + } + + private Identity resolveInternal(ReadGraph graph, SerialisationSupport ss, ConsistsOfProcessEntry entry, + TIntObjectMap internalMap) throws DatabaseException { + int id = state.ids.get(ss.getTransientId(entry.resource)); + Identity existing = internalMap.get(id); + if (existing != null) + return existing; + + if (entry.parent == null) { + Layer0 L0 = Layer0.getInstance(graph); + Resource possibleParent = graph.getPossibleObject(entry.resource, L0.PartOf); + if (possibleParent == null) + throw new DatabaseException("Invalid root or internal parent path: " + entry.resource); + int externalId = state.ids.get(ss.getTransientId(possibleParent)); + Identity result = new Identity(id, new Internal(externalId, entry.name)); + internalMap.put(id, result); + return result; + } else { + Identity parent = resolveInternal(graph, ss, entry.parent, internalMap); + Identity result = new Identity(id, new Internal(parent.resource, entry.name)); + internalMap.put(id, result); + return result; + } + } + + @Override + public TreeMap getExtensions() { + return state.extensions; + } + + public File[] getFiles() { + return files; + } + + private static T tryClose(T c) throws IOException { + if (c != null && c instanceof Closeable) + ((Closeable) c).close(); + return null; + } + + public void closeStreams() throws IOException { + state.valueInput = tryClose(state.valueInput); + state.otherStatementsInput = tryClose(state.otherStatementsInput); + state.statementsOutput = tryClose(state.statementsOutput); + state.valueOutput = tryClose(state.valueOutput); + } + + @Override + public void reset() throws Exception { + throw new UnsupportedOperationException(); + } + + public long[] getResourceArray(ReadGraph graph) throws DatabaseException { + final SerialisationSupport ss = graph.getService(SerialisationSupport.class); + final long[] result = new long[state.ids.size()]; + state.ids.forEachEntry(new TIntIntProcedure() { + + @Override + public boolean execute(int a, int b) { + + try { + Resource r = ss.getResource(a); + result[b] = r.getResourceId(); + } catch (DatabaseException e) { + e.printStackTrace(); + } + + return true; - default: - throw new IllegalArgumentException("Unrecognized variant value type encountered: " + valueType); + } + }); + return result; + } + + public DomainProcessorState getState() { + return state; + } + + public void forResourceStatements(ReadGraph graph, TransferableGraphSourceProcedure procedure) + throws Exception { + + int[] value = new int[4]; + long length = state.otherStatementsInput.length(); + state.otherStatementsInput.position(0); + + while (state.otherStatementsInput.position() < length) { + + int s = state.otherStatementsInput.readInt(); + int subjectId = state.ids.get(s); + + boolean exclude = subjectId == -1; + + int size = state.otherStatementsInput.readInt(); + for (int i = 0; i < size; i++) { + int p = state.otherStatementsInput.readInt(); + int o = state.otherStatementsInput.readInt(); + if (!exclude) { + if (state.excludedShared.contains(o)) { + System.err.println("excluding shared " + s + " " + p + " " + o); + } else { + + int objectId = getExistingId(graph, o); + // The statement can be denied still + if (objectId != -2) { + value[0] = s; + value[1] = p; + int inverse = state.inverses.get(p); + if (inverse != 0) { + value[2] = inverse; + } else { + value[2] = -1; + } + value[3] = o; + + try { + procedure.execute(value); + } catch (Exception e) { + LOGGER.error("Error while processing a statement in transferable graph source", e); + } + + } else { + System.err.println("Denied (" + NameUtils.getSafeName(graph, getResource(graph, s)) + ", " + + NameUtils.getSafeName(graph, getResource(graph, p)) + "," + + NameUtils.getSafeName(graph, getResource(graph, o)) + ")"); + } + + } + } else { + System.err.println("excluding shared " + s); + } } } } - protected Identity getRootIdentity(DomainProcessorState state, SerialisationSupport support, Resource rootLibrary) throws DatabaseException { - return new Identity(state.ids.get(support.getTransientId(rootLibrary)), new External(-1, "")); - } - - @Override - public void forIdentities(ReadGraph graph, TransferableGraphSourceProcedure procedure) throws Exception { - - SerialisationSupport support = graph.getService(SerialisationSupport.class); - Layer0 L0 = Layer0.getInstance(graph); - - // TODO: this should be Root with name "" - procedure.execute(getRootIdentity(state, support, graph.getRootLibrary())); - - TIntObjectMap internalMap = new TIntObjectHashMap<>(100, 0.5f, Integer.MIN_VALUE); - - // Declare internal and external roots - for(SeedSpec r : configuration.seeds) { - if(SeedSpecType.INTERNAL.equals(r.specType)) continue; - String typeId = r.type; - if (typeId == null) { - Resource type = graph.getPossibleType(r.resource, L0.Entity); - typeId = type != null ? graph.getURI(type) : Layer0.URIs.Entity; - } - int id = state.ids.get(support.getTransientId(r.resource)); - Root root = new Root(r.name, typeId); - Identity rootId = new Identity(id,root); - internalMap.put(id, rootId); - procedure.execute(rootId); - } - - for(int i = 0; i < state.externals.size() ; i++) { - int parent = externalParents.get(i); - String name = externalNames.get(i); - procedure.execute(new Identity(externalBase + i, new External(parent,name))); - } - - if(state.internalEntries != null) { - for(ConsistsOfProcessEntry ie : state.internalEntries) { - if(ie.parent != null) { - if(ie.name != null) { - procedure.execute(resolveInternal(graph, support, ie, internalMap)); - } else { - // In this case there is a child that has no HasName => this should be treated as a blank - } - } else { - procedure.execute(resolveInternal(graph, support, ie, internalMap)); - } - } - } - - } - - private Identity resolveInternal(ReadGraph graph, SerialisationSupport ss, ConsistsOfProcessEntry entry, TIntObjectMap internalMap) throws DatabaseException { - int id = state.ids.get(ss.getTransientId(entry.resource)); - Identity existing = internalMap.get(id); - if(existing != null) return existing; - - if(entry.parent == null) { - Layer0 L0 = Layer0.getInstance(graph); - Resource possibleParent = graph.getPossibleObject(entry.resource, L0.PartOf); - if(possibleParent == null) throw new DatabaseException("Invalid root or internal parent path: " + entry.resource); - int externalId = state.ids.get(ss.getTransientId(possibleParent)); - Identity result = new Identity(id, - new Internal(externalId, entry.name)); - internalMap.put(id, result); - return result; - } else { - Identity parent = resolveInternal(graph, ss, entry.parent, internalMap); - Identity result = new Identity(id, - new Internal(parent.resource, entry.name)); - internalMap.put(id, result); - return result; - } - } - - @Override - public TreeMap getExtensions() { - return state.extensions; - } - - public File[] getFiles() { - return files; - } - - private static T tryClose(T c) throws IOException { - if (c != null && c instanceof Closeable) - ((Closeable) c).close(); - return null; - } - - public void closeStreams() throws IOException { - state.valueInput = tryClose(state.valueInput); - state.otherStatementsInput = tryClose(state.otherStatementsInput); - state.statementsOutput = tryClose(state.statementsOutput); - state.valueOutput = tryClose(state.valueOutput); - } - - @Override - public void reset() throws Exception { - throw new UnsupportedOperationException(); - } - - public long[] getResourceArray(ReadGraph graph) throws DatabaseException { - final SerialisationSupport ss = graph.getService(SerialisationSupport.class); - final long[] result = new long[state.ids.size()]; - state.ids.forEachEntry(new TIntIntProcedure() { - - @Override - public boolean execute(int a, int b) { - - try { - Resource r = ss.getResource(a); - result[b] = r.getResourceId(); - } catch (DatabaseException e) { - e.printStackTrace(); - } - - return true; - - } - }); - return result; - } - - public DomainProcessorState getState() { - return state; - } - - public void forResourceStatements(ReadGraph graph, TransferableGraphSourceProcedure procedure) throws Exception { - - int[] value = new int[4]; - long length = state.otherStatementsInput.length(); - state.otherStatementsInput.position(0); - - while(state.otherStatementsInput.position() < length) { - - int s = state.otherStatementsInput.readInt(); - int subjectId = state.ids.get(s); - - boolean exclude = subjectId == -1; - - int size = state.otherStatementsInput.readInt(); - for(int i=0;i procedure) throws Exception { - int[] value = { 0 }; - long length = state.valueInput.length(); - while (state.valueInput.position() < length) { - value[0] = state.valueInput.readInt(); - procedure.execute(value); - } - } - - public TransferableGraphConfiguration2 getConfiguration() { - return configuration; - } - - @Override - public void close() throws IOException { - synchronized (this) { - if (closed) - return; - closed = true; - } - closeStreams(); - if (files != null) { - for (File f : files) { - Files.deleteIfExists(f.toPath()); - } - } - } + public void forValueResources(ReadGraph graph, TransferableGraphSourceProcedure procedure) throws Exception { + int[] value = { 0 }; + long length = state.valueInput.length(); + while (state.valueInput.position() < length) { + value[0] = state.valueInput.readInt(); + try { + procedure.execute(value); + } catch (Exception e) { + LOGGER.error("Error while processing a value in transferable graph source", e); + } + } + } + + public TransferableGraphConfiguration2 getConfiguration() { + return configuration; + } + + @Override + public void close() throws IOException { + synchronized (this) { + if (closed) + return; + closed = true; + } + closeStreams(); + if (files != null) { + for (File f : files) { + Files.deleteIfExists(f.toPath()); + } + } + } } \ No newline at end of file diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterChange.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterChange.java index 1a264dc51..fa0b0797f 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterChange.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterChange.java @@ -54,7 +54,12 @@ public final class ClusterChange { public ClusterImpl clusterImpl; public ClusterChange(ClusterStream clusterStream, ClusterImpl clusterImpl) { + this.clusterImpl = clusterImpl; + + if (!clusterImpl.isLoaded()) + new IllegalStateException("Change to proxy cluster " + clusterImpl.getClusterUID()).printStackTrace(); + clusterUID = clusterImpl.getClusterUID(); long[] longs = new long[ClusterUID.getLongLength()]; clusterUID.toLong(longs, 0); @@ -69,9 +74,13 @@ public final class ClusterChange { Bytes.writeLE(header, offset, longs[i]); //initBuffer(); this.clusterStream = clusterStream; - this.clusterChange2 = new ClusterChange2(clusterUID, clusterImpl); + this.clusterChange2 = new ClusterChange2(clusterUID); clusterStream.changes.add(this); } + + public void adopt(ClusterImpl impl) { + this.clusterImpl = impl; + } private void setHeaderVectorSize(int size) { if (size < 0) @@ -81,7 +90,7 @@ public final class ClusterChange { } @Override public String toString() { - return super.toString() + " cluster=" + clusterImpl.getClusterUID() + " id=" + clusterImpl.getClusterId() + " off=" + byteIndex; + return super.toString() + " cluster=" + clusterUID + " id=" + clusterImpl.getClusterId() + " off=" + byteIndex; } private final void initBuffer() { flushed = false; diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterChange2.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterChange2.java index cebcdcf42..234f2ada4 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterChange2.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterChange2.java @@ -2,7 +2,6 @@ package fi.vtt.simantics.procore.internal; import java.util.Arrays; -import org.simantics.db.procore.cluster.ClusterImpl; import org.simantics.db.service.Bytes; import org.simantics.db.service.ClusterUID; @@ -16,7 +15,7 @@ public class ClusterChange2 { private byte[] bytes; private int byteIndex; private ClusterUID clusterUID; - ClusterChange2(ClusterUID clusterUID, ClusterImpl cluster) { + ClusterChange2(ClusterUID clusterUID) { this.clusterUID = clusterUID; init(); } diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterTable.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterTable.java index c6fd11c4e..7df13315f 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterTable.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterTable.java @@ -289,14 +289,29 @@ public final class ClusterTable implements IClusterTable { } } - synchronized void replaceCluster(ClusterI cluster) { - //printMaps("replaceCluster"); + synchronized void replaceCluster(ClusterI cluster_) { + ClusterImpl cluster = (ClusterImpl) cluster_; checkCollect(); int clusterKey = cluster.getClusterKey(); - ClusterI existing = clusterArray[clusterKey]; + ClusterImpl existing = (ClusterImpl) clusterArray[clusterKey]; if (existing.hasVirtual()) cluster.markVirtual(); + if (existing.cc != null) { + if (existing.isLoaded()) { + // This shall be promoted to actual exception in the future - + // for now, minimal changes + new Exception("Trying to replace cluster with pending changes " + existing.getClusterUID()) + .printStackTrace(); + } else { + // Adopt changes to loaded cluster + cluster.cc = existing.cc; + cluster.cc.adopt(cluster); + cluster.foreignLookup = existing.foreignLookup; + cluster.change = existing.change; + } + } + importanceMap.remove(existing.getImportance()); if (collectorPolicy != null) collectorPolicy.removed((ClusterImpl)existing); @@ -589,7 +604,6 @@ public final class ClusterTable implements IClusterTable { public boolean execute(int clusterKey) { ClusterImpl proxy = clusterArray[clusterKey]; ClusterUID clusterUID = proxy.getClusterUID(); - System.err.println("writeOnlyInvalidate " + clusterUID); clusters.freeProxy(proxy); return true; } diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DirectStatementsImpl.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DirectStatementsImpl.java index 8313beeca..105119791 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DirectStatementsImpl.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DirectStatementsImpl.java @@ -24,116 +24,121 @@ import org.simantics.db.impl.support.ResourceSupport; final public class DirectStatementsImpl implements DirectStatements { - final ResourceSupport support; - 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 add(Statement arg0) { - throw new Error("Not supported"); - } - - @Override - public boolean addAll(Collection arg0) { - throw new Error("Not supported"); - } - - @Override - public void clear() { - throw new Error("Not supported"); - } - - @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 arg0) { + throw new Error("Not supported"); + } + + @Override + public void clear() { + throw new Error("Not supported"); + } + + @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) { 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; - } - - @Override - public boolean containsAll(Collection arg0) { - throw new Error("Not supported"); - } - - @Override - public boolean isEmpty() { - throw new Error("Not supported"); - } - - @Override - public Iterator iterator() { - return new Iterator() { - - int index = 0; - int max = statements.size(); - - @Override - public boolean hasNext() { - return index < max; - } - - @Override - public Statement next() { - return new DirectStatementImpl(support, subject, statements.getQuick(index++), statements.getQuick(index++)); - } - - @Override - public void remove() { - throw new Error("Not supported"); - } - - }; - } - - @Override - public boolean remove(Object arg0) { - throw new Error("Not supported"); - } - - @Override - public boolean removeAll(Collection arg0) { - throw new Error("Not supported"); - } - - @Override - public boolean retainAll(Collection arg0) { - throw new Error("Not supported"); - } - - @Override - public int size() { - return statements.size() >> 1; - } - - @Override - public Object[] toArray() { - throw new Error("Not supported"); - } - - @Override - public T[] toArray(T[] arg0) { - throw new Error("Not supported"); - } - + } + + @Override + public boolean containsAll(Collection arg0) { + throw new Error("Not supported"); + } + + @Override + public boolean isEmpty() { + throw new Error("Not supported"); + } + + @Override + public Iterator iterator() { + return new Iterator() { + + int index = 0; + + int max = statements.size(); + + @Override + public boolean hasNext() { + return index < max; + } + + @Override + public Statement next() { + return new DirectStatementImpl(support, subject, statements.getQuick(index++), + statements.getQuick(index++)); + } + + @Override + public void remove() { + throw new Error("Not supported"); + } + + }; + } + + @Override + public boolean remove(Object arg0) { + throw new Error("Not supported"); + } + + @Override + public boolean removeAll(Collection arg0) { + throw new Error("Not supported"); + } + + @Override + public boolean retainAll(Collection arg0) { + throw new Error("Not supported"); + } + + @Override + public int size() { + return statements.size() >> 1; + } + + @Override + public Object[] toArray() { + throw new Error("Not supported"); + } + + @Override + public T[] toArray(T[] arg0) { + throw new Error("Not supported"); + } + } diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplSocket.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplSocket.java index 9290ac99f..d71a8bfc8 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplSocket.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplSocket.java @@ -1022,15 +1022,13 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule try { int sResourceKey = ClusterTraits.getResourceIndexFromResourceKey(s); - int pResourceKey = ClusterTraits.getResourceIndexFromResourceKey(p); - int oResourceKey = ClusterTraits.getResourceIndexFromResourceKey(o); ClusterI pc = clusterTable.getClusterProxyByResourceKey(p); ClusterI oc = clusterTable.getClusterProxyByResourceKey(o); clusterTranslator.addStatementIndex(cluster, sResourceKey, cluster.getClusterUID(), ClusterChange.REMOVE_OPERATION); - clusterTranslator.addStatementIndex(cluster, pResourceKey, pc.getClusterUID(), ClusterStream.NULL_OPERATION); - clusterTranslator.addStatementIndex(cluster, oResourceKey, oc.getClusterUID(), ClusterStream.NULL_OPERATION); + clusterTranslator.addStatementIndex(cluster, p, pc.getClusterUID(), ClusterStream.NULL_OPERATION); + clusterTranslator.addStatementIndex(cluster, o, oc.getClusterUID(), ClusterStream.NULL_OPERATION); clusterTranslator.removeStatement(cluster); queryProvider2.invalidateResource(s); -- 2.47.1