This is an automated email from the ASF dual-hosted git repository.
pdesai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openwhisk-devtools.git
The following commit(s) were added to refs/heads/master by this push:
new b37cd0f Allow multiple inits of java runtime to enable cache priming
(#289)
b37cd0f is described below
commit b37cd0f5ffaaf6e4d386c82244a7c402b705e915
Author: Matt Rutkowski <[email protected]>
AuthorDate: Fri Sep 13 16:12:41 2019 -0500
Allow multiple inits of java runtime to enable cache priming (#289)
---
knative-build/runtimes/java/WhiskSim/.classpath | 2 +-
.../java/core/java8/proxy/compileClassCache.sh | 2 ++
.../java8/proxy/profiles/base/tests/exec_tests.sh | 33 ++++++++++++++++++
.../tests/helloworld/native-data-init-run.json | 18 ++++++++++
.../helloworldwithparams/native-data-init-run.json | 20 +++++++++++
.../native-data-init-run.json | 20 +++++++++++
.../proxy/profiles/base/tests/test-list-all.txt | 3 --
.../openwhisk/runtime/java/action/Debug.java | 15 ++++++---
.../openwhisk/runtime/java/action/JarLoader.java | 22 ++++++++++--
.../openwhisk/runtime/java/action/Proxy.java | 39 ++++++++++++++++++----
10 files changed, 157 insertions(+), 17 deletions(-)
diff --git a/knative-build/runtimes/java/WhiskSim/.classpath
b/knative-build/runtimes/java/WhiskSim/.classpath
index f0257c5..71f5fef 100644
--- a/knative-build/runtimes/java/WhiskSim/.classpath
+++ b/knative-build/runtimes/java/WhiskSim/.classpath
@@ -13,7 +13,7 @@
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
- <classpathentry kind="con"
path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+ <classpathentry kind="con"
path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
diff --git a/knative-build/runtimes/java/core/java8/proxy/compileClassCache.sh
b/knative-build/runtimes/java/core/java8/proxy/compileClassCache.sh
index 503adfc..5ecc9b0 100755
--- a/knative-build/runtimes/java/core/java8/proxy/compileClassCache.sh
+++ b/knative-build/runtimes/java/core/java8/proxy/compileClassCache.sh
@@ -40,6 +40,8 @@
JAVA_EXTENDED_OPTIONS="-Xshareclasses:cacheDir=/javaSharedCache/ -Xquickstart"
JAVA_VERBOSE_OPTIONS="-verbose:class -verbose:sizes"
JAVA_JVM_KILL_DELAY=5s
+export OW_ALLOW_MULTIPLE_INIT=true
+
echo "Creating shared class cache with Proxy and 'base' profile libraries..."
java $JAVA_VERBOSE_OPTIONS $JAVA_STANDARD_OPTIONS $JAVA_EXTENDED_OPTIONS
"-jar" "/javaAction/build/libs/javaAction-all.jar" &
HTTP_PID=$!
diff --git
a/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/exec_tests.sh
b/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/exec_tests.sh
new file mode 100755
index 0000000..5db373a
--- /dev/null
+++
b/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/exec_tests.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+#
+# 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.
+#
+set +x
+
+for f in *; do
+ # if the file is a directory
+ if [ -d ${f} ]; then
+ echo "Updating 'code' payload with base64 encoded archive data: ${f}"
+ cd $f
+ sed "s#BASE64_ENCODED_JAR#$(cat hello.jar.base64)#"
openwhisk-data-init.json.tmpl > openwhisk-data-init.json
+ sed "s#BASE64_ENCODED_JAR#$(cat hello.jar.base64)#"
knative-data-init.json.tmpl > knative-data-init.json
+ sed "s#BASE64_ENCODED_JAR#$(cat hello.jar.base64)#"
knative-data-init-run.json.tmpl > native-data-init-run.json
+ sed "s#BASE64_ENCODED_JAR#$(cat hello.jar.base64)#"
payload-knative-init.http.tmpl > payload-knative-init.http
+ sed "s#BASE64_ENCODED_JAR#$(cat hello.jar.base64)#"
payload-knative-init-run.http.tmpl > payload-knative-init-run.http
+ sed "s#BASE64_ENCODED_JAR#$(cat hello.jar.base64)#"
payload-openwhisk-init.http.tmpl > payload-openwhisk-init.http
+ cd ..
+ fi
+done
diff --git
a/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/helloworld/native-data-init-run.json
b/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/helloworld/native-data-init-run.json
new file mode 100644
index 0000000..30282d3
--- /dev/null
+++
b/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/helloworld/native-data-init-run.json
@@ -0,0 +1,18 @@
+{
+ "init": {
+ "name": "java-helloworld",
+ "main": "Hello",
+ "binary": true,
+ "code" :
"UEsDBBQACAgIAA18LU8AAAAAAAAAAAAAAAAJAAQATUVUQS1JTkYv/soAAAMAUEsHCAAAAAACAAAAAAAAAFBLAwQUAAgICAANfC1PAAAAAAAAAAAAAAAAFAAAAE1FVEEtSU5GL01BTklGRVNULk1G803My0xLLS7RDUstKs7Mz7NSMNQz4OVyLkpNLElN0XWqBAlY6BnEGxkYKWi4JudkFhSnKvgXpOZ5WWrycvFyAQBQSwcIMFMkp0EAAABBAAAAUEsDBBQACAgIAA18LU8AAAAAAAAAAAAAAAALAAAASGVsbG8uY2xhc3N9UmtP02AUfg67tHSdzAJD0CHzRjcGVREvjJCIiTFmKMkMiX57t72pxV6WriP6U/wX+mUkkvgD/E3GeN7GaYKDJj2X9znnec572h+/vn0H8ABNAxYqOpZ1XDegYUWZqoEbuKnhlkoYvK3hjgFDhavK2zpqytcVvqahoWGdkN
[...]
+ },
+ "activation": {
+ "namespace": "default",
+ "action_name": "java-helloworld",
+ "api_host": "",
+ "api_key": "",
+ "activation_id": "",
+ "deadline": "4102498800000"
+ },
+ "value": {
+ }
+}
diff --git
a/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/helloworldwithparams/native-data-init-run.json
b/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/helloworldwithparams/native-data-init-run.json
new file mode 100644
index 0000000..752b692
--- /dev/null
+++
b/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/helloworldwithparams/native-data-init-run.json
@@ -0,0 +1,20 @@
+{
+ "init": {
+ "name" : "java-helloworld-with-params",
+ "main" : "Hello",
+ "binary": true,
+ "code" :
"UEsDBBQACAgIAA18LU8AAAAAAAAAAAAAAAAJAAQATUVUQS1JTkYv/soAAAMAUEsHCAAAAAACAAAAAAAAAFBLAwQUAAgICAANfC1PAAAAAAAAAAAAAAAAFAAAAE1FVEEtSU5GL01BTklGRVNULk1G803My0xLLS7RDUstKs7Mz7NSMNQz4OVyLkpNLElN0XWqBAlY6BnEGxkYKWi4JudkFhSnKvgXpOZ5WWrycvFyAQBQSwcIMFMkp0EAAABBAAAAUEsDBBQACAgIAA18LU8AAAAAAAAAAAAAAAALAAAASGVsbG8uY2xhc3N9Uu1uEkEUPcPXLssiuG2t1KJQtQUKRW39KrW1mhhjoDbBNFHjjwHG7db9IMtS46P4BP7VPzSxiQ/gO2m8s4omlXZn986dO2fPOXMz339+/QZgDdsaZlBQUVSxoOKqhiSuyXBdwyKWVJQUlOWaIBUFyxp0mVblXFOxoq
[...]
+ },
+ "activation": {
+ "namespace": "default",
+ "action_name": "java-helloworld-with-params",
+ "api_host": "",
+ "api_key": "",
+ "activation_id": "",
+ "deadline": "4102498800000"
+ },
+ "value": {
+ "name" : "Joe",
+ "place" : "TX"
+ }
+}
diff --git
a/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/helloworldwithparamsfromenv/native-data-init-run.json
b/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/helloworldwithparamsfromenv/native-data-init-run.json
new file mode 100644
index 0000000..ca94e97
--- /dev/null
+++
b/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/helloworldwithparamsfromenv/native-data-init-run.json
@@ -0,0 +1,20 @@
+{
+ "init": {
+ "name" : "java-helloworld-with-params-from-env",
+ "main" : "Hello",
+ "binary": true,
+ "code" :
"UEsDBBQACAgIAA58LU8AAAAAAAAAAAAAAAAJAAQATUVUQS1JTkYv/soAAAMAUEsHCAAAAAACAAAAAAAAAFBLAwQUAAgICAAOfC1PAAAAAAAAAAAAAAAAFAAAAE1FVEEtSU5GL01BTklGRVNULk1G803My0xLLS7RDUstKs7Mz7NSMNQz4OVyLkpNLElN0XWqBAlY6BnEGxkYKWi4JudkFhSnKvgXpOZ5WWrycvFyAQBQSwcIMFMkp0EAAABBAAAAUEsDBBQACAgIAA58LU8AAAAAAAAAAAAAAAALAAAASGVsbG8uY2xhc3ONUttu00AUnNMmsesaWtzQGxQSLq3TNjW3Jwo8gIQQCgUpqBKPm/hgubJ3I9ep1L+ClxRRiQ/goxBnQ7kIAsKWZ2dnz5lZ2/v5y8dPAO7hrocLWHVxycNlrLm44uCqh6qVGg6aHlxLr9nxuosbLm5aum5LNhyEDlqE2o
[...]
+ },
+ "activation": {
+ "namespace": "default",
+ "action_name": "java-helloworld-with-params-from-env",
+ "api_host": "",
+ "api_key": "",
+ "activation_id": "",
+ "deadline": "4102498800000"
+ },
+ "value": {
+ "name" : "Jess",
+ "place" : "OK"
+ }
+}
diff --git
a/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/test-list-all.txt
b/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/test-list-all.txt
deleted file mode 100644
index ea8521b..0000000
---
a/knative-build/runtimes/java/core/java8/proxy/profiles/base/tests/test-list-all.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-helloworld
-helloworldwithparams
-helloworldwithparamsfromenv
diff --git
a/knative-build/runtimes/java/core/java8/proxy/src/main/java/org/apache/openwhisk/runtime/java/action/Debug.java
b/knative-build/runtimes/java/core/java8/proxy/src/main/java/org/apache/openwhisk/runtime/java/action/Debug.java
index e32afc9..287107a 100644
---
a/knative-build/runtimes/java/core/java8/proxy/src/main/java/org/apache/openwhisk/runtime/java/action/Debug.java
+++
b/knative-build/runtimes/java/core/java8/proxy/src/main/java/org/apache/openwhisk/runtime/java/action/Debug.java
@@ -16,7 +16,7 @@
*/
package org.apache.openwhisk.runtime.java.action;
-import java.time.*;
+import java.util.Map;
public class Debug {
@@ -50,8 +50,6 @@ public class Debug {
private static String FQ_METHOD = "";
private static String METHOD = "";
private static long currentTime = 0;
- //private static long startTime = 0;
- //private static long stopTime = 0;
private static long updateContext(){
currentTime = System.nanoTime();
@@ -99,11 +97,20 @@ public class Debug {
public static long end() { return end("",-1);}
public static long end(long startTime) { return end("", startTime);}
- public static long end(String msg, long startTime){
+ public static long end(String msg, long startTime) {
currentTime = updateContext();
String formattedMsg = formatMessage(functionEndMarker, msg, startTime);
System.out.println(formattedMsg);
return currentTime;
}
+ public static void printEnv() {
+ Map<String, String> envVars = System.getenv();
+ long ts = System.nanoTime();
+ System.out.printf("%sEnvironment Variables (%d):%s\n", prefixFGColor,
ts, bodyFGColor);
+ for (String key : envVars.keySet()) {
+ System.out.printf(">> %s=\"%s\"%n", key, envVars.get(key));
+ }
+ }
+
}
diff --git
a/knative-build/runtimes/java/core/java8/proxy/src/main/java/org/apache/openwhisk/runtime/java/action/JarLoader.java
b/knative-build/runtimes/java/core/java8/proxy/src/main/java/org/apache/openwhisk/runtime/java/action/JarLoader.java
index 03f7c90..21f4afb 100644
---
a/knative-build/runtimes/java/core/java8/proxy/src/main/java/org/apache/openwhisk/runtime/java/action/JarLoader.java
+++
b/knative-build/runtimes/java/core/java8/proxy/src/main/java/org/apache/openwhisk/runtime/java/action/JarLoader.java
@@ -35,8 +35,8 @@ import java.util.Map;
import com.google.gson.JsonObject;
public class JarLoader extends URLClassLoader {
- private final Class<?> mainClass;
- private final Method mainMethod;
+ private Class<?> mainClass = null;
+ private Method mainMethod = null;
public static Path saveBase64EncodedFile(InputStream encoded) throws
Exception {
Base64.Decoder decoder = Base64.getDecoder();
@@ -55,7 +55,10 @@ public class JarLoader extends URLClassLoader {
public JarLoader(Path jarPath, String entrypoint)
throws MalformedURLException, ClassNotFoundException,
NoSuchMethodException, SecurityException {
super(new URL[] { jarPath.toUri().toURL() });
+ loadMainClassAndMethod(entrypoint);
+ }
+ public void loadMainClassAndMethod(String entrypoint) throws
NoSuchMethodException, ClassNotFoundException {
final String[] splittedEntrypoint = entrypoint.split("#");
final String entrypointClassName = splittedEntrypoint[0];
final String entrypointMethodName = splittedEntrypoint.length > 1 ?
splittedEntrypoint[1] : "main";
@@ -69,7 +72,20 @@ public class JarLoader extends URLClassLoader {
throw new NoSuchMethodException("main");
}
- this.mainMethod = m;
+ mainMethod = m;
+ }
+
+ public void addJAR(Path jarPath) throws MalformedURLException {
+ if(jarPath!=null){
+ try{
+ this.addURL(jarPath.toUri().toURL());
+ } catch (MalformedURLException e){
+ System.err.format("Invalid JAR file path. [%s]", jarPath);
+ throw e;
+ }
+ } else {
+ System.err.format("Invalid JAR file path. [%s]", jarPath);
+ }
}
public JsonObject invokeMain(JsonObject arg, Map<String, String> env)
throws Exception {
diff --git
a/knative-build/runtimes/java/core/java8/proxy/src/main/java/org/apache/openwhisk/runtime/java/action/Proxy.java
b/knative-build/runtimes/java/core/java8/proxy/src/main/java/org/apache/openwhisk/runtime/java/action/Proxy.java
index cad2845..91b5c94 100644
---
a/knative-build/runtimes/java/core/java8/proxy/src/main/java/org/apache/openwhisk/runtime/java/action/Proxy.java
+++
b/knative-build/runtimes/java/core/java8/proxy/src/main/java/org/apache/openwhisk/runtime/java/action/Proxy.java
@@ -41,16 +41,35 @@ import com.sun.net.httpserver.HttpServer;
public class Proxy {
private HttpServer server;
private JarLoader loader = null;
+ private boolean allowMultipleInits = false;
public Proxy(int port) throws IOException {
long startTime = Debug.start();
+ Debug.printEnv();
this.server = HttpServer.create(new InetSocketAddress(port), -1);
this.server.createContext("/init", new InitHandler());
this.server.createContext("/run", new RunHandler());
this.server.setExecutor(null); // creates a default executor
+
+ // Default is false; used primarily for establishing boot shared class
cache
+ checkMultipleInitEnabled();
+
Debug.end(startTime);
}
+ private void checkMultipleInitEnabled() {
+ String strMultipleInit = System.getenv("OW_ALLOW_MULTIPLE_INIT");
+ System.out.printf("OW_ALLOW_MULTIPLE_INIT=%s\n", strMultipleInit);
+
+ // Determine if we allow multiple "init" calls (i.e., Java container
reuse); default:false
+ if(strMultipleInit!=null)
+ this.allowMultipleInits = Boolean.parseBoolean(strMultipleInit);
+
+ if(this.allowMultipleInits){
+ System.out.println("Multiple '/init' allowed.");
+ }
+ }
+
public void start() {
server.start();
}
@@ -79,7 +98,8 @@ public class Proxy {
private class InitHandler implements HttpHandler {
public void handle(HttpExchange t) throws IOException {
long startTime = Debug.start();
- if (loader != null) {
+
+ if (loader != null && !allowMultipleInits) {
String errorMessage = "Cannot initialize the action more than
once.";
System.err.println(errorMessage);
Proxy.writeError(t, errorMessage);
@@ -108,7 +128,12 @@ public class Proxy {
// Start up the custom classloader. This also checks
that the
// main method exists.
- loader = new JarLoader(jarPath, mainClass);
+ if( loader == null)
+ loader = new JarLoader(jarPath, mainClass);
+ else {
+ loader.addJAR(jarPath);
+ loader.loadMainClassAndMethod(mainClass);
+ }
Proxy.writeResponse(t, 200, "OK");
return;
@@ -151,7 +176,8 @@ public class Proxy {
for(Map.Entry<String, JsonElement> entry : entrySet){
try {
if(!entry.getKey().equalsIgnoreCase("value"))
- env.put(String.format("__OW_%s",
entry.getKey().toUpperCase()), entry.getValue().getAsString());
+ env.put(String.format("__OW_%s",
entry.getKey().toUpperCase()),
+ entry.getValue().getAsString());
} catch (Exception e) {}
}
@@ -169,12 +195,13 @@ public class Proxy {
Proxy.writeResponse(t, 200, output.toString());
return;
} catch (InvocationTargetException ite) {
- // These are exceptions from the action, wrapped in ite because
- // of reflection
+ // When you invoke a method using reflection (as we do for the
Action function)
+ // and it throws an exception, you must check for it using
InvocationTargetException as follows:
Throwable underlying = ite.getCause();
underlying.printStackTrace(System.err);
Proxy.writeError(t,
- "An error has occured while invoking the action (see
logs for details): " + underlying);
+ "An error has occurred while invoking the action (see
logs for details): "
+ + underlying);
} catch (Exception e) {
e.printStackTrace(System.err);
Proxy.writeError(t, "An error has occurred (see logs for
details): " + e);