Skip to content

Commit dbd9963

Browse files
committedMay 7, 2019
Prototype for Java Checkpoint Restore
0 parents  commit dbd9963

File tree

4 files changed

+250
-0
lines changed

4 files changed

+250
-0
lines changed
 

‎CheckpointRestore.cpp

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#include "CheckpointRestore.hpp"
2+
#include <criu.h>
3+
#include <dirent.h>
4+
#include <errno.h>
5+
#include <fcntl.h>
6+
#include <jni.h>
7+
#include <signal.h>
8+
#include <stdio.h>
9+
#include <stdlib.h>
10+
#include <string.h>
11+
#include <sys/socket.h>
12+
#include <sys/stat.h>
13+
#include <sys/types.h>
14+
#include <sys/un.h>
15+
#include <sys/wait.h>
16+
#include <unistd.h>
17+
18+
JNIEXPORT void JNICALL Java_CheckpointRestore_CheckTheWorldNative(JNIEnv *env, jobject obj) {
19+
int init_result = criu_init_opts();
20+
21+
if (init_result < 0) {
22+
perror("Can't init opts");
23+
}
24+
25+
int result = criu_check();
26+
27+
if (result == 0) {
28+
printf("Criu Check success\n");
29+
} else {
30+
printf("Criu Check failed with error: %d: %s\n", result, strerror(result));
31+
}
32+
return;
33+
}
34+
35+
36+
JNIEXPORT void JNICALL Java_CheckpointRestore_SaveTheWorldNative (JNIEnv * env, jobject jobj, jstring jstr) {
37+
const char * path = env->GetStringUTFChars(jstr, NULL);
38+
struct stat st = {0};
39+
40+
if (stat(path, &st) == -1) {
41+
mkdir(path, 0700);
42+
}
43+
44+
int fd = open(path, O_DIRECTORY);
45+
46+
printf("\npath = %s\n",path);
47+
48+
if (fd < 0) {
49+
perror("Can't open images dir");
50+
}
51+
52+
int init_result = criu_init_opts();
53+
54+
if (init_result < 0) {
55+
perror("Can't init opts");
56+
}
57+
58+
criu_set_images_dir_fd(fd);
59+
criu_set_shell_job(true);
60+
criu_set_log_level(4);
61+
62+
criu_set_log_file((char *) "save.log");
63+
criu_set_leave_running(true);
64+
65+
66+
criu_set_ext_unix_sk(true);
67+
int ret = criu_dump();
68+
69+
if (ret == 0) {
70+
printf("Successful dump\n");
71+
} else {
72+
printf("Error from dump %d\n", ret);
73+
perror("Dump Error");
74+
}
75+
}
76+
77+
78+
/*
79+
* Class: CheckpointRestore
80+
* Method: RestoreTheWorld
81+
* Signature: ()V
82+
*/
83+
84+
JNIEXPORT void JNICALL Java_CheckpointRestore_RestoreTheWorldNative
85+
(JNIEnv * env, jobject jobj, jstring jstr) {
86+
const char * path = env->GetStringUTFChars(jstr, NULL);
87+
printf("\nRestore The World Path = %s\n",path);
88+
int fd = open(path, O_DIRECTORY);
89+
90+
if (fd < 0) {
91+
perror("Can't open images dir");
92+
}
93+
94+
int init_result = criu_init_opts();
95+
96+
if (init_result < 0) {
97+
perror("Can't init opts");
98+
}
99+
100+
printf("RestoreTheWorld: file = %s fd = %d\n", path, fd);
101+
102+
criu_set_shell_job(true);
103+
criu_set_images_dir_fd(fd);
104+
criu_set_log_file((char *) "chfrestore.log");
105+
criu_set_log_level(4);
106+
107+
int pid = criu_restore_child();
108+
printf("\npid = %d\n", pid);
109+
if (pid < 0) {
110+
perror("Criu Restore Bad Pid \n");
111+
} else {
112+
int status = 0;
113+
int result = waitpid(pid, &status, 0);
114+
if (result < 0) {
115+
printf("pid = %d status = %d result = %d\n", pid, status, result);
116+
perror("Can't wait rchild");
117+
}
118+
}
119+
}
120+
121+
/*
122+
* Class: CheckpointRestore
123+
* Method: MigrateTheWorld
124+
* Signature: ()V
125+
*/
126+
JNIEXPORT void JNICALL Java_CheckpointRestore_MigrateTheWorld
127+
(JNIEnv *, jobject);
128+
129+
/*
130+
* Class: CheckpointRestore
131+
* Method: SaveTheWorldIncremental
132+
* Signature: ()V
133+
*/
134+
JNIEXPORT void JNICALL Java_CheckpointRestore_SaveTheWorldIncremental
135+
(JNIEnv *, jobject);
136+

‎CheckpointRestore.java

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import java.util.Map;
2+
3+
public class CheckpointRestore {
4+
5+
public static void CleanupTheWorld() {
6+
System.gc();
7+
System.gc();
8+
}
9+
10+
private native void CheckTheWorldNative();
11+
private native void SaveTheWorldNative(String dir);
12+
private native void RestoreTheWorldNative(String dir);
13+
14+
public static native void MigrateTheWorld();
15+
public static native void SaveTheWorldIncremental();
16+
17+
public static void CheckTheWorld() {
18+
CheckpointRestore cr = new CheckpointRestore();
19+
cr.CheckTheWorldNative();
20+
}
21+
22+
public static void SaveTheWorld(String dir) {
23+
CheckpointRestore cr = new CheckpointRestore();
24+
cr.SaveTheWorldNative(dir);
25+
}
26+
27+
public static void RestoreTheWorld(String dir) {
28+
System.out.println("RestoreTheWorld java call");
29+
CheckpointRestore cr = new CheckpointRestore();
30+
cr.RestoreTheWorldNative(dir);
31+
}
32+
33+
static {
34+
35+
System.out.println("Library path = " + System.getProperty("java.library.path"));
36+
System.out.println("About to load Checkpoint Restore library " + System.mapLibraryName("CheckpointRestore"));
37+
System.out.println("About to load criu library " + System.mapLibraryName("criu"));
38+
39+
System.out.println("Before call to load CheckpointRestore");
40+
System.loadLibrary("CheckpointRestore");
41+
System.out.println("After call to load CheckpointRestore");
42+
System.loadLibrary("criu");
43+
System.out.println("After call to load criu");
44+
}
45+
}

‎ReadMe

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
This is demo code to show how to use CRIU (Checkpoint Restore In Userspace) from Java.
2+
3+
It's very much a prototype. There are many caveats in this file. Please try it and let me know how it goes.
4+
chf@redhat.com
5+
6+
Make sure criu is running from the directory that has the socket file.
7+
[cflood@cflood FromInsideJava]$ sudo /home/cflood/criu/criu-latest/criu/criu service
8+
Warn (criu/cr-service.c:1160): Binding to local dir address!
9+
10+
Make sure kernel is compiled with CR turned on
11+
sudo grep CHECKPOINT /boot/config-*
12+
13+
javac CheckpointRestore.java
14+
15+
javah CheckpointRestore
16+
17+
mv CheckpointRestore.h CheckpointRestore.hpp
18+
19+
Make sure criu is installed and libcriu is on your library path. I set mine via
20+
export LOAD_LIBRARY_PATH=/usr/lib64:./
21+
There is probably a better way
22+
23+
Build the criu library.
24+
gcc -shared -fPIC -I/usr/lib/jvm/java-openjdk/include -I/usr/lib/jvm/java-openjdk/include/linux -I/usr/lib64/ -I/usr/include/criu -lcriu -o libCheckpointRestore.so CheckpointRestore.cpp
25+
26+
There is currently a problem with a socket file which is causing tests to fail. The short term fix is to delete this file.
27+
I did rm -rf rm -f /var/lib/sss/pipes/nss
28+
I'm working on addressing this problem.
29+
30+
You can now checkpoint java code:
31+
sudo setsid java -XX:+UseSerialGC -XX:-UsePerfData -Djava.library.path=$LOAD_LIBRARY_PATH TestRandom 1000000 1000
32+
33+
and restore:
34+
35+
sudo bash
36+
cd /home/chf/SavedWorlds/run<x>
37+
criu restore --shell-job

‎TestRandom.java

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
public class TestRandom {
2+
3+
public static void main(String[] args) {
4+
if (args.length != 2) System.out.println("Usage: please provide upper bound and sample size");
5+
int upperBound = Integer.parseInt(args[0]);
6+
long sampleSize = Long.parseLong(args[1]);
7+
long testarray[] = new long[upperBound];
8+
9+
for (long i = 0; i < sampleSize; i++) {
10+
Double r = Math.random() * upperBound;
11+
int v = (int) Math.floor(r);
12+
testarray[v] += 1;
13+
}
14+
System.out.println("Before any goodness");
15+
CheckpointRestore.CheckTheWorld();
16+
long end = System.currentTimeMillis();
17+
System.out.println("Saving the world in directory /home/chf/SavedWorlds/run" + end);
18+
CheckpointRestore.SaveTheWorld("/home/chf/SavedWorlds/run" + end);
19+
20+
long max = 0; long min = upperBound; long average = 0;
21+
for (int i = 0; i < upperBound; i++) {
22+
long s = testarray[i];
23+
if (s > max) { max = s;}
24+
if (s < min) { min = s;}
25+
average = average + s;
26+
}
27+
double median = average / upperBound;
28+
29+
System.out.println("Testing random number generator with upper bound = " + upperBound + " and sample size " + sampleSize);
30+
System.out.println("Max bin size = " + max + " Min bin size = " + min + " median bin size = " + median);
31+
}
32+
}

0 commit comments

Comments
 (0)
Please sign in to comment.