From a5db6fe37388889277a4d30e9ee6f21c0cb72bc7 Mon Sep 17 00:00:00 2001 From: pkupczyk <pkupczyk> Date: Fri, 17 Nov 2017 17:29:21 +0000 Subject: [PATCH] SSDM-5370 : openBIS sync datasource doesn't scale - improve performance of fetching entities from the datasource SVN: 38913 --- .../plugins/sync/common/EntityRetriever.java | 269 ++++++++---------- 1 file changed, 117 insertions(+), 152 deletions(-) diff --git a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/common/EntityRetriever.java b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/common/EntityRetriever.java index 07c7d77ba79..916481ae4e8 100644 --- a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/common/EntityRetriever.java +++ b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/common/EntityRetriever.java @@ -32,10 +32,8 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.ICodeHolder; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult; import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet; import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetFetchOptions; -import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.DataSetSearchCriteria; import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.Experiment; import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.fetchoptions.ExperimentFetchOptions; -import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.search.ExperimentSearchCriteria; import ch.ethz.sis.openbis.generic.asapi.v3.dto.material.Material; import ch.ethz.sis.openbis.generic.asapi.v3.dto.material.fetchoptions.MaterialFetchOptions; import ch.ethz.sis.openbis.generic.asapi.v3.dto.material.search.MaterialSearchCriteria; @@ -76,7 +74,7 @@ public class EntityRetriever implements IEntityRetriever this.sessionToken = sessionToken; this.masterDataRegistrationTransaction = masterDataRegistrationTransaction; } - + public static EntityRetriever createWithMasterDataRegistationTransaction(IApplicationServerApi v3Api, String sessionToken, IMasterDataRegistrationTransaction masterDataRegistrationTransaction) { @@ -123,266 +121,184 @@ public class EntityRetriever implements IEntityRetriever * will have the shared entity. When we add them to the RL (Resource List) in the data source servlet, any duplicate will throw an error when * using the Resync library. To work around this we catch the duplicate exceptions where a shared sample is involved. */ - findSharedSamples(); + addSharedSamples(); - // build the graph for the space from top-down starting from projects - ProjectSearchCriteria prjCriteria = new ProjectSearchCriteria(); - prjCriteria.withSpace().withCode().thatEquals(spaceId); + ProjectSearchCriteria criteria = new ProjectSearchCriteria(); + criteria.withSpace().withCode().thatEquals(spaceId); - ProjectFetchOptions projectFetchOptions = new ProjectFetchOptions(); - projectFetchOptions.withSpace(); - projectFetchOptions.withAttachments(); + List<Project> projects = v3Api.searchProjects(sessionToken, criteria, createProjectFetchOptions()).getObjects(); - List<Project> projects = v3Api.searchProjects(sessionToken, prjCriteria, projectFetchOptions).getObjects(); for (Project project : projects) { Node<Project> prjNode = new Node<Project>(project); graph.addNode(prjNode); - findExperiments(prjNode); + addExperiments(prjNode); } // add space samples - findSpaceSamples(spaceId); - + addSpaceSamples(spaceId); // TODO logout? // v3.logout(sessionToken); } - // TODO temporary solution until V3 API SampleSearchCriteria.withoutSpace() is implemented - private void findSharedSamples() + private void addSharedSamples() { - SampleFetchOptions fetchOptions = new SampleFetchOptions(); - fetchOptions.withProperties(); - fetchOptions.withType(); - fetchOptions.withExperiment(); - fetchOptions.withSpace(); - fetchOptions.withAttachments(); + SampleSearchCriteria criteria = new SampleSearchCriteria(); + criteria.withoutSpace(); + + List<Sample> samples = v3Api.searchSamples(sessionToken, criteria, createSampleFetchOptions()).getObjects(); - List<Sample> samples = v3Api.searchSamples(sessionToken, new SampleSearchCriteria(), fetchOptions).getObjects(); for (Sample sample : samples) { - if (sample.getSpace() == null) + if (sample.getSpace() != null) { - Node<Sample> sampleNode = new Node<Sample>(sample); - graph.addNode(sampleNode); - findChildAndComponentSamples(sampleNode); - findAndAttachDataSets(sampleNode); + throw new RuntimeException("Expected a shared sample but got " + sample); } + Node<Sample> sampleNode = new Node<Sample>(sample); + graph.addNode(sampleNode); + addChildAndComponentSamples(sampleNode); + addDataSetsForSample(sampleNode); } } - private void findExperiments(Node<Project> prjNode) - { - ExperimentSearchCriteria criteria = new ExperimentSearchCriteria(); - criteria.withProject().withCode().thatEquals(prjNode.getCode()); - criteria.withProject().withSpace().withCode().thatEquals(prjNode.getEntity().getSpace().getCode()); - ExperimentFetchOptions fetchOptions = new ExperimentFetchOptions(); - fetchOptions.withProperties(); - fetchOptions.withProject().withSpace(); - fetchOptions.withType(); - fetchOptions.withAttachments(); - - List<Experiment> experiments = v3Api.searchExperiments(sessionToken, criteria, fetchOptions).getObjects(); - for (Experiment exp : experiments) - { - Node<Experiment> expNode = new Node<Experiment>(exp); - graph.addEdge(prjNode, expNode, new Edge(CONNECTION)); - findSamplesForExperiment(expNode); - findAndAttachDataSetsForExperiment(expNode); - } - } - - private void findSpaceSamples(String spaceCode) + private void addSpaceSamples(String spaceCode) { SampleSearchCriteria criteria = new SampleSearchCriteria(); criteria.withSpace().withCode().thatEquals(spaceCode); criteria.withoutExperiment(); criteria.withAndOperator(); - SampleFetchOptions fetchOptions = new SampleFetchOptions(); - fetchOptions.withProperties(); - fetchOptions.withType(); - fetchOptions.withExperiment(); - fetchOptions.withSpace(); - fetchOptions.withAttachments(); + List<Sample> samples = v3Api.searchSamples(sessionToken, criteria, createSampleFetchOptions()).getObjects(); - List<Sample> samples = v3Api.searchSamples(sessionToken, criteria, fetchOptions).getObjects(); for (Sample sample : samples) { Node<Sample> sampleNode = new Node<Sample>(sample); graph.addNode(sampleNode); - findChildAndComponentSamples(sampleNode); - findAndAttachDataSets(sampleNode); + addChildAndComponentSamples(sampleNode); + addDataSetsForSample(sampleNode); } } - private void findSamplesForExperiment(Node<Experiment> expNode) + private void addExperiments(Node<Project> prjNode) { - SampleSearchCriteria criteria = new SampleSearchCriteria(); - criteria.withExperiment().withId().thatEquals(expNode.getEntity().getPermId()); - - SampleFetchOptions fetchOptions = new SampleFetchOptions(); - fetchOptions.withProperties(); - fetchOptions.withDataSets(); - fetchOptions.withType(); - fetchOptions.withExperiment(); - fetchOptions.withSpace(); - fetchOptions.withAttachments(); + for (Experiment exp : prjNode.getEntity().getExperiments()) + { + Node<Experiment> expNode = new Node<Experiment>(exp); + graph.addEdge(prjNode, expNode, new Edge(CONNECTION)); + addSamplesForExperiment(expNode); + addDataSetsForExperiment(expNode); + } + } - List<Sample> samples = v3Api.searchSamples(sessionToken, criteria, fetchOptions).getObjects(); - for (Sample sample : samples) + private void addSamplesForExperiment(Node<Experiment> expNode) + { + for (Sample sample : expNode.getEntity().getSamples()) { Node<Sample> sampleNode = new Node<Sample>(sample); graph.addEdge(expNode, sampleNode, new Edge(CONNECTION)); - findAndAttachDataSets(sampleNode); - findChildAndComponentSamples(sampleNode); + addDataSetsForSample(sampleNode); + addChildAndComponentSamples(sampleNode); } } - private void findAndAttachDataSetsForExperiment(Node<Experiment> expNode) + private void addDataSetsForExperiment(Node<Experiment> expNode) { - DataSetSearchCriteria dsCriteria = new DataSetSearchCriteria(); - dsCriteria.withExperiment().withId().thatEquals(expNode.getEntity().getIdentifier()); - - DataSetFetchOptions dsFetchOptions = new DataSetFetchOptions(); - dsFetchOptions.withType(); - dsFetchOptions.withSample(); - dsFetchOptions.withExperiment(); - dsFetchOptions.withProperties(); - - List<DataSet> dataSets = v3Api.searchDataSets(sessionToken, dsCriteria, dsFetchOptions).getObjects(); - for (DataSet dataSet : dataSets) + for (DataSet dataSet : expNode.getEntity().getDataSets()) { Node<DataSet> dataSetNode = new Node<DataSet>(dataSet); graph.addEdge(expNode, dataSetNode, new Edge(CONNECTION)); - findChildAndContainedDataSets(dataSetNode); + addChildAndContainedDataSets(dataSetNode); } } - private void findAndAttachDataSets(Node<Sample> sampleNode) + private void addDataSetsForSample(Node<Sample> sampleNode) { - DataSetSearchCriteria dsCriteria = new DataSetSearchCriteria(); - dsCriteria.withSample().withId().thatEquals(sampleNode.getEntity().getIdentifier()); - - DataSetFetchOptions dsFetchOptions = new DataSetFetchOptions(); - dsFetchOptions.withType(); - dsFetchOptions.withSample(); - dsFetchOptions.withExperiment(); - dsFetchOptions.withProperties(); - - List<DataSet> dataSets = v3Api.searchDataSets(sessionToken, dsCriteria, dsFetchOptions).getObjects(); - for (DataSet dataSet : dataSets) + for (DataSet dataSet : sampleNode.getEntity().getDataSets()) { Node<DataSet> dataSetNode = new Node<DataSet>(dataSet); graph.addEdge(sampleNode, dataSetNode, new Edge(CONNECTION)); - findChildAndContainedDataSets(dataSetNode); + addChildAndContainedDataSets(dataSetNode); } } - private void findChildAndComponentSamples(Node<Sample> sampleNode) + private void addChildAndComponentSamples(Node<Sample> sampleNode) { - SampleFetchOptions fetchOptions = new SampleFetchOptions(); - fetchOptions.withProperties(); - fetchOptions.withType(); - fetchOptions.withDataSets(); - fetchOptions.withExperiment(); - fetchOptions.withSpace(); - fetchOptions.withAttachments(); - - // first find the children + // first add the children if (graph.isVisitedAsParent(sampleNode.getIdentifier()) == false) { graph.markAsVisitedAsParent(sampleNode.getIdentifier()); - findChildSamples(sampleNode, fetchOptions); + addChildSamples(sampleNode); } - // then find contained samples + // then add contained samples if (graph.isVisitedAsContainer(sampleNode.getIdentifier()) == false) { graph.markAsVisitedAsContainer(sampleNode.getIdentifier()); - findComponentSamples(sampleNode, fetchOptions); + addComponentSamples(sampleNode); } } - private void findComponentSamples(Node<Sample> sampleNode, SampleFetchOptions fetchOptions) + private void addComponentSamples(Node<Sample> sampleNode) { - SampleSearchCriteria criteria = new SampleSearchCriteria(); - criteria.withContainer().withId().thatEquals(sampleNode.getEntity().getPermId()); - List<Sample> components = v3Api.searchSamples(sessionToken, criteria, fetchOptions).getObjects(); - for (Sample sample : components) + for (Sample sample : sampleNode.getEntity().getComponents()) { Node<Sample> subSampleNode = new Node<Sample>(sample); graph.addEdge(sampleNode, subSampleNode, new Edge(COMPONENT)); - findAndAttachDataSets(subSampleNode); - findChildAndComponentSamples(subSampleNode); + addDataSetsForSample(subSampleNode); + addChildAndComponentSamples(subSampleNode); } } - private void findChildSamples(Node<Sample> sampleNode, SampleFetchOptions fetchOptions) + private void addChildSamples(Node<Sample> sampleNode) { - SampleSearchCriteria criteria = new SampleSearchCriteria(); - criteria.withParents().withId().thatEquals(sampleNode.getEntity().getPermId()); - List<Sample> children = v3Api.searchSamples(sessionToken, criteria, fetchOptions).getObjects(); - for (Sample sample : children) + for (Sample sample : sampleNode.getEntity().getChildren()) { Node<Sample> subSampleNode = new Node<Sample>(sample); graph.addEdge(sampleNode, subSampleNode, new Edge(CHILD)); - - findAndAttachDataSets(subSampleNode); - findChildAndComponentSamples(subSampleNode); + + addDataSetsForSample(subSampleNode); + addChildAndComponentSamples(subSampleNode); } } - private void findChildAndContainedDataSets(Node<DataSet> dsNode) + private void addChildAndContainedDataSets(Node<DataSet> dsNode) { - DataSetFetchOptions dsFetchOptions = new DataSetFetchOptions(); - dsFetchOptions.withType(); - dsFetchOptions.withSample(); - dsFetchOptions.withExperiment(); - dsFetchOptions.withProperties(); - - // first find the children + // first add the children if (graph.isVisitedAsParent(dsNode.getIdentifier()) == false) { graph.markAsVisitedAsParent(dsNode.getIdentifier()); - findChildDataSets(dsNode, dsFetchOptions); + addChildDataSets(dsNode); } - // then find contained data sets + // then add contained data sets if (graph.isVisitedAsContainer(dsNode.getIdentifier()) == false) { graph.markAsVisitedAsContainer(dsNode.getIdentifier()); - findComponentDataSets(dsNode, dsFetchOptions); + addComponentDataSets(dsNode); } } - private void findComponentDataSets(Node<DataSet> dsNode, DataSetFetchOptions dsFetchOptions) + private void addComponentDataSets(Node<DataSet> dsNode) { - DataSetSearchCriteria criteria = new DataSetSearchCriteria(); - criteria.withContainer().withId().thatEquals(dsNode.getEntity().getPermId()); - List<DataSet> components = v3Api.searchDataSets(sessionToken, criteria, dsFetchOptions).getObjects(); - for (DataSet ds : components) + for (DataSet ds : dsNode.getEntity().getComponents()) { Node<DataSet> containedDsNode = new Node<DataSet>(ds); graph.addEdge(dsNode, containedDsNode, new Edge(COMPONENT)); - findChildAndContainedDataSets(containedDsNode); + addChildAndContainedDataSets(containedDsNode); } } - private void findChildDataSets(Node<DataSet> dsNode, DataSetFetchOptions dsFetchOptions) + private void addChildDataSets(Node<DataSet> dsNode) { - DataSetSearchCriteria criteria = new DataSetSearchCriteria(); - criteria.withParents().withId().thatEquals(dsNode.getEntity().getPermId()); - List<DataSet> children = v3Api.searchDataSets(sessionToken, criteria, dsFetchOptions).getObjects(); - for (DataSet ds : children) + for (DataSet ds : dsNode.getEntity().getChildren()) { Node<DataSet> childDsNode = new Node<DataSet>(ds); graph.addEdge(dsNode, childDsNode, new Edge(CHILD)); - findChildAndContainedDataSets(childDsNode); + addChildAndContainedDataSets(childDsNode); } } @@ -394,7 +310,7 @@ public class EntityRetriever implements IEntityRetriever final MaterialFetchOptions fetchOptions = new MaterialFetchOptions(); fetchOptions.withType(); fetchOptions.withProperties(); - + SearchResult<Material> searchResult = v3Api.searchMaterials(sessionToken, criteria, fetchOptions); @@ -416,4 +332,53 @@ public class EntityRetriever implements IEntityRetriever } return codes; } + + private ProjectFetchOptions createProjectFetchOptions() + { + ProjectFetchOptions fo = new ProjectFetchOptions(); + fo.withSpace(); + fo.withAttachments(); + fo.withExperimentsUsing(createExperimentFetchOptions()); + return fo; + } + + private ExperimentFetchOptions createExperimentFetchOptions() + { + ExperimentFetchOptions fo = new ExperimentFetchOptions(); + fo.withProperties(); + fo.withProject().withSpace(); + fo.withType(); + fo.withAttachments(); + fo.withSamplesUsing(createSampleFetchOptions()); + fo.withDataSetsUsing(createDataSetFetchOptions()); + return fo; + } + + private SampleFetchOptions createSampleFetchOptions() + { + SampleFetchOptions fo = new SampleFetchOptions(); + fo.withProperties(); + fo.withDataSets(); + fo.withType(); + fo.withExperiment(); + fo.withSpace(); + fo.withAttachments(); + fo.withChildrenUsing(fo); + fo.withComponentsUsing(fo); + fo.withDataSetsUsing(createDataSetFetchOptions()); + return fo; + } + + private DataSetFetchOptions createDataSetFetchOptions() + { + DataSetFetchOptions fo = new DataSetFetchOptions(); + fo.withType(); + fo.withSample(); + fo.withExperiment(); + fo.withProperties(); + fo.withChildrenUsing(fo); + fo.withComponentsUsing(fo); + return fo; + } + } \ No newline at end of file -- GitLab