aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteEngine.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteEngine.java')
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteEngine.java134
1 files changed, 134 insertions, 0 deletions
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteEngine.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteEngine.java
new file mode 100644
index 00000000..c088219b
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteEngine.java
@@ -0,0 +1,134 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.rete;
7
8import org.apache.log4j.Logger;
9import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory;
10import org.eclipse.viatra.query.runtime.matchers.context.IQueryBackendContext;
11import org.eclipse.viatra.query.runtime.rete.matcher.ReteEngine;
12import org.eclipse.viatra.query.runtime.rete.matcher.TimelyConfiguration;
13import org.eclipse.viatra.query.runtime.rete.network.Network;
14import org.eclipse.viatra.query.runtime.rete.network.NodeProvisioner;
15import org.eclipse.viatra.query.runtime.rete.network.ReteContainer;
16
17import java.io.IOException;
18import java.lang.invoke.MethodHandle;
19import java.lang.invoke.MethodHandles;
20import java.lang.invoke.MethodType;
21
22public class RefineryReteEngine extends ReteEngine {
23 private static final MethodHandle REFINERY_NODE_FACTORY_CONSTRUCTOR;
24 private static final MethodHandle REFINERY_CONNECTION_FACTORY_CONSTRUCTOR;
25 private static final MethodHandle NETWORK_NODE_FACTORY_SETTER;
26 private static final MethodHandle RETE_CONTAINER_CONNECTION_FACTORY_SETTER;
27 private static final MethodHandle NODE_PROVISIONER_NODE_FACTORY_SETTER;
28 private static final MethodHandle NODE_PROVISIONER_CONNECTION_FACTORY_SETTER;
29
30 static {
31 MethodHandles.Lookup lookup;
32 try {
33 lookup = MethodHandles.privateLookupIn(Network.class, MethodHandles.lookup());
34 } catch (IllegalAccessException e) {
35 throw new IllegalStateException("Cannot create private lookup", e);
36 }
37 var refineryNodeFactoryClass = defineClassFromFile(lookup, "RefineryNodeFactory");
38 var refinaryConnectionFactoryClass = defineClassFromFile(lookup, "RefineryConnectionFactory");
39 try {
40 REFINERY_NODE_FACTORY_CONSTRUCTOR = lookup.findConstructor(refineryNodeFactoryClass,
41 MethodType.methodType(Void.TYPE, Logger.class));
42 REFINERY_CONNECTION_FACTORY_CONSTRUCTOR = lookup.findConstructor(refinaryConnectionFactoryClass,
43 MethodType.methodType(Void.TYPE, ReteContainer.class));
44 } catch (NoSuchMethodException | IllegalAccessException e) {
45 throw new IllegalStateException("Cannot get constructor", e);
46 }
47 var nodeFactoryClass = refineryNodeFactoryClass.getSuperclass();
48 var connectionFactoryClass = refinaryConnectionFactoryClass.getSuperclass();
49 try {
50 NETWORK_NODE_FACTORY_SETTER = lookup.findSetter(Network.class, "nodeFactory", nodeFactoryClass);
51 RETE_CONTAINER_CONNECTION_FACTORY_SETTER = lookup.findSetter(ReteContainer.class, "connectionFactory",
52 connectionFactoryClass);
53 NODE_PROVISIONER_NODE_FACTORY_SETTER = lookup.findSetter(NodeProvisioner.class, "nodeFactory",
54 nodeFactoryClass);
55 NODE_PROVISIONER_CONNECTION_FACTORY_SETTER = lookup.findSetter(NodeProvisioner.class, "connectionFactory",
56 connectionFactoryClass);
57 } catch (NoSuchFieldException | IllegalAccessException e) {
58 throw new IllegalStateException("Cannot get field setter", e);
59 }
60 }
61
62 private static Class<?> defineClassFromFile(MethodHandles.Lookup lookup, String name) {
63 byte[] classBytes;
64 try (var resource = Network.class.getResourceAsStream(name + ".class")) {
65 if (resource == null) {
66 throw new IllegalStateException("Cannot find %s class file".formatted(name));
67 }
68 classBytes = resource.readAllBytes();
69 } catch (IOException e) {
70 throw new IllegalStateException("Cannot read %s class file".formatted(name), e);
71 }
72 Class<?> clazz;
73 try {
74 clazz = lookup.defineClass(classBytes);
75 } catch (IllegalAccessException e) {
76 throw new IllegalStateException("Cannot define %s class".formatted(name), e);
77 }
78 return clazz;
79 }
80
81 public RefineryReteEngine(IQueryBackendContext context, int reteThreads, boolean deleteAndReDeriveEvaluation,
82 TimelyConfiguration timelyConfiguration) {
83 super(context, reteThreads, deleteAndReDeriveEvaluation, timelyConfiguration);
84 installFactories();
85 }
86
87 private void installFactories() {
88 var logger = getLogger();
89 Object nodeFactory;
90 try {
91 nodeFactory = REFINERY_NODE_FACTORY_CONSTRUCTOR.invoke(logger);
92 } catch (Error e) {
93 // Fatal JVM errors should not be wrapped.
94 throw e;
95 } catch (Throwable e) {
96 throw new IllegalStateException("Cannot construct node factory", e);
97 }
98 try {
99 NETWORK_NODE_FACTORY_SETTER.invoke(reteNet, nodeFactory);
100 } catch (Error e) {
101 // Fatal JVM errors should not be wrapped.
102 throw e;
103 } catch (Throwable e) {
104 throw new IllegalStateException("Cannot set factory", e);
105 }
106 for (var container : reteNet.getContainers()) {
107 Object connectionFactory;
108 try {
109 connectionFactory = REFINERY_CONNECTION_FACTORY_CONSTRUCTOR.invoke(container);
110 } catch (Error e) {
111 // Fatal JVM errors should not be wrapped.
112 throw e;
113 } catch (Throwable e) {
114 throw new IllegalStateException("Cannot construct connection factory", e);
115 }
116 var provisioner = container.getProvisioner();
117 try {
118 RETE_CONTAINER_CONNECTION_FACTORY_SETTER.invoke(container, connectionFactory);
119 NODE_PROVISIONER_NODE_FACTORY_SETTER.invoke(provisioner, nodeFactory);
120 NODE_PROVISIONER_CONNECTION_FACTORY_SETTER.invoke(provisioner, connectionFactory);
121 } catch (Error e) {
122 // Fatal JVM errors should not be wrapped.
123 throw e;
124 } catch (Throwable e) {
125 throw new IllegalStateException("Cannot set factory", e);
126 }
127 }
128 }
129
130 @Override
131 public IQueryBackendFactory getFactory() {
132 return RefineryReteBackendFactory.INSTANCE;
133 }
134}