Repository: mesos
Updated Branches:
  refs/heads/master 4809d161e -> 5d0b5fdb5


Fix memory corruption in AbstractState JNI bindings. MESOS-2161.

Review: https://reviews.apache.org/r/32152


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/5d0b5fdb
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/5d0b5fdb
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/5d0b5fdb

Branch: refs/heads/master
Commit: 5d0b5fdb5d8d78b44537cb01916263a3769b5d7d
Parents: 9706bb0
Author: Joris Van Remoortere <[email protected]>
Authored: Sun Mar 29 12:20:24 2015 -0700
Committer: Benjamin Hindman <[email protected]>
Committed: Sun Mar 29 12:44:36 2015 -0700

----------------------------------------------------------------------
 .../org_apache_mesos_state_AbstractState.cpp    | 514 +++++++++++++++++++
 .../org/apache/mesos/state/AbstractState.java   | 165 +++++-
 2 files changed, 678 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/5d0b5fdb/src/java/jni/org_apache_mesos_state_AbstractState.cpp
----------------------------------------------------------------------
diff --git a/src/java/jni/org_apache_mesos_state_AbstractState.cpp 
b/src/java/jni/org_apache_mesos_state_AbstractState.cpp
index 1accc8a..2be377c 100644
--- a/src/java/jni/org_apache_mesos_state_AbstractState.cpp
+++ b/src/java/jni/org_apache_mesos_state_AbstractState.cpp
@@ -23,6 +23,16 @@ using std::string;
 
 extern "C" {
 
+// TODO(jmlvanre): Deprecate the JNI functions that are in the AbstractState
+// scope that we have replaced with the ones in the names classes 
'FetchFuture',
+// 'StoreFuture', 'ExpungeFuture', and 'NamesFuture'. (MESOS-2161). The
+// anonymous futures that used these function accidentally captured the 'thiz'
+// for the 'AbstractState' class, which was not intended and caused the C++
+// Future to be prematurely deleted as a result of the anonymous Future getting
+// garbaged collected by the JVM and invoking the finalizer which deleted the
+// C++ Future. The intent was to capture the 'thiz' for the 'Future'. This is
+// done correctly by using the named inner classes.
+
 /*
  * Class:     org_apache_mesos_state_AbstractState
  * Method:    finalize
@@ -228,6 +238,132 @@ JNIEXPORT void JNICALL 
Java_org_apache_mesos_state_AbstractState__1_1fetch_1fina
 
 
 /*
+ * Class:     org_apache_mesos_state_AbstractState$FetchFuture
+ * Method:    cancel
+ * Signature: (Z)Z
+ */
+JNIEXPORT jboolean JNICALL 
Java_org_apache_mesos_state_AbstractState_00024FetchFuture_cancel
+  (JNIEnv* env, jobject thiz, jboolean mayInterruptIfRunning)
+{
+  if (mayInterruptIfRunning) {
+    static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+    static jfieldID field = env->GetFieldID(clazz, "future", "J");
+    jlong jfuture = env->GetLongField(thiz, field);
+
+    // See TODO at top of file for why we proxy this call.
+    return Java_org_apache_mesos_state_AbstractState__1_1fetch_1cancel(
+        env,
+        thiz,
+        jfuture);
+  }
+
+  return false; // Should not interrupt and already running (or finished).
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$FetchFuture
+ * Method:    is_cancelled
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL 
Java_org_apache_mesos_state_AbstractState_00024FetchFuture_is_1cancelled
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1fetch_1is_1cancelled(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$FetchFuture
+ * Method:    is_done
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL 
Java_org_apache_mesos_state_AbstractState_00024FetchFuture_is_1done
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1fetch_1is_1done(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$FetchFuture
+ * Method:    get
+ * Signature: ()Lorg/apache/mesos/state/Variable;
+ */
+JNIEXPORT jobject JNICALL 
Java_org_apache_mesos_state_AbstractState_00024FetchFuture_get
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1fetch_1get(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$FetchFuture
+ * Method:    get_timeout
+ * Signature: 
(JLjava/util/concurrent/TimeUnit;)Lorg/apache/mesos/state/Variable;
+ */
+JNIEXPORT jobject JNICALL 
Java_org_apache_mesos_state_AbstractState_00024FetchFuture_get_1timeout
+  (JNIEnv* env, jobject thiz, jlong jtimeout, jobject junit)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1fetch_1get_1timeout(
+      env,
+      thiz,
+      jfuture,
+      jtimeout,
+      junit);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$FetchFuture
+ * Method:    finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL 
Java_org_apache_mesos_state_AbstractState_00024FetchFuture_finalize
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  Java_org_apache_mesos_state_AbstractState__1_1fetch_1finalize(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
  * Class:     org_apache_mesos_state_AbstractState
  * Method:    __store
  * Signature: (Lorg/apache/mesos/state/Variable;)J
@@ -422,6 +558,132 @@ JNIEXPORT void JNICALL 
Java_org_apache_mesos_state_AbstractState__1_1store_1fina
 
 
 /*
+ * Class:     org_apache_mesos_state_AbstractState$StoreFuture
+ * Method:    cancel
+ * Signature: (Z)Z
+ */
+JNIEXPORT jboolean JNICALL 
Java_org_apache_mesos_state_AbstractState_00024StoreFuture_cancel
+  (JNIEnv* env, jobject thiz, jboolean mayInterruptIfRunning)
+{
+  if (mayInterruptIfRunning) {
+    static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+    static jfieldID field = env->GetFieldID(clazz, "future", "J");
+    jlong jfuture = env->GetLongField(thiz, field);
+
+    // See TODO at top of file for why we proxy this call.
+    return Java_org_apache_mesos_state_AbstractState__1_1store_1cancel(
+        env,
+        thiz,
+        jfuture);
+  }
+
+  return false; // Should not interrupt and already running (or finished).
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$StoreFuture
+ * Method:    is_cancelled
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL 
Java_org_apache_mesos_state_AbstractState_00024StoreFuture_is_1cancelled
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1store_1is_1cancelled(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$StoreFuture
+ * Method:    is_done
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL 
Java_org_apache_mesos_state_AbstractState_00024StoreFuture_is_1done
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1store_1is_1done(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$StoreFuture
+ * Method:    get
+ * Signature: ()Lorg/apache/mesos/state/Variable;
+ */
+JNIEXPORT jobject JNICALL 
Java_org_apache_mesos_state_AbstractState_00024StoreFuture_get
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1store_1get(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$StoreFuture
+ * Method:    get_timeout
+ * Signature: 
(JLjava/util/concurrent/TimeUnit;)Lorg/apache/mesos/state/Variable;
+ */
+JNIEXPORT jobject JNICALL 
Java_org_apache_mesos_state_AbstractState_00024StoreFuture_get_1timeout
+  (JNIEnv* env, jobject thiz, jlong jtimeout, jobject junit)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1store_1get_1timeout(
+      env,
+      thiz,
+      jfuture,
+      jtimeout,
+      junit);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$StoreFuture
+ * Method:    finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL 
Java_org_apache_mesos_state_AbstractState_00024StoreFuture_finalize
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  Java_org_apache_mesos_state_AbstractState__1_1store_1finalize(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
  * Class:     org_apache_mesos_state_AbstractState
  * Method:    __expunge
  * Signature: (Lorg/apache/mesos/state/Variable;)J
@@ -601,6 +863,132 @@ JNIEXPORT void JNICALL 
Java_org_apache_mesos_state_AbstractState__1_1expunge_1fi
 
 
 /*
+ * Class:     org_apache_mesos_state_AbstractState$ExpungeFuture
+ * Method:    cancel
+ * Signature: (Z)Z
+ */
+JNIEXPORT jboolean JNICALL 
Java_org_apache_mesos_state_AbstractState_00024ExpungeFuture_cancel
+  (JNIEnv* env, jobject thiz, jboolean mayInterruptIfRunning)
+{
+  if (mayInterruptIfRunning) {
+    static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+    static jfieldID field = env->GetFieldID(clazz, "future", "J");
+    jlong jfuture = env->GetLongField(thiz, field);
+
+    // See TODO at top of file for why we proxy this call.
+    return Java_org_apache_mesos_state_AbstractState__1_1expunge_1cancel(
+        env,
+        thiz,
+        jfuture);
+  }
+
+  return false; // Should not interrupt and already running (or finished).
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$ExpungeFuture
+ * Method:    is_cancelled
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL 
Java_org_apache_mesos_state_AbstractState_00024ExpungeFuture_is_1cancelled
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1expunge_1is_1cancelled(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$ExpungeFuture
+ * Method:    is_done
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL 
Java_org_apache_mesos_state_AbstractState_00024ExpungeFuture_is_1done
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1expunge_1is_1done(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$ExpungeFuture
+ * Method:    __get
+ * Signature: ()Ljava/lang/Boolean;
+ */
+JNIEXPORT jobject JNICALL 
Java_org_apache_mesos_state_AbstractState_00024ExpungeFuture_get
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1expunge_1get(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$ExpungeFuture
+ * Method:    get_timeout
+ * Signature: (JLjava/util/concurrent/TimeUnit;)Ljava/lang/Boolean;
+ */
+JNIEXPORT jobject JNICALL 
Java_org_apache_mesos_state_AbstractState_00024ExpungeFuture_get_1timeout
+  (JNIEnv* env, jobject thiz, jlong jtimeout, jobject junit)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1expunge_1get_1timeout(
+      env,
+      thiz,
+      jfuture,
+      jtimeout,
+      junit);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$ExpungeFuture
+ * Method:    finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL 
Java_org_apache_mesos_state_AbstractState_00024ExpungeFuture_finalize
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  Java_org_apache_mesos_state_AbstractState__1_1expunge_1finalize(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
  * Class:     org_apache_mesos_state_AbstractState
  * Method:    __names
  * Signature: ()J
@@ -792,4 +1180,130 @@ JNIEXPORT void JNICALL 
Java_org_apache_mesos_state_AbstractState__1_1names_1fina
   delete future;
 }
 
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$NamesFuture
+ * Method:    cancel
+ * Signature: (Z)Z
+ */
+JNIEXPORT jboolean JNICALL 
Java_org_apache_mesos_state_AbstractState_00024NamesFuture_cancel
+  (JNIEnv* env, jobject thiz, jboolean mayInterruptIfRunning)
+{
+  if (mayInterruptIfRunning) {
+    static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+    static jfieldID field = env->GetFieldID(clazz, "future", "J");
+    jlong jfuture = env->GetLongField(thiz, field);
+
+    // See TODO at top of file for why we proxy this call.
+    return Java_org_apache_mesos_state_AbstractState__1_1names_1cancel(
+        env,
+        thiz,
+        jfuture);
+  }
+
+  return false; // Should not interrupt and already running (or finished).
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$NamesFuture
+ * Method:    is_cancelled
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL 
Java_org_apache_mesos_state_AbstractState_00024NamesFuture_is_1cancelled
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1names_1is_1cancelled(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$NamesFuture
+ * Method:    is_done
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL 
Java_org_apache_mesos_state_AbstractState_00024NamesFuture_is_1done
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1names_1is_1done(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$NamesFuture
+ * Method:    get
+ * Signature: ()Ljava/util/Iterator;
+ */
+JNIEXPORT jobject JNICALL 
Java_org_apache_mesos_state_AbstractState_00024NamesFuture_get
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1names_1get(
+      env,
+      thiz,
+      jfuture);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$NamesFuture
+ * Method:    get_timeout
+ * Signature: (JLjava/util/concurrent/TimeUnit;)Ljava/util/Iterator;
+ */
+JNIEXPORT jobject JNICALL 
Java_org_apache_mesos_state_AbstractState_00024NamesFuture_get_1timeout
+  (JNIEnv* env, jobject thiz, jlong jtimeout, jobject junit)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  return Java_org_apache_mesos_state_AbstractState__1_1names_1get_1timeout(
+      env,
+      thiz,
+      jfuture,
+      jtimeout,
+      junit);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_AbstractState$NamesFuture
+ * Method:    finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL 
Java_org_apache_mesos_state_AbstractState_00024NamesFuture_finalize
+  (JNIEnv* env, jobject thiz)
+{
+  static jclass clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(thiz));
+  static jfieldID field = env->GetFieldID(clazz, "future", "J");
+  jlong jfuture = env->GetLongField(thiz, field);
+
+  // See TODO at top of file for why we proxy this call.
+  Java_org_apache_mesos_state_AbstractState__1_1names_1finalize(
+      env,
+      thiz,
+      jfuture);
+}
+
 } // extern "C" {

http://git-wip-us.apache.org/repos/asf/mesos/blob/5d0b5fdb/src/java/src/org/apache/mesos/state/AbstractState.java
----------------------------------------------------------------------
diff --git a/src/java/src/org/apache/mesos/state/AbstractState.java 
b/src/java/src/org/apache/mesos/state/AbstractState.java
index c66bf05..6514954 100644
--- a/src/java/src/org/apache/mesos/state/AbstractState.java
+++ b/src/java/src/org/apache/mesos/state/AbstractState.java
@@ -38,6 +38,11 @@ public abstract class AbstractState implements State {
 
   @Override
   public Future<Variable> fetch(final String name) {
+    if (!MesosNativeLibrary.version().before(MESOS_2161_JIRA_FIX_VERSION)) {
+      return new FetchFuture(name);
+    }
+
+    // TODO(jmlvanre): Deprecate anonymous future in 0.24 (MESOS-2161).
     final long future = __fetch(name); // Asynchronously start the operation.
     return new Future<Variable>() {
       @Override
@@ -78,6 +83,11 @@ public abstract class AbstractState implements State {
 
   @Override
   public Future<Variable> store(Variable variable) {
+    if (!MesosNativeLibrary.version().before(MESOS_2161_JIRA_FIX_VERSION)) {
+      return new StoreFuture(variable);
+    }
+
+    // TODO(jmlvanre): Deprecate anonymous future in 0.24 (MESOS-2161).
     final long future = __store(variable); // Asynchronously start the 
operation.
     return new Future<Variable>() {
       @Override
@@ -118,6 +128,11 @@ public abstract class AbstractState implements State {
 
   @Override
   public Future<Boolean> expunge(Variable variable) {
+    if (!MesosNativeLibrary.version().before(MESOS_2161_JIRA_FIX_VERSION)) {
+      return new ExpungeFuture(variable);
+    }
+
+    // TODO(jmlvanre): Deprecate anonymous future in 0.24 (MESOS-2161).
     final long future = __expunge(variable); // Asynchronously start the 
operation.
     return new Future<Boolean>() {
       @Override
@@ -157,6 +172,11 @@ public abstract class AbstractState implements State {
   }
 
   public Future<Iterator<String>> names() {
+    if (!MesosNativeLibrary.version().before(MESOS_2161_JIRA_FIX_VERSION)) {
+      return new NamesFuture();
+    }
+
+    // TODO(jmlvanre): Deprecate anonymous future in 0.24 (MESOS-2161).
     final long future = __names(); // Asynchronously start the operation.
     return new Future<Iterator<String>>() {
       @Override
@@ -198,8 +218,46 @@ public abstract class AbstractState implements State {
 
   protected native void finalize();
 
-  // Native implementations of 'fetch', 'store', 'expunge', and 'names'.
+  // Native implementations of 'fetch', 'store', 'expunge', and 'names'. We 
wrap
+  // them in classes to carry the java references correctly through the JNI
+  // bindings (MESOS-2161). The native functions in AbstractState will be
+  // deprecated in 0.24.
+
+  private class FetchFuture implements Future<Variable> {
+
+    public FetchFuture(String name) {
+      future = __fetch(name);
+    }
+
+    @Override
+    public native boolean cancel(boolean mayInterruptIfRunning);
+
+    @Override
+    public native boolean isCancelled();
+
+    @Override
+    public native boolean isDone();
+
+    @Override
+    public native Variable get()
+        throws InterruptedException, ExecutionException;
+
+    @Override
+    public native Variable get(long timeout, TimeUnit unit)
+        throws InterruptedException, ExecutionException, TimeoutException;
+
+    @Override
+    protected native void finalize();
+
+    private long future;
+  }
+
   private native long __fetch(String name);
+
+  // TODO(jmlvanre): Deprecate below functions in 0.24 because we can't track
+  // the java object references correctly. (MESOS-2161). The above 
'FetchFuture'
+  // class fixes this bug. We leave the below functions for backwards
+  // compatibility.
   private native boolean __fetch_cancel(long future);
   private native boolean __fetch_is_cancelled(long future);
   private native boolean __fetch_is_done(long future);
@@ -208,7 +266,41 @@ public abstract class AbstractState implements State {
       long future, long timeout, TimeUnit unit);
   private native void __fetch_finalize(long future);
 
+  private class StoreFuture implements Future<Variable> {
+
+    public StoreFuture(Variable variable) {
+      future = __store(variable);
+    }
+
+    @Override
+    public native boolean cancel(boolean mayInterruptIfRunning);
+
+    @Override
+    public native boolean isCancelled();
+
+    @Override
+    public native boolean isDone();
+
+    @Override
+    public native Variable get()
+        throws InterruptedException, ExecutionException;
+
+    @Override
+    public native Variable get(long timeout, TimeUnit unit)
+        throws InterruptedException, ExecutionException, TimeoutException;
+
+    @Override
+    protected native void finalize();
+
+    private long future;
+  }
+
   private native long __store(Variable variable);
+
+  // TODO(jmlvanre): Deprecate below functions in 0.24 because we can't track
+  // the java object references correctly. (MESOS-2161). The above 
'StoreFuture'
+  // class fixes this bug. We leave the below functions for backwards
+  // compatibility.
   private native boolean __store_cancel(long future);
   private native boolean __store_is_cancelled(long future);
   private native boolean __store_is_done(long future);
@@ -217,7 +309,41 @@ public abstract class AbstractState implements State {
       long future, long timeout, TimeUnit unit);
   private native void __store_finalize(long future);
 
+  private class ExpungeFuture implements Future<Boolean> {
+
+    public ExpungeFuture(Variable variable) {
+      future = __expunge(variable);
+    }
+
+    @Override
+    public native boolean cancel(boolean mayInterruptIfRunning);
+
+    @Override
+    public native boolean isCancelled();
+
+    @Override
+    public native boolean isDone();
+
+    @Override
+    public native Boolean get()
+        throws InterruptedException, ExecutionException;
+
+    @Override
+    public native Boolean get(long timeout, TimeUnit unit)
+        throws InterruptedException, ExecutionException, TimeoutException;
+
+    @Override
+    protected native void finalize();
+
+    private long future;
+  }
+
   private native long __expunge(Variable variable);
+
+  // TODO(jmlvanre): Deprecate below functions in 0.24 because we can't track
+  // the java object references correctly. (MESOS-2161). The above
+  // 'ExpungeFuture' class fixes this bug. We leave the below functions for
+  // backwards compatibility.
   private native boolean __expunge_cancel(long future);
   private native boolean __expunge_is_cancelled(long future);
   private native boolean __expunge_is_done(long future);
@@ -226,7 +352,41 @@ public abstract class AbstractState implements State {
       long future, long timeout, TimeUnit unit);
   private native void __expunge_finalize(long future);
 
+  private class NamesFuture implements Future<Iterator<String>> {
+
+    public NamesFuture() {
+      future = __names();
+    }
+
+    @Override
+    public native boolean cancel(boolean mayInterruptIfRunning);
+
+    @Override
+    public native boolean isCancelled();
+
+    @Override
+    public native boolean isDone();
+
+    @Override
+    public native Iterator<String> get()
+        throws InterruptedException, ExecutionException;
+
+    @Override
+    public native Iterator<String> get(long timeout, TimeUnit unit)
+        throws InterruptedException, ExecutionException, TimeoutException;
+
+    @Override
+    protected native void finalize();
+
+    private long future;
+  }
+
   private native long __names();
+
+  // TODO(jmlvanre): Deprecate below functions in 0.24 because we can't track
+  // the java object references correctly. (MESOS-2161). The above 
'NamesFuture'
+  // class fixes this bug. We leave the below functions for backwards
+  // compatibility.
   private native boolean __names_cancel(long future);
   private native boolean __names_is_cancelled(long future);
   private native boolean __names_is_done(long future);
@@ -237,4 +397,7 @@ public abstract class AbstractState implements State {
 
   private long __storage;
   private long __state;
+
+  private final static MesosNativeLibrary.Version MESOS_2161_JIRA_FIX_VERSION =
+    new MesosNativeLibrary.Version(0, 22, 1);
 }

Reply via email to