Browse Source

Merge in sync

JNI-94
heck 5 years ago
parent
commit
72bf286bc1
  1. 19
      Makefile.conf
  2. 136
      src/basic_api.cc
  3. 2
      src/foundation/pEp/jniadapter/AbstractEngine.java
  4. 11
      src/foundation/pEp/jniadapter/UniquelyIdentifiable.java
  5. 119
      src/foundation_pEp_jniadapter_AbstractEngine.cc
  6. 7
      src/foundation_pEp_jniadapter__Blob.cc
  7. 11
      src/gen_cpp_Engine.ysl2
  8. 8
      src/gen_cpp_Message.ysl2
  9. 3
      src/identity_api.cc
  10. 57
      src/jniutils.cc
  11. 40
      src/jniutils.hh
  12. 4
      test/java/foundation/pEp/jniadapter/test/jni88/TestMain.java
  13. 98
      test/java/foundation/pEp/jniadapter/test/jni92/TestMain.java
  14. 20
      test/java/foundation/pEp/jniadapter/test/utils/TestUtils.java

19
Makefile.conf

@ -16,23 +16,16 @@ BUILD_FOR:=$(shell uname)
######### C and C++ #########
CXXFLAGS+=-g -O0
CXXFLAGS+=-g -O0 -std=c++11
LDFLAGS+=-shared $(ENGINE_LIB) $(AD_LIB)
LDLIBS=-lstdc++ -lpEpEngine -lpEpAdapter
######### C++ #########
ifeq ($(BUILD_FOR),Linux)
CXX=g++ -std=c++11
else ifeq ($(BUILD_FOR),Darwin)
CXX=clang -std=c++11
endif
ifeq ($(BUILD_FOR),Linux)
CXXFLAGS+=-fdiagnostics-color=always -fpermissive -fPIC -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux $(AD_INC) $(ENGINE_INC)
else ifeq ($(BUILD_FOR),Darwin)
CXXFLAGS+=-fcolor-diagnostics -fpermissive -fPIC -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/darwin $(AD_INC) $(ENGINE_INC)
CXXFLAGS+=-fpermissive -fPIC -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(shell uname) $(AD_INC) $(ENGINE_INC)
ifneq (,$(findstring g++,$(CXX)))
CXXFLAGS+=-fdiagnostics-color=always
else ifneq (,$(findstring clang,$(CXX)))
CXXFLAGS+=-fcolor-diagnostics
endif
# DEV ENV PATHS & CFG

136
src/basic_api.cc

@ -1,6 +1,5 @@
#include <pEp/keymanagement.h>
#include <pEp/blacklist.h>
#include <pEp/sync_api.h>
#include <pEp/Adapter.hh>
#ifndef ANDROID
@ -20,7 +19,14 @@ JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine_trustwords(
jobject ident
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
pEp_identity *_ident = to_identity(env, ident);
char *words;
size_t wsize;
@ -58,7 +64,14 @@ JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine_myself(
jobject ident
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
pEp_identity *_ident = to_identity(env, ident);
PEP_STATUS status = ::myself(session(), _ident);
@ -77,7 +90,14 @@ JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine_updateIdentity(
jobject ident
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
pEp_identity *_ident = to_identity(env, ident);
::update_identity(session(), _ident);
@ -92,7 +112,14 @@ JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine_setOwnKey(
jbyteArray fpr
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
pEp_identity *_ident = to_identity(env, ident);
char *_fpr = to_string(env, fpr);
@ -113,7 +140,14 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_keyMistrusted(
jobject ident
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
pEp_identity *_ident = to_identity(env, ident);
if (_ident->fpr == NULL || _ident->fpr[0] == 0) {
@ -137,7 +171,14 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_keyResetTrust(
jobject ident
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
pEp_identity *_ident = to_identity(env, ident);
if (_ident->fpr == NULL || _ident->fpr[0] == 0) {
@ -161,7 +202,14 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_trustPersonalKey(
jobject ident
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
pEp_identity *_ident = to_identity(env, ident);
if (_ident->fpr == NULL || _ident->fpr[0] == 0) {
@ -185,7 +233,14 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_trustOwnKey(
jobject ident
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
pEp_identity *_ident = to_identity(env, ident);
if (_ident->fpr == NULL || _ident->fpr[0] == 0) {
@ -202,7 +257,14 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_importKey(
jbyteArray key
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
size_t _size = (size_t) env->GetArrayLength(key);
char *_key = (char *) env->GetByteArrayElements(key, NULL);
@ -226,7 +288,14 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_config_1passive_1mo
jboolean enable
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
::config_passive_mode(session(), (bool)enable);
}
@ -237,7 +306,14 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_config_1unencrypted
jboolean enable
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
::config_unencrypted_subject(session(), (bool)enable);
}
@ -247,7 +323,14 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_blacklist_1add(
jbyteArray fpr
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
char *_fpr = to_string(env, fpr);
if(_fpr == NULL){
@ -269,7 +352,14 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_blacklist_1delete(
jbyteArray fpr
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
char *_fpr = to_string(env, fpr);
if(_fpr == NULL){
@ -291,7 +381,14 @@ JNIEXPORT jboolean JNICALL Java_foundation_pEp_jniadapter_Engine_blacklist_1is_1
jbyteArray fpr
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
char *_fpr = to_string(env, fpr);
bool _listed = 0;
@ -316,7 +413,14 @@ JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine_getCrashdumpL
jint maxlines
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
int _maxlines = (int) maxlines;
char *_logdata;

2
src/foundation/pEp/jniadapter/AbstractEngine.java

@ -8,7 +8,7 @@ import foundation.pEp.jniadapter.Sync.DefaultCallback;
import java.io.UnsupportedEncodingException;
import java.text.Normalizer;
abstract class AbstractEngine implements AutoCloseable {
abstract class AbstractEngine extends UniquelyIdentifiable implements AutoCloseable {
static {
System.loadLibrary("pEpJNI");
}

11
src/foundation/pEp/jniadapter/UniquelyIdentifiable.java

@ -0,0 +1,11 @@
package foundation.pEp.jniadapter;
import java.util.concurrent.atomic.AtomicLong;
abstract class UniquelyIdentifiable {
static final AtomicLong NEXT_ID = new AtomicLong(1);
final long id = NEXT_ID.getAndIncrement();
public long getId() {
return id;
}
}

119
src/foundation_pEp_jniadapter_AbstractEngine.cc

@ -1,8 +1,5 @@
#include "foundation_pEp_jniadapter_AbstractEngine.h"
#include <stdexcept>
#include <unistd.h>
#include <assert.h>
#include <pthread.h>
#include <pEp/keymanagement.h>
#include <pEp/message_api.h>
#include <pEp/sync_api.h>
@ -28,7 +25,7 @@ jmethodID notifyHandShakeMethodID = nullptr;
jmethodID needsFastPollMethodID = nullptr;
jmethodID method_values = nullptr;
jobject obj = nullptr;
jobject objj = nullptr;
jclass messageClass = nullptr;
jclass identityClass = nullptr;;
@ -96,15 +93,15 @@ void jni_init() {
PEP_STATUS messageToSend(message *msg)
{
std::lock_guard<std::mutex> l(mutex_obj);
pEpLog("############### messageToSend() called");
pEpLog("############### messageToSend() called");
jobject msg_ = nullptr;
assert(messageClass && messageConstructorMethodID && obj && messageToSendMethodID);
assert(messageClass && messageConstructorMethodID && objj && messageToSendMethodID);
msg_ = o.env()->NewObject(messageClass, messageConstructorMethodID, (jlong) msg);
PEP_STATUS status = (PEP_STATUS) o.env()->CallIntMethod(obj, messageToSendMethodID, msg_);
PEP_STATUS status = (PEP_STATUS) o.env()->CallIntMethod(objj, messageToSendMethodID, msg_);
if (o.env()->ExceptionCheck()) {
o.env()->ExceptionDescribe();
status = PEP_UNKNOWN_ERROR;
@ -118,8 +115,8 @@ PEP_STATUS messageToSend(message *msg)
PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal)
{
std::lock_guard<std::mutex> l(mutex_obj);
pEpLog("############### notifyHandshake() called");
pEpLog("############### notifyHandshake() called");
jobject me_ = nullptr;
jobject partner_ = nullptr;
@ -152,9 +149,9 @@ PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handsha
}
}
assert(obj && notifyHandShakeMethodID);
assert(objj && notifyHandShakeMethodID);
PEP_STATUS status = (PEP_STATUS) o.env()->CallIntMethod(obj, notifyHandShakeMethodID, me_, partner_, signal_);
PEP_STATUS status = (PEP_STATUS) o.env()->CallIntMethod(objj, notifyHandShakeMethodID, me_, partner_, signal_);
if (o.env()->ExceptionCheck()) {
o.env()->ExceptionClear();
return PEP_UNKNOWN_ERROR;
@ -169,45 +166,65 @@ using namespace pEp;
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_init(
JNIEnv *env,
jobject me
jobject obj
)
{
std::lock_guard<std::mutex> l(global_mutex); // global mutex for write access to <unordered_map>
pEpLog("called");
if (first) {
pEpLog("first Engine instance");
first = false;
env->GetJavaVM(&jvm);
jni_init();
obj = env->NewGlobalRef(me);
objj = env->NewGlobalRef(obj);
Adapter::_messageToSend = messageToSend;
}
create_engine_java_object_mutex(env, obj); // Create a mutex per java object
Adapter::session();
}
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_release(
JNIEnv *env,
jobject me
jobject obj
)
{
std::lock_guard<std::mutex> l(global_mutex); // global mutex for write access to <unordered_map>
pEpLog("called");
release_engine_java_object_mutex(env, obj);
Adapter::session(pEp::Adapter::release);
}
JNIEXPORT jstring JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_getVersion(
JNIEnv *env,
jobject
jobject obj
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
return env->NewStringUTF(::get_engine_version());
}
JNIEXPORT jstring JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_getProtocolVersion(
JNIEnv *env,
jobject
jobject obj
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
return env->NewStringUTF(::get_protocol_version());
}
@ -248,10 +265,17 @@ static void *keyserver_thread_routine(void *arg)
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startKeyserverLookup(
JNIEnv *env,
jobject me
jobject obj
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
pthread_t *thread = nullptr;
locked_queue< pEp_identity * > *queue = nullptr;
@ -267,16 +291,16 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startKeyser
return;
}
thread = (pthread_t *) env->GetLongField(me, thread_handle);
thread = (pthread_t *) env->GetLongField(obj, thread_handle);
if (thread)
return;
thread = (pthread_t *) calloc(1, sizeof(pthread_t));
assert(thread);
env->SetLongField(me, thread_handle, (jlong) thread);
env->SetLongField(obj, thread_handle, (jlong) thread);
queue = new locked_queue< pEp_identity * >();
env->SetLongField(me, queue_handle, (jlong) queue);
env->SetLongField(obj, queue_handle, (jlong) queue);
register_examine_function(Adapter::session(), examine_identity, (void *) queue);
@ -285,10 +309,17 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startKeyser
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_stopKeyserverLookup(
JNIEnv *env,
jobject me
jobject obj
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
pthread_t *thread = nullptr;
locked_queue< pEp_identity * > *queue = nullptr;
@ -304,14 +335,14 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_stopKeyserv
return;
}
thread = (pthread_t *) env->GetLongField(me, thread_handle);
thread = (pthread_t *) env->GetLongField(obj, thread_handle);
if (!thread)
return;
queue = (locked_queue< pEp_identity * > *) env->GetLongField(me, queue_handle);
queue = (locked_queue< pEp_identity * > *) env->GetLongField(obj, queue_handle);
env->SetLongField(me, queue_handle, (jlong) 0);
env->SetLongField(me, thread_handle, (jlong) 0);
env->SetLongField(obj, queue_handle, (jlong) 0);
env->SetLongField(obj, thread_handle, (jlong) 0);
register_examine_function(Adapter::session(), nullptr, nullptr);
@ -322,9 +353,17 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_stopKeyserv
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startSync(
JNIEnv *env,
jobject me
jobject obj
)
{
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
pEpLog("######## starting sync");
try {
Adapter::startup<JNISync>(messageToSend, notifyHandshake, &o, &JNISync::onSyncStartup, &JNISync::onSyncShutdown);
@ -337,19 +376,33 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startSync(
JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_stopSync(
JNIEnv *env,
jobject me
jobject obj
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
Adapter::shutdown();
}
JNIEXPORT jboolean JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_isSyncRunning(
JNIEnv *env,
jobject me
jobject obj
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
return (jboolean) Adapter::is_sync_running();
}

7
src/foundation_pEp_jniadapter__Blob.cc

@ -1,11 +1,8 @@
#include <pEp/bloblist.h>
#include <cassert>
#include <pEp/platform.h>
#include <pEp/sync_codec.h>
#include <pEp/distribution_codec.h>
#include <pEp/pEpLog.hh>
#include <iostream>
#include <cstring>
#include <cassert>
#include "jniutils.hh"
#include "throw_pEp_exception.hh"
#include "foundation_pEp_jniadapter__Blob.h"

11
src/gen_cpp_Engine.ysl2

@ -9,8 +9,6 @@ tstylesheet {
template "interface" document("foundation_pEp_jniadapter_{@name}.cc", "text")
||
#include <assert.h>
#include <pEp/message_api.h>
#include <pEp/blacklist.h>
#include <pEp/openpgp_compat.h>
#include <pEp/key_reset.h>
@ -50,7 +48,14 @@ tstylesheet {
jobject obj`apply "parm[in|inout]", mode=sig`
)
{
pEpLog("called");
std::mutex *mutex_local = nullptr;
{
std::lock_guard<std::mutex> l(global_mutex);
pEpLog("called with lock_guard");
mutex_local = get_engine_java_object_mutex(env, obj);
}
std::lock_guard<std::mutex> l(*mutex_local);
||
apply "parm[in|inout]", mode=in;

8
src/gen_cpp_Message.ysl2

@ -12,15 +12,9 @@ tstylesheet {
document("foundation_pEp_jniadapter_{$jname}.cc", "text") {
||
#include <exception>
#include <new>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <pEp/«@name».h>
#include <cassert>
#include <pEp/mime.h>
#include <pEp/pEpLog.hh>
#include "jniutils.hh"
#include "throw_pEp_exception.hh"
#include "foundation_pEp_jniadapter_«$jname».h"

3
src/identity_api.cc

@ -1,7 +1,4 @@
#include <pEp/message_api.h>
#include <pEp/pEpLog.hh>
#include "jniutils.hh"
extern "C" {

57
src/jniutils.cc

@ -1,11 +1,6 @@
#include <cassert>
#include "jniutils.hh"
#include <stdexcept>
#include <typeinfo>
#include <time.h>
#include <stdlib.h>
#include <assert.h>
#include <string>
#include <pEp/pEpLog.hh>
#ifndef __LP64__
#include <time64.h>
#define time_t time64_t
@ -17,6 +12,54 @@
namespace pEp {
namespace JNIAdapter {
std::mutex global_mutex;
std::unordered_map<long, std::mutex*> engine_objid_mutex;
std::mutex* get_engine_java_object_mutex(
JNIEnv *env,
jobject obj
)
{
long engine_obj_id = (long)callLongMethod(env, obj, "getId");
assert(engine_obj_id);
pEpLog("for java object id: " << engine_obj_id);
std::mutex *engine_obj_mutex = engine_objid_mutex.at(engine_obj_id);
pEpLog("found mutex: " << engine_obj_mutex << " with native_handle: " << engine_obj_mutex->native_handle());
assert(engine_obj_mutex);
return engine_obj_mutex;
}
void create_engine_java_object_mutex(
JNIEnv *env,
jobject obj
)
{
long engine_obj_id = (long)callLongMethod(env, obj, "getId");
assert(engine_obj_id);
std::mutex *engine_obj_mutex = new std::mutex();
pEpLog(engine_obj_mutex << " with native_handle: " << engine_obj_mutex->native_handle() << " for java object id: " << engine_obj_id);
assert(engine_obj_mutex);
if(engine_objid_mutex.count(engine_obj_id) > 0) {
pEpLog("Fatal: mutex already existing for object id: " << engine_obj_id);
assert(0);
}
engine_objid_mutex.insert(std::make_pair(engine_obj_id, engine_obj_mutex ));
}
void release_engine_java_object_mutex(
JNIEnv *env,
jobject obj
)
{
long engine_obj_id = (long)callLongMethod(env, obj, "getId");
assert(engine_obj_id);
std::mutex *engine_obj_mutex = engine_objid_mutex.at(engine_obj_id);
pEpLog(engine_obj_mutex << " with native_handle: " << engine_obj_mutex->native_handle() << " for java object id: " << engine_obj_id);
assert(engine_obj_mutex);
engine_objid_mutex.erase(engine_obj_id);
delete engine_obj_mutex;
}
jclass findClass(JNIEnv *env, const char *classname)
{
jclass clazz = env->FindClass(classname);

40
src/jniutils.hh

@ -1,8 +1,7 @@
#pragma once
#include <list>
#include <pthread.h>
#include <errno.h>
#include <unordered_map>
#include <thread>
#include <mutex>
#include <jni.h>
#include <pEp/stringpair.h>
#include <pEp/identity_list.h>
@ -15,11 +14,42 @@
#define LOG_TAG "pEpJNIAdapter"
#define LOGD(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#else
#define LOGD(...)
#define LOGD(...) do{}while(0)
#endif
namespace pEp {
namespace JNIAdapter {
// Global mutex needs to be locked in all constructors which insert their own mutex object
// into the unordered_map (which is thread safe for read, but not for write)
extern std::mutex global_mutex;
// Stores mutex per java object
extern std::unordered_map<long, std::mutex*> engine_objid_mutex;
// needs to be called after create_engine_java_object_mutex()
// and before release_engine_java_object_mutex()
// Thread safe
std::mutex* get_engine_java_object_mutex(
JNIEnv *env,
jobject me
);
// Needs to be called exactly once per obj, in the constructor of the obj
// You need to lock a global mutex before calling this function (write to unordered_map)
void create_engine_java_object_mutex(
JNIEnv *env,
jobject me
);
// Needs to be called exactly once per obj, in the destructor of this obj
// You need to lock a global mutex before calling this function (write to unordered_map)
void release_engine_java_object_mutex(
JNIEnv *env,
jobject me
);
jclass findClass(JNIEnv *env, const char *classname);
jfieldID getFieldID(

4
test/java/foundation/pEp/jniadapter/test/jni88/TestMain.java

@ -89,8 +89,8 @@ class TestThread extends Thread {
class TestMain {
public static void main(String[] args) {
// Test parameters
boolean useSharedEngine = true;
int numThreads = 2;
boolean useSharedEngine = false;
int numThreads = 200;
int numIters = 1000000000;
Engine sharedEngine = null;

98
test/java/foundation/pEp/jniadapter/test/jni92/TestMain.java

@ -4,6 +4,7 @@ import foundation.pEp.jniadapter.*;
import java.lang.Thread;
import java.util.Vector;
import java.util.function.Consumer;
/*
@ -14,24 +15,29 @@ https://pep.foundation/jira/browse/JNI-81
*/
class TestThread extends Thread {
TestThread(String threadName) {
int nrEngines = 1;
boolean useSharedEngines = false;
TestThread(String threadName, int nrEngines, boolean useSharedEngines) {
Thread.currentThread().setName(threadName);
this.nrEngines = nrEngines;
this.useSharedEngines = useSharedEngines;
}
public void run() {
TestUtils.logH1( "Thread Starting");
TestMain.TestMainRun(2);
TestMain.TestMainRun(nrEngines, useSharedEngines);
}
}
class TestMain {
static Vector<Engine> sharedEngines;
public static Engine createNewEngine() throws pEpException {
Engine e;
TestUtils.logH2("Creating new Engine");
e = new Engine();
TestUtils.log("Engine created\n");
TestUtils.log("Engine created with java object ID: " + e.getId());
return e;
}
@ -43,51 +49,73 @@ class TestMain {
return ev;
}
public static void own_identities_retrieve_on_EngineVector(Vector<Engine> ev) {
public static void engineConsumer(Vector<Engine> ev, Consumer<Engine> ec) {
ev.forEach(e -> {
TestUtils.logH2("own_identities_retrieve()");
e.own_identities_retrieve();
TestUtils.log("\n");
TestUtils.logH2("engineConsumer: on engine java object ID: " + e.getId());
ec.accept(e);
});
}
public static void TestMainRun(int nrEngines, boolean useSharedEngines) {
Consumer<Engine> c = (e) -> {
Vector<Identity> v = e.own_identities_retrieve();
TestUtils.log("own idents: " + v.size());
v.forEach( i -> {
TestUtils.log(TestUtils.identityToString(i));
});
e.getVersion();
e.OpenPGP_list_keyinfo("");
};
public static void TestMainRun(int nrEngines) {
Vector<Engine> engineVector = TestMain.createEngines(nrEngines);
// TestUtils.sleep(200);
TestMain.own_identities_retrieve_on_EngineVector(engineVector);
if(useSharedEngines) {
TestMain.engineConsumer(sharedEngines, c);
} else {
Vector<Engine> threadLocalEngines = TestMain.createEngines(nrEngines);
TestMain.engineConsumer(threadLocalEngines, c);
}
}
public static void main(String[] args) throws Exception {
public static void main(String[] args) {
TestUtils.logH1("JNI-92 Starting");
TestUtils.setLoggingEnabled(false);
int nrTestruns = 1000;
boolean multiThreaded = true;
int nrEngines = 3;
if (!multiThreaded) {
// Single Threaded
TestMainRun(nrEngines);
} else {
// Mutli Threaded
Vector<TestThread> tts = new Vector<TestThread>();
int nrThreads = nrEngines;
for (int i = 0; i < nrThreads; i++) {
tts.add(new TestThread("TestThread-" + i));
// TestUtils.sleep(200);
}
boolean useSharedEngines = true;
int nrThreads = 100;
int nrEnginesPerThread = 1;
tts.forEach(t -> {
t.start();
// TestUtils.sleep(2000);
});
if(useSharedEngines) {
sharedEngines = TestMain.createEngines(nrEnginesPerThread);
}
tts.forEach(t -> {
try {
t.join();
} catch (Exception e) {
TestUtils.log("Exception joining thread" + e.toString());
for (int run = 0; run < nrTestruns; run++ ) {
TestUtils.logH1("Testrun Nr: " + run);
if (!multiThreaded) {
// Single Threaded
TestMainRun(nrEnginesPerThread, useSharedEngines);
} else {
// Mutli Threaded
Vector<TestThread> tts = new Vector<TestThread>();
for (int i = 0; i < nrThreads; i++) {
tts.add(new TestThread("TestThread-" + i, nrEnginesPerThread, useSharedEngines));
}
});
tts.forEach(t -> {
t.start();
});
tts.forEach(t -> {
try {
t.join();
} catch (Exception e) {
TestUtils.log("Exception joining thread" + e.toString());
}
});
}
TestUtils.logH1("Testrun DONE" );
System.gc();
// TestUtils.sleep(2000);
}
}
}

20
test/java/foundation/pEp/jniadapter/test/utils/TestUtils.java

@ -22,10 +22,24 @@ public class TestUtils {
return ret;
}
// ------------------------ Logging ------------------------
private static boolean logEnabled = true;
public static void setLoggingEnabled(boolean enabled) {
logEnabled = enabled;
}
public static boolean isLoggingEnabled() {
return logEnabled;
}
public static void log(String msg) {
String threadNameFmt = String.format("%-10s", Thread.currentThread().getName());
String msgOut = threadNameFmt + ": " + msg;
System.out.println(msgOut);
if(logEnabled) {
String threadNameFmt = String.format("%-10s", Thread.currentThread().getName());
String msgOut = threadNameFmt + ": " + msg;
System.out.println(msgOut);
}
}
public static void logH1(String msg) {

Loading…
Cancel
Save