blob: 809aa17644741a26831149bfb2b29a2ac736522b [file]
/*
* 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.
*/
// ReSharper disable once CppUnusedIncludeDirective
#include <cstring> // needed only on linux
#include <string>
#include <exception>
#include <vector>
#include <algorithm>
#include <stdexcept>
#include "ignite/jni/utils.h"
#include "ignite/common/concurrent.h"
#include "ignite/jni/java.h"
#include <ignite/ignite_error.h>
#define IGNITE_SAFE_PROC_NO_ARG(jniEnv, envPtr, type, field) { \
JniHandlers* hnds = reinterpret_cast<JniHandlers*>(envPtr); \
type hnd = hnds->field; \
if (hnd) \
{ \
try \
{ \
hnd(hnds->target); \
} \
catch (std::exception& err) \
{ \
ThrowToJava(jniEnv, err.what()); \
} \
} \
else \
ThrowOnMissingHandler(jniEnv); \
}
#define IGNITE_SAFE_PROC(jniEnv, envPtr, type, field, ...) { \
JniHandlers* hnds = reinterpret_cast<JniHandlers*>(envPtr); \
type hnd = hnds->field; \
if (hnd) \
{ \
try \
{ \
hnd(hnds->target, __VA_ARGS__); \
} \
catch (std::exception& err) \
{ \
ThrowToJava(jniEnv, err.what()); \
} \
} \
else \
ThrowOnMissingHandler(jniEnv); \
}
#define IGNITE_SAFE_FUNC(jniEnv, envPtr, type, field, ...) { \
JniHandlers* hnds = reinterpret_cast<JniHandlers*>(envPtr); \
type hnd = hnds->field; \
if (hnd) \
{ \
try \
{ \
return hnd(hnds->target, __VA_ARGS__); \
} \
catch (std::exception& err) \
{ \
ThrowToJava(jniEnv, err.what()); \
return 0; \
} \
} \
else \
{ \
ThrowOnMissingHandler(jniEnv); \
return 0; \
}\
}
using namespace ignite::java;
namespace ignite
{
namespace jni
{
namespace java
{
namespace gcc = ignite::common::concurrent;
/* --- Startup exception. --- */
class JvmException : public std::exception {
// No-op.
};
/* --- JNI method definitions. --- */
struct JniMethod {
char* name;
char* sign;
bool isStatic;
JniMethod(const char* name, const char* sign, bool isStatic) {
this->name = const_cast<char*>(name);
this->sign = const_cast<char*>(sign);
this->isStatic = isStatic;
}
};
/**
* Heloper function to copy characters.
*
* @param src Source.
* @return Result.
*/
char* CopyChars(const char* src)
{
if (src)
{
size_t len = strlen(src);
char* dest = new char[len + 1];
strcpy(dest, src);
*(dest + len) = 0;
return dest;
}
else
return NULL;
}
JniErrorInfo::JniErrorInfo() : code(IGNITE_JNI_ERR_SUCCESS), errCls(NULL), errMsg(NULL)
{
// No-op.
}
JniErrorInfo::JniErrorInfo(int code, const char* errCls, const char* errMsg) : code(code)
{
this->errCls = CopyChars(errCls);
this->errMsg = CopyChars(errMsg);
}
JniErrorInfo::JniErrorInfo(const JniErrorInfo& other) : code(other.code)
{
this->errCls = CopyChars(other.errCls);
this->errMsg = CopyChars(other.errMsg);
}
JniErrorInfo& JniErrorInfo::operator=(const JniErrorInfo& other)
{
if (this != &other)
{
// 1. Create new instance, exception could occur at this point.
JniErrorInfo tmp(other);
// 2. Swap with temp.
int code0 = code;
char* errCls0 = errCls;
char* errMsg0 = errMsg;
code = tmp.code;
errCls = tmp.errCls;
errMsg = tmp.errMsg;
tmp.code = code0;
tmp.errCls = errCls0;
tmp.errMsg = errMsg0;
}
return *this;
}
JniErrorInfo::~JniErrorInfo()
{
if (errCls)
delete[] errCls;
if (errMsg)
delete[] errMsg;
}
/**
* Guard to ensure global reference cleanup.
*/
class JniGlobalRefGuard
{
public:
JniGlobalRefGuard(JNIEnv *e, jobject obj) : env(e), ref(obj)
{
// No-op.
}
~JniGlobalRefGuard()
{
env->DeleteGlobalRef(ref);
}
private:
/** Environment. */
JNIEnv* env;
/** Target reference. */
jobject ref;
IGNITE_NO_COPY_ASSIGNMENT(JniGlobalRefGuard)
};
const char* C_THROWABLE = "java/lang/Throwable";
JniMethod M_THROWABLE_GET_MESSAGE = JniMethod("getMessage", "()Ljava/lang/String;", false);
JniMethod M_THROWABLE_PRINT_STACK_TRACE = JniMethod("printStackTrace", "()V", false);
const char* C_CLASS = "java/lang/Class";
JniMethod M_CLASS_GET_NAME = JniMethod("getName", "()Ljava/lang/String;", false);
const char* C_IGNITE_EXCEPTION = "org/apache/ignite/IgniteException";
const char* C_PLATFORM_NO_CALLBACK_EXCEPTION = "org/apache/ignite/internal/processors/platform/PlatformNoCallbackException";
const char* C_PLATFORM_PROCESSOR = "org/apache/ignite/internal/processors/platform/PlatformProcessor";
JniMethod M_PLATFORM_PROCESSOR_RELEASE_START = JniMethod("releaseStart", "()V", false);
JniMethod M_PLATFORM_PROCESSOR_PROJECTION = JniMethod("projection", "()Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_CACHE = JniMethod("cache", "(Ljava/lang/String;)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_CREATE_CACHE = JniMethod("createCache", "(Ljava/lang/String;)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_GET_OR_CREATE_CACHE = JniMethod("getOrCreateCache", "(Ljava/lang/String;)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_CREATE_CACHE_FROM_CONFIG = JniMethod("createCacheFromConfig", "(J)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_GET_OR_CREATE_CACHE_FROM_CONFIG = JniMethod("getOrCreateCacheFromConfig", "(J)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_CREATE_NEAR_CACHE = JniMethod("createNearCache", "(Ljava/lang/String;J)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_GET_OR_CREATE_NEAR_CACHE = JniMethod("getOrCreateNearCache", "(Ljava/lang/String;J)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_DESTROY_CACHE = JniMethod("destroyCache", "(Ljava/lang/String;)V", false);
JniMethod M_PLATFORM_PROCESSOR_AFFINITY = JniMethod("affinity", "(Ljava/lang/String;)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_DATA_STREAMER = JniMethod("dataStreamer", "(Ljava/lang/String;Z)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_TRANSACTIONS = JniMethod("transactions", "()Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_COMPUTE = JniMethod("compute", "(Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_MESSAGE = JniMethod("message", "(Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_EVENTS = JniMethod("events", "(Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_SERVICES = JniMethod("services", "(Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_EXTENSIONS = JniMethod("extensions", "()Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_EXTENSION = JniMethod("extension", "(I)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_ATOMIC_LONG = JniMethod("atomicLong", "(Ljava/lang/String;JZ)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_ATOMIC_SEQUENCE = JniMethod("atomicSequence", "(Ljava/lang/String;JZ)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_ATOMIC_REFERENCE = JniMethod("atomicReference", "(Ljava/lang/String;JZ)Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
JniMethod M_PLATFORM_PROCESSOR_GET_IGNITE_CONFIGURATION = JniMethod("getIgniteConfiguration", "(J)V", false);
JniMethod M_PLATFORM_PROCESSOR_GET_CACHE_NAMES = JniMethod("getCacheNames", "(J)V", false);
JniMethod M_PLATFORM_PROCESSOR_LOGGER_IS_LEVEL_ENABLED = JniMethod("loggerIsLevelEnabled", "(I)Z", false);
JniMethod M_PLATFORM_PROCESSOR_LOGGER_LOG = JniMethod("loggerLog", "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", false);
JniMethod M_PLATFORM_PROCESSOR_BINARY_PROCESSOR = JniMethod("binaryProcessor", "()Lorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;", false);
const char* C_PLATFORM_TARGET = "org/apache/ignite/internal/processors/platform/PlatformTargetProxy";
JniMethod M_PLATFORM_TARGET_IN_LONG_OUT_LONG = JniMethod("inLongOutLong", "(IJ)J", false);
JniMethod M_PLATFORM_TARGET_IN_STREAM_OUT_LONG = JniMethod("inStreamOutLong", "(IJ)J", false);
JniMethod M_PLATFORM_TARGET_IN_STREAM_OUT_OBJECT = JniMethod("inStreamOutObject", "(IJ)Ljava/lang/Object;", false);
JniMethod M_PLATFORM_TARGET_IN_STREAM_OUT_STREAM = JniMethod("inStreamOutStream", "(IJJ)V", false);
JniMethod M_PLATFORM_TARGET_IN_OBJECT_STREAM_OUT_OBJECT_STREAM = JniMethod("inObjectStreamOutObjectStream", "(ILjava/lang/Object;JJ)Ljava/lang/Object;", false);
JniMethod M_PLATFORM_TARGET_OUT_STREAM = JniMethod("outStream", "(IJ)V", false);
JniMethod M_PLATFORM_TARGET_OUT_OBJECT = JniMethod("outObject", "(I)Ljava/lang/Object;", false);
JniMethod M_PLATFORM_TARGET_IN_STREAM_ASYNC = JniMethod("inStreamAsync", "(IJ)V", false);
const char* C_PLATFORM_CALLBACK_UTILS = "org/apache/ignite/internal/processors/platform/callback/PlatformCallbackUtils";
JniMethod M_PLATFORM_CALLBACK_UTILS_CACHE_STORE_CREATE = JniMethod("cacheStoreCreate", "(JJ)J", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_CACHE_STORE_INVOKE = JniMethod("cacheStoreInvoke", "(JJJ)I", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_CACHE_STORE_DESTROY = JniMethod("cacheStoreDestroy", "(JJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_CACHE_STORE_SESSION_CREATE = JniMethod("cacheStoreSessionCreate", "(JJ)J", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_CACHE_ENTRY_FILTER_CREATE = JniMethod("cacheEntryFilterCreate", "(JJ)J", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_CACHE_ENTRY_FILTER_APPLY = JniMethod("cacheEntryFilterApply", "(JJJ)I", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_CACHE_ENTRY_FILTER_DESTROY = JniMethod("cacheEntryFilterDestroy", "(JJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_CACHE_INVOKE = JniMethod("cacheInvoke", "(JJJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_COMPUTE_TASK_MAP = JniMethod("computeTaskMap", "(JJJJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_COMPUTE_TASK_JOB_RESULT = JniMethod("computeTaskJobResult", "(JJJJ)I", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_COMPUTE_TASK_REDUCE = JniMethod("computeTaskReduce", "(JJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_COMPUTE_TASK_COMPLETE = JniMethod("computeTaskComplete", "(JJJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_COMPUTE_JOB_SERIALIZE = JniMethod("computeJobSerialize", "(JJJ)I", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_COMPUTE_JOB_CREATE = JniMethod("computeJobCreate", "(JJ)J", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_COMPUTE_JOB_EXECUTE = JniMethod("computeJobExecute", "(JJIJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_COMPUTE_JOB_DESTROY = JniMethod("computeJobDestroy", "(JJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_COMPUTE_JOB_CANCEL = JniMethod("computeJobCancel", "(JJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_CONTINUOUS_QUERY_LSNR_APPLY = JniMethod("continuousQueryListenerApply", "(JJJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_CONTINUOUS_QUERY_FILTER_CREATE = JniMethod("continuousQueryFilterCreate", "(JJ)J", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_CONTINUOUS_QUERY_FILTER_EVAL = JniMethod("continuousQueryFilterApply", "(JJJ)I", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_CONTINUOUS_QUERY_FILTER_RELEASE = JniMethod("continuousQueryFilterRelease", "(JJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_DATA_STREAMER_TOPOLOGY_UPDATE = JniMethod("dataStreamerTopologyUpdate", "(JJJI)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_DATA_STREAMER_STREAM_RECEIVER_INVOKE = JniMethod("dataStreamerStreamReceiverInvoke", "(JJLorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;JZ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_FUTURE_BYTE_RES = JniMethod("futureByteResult", "(JJI)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_FUTURE_BOOL_RES = JniMethod("futureBoolResult", "(JJI)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_FUTURE_SHORT_RES = JniMethod("futureShortResult", "(JJI)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_FUTURE_CHAR_RES = JniMethod("futureCharResult", "(JJI)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_FUTURE_INT_RES = JniMethod("futureIntResult", "(JJI)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_FUTURE_FLOAT_RES = JniMethod("futureFloatResult", "(JJF)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_FUTURE_LONG_RES = JniMethod("futureLongResult", "(JJJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_FUTURE_DOUBLE_RES = JniMethod("futureDoubleResult", "(JJD)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_FUTURE_OBJ_RES = JniMethod("futureObjectResult", "(JJJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_FUTURE_NULL_RES = JniMethod("futureNullResult", "(JJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_FUTURE_ERR = JniMethod("futureError", "(JJJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_LIFECYCLE_EVENT = JniMethod("lifecycleEvent", "(JJI)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_MESSAGING_FILTER_CREATE = JniMethod("messagingFilterCreate", "(JJ)J", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_MESSAGING_FILTER_APPLY = JniMethod("messagingFilterApply", "(JJJ)I", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_MESSAGING_FILTER_DESTROY = JniMethod("messagingFilterDestroy", "(JJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_EVENT_FILTER_CREATE = JniMethod("eventFilterCreate", "(JJ)J", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_EVENT_FILTER_APPLY = JniMethod("eventFilterApply", "(JJJ)I", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_EVENT_FILTER_DESTROY = JniMethod("eventFilterDestroy", "(JJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_SERVICE_INIT = JniMethod("serviceInit", "(JJ)J", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_SERVICE_EXECUTE = JniMethod("serviceExecute", "(JJJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_SERVICE_CANCEL = JniMethod("serviceCancel", "(JJJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_SERVICE_INVOKE_METHOD = JniMethod("serviceInvokeMethod", "(JJJJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_CLUSTER_NODE_FILTER_APPLY = JniMethod("clusterNodeFilterApply", "(JJ)I", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_NODE_INFO = JniMethod("nodeInfo", "(JJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_MEMORY_REALLOCATE = JniMethod("memoryReallocate", "(JJI)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_ON_START = JniMethod("onStart", "(JLjava/lang/Object;J)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_ON_STOP = JniMethod("onStop", "(J)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_EXTENSION_CALLBACK_IN_LONG_OUT_LONG = JniMethod("extensionCallbackInLongOutLong", "(JIJ)J", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_EXTENSION_CALLBACK_IN_LONG_LONG_OUT_LONG = JniMethod("extensionCallbackInLongLongOutLong", "(JIJJ)J", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_ON_CLIENT_DISCONNECTED = JniMethod("onClientDisconnected", "(J)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_ON_CLIENT_RECONNECTED = JniMethod("onClientReconnected", "(JZ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_LOGGER_LOG = JniMethod("loggerLog", "(JILjava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_LOGGER_IS_LEVEL_ENABLED = JniMethod("loggerIsLevelEnabled", "(JI)Z", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_INIT = JniMethod("affinityFunctionInit", "(JJLorg/apache/ignite/internal/processors/platform/PlatformTargetProxy;)J", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_PARTITION = JniMethod("affinityFunctionPartition", "(JJJ)I", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_ASSIGN_PARTITIONS = JniMethod("affinityFunctionAssignPartitions", "(JJJJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_REMOVE_NODE = JniMethod("affinityFunctionRemoveNode", "(JJJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_DESTROY = JniMethod("affinityFunctionDestroy", "(JJ)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_CONSOLE_WRITE = JniMethod("consoleWrite", "(Ljava/lang/String;Z)V", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_IN_LONG_OUT_LONG = JniMethod("inLongOutLong", "(JIJ)J", true);
JniMethod M_PLATFORM_CALLBACK_UTILS_IN_LONG_LONG_LONG_OBJECT_OUT_LONG = JniMethod("inLongLongLongObjectOutLong", "(JIJJJLjava/lang/Object;)J", true);
const char* C_PLATFORM_UTILS = "org/apache/ignite/internal/processors/platform/utils/PlatformUtils";
JniMethod M_PLATFORM_UTILS_REALLOC = JniMethod("reallocate", "(JI)V", true);
JniMethod M_PLATFORM_UTILS_ERR_DATA = JniMethod("errorData", "(Ljava/lang/Throwable;)[B", true);
JniMethod M_PLATFORM_UTILS_GET_FULL_STACK_TRACE = JniMethod("getFullStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;", true);
const char* C_PLATFORM_IGNITION = "org/apache/ignite/internal/processors/platform/PlatformIgnition";
JniMethod M_PLATFORM_IGNITION_START = JniMethod("start", "(Ljava/lang/String;Ljava/lang/String;IJJ)Lorg/apache/ignite/internal/processors/platform/PlatformProcessor;", true);
JniMethod M_PLATFORM_IGNITION_INSTANCE = JniMethod("instance", "(Ljava/lang/String;)Lorg/apache/ignite/internal/processors/platform/PlatformProcessor;", true);
JniMethod M_PLATFORM_IGNITION_ENVIRONMENT_POINTER = JniMethod("environmentPointer", "(Ljava/lang/String;)J", true);
JniMethod M_PLATFORM_IGNITION_STOP = JniMethod("stop", "(Ljava/lang/String;Z)Z", true);
JniMethod M_PLATFORM_IGNITION_STOP_ALL = JniMethod("stopAll", "(Z)V", true);
/* STATIC STATE. */
gcc::CriticalSection JVM_LOCK;
gcc::CriticalSection CONSOLE_LOCK;
JniJvm JVM;
bool PRINT_EXCEPTION = false;
std::vector<ConsoleWriteHandler> consoleWriteHandlers;
/* HELPER METHODS. */
/**
* Throw exception to Java in case of missing callback pointer. It means that callback is not implemented in
* native platform and Java -> platform operation cannot proceede further. As JniContext is not available at
* this point, we have to obtain exception details from scratch. This is not critical from performance
* perspective because missing handler usually denotes fatal condition.
*
* @param env JNI environment.
*/
int ThrowOnMissingHandler(JNIEnv* env)
{
jclass cls = env->FindClass(C_PLATFORM_NO_CALLBACK_EXCEPTION);
env->ThrowNew(cls, "Callback handler is not set in native platform.");
return 0;
}
/**
* Throw generic exception to Java in case of native exception. As JniContext is not available at
* this point, we have to obtain exception details from scratch. This is not critical from performance
* perspective because such exception is usually denotes fatal condition.
*
* @param env JNI environment.
* @param msg Message.
*/
void ThrowToJava(JNIEnv* env, const char* msg)
{
jclass cls = env->FindClass(C_IGNITE_EXCEPTION);
env->ThrowNew(cls, msg);
}
char* StringToChars(JNIEnv* env, jstring str, int* len) {
if (!str) {
*len = 0;
return NULL;
}
const char* strChars = env->GetStringUTFChars(str, 0);
const int strCharsLen = env->GetStringUTFLength(str);
char* strChars0 = new char[strCharsLen + 1];
std::strcpy(strChars0, strChars);
*(strChars0 + strCharsLen) = 0;
env->ReleaseStringUTFChars(str, strChars);
if (len)
*len = strCharsLen;
return strChars0;
}
std::string JavaStringToCString(JNIEnv* env, jstring str, int* len)
{
char* resChars = StringToChars(env, str, len);
if (resChars)
{
std::string res = std::string(resChars, *len);
delete[] resChars;
return res;
}
else
return std::string();
}
jclass FindClass(JNIEnv* env, const char *name) {
jclass res = env->FindClass(name);
if (!res)
throw JvmException();
jclass res0 = static_cast<jclass>(env->NewGlobalRef(res));
env->DeleteLocalRef(res);
return res0;
}
void DeleteClass(JNIEnv* env, jclass cls) {
if (cls)
env->DeleteGlobalRef(cls);
}
void CheckClass(JNIEnv* env, const char *name)
{
jclass res = env->FindClass(name);
if (!res)
throw JvmException();
}
jmethodID FindMethod(JNIEnv* env, jclass cls, JniMethod mthd) {
jmethodID mthd0 = mthd.isStatic ?
env->GetStaticMethodID(cls, mthd.name, mthd.sign) : env->GetMethodID(cls, mthd.name, mthd.sign);
if (!mthd0)
throw JvmException();
return mthd0;
}
void AddNativeMethod(JNINativeMethod* mthd, JniMethod jniMthd, void* fnPtr) {
mthd->name = jniMthd.name;
mthd->signature = jniMthd.sign;
mthd->fnPtr = fnPtr;
}
void JniJavaMembers::Initialize(JNIEnv* env) {
c_Class = FindClass(env, C_CLASS);
m_Class_getName = FindMethod(env, c_Class, M_CLASS_GET_NAME);
c_Throwable = FindClass(env, C_THROWABLE);
m_Throwable_getMessage = FindMethod(env, c_Throwable, M_THROWABLE_GET_MESSAGE);
m_Throwable_printStackTrace = FindMethod(env, c_Throwable, M_THROWABLE_PRINT_STACK_TRACE);
c_PlatformUtils = FindClass(env, C_PLATFORM_UTILS);
m_PlatformUtils_getFullStackTrace = FindMethod(env, c_PlatformUtils, M_PLATFORM_UTILS_GET_FULL_STACK_TRACE);
}
void JniJavaMembers::Destroy(JNIEnv* env) {
DeleteClass(env, c_Class);
DeleteClass(env, c_Throwable);
DeleteClass(env, c_PlatformUtils);
}
bool JniJavaMembers::WriteErrorInfo(JNIEnv* env, char** errClsName, int* errClsNameLen, char** errMsg,
int* errMsgLen, char** stackTrace, int* stackTraceLen) {
if (env && env->ExceptionCheck()) {
if (m_Class_getName && m_Throwable_getMessage) {
jthrowable err = env->ExceptionOccurred();
env->ExceptionClear();
jclass errCls = env->GetObjectClass(err);
jstring clsName = static_cast<jstring>(env->CallObjectMethod(errCls, m_Class_getName));
*errClsName = StringToChars(env, clsName, errClsNameLen);
jstring msg = static_cast<jstring>(env->CallObjectMethod(err, m_Throwable_getMessage));
*errMsg = StringToChars(env, msg, errMsgLen);
jstring trace = NULL;
if (c_PlatformUtils && m_PlatformUtils_getFullStackTrace) {
trace = static_cast<jstring>(env->CallStaticObjectMethod(c_PlatformUtils, m_PlatformUtils_getFullStackTrace, err));
*stackTrace = StringToChars(env, trace, stackTraceLen);
}
if (errCls)
env->DeleteLocalRef(errCls);
if (clsName)
env->DeleteLocalRef(clsName);
if (msg)
env->DeleteLocalRef(msg);
if (trace)
env->DeleteLocalRef(trace);
return true;
}
else {
env->ExceptionClear();
}
}
return false;
}
void JniMembers::Initialize(JNIEnv* env) {
c_IgniteException = FindClass(env, C_IGNITE_EXCEPTION);
c_PlatformIgnition = FindClass(env, C_PLATFORM_IGNITION);
m_PlatformIgnition_start = FindMethod(env, c_PlatformIgnition, M_PLATFORM_IGNITION_START);
m_PlatformIgnition_instance = FindMethod(env, c_PlatformIgnition, M_PLATFORM_IGNITION_INSTANCE);
m_PlatformIgnition_environmentPointer = FindMethod(env, c_PlatformIgnition, M_PLATFORM_IGNITION_ENVIRONMENT_POINTER);
m_PlatformIgnition_stop = FindMethod(env, c_PlatformIgnition, M_PLATFORM_IGNITION_STOP);
m_PlatformIgnition_stopAll = FindMethod(env, c_PlatformIgnition, M_PLATFORM_IGNITION_STOP_ALL);
c_PlatformProcessor = FindClass(env, C_PLATFORM_PROCESSOR);
m_PlatformProcessor_releaseStart = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_RELEASE_START);
m_PlatformProcessor_cache = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_CACHE);
m_PlatformProcessor_createCache = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_CREATE_CACHE);
m_PlatformProcessor_getOrCreateCache = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_GET_OR_CREATE_CACHE);
m_PlatformProcessor_createCacheFromConfig = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_CREATE_CACHE_FROM_CONFIG);
m_PlatformProcessor_getOrCreateCacheFromConfig = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_GET_OR_CREATE_CACHE_FROM_CONFIG);
m_PlatformProcessor_createNearCache = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_CREATE_NEAR_CACHE);
m_PlatformProcessor_getOrCreateNearCache = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_GET_OR_CREATE_NEAR_CACHE);
m_PlatformProcessor_destroyCache = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_DESTROY_CACHE);
m_PlatformProcessor_affinity = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_AFFINITY);
m_PlatformProcessor_dataStreamer = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_DATA_STREAMER);
m_PlatformProcessor_transactions = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_TRANSACTIONS);
m_PlatformProcessor_projection = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_PROJECTION);
m_PlatformProcessor_compute = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_COMPUTE);
m_PlatformProcessor_message = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_MESSAGE);
m_PlatformProcessor_events = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_EVENTS);
m_PlatformProcessor_services = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_SERVICES);
m_PlatformProcessor_extensions = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_EXTENSIONS);
m_PlatformProcessor_extension = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_EXTENSION);
m_PlatformProcessor_atomicLong = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_ATOMIC_LONG);
m_PlatformProcessor_atomicSequence = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_ATOMIC_SEQUENCE);
m_PlatformProcessor_atomicReference = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_ATOMIC_REFERENCE);
m_PlatformProcessor_getIgniteConfiguration = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_GET_IGNITE_CONFIGURATION);
m_PlatformProcessor_getCacheNames = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_GET_CACHE_NAMES);
m_PlatformProcessor_loggerIsLevelEnabled = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_LOGGER_IS_LEVEL_ENABLED);
m_PlatformProcessor_loggerLog = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_LOGGER_LOG);
m_PlatformProcessor_binaryProcessor = FindMethod(env, c_PlatformProcessor, M_PLATFORM_PROCESSOR_BINARY_PROCESSOR);
c_PlatformTarget = FindClass(env, C_PLATFORM_TARGET);
m_PlatformTarget_inLongOutLong = FindMethod(env, c_PlatformTarget, M_PLATFORM_TARGET_IN_LONG_OUT_LONG);
m_PlatformTarget_inStreamOutLong = FindMethod(env, c_PlatformTarget, M_PLATFORM_TARGET_IN_STREAM_OUT_LONG);
m_PlatformTarget_inStreamOutObject = FindMethod(env, c_PlatformTarget, M_PLATFORM_TARGET_IN_STREAM_OUT_OBJECT);
m_PlatformTarget_outStream = FindMethod(env, c_PlatformTarget, M_PLATFORM_TARGET_OUT_STREAM);
m_PlatformTarget_outObject = FindMethod(env, c_PlatformTarget, M_PLATFORM_TARGET_OUT_OBJECT);
m_PlatformTarget_inStreamOutStream = FindMethod(env, c_PlatformTarget, M_PLATFORM_TARGET_IN_STREAM_OUT_STREAM);
m_PlatformTarget_inObjectStreamOutObjectStream = FindMethod(env, c_PlatformTarget, M_PLATFORM_TARGET_IN_OBJECT_STREAM_OUT_OBJECT_STREAM);
m_PlatformTarget_inStreamAsync = FindMethod(env, c_PlatformTarget, M_PLATFORM_TARGET_IN_STREAM_ASYNC);
c_PlatformUtils = FindClass(env, C_PLATFORM_UTILS);
m_PlatformUtils_reallocate = FindMethod(env, c_PlatformUtils, M_PLATFORM_UTILS_REALLOC);
m_PlatformUtils_errData = FindMethod(env, c_PlatformUtils, M_PLATFORM_UTILS_ERR_DATA);
// Find utility classes which are not used from context, but are still required in other places.
CheckClass(env, C_PLATFORM_NO_CALLBACK_EXCEPTION);
}
void JniMembers::Destroy(JNIEnv* env) {
DeleteClass(env, c_IgniteException);
DeleteClass(env, c_PlatformIgnition);
DeleteClass(env, c_PlatformProcessor);
DeleteClass(env, c_PlatformTarget);
DeleteClass(env, c_PlatformUtils);
}
JniJvm::JniJvm() : jvm(NULL), javaMembers(JniJavaMembers()), members(JniMembers())
{
// No-op.
}
JniJvm::JniJvm(JavaVM* jvm, JniJavaMembers javaMembers, JniMembers members) :
jvm(jvm), javaMembers(javaMembers), members(members)
{
// No-op.
}
JavaVM* JniJvm::GetJvm()
{
return jvm;
}
JniJavaMembers& JniJvm::GetJavaMembers()
{
return javaMembers;
}
JniMembers& JniJvm::GetMembers()
{
return members;
}
/**
* Create JVM.
*/
jint CreateJvm(char** opts, int optsLen, JavaVM** jvm, JNIEnv** env) {
JavaVMOption* opts0 = new JavaVMOption[optsLen];
for (int i = 0; i < optsLen; i++)
opts0[i].optionString = *(opts + i);
JavaVMInitArgs args;
args.version = JNI_VERSION_1_6;
args.nOptions = optsLen;
args.options = opts0;
args.ignoreUnrecognized = 0;
jint res = JNI_CreateJavaVM(jvm, reinterpret_cast<void**>(env), &args);
delete[] opts0;
return res;
}
void RegisterNatives(JNIEnv* env) {
{
JNINativeMethod methods[5];
int idx = 0;
AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_CONSOLE_WRITE, reinterpret_cast<void*>(JniConsoleWrite));
AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_LOG, reinterpret_cast<void*>(JniLoggerLog));
AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_IS_LEVEL_ENABLED, reinterpret_cast<void*>(JniLoggerIsLevelEnabled));
AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_IN_LONG_OUT_LONG, reinterpret_cast<void*>(JniInLongOutLong));
AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_IN_LONG_LONG_LONG_OBJECT_OUT_LONG, reinterpret_cast<void*>(JniInLongLongLongObjectOutLong));
jint res = env->RegisterNatives(FindClass(env, C_PLATFORM_CALLBACK_UTILS), methods, idx);
if (res != JNI_OK)
throw JvmException();
}
}
JniContext::JniContext(JniJvm* jvm, JniHandlers hnds) : jvm(jvm), hnds(hnds) {
// No-op.
}
JniContext* JniContext::Create(char** opts, int optsLen, JniHandlers hnds) {
return Create(opts, optsLen, hnds, NULL);
}
void GetJniErrorMessage(std::string& errMsg, jint res)
{
switch (res)
{
case JNI_ERR:
errMsg = "Unknown error (JNI_ERR).";
break;
case JNI_EDETACHED:
errMsg = "Thread detached from the JVM.";
break;
case JNI_EVERSION:
errMsg = "JNI version error.";
break;
case JNI_ENOMEM:
errMsg = "Could not reserve enough space for object heap. Check Xmx option.";
break;
case JNI_EEXIST:
errMsg = "JVM already created.";
break;
case JNI_EINVAL:
errMsg = "Invalid JVM arguments.";
break;
default:
errMsg = "Unexpected JNI_CreateJavaVM result.";
break;
}
}
JniContext* JniContext::Create(char** opts, int optsLen, JniHandlers hnds, JniErrorInfo* errInfo)
{
// Acquire global lock to instantiate the JVM.
JVM_LOCK.Enter();
// Define local variables.
JavaVM* jvm = NULL;
JNIEnv* env = NULL;
JniJavaMembers javaMembers;
memset(&javaMembers, 0, sizeof(javaMembers));
JniMembers members;
memset(&members, 0, sizeof(members));
JniContext* ctx = NULL;
std::string errClsName;
int errClsNameLen = 0;
std::string errMsg;
int errMsgLen = 0;
std::string stackTrace;
int stackTraceLen = 0;
try {
if (!JVM.GetJvm())
{
// 1. Create JVM itself.
jint res = CreateJvm(opts, optsLen, &jvm, &env);
if (res == JNI_OK)
{
// 2. Populate members;
javaMembers.Initialize(env);
members.Initialize(env);
// 3. Register native functions.
RegisterNatives(env);
// 4. Create JNI JVM.
JVM = JniJvm(jvm, javaMembers, members);
char* printStack = getenv("IGNITE_CPP_PRINT_STACK");
PRINT_EXCEPTION = printStack && strcmp("true", printStack) == 0;
}
else
{
GetJniErrorMessage(errMsg, res);
errMsgLen = static_cast<int>(errMsg.length());
}
}
if (JVM.GetJvm())
ctx = new JniContext(&JVM, hnds);
}
catch (JvmException)
{
char* errClsNameChars = NULL;
char* errMsgChars = NULL;
char* stackTraceChars = NULL;
// Read error info if possible.
javaMembers.WriteErrorInfo(env, &errClsNameChars, &errClsNameLen, &errMsgChars, &errMsgLen,
&stackTraceChars, &stackTraceLen);
if (errClsNameChars) {
errClsName = errClsNameChars;
delete[] errClsNameChars;
}
if (errMsgChars)
{
errMsg = errMsgChars;
delete[] errMsgChars;
}
if (stackTraceChars)
{
stackTrace = stackTraceChars;
delete[] stackTraceChars;
}
// Destroy mmebers.
if (env) {
members.Destroy(env);
javaMembers.Destroy(env);
}
// Destroy faulty JVM.
if (jvm)
jvm->DestroyJavaVM();
}
// It safe to release the lock at this point.
JVM_LOCK.Leave();
// Notify err callback if needed.
if (!ctx) {
if (errInfo) {
JniErrorInfo errInfo0(IGNITE_JNI_ERR_JVM_INIT, errClsName.c_str(), errMsg.c_str());
*errInfo = errInfo0;
}
if (hnds.error)
hnds.error(hnds.target, IGNITE_JNI_ERR_JVM_INIT, errClsName.c_str(), errClsNameLen,
errMsg.c_str(), errMsgLen, stackTrace.c_str(), stackTraceLen, NULL, 0);
}
return ctx;
}
int JniContext::Reallocate(long long memPtr, int cap) {
JavaVM* jvm = JVM.GetJvm();
JNIEnv* env;
int attachRes = jvm->AttachCurrentThread(reinterpret_cast<void**>(&env), NULL);
if (attachRes == JNI_OK)
AttachHelper::OnThreadAttach();
else
return -1;
env->CallStaticVoidMethod(JVM.GetMembers().c_PlatformUtils, JVM.GetMembers().m_PlatformUtils_reallocate, memPtr, cap);
if (env->ExceptionCheck()) {
env->ExceptionClear();
return -1;
}
return 0;
}
void JniContext::Detach() {
gcc::Memory::Fence();
if (JVM.GetJvm()) {
JNIEnv* env;
JVM.GetJvm()->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
if (env)
JVM.GetJvm()->DetachCurrentThread();
}
}
jobject JniContext::IgnitionStart(char* cfgPath, char* name, int factoryId, long long dataPtr) {
return IgnitionStart(cfgPath, name, factoryId, dataPtr, NULL);
}
jobject JniContext::IgnitionStart(char* cfgPath, char* name, int factoryId, long long dataPtr, JniErrorInfo* errInfo)
{
JNIEnv* env = Attach();
jstring cfgPath0 = env->NewStringUTF(cfgPath);
jstring name0 = env->NewStringUTF(name);
jobject interop = env->CallStaticObjectMethod(
jvm->GetMembers().c_PlatformIgnition,
jvm->GetMembers().m_PlatformIgnition_start,
cfgPath0,
name0,
factoryId,
reinterpret_cast<long long>(&hnds),
dataPtr
);
ExceptionCheck(env, errInfo);
return LocalToGlobal(env, interop);
}
jobject JniContext::IgnitionInstance(char* name)
{
return IgnitionInstance(name, NULL);
}
jobject JniContext::IgnitionInstance(char* name, JniErrorInfo* errInfo)
{
JNIEnv* env = Attach();
jstring name0 = env->NewStringUTF(name);
jobject interop = env->CallStaticObjectMethod(jvm->GetMembers().c_PlatformIgnition,
jvm->GetMembers().m_PlatformIgnition_instance, name0);
ExceptionCheck(env, errInfo);
return LocalToGlobal(env, interop);
}
long long JniContext::IgnitionEnvironmentPointer(char* name)
{
return IgnitionEnvironmentPointer(name, NULL);
}
long long JniContext::IgnitionEnvironmentPointer(char* name, JniErrorInfo* errInfo)
{
JNIEnv* env = Attach();
jstring name0 = env->NewStringUTF(name);
long long res = env->CallStaticLongMethod(jvm->GetMembers().c_PlatformIgnition,
jvm->GetMembers().m_PlatformIgnition_environmentPointer, name0);
ExceptionCheck(env, errInfo);
return res;
}
bool JniContext::IgnitionStop(char* name, bool cancel)
{
return IgnitionStop(name, cancel, NULL);
}
bool JniContext::IgnitionStop(char* name, bool cancel, JniErrorInfo* errInfo)
{
JNIEnv* env = Attach();
jstring name0 = env->NewStringUTF(name);
jboolean res = env->CallStaticBooleanMethod(jvm->GetMembers().c_PlatformIgnition,
jvm->GetMembers().m_PlatformIgnition_stop, name0, cancel);
ExceptionCheck(env, errInfo);
return res != 0;
}
void JniContext::IgnitionStopAll(bool cancel)
{
return IgnitionStopAll(cancel, NULL);
}
void JniContext::IgnitionStopAll(bool cancel, JniErrorInfo* errInfo)
{
JNIEnv* env = Attach();
env->CallStaticVoidMethod(jvm->GetMembers().c_PlatformIgnition,
jvm->GetMembers().m_PlatformIgnition_stopAll, cancel);
ExceptionCheck(env, errInfo);
}
void JniContext::ProcessorReleaseStart(jobject obj) {
JNIEnv* env = Attach();
env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformProcessor_releaseStart);
ExceptionCheck(env);
}
jobject JniContext::ProcessorProjection(jobject obj, JniErrorInfo* errInfo) {
JNIEnv* env = Attach();
jobject prj = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_projection);
ExceptionCheck(env, errInfo);
return LocalToGlobal(env, prj);
}
jobject JniContext::ProcessorCache0(jobject obj, const char* name, jmethodID mthd, JniErrorInfo* errInfo)
{
JNIEnv* env = Attach();
jstring name0 = name != NULL ? env->NewStringUTF(name) : NULL;
jobject cache = env->CallObjectMethod(obj, mthd, name0);
if (name0)
env->DeleteLocalRef(name0);
ExceptionCheck(env, errInfo);
return LocalToGlobal(env, cache);
}
jobject JniContext::ProcessorCacheFromConfig0(jobject obj, long long memPtr, jmethodID mthd, JniErrorInfo* errInfo)
{
JNIEnv* env = Attach();
jobject cache = env->CallObjectMethod(obj, mthd, memPtr);
ExceptionCheck(env, errInfo);
return LocalToGlobal(env, cache);
}
jobject JniContext::ProcessorCache(jobject obj, const char* name) {
return ProcessorCache(obj, name, NULL);
}
jobject JniContext::ProcessorCache(jobject obj, const char* name, JniErrorInfo* errInfo) {
return ProcessorCache0(obj, name, jvm->GetMembers().m_PlatformProcessor_cache, errInfo);
}
jobject JniContext::ProcessorCreateCache(jobject obj, const char* name) {
return ProcessorCreateCache(obj, name, NULL);
}
jobject JniContext::ProcessorCreateCache(jobject obj, const char* name, JniErrorInfo* errInfo)
{
return ProcessorCache0(obj, name, jvm->GetMembers().m_PlatformProcessor_createCache, errInfo);
}
jobject JniContext::ProcessorGetOrCreateCache(jobject obj, const char* name) {
return ProcessorGetOrCreateCache(obj, name, NULL);
}
jobject JniContext::ProcessorGetOrCreateCache(jobject obj, const char* name, JniErrorInfo* errInfo)
{
return ProcessorCache0(obj, name, jvm->GetMembers().m_PlatformProcessor_getOrCreateCache, errInfo);
}
void JniContext::ProcessorDestroyCache(jobject obj, const char* name) {
ProcessorDestroyCache(obj, name, NULL);
}
void JniContext::ProcessorDestroyCache(jobject obj, const char* name, JniErrorInfo* errInfo)
{
JNIEnv* env = Attach();
jstring name0 = name != NULL ? env->NewStringUTF(name) : NULL;
env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformProcessor_destroyCache, name0);
if (name0)
env->DeleteLocalRef(name0);
ExceptionCheck(env, errInfo);
}
jobject JniContext::ProcessorCreateCacheFromConfig(jobject obj, long long memPtr) {
return ProcessorCreateCacheFromConfig(obj, memPtr, NULL);
}
jobject JniContext::ProcessorCreateCacheFromConfig(jobject obj, long long memPtr, JniErrorInfo* errInfo)
{
return ProcessorCacheFromConfig0(obj, memPtr, jvm->GetMembers().m_PlatformProcessor_createCacheFromConfig, errInfo);
}
jobject JniContext::ProcessorGetOrCreateCacheFromConfig(jobject obj, long long memPtr) {
return ProcessorGetOrCreateCacheFromConfig(obj, memPtr, NULL);
}
jobject JniContext::ProcessorGetOrCreateCacheFromConfig(jobject obj, long long memPtr, JniErrorInfo* errInfo)
{
return ProcessorCacheFromConfig0(obj, memPtr, jvm->GetMembers().m_PlatformProcessor_getOrCreateCacheFromConfig, errInfo);
}
jobject JniContext::ProcessorCreateNearCache(jobject obj, const char* name, long long memPtr)
{
return ProcessorGetOrCreateNearCache0(obj, name, memPtr, jvm->GetMembers().m_PlatformProcessor_createNearCache);
}
jobject JniContext::ProcessorGetOrCreateNearCache(jobject obj, const char* name, long long memPtr)
{
return ProcessorGetOrCreateNearCache0(obj, name, memPtr, jvm->GetMembers().m_PlatformProcessor_getOrCreateNearCache);
}
jobject JniContext::ProcessorGetOrCreateNearCache0(jobject obj, const char* name, long long memPtr, jmethodID methodID)
{
JNIEnv* env = Attach();
jstring name0 = name != NULL ? env->NewStringUTF(name) : NULL;
jobject cache = env->CallObjectMethod(obj, methodID, name0, memPtr);
if (name0)
env->DeleteLocalRef(name0);
ExceptionCheck(env);
return LocalToGlobal(env, cache);
}
jobject JniContext::ProcessorAffinity(jobject obj, const char* name) {
JNIEnv* env = Attach();
jstring name0 = name != NULL ? env->NewStringUTF(name) : NULL;
jobject aff = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_affinity, name0);
if (name0)
env->DeleteLocalRef(name0);
ExceptionCheck(env);
return LocalToGlobal(env, aff);
}
jobject JniContext::ProcessorDataStreamer(jobject obj, const char* name, bool keepPortable) {
JNIEnv* env = Attach();
jstring name0 = name != NULL ? env->NewStringUTF(name) : NULL;
jobject ldr = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_dataStreamer, name0,
keepPortable);
if (name0)
env->DeleteLocalRef(name0);
ExceptionCheck(env);
return LocalToGlobal(env, ldr);
}
jobject JniContext::ProcessorTransactions(jobject obj, JniErrorInfo* errInfo) {
JNIEnv* env = Attach();
jobject tx = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_transactions);
ExceptionCheck(env, errInfo);
return LocalToGlobal(env, tx);
}
jobject JniContext::ProcessorCompute(jobject obj, jobject prj) {
JNIEnv* env = Attach();
jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_compute, prj);
ExceptionCheck(env);
return LocalToGlobal(env, res);
}
jobject JniContext::ProcessorMessage(jobject obj, jobject prj) {
JNIEnv* env = Attach();
jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_message, prj);
ExceptionCheck(env);
return LocalToGlobal(env, res);
}
jobject JniContext::ProcessorEvents(jobject obj, jobject prj) {
JNIEnv* env = Attach();
jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_events, prj);
ExceptionCheck(env);
return LocalToGlobal(env, res);
}
jobject JniContext::ProcessorServices(jobject obj, jobject prj) {
JNIEnv* env = Attach();
jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_services, prj);
ExceptionCheck(env);
return LocalToGlobal(env, res);
}
jobject JniContext::ProcessorExtensions(jobject obj)
{
JNIEnv* env = Attach();
jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_extensions);
ExceptionCheck(env);
return LocalToGlobal(env, res);
}
jobject JniContext::ProcessorExtension(jobject obj, int id)
{
JNIEnv* env = Attach();
jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_extension, id);
ExceptionCheck(env);
return LocalToGlobal(env, res);
}
jobject JniContext::ProcessorAtomicLong(jobject obj, char* name, long long initVal, bool create)
{
JNIEnv* env = Attach();
jstring name0 = name != NULL ? env->NewStringUTF(name) : NULL;
jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_atomicLong, name0, initVal, create);
if (name0)
env->DeleteLocalRef(name0);
ExceptionCheck(env);
return LocalToGlobal(env, res);
}
jobject JniContext::ProcessorAtomicSequence(jobject obj, char* name, long long initVal, bool create)
{
JNIEnv* env = Attach();
jstring name0 = name != NULL ? env->NewStringUTF(name) : NULL;
jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_atomicSequence, name0, initVal, create);
if (name0)
env->DeleteLocalRef(name0);
ExceptionCheck(env);
return LocalToGlobal(env, res);
}
jobject JniContext::ProcessorAtomicReference(jobject obj, char* name, long long memPtr, bool create)
{
JNIEnv* env = Attach();
jstring name0 = name != NULL ? env->NewStringUTF(name) : NULL;
jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_atomicReference, name0, memPtr, create);
if (name0)
env->DeleteLocalRef(name0);
ExceptionCheck(env);
return LocalToGlobal(env, res);
}
void JniContext::ProcessorGetIgniteConfiguration(jobject obj, long long memPtr)
{
JNIEnv* env = Attach();
env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformProcessor_getIgniteConfiguration, memPtr);
ExceptionCheck(env);
}
void JniContext::ProcessorGetCacheNames(jobject obj, long long memPtr)
{
JNIEnv* env = Attach();
env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformProcessor_getCacheNames, memPtr);
ExceptionCheck(env);
}
long long JniContext::TargetInLongOutLong(jobject obj, int opType, long long val, JniErrorInfo* err) {
JNIEnv* env = Attach();
long long res = env->CallLongMethod(obj, jvm->GetMembers().m_PlatformTarget_inLongOutLong, opType, val);
ExceptionCheck(env, err);
return res;
}
bool JniContext::ProcessorLoggerIsLevelEnabled(jobject obj, int level)
{
JNIEnv* env = Attach();
jboolean res = env->CallBooleanMethod(obj, jvm->GetMembers().m_PlatformProcessor_loggerIsLevelEnabled, level);
ExceptionCheck(env);
return res != 0;
}
void JniContext::ProcessorLoggerLog(jobject obj, int level, char* message, char* category, char* errorInfo)
{
JNIEnv* env = Attach();
jstring message0 = message != NULL ? env->NewStringUTF(message) : NULL;
jstring category0 = category != NULL ? env->NewStringUTF(category) : NULL;
jstring errorInfo0 = errorInfo != NULL ? env->NewStringUTF(errorInfo) : NULL;
env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformProcessor_loggerLog, level, message0, category0, errorInfo0);
if (message0)
env->DeleteLocalRef(message0);
if (category0)
env->DeleteLocalRef(category0);
if (errorInfo0)
env->DeleteLocalRef(errorInfo0);
ExceptionCheck(env);
}
jobject JniContext::ProcessorBinaryProcessor(jobject obj)
{
JNIEnv* env = Attach();
jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformProcessor_binaryProcessor);
ExceptionCheck(env);
return LocalToGlobal(env, res);
}
long long JniContext::TargetInStreamOutLong(jobject obj, int opType, long long memPtr, JniErrorInfo* err) {
JNIEnv* env = Attach();
long long res = env->CallLongMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamOutLong, opType, memPtr);
ExceptionCheck(env, err);
return res;
}
void JniContext::TargetInStreamOutStream(jobject obj, int opType, long long inMemPtr, long long outMemPtr, JniErrorInfo* err) {
JNIEnv* env = Attach();
env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamOutStream, opType, inMemPtr, outMemPtr);
ExceptionCheck(env, err);
}
jobject JniContext::TargetInStreamOutObject(jobject obj, int opType, long long memPtr, JniErrorInfo* err) {
JNIEnv* env = Attach();
jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamOutObject, opType, memPtr);
ExceptionCheck(env, err);
return LocalToGlobal(env, res);
}
jobject JniContext::TargetInObjectStreamOutObjectStream(jobject obj, int opType, void* arg, long long inMemPtr, long long outMemPtr, JniErrorInfo* err) {
JNIEnv* env = Attach();
jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformTarget_inObjectStreamOutObjectStream, opType, arg, inMemPtr, outMemPtr);
ExceptionCheck(env, err);
return LocalToGlobal(env, res);
}
void JniContext::TargetOutStream(jobject obj, int opType, long long memPtr, JniErrorInfo* err) {
JNIEnv* env = Attach();
env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformTarget_outStream, opType, memPtr);
ExceptionCheck(env, err);
}
jobject JniContext::TargetOutObject(jobject obj, int opType, JniErrorInfo* err)
{
JNIEnv* env = Attach();
jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformTarget_outObject, opType);
ExceptionCheck(env, err);
return LocalToGlobal(env, res);
}
void JniContext::TargetInStreamAsync(jobject obj, int opType, long long memPtr, JniErrorInfo* err) {
JNIEnv* env = Attach();
env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamAsync, opType, memPtr);
ExceptionCheck(env, err);
}
jobject JniContext::CacheOutOpQueryCursor(jobject obj, int type, long long memPtr, JniErrorInfo* err) {
JNIEnv* env = Attach();
jobject res = env->CallObjectMethod(
obj, jvm->GetMembers().m_PlatformTarget_inStreamOutObject, type, memPtr);
ExceptionCheck(env, err);
return LocalToGlobal(env, res);
}
jobject JniContext::CacheOutOpContinuousQuery(jobject obj, int type, long long memPtr, JniErrorInfo* err) {
JNIEnv* env = Attach();
jobject res = env->CallObjectMethod(
obj, jvm->GetMembers().m_PlatformTarget_inStreamOutObject, type, memPtr);
ExceptionCheck(env, err);
return LocalToGlobal(env, res);
}
jobject JniContext::Acquire(jobject obj)
{
if (obj) {
JNIEnv* env = Attach();
jobject obj0 = env->NewGlobalRef(obj);
ExceptionCheck(env);
return obj0;
}
return NULL;
}
void JniContext::Release(jobject obj) {
if (obj)
{
JavaVM* jvm = JVM.GetJvm();
if (jvm)
{
JNIEnv* env;
jint attachRes = jvm->AttachCurrentThread(reinterpret_cast<void**>(&env), NULL);
if (attachRes == JNI_OK)
{
AttachHelper::OnThreadAttach();
env->DeleteGlobalRef(obj);
}
}
}
}
void JniContext::SetConsoleHandler(ConsoleWriteHandler consoleHandler) {
if (!consoleHandler)
throw std::invalid_argument("consoleHandler can not be null");
CONSOLE_LOCK.Enter();
consoleWriteHandlers.push_back(consoleHandler);
CONSOLE_LOCK.Leave();
}
int JniContext::RemoveConsoleHandler(ConsoleWriteHandler consoleHandler) {
if (!consoleHandler)
throw std::invalid_argument("consoleHandler can not be null");
CONSOLE_LOCK.Enter();
int oldSize = static_cast<int>(consoleWriteHandlers.size());
consoleWriteHandlers.erase(remove(consoleWriteHandlers.begin(), consoleWriteHandlers.end(),
consoleHandler), consoleWriteHandlers.end());
int removedCnt = oldSize - static_cast<int>(consoleWriteHandlers.size());
CONSOLE_LOCK.Leave();
return removedCnt;
}
void JniContext::ThrowToJava(char* msg) {
JNIEnv* env = Attach();
env->ThrowNew(jvm->GetMembers().c_IgniteException, msg);
}
void JniContext::DestroyJvm() {
jvm->GetJvm()->DestroyJavaVM();
}
/**
* Attach thread to JVM.
*/
JNIEnv* JniContext::Attach() {
JNIEnv* env;
jint attachRes = jvm->GetJvm()->AttachCurrentThread(reinterpret_cast<void**>(&env), NULL);
if (attachRes == JNI_OK)
AttachHelper::OnThreadAttach();
else {
if (hnds.error)
hnds.error(hnds.target, IGNITE_JNI_ERR_JVM_ATTACH, NULL, 0, NULL, 0, NULL, 0, NULL, 0);
}
return env;
}
void JniContext::ExceptionCheck(JNIEnv* env) {
ExceptionCheck(env, NULL);
}
void JniContext::ExceptionCheck(JNIEnv* env, JniErrorInfo* errInfo)
{
if (env->ExceptionCheck()) {
jthrowable err = env->ExceptionOccurred();
if (PRINT_EXCEPTION)
env->CallVoidMethod(err, jvm->GetJavaMembers().m_Throwable_printStackTrace);
env->ExceptionClear();
// Get error class name and message.
jclass cls = env->GetObjectClass(err);
jstring clsName = static_cast<jstring>(env->CallObjectMethod(cls, jvm->GetJavaMembers().m_Class_getName));
jstring msg = static_cast<jstring>(env->CallObjectMethod(err, jvm->GetJavaMembers().m_Throwable_getMessage));
jstring trace = static_cast<jstring>(env->CallStaticObjectMethod(jvm->GetJavaMembers().c_PlatformUtils, jvm->GetJavaMembers().m_PlatformUtils_getFullStackTrace, err));
env->DeleteLocalRef(cls);
int clsNameLen;
std::string clsName0 = JavaStringToCString(env, clsName, &clsNameLen);
int msgLen;
std::string msg0 = JavaStringToCString(env, msg, &msgLen);
int traceLen;
std::string trace0 = JavaStringToCString(env, trace, &traceLen);
if (errInfo)
{
JniErrorInfo errInfo0(IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), msg0.c_str());
*errInfo = errInfo0;
}
// Get error additional data (if any).
jbyteArray errData = static_cast<jbyteArray>(env->CallStaticObjectMethod(
jvm->GetMembers().c_PlatformUtils, jvm->GetMembers().m_PlatformUtils_errData, err));
if (errData)
{
jbyte* errBytesNative = env->GetByteArrayElements(errData, NULL);
int errBytesLen = env->GetArrayLength(errData);
if (hnds.error)
hnds.error(hnds.target, IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), clsNameLen, msg0.c_str(),
msgLen, trace0.c_str(), traceLen, errBytesNative, errBytesLen);
env->ReleaseByteArrayElements(errData, errBytesNative, JNI_ABORT);
}
else
{
if (hnds.error)
hnds.error(hnds.target, IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), clsNameLen, msg0.c_str(),
msgLen, trace0.c_str(), traceLen, NULL, 0);
}
env->DeleteLocalRef(err);
}
}
/**
* Convert local reference to global.
*/
jobject JniContext::LocalToGlobal(JNIEnv* env, jobject localRef) {
if (localRef) {
jobject globalRef = env->NewGlobalRef(localRef);
env->DeleteLocalRef(localRef); // Clear local ref irrespective of result.
if (!globalRef)
ExceptionCheck(env);
return globalRef;
}
else
return NULL;
}
JNIEXPORT void JNICALL JniConsoleWrite(JNIEnv *env, jclass cls, jstring str, jboolean isErr) {
CONSOLE_LOCK.Enter();
if (consoleWriteHandlers.size() > 0) {
ConsoleWriteHandler consoleWrite = consoleWriteHandlers.at(0);
const char* strChars = env->GetStringUTFChars(str, 0);
const int strCharsLen = env->GetStringUTFLength(str);
consoleWrite(strChars, strCharsLen, isErr);
env->ReleaseStringUTFChars(str, strChars);
}
CONSOLE_LOCK.Leave();
}
JNIEXPORT void JNICALL JniLoggerLog(JNIEnv *env, jclass cls, jlong envPtr, jint level, jstring message, jstring category, jstring errorInfo, jlong memPtr) {
int messageLen;
char* messageChars = StringToChars(env, message, &messageLen);
int categoryLen;
char* categoryChars = StringToChars(env, category, &categoryLen);
int errorInfoLen;
char* errorInfoChars = StringToChars(env, errorInfo, &errorInfoLen);
IGNITE_SAFE_PROC(env, envPtr, LoggerLogHandler, loggerLog, level, messageChars, messageLen, categoryChars, categoryLen, errorInfoChars, errorInfoLen, memPtr);
if (messageChars)
delete[] messageChars;
if (categoryChars)
delete[] categoryChars;
if (errorInfoChars)
delete[] errorInfoChars;
}
JNIEXPORT jboolean JNICALL JniLoggerIsLevelEnabled(JNIEnv *env, jclass cls, jlong envPtr, jint level) {
IGNITE_SAFE_FUNC(env, envPtr, LoggerIsLevelEnabledHandler, loggerIsLevelEnabled, level);
}
JNIEXPORT jlong JNICALL JniInLongOutLong(JNIEnv *env, jclass cls, jlong envPtr, jint type, jlong val) {
IGNITE_SAFE_FUNC(env, envPtr, InLongOutLongHandler, inLongOutLong, type, val);
}
JNIEXPORT jlong JNICALL JniInLongLongLongObjectOutLong(JNIEnv *env, jclass cls, jlong envPtr, jint type, jlong val1, jlong val2, jlong val3, jobject arg) {
IGNITE_SAFE_FUNC(env, envPtr, InLongLongLongObjectOutLongHandler, inLongLongLongObjectOutLong, type, val1, val2, val3, arg);
}
}
}
}