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);

Reply via email to