diff --git a/README.md b/README.md
index 044f00a63..9770cb2ca 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,16 @@
+# AWS Lambda Libs on CRaC
+
+This is a version of the original AWS Lambda Libraries with CRaC support added.
+
+To use, add next to the pom.xml:
+```
+
+ io.github.crac.com.amazonaws
+ aws-lambda-java-runtime-interface-client
+ 2.2.0
+
+```
+
# AWS Lambda Java Support Libraries
Key libraries for running Java on the AWS Lambda platform.
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index 8de738de6..f4742283e 100644
--- a/aws-lambda-java-runtime-interface-client/pom.xml
+++ b/aws-lambda-java-runtime-interface-client/pom.xml
@@ -2,7 +2,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0
- com.amazonaws
+ io.github.crac.com.amazonaws
aws-lambda-java-runtime-interface-client
2.2.0
jar
@@ -20,9 +20,15 @@
- https://github.com/aws/aws-lambda-java-libs.git
+ http://github.com/CRaC/aws-lambda-java-libs/tree/master
+
+ antonkozlov
+ Anton Kozlov
+ https://github.com/AntonKozlov
+ akozlov@azul.com
+
AWS Lambda team
Amazon Web Services
@@ -53,6 +59,11 @@
aws-lambda-java-core
1.2.2
+
+ io.github.crac
+ org-crac
+ 0.1.0
+
com.amazonaws
aws-lambda-java-serialization
@@ -258,8 +269,8 @@
1.6.3
true
- sonatype-nexus-staging
- https://aws.oss.sonatype.org/
+ ossrh
+ https://s01.oss.sonatype.org/
false
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeClient.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeClient.java
index 05aa50a1b..b623bdb91 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeClient.java
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeClient.java
@@ -38,11 +38,11 @@ public LambdaRuntimeClient(String hostnamePort) {
}
public InvocationRequest waitForNextInvocation() {
- return NativeClient.next();
+ return NativeClient.nextWrapper();
}
public void postInvocationResponse(String requestId, byte[] response) {
- NativeClient.postInvocationResponse(requestId.getBytes(UTF_8), response);
+ NativeClient.postInvocationResponseWrapper(requestId.getBytes(UTF_8), response);
}
public void postInvocationError(String requestId, byte[] errorResponse, String errorType) throws IOException {
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java
index a9592e1a8..3a6378170 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java
@@ -2,8 +2,13 @@
package com.amazonaws.services.lambda.runtime.api.client.runtimeapi;
+import org.crac.Context;
+import org.crac.Resource;
+
import java.io.InputStream;
+import java.lang.annotation.Native;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
@@ -22,10 +27,67 @@ class NativeClient {
"aws-lambda-runtime-interface-client.musl.so",
};
private static final Throwable[] exceptions = new Throwable[libsToTry.length];
+
+ static class CheckpointState implements Resource {
+ enum State {
+ WORKING,
+ SYNCING,
+ SYNCED,
+ };
+
+ State state = State.WORKING;
+
+ private void waitFor(State targetState) {
+ while (state != targetState) {
+ try {
+ this.wait();
+ } catch (InterruptedException interruptedException) {
+ }
+ }
+ }
+
+ @Override
+ public synchronized void beforeCheckpoint(Context extends Resource> context) throws Exception {
+ state = State.SYNCING;
+ waitFor(State.SYNCED);
+ deinitializeClient();
+ }
+
+ @Override
+ public synchronized void afterRestore(Context extends Resource> context) throws Exception {
+ initializeNativeClient();
+ state = State.WORKING;
+ this.notifyAll();
+ }
+
+ public synchronized void syncPoint() {
+ if (state == State.SYNCING) {
+ state = State.SYNCED;
+ this.notifyAll();
+ }
+ waitFor(State.WORKING);
+ }
+ }
+
+ static CheckpointState checkpointState = new CheckpointState();
static {
- boolean loaded = false;
- for (int i = 0; !loaded && i < libsToTry.length; ++i) {
- try (InputStream lib = NativeClient.class.getResourceAsStream(
+ boolean loaded = false;
+ String basestr = System.getProperty("com.amazonaws.services.lambda.runtime.api.client.NativeClient.libsBase", "/");
+ Path base = Paths.get(basestr);
+ for (int i = 0; !loaded && i < libsToTry.length; ++i) {
+ Path p = base.resolve(libsToTry[i]);
+ if (Files.exists(p)) {
+ try {
+ System.load(p.toString());
+ loaded = true;
+ } catch (UnsatisfiedLinkError e) {
+ exceptions[i] = e;
+ } catch (Exception e) {
+ exceptions[i] = e;
+ }
+ }
+ if (!loaded && exceptions[i] == null) {
+ try (InputStream lib = NativeClient.class.getResourceAsStream("/" +
Paths.get(architecturePathSuffix, libsToTry[i]).toString())) {
Files.copy(lib, Paths.get(nativeLibPath), StandardCopyOption.REPLACE_EXISTING);
System.load(nativeLibPath);
@@ -36,17 +98,25 @@ class NativeClient {
exceptions[i] = e;
}
}
- if (!loaded) {
- for (int i = 0; i < libsToTry.length; ++i) {
- System.err.printf("Failed to load the native runtime interface client library %s. Exception: %s\n", libsToTry[i], exceptions[i].getMessage());
- }
- System.exit(-1);
+ }
+
+ if (!loaded) {
+ for (int i = 0; i < libsToTry.length; ++i) {
+ System.err.print(exceptions[i]);
+ System.err.printf("Failed to load the native runtime interface client library %s. Exception: %s\n", libsToTry[i], exceptions[i].getMessage());
}
- String userAgent = String.format(
- "aws-lambda-java/%s-%s" ,
- System.getProperty("java.vendor.version"),
- NativeClient.class.getPackage().getImplementationVersion());
- initializeClient(userAgent.getBytes());
+ System.exit(-1);
+ }
+ initializeNativeClient();
+ org.crac.Core.getGlobalContext().register(checkpointState);
+ }
+
+ private static void initializeNativeClient() {
+ String userAgent = String.format(
+ "aws-lambda-java/%s-%s" ,
+ System.getProperty("java.vendor.version"),
+ NativeClient.class.getPackage().getImplementationVersion());
+ initializeClient(userAgent.getBytes());
}
/**
@@ -67,7 +137,18 @@ static String getArchIdentifier() {
static native void initializeClient(byte[] userAgent);
- static native InvocationRequest next();
+ private static native InvocationRequest next();
+
+ static InvocationRequest nextWrapper() {
+ return next();
+ }
+
+ private static native void postInvocationResponse(byte[] requestId, byte[] response);
+
+ static void postInvocationResponseWrapper(byte[] requestId, byte[] response) {
+ postInvocationResponse(requestId, response);
+ checkpointState.syncPoint();
+ }
- static native void postInvocationResponse(byte[] requestId, byte[] response);
+ static native void deinitializeClient();
}
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp
index 87fa9f028..240a8a795 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp
@@ -149,3 +149,9 @@ JNIEXPORT void JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_run
throwLambdaRuntimeClientException(env, errorMessage, outcome.get_failure());
}
}
+
+JNIEXPORT void JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient_deinitializeClient(JNIEnv *env, jobject thisObject) {
+ delete CLIENT;
+ CLIENT = NULL;
+}
+
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h
index 28a6f444a..47d1265df 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h
@@ -15,6 +15,9 @@ JNIEXPORT jobject JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_
JNIEXPORT void JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient_postInvocationResponse
(JNIEnv *, jobject, jbyteArray, jbyteArray);
+JNIEXPORT void JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient_deinitializeClient
+ (JNIEnv *, jobject);
+
#ifdef __cplusplus
}
#endif