# ignite-496
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/39f9760b Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/39f9760b Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/39f9760b Branch: refs/heads/ignite-496 Commit: 39f9760bb591175d513144fc8288a14e9c65baba Parents: 08cb065 Author: sboikov <semen.boi...@inria.fr> Authored: Mon Mar 23 22:05:38 2015 +0300 Committer: sboikov <semen.boi...@inria.fr> Committed: Mon Mar 23 23:35:21 2015 +0300 ---------------------------------------------------------------------- .../src/main/cpp/include/ignite-interop-api.h | 180 ++++++++++++++++--- .../src/main/cpp/src/ignite-interop-api.cpp | 107 ++++++----- .../src/test/cpp/ingite-interop-api-test.cpp | 39 +++- 3 files changed, 256 insertions(+), 70 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/39f9760b/modules/interop-api/src/main/cpp/include/ignite-interop-api.h ---------------------------------------------------------------------- diff --git a/modules/interop-api/src/main/cpp/include/ignite-interop-api.h b/modules/interop-api/src/main/cpp/include/ignite-interop-api.h index 7049cd5..60e5907 100644 --- a/modules/interop-api/src/main/cpp/include/ignite-interop-api.h +++ b/modules/interop-api/src/main/cpp/include/ignite-interop-api.h @@ -18,7 +18,7 @@ #ifndef IGNITE_INTEROP_API #define IGNITE_INTEROP_API -#if defined(__CYGWIN__) || defined(_WINDLL) +#if defined(__CYGWIN__) || defined(_WIN32) # ifdef IGNITE_API_EXPORT # define IGNITE_API_IMPORT_EXPORT __declspec(dllexport) # else @@ -28,37 +28,167 @@ # define IGNITE_API_IMPORT_EXPORT #endif +#include <stdint.h> #include <string> namespace ignite { /** - * Ignite exception. - */ - class IGNITE_API_IMPORT_EXPORT IgniteException: public std::exception { - public: - /** - * Constructor of exception with message text. - * - * @param what Exception text. - */ - IgniteException(const std::string& what) : what_(what) { - // No-op. - } - - virtual const char* what() const throw() { - return what_.c_str(); - } + * Callback to handle Java errors. + */ + typedef void(*IgniteErrorCallback)(const std::string& errMsg, const std::string& errCls); - private: - std::string what_; - }; /** * Callback for asynchronous operations. */ typedef void(*IgniteAsyncCallback)(void* data, int resType, void* res); - class IgniteJvm; + class IgniteInputStream { + public: + IgniteInputStream(uint64_t dataPtr, int32_t size, int32_t allocSize) : + dataPtr(dataPtr), size(size), allocSize(allocSize), readPos(0) { + assert(dataPtr); + assert(size > 0); + assert(allocSize > 0); + } + + IgniteInputStream(void* dataPtr, int32_t size, int32_t allocSize) : + dataPtr(reinterpret_cast<uint64_t>(dataPtr)), size(size), allocSize(allocSize), readPos(0) { + assert(dataPtr); + assert(size > 0); + assert(allocSize > 0); + } + + int8_t readByte() { + checkAvailable(1); + + int8_t res = *reinterpret_cast<int8_t*>(dataPtr + readPos); + + readPos++; + + return res; + } + + int32_t readInt() { + checkAvailable(4); + + int32_t res = *reinterpret_cast<int32_t*>(dataPtr + readPos); + + readPos += 4; + + return res; + } + + int64_t readLong() { + checkAvailable(8); + + int64_t res = *reinterpret_cast<int64_t*>(dataPtr + readPos); + + readPos += 8; + + return res; + } + + private: + void checkAvailable(int32_t cnt) { + assert(readPos + cnt <= size); + } + + uint64_t dataPtr; + + int32_t size; + + int32_t allocSize; + + int32_t readPos; + }; + + class IgniteOutputStream { + public: + /** + * @param initialSize Initially allocated size. + */ + IgniteOutputStream(int initialSize) : allocSize(initialSize), pos(0) { + assert(initialSize > 0); + + dataPtr = reinterpret_cast<uint64_t>(malloc(initialSize)); + } + + ~IgniteOutputStream() { + free(reinterpret_cast<void*>(dataPtr)); + } + + /** + * @param val Value to write. + */ + void writeBool(bool val) { + writeByte(val ? 1 : 0); + } + + /** + * @param val Value to write. + */ + void writeByte(int8_t val) { + resizeIfNeeded(1); + + *reinterpret_cast<int8_t*>(dataPtr + pos) = val; + + pos++; + } + + void writeInt(int32_t val) { + resizeIfNeeded(4); + + *reinterpret_cast<int32_t*>(dataPtr + pos) = val; + + pos += 4; + } + + void writeLong(int64_t val) { + resizeIfNeeded(8); + + *reinterpret_cast<int64_t*>(dataPtr + pos) = val; + + pos += 8; + } + + uint64_t dataPointer() { + return dataPtr; + } + + int32_t position() { + return pos; + } + + int32_t allocatedSize() { + return allocSize; + } + + private: + /** + * @param cnt Resize byte count. + */ + void resizeIfNeeded(int32_t cnt) { + int32_t newSize = pos + cnt; + + if (newSize > allocSize) { + allocSize *= 2; + + if (newSize > allocSize) + allocSize = newSize; + + dataPtr = reinterpret_cast<uint64_t>(realloc(reinterpret_cast<void*>(dataPtr), allocSize)); + } + } + + uint64_t dataPtr; + + int32_t pos; + + int32_t allocSize; + }; + + class IgniteJvm; class IgniteCache; class IGNITE_API_IMPORT_EXPORT Ignite { @@ -103,15 +233,15 @@ namespace ignite { public: ~IgniteJvm(); - Ignite* startIgnite(char* cfgPath, char* igniteName) throw(IgniteException); + Ignite* startIgnite(char* cfgPath, char* igniteName); class Context; private: - IgniteJvm(); + IgniteJvm(IgniteErrorCallback errCb); Context* ctx; - friend IGNITE_API_IMPORT_EXPORT IgniteJvm* testIgniteJvmStart(); + friend IGNITE_API_IMPORT_EXPORT IgniteJvm* testIgniteJvmStart(IgniteErrorCallback errCb); friend class Ignite; @@ -121,7 +251,7 @@ namespace ignite { /** * Initialization function for test. */ - IGNITE_API_IMPORT_EXPORT extern IgniteJvm* testIgniteJvmStart(); + IGNITE_API_IMPORT_EXPORT extern IgniteJvm* testIgniteJvmStart(IgniteErrorCallback errCb); } #endif http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/39f9760b/modules/interop-api/src/main/cpp/src/ignite-interop-api.cpp ---------------------------------------------------------------------- diff --git a/modules/interop-api/src/main/cpp/src/ignite-interop-api.cpp b/modules/interop-api/src/main/cpp/src/ignite-interop-api.cpp index 6e260c6..e5728b4 100644 --- a/modules/interop-api/src/main/cpp/src/ignite-interop-api.cpp +++ b/modules/interop-api/src/main/cpp/src/ignite-interop-api.cpp @@ -86,6 +86,12 @@ namespace ignite { */ class IgniteJvm::Context { public: + Context(IgniteErrorCallback errCb) : errCb(errCb) { + // No-op. + } + + IgniteErrorCallback errCb; + JavaVM* jvm; jclass c_Throwable; @@ -143,16 +149,19 @@ namespace ignite { } /* - * Clear pending exception and throw it. Callee of this method must first ensure + * Clear pending exception and call error callback. Callee of this method must first ensure * that exception really happened. */ - void clearAndThrow(JNIEnv* env, IgniteJvm::Context* jvmCtx) throw(IgniteException) { + void clearErrorAndRunCallback(JNIEnv* env, IgniteJvm::Context* jvmCtx) { assert (env->ExceptionCheck()); jthrowable err = env->ExceptionOccurred(); - if (!err) - throw IgniteException("Exception handler was called, but there is no pending Java exception."); + if (!err) { + jvmCtx->errCb("Exception handler was called, but there is no pending Java exception.", ""); + + return; + } env->ExceptionDescribe(); @@ -169,13 +178,13 @@ namespace ignite { env->ReleaseStringUTFChars(msg, str); - throw IgniteException(msgStr); + jvmCtx->errCb(msgStr, ""); } else { if (env->ExceptionCheck()) - clearAndThrow(env, jvmCtx); + clearErrorAndRunCallback(env, jvmCtx); else - throw IgniteException("Unknown ignite exception."); + jvmCtx->errCb("Unknown ignite exception.", ""); } } @@ -186,7 +195,7 @@ namespace ignite { env->DeleteLocalRef(localRef); // Clear local ref irrespective of result. if (!globalRef) - clearAndThrow(env, jvmCtx); + clearErrorAndRunCallback(env, jvmCtx); return globalRef; } @@ -205,11 +214,11 @@ namespace ignite { ~IgniteInteropTarget(); - jint inOp(jint type, void* ptr, jint len); + bool inOp(jint type, void* ptr, jint len); void* inOutOp(jint type, void* ptr, jint len); - void inOpAsync(jint type, void* ptr, jint len, IgniteAsyncCallback cb, void* data); + bool inOpAsync(jint type, void* ptr, jint len, IgniteAsyncCallback cb, void* data); private: /** */ @@ -228,20 +237,18 @@ namespace ignite { env->DeleteGlobalRef(obj); } - jint IgniteInteropTarget::inOp(jint type, void* ptr, jint len) { + bool IgniteInteropTarget::inOp(jint type, void* ptr, jint len) { JNIEnv* env = attach(jvmCtx); jint res = env->CallNonvirtualIntMethod(this->obj, this->cls, jvmCtx->m_InteropTarget_inOp, type, ptr, len); if (env->ExceptionCheck()) { - clearAndThrow(env, jvmCtx); - - assert(false); + clearErrorAndRunCallback(env, jvmCtx); return 0; } - return res; + return 1; } void* IgniteInteropTarget::inOutOp(jint type, void* ptr, jint len) { @@ -250,9 +257,7 @@ namespace ignite { jlong res = env->CallNonvirtualLongMethod(this->obj, this->cls, jvmCtx->m_InteropTarget_inOutOp, type, ptr, len); if (env->ExceptionCheck()) { - clearAndThrow(env, jvmCtx); - - assert(false); + clearErrorAndRunCallback(env, jvmCtx); return NULL; } @@ -260,13 +265,18 @@ namespace ignite { return (void*)res; } - void IgniteInteropTarget::inOpAsync(jint type, void* ptr, jint len, IgniteAsyncCallback cb, void* data) { + bool IgniteInteropTarget::inOpAsync(jint type, void* ptr, jint len, IgniteAsyncCallback cb, void* data) { JNIEnv* env = attach(jvmCtx); env->CallNonvirtualVoidMethod(this->obj, this->cls, jvmCtx->m_InteropTarget_inOutOpAsync, type, ptr, len, cb, data); - if (env->ExceptionCheck()) - clearAndThrow(env, jvmCtx); + if (env->ExceptionCheck()) { + clearErrorAndRunCallback(env, jvmCtx); + + return 0; + } + + return 1; } class IgniteCache::Impl : public IgniteInteropTarget { @@ -276,15 +286,17 @@ namespace ignite { } }; - IgniteJvm::IgniteJvm() { - ctx = new Context(); + IgniteJvm::IgniteJvm(IgniteErrorCallback errCb) { + assert (errCb); + + ctx = new Context(errCb); } IgniteJvm::~IgniteJvm() { delete ctx; } - Ignite* IgniteJvm::startIgnite(char* cfgPath, char* igniteName) throw(IgniteException){ + Ignite* IgniteJvm::startIgnite(char* cfgPath, char* igniteName) { JNIEnv* env = attach(ctx); jstring cfgPath0 = env->NewStringUTF(cfgPath); @@ -305,12 +317,15 @@ namespace ignite { if (env->ExceptionCheck()) { assert (!igniteObj); - clearAndThrow(env, ctx); + clearErrorAndRunCallback(env, ctx); - assert (false); + return NULL; } - else if (!igniteObj) - throw IgniteException("Failed to start Ignite."); + else if (!igniteObj) { + ctx->errCb("Failed to start Ignite.", ""); + + return NULL; + } cout << "Started ignite" << endl; @@ -323,12 +338,15 @@ namespace ignite { if (env->ExceptionCheck()) { assert (!interopProc); - clearAndThrow(env, ctx); + clearErrorAndRunCallback(env, ctx); - assert (false); + return NULL; } - else if (!interopProc) - throw IgniteException("Failed to get InteropProcessor."); + else if (!interopProc) { + ctx->errCb("Failed to get InteropProcessor.", ""); + + return NULL; + } Ignite* ignite0 = new Ignite(this); @@ -360,9 +378,7 @@ namespace ignite { if (name0) env->DeleteLocalRef(name0); - clearAndThrow(env, jvm->ctx); - - assert(false); + clearErrorAndRunCallback(env, jvm->ctx); return NULL; } @@ -373,14 +389,15 @@ namespace ignite { env->DeleteLocalRef(name0); if (env->ExceptionCheck()) { - clearAndThrow(env, jvm->ctx); - - assert(false); + clearErrorAndRunCallback(env, jvm->ctx); return NULL; } - else if (!cache) - throw IgniteException("Failed to create cache."); + else if (!cache) { + jvm->ctx->errCb("Failed to create cache.", ""); + + return NULL; + } cache = localToGlobal(env, cache, jvm->ctx); @@ -646,8 +663,10 @@ namespace ignite { return res; } - IGNITE_API_IMPORT_EXPORT IgniteJvm* testIgniteJvmStart() { - char* igniteHome; + IGNITE_API_IMPORT_EXPORT IgniteJvm* testIgniteJvmStart(IgniteErrorCallback errCb) { + assert(errCb); + + char* igniteHome; igniteHome = getenv("IGNITE_HOME"); @@ -690,7 +709,7 @@ namespace ignite { char* errClsName; char* errMsg; - IgniteJvm* jvm = new IgniteJvm(); + IgniteJvm* jvm = new IgniteJvm(errCb); int res = ContextInit(args, *jvm->ctx, &errClsName, &errMsg); @@ -701,6 +720,8 @@ namespace ignite { cout << "Failed to create JVM: " << errMsg << endl; + errCb(errMsg, ""); + return NULL; } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/39f9760b/modules/interop-api/src/test/cpp/ingite-interop-api-test.cpp ---------------------------------------------------------------------- diff --git a/modules/interop-api/src/test/cpp/ingite-interop-api-test.cpp b/modules/interop-api/src/test/cpp/ingite-interop-api-test.cpp index b95ab17..a565f1e 100644 --- a/modules/interop-api/src/test/cpp/ingite-interop-api-test.cpp +++ b/modules/interop-api/src/test/cpp/ingite-interop-api-test.cpp @@ -25,10 +25,45 @@ using namespace ignite; using namespace std; +class TestError { +}; + +void testErrorCallback(const string& errMsg, const string& errCls) { + cout << "Test error callback [err=" << errMsg << "]" << endl; + + throw TestError(); +} + +TEST_CASE("Stream", "[ignite]") { + IgniteOutputStream out(1); + + REQUIRE(sizeof(out) == 16); + + out.writeByte(1); + out.writeInt(1024); + out.writeLong(2048); + + out.writeByte(-1); + out.writeInt(-1024); + out.writeLong(-2048); + + IgniteInputStream in(out.dataPointer(), out.position(), out.allocatedSize()); + + REQUIRE(in.readByte() == 1); + REQUIRE(in.readInt() == 1024); + REQUIRE(in.readLong() == 2048); + + REQUIRE(in.readByte() == -1); + REQUIRE(in.readInt() == -1024); + REQUIRE(in.readLong() == -2048); +} + TEST_CASE("StartIgnite", "[ignite]") { - IgniteJvm* jvm = testIgniteJvmStart(); + IgniteJvm* jvm = testIgniteJvmStart(testErrorCallback); + + REQUIRE(jvm); - REQUIRE_THROWS_AS(jvm->startIgnite("invalid config", "ignite1"), IgniteException); + REQUIRE_THROWS_AS(jvm->startIgnite("invalid config", "ignite1"), TestError); Ignite* ignite = jvm->startIgnite("modules\\interop-api\\src\\test\\config\\test-single-node.xml", "ignite1");