Commit 2323cf00 authored by Olivier Bertrand's avatar Olivier Bertrand

- Make the JVM lib dynamically loaded

  This makes the CONNECT storage engine usable when Java JDK is not installed.
  modified:   storage/connect/ha_connect.cc
  modified:   storage/connect/jdbconn.cpp
  modified:   storage/connect/jdbconn.h

- Typo
  modified:   storage/connect/reldef.cpp
parent 025decfc
...@@ -129,6 +129,7 @@ ...@@ -129,6 +129,7 @@
#endif // ODBC_SUPPORT #endif // ODBC_SUPPORT
#if defined(JDBC_SUPPORT) #if defined(JDBC_SUPPORT)
#include "jdbccat.h" #include "jdbccat.h"
#include "jdbconn.h"
#endif // JDBC_SUPPORT #endif // JDBC_SUPPORT
#include "xtable.h" #include "xtable.h"
#include "tabmysql.h" #include "tabmysql.h"
...@@ -169,7 +170,7 @@ ...@@ -169,7 +170,7 @@
#define JSONMAX 10 // JSON Default max grp size #define JSONMAX 10 // JSON Default max grp size
extern "C" { extern "C" {
char version[]= "Version 1.04.0006 March 12, 2016"; char version[]= "Version 1.04.0006 May 08, 2016";
#if defined(__WIN__) #if defined(__WIN__)
char compver[]= "Version 1.04.0006 " __DATE__ " " __TIME__; char compver[]= "Version 1.04.0006 " __DATE__ " " __TIME__;
char slash= '\\'; char slash= '\\';
...@@ -190,6 +191,10 @@ extern "C" { ...@@ -190,6 +191,10 @@ extern "C" {
} // extern "C" } // extern "C"
#endif // XMSG #endif // XMSG
#if defined(JDBC_SUPPORT)
char *JvmPath;
#endif // JDBC_SUPPORT
#if defined(__WIN__) #if defined(__WIN__)
CRITICAL_SECTION parsec; // Used calling the Flex parser CRITICAL_SECTION parsec; // Used calling the Flex parser
#else // !__WIN__ #else // !__WIN__
...@@ -667,6 +672,9 @@ static int connect_init_func(void *p) ...@@ -667,6 +672,9 @@ static int connect_init_func(void *p)
DTVAL::SetTimeShift(); // Initialize time zone shift once for all DTVAL::SetTimeShift(); // Initialize time zone shift once for all
BINCOL::SetEndian(); // Initialize host endian setting BINCOL::SetEndian(); // Initialize host endian setting
#if defined(JDBC_SUPPORT)
JDBConn::SetJVM();
#endif // JDBC_SUPPORT
DBUG_RETURN(0); DBUG_RETURN(0);
} // end of connect_init_func } // end of connect_init_func
...@@ -685,6 +693,10 @@ static int connect_done_func(void *) ...@@ -685,6 +693,10 @@ static int connect_done_func(void *)
XmlCleanupParserLib(); XmlCleanupParserLib();
#endif // LIBXML2_SUPPORT #endif // LIBXML2_SUPPORT
#ifdef JDBC_SUPPORT
JDBConn::ResetJVM();
#endif // JDBC_SUPPORT
#if defined(__WIN__) #if defined(__WIN__)
DeleteCriticalSection((LPCRITICAL_SECTION)&parsec); DeleteCriticalSection((LPCRITICAL_SECTION)&parsec);
#else // !__WIN__ #else // !__WIN__
...@@ -6835,6 +6847,15 @@ static MYSQL_SYSVAR_STR(errmsg_dir_path, msg_path, ...@@ -6835,6 +6847,15 @@ static MYSQL_SYSVAR_STR(errmsg_dir_path, msg_path,
"../../../../storage/connect/"); // for testing "../../../../storage/connect/"); // for testing
#endif // XMSG #endif // XMSG
#if defined(JDBC_SUPPORT)
static MYSQL_SYSVAR_STR(jvm_path, JvmPath,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
"Path to the directory where is the JVM lib",
// check_jvm_path, update_jvm_path,
NULL, NULL, NULL);
#endif // JDBC_SUPPORT
static struct st_mysql_sys_var* connect_system_variables[]= { static struct st_mysql_sys_var* connect_system_variables[]= {
MYSQL_SYSVAR(xtrace), MYSQL_SYSVAR(xtrace),
MYSQL_SYSVAR(conv_size), MYSQL_SYSVAR(conv_size),
...@@ -6852,6 +6873,7 @@ static struct st_mysql_sys_var* connect_system_variables[]= { ...@@ -6852,6 +6873,7 @@ static struct st_mysql_sys_var* connect_system_variables[]= {
MYSQL_SYSVAR(errmsg_dir_path), MYSQL_SYSVAR(errmsg_dir_path),
#endif // XMSG #endif // XMSG
MYSQL_SYSVAR(json_grp_size), MYSQL_SYSVAR(json_grp_size),
MYSQL_SYSVAR(jvm_path),
NULL NULL
}; };
......
...@@ -17,17 +17,19 @@ ...@@ -17,17 +17,19 @@
#include <direct.h> // for getcwd #include <direct.h> // for getcwd
#if defined(__BORLANDC__) #if defined(__BORLANDC__)
#define __MFC_COMPAT__ // To define min/max as macro #define __MFC_COMPAT__ // To define min/max as macro
#endif #endif // __BORLANDC__
//#include <windows.h> //#include <windows.h>
#else #else // !__WIN__
#if defined(UNIX) #if defined(UNIX)
#include <errno.h> #include <errno.h>
#else #else // !UNIX
//nclude <io.h> //nclude <io.h>
#endif #endif // !UNIX
#include <stdio.h>
#include <stdlib.h> // for getenv
//nclude <fcntl.h> //nclude <fcntl.h>
#define NODW #define NODW
#endif #endif // !__WIN__
/***********************************************************************/ /***********************************************************************/
/* Required objects includes. */ /* Required objects includes. */
...@@ -52,6 +54,14 @@ extern "C" HINSTANCE s_hModule; // Saved module handle ...@@ -52,6 +54,14 @@ extern "C" HINSTANCE s_hModule; // Saved module handle
#endif // !__WIN__ #endif // !__WIN__
int GetConvSize(); int GetConvSize();
extern char *JvmPath; // The connect_jvm_path global variable value
/***********************************************************************/
/* Static JDBConn objects. */
/***********************************************************************/
void *JDBConn::LibJvm = NULL;
CRTJVM JDBConn::CreateJavaVM = NULL;
GETJVM JDBConn::GetCreatedJavaVMs = NULL;
/***********************************************************************/ /***********************************************************************/
/* Some macro's (should be defined elsewhere to be more accessible) */ /* Some macro's (should be defined elsewhere to be more accessible) */
...@@ -618,90 +628,6 @@ PQRYRES JDBCPrimaryKeys(PGLOBAL g, JDBConn *op, char *dsn, char *table) ...@@ -618,90 +628,6 @@ PQRYRES JDBCPrimaryKeys(PGLOBAL g, JDBConn *op, char *dsn, char *table)
/************************************************************************/ /************************************************************************/
return qrp; return qrp;
} // end of JDBCPrimaryKeys } // end of JDBCPrimaryKeys
/**************************************************************************/
/* Statistics: constructs the result blocks containing statistics */
/* about one or several tables to be retrieved by GetData commands. */
/**************************************************************************/
PQRYRES JDBCStatistics(PGLOBAL g, JDBConn *op, char *dsn, char *pat,
int un, int acc)
{
static int buftyp[] ={ TYPE_STRING,
TYPE_STRING, TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_STRING,
TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_STRING };
static unsigned int length[] ={ 0, 0, 0, 6, 0, 0, 6, 6, 0, 2, 10, 10, 128 };
int n, ncol = 13;
int maxres;
PQRYRES qrp;
JCATPARM *cap;
JDBConn *jcp = op;
if (!op) {
/**********************************************************************/
/* Open the connection with the JDBC data source. */
/**********************************************************************/
jcp = new(g)JDBConn(g, NULL);
if (jcp->Open(dsn, 2) < 1) // 2 is openReadOnly
return NULL;
} // endif op
/************************************************************************/
/* Do an evaluation of the result size. */
/************************************************************************/
n = 1 + jcp->GetMaxValue(SQL_MAX_COLUMNS_IN_INDEX);
maxres = (n) ? (int)n : 32;
n = jcp->GetMaxValue(SQL_MAX_SCHEMA_NAME_LEN);
length[1] = (n) ? (n + 1) : 128;
n = jcp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
length[2] = length[5] = (n) ? (n + 1) : 128;
n = jcp->GetMaxValue(SQL_MAX_CATALOG_NAME_LEN);
length[0] = length[4] = (n) ? (n + 1) : length[2];
n = jcp->GetMaxValue(SQL_MAX_COLUMN_NAME_LEN);
length[7] = (n) ? (n + 1) : 128;
if (trace)
htrc("SemStatistics: max=%d pat=%s\n", maxres, SVP(pat));
/************************************************************************/
/* Allocate the structure used to refer to the result set. */
/************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_STAT,
buftyp, NULL, length, false, true);
if (trace)
htrc("Getting stat results ncol=%d\n", qrp->Nbcol);
cap = AllocCatInfo(g, CAT_STAT, NULL, pat, qrp);
cap->Unique = (un < 0) ? SQL_INDEX_UNIQUE : (UWORD)un;
cap->Accuracy = (acc < 0) ? SQL_QUICK : (UWORD)acc;
/************************************************************************/
/* Now get the results into blocks. */
/************************************************************************/
if ((n = jcp->GetCatInfo(cap)) >= 0) {
qrp->Nblin = n;
// ResetNullValues(cap);
if (trace)
htrc("Statistics: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin);
} else
qrp = NULL;
/************************************************************************/
/* Close any local connection. */
/************************************************************************/
if (!op)
jcp->Close();
/************************************************************************/
/* Return the result pointer for use by GetData routines. */
/************************************************************************/
return qrp;
} // end of Statistics
#endif // 0 #endif // 0
/***********************************************************************/ /***********************************************************************/
...@@ -842,13 +768,98 @@ int JDBConn::GetMaxValue(int n) ...@@ -842,13 +768,98 @@ int JDBConn::GetMaxValue(int n)
return (int)env->CallIntMethod(job, maxid, n); return (int)env->CallIntMethod(job, maxid, n);
} // end of GetMaxValue } // end of GetMaxValue
/***********************************************************************/
/* Reset the JVM library. */
/***********************************************************************/
void JDBConn::ResetJVM(void)
{
if (!LibJvm) {
#if defined(__WIN__)
FreeLibrary((HMODULE)LibJvm);
#else // !__WIN__
dlclose(LibJvm);
#endif // !__WIN__
LibJvm = NULL;
CreateJavaVM = NULL;
GetCreatedJavaVMs = NULL;
} // endif LibJvm
} // end of ResetJVM
/***********************************************************************/
/* Dynamically link the JVM library. */
/* The purpose of this function is to allow using the CONNECT plugin */
/* for other table types when the Java JDK is not installed. */
/***********************************************************************/
bool JDBConn::GetJVM(PGLOBAL g)
{
if (!LibJvm) {
char soname[512];
if (JvmPath)
strcat(strcpy(soname, JvmPath), "\\jvm.dll");
else
strcpy(soname, "jvm.dll");
#if defined(__WIN__)
// Load the desired shared library
if (!(LibJvm = LoadLibrary(soname))) {
char buf[256];
DWORD rc = GetLastError();
sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
(LPTSTR)buf, sizeof(buf), NULL);
strcat(strcat(g->Message, ": "), buf);
} else if (!(CreateJavaVM = (CRTJVM)GetProcAddress((HINSTANCE)LibJvm,
"JNI_CreateJavaVM"))) {
sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), "JNI_CreateJavaVM");
FreeLibrary((HMODULE)LibJvm);
LibJvm = NULL;
} else if (!(GetCreatedJavaVMs = (GETJVM)GetProcAddress((HINSTANCE)LibJvm,
"JNI_GetCreatedJavaVMs"))) {
sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), "JNI_GetCreatedJavaVMs");
FreeLibrary((HMODULE)LibJvm);
LibJvm = NULL;
} // endif LibJvm
#else // !__WIN__
const char *error = NULL;
// Load the desired shared library
if (!(LibJvm = dlopen(soname, RTLD_LAZY))) {
error = dlerror();
sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
} else if (!(CreateJavaVM = (CRTJVM)dlsym(LibJvm, "JNI_CreateJavaVM"))) {
error = dlerror();
sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_CreateJavaVM", SVP(error));
dlclose(LibJvm);
LibJvm = NULL;
} else if (!(GetCreatedJavaVMs = (CRTJVM)dlsym(LibJvm, "JNI_GetCreatedJavaVMs"))) {
error = dlerror();
sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_GetCreatedJavaVMs", SVP(error));
dlclose(LibJvm);
LibJvm = NULL;
} // endif LibJvm
#endif // !__WIN__
} // endif LibJvm
return LibJvm == NULL;
} // end of GetJVM
/***********************************************************************/ /***********************************************************************/
/* Open: connect to a data source. */ /* Open: connect to a data source. */
/***********************************************************************/ /***********************************************************************/
int JDBConn::Open(PSZ jpath, PJPARM sop) int JDBConn::Open(PSZ jpath, PJPARM sop)
{ {
PGLOBAL& g = m_G; PGLOBAL& g = m_G;
if (GetJVM(g))
return true;
PSTRG jpop = new(g) STRING(g, 512, "-Djava.class.path="); PSTRG jpop = new(g) STRING(g, 512, "-Djava.class.path=");
char *cp = NULL;
char sep; char sep;
#if defined(__WIN__) #if defined(__WIN__)
...@@ -874,13 +885,24 @@ int JDBConn::Open(PSZ jpath, PJPARM sop) ...@@ -874,13 +885,24 @@ int JDBConn::Open(PSZ jpath, PJPARM sop)
JavaVMOption* options = new JavaVMOption[1]; // JVM invocation options JavaVMOption* options = new JavaVMOption[1]; // JVM invocation options
// where to find java .class // where to find java .class
jpop->Append(getenv("CLASSPATH")); if ((cp = PlugDup(m_G, getenv("CLASSPATH"))))
jpop->Append(cp);
if (trace) {
htrc("CLASSPATH=%s\n", cp);
htrc("jpath=%s\n", jpath);
} // endif trace
if (jpath) { if (jpath && *jpath) {
if (cp)
jpop->Append(sep); jpop->Append(sep);
jpop->Append(jpath); jpop->Append(jpath);
} // endif jpath } // endif jpath
if (trace)
htrc("%s\n", jpop->GetStr());
options[0].optionString = jpop->GetStr(); options[0].optionString = jpop->GetStr();
//options[1].optionString = "-verbose:jni"; //options[1].optionString = "-verbose:jni";
vm_args.version = JNI_VERSION_1_6; // minimum Java version vm_args.version = JNI_VERSION_1_6; // minimum Java version
...@@ -889,7 +911,7 @@ int JDBConn::Open(PSZ jpath, PJPARM sop) ...@@ -889,7 +911,7 @@ int JDBConn::Open(PSZ jpath, PJPARM sop)
vm_args.ignoreUnrecognized = false; // invalid options make the JVM init fail vm_args.ignoreUnrecognized = false; // invalid options make the JVM init fail
//=============== load and initialize Java VM and JNI interface ============= //=============== load and initialize Java VM and JNI interface =============
jint rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); // YES !! jint rc = CreateJavaVM(&jvm, (void**)&env, &vm_args); // YES !!
delete options; // we then no longer need the initialisation options. delete options; // we then no longer need the initialisation options.
switch (rc) { switch (rc) {
...@@ -914,7 +936,7 @@ int JDBConn::Open(PSZ jpath, PJPARM sop) ...@@ -914,7 +936,7 @@ int JDBConn::Open(PSZ jpath, PJPARM sop)
JavaVM* jvms[1]; JavaVM* jvms[1];
jsize jsz; jsize jsz;
rc = JNI_GetCreatedJavaVMs(jvms, 1, &jsz); rc = GetCreatedJavaVMs(jvms, 1, &jsz);
if (rc == JNI_OK && jsz == 1) { if (rc == JNI_OK && jsz == 1) {
jvm = jvms[0]; jvm = jvms[0];
...@@ -1952,6 +1974,9 @@ bool JDBConn::SetParam(JDBCCOL *colp) ...@@ -1952,6 +1974,9 @@ bool JDBConn::SetParam(JDBCCOL *colp)
// Not used anymore // Not used anymore
env->DeleteLocalRef(parms); env->DeleteLocalRef(parms);
if (trace)
htrc("Method %s returned %d columns\n", fnc, ncol);
// n because we no more ignore the first column // n because we no more ignore the first column
if ((n = qrp->Nbcol) > (uint)ncol) { if ((n = qrp->Nbcol) > (uint)ncol) {
strcpy(g->Message, MSG(COL_NUM_MISM)); strcpy(g->Message, MSG(COL_NUM_MISM));
...@@ -1989,9 +2014,12 @@ bool JDBConn::SetParam(JDBCCOL *colp) ...@@ -1989,9 +2014,12 @@ bool JDBConn::SetParam(JDBCCOL *colp)
// Now fetch the result // Now fetch the result
for (i = 0; i < qrp->Maxres; i++) { for (i = 0; i < qrp->Maxres; i++) {
if ((rc = Fetch(0)) == 0) if ((rc = Fetch(0)) == 0) {
if (trace)
htrc("End of fetches i=%d\n", i);
break; break;
else if (rc < 0) } else if (rc < 0)
return -1; return -1;
for (n = 0, crp = qrp->Colresp; crp; n++, crp = crp->Next) { for (n = 0, crp = qrp->Colresp; crp; n++, crp = crp->Next) {
......
...@@ -60,6 +60,9 @@ typedef struct tagJCATPARM { ...@@ -60,6 +60,9 @@ typedef struct tagJCATPARM {
PUCHAR Pat; // Table type or column pattern PUCHAR Pat; // Table type or column pattern
} JCATPARM; } JCATPARM;
typedef jint(JNICALL *CRTJVM) (JavaVM **, void **, void *);
typedef jint(JNICALL *GETJVM) (JavaVM **, jsize, jsize *);
// JDBC connection to a data source // JDBC connection to a data source
class TDBJDBC; class TDBJDBC;
class JDBCCOL; class JDBCCOL;
...@@ -114,8 +117,11 @@ class JDBConn : public BLOCK { ...@@ -114,8 +117,11 @@ class JDBConn : public BLOCK {
PQRYRES GetMetaData(PGLOBAL g, char *src); PQRYRES GetMetaData(PGLOBAL g, char *src);
public: public:
// Set special options // Set static variables
//void OnSetOptions(HSTMT hstmt); static void SetJVM(void)
{ LibJvm = NULL; CreateJavaVM = NULL; GetCreatedJavaVMs = NULL; }
static void ResetJVM(void);
static bool GetJVM(PGLOBAL g);
// Implementation // Implementation
public: public:
...@@ -126,15 +132,17 @@ class JDBConn : public BLOCK { ...@@ -126,15 +132,17 @@ class JDBConn : public BLOCK {
char *Check(void); char *Check(void);
//void ThrowDJX(int rc, PSZ msg/*, HSTMT hstmt = SQL_NULL_HSTMT*/); //void ThrowDJX(int rc, PSZ msg/*, HSTMT hstmt = SQL_NULL_HSTMT*/);
//void ThrowDJX(PSZ msg); //void ThrowDJX(PSZ msg);
//void AllocConnect(DWORD dwOptions);
//void Connect(void);
//bool DriverConnect(DWORD Options);
//void VerifyConnect(void);
//void GetConnectInfo(void);
//void Free(void); //void Free(void);
protected: protected:
// Members // Members
#if defined(__WIN__)
static HANDLE LibJvm; // Handle to the jvm DLL
#else // !__WIN__
static void *LibJvm; // Handle for the jvm shared library
#endif // !__WIN__
static CRTJVM CreateJavaVM;
static GETJVM GetCreatedJavaVMs;
PGLOBAL m_G; PGLOBAL m_G;
TDBJDBC *m_Tdb; TDBJDBC *m_Tdb;
JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine) JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine)
......
...@@ -514,9 +514,10 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) ...@@ -514,9 +514,10 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
} // endif getdef } // endif getdef
#else // !__WIN__ #else // !__WIN__
const char *error = NULL; const char *error = NULL;
Dl_info dl_info;
#if 0 // Don't know what all this stuff does #if 0 // Don't know what all this stuff does
Dl_info dl_info;
// The OEM lib must retrieve exported CONNECT variables // The OEM lib must retrieve exported CONNECT variables
if (dladdr(&connect_hton, &dl_info)) { if (dladdr(&connect_hton, &dl_info)) {
if (dlopen(dl_info.dli_fname, RTLD_NOLOAD | RTLD_NOW | RTLD_GLOBAL) == 0) { if (dlopen(dl_info.dli_fname, RTLD_NOLOAD | RTLD_NOW | RTLD_GLOBAL) == 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment