mirror of
https://github.com/apple/foundationdb.git
synced 2025-05-16 10:52:20 +08:00
Allow classPath to be modified at runtime
This commit is contained in:
parent
e19901186f
commit
371a41dbba
@ -22,6 +22,13 @@ package com.apple.foundationdb.testing;
|
||||
|
||||
import com.apple.foundationdb.Database;
|
||||
import com.apple.foundationdb.FDB;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
@ -31,6 +38,7 @@ import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class AbstractWorkload {
|
||||
private static final Class[] parameters = new Class[]{URL.class};
|
||||
protected WorkloadContext context;
|
||||
private ThreadPoolExecutor executorService;
|
||||
|
||||
@ -99,4 +107,29 @@ public abstract class AbstractWorkload {
|
||||
private native void setProcessID(long processID);
|
||||
private native void sendVoid(long handle);
|
||||
private native void sendBool(long handle, boolean value);
|
||||
|
||||
// Helper functions to add to the class path at Runtime - will be called
|
||||
// from C++
|
||||
private static void addFile(String s) throws IOException {
|
||||
File f = new File(s);
|
||||
addFile(f);
|
||||
}
|
||||
|
||||
private static void addFile(File f) throws IOException {
|
||||
addURL(f.toURI().toURL());
|
||||
}
|
||||
|
||||
private static void addURL(URL u) throws IOException {
|
||||
URLClassLoader sysLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
|
||||
Class sysClass = URLClassLoader.class;
|
||||
|
||||
try {
|
||||
Method method = sysClass.getDeclaredMethod("addURL", parameters);
|
||||
method.setAccessible(true);
|
||||
method.invoke(sysLoader, new Object[]{u});
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
throw new IOException("Error, could not add URL to system classloader");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,6 +96,7 @@ struct JVMContext {
|
||||
// this is a bit ugly - but JNINativeMethod requires
|
||||
// char* not const char *
|
||||
std::vector<char*> charArrays;
|
||||
std::set<std::string> classPath;
|
||||
|
||||
void setWorkloadMethods(const std::initializer_list<std::tuple<StringRef, StringRef, void*>>& methods) {
|
||||
charArrays.reserve(charArrays.size() + 2*methods.size());
|
||||
@ -175,6 +176,30 @@ struct JVMContext {
|
||||
flushTraceFileVoid();
|
||||
}
|
||||
|
||||
bool addToClassPath(const std::string& path) {
|
||||
TraceEvent("TryAddToClassPath")
|
||||
.detail("Path", "path");
|
||||
flushTraceFileVoid();
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
if (classPath.count(path) > 0) {
|
||||
// already added
|
||||
return true;
|
||||
}
|
||||
auto addFileMethod = env->GetStaticMethodID(workloadClass, "addFile", "(Ljava/lang/String;)V");
|
||||
if (!checkException()) {
|
||||
return false;
|
||||
}
|
||||
auto p = env->NewStringUTF(path.c_str());
|
||||
env->CallStaticVoidMethod(workloadClass, addFileMethod, p);
|
||||
if (!checkException()) {
|
||||
return false;
|
||||
}
|
||||
classPath.insert(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkException() {
|
||||
auto flag = env->ExceptionCheck();
|
||||
if (flag) {
|
||||
@ -261,6 +286,7 @@ struct JavaWorkload : TestWorkload {
|
||||
// This means, that we have to share the VM across workloads.
|
||||
static std::weak_ptr<JVMContext> globalVM;
|
||||
std::shared_ptr<JVMContext> vm;
|
||||
std::vector<std::string> classPath;
|
||||
|
||||
std::string className;
|
||||
|
||||
@ -275,6 +301,7 @@ struct JavaWorkload : TestWorkload {
|
||||
return;
|
||||
}
|
||||
auto jvmOptions = getOption(options, LiteralStringRef("jvmOptions"), std::vector<std::string>{});
|
||||
classPath = getOption(options, LiteralStringRef("classPath"), std::vector<std::string>{});
|
||||
vm = globalVM.lock();
|
||||
if (!vm) {
|
||||
std::vector<char*> args;
|
||||
@ -292,6 +319,8 @@ struct JavaWorkload : TestWorkload {
|
||||
success = vm->success;
|
||||
}
|
||||
if (success) {
|
||||
TraceEvent("JVMRunning");
|
||||
flushTraceFileVoid();
|
||||
try {
|
||||
createContext();
|
||||
} catch (Error& e) {
|
||||
@ -332,6 +361,19 @@ struct JavaWorkload : TestWorkload {
|
||||
}
|
||||
|
||||
void createContext() {
|
||||
TraceEvent("AddClassPaths")
|
||||
.detail("Num", classPath.size());
|
||||
flushTraceFileVoid();
|
||||
for (const auto& p : classPath) {
|
||||
if (!vm->addToClassPath(p)) {
|
||||
TraceEvent("AddToClassPathFailed")
|
||||
.detail("Path", p);
|
||||
success = false;
|
||||
return;
|
||||
}
|
||||
TraceEvent("AddToClassPath")
|
||||
.detail("Path", p);
|
||||
}
|
||||
std::transform(className.begin(), className.end(), className.begin(), [](char c) {
|
||||
if (c == '.') return '/';
|
||||
return c;
|
||||
@ -379,6 +421,7 @@ struct JavaWorkload : TestWorkload {
|
||||
vm->env->CallVoidMethod(hashMap, put, key, value);
|
||||
vm->env->DeleteLocalRef(key);
|
||||
vm->env->DeleteLocalRef(value);
|
||||
kv.value = LiteralStringRef("");
|
||||
}
|
||||
auto workloadContextClass = findClass("com/apple/foundationdb/testing/WorkloadContext");
|
||||
auto workloadContextConstructor = getMethodID(workloadContextClass, "<init>", "(Ljava/util/Map;IIJJ)V");
|
||||
|
Loading…
x
Reference in New Issue
Block a user