diff options
author | Don Anderson <dda@ddanderson.com> | 2015-06-26 15:52:35 -0400 |
---|---|---|
committer | Don Anderson <dda@ddanderson.com> | 2015-06-26 15:52:35 -0400 |
commit | df854884079e1839d3353483c4988dd74fb7ecd3 (patch) | |
tree | b5f070cdfbd1ca1c79c8c19c92a0b7a1da31c616 /lang | |
parent | 74271fa733f4381084702d94ae5ef2f600dcb8b6 (diff) | |
download | mongo-df854884079e1839d3353483c4988dd74fb7ecd3.tar.gz |
WT-1964. For Java, handle cases where a session or cursor is closed
when the thread that open it no longer exists. Add tests to kill
threads that have open cursors and sessions.
Diffstat (limited to 'lang')
-rw-r--r-- | lang/java/wiredtiger.i | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/lang/java/wiredtiger.i b/lang/java/wiredtiger.i index fbdfbb32212..0cbf154eaa0 100644 --- a/lang/java/wiredtiger.i +++ b/lang/java/wiredtiger.i @@ -177,6 +177,9 @@ static void throwWiredTigerException(JNIEnv *jenv, int err) { } %enddef +/* + * 'Declare' a WiredTiger class. This sets up boilerplate typemaps. + */ %define WT_CLASS(type, class, name) /* * Extra 'self' elimination. @@ -210,17 +213,32 @@ static void throwWiredTigerException(JNIEnv *jenv, int err) { */" %enddef -%define WT_CLASS_WITH_CLOSE_HANDLER(type, class, name, closeHandler, priv) +/* + * Declare a WT_CLASS so that close methods call a specified closeHandler, + * after the WT core close function has completed. Arguments to the + * closeHandler are saved in advance since, as macro args, they may refer to + * values that are freed/zeroed by the close. + */ +%define WT_CLASS_WITH_CLOSE_HANDLER(type, class, name, closeHandler, + sess, priv) WT_CLASS(type, class, name) -%typemap(in, numinputs=0) class ## _CLOSED *name (JAVA_CALLBACK *jcb) { +/* + * This typemap recognizes a close function via a special declaration on its + * first argument. See WT_HANDLE_CLOSED in wiredtiger.h . Like + * WT_CURSOR_NULLABLE, the WT_{CURSOR,SESSION,CONNECTION}_CLOSED typedefs + * are only visible to the SWIG parser. + */ +%typemap(in, numinputs=0) class ## _CLOSED *name ( + WT_SESSION *savesess, JAVA_CALLBACK *jcb) { $1 = *(type **)&jarg1; NULL_CHECK($1, $1_name) + savesess = sess; jcb = (JAVA_CALLBACK *)(priv); } %typemap(freearg, numinputs=0) class ## _CLOSED *name { - closeHandler(jcb2); + closeHandler(jenv, savesess2, jcb2); priv = NULL; } @@ -239,11 +257,11 @@ WT_CLASS(type, class, name) %} WT_CLASS_WITH_CLOSE_HANDLER(struct __wt_connection, WT_CONNECTION, connection, - closeHandler, ((WT_CONNECTION_IMPL *)$1)->lang_private) + closeHandler, NULL, ((WT_CONNECTION_IMPL *)$1)->lang_private) WT_CLASS_WITH_CLOSE_HANDLER(struct __wt_session, WT_SESSION, session, - closeHandler, ((WT_SESSION_IMPL *)$1)->lang_private) + closeHandler, $1, ((WT_SESSION_IMPL *)$1)->lang_private) WT_CLASS_WITH_CLOSE_HANDLER(struct __wt_cursor, WT_CURSOR, cursor, - cursorCloseHandler, ((WT_CURSOR *)$1)->lang_private) + cursorCloseHandler, $1->session, ((WT_CURSOR *)$1)->lang_private) WT_CLASS(struct __wt_async_op, WT_ASYNC_OP, op) %define COPYDOC(SIGNATURE_CLASS, CLASS, METHOD) @@ -312,21 +330,35 @@ enum SearchStatus { FOUND, NOTFOUND, SMALLER, LARGER }; %wrapper %{ /* Zero out SWIG's pointer to the C object, * equivalent to 'jobj.swigCPtr = 0;' in java. + * We expect that either env in non-null (if called + * via an explicit session/cursor close() call), or + * that session is non-null (if called implicitly + * as part of connection/session close). */ static int -javaClose(JNIEnv *env, JAVA_CALLBACK *jcb, jfieldID *pfid) +javaClose(JNIEnv *env, WT_SESSION *session, JAVA_CALLBACK *jcb, jfieldID *pfid) { jclass cls; jfieldID fid; + WT_CONNECTION_IMPL *conn; + /* If we were not called via an implicit close call, + * we won't have a JNIEnv yet. Get one from the connection, + * since the thread that started the session may have + * terminated. + */ + if (env == NULL) { + conn = (WT_CONNECTION_IMPL *)session->connection; + env = ((JAVA_CALLBACK *)conn->lang_private)->jnienv; + } if (pfid == NULL || *pfid == NULL) { cls = (*env)->GetObjectClass(env, jcb->jobj); fid = (*env)->GetFieldID(env, cls, "swigCPtr", "J"); if (pfid != NULL) *pfid = fid; - } else { + } else fid = *pfid; - } + (*env)->SetLongField(env, jcb->jobj, fid, 0L); (*env)->DeleteGlobalRef(env, jcb->jobj); __wt_free(jcb->session, jcb); @@ -335,20 +367,22 @@ javaClose(JNIEnv *env, JAVA_CALLBACK *jcb, jfieldID *pfid) /* Connection and Session close handler. */ static int -closeHandler(JAVA_CALLBACK *jcb) +closeHandler(JNIEnv *env, WT_SESSION *session, JAVA_CALLBACK *jcb) { - return (javaClose(jcb->jnienv, jcb, NULL)); + return (javaClose(env, session, jcb, NULL)); } /* Cursor specific close handler. */ static int -cursorCloseHandler(JAVA_CALLBACK *jcb) +cursorCloseHandler(JNIEnv *env, WT_SESSION *wt_session, JAVA_CALLBACK *jcb) { int ret; JAVA_CALLBACK *sess_jcb; + WT_SESSION_IMPL *session; - sess_jcb = (JAVA_CALLBACK *)jcb->session->lang_private; - ret = javaClose(jcb->jnienv, jcb, + session = (WT_SESSION_IMPL *)wt_session; + sess_jcb = (JAVA_CALLBACK *)session->lang_private; + ret = javaClose(env, wt_session, jcb, sess_jcb ? &sess_jcb->cptr_fid : NULL); return (ret); @@ -364,9 +398,10 @@ javaCloseHandler(WT_EVENT_HANDLER *handler, WT_SESSION *session, WT_UNUSED(handler); if (cursor != NULL) - ret = cursorCloseHandler((JAVA_CALLBACK *)cursor->lang_private); + ret = cursorCloseHandler(NULL, session, (JAVA_CALLBACK *) + cursor->lang_private); else - ret = closeHandler((JAVA_CALLBACK *) + ret = closeHandler(NULL, session, (JAVA_CALLBACK *) ((WT_SESSION_IMPL *)session)->lang_private); return (ret); } @@ -474,7 +509,7 @@ err: __wt_err(session, ret, "Java async callback error"); } /* Invalidate the AsyncOp, further use throws NullPointerException. */ - ret = javaClose(jenv, jcb, &conn_jcb->asynccptr_fid); + ret = javaClose(jenv, NULL, jcb, &conn_jcb->asynccptr_fid); (*jenv)->DeleteGlobalRef(jenv, jcallback); |