get rid of open/close context

This commit is contained in:
B. Petersen 2020-05-25 16:59:13 +02:00
parent 4782d18824
commit d42eb1d920
No known key found for this signature in database
GPG key ID: 3B88E92DEA8E9AFC
4 changed files with 43 additions and 96 deletions

View file

@ -173,14 +173,6 @@ static uint32_t* jintArray2uint32Pointer(JNIEnv* env, jintArray ja, int* ret_icn
******************************************************************************/ ******************************************************************************/
typedef struct dc_jnicontext_t {
JavaVM* jvm; // JNIEnv cannot be shared between threads, so we share the JavaVM object
jclass cls;
jobject obj;
jmethodID methodId;
} dc_jnicontext_t;
static dc_context_t* get_dc_context(JNIEnv *env, jobject obj) static dc_context_t* get_dc_context(JNIEnv *env, jobject obj)
{ {
static jfieldID fid = 0; static jfieldID fid = 0;
@ -195,42 +187,12 @@ static dc_context_t* get_dc_context(JNIEnv *env, jobject obj)
} }
static uintptr_t s_context_callback_(dc_context_t* context, int event, uintptr_t data1, uintptr_t data2) JNIEXPORT jlong Java_com_b44t_messenger_DcContext_createContextCPtr(JNIEnv *env, jobject obj, jstring osname, jstring dbfile)
{ {
jlong l;
JNIEnv* env;
dc_jnicontext_t* jnicontext = dc_get_userdata(context);
if (jnicontext==NULL || jnicontext->jvm==NULL || jnicontext->cls==NULL || jnicontext->obj==NULL || jnicontext->methodId==NULL) {
return 0; /* may happen on startup */
}
(*jnicontext->jvm)->GetEnv(jnicontext->jvm, (void**)&env, JNI_VERSION_1_6); // as this function may be called from _any_ thread, we cannot use a static pointer to JNIEnv
if (env==NULL) {
return 0; /* may happen on startup */
}
l = (*env)->CallLongMethod(env, jnicontext->obj, jnicontext->methodId, (jint)event, (jlong)data1, (jlong)data2);
return (uintptr_t)l;
}
JNIEXPORT jlong Java_com_b44t_messenger_DcContext_createContextCPtr(JNIEnv *env, jobject obj, jstring osname)
{
jclass cls = (*env)->GetObjectClass(env, obj);
dc_jnicontext_t* jnicontext = calloc(1, sizeof(dc_jnicontext_t));
if (cls==NULL || jnicontext==NULL) {
return 0;
}
(*env)->GetJavaVM(env, &jnicontext->jvm);
jnicontext->cls = (*env)->NewGlobalRef(env, cls);
jnicontext->obj = (*env)->NewGlobalRef(env, obj);
jnicontext->methodId = (*env)->GetMethodID(env, jnicontext->cls, "handleEvent","(IJJ)J" /*signature as "(param)ret" with I=int, J=long*/);
CHAR_REF(osname); CHAR_REF(osname);
jlong contextCPtr = (jlong)dc_context_new(s_context_callback_, jnicontext, osnamePtr); CHAR_REF(dbfile)
jlong contextCPtr = (jlong)dc_context_new(osnamePtr, dbfilePtr, NULL);
CHAR_UNREF(dbfile)
CHAR_UNREF(osname); CHAR_UNREF(osname);
return contextCPtr; return contextCPtr;
} }
@ -244,21 +206,6 @@ JNIEXPORT void Java_com_b44t_messenger_DcContact_unrefContextCPtr(JNIEnv *env, j
/* DcContext - open/configure/connect/fetch */ /* DcContext - open/configure/connect/fetch */
JNIEXPORT jint Java_com_b44t_messenger_DcContext_open(JNIEnv *env, jobject obj, jstring dbfile)
{
CHAR_REF(dbfile);
jint ret = dc_open(get_dc_context(env, obj), dbfilePtr, NULL);
CHAR_UNREF(dbfile)
return ret;
}
JNIEXPORT void Java_com_b44t_messenger_DcContext_close(JNIEnv *env, jobject obj)
{
dc_close(get_dc_context(env, obj));
}
JNIEXPORT void Java_com_b44t_messenger_DcContext_setStockTranslation(JNIEnv *env, jobject obj, jint stock_id, jstring translation) JNIEXPORT void Java_com_b44t_messenger_DcContext_setStockTranslation(JNIEnv *env, jobject obj, jint stock_id, jstring translation)
{ {
CHAR_REF(translation); CHAR_REF(translation);
@ -303,93 +250,79 @@ JNIEXPORT jint Java_com_b44t_messenger_DcContext_isConfigured(JNIEnv *env, jobje
} }
// TODO-ASYNC: delete these functions, also in the java-part
JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapJobs(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapJobs(JNIEnv *env, jobject obj)
{ {
dc_perform_imap_jobs(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapIdle(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapIdle(JNIEnv *env, jobject obj)
{ {
dc_perform_imap_idle(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapFetch(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapFetch(JNIEnv *env, jobject obj)
{ {
dc_perform_imap_fetch(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptImapIdle(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptImapIdle(JNIEnv *env, jobject obj)
{ {
dc_interrupt_imap_idle(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_performSentboxJobs(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_performSentboxJobs(JNIEnv *env, jobject obj)
{ {
dc_perform_sentbox_jobs(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_performSentboxFetch(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_performSentboxFetch(JNIEnv *env, jobject obj)
{ {
dc_perform_sentbox_fetch(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_performSentboxIdle(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_performSentboxIdle(JNIEnv *env, jobject obj)
{ {
dc_perform_sentbox_idle(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptSentboxIdle(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptSentboxIdle(JNIEnv *env, jobject obj)
{ {
dc_interrupt_sentbox_idle(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_performMvboxJobs(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_performMvboxJobs(JNIEnv *env, jobject obj)
{ {
dc_perform_mvbox_jobs(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_performMvboxFetch(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_performMvboxFetch(JNIEnv *env, jobject obj)
{ {
dc_perform_mvbox_fetch(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_performMvboxIdle(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_performMvboxIdle(JNIEnv *env, jobject obj)
{ {
dc_perform_mvbox_idle(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptMvboxIdle(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptMvboxIdle(JNIEnv *env, jobject obj)
{ {
dc_interrupt_mvbox_idle(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_performSmtpJobs(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_performSmtpJobs(JNIEnv *env, jobject obj)
{ {
dc_perform_smtp_jobs(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_performSmtpIdle(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_performSmtpIdle(JNIEnv *env, jobject obj)
{ {
dc_perform_smtp_idle(get_dc_context(env, obj));
} }
JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptSmtpIdle(JNIEnv *env, jobject obj) JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptSmtpIdle(JNIEnv *env, jobject obj)
{ {
dc_interrupt_smtp_idle(get_dc_context(env, obj));
} }

View file

@ -72,20 +72,27 @@ public class DcContext {
public final static int DC_EMPTY_MVBOX = 0x01; public final static int DC_EMPTY_MVBOX = 0x01;
public final static int DC_EMPTY_INBOX = 0x02; public final static int DC_EMPTY_INBOX = 0x02;
public DcContext(String osName) { public DcContext(String osName, String dbfile) {
handleEvent(0,0,0); // call handleEvent() to make sure it is not optimized away and JNI won't find it contextCPtr = createContextCPtr(osName, dbfile);
contextCPtr = createContextCPtr(osName); }
public boolean isOk() {
return contextCPtr != 0;
} }
@Override @Override
protected void finalize() throws Throwable { protected void finalize() throws Throwable {
super.finalize(); super.finalize();
unrefContextCPtr(); unref();
contextCPtr = 0; }
public void unref() {
if (contextCPtr != 0) {
unrefContextCPtr();
contextCPtr = 0;
}
} }
public native int open (String dbfile);
public native void close ();
public native void setStockTranslation (int stockId, String translation); public native void setStockTranslation (int stockId, String translation);
public native String getBlobdir (); public native String getBlobdir ();
public native void configure (); public native void configure ();
@ -189,11 +196,6 @@ public class DcContext {
*/ */
public native boolean setLocation (float latitude, float longitude, float accuracy); public native boolean setLocation (float latitude, float longitude, float accuracy);
// event handling - you should @Override this function in derived classes
public long handleEvent(int event, long data1, long data2) {
return 0;
}
// helper to get/return strings from/to handleEvent() // helper to get/return strings from/to handleEvent()
public native static boolean data1IsString(int event); public native static boolean data1IsString(int event);
public native static boolean data2IsString(int event); public native static boolean data2IsString(int event);
@ -201,7 +203,7 @@ public class DcContext {
// working with raw c-data // working with raw c-data
private long contextCPtr; // CAVE: the name is referenced in the JNI private long contextCPtr; // CAVE: the name is referenced in the JNI
private native long createContextCPtr(String osName); private native long createContextCPtr(String osName, String dbfile);
private native void unrefContextCPtr (); private native void unrefContextCPtr ();
public native long createMsgCPtr (int viewtype); public native long createMsgCPtr (int viewtype);
private native long getChatlistCPtr (int listflags, String query, int queryId); private native long getChatlistCPtr (int listflags, String query, int queryId);

View file

@ -65,8 +65,8 @@ public class AccountManager {
private @Nullable Account maybeGetAccount(File file) { private @Nullable Account maybeGetAccount(File file) {
try { try {
if (!file.isDirectory() && file.getName().endsWith(".db")) { if (!file.isDirectory() && file.getName().endsWith(".db")) {
DcContext testContext = new DcContext(null); DcContext testContext = new DcContext(null, file.getAbsolutePath());
if (testContext.open(file.getAbsolutePath()) != 0) { if (testContext.isOk()) {
Account ret = new Account(); Account ret = new Account();
ret.dbName = file.getName(); ret.dbName = file.getName();
ret.displayname = testContext.getConfig("displayname"); ret.displayname = testContext.getConfig("displayname");
@ -99,7 +99,7 @@ public class AccountManager {
// getSelectedAccount() // getSelectedAccount()
ApplicationContext appContext = (ApplicationContext)context.getApplicationContext(); ApplicationContext appContext = (ApplicationContext)context.getApplicationContext();
appContext.dcContext.stopThreads(); appContext.dcContext.stopThreads();
appContext.dcContext.close(); appContext.dcContext.unref();
appContext.dcContext = new ApplicationDcContext(context); appContext.dcContext = new ApplicationDcContext(context);
} }
@ -243,10 +243,10 @@ public class AccountManager {
if (deleteDbName!=null) { if (deleteDbName!=null) {
// used to delete the previous account, however, as a resilience check, make sure, // used to delete the previous account, however, as a resilience check, make sure,
// we do not delete already configured accounts (just in case sth. changes the flow of activities) // we do not delete already configured accounts (just in case sth. changes the flow of activities)
DcContext testContext = new DcContext(null); DcContext testContext = new DcContext(null, new File(activity.getFilesDir(), deleteDbName).getAbsolutePath());
if (testContext.open(new File(activity.getFilesDir(), deleteDbName).getAbsolutePath()) != 0) { if (testContext.isOk()) {
if (testContext.isConfigured() == 0) { if (testContext.isConfigured() == 0) {
testContext.close(); testContext.unref();
AccountManager.getInstance().deleteAccount(activity, deleteDbName); AccountManager.getInstance().deleteAccount(activity, deleteDbName);
PreferenceManager.getDefaultSharedPreferences(activity) PreferenceManager.getDefaultSharedPreferences(activity)
.edit().putString("prev_account_db_name", "").apply(); .edit().putString("prev_account_db_name", "").apply();

View file

@ -56,12 +56,9 @@ public class ApplicationDcContext extends DcContext {
public NotificationCenter notificationCenter; public NotificationCenter notificationCenter;
public ApplicationDcContext(Context context) { public ApplicationDcContext(Context context) {
super("Android "+BuildConfig.VERSION_NAME); super("Android "+BuildConfig.VERSION_NAME, AccountManager.getInstance().getSelectedAccount(context).getAbsolutePath());
this.context = context; this.context = context;
File dbfile = AccountManager.getInstance().getSelectedAccount(context);
open(dbfile.getAbsolutePath());
// migration, can be removed after some versions (added 5/2020) // migration, can be removed after some versions (added 5/2020)
// (this will convert only for one account, but that is fine, multi-account is experimental anyway) // (this will convert only for one account, but that is fine, multi-account is experimental anyway)
try { try {
@ -341,6 +338,10 @@ public class ApplicationDcContext extends DcContext {
public boolean run = true; public boolean run = true;
public void startThreads(int flags) { public void startThreads(int flags) {
// TODO-ASYNC: remove this function, handle the flags differently
/*
synchronized (threadsCritical) { synchronized (threadsCritical) {
if (imapThread == null || !imapThread.isAlive()) { if (imapThread == null || !imapThread.isAlive()) {
@ -432,9 +433,14 @@ public class ApplicationDcContext extends DcContext {
smtpThread.start(); smtpThread.start();
} }
} }
*/
} }
public void waitForThreadsExecutedOnce() { public void waitForThreadsExecutedOnce() {
// TODO-ASYNC
/*
while(true) { while(true) {
synchronized (incLoopsCritical) { synchronized (incLoopsCritical) {
if(inboxLoops>0 && mvboxLoops>0 && smtpLoops>0) { if(inboxLoops>0 && mvboxLoops>0 && smtpLoops>0) {
@ -443,10 +449,15 @@ public class ApplicationDcContext extends DcContext {
} }
Util.sleep(500); Util.sleep(500);
} }
*/
} }
public void stopThreads() { public void stopThreads() {
notificationCenter.removeAllNotifiations(); notificationCenter.removeAllNotifiations();
// TODO-ASYNC
/*
run = false; run = false;
synchronized (threadsCritical) { synchronized (threadsCritical) {
while (true) { while (true) {
@ -470,6 +481,7 @@ public class ApplicationDcContext extends DcContext {
} }
} }
Log.i(TAG, "!!!!!!!!!!!! threads stopped"); Log.i(TAG, "!!!!!!!!!!!! threads stopped");
*/
} }
@ -557,7 +569,7 @@ public class ApplicationDcContext extends DcContext {
}); });
} }
@Override // TODO-ASYNC: make this work again
public long handleEvent(final int event, long data1, long data2) { public long handleEvent(final int event, long data1, long data2) {
switch (event) { switch (event) {
case DC_EVENT_INFO: case DC_EVENT_INFO: