Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add InternalCRIUSupport.getCheckpointRestoreTimeDelta() & tests #15112

Merged
merged 1 commit into from
Jun 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,24 @@
/*[ENDIF] JAVA_SPEC_VERSION >= 17 */
public final class InternalCRIUSupport {
private static boolean criuSupportEnabled = isCRIUSupportEnabledImpl();
private static long checkpointRestoreNanoTimeDelta;

private static native boolean isCRIUSupportEnabledImpl();
private static native boolean isCheckpointAllowedImpl();
private static native long getCheckpointRestoreNanoTimeDeltaImpl();

/**
* Retrieve the elapsed time between Checkpoint and Restore.
* Only support one Checkpoint.
*
* @return the time in nanoseconds.
*/
public static long getCheckpointRestoreNanoTimeDelta() {
if (checkpointRestoreNanoTimeDelta == 0) {
checkpointRestoreNanoTimeDelta = getCheckpointRestoreNanoTimeDeltaImpl();
}
return checkpointRestoreNanoTimeDelta;
}

/**
* Queries if CRIU support is enabled.
Expand Down
6 changes: 0 additions & 6 deletions runtime/criusupport/criusupport.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@

extern "C" {

jboolean JNICALL
Java_openj9_internal_criu_InternalCRIUSupport_isCheckpointAllowedImpl(JNIEnv *env, jclass unused);

jboolean JNICALL
Java_openj9_internal_criu_InternalCRIUSupport_isCRIUSupportEnabledImpl(JNIEnv *env, jclass unused);

JasonFengJ9 marked this conversation as resolved.
Show resolved Hide resolved
void JNICALL
Java_org_eclipse_openj9_criu_CRIUSupport_checkpointJVMImpl(JNIEnv *env, jclass unused, jstring imagesDir, jboolean leaveRunning, jboolean shellJob, jboolean extUnixSupport, jint logLevel, jstring logFile, jboolean fileLocks, jstring workDir, jboolean tcpEstablished, jboolean autoDedup, jboolean trackMemory, jboolean unprivileged);

Expand Down
2 changes: 0 additions & 2 deletions runtime/criusupport/exports.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@

if(J9VM_OPT_CRIU_SUPPORT)
omr_add_exports(j9criu
Java_openj9_internal_criu_InternalCRIUSupport_isCheckpointAllowedImpl
Java_openj9_internal_criu_InternalCRIUSupport_isCRIUSupportEnabledImpl
Java_org_eclipse_openj9_criu_CRIUSupport_checkpointJVMImpl
)
endif()
2 changes: 0 additions & 2 deletions runtime/criusupport/uma/criusupport_exports.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,5 @@ OpenJDK Assembly Exception [2].
SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
-->
<exports group="criusupport">
<export name="Java_openj9_internal_criu_InternalCRIUSupport_isCheckpointAllowedImpl" />
<export name="Java_openj9_internal_criu_InternalCRIUSupport_isCRIUSupportEnabledImpl" />
<export name="Java_org_eclipse_openj9_criu_CRIUSupport_checkpointJVMImpl" />
</exports>
8 changes: 8 additions & 0 deletions runtime/jcl/common/criu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ extern "C" {

#if defined(J9VM_OPT_CRIU_SUPPORT)

jlong JNICALL
Java_openj9_internal_criu_InternalCRIUSupport_getCheckpointRestoreNanoTimeDeltaImpl(JNIEnv *env, jclass unused)
{
PORT_ACCESS_FROM_ENV(env);

return PORTLIB->checkpointRestoreTimeDelta;
}

jboolean JNICALL
Java_openj9_internal_criu_InternalCRIUSupport_isCheckpointAllowedImpl(JNIEnv *env, jclass unused)
{
Expand Down
1 change: 1 addition & 0 deletions runtime/jcl/exports.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,7 @@ endif()
# J9VM_OPT_CRIU_SUPPORT
if(J9VM_OPT_CRIU_SUPPORT)
omr_add_exports(jclse
Java_openj9_internal_criu_InternalCRIUSupport_getCheckpointRestoreNanoTimeDeltaImpl
Java_openj9_internal_criu_InternalCRIUSupport_isCheckpointAllowedImpl
Java_openj9_internal_criu_InternalCRIUSupport_isCRIUSupportEnabledImpl
)
Expand Down
1 change: 1 addition & 0 deletions runtime/jcl/uma/criu_exports.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ OpenJDK Assembly Exception [2].
SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
-->
<exports group="criu">
<export name="Java_openj9_internal_criu_InternalCRIUSupport_getCheckpointRestoreNanoTimeDeltaImpl" />
<export name="Java_openj9_internal_criu_InternalCRIUSupport_isCheckpointAllowedImpl" />
<export name="Java_openj9_internal_criu_InternalCRIUSupport_isCRIUSupportEnabledImpl" />
</exports>
47 changes: 45 additions & 2 deletions test/functional/cmdLineTests/criu/criu_nonPortable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@
<output type="required" caseSensitive="yes" regex="no">Error</output>
</test>

<test id="Create CRIU checkpoint image and restore three times">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" $MAINCLASS_TIMECHANGE$ ThreeCheckpoints</command>
<test id="Create CRIU checkpoint image and restore three times - testSystemNanoTime">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" "$MAINCLASS_TIMECHANGE$ testSystemNanoTime" ThreeCheckpoints</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
<output type="required" caseSensitive="yes" regex="no">System.nanoTime() before CRIU checkpoint:</output>
<output type="required" caseSensitive="yes" regex="no">PASSED: System.nanoTime() after CRIU restore:</output>
Expand All @@ -61,4 +61,47 @@
<output type="required" caseSensitive="yes" regex="no">Error</output>
</test>

<test id="Create CRIU checkpoint image and restore three times - testMillisDelayBeforeCheckpointDone">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" "$MAINCLASS_TIMECHANGE$ testMillisDelayBeforeCheckpointDone" ThreeCheckpoints</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
<output type="required" caseSensitive="yes" regex="no">Start test name: testMillisDelay</output>
<output type="required" caseSensitive="yes" regex="no">PASSED: expected MILLIS_DELAY</output>
<output type="failure" caseSensitive="yes" regex="no">CRIU is not enabled</output>
<output type="failure" caseSensitive="yes" regex="no">Operation not permitted</output>
<output type="failure" caseSensitive="yes" regex="no">FAILED: expected MILLIS_DELAY</output>
<output type="required" caseSensitive="yes" regex="no">Error</output>
</test>

<test id="Create CRIU checkpoint image and restore three times - testMillisDelayBeforeCheckpointDone">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" "$MAINCLASS_TIMECHANGE$ testMillisDelayAfterCheckpointDone" ThreeCheckpoints</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
<output type="required" caseSensitive="yes" regex="no">Start test name: testMillisDelay</output>
<output type="required" caseSensitive="yes" regex="no">PASSED: expected MILLIS_DELAY</output>
<output type="failure" caseSensitive="yes" regex="no">CRIU is not enabled</output>
<output type="failure" caseSensitive="yes" regex="no">Operation not permitted</output>
<output type="failure" caseSensitive="yes" regex="no">FAILED: expected MILLIS_DELAY</output>
<output type="required" caseSensitive="yes" regex="no">Error</output>
</test>

<test id="Create CRIU checkpoint image and restore three times - testDateScheduledBeforeCheckpointDone">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" "$MAINCLASS_TIMECHANGE$ testDateScheduledBeforeCheckpointDone" ThreeCheckpoints</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
<output type="required" caseSensitive="yes" regex="no">Start test name: testDateScheduledBeforeCheckpointDone</output>
<output type="required" caseSensitive="yes" regex="no">PASSED: expected to run after timeMillisScheduledBeforeCheckpointDone</output>
<output type="failure" caseSensitive="yes" regex="no">CRIU is not enabled</output>
<output type="failure" caseSensitive="yes" regex="no">Operation not permitted</output>
<output type="failure" caseSensitive="yes" regex="no">FAILED: expected to run after timeMillisScheduledBeforeCheckpointDone</output>
<output type="required" caseSensitive="yes" regex="no">Error</output>
</test>

<test id="Create CRIU checkpoint image and restore three times - testDateScheduledAfterCheckpointDone">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" "$MAINCLASS_TIMECHANGE$ testDateScheduledAfterCheckpointDone" ThreeCheckpoints</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
<output type="required" caseSensitive="yes" regex="no">Start test name: testDateScheduledAfterCheckpointDone</output>
<output type="required" caseSensitive="yes" regex="no">PASSED: expected to run after timeMillisScheduledAfterCheckpointDone</output>
<output type="failure" caseSensitive="yes" regex="no">CRIU is not enabled</output>
<output type="failure" caseSensitive="yes" regex="no">Operation not permitted</output>
<output type="failure" caseSensitive="yes" regex="no">FAILED: expected to run after timeMillisScheduledAfterCheckpointDone</output>
<output type="required" caseSensitive="yes" regex="no">Error</output>
</test>
</suite>
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,196 @@
*******************************************************************************/
package org.openj9.criu;

import java.nio.file.Paths;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class TimeChangeTest {

// The elapsed time is expected less than 2 second.
private static long MAX_ELAPSED_TIME = 2000 * 1000 * 1000;
private static Path imagePath = Paths.get("cpData");
// maximum tardiness - 4 second
private final static long MAX_TARDINESS_MS = 4000;
private final static long MAX_TARDINESS_NS = MAX_TARDINESS_MS * 1000 * 1000;
// delay 100 millisecond
private final static long MILLIS_DELAY_BEFORECHECKPOINTDONE = 100;
// delay 5000 millisecond
private final static long MILLIS_DELAY_AFTERCHECKPOINTDONE = 5000;
private final long startNanoTime = System.nanoTime();
private final long currentTimeMillis = System.currentTimeMillis();
private final static Path imagePath = Paths.get("cpData");

public static void main(String args[]) {
new TimeChangeTest().testSystemNanoTime();
public static void main(String args[]) throws InterruptedException {
if (args.length == 0) {
throw new RuntimeException("Test name required");
} else {
String testName = args[0];
TimeChangeTest tct = new TimeChangeTest();
if ("testSystemNanoTime".equalsIgnoreCase(testName)) {
tct.testSystemNanoTime();
} else {
tct.test(testName);
}
}
}

private void test(String testName) throws InterruptedException {
System.out.println("Start test name: " + testName);
showThreadCurrentTime("Before starting " + testName);
Timer timer = new Timer();
switch (testName) {
case "testMillisDelayBeforeCheckpointDone":
testMillisDelayBeforeCheckpointDone(timer);
break;
case "testMillisDelayAfterCheckpointDone":
testMillisDelayAfterCheckpointDone(timer);
break;
case "testDateScheduledBeforeCheckpointDone":
testDateScheduledBeforeCheckpointDone(timer);
break;
case "testDateScheduledAfterCheckpointDone":
testDateScheduledAfterCheckpointDone(timer);
break;
default:
throw new RuntimeException("Unrecognized test name: " + testName);
}
CRIUTestUtils.checkPointJVM(imagePath, false);
// maximum test running time is 12s
Thread.sleep(12000);
showThreadCurrentTime("End " + testName);
timer.cancel();
}

public void testSystemNanoTime() {
final long beforeCheckpoint = System.nanoTime();
System.out.println("System.nanoTime() before CRIU checkpoint: " + beforeCheckpoint);
CRIUTestUtils.checkPointJVM(imagePath);
CRIUTestUtils.checkPointJVM(imagePath, false);
final long afterRestore = System.nanoTime();
final long elapsedTime = afterRestore - beforeCheckpoint;
if (elapsedTime < MAX_ELAPSED_TIME) {
System.out.println("PASSED: System.nanoTime() after CRIU restore: " + afterRestore + ", the elapse time is: " + elapsedTime);
if (elapsedTime < MAX_TARDINESS_NS) {
System.out.println("PASSED: System.nanoTime() after CRIU restore: " + afterRestore
+ ", the elapse time is: " + elapsedTime + " ns");
} else {
System.out.println("FAILED: System.nanoTime() after CRIU restore: " + afterRestore + ", the elapse time is: " + elapsedTime);
System.out.println("FAILED: System.nanoTime() after CRIU restore: " + afterRestore
+ ", the elapse time is: " + elapsedTime + " ns, w/ MAX_TARDINESS_NS : " + MAX_TARDINESS_NS);
}
}

private final TimerTask taskMillisDelayBeforeCheckpointDone = new TimerTask() {
public void run() {
final long endNanoTime = System.nanoTime();
final long elapsedTime = (endNanoTime - startNanoTime) / 1000000;
boolean pass = false;
if ((elapsedTime >= MILLIS_DELAY_BEFORECHECKPOINTDONE)
&& (elapsedTime < (MILLIS_DELAY_BEFORECHECKPOINTDONE + MAX_TARDINESS_MS))) {
pass = true;
}
showThreadCurrentTime("taskMillisDelayBeforeCheckpointDone");
if (pass) {
System.out.println(
"PASSED: expected MILLIS_DELAY_BEFORECHECKPOINTDONE " + MILLIS_DELAY_BEFORECHECKPOINTDONE
+ " ms, the actual elapsed time is: " + elapsedTime + " ms");
} else {
System.out.println(
"FAILED: expected MILLIS_DELAY_BEFORECHECKPOINTDONE " + MILLIS_DELAY_BEFORECHECKPOINTDONE
+ " ms, but the actual elapsed time is: " + elapsedTime + " ms");
}
}
};

// Timer.schedule(TimerTask task, long delay)
private void testMillisDelayBeforeCheckpointDone(Timer timerMillisDelay) throws InterruptedException {
timerMillisDelay.schedule(taskMillisDelayBeforeCheckpointDone, MILLIS_DELAY_BEFORECHECKPOINTDONE);
}

private final TimerTask taskMillisDelayAfterCheckpointDone = new TimerTask() {
public void run() {
final long endNanoTime = System.nanoTime();
final long elapsedTime = (endNanoTime - startNanoTime) / 1000000;
boolean pass = false;
if ((elapsedTime >= MILLIS_DELAY_AFTERCHECKPOINTDONE)
&& (elapsedTime < (MILLIS_DELAY_AFTERCHECKPOINTDONE + MAX_TARDINESS_MS))) {
pass = true;
}
showThreadCurrentTime("taskMillisDelayAfterCheckpointDone");
if (pass) {
System.out.println("PASSED: expected MILLIS_DELAY_AFTERCHECKPOINTDONE "
+ MILLIS_DELAY_AFTERCHECKPOINTDONE + " ms, the actual elapsed time is: " + elapsedTime + " ms");
} else {
System.out
.println("FAILED: expected MILLIS_DELAY_AFTERCHECKPOINTDONE " + MILLIS_DELAY_AFTERCHECKPOINTDONE
+ " ms, but the actual elapsed time is: " + elapsedTime + " ms");
}
}
};

// Timer.schedule(TimerTask task, long delay)
private void testMillisDelayAfterCheckpointDone(Timer timerMillisDelay) throws InterruptedException {
timerMillisDelay.schedule(taskMillisDelayAfterCheckpointDone, MILLIS_DELAY_AFTERCHECKPOINTDONE);
}

// expect the checkpoint takes longer than 10ms
private final long timeMillisScheduledBeforeCheckpointDone = currentTimeMillis + 10;
private final TimerTask taskDateScheduledBeforeCheckpointDone = new TimerTask() {
public void run() {
final long taskRunTimeMillis = System.currentTimeMillis();
boolean pass = false;
if ((taskRunTimeMillis >= timeMillisScheduledBeforeCheckpointDone)
&& (taskRunTimeMillis < (timeMillisScheduledBeforeCheckpointDone + MAX_TARDINESS_MS))) {
pass = true;
}
showThreadCurrentTime("taskDateScheduledBeforeCheckpointDone");
if (pass) {
System.out.println("PASSED: expected to run after timeMillisScheduledBeforeCheckpointDone "
+ timeMillisScheduledBeforeCheckpointDone + " ms, the actual taskRunTimeMillis is: "
+ taskRunTimeMillis + " ms");
} else {
System.out.println("FAILED: expected to run after timeMillisScheduledBeforeCheckpointDone "
+ timeMillisScheduledBeforeCheckpointDone + " ms, but the actual taskRunTimeMillis is: "
+ taskRunTimeMillis + " ms");
}
}
};

// Timer.schedule(TimerTask task, Date time)
private void testDateScheduledBeforeCheckpointDone(Timer timerDateScheduledBeforeCheckpointDone)
throws InterruptedException {
Date dateScheduled = new Date(timeMillisScheduledBeforeCheckpointDone);
timerDateScheduledBeforeCheckpointDone.schedule(taskDateScheduledBeforeCheckpointDone, dateScheduled);
}

// expect the Checkpoint takes less than 2000ms
private final long timeMillisScheduledAfterCheckpointDone = currentTimeMillis + 2000;
private final TimerTask taskDateScheduledAfterCheckpoint = new TimerTask() {
public void run() {
final long taskRunTimeMillis = System.currentTimeMillis();
boolean pass = false;
if ((taskRunTimeMillis >= timeMillisScheduledAfterCheckpointDone)
&& (taskRunTimeMillis < (timeMillisScheduledAfterCheckpointDone + MAX_TARDINESS_MS))) {
pass = true;
}
showThreadCurrentTime("taskDateScheduledAfterCheckpoint");
if (pass) {
System.out.println("PASSED: expected to run after timeMillisScheduledAfterCheckpointDone "
+ timeMillisScheduledAfterCheckpointDone + " ms, the actual taskRunTimeMillis is: "
+ taskRunTimeMillis + " ms");
} else {
System.out.println("FAILED: expected to run after timeMillisScheduledAfterCheckpointDone "
+ timeMillisScheduledAfterCheckpointDone + " ms, but the actual taskRunTimeMillis is: "
+ taskRunTimeMillis + " ms");
}
}
};

// Timer.schedule(TimerTask task, Date time)
private void testDateScheduledAfterCheckpointDone(Timer timerDateScheduledAfterCheckpointDone)
throws InterruptedException {
Date dateScheduled = new Date(timeMillisScheduledAfterCheckpointDone);
timerDateScheduledAfterCheckpointDone.schedule(taskDateScheduledAfterCheckpoint, dateScheduled);
}

private void showThreadCurrentTime(String logStr) {
System.out.println(logStr + ": System.currentTimeMillis: " + System.currentTimeMillis() + ", " + new Date()
+ ", Thread's name: " + Thread.currentThread().getName());
}
}