You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2018/08/31 23:46:43 UTC
[isis] 01/06: ISIS-1974: introspects in parallel
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch maint-1.16.2
in repository https://gitbox.apache.org/repos/asf/isis.git
commit b3eb20c97ab14bf8951018149b7cc71ba0533c73
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Sun Aug 26 23:31:04 2018 +0100
ISIS-1974: introspects in parallel
---
.../metamodel/specloader/SpecificationLoader.java | 83 +++++++++++++++++++---
.../specimpl/dflt/ObjectSpecificationDefault.java | 1 -
.../core/runtime/threadpool/ThreadPoolSupport.java | 47 ++++++++++--
.../dflt/ProgrammingModelForObjectSpecIdFacet.java | 45 ++++++++++++
.../system/session/IsisSessionFactoryBuilder.java | 3 +-
5 files changed, 161 insertions(+), 18 deletions(-)
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
index ca81150..81f39e8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
@@ -20,7 +20,10 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Properties;
import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
@@ -40,6 +43,7 @@ import org.apache.isis.core.commons.exceptions.IsisException;
import org.apache.isis.core.commons.lang.ClassUtil;
import org.apache.isis.core.metamodel.facetapi.Facet;
import org.apache.isis.core.metamodel.facets.FacetFactory;
+import org.apache.isis.core.metamodel.facets.MethodRemoverConstants;
import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacet;
import org.apache.isis.core.metamodel.facets.object.objectspecid.ObjectSpecIdFacet;
import org.apache.isis.core.metamodel.layoutmetadata.LayoutMetadataReader;
@@ -58,7 +62,9 @@ import org.apache.isis.core.metamodel.specloader.specimpl.dflt.ObjectSpecificati
import org.apache.isis.core.metamodel.specloader.specimpl.standalonelist.ObjectSpecificationOnStandaloneList;
import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidator;
import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
+import org.apache.isis.core.runtime.threadpool.ThreadPoolSupport;
import org.apache.isis.progmodels.dflt.ProgrammingModelFacetsJava5;
+import org.apache.isis.progmodels.dflt.ProgrammingModelForObjectSpecIdFacet;
/**
* Builds the meta-model.
@@ -93,6 +99,8 @@ public class SpecificationLoader implements ApplicationScopedComponent {
private final ProgrammingModel programmingModel;
private final FacetProcessor facetProcessor;
+ FacetProcessor facetProcessorObjectSpecId;
+
private final IsisConfiguration configuration;
private final ServicesInjector servicesInjector;
@@ -101,6 +109,13 @@ public class SpecificationLoader implements ApplicationScopedComponent {
private final List<LayoutMetadataReader> layoutMetadataReaders;
private final PostProcessor postProcessor;
+ enum State {
+ NOT_INITIALIZED,
+ CACHING,
+ INTROSPECTING
+ }
+
+
public SpecificationLoader(
final IsisConfiguration configuration,
final ProgrammingModel programmingModel,
@@ -118,6 +133,8 @@ public class SpecificationLoader implements ApplicationScopedComponent {
this.postProcessor = new PostProcessor(programmingModel, servicesInjector);
this.layoutMetadataReaders = layoutMetadataReaders;
+
+ this.state = State.NOT_INITIALIZED;
}
@Override
@@ -132,7 +149,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
//region > init
- private boolean initialized = false;
+ private State state;
/**
* Initializes and wires up, and primes the cache based on any service
@@ -152,34 +169,78 @@ public class SpecificationLoader implements ApplicationScopedComponent {
}
// initialize subcomponents
- programmingModel.init();
+ this.programmingModel.init();
facetProcessor.init();
+
+ ProgrammingModel programmingModelForObjectSpecId = new ProgrammingModelForObjectSpecIdFacet(configuration);
+ facetProcessorObjectSpecId = new FacetProcessor(programmingModelForObjectSpecId) {
+ @Override
+ public void injectDependenciesInto(final FacetFactory factory) {
+ // no-op... otherwise hit an exception in the other thread, but don't (yet) know why.
+ }
+ };
+ programmingModelForObjectSpecId.init();
+ facetProcessorObjectSpecId.init();
+
postProcessor.init();
metaModelValidator.init(this);
+
+ state = State.CACHING;
+
loadSpecificationsForServices();
loadSpecificationsForMixins();
cacheBySpecId();
- initialized = true;
+ state = State.INTROSPECTING;
+
+ final Collection<ObjectSpecification> objectSpecifications = allSpecifications();
+
+ final List<Callable<Object>> callables = Lists.newArrayList();
+ for (final ObjectSpecification specification : objectSpecifications) {
+ Callable<Object> callable = new Callable<Object>() {
+ @Override
+ public Object call() {
+ introspectIfRequired(specification);
+ return null;
+ }
+ };
+ callables.add(callable);
+ }
+ List<Future<Object>> futures = ThreadPoolSupport.invokeAll(callables);
+ ThreadPoolSupport.joinGatherFailures(futures);
+
}
private void loadSpecificationsForServices() {
- for (final Class<?> serviceClass : allServiceClasses()) {
+ final Properties metadataProperties = new Properties();
+
+ List<Class<?>> classes = allServiceClasses();
+ for (final Class<?> serviceClass : classes) {
final DomainService domainService = serviceClass.getAnnotation(DomainService.class);
final NatureOfService nature = domainService != null ? domainService.nature() : NatureOfService.DOMAIN;
// will 'markAsService'
- internalLoadSpecification(serviceClass, nature);
+ ObjectSpecification objectSpecification = internalLoadSpecification(serviceClass, nature);
+
+ facetProcessorObjectSpecId.process(
+ serviceClass, metadataProperties,
+ MethodRemoverConstants.NULL, objectSpecification);
}
}
private void loadSpecificationsForMixins() {
+ final Properties metadataProperties = new Properties();
+
final Set<Class<?>> mixinTypes = AppManifest.Registry.instance().getMixinTypes();
if(mixinTypes == null) {
return;
}
for (final Class<?> mixinType : mixinTypes) {
- internalLoadSpecification(mixinType);
+ ObjectSpecification objectSpecification = internalLoadSpecification(mixinType);
+ facetProcessorObjectSpecId.process(
+ mixinType, metadataProperties,
+ MethodRemoverConstants.NULL, objectSpecification);
+
}
}
@@ -196,10 +257,6 @@ public class SpecificationLoader implements ApplicationScopedComponent {
cache.setCacheBySpecId(specById);
}
- @Programmatic
- public boolean isInitialized() {
- return initialized;
- }
//endregion
@@ -210,7 +267,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
public void shutdown() {
LOG.info("shutting down {}", this);
- initialized = false;
+ state = State.NOT_INITIALIZED;
cache.clear();
}
@@ -437,6 +494,10 @@ public class SpecificationLoader implements ApplicationScopedComponent {
*/
private ObjectSpecification introspectIfRequired(final ObjectSpecification spec) {
+ if(state != State.INTROSPECTING) {
+ return spec;
+ }
+
final ObjectSpecificationAbstract specSpi = (ObjectSpecificationAbstract)spec;
final ObjectSpecificationAbstract.IntrospectionState introspectionState = specSpi.getIntrospectionState();
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index 65d2ff3..ca56568 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -103,7 +103,6 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
}
-
//endregion
//region > introspectTypeHierarchyAndMembers
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/runtime/threadpool/ThreadPoolSupport.java b/core/metamodel/src/main/java/org/apache/isis/core/runtime/threadpool/ThreadPoolSupport.java
index 09c9fe7..c131f18 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/runtime/threadpool/ThreadPoolSupport.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/runtime/threadpool/ThreadPoolSupport.java
@@ -26,6 +26,7 @@ import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -50,7 +51,7 @@ public final class ThreadPoolSupport {
final int maximumPoolSize = Runtime.getRuntime().availableProcessors();
final int keepAliveTimeSecs = 5;
- final int queueCapacity = 25;
+ final int queueCapacity = 200;
final BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(queueCapacity);
executor = new ThreadPoolExecutor(
@@ -63,7 +64,14 @@ public final class ThreadPoolSupport {
public Thread newThread(final Runnable r) {
return new Thread(group, r);
}
- });
+ }, new RejectedExecutionHandler() {
+ @Override
+ public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) {
+ int i;
+ i=1;
+
+ }
+ });
}
public static List<Object> join(final List<Future<Object>> futures) {
@@ -75,7 +83,38 @@ public final class ThreadPoolSupport {
try{
final List<Object> returnValues = Lists.newArrayList();
for (Future<Object> future : futures) {
- returnValues.add(join(future));
+ Object result;
+ try {
+ result = future.get();
+ } catch (InterruptedException | ExecutionException e) {
+ // ignore
+ result = null;
+ }
+ returnValues.add(result);
+ }
+ return returnValues;
+ } finally {
+ final long t1 = System.currentTimeMillis();
+ LOG.info("join'ing {} tasks: waited {} milliseconds ", futures.size(), (t1-t0));
+ }
+ }
+
+ public static List<Object> joinGatherFailures(final List<Future<Object>> futures) {
+ if (futures == null) {
+ return null;
+ }
+
+ final long t0 = System.currentTimeMillis();
+ try{
+ final List<Object> returnValues = Lists.newArrayList();
+ for (Future<Object> future : futures) {
+ final Object result;
+ try {
+ result = future.get();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ returnValues.add(result);
}
return returnValues;
} finally {
@@ -89,8 +128,8 @@ public final class ThreadPoolSupport {
return future.get();
} catch (InterruptedException | ExecutionException e) {
// ignore
+ return null;
}
- return null;
}
public static List<Future<Object>> invokeAll(final List<Callable<Object>> callables) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelForObjectSpecIdFacet.java b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelForObjectSpecIdFacet.java
new file mode 100644
index 0000000..61f08a1
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelForObjectSpecIdFacet.java
@@ -0,0 +1,45 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License. */
+
+package org.apache.isis.progmodels.dflt;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.facets.object.objectspecid.classname.ObjectSpecIdFacetDerivedFromClassNameFactory;
+import org.apache.isis.core.metamodel.progmodel.ObjectSpecificationPostProcessor;
+import org.apache.isis.core.metamodel.progmodel.ProgrammingModelAbstract;
+
+public final class ProgrammingModelForObjectSpecIdFacet extends ProgrammingModelAbstract {
+
+ public ProgrammingModelForObjectSpecIdFacet(final IsisConfiguration configuration) {
+ this(DeprecatedPolicy.parse(configuration));
+ }
+
+ public ProgrammingModelForObjectSpecIdFacet(final DeprecatedPolicy deprecatedPolicy) {
+ super(deprecatedPolicy);
+
+ addFactory(new ObjectSpecIdFacetDerivedFromClassNameFactory());
+ }
+
+ @Override
+ public List<ObjectSpecificationPostProcessor> getPostProcessors() {
+ return Collections.emptyList();
+ }
+
+}
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryBuilder.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryBuilder.java
index 72d8ef2..9aa7097 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryBuilder.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryBuilder.java
@@ -221,8 +221,7 @@ public class IsisSessionFactoryBuilder {
}
);
- ThreadPoolSupport.join(futures);
-
+ ThreadPoolSupport.joinGatherFailures(futures);
persistenceSessionFactory.catalogNamedQueries(specificationLoader);