Below is the list of changes that have just been committed into a local
5.2 repository of eric. When eric does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-09-21 21:15:23+02:00, eherman@stripped +6 -0
Most of the the Native-to-Java side started. Needs JVM startup parameters and better error checking and needs java-to-native piece done.
plugin/java_udf/Makefile.am@stripped, 2007-09-21 21:15:20+02:00, eherman@stripped +6 -2
added jni abstraction/support sources to the build.
plugin/java_udf/java_context.cc@stripped, 2007-09-21 21:15:20+02:00, eherman@stripped +19 -5
java_context now detaches from JVM upon destruction; added some null-safety checks.
plugin/java_udf/java_context.h@stripped, 2007-09-21 21:15:20+02:00, eherman@stripped +1 -0
added destructor
plugin/java_udf/java_udf.cc@stripped, 2007-09-21 21:15:20+02:00, eherman@stripped +167 -85
a more complete implementation.
plugin/java_udf/jvm_singleton.cc@stripped, 2007-09-21 21:15:20+02:00, eherman@stripped +9 -0
added a non-creating singleton get
plugin/java_udf/jvm_singleton.h@stripped, 2007-09-21 21:15:21+02:00, eherman@stripped +1 -0
added a get-like method that does not create.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: eherman
# Host: halle.local
# Root: /Users/eric/src/mysql-5.2-eric+antony
--- 1.3/plugin/java_udf/Makefile.am 2007-06-08 07:24:18 +02:00
+++ 1.4/plugin/java_udf/Makefile.am 2007-09-21 21:15:20 +02:00
@@ -36,13 +36,17 @@ noinst_HEADERS = java_context.h jbyte_ar
native_jvm.h java_util_arraylist.h \
jvm_interface.h test_utils.h
+java_udf_source= java_udf.cc java_context.cc jbyte_array.cc \
+ native_jvm.cc java_object_parameter.cc \
+ jobject_wrapper.cc jvm_interface.cc \
+ java_util_arraylist.cc jvm_singleton.cc
EXTRA_LTLIBRARIES= psm_java.la
pkglib_LTLIBRARIES= @plugin_java_udf_shared_target@
psm_java_la_LDFLAGS= -module -rpath $(MYSQLLIBdir) $(JAVA_LDFLAGS)
psm_java_la_CXXFLAGS= $(AM_CFLAGS) $(JAVA_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN
psm_java_la_CFLAGS= $(AM_CFLAGS) $(JAVA_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-psm_java_la_SOURCES= java_udf.cc
+psm_java_la_SOURCES= $(java_udf_source)
EXTRA_DIST = plug.in
@@ -53,7 +57,7 @@ jnicallback.h: com/mysql/udf/NativeUDFCa
$(JAVAH) -jni -o $@ com.mysql.udf.NativeUDFCallback
-test:
+test: jbyte_array_test jvm_singleton_test native_jvm_test java_context_test
./jbyte_array_test
./jvm_singleton_test
./native_jvm_test
--- 1.1/plugin/java_udf/java_context.cc 2007-06-04 21:41:14 +02:00
+++ 1.2/plugin/java_udf/java_context.cc 2007-09-21 21:15:20 +02:00
@@ -1,17 +1,21 @@
+#include "jvm_interface.h"
#include "java_context.h"
+#include "jvm_singleton.h"
#include <stdio.h>
#include <jni.h>
#include <string.h>
+#if 1
#define JNI_DBUG_ENTER(a1)
#define JNI_DBUG_RETURN(a0, a1) return(a1)
#define JNI_DBUG_VOID_RETURN(a0) return
#define JNI_DBUG_PRINT(a0, a1)
-
-//#define JNI_DBUG_ENTER(a1) fprintf(stderr, "entering: ");fprintf(stderr, a1);fprintf(stderr, "\n");
-//#define JNI_DBUG_RETURN(a0, a1) fprintf(stderr, "leaving %s\n", a0); return(a1)
-//#define JNI_DBUG_VOID_RETURN(a0) fprintf(stderr, "leaving %s\n", a0); return
-//#define JNI_DBUG_PRINT(a0, a1) fprintf(stderr, a0, a1); fprintf(stderr, "\n");
+# else
+#define JNI_DBUG_ENTER(a1) fprintf(stderr, "entering: ");fprintf(stderr, a1);fprintf(stderr, "\n");
+#define JNI_DBUG_RETURN(a0, a1) fprintf(stderr, "leaving %s\n", a0); return(a1)
+#define JNI_DBUG_VOID_RETURN(a0) fprintf(stderr, "leaving %s\n", a0); return
+#define JNI_DBUG_PRINT(a0, a1) fprintf(stderr, a0, a1); fprintf(stderr, "\n");
+#endif
// JNI Signatures
const char *JNI_VOID= "V";
@@ -43,6 +47,12 @@ Java_context::Java_context(JNIEnv *jenv)
env= jenv;
}
+Java_context::~Java_context()
+{
+ Jvm *jvm = Jvm_singleton::check();
+ if(jvm)
+ jvm->detach();
+}
jstring Java_context::to_jstring(const char *str)
{
@@ -778,6 +788,7 @@ jobject Java_context::new_java_object(co
JNI_DBUG_ENTER("Java_context::new_java_object class_name, signature, jargs");
JNI_DBUG_PRINT("getting jclass <%s> ...", class_name);
jclass cls= get_java_class(class_name);
+ if(cls == NULL) goto err;
JNI_DBUG_PRINT("getting jmethodID <init> with signature: %s ...", signature);
jmethodID methodId= get_method_id(cls, "<init>", signature);
JNI_DBUG_PRINT("creating new object ...%s", "");
@@ -791,6 +802,7 @@ jobject Java_context::new_java_object(co
fprintf(stderr, "jclass <%s> ...\n", class_name);
fprintf(stderr, "jmethodID <init> with signature: %s ...\n", signature);
if_java_exception_occurred_describe();
+err:
JNI_DBUG_RETURN(
"ERROR: Java_context::new_java_object class_name, signature, jargs",
NULL);
@@ -935,6 +947,7 @@ jclass Java_context::get_java_class(cons
{
fprintf(stderr, "Can't find class: %s", class_name);
jclass jsys= env->FindClass("System");
+ if (jsys == NULL) goto end;
const char *sig= STRING_RETURN_STRING;
jmethodID methodId= env->GetStaticMethodID(jsys, "getProperty", sig);
jvalue args[1];
@@ -948,6 +961,7 @@ jclass Java_context::get_java_class(cons
fprintf(stderr, "Syste.getProperty(\"java.class.path\")=%s", buf);
// throw(1);
}
+end:
JNI_DBUG_PRINT("jclass= %p", cls);
JNI_DBUG_RETURN("Java_context::get_java_class", cls);
}
--- 1.1/plugin/java_udf/java_context.h 2007-06-04 21:41:14 +02:00
+++ 1.2/plugin/java_udf/java_context.h 2007-09-21 21:15:20 +02:00
@@ -10,6 +10,7 @@ class Java_context
public:
Java_context(JNIEnv *jenv);
+ ~Java_context();
jobject new_java_object(const char *class_name);
jobject new_java_object(const char *class_name, const char *arg0);
--- 1.2/plugin/java_udf/java_udf.cc 2007-06-08 07:24:18 +02:00
+++ 1.3/plugin/java_udf/java_udf.cc 2007-09-21 21:15:20 +02:00
@@ -18,129 +18,192 @@
#include <strings.h>
#include <mysql.h>
#include <mysql/plugin.h>
-
-#include <jni.h>
+#include "java_context.h"
#include "jvm_singleton.h"
#include "jvm_interface.h"
-#include "java_context.h"
+#include "jobject_wrapper.h"
-static jobject _udf_module_instance;
+#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8)
+#define __attribute__(A)
+#endif
-/* this shouldn't be here, this is a temporary cheesy hack: */
-static jobject _some_java_function_invoker;
+static MYSQL_THDVAR_ULONG(context, PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_NOCMDOPT,
+ NULL, NULL, NULL, 0, 0, ~0UL, 0);
+
+static jobject udf_module;
+
+struct psm_java_context /* one context per thread */
+{
+ int nesting_level;
+ int ref_count;
+ MYSQL_THD thd;
+ Jvm *jvm;
+ Java_context *java_context;
+};
+
+struct st_mysql_psmroutine /* each function handle per thread*/
+{
+ psm_java_context *context;
+ jobject jo_function_descriptor; /* java FunctionDescriptor */
+ jobject invoker; /* java Invoker */
+};
/*
Initialize the plugin at server start or plugin installation.
+
+ SYNOPSIS
+ java_udf_plugin_init()
+
+ DESCRIPTION
+ Does nothing.
+
RETURN VALUE
0 success
+ 1 failure (could not instantiate JVM)
+ 2 failure (could not instantiate java UDFModule class)
*/
static int java_udf_plugin_init(void *arg __attribute__((unused)))
{
- char *argv;
- int argc;
-
- /* TODO: Consider whether we want to manage the jvm singlton differently */
- Jvm *jvm= Jvm_singleton::get();
-
- Java_context *java= jvm->attach();
- _udf_module_instance= java->new_java_object("com/mysql/udf/UDFModule");
-
- /* the init function can receive an array of initialization parameters */
- *argv= NULL;
- argc= 0;
- //java->call_void_method(_udf_module_instance, "init", argv, argc);
+ Jvm *jvm = Jvm_singleton::get();
+ if (!jvm)
+ return 1;
+ Java_context *java_context = jvm->attach();
- jvm->detach();
+ udf_module = java_context->new_java_object("com/mysql/udf/UDFModule");
- return(0);
+ delete java_context;
+
+ if (!udf_module)
+ {
+ Jvm_singleton::set(NULL);
+ delete jvm;
+ return 2;
+ }
+ return 0;
}
/*
Terminate the plugin at server shutdown or plugin deinstallation.
+ SYNOPSIS
+ java_udf_plugin_deinit()
+ Does nothing.
+
RETURN VALUE
0 success
+ 1 failure (cannot happen)
+
*/
static int java_udf_plugin_deinit(void *arg __attribute__((unused)))
{
- //if (1==0) return;
- if(_udf_module_instance != NULL)
- {
- Jvm *jvm= Jvm_singleton::get();
- Java_context *java= jvm->attach();
- java->delete_global_reference(_udf_module_instance);
- _udf_module_instance= NULL;
- jvm->detach();
- }
-
- return(0);
+ Jvm *jvm = Jvm_singleton::check();
+ if (!jvm)
+ return 1;
+ Java_context *java_context = jvm->attach();
+ java_context->delete_global_reference(udf_module);
+ delete java_context;
+ delete jvm;
+ Jvm_singleton::set(NULL);
}
static int java_udf_find(MYSQL_PSM_ROUTINE *handle,
const char *name, int name_length)
{
- Jvm *jvm= Jvm_singleton::get();
- Java_context *java= jvm->attach();
- /* later we can see if adding these to a cache will speed things up */
- jobject jfd= java->call_object_method(_udf_module_instance,
- "find",
- "com/mysql/udf/FunctionDescriptor",
- name);
-#if 0
- Java_function_descriptor *fd= new Java_function_descriptor(jfd);
-
- /*
- FIXXXME: now that we _have_ a function desctriptor,
- what do we do with it?
-
- We need to store the function on the *handle I think.
- */
- long long callback= 0;
- _some_java_function_invoker= java->new_java_object("com/mysql/udf/Invoker", fd, callback);
+ *handle= (MYSQL_PSM_ROUTINE) malloc(sizeof(struct st_mysql_psmroutine));
+ bzero(*handle, sizeof(struct st_mysql_psmroutine));
+
+ Jvm *jvm = Jvm_singleton::get();
+ Java_context *java_context = jvm->attach();
+ (*handle)->jo_function_descriptor = java_context->call_object_method(
+ udf_module, "find", "com/mysql/udf/FunctionDescriptor",
+ name); /* make 'name' utf8 from system charset */
+ delete java_context;
+
+ if( !(*handle)->jo_function_descriptor ) goto err;
-#endif
- jvm->detach();
return 0;
- error:
+
+err:
+ free (*handle);
+ (*handle) = NULL;
return -1;
}
-
static int java_udf_execute(MYSQL_PSM_ROUTINE handle,
- MYSQL_PSM_CONTEXT context)
+ MYSQL_PSM_CONTEXT psm_context)
{
- jobject udf_invoker;
+ psm_java_context *context;
+ if ((context= (psm_java_context *) THDVAR(psm_context->thd, context)) == 0)
+ {
+ context = new psm_java_context;
+ THDVAR(psm_context->thd, context) = (unsigned long) context;
+ context->thd = psm_context->thd;
+ context->jvm = Jvm_singleton::get();
+ context->nesting_level = 1;
+ context->ref_count = 1;
+ context->java_context = context->jvm->attach();
+ }
+ else
+ {
+ context->nesting_level++;
+ context->ref_count++;
+ }
+ handle->context = context;
+
+ if(!handle->invoker)
+ {
+ Jobject_wrapper jw_function_descriptor(context->java_context,
+ handle->jo_function_descriptor);
+ jobject jo_callback = context->java_context->new_java_object(
+ "com/mysql/udf/NativeUDFCallback",
+ (unsigned long) psm_context);
+ Jobject_wrapper jw_callback(context->java_context, jo_callback);
+ handle->invoker = context->java_context->new_java_object(
+ "com/mysql/udf/Invoker",
+ &jw_function_descriptor,
+ &jw_callback);
+ context->java_context->call_object_method(handle->invoker, "init");
+ context->java_context->delete_global_reference(jo_callback);
+ }
- /*
- FIXXXME: we neet to get the invoker from the handle
- */
- udf_invoker= _some_java_function_invoker;
-
- Jvm *jvm= Jvm_singleton::get();
- Java_context *java= jvm->attach();
- java->call_void_method(udf_invoker, "exec");
- jvm->detach();
+ context->java_context->call_void_method(handle->invoker, "exec");
+ context->nesting_level--;
+
+ if (context->ref_count != 1)
+ {
+ context->ref_count--;
+ handle->context = NULL;
+ }
+
return 0;
+err:
+ return -1;
}
static int java_udf_release(MYSQL_PSM_ROUTINE handle)
{
- jobject udf_invoker;
+ Java_context *java_context = handle->context ?
+ handle->context->java_context : Jvm_singleton::get()->attach();
- /*
- FIXXXME: we neet to get the invoker from the handle
- */
- udf_invoker= _some_java_function_invoker;
-
- Jvm *jvm= Jvm_singleton::get();
- Java_context *java= jvm->attach();
- java->call_void_method(udf_invoker, "fini");
- jvm->detach();
+ java_context->delete_global_reference(handle->invoker);
+ java_context->delete_global_reference(handle->jo_function_descriptor);
+
+ if (!handle->context)
+ delete java_context;
+ else
+ if(!(--handle->context->ref_count))
+ {
+ delete java_context;
+ THDVAR(handle->context->thd, context) = NULL;
+ delete handle->context;
+ }
+
+ free(handle);
return 0;
};
@@ -158,22 +221,41 @@ static struct st_mysql_psmlanguage java_
};
/*
+ Plugin status variables for SHOW STATUS
+*/
+
+static struct st_mysql_show_var simple_status[]=
+{
+ {"jvm_version", "", SHOW_CHAR},
+ {0,0,SHOW_UNDEF}
+};
+
+/*
+ Plugin system variables.
+*/
+
+static struct st_mysql_sys_var* system_variables[]= {
+ MYSQL_SYSVAR(context),
+ NULL
+};
+
+/*
Plugin library descriptor
*/
mysql_declare_plugin(ftexample)
{
- MYSQL_PSMLANGUAGE_PLUGIN, /* type */
- &java_udf_descriptor, /* descriptor */
- "Java UDF", /* name */
- "MySQL AB", /* author */
- "Java UDF", /* description */
+ MYSQL_PSMLANGUAGE_PLUGIN, /* type */
+ &java_udf_descriptor, /* descriptor */
+ "Java_UDF", /* name */
+ "MySQL AB", /* author */
+ "Java UDF Demo", /* description */
PLUGIN_LICENSE_GPL,
- java_udf_plugin_init, /* init function (when loaded) */
- java_udf_plugin_deinit, /* deinit function (when unloaded) */
- 0x0001, /* version */
- NULL, /* status variables */
- NULL, /* system variables */
+ java_udf_plugin_init, /* init function (when loaded) */
+ java_udf_plugin_deinit, /* deinit function (when unloaded) */
+ 0x0001, /* version */
+ simple_status, /* status variables */
+ system_variables, /* system variables */
NULL
}
mysql_declare_plugin_end;
--- 1.1/plugin/java_udf/jvm_singleton.cc 2007-06-04 21:41:15 +02:00
+++ 1.2/plugin/java_udf/jvm_singleton.cc 2007-09-21 21:15:20 +02:00
@@ -29,6 +29,15 @@ Jvm *Jvm_singleton::get()
}
+Jvm *Jvm_singleton::check()
+{
+ Jvm *jvm;
+ pthread_mutex_lock(&_jvm_mutex);
+ jvm = _instance;
+ pthread_mutex_unlock(&_jvm_mutex);
+ return jvm;
+}
+
void Jvm_singleton::set(Jvm *new_jvm)
{
pthread_mutex_lock(&_jvm_mutex);
--- 1.1/plugin/java_udf/jvm_singleton.h 2007-06-04 21:41:15 +02:00
+++ 1.2/plugin/java_udf/jvm_singleton.h 2007-09-21 21:15:21 +02:00
@@ -10,6 +10,7 @@ class Jvm_singleton
public:
static Jvm *get();
+ static Jvm *check();
static void set(Jvm *newJvm);
static void set_default_jvm_options(char *vm_options_file);
| Thread |
|---|
| • bk commit into 5.2 tree (eherman:1.2524) | eherman | 21 Sep |