You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by an...@apache.org on 2016/08/02 15:42:44 UTC

[2/7] mesos git commit: Added native implementation for v1 Mesos interface.

Added native implementation for v1 Mesos interface.

This change adds the native C++ implementation for the v1
Java class `JNIMesos` used for interacting with Mesos.

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


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

Branch: refs/heads/master
Commit: bca68f63aa04d91cdb44b8e100f364bf981d6bd2
Parents: 5855532
Author: Anand Mazumdar <an...@apache.org>
Authored: Tue Jul 19 23:17:50 2016 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Tue Aug 2 08:25:48 2016 -0700

----------------------------------------------------------------------
 src/Makefile.am                                 |   9 +-
 .../org_apache_mesos_v1_scheduler_JNIMesos.cpp  | 317 +++++++++++++++++++
 2 files changed, 325 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/bca68f63/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 3a743e4..2b02b5f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1562,6 +1562,7 @@ libjava_la_SOURCES =							\
   java/jni/org_apache_mesos_state_LogState.cpp				\
   java/jni/org_apache_mesos_state_Variable.cpp				\
   java/jni/org_apache_mesos_state_ZooKeeperState.cpp			\
+  java/jni/org_apache_mesos_v1_scheduler_JNIMesos.cpp			\
   jvm/jvm.cpp								\
   jvm/jvm.hpp								\
   jvm/java/io.hpp							\
@@ -1603,7 +1604,8 @@ nodist_libjava_la_SOURCES =						\
   java/jni/org_apache_mesos_state_LevelDBState.h			\
   java/jni/org_apache_mesos_state_LogState.h				\
   java/jni/org_apache_mesos_state_Variable.h				\
-  java/jni/org_apache_mesos_state_ZooKeeperState.h
+  java/jni/org_apache_mesos_state_ZooKeeperState.h			\
+  java/jni/org_apache_mesos_v1_scheduler_JNIMesos.h
 
 BUILT_SOURCES += $(nodist_libjava_la_SOURCES)
 
@@ -1647,6 +1649,11 @@ java/jni/org_apache_mesos_state_ZooKeeperState.h: $(MESOS_JAR)
 	-classpath $(MESOS_JAR):@PROTOBUF_JAR@				\
 	  org.apache.mesos.state.ZooKeeperState
 
+java/jni/org_apache_mesos_v1_scheduler_JNIMesos.h: $(MESOS_JAR)
+	$(JAVA_HOME)/bin/javah -d java/jni				\
+	-classpath $(MESOS_JAR):@PROTOBUF_JAR@				\
+	  org.apache.mesos.v1.scheduler.JNIMesos
+
 $(EXAMPLES_JAR): $(EXAMPLES_SOURCE)
 	@echo "Building examples.jar ..."
 	$(MKDIR_P) examples/java

http://git-wip-us.apache.org/repos/asf/mesos/blob/bca68f63/src/java/jni/org_apache_mesos_v1_scheduler_JNIMesos.cpp
----------------------------------------------------------------------
diff --git a/src/java/jni/org_apache_mesos_v1_scheduler_JNIMesos.cpp b/src/java/jni/org_apache_mesos_v1_scheduler_JNIMesos.cpp
new file mode 100644
index 0000000..e197b37
--- /dev/null
+++ b/src/java/jni/org_apache_mesos_v1_scheduler_JNIMesos.cpp
@@ -0,0 +1,317 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <string>
+#include <vector>
+
+#include <process/owned.hpp>
+
+#include <mesos/v1/mesos.hpp>
+
+#include <mesos/v1/scheduler.hpp>
+
+#include <mesos/v1/scheduler/scheduler.hpp>
+
+#include <stout/foreach.hpp>
+#include <stout/lambda.hpp>
+#include <stout/option.hpp>
+#include <stout/result.hpp>
+#include <stout/try.hpp>
+
+#include "jvm/jvm.hpp"
+
+#include "construct.hpp"
+#include "convert.hpp"
+#include "org_apache_mesos_v1_scheduler_JNIMesos.h"
+
+using namespace mesos::v1::scheduler;
+
+using mesos::v1::Credential;
+
+using process::Owned;
+
+using std::string;
+using std::vector;
+
+namespace v1 {
+
+class JNIMesos
+{
+public:
+  JNIMesos(
+      JNIEnv* _env,
+      jweak _jmesos,
+      const string& master,
+      const Option<Credential>& credential)
+    : jvm(nullptr), env(_env), jmesos(_jmesos)
+  {
+    env->GetJavaVM(&jvm);
+
+    mesos.reset(
+        new Mesos(master,
+            mesos::ContentType::PROTOBUF,
+            std::bind(&JNIMesos::connected, this),
+            std::bind(&JNIMesos::disconnected, this),
+            std::bind(&JNIMesos::received_, this, lambda::_1),
+            credential));
+  }
+
+  virtual ~JNIMesos() = default;
+
+  virtual void connected();
+  virtual void disconnected();
+  virtual void received(const Event& event);
+
+  void received_(std::queue<Event> events) {
+    while (!events.empty()) {
+      received(events.front());
+      events.pop();
+    }
+  }
+
+  JavaVM* jvm;
+  JNIEnv* env;
+  jweak jmesos;
+
+  Owned<Mesos> mesos;
+};
+
+
+void JNIMesos::connected()
+{
+  jvm->AttachCurrentThread(JNIENV_CAST(&env), nullptr);
+
+  jclass clazz = env->GetObjectClass(jmesos);
+
+  jfieldID scheduler =
+    env->GetFieldID(clazz, "scheduler",
+                    "Lorg/apache/mesos/v1/scheduler/Scheduler;");
+
+  jobject jscheduler = env->GetObjectField(jmesos, scheduler);
+
+  clazz = env->GetObjectClass(jscheduler);
+
+  // scheduler.connected(mesos);
+  jmethodID connected =
+    env->GetMethodID(clazz, "connected",
+                     "(Lorg/apache/mesos/v1/scheduler/Mesos;)V");
+
+  env->ExceptionClear();
+
+  env->CallVoidMethod(jscheduler, connected, jmesos);
+
+  if (env->ExceptionCheck()) {
+    env->ExceptionDescribe();
+    env->ExceptionClear();
+    jvm->DetachCurrentThread();
+    ABORT("Exception thrown during `connected` call");
+  }
+
+  jvm->DetachCurrentThread();
+}
+
+
+void JNIMesos::disconnected()
+{
+  jvm->AttachCurrentThread(JNIENV_CAST(&env), nullptr);
+
+  jclass clazz = env->GetObjectClass(jmesos);
+
+  jfieldID scheduler =
+    env->GetFieldID(clazz, "scheduler",
+                    "Lorg/apache/mesos/v1/scheduler/Scheduler;");
+
+  jobject jscheduler = env->GetObjectField(jmesos, scheduler);
+
+  clazz = env->GetObjectClass(jscheduler);
+
+  // scheduler.disconnected(mesos);
+  jmethodID disconnected =
+    env->GetMethodID(clazz, "disconnected",
+                     "(Lorg/apache/mesos/v1/scheduler/Mesos;)V");
+
+  env->ExceptionClear();
+
+  env->CallVoidMethod(jscheduler, disconnected, jmesos);
+
+  if (env->ExceptionCheck()) {
+    env->ExceptionDescribe();
+    env->ExceptionClear();
+    jvm->DetachCurrentThread();
+    ABORT("Exception thrown during `disconnected` call");
+  }
+
+  jvm->DetachCurrentThread();
+}
+
+
+void JNIMesos::received(const Event& event)
+{
+  jvm->AttachCurrentThread(JNIENV_CAST(&env), nullptr);
+
+  jclass clazz = env->GetObjectClass(jmesos);
+
+  jfieldID scheduler =
+    env->GetFieldID(clazz, "scheduler",
+                    "Lorg/apache/mesos/v1/scheduler/Scheduler;");
+
+  jobject jscheduler = env->GetObjectField(jmesos, scheduler);
+
+  clazz = env->GetObjectClass(jscheduler);
+
+  // scheduler.received(mesos, event);
+  jmethodID received =
+    env->GetMethodID(clazz, "received",
+                     "(Lorg/apache/mesos/v1/scheduler/Mesos;"
+                     "Lorg/apache/mesos/v1/scheduler/Protos$Event;)V");
+
+  jobject jevent = convert<Event>(env, event);
+
+  env->ExceptionClear();
+
+  env->CallVoidMethod(jscheduler, received, jmesos, jevent);
+
+  if (env->ExceptionCheck()) {
+    env->ExceptionDescribe();
+    env->ExceptionClear();
+    jvm->DetachCurrentThread();
+    ABORT("Exception thrown during `received` call");
+  }
+
+  jvm->DetachCurrentThread();
+}
+
+} // namespace v1 {
+
+
+extern "C" {
+
+/*
+ * Class:     org_apache_mesos_v1_JNIMesos
+ * Method:    initialize
+ * Signature: ()V
+ *
+ */
+JNIEXPORT void JNICALL Java_org_apache_mesos_v1_scheduler_JNIMesos_initialize
+  (JNIEnv* env, jobject thiz)
+{
+  jclass clazz = env->GetObjectClass(thiz);
+
+  // Create a weak global reference to the Scheduler
+  // instance (we want a global reference so the GC doesn't collect
+  // the instance but we make it weak so the JVM can exit).
+  jweak jmesos = env->NewWeakGlobalRef(thiz);
+
+  // Get out the master passed into the constructor.
+  jfieldID master = env->GetFieldID(clazz, "master", "Ljava/lang/String;");
+  jobject jmaster = env->GetObjectField(thiz, master);
+
+  // Get out the credential passed into the constructor.
+  jfieldID credential =
+    env->GetFieldID(clazz, "credential",
+                    "Lorg/apache/mesos/v1/Protos$Credential;");
+
+  jobject jcredential = env->GetObjectField(thiz, credential);
+
+  Option<Credential> credential_;
+  if (!env->IsSameObject(jcredential, nullptr)) {
+    credential_ = construct<Credential>(env, jcredential);
+  }
+
+  // Create the C++ scheduler and initialize `__mesos`.
+  v1::JNIMesos* mesos =
+    new v1::JNIMesos(env, jmesos, construct<string>(env, jmaster), credential_);
+
+  jfieldID __mesos = env->GetFieldID(clazz, "__mesos", "J");
+  env->SetLongField(thiz, __mesos, (jlong) mesos);
+}
+
+
+/*
+ * Class:     org_apache_mesos_v1_JNIMesos
+ * Method:    finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_apache_mesos_v1_scheduler_JNIMesos_finalize
+  (JNIEnv* env, jobject thiz)
+{
+  jclass clazz = env->GetObjectClass(thiz);
+
+  jfieldID __mesos = env->GetFieldID(clazz, "__mesos", "J");
+  v1::JNIMesos* mesos =
+    (v1::JNIMesos*) env->GetLongField(thiz, __mesos);
+
+  env->DeleteWeakGlobalRef(mesos->jmesos);
+
+  delete mesos;
+}
+
+
+/*
+ * Class:     org_apache_mesos_v1_JNIMesos
+ * Method:    send
+ * Signature: (Lorg/apache/mesos/v1/scheduler/Protos/Call;)V
+ */
+JNIEXPORT void JNICALL Java_org_apache_mesos_v1_scheduler_JNIMesos_send
+  (JNIEnv* env, jobject thiz, jobject jcall)
+{
+  // Construct a C++ Call from the Java Call.
+  const Call& call = construct<Call>(env, jcall);
+
+  jclass clazz = env->GetObjectClass(thiz);
+
+  jfieldID __mesos = env->GetFieldID(clazz, "__mesos", "J");
+  v1::JNIMesos* mesos =
+    (v1::JNIMesos*) env->GetLongField(thiz, __mesos);
+
+  // It is possible that `mesos` might not be initialized in some cases due to
+  // a possible race condition. See MESOS-5926 for more details.
+  if (mesos->mesos.get() == nullptr) {
+    LOG(WARNING) << "Ignoring call " << call.type() << " as the library has "
+                 << "not been initialized yet";
+    return;
+  }
+
+  mesos->mesos->send(call);
+}
+
+
+/*
+ * Class:     org_apache_mesos_v1_scheduler_JNIMesos
+ * Method:    reconnect
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_apache_mesos_v1_scheduler_JNIMesos_reconnect
+  (JNIEnv* env, jobject thiz)
+{
+  jclass clazz = env->GetObjectClass(thiz);
+
+  jfieldID __mesos = env->GetFieldID(clazz, "__mesos", "J");
+  v1::JNIMesos* mesos =
+    (v1::JNIMesos*) env->GetLongField(thiz, __mesos);
+
+  // It is possible that `mesos` might not be initialized in some cases due to
+  // a possible race condition. See MESOS-5926 for more details.
+  if (mesos->mesos.get() == nullptr) {
+    LOG(WARNING) << "Ignoring the reconnect request as the library has not "
+                 << "been initialized yet";
+    return;
+  }
+
+  mesos->mesos->reconnect();
+}
+
+} // extern "C" {