X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fjava.c;h=2d310c6f4c2947f2df3cf311d8d7f8c496aaa03b;hb=fb9f56e5af1a63d94c80a2ea6f067aeb7787f397;hp=984d29a4c20d6da55315bf6bcf7bd28bef413d51;hpb=d3733caf0686008ac5130e2f81fa30d60993c63c;p=collectd.git diff --git a/src/java.c b/src/java.c index 984d29a4..2d310c6f 100644 --- a/src/java.c +++ b/src/java.c @@ -60,11 +60,14 @@ struct java_plugin_config_s /* {{{ */ typedef struct java_plugin_config_s java_plugin_config_t; /* }}} */ -#define CB_TYPE_CONFIG 1 -#define CB_TYPE_INIT 2 -#define CB_TYPE_READ 3 -#define CB_TYPE_WRITE 4 -#define CB_TYPE_SHUTDOWN 5 +#define CB_TYPE_CONFIG 1 +#define CB_TYPE_INIT 2 +#define CB_TYPE_READ 3 +#define CB_TYPE_WRITE 4 +#define CB_TYPE_FLUSH 5 +#define CB_TYPE_SHUTDOWN 6 +#define CB_TYPE_LOG 7 +#define CB_TYPE_NOTIFICATION 8 struct cjni_callback_info_s /* {{{ */ { char *name; @@ -113,6 +116,9 @@ static int cjni_callback_register (JNIEnv *jvm_env, jobject o_name, static int cjni_read (user_data_t *user_data); static int cjni_write (const data_set_t *ds, const value_list_t *vl, user_data_t *ud); +static int cjni_flush (int timeout, const char *identifier, user_data_t *ud); +static void cjni_log (int severity, const char *message, user_data_t *ud); +static int cjni_notification (const notification_t *n, user_data_t *ud); /* * C to Java conversion functions @@ -832,7 +838,90 @@ static jobject ctoj_value_list (JNIEnv *jvm_env, /* {{{ */ } return (o_valuelist); -} /* }}} int ctoj_value_list */ +} /* }}} jobject ctoj_value_list */ + +/* Convert a notification_t to a org.collectd.api.Notification */ +static jobject ctoj_notification (JNIEnv *jvm_env, /* {{{ */ + const notification_t *n) +{ + jclass c_notification; + jmethodID m_constructor; + jobject o_notification; + int status; + + /* First, create a new Notification instance.. + * Look up the class.. */ + c_notification = (*jvm_env)->FindClass (jvm_env, + "org.collectd.api.Notification"); + if (c_notification == NULL) + { + ERROR ("java plugin: ctoj_notification: " + "FindClass (org.collectd.api.Notification) failed."); + return (NULL); + } + + /* Lookup the `Notification ()' constructor. */ + m_constructor = (*jvm_env)->GetMethodID (jvm_env, c_notification, + "", "()V"); + if (m_constructor == NULL) + { + ERROR ("java plugin: ctoj_notification: Cannot find the " + "`Notification ()' constructor."); + return (NULL); + } + + /* Create a new instance. */ + o_notification = (*jvm_env)->NewObject (jvm_env, c_notification, + m_constructor); + if (o_notification == NULL) + { + ERROR ("java plugin: ctoj_notification: Creating a new Notification " + "instance failed."); + return (NULL); + } + + /* Set the strings.. */ +#define SET_STRING(str,method_name) do { \ + status = ctoj_string (jvm_env, str, \ + c_notification, o_notification, method_name); \ + if (status != 0) { \ + ERROR ("java plugin: ctoj_notification: jtoc_string (%s) failed.", \ + method_name); \ + (*jvm_env)->DeleteLocalRef (jvm_env, o_notification); \ + return (NULL); \ + } } while (0) + + SET_STRING (n->host, "setHost"); + SET_STRING (n->plugin, "setPlugin"); + SET_STRING (n->plugin_instance, "setPluginInstance"); + SET_STRING (n->type, "setType"); + SET_STRING (n->type_instance, "setTypeInstance"); + SET_STRING (n->message, "setMessage"); + +#undef SET_STRING + + /* Set the `time' member. Java stores time in milliseconds. */ + status = ctoj_long (jvm_env, ((jlong) n->time) * ((jlong) 1000), + c_notification, o_notification, "setTime"); + if (status != 0) + { + ERROR ("java plugin: ctoj_notification: ctoj_long (setTime) failed."); + (*jvm_env)->DeleteLocalRef (jvm_env, o_notification); + return (NULL); + } + + /* Set the `interval' member.. */ + status = ctoj_int (jvm_env, (jint) n->severity, + c_notification, o_notification, "setSeverity"); + if (status != 0) + { + ERROR ("java plugin: ctoj_notification: ctoj_int (setSeverity) failed."); + (*jvm_env)->DeleteLocalRef (jvm_env, o_notification); + return (NULL); + } + + return (o_notification); +} /* }}} jobject ctoj_notification */ /* * Java to C conversion functions @@ -1247,6 +1336,29 @@ static jint JNICALL cjni_api_register_write (JNIEnv *jvm_env, /* {{{ */ return (0); } /* }}} jint cjni_api_register_write */ +static jint JNICALL cjni_api_register_flush (JNIEnv *jvm_env, /* {{{ */ + jobject this, jobject o_name, jobject o_flush) +{ + user_data_t ud; + cjni_callback_info_t *cbi; + + cbi = cjni_callback_info_create (jvm_env, o_name, o_flush, CB_TYPE_FLUSH); + if (cbi == NULL) + return (-1); + + DEBUG ("java plugin: Registering new flush callback: %s", cbi->name); + + memset (&ud, 0, sizeof (ud)); + ud.data = (void *) cbi; + ud.free_func = cjni_callback_info_destroy; + + plugin_register_flush (cbi->name, cjni_flush, &ud); + + (*jvm_env)->DeleteLocalRef (jvm_env, o_flush); + + return (0); +} /* }}} jint cjni_api_register_flush */ + static jint JNICALL cjni_api_register_shutdown (JNIEnv *jvm_env, /* {{{ */ jobject this, jobject o_name, jobject o_shutdown) { @@ -1254,6 +1366,53 @@ static jint JNICALL cjni_api_register_shutdown (JNIEnv *jvm_env, /* {{{ */ CB_TYPE_SHUTDOWN)); } /* }}} jint cjni_api_register_shutdown */ +static jint JNICALL cjni_api_register_log (JNIEnv *jvm_env, /* {{{ */ + jobject this, jobject o_name, jobject o_log) +{ + user_data_t ud; + cjni_callback_info_t *cbi; + + cbi = cjni_callback_info_create (jvm_env, o_name, o_log, CB_TYPE_LOG); + if (cbi == NULL) + return (-1); + + DEBUG ("java plugin: Registering new log callback: %s", cbi->name); + + memset (&ud, 0, sizeof (ud)); + ud.data = (void *) cbi; + ud.free_func = cjni_callback_info_destroy; + + plugin_register_log (cbi->name, cjni_log, &ud); + + (*jvm_env)->DeleteLocalRef (jvm_env, o_log); + + return (0); +} /* }}} jint cjni_api_register_log */ + +static jint JNICALL cjni_api_register_notification (JNIEnv *jvm_env, /* {{{ */ + jobject this, jobject o_name, jobject o_notification) +{ + user_data_t ud; + cjni_callback_info_t *cbi; + + cbi = cjni_callback_info_create (jvm_env, o_name, o_notification, + CB_TYPE_NOTIFICATION); + if (cbi == NULL) + return (-1); + + DEBUG ("java plugin: Registering new notification callback: %s", cbi->name); + + memset (&ud, 0, sizeof (ud)); + ud.data = (void *) cbi; + ud.free_func = cjni_callback_info_destroy; + + plugin_register_notification (cbi->name, cjni_notification, &ud); + + (*jvm_env)->DeleteLocalRef (jvm_env, o_notification); + + return (0); +} /* }}} jint cjni_api_register_notification */ + static void JNICALL cjni_api_log (JNIEnv *jvm_env, /* {{{ */ jobject this, jint severity, jobject o_message) { @@ -1304,10 +1463,22 @@ static JNINativeMethod jni_api_functions[] = /* {{{ */ "(Ljava/lang/String;Lorg/collectd/api/CollectdWriteInterface;)I", cjni_api_register_write }, + { "registerFlush", + "(Ljava/lang/String;Lorg/collectd/api/CollectdFlushInterface;)I", + cjni_api_register_flush }, + { "registerShutdown", "(Ljava/lang/String;Lorg/collectd/api/CollectdShutdownInterface;)I", cjni_api_register_shutdown }, + { "registerLog", + "(Ljava/lang/String;Lorg/collectd/api/CollectdLogInterface;)I", + cjni_api_register_log }, + + { "registerNotification", + "(Ljava/lang/String;Lorg/collectd/api/CollectdNotificationInterface;)I", + cjni_api_register_notification }, + { "log", "(ILjava/lang/String;)V", cjni_api_log }, @@ -1351,11 +1522,26 @@ static cjni_callback_info_t *cjni_callback_info_create (JNIEnv *jvm_env, /* {{{ method_signature = "(Lorg/collectd/api/ValueList;)I"; break; + case CB_TYPE_FLUSH: + method_name = "flush"; + method_signature = "(ILjava/lang/String;)I"; + break; + case CB_TYPE_SHUTDOWN: method_name = "shutdown"; method_signature = "()I"; break; + case CB_TYPE_LOG: + method_name = "log"; + method_signature = "(ILjava/lang/String;)V"; + break; + + case CB_TYPE_NOTIFICATION: + method_name = "notification"; + method_signature = "(LLorg/collectd/api/Notification;)I"; + break; + default: ERROR ("java plugin: cjni_callback_info_create: Unknown type: %#x", type); @@ -1798,6 +1984,15 @@ static void cjni_callback_info_destroy (void *arg) /* {{{ */ DEBUG ("java plugin: cjni_callback_info_destroy (arg = %p);", arg); + cbi = (cjni_callback_info_t *) arg; + + /* This condition can occurr when shutting down. */ + if (jvm == NULL) + { + sfree (cbi); + return; + } + if (arg == NULL) return; @@ -1808,8 +2003,6 @@ static void cjni_callback_info_destroy (void *arg) /* {{{ */ return; } - cbi = (cjni_callback_info_t *) arg; - (*jvm_env)->DeleteGlobalRef (jvm_env, cbi->object); cbi->method = NULL; @@ -1826,6 +2019,7 @@ static int cjni_read (user_data_t *ud) /* {{{ */ JNIEnv *jvm_env; cjni_callback_info_t *cbi; int status; + int ret_status; if (jvm == NULL) { @@ -1845,7 +2039,7 @@ static int cjni_read (user_data_t *ud) /* {{{ */ cbi = (cjni_callback_info_t *) ud->data; - status = (*jvm_env)->CallIntMethod (jvm_env, cbi->object, + ret_status = (*jvm_env)->CallIntMethod (jvm_env, cbi->object, cbi->method); status = cjni_thread_detach (); @@ -1855,7 +2049,7 @@ static int cjni_read (user_data_t *ud) /* {{{ */ return (-1); } - return (status); + return (ret_status); } /* }}} int cjni_read */ /* Call the CB_TYPE_WRITE callback pointed to by the `user_data_t' pointer. */ @@ -1866,6 +2060,7 @@ static int cjni_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */ cjni_callback_info_t *cbi; jobject vl_java; int status; + int ret_status; if (jvm == NULL) { @@ -1892,7 +2087,7 @@ static int cjni_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */ return (-1); } - status = (*jvm_env)->CallIntMethod (jvm_env, + ret_status = (*jvm_env)->CallIntMethod (jvm_env, cbi->object, cbi->method, vl_java); (*jvm_env)->DeleteLocalRef (jvm_env, vl_java); @@ -1904,9 +2099,146 @@ static int cjni_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */ return (-1); } - return (status); + return (ret_status); } /* }}} int cjni_write */ +/* Call the CB_TYPE_FLUSH callback pointed to by the `user_data_t' pointer. */ +static int cjni_flush (int timeout, const char *identifier, /* {{{ */ + user_data_t *ud) +{ + JNIEnv *jvm_env; + cjni_callback_info_t *cbi; + jobject o_identifier; + int status; + int ret_status; + + if (jvm == NULL) + { + ERROR ("java plugin: cjni_flush: jvm == NULL"); + return (-1); + } + + if ((ud == NULL) || (ud->data == NULL)) + { + ERROR ("java plugin: cjni_flush: Invalid user data."); + return (-1); + } + + jvm_env = cjni_thread_attach (); + if (jvm_env == NULL) + return (-1); + + cbi = (cjni_callback_info_t *) ud->data; + + o_identifier = NULL; + if (identifier != NULL) + { + o_identifier = (*jvm_env)->NewStringUTF (jvm_env, identifier); + if (o_identifier == NULL) + { + ERROR ("java plugin: cjni_flush: NewStringUTF failed."); + return (-1); + } + } + + ret_status = (*jvm_env)->CallIntMethod (jvm_env, + cbi->object, cbi->method, (jint) timeout, o_identifier); + + (*jvm_env)->DeleteLocalRef (jvm_env, o_identifier); + + status = cjni_thread_detach (); + if (status != 0) + { + ERROR ("java plugin: cjni_flush: cjni_thread_detach failed."); + return (-1); + } + + return (ret_status); +} /* }}} int cjni_flush */ + +/* Call the CB_TYPE_LOG callback pointed to by the `user_data_t' pointer. */ +static void cjni_log (int severity, const char *message, /* {{{ */ + user_data_t *ud) +{ + JNIEnv *jvm_env; + cjni_callback_info_t *cbi; + jobject o_message; + + if (jvm == NULL) + return; + + if ((ud == NULL) || (ud->data == NULL)) + return; + + jvm_env = cjni_thread_attach (); + if (jvm_env == NULL) + return; + + cbi = (cjni_callback_info_t *) ud->data; + + o_message = (*jvm_env)->NewStringUTF (jvm_env, message); + if (o_message == NULL) + return; + + (*jvm_env)->CallVoidMethod (jvm_env, + cbi->object, cbi->method, (jint) severity, o_message); + + (*jvm_env)->DeleteLocalRef (jvm_env, o_message); + + cjni_thread_detach (); +} /* }}} void cjni_log */ + +/* Call the CB_TYPE_NOTIFICATION callback pointed to by the `user_data_t' + * pointer. */ +static int cjni_notification (const notification_t *n, /* {{{ */ + user_data_t *ud) +{ + JNIEnv *jvm_env; + cjni_callback_info_t *cbi; + jobject o_notification; + int status; + int ret_status; + + if (jvm == NULL) + { + ERROR ("java plugin: cjni_read: jvm == NULL"); + return (-1); + } + + if ((ud == NULL) || (ud->data == NULL)) + { + ERROR ("java plugin: cjni_read: Invalid user data."); + return (-1); + } + + jvm_env = cjni_thread_attach (); + if (jvm_env == NULL) + return (-1); + + cbi = (cjni_callback_info_t *) ud->data; + + o_notification = ctoj_notification (jvm_env, n); + if (o_notification == NULL) + { + ERROR ("java plugin: cjni_notification: ctoj_notification failed."); + return (-1); + } + + ret_status = (*jvm_env)->CallIntMethod (jvm_env, + cbi->object, cbi->method, o_notification); + + (*jvm_env)->DeleteLocalRef (jvm_env, o_notification); + + status = cjni_thread_detach (); + if (status != 0) + { + ERROR ("java plugin: cjni_read: cjni_thread_detach failed."); + return (-1); + } + + return (ret_status); +} /* }}} int cjni_notification */ + /* Iterate over `java_classes_list' and create one object of each class. This * will trigger the object's constructors, to the objects can register callback * methods. */ @@ -2110,6 +2442,7 @@ static int cjni_shutdown (void) /* {{{ */ sfree (java_classes_list); /* Destroy the JVM */ + DEBUG ("java plugin: Destroying the JVM."); (*jvm)->DestroyJavaVM (jvm); jvm = NULL; jvm_env = NULL;