List:Commits« Previous MessageNext Message »
From:Martin Zaun Date:July 2 2011 10:09am
Subject:bzr commit into mysql-5.1-telco-7.1 branch (martin.zaun:4277)
View as plain text  
#At file:///Users/mz/mysql/ndb-7.1-jtie/ based on revid:maitrayi.sabaratnam@stripped

 4277 Martin Zaun	2011-07-02
      ndbjtie - fixed class reference assumptions in MemberIdCache, added code doc, some clean up.

    modified:
      storage/ndb/src/ndbjtie/jtie/jtie_tconv_idcache_impl.hpp
      storage/ndb/src/ndbjtie/jtie/jtie_tconv_object.hpp
      storage/ndb/src/ndbjtie/jtie/jtie_tconv_object_impl.hpp
      storage/ndb/src/ndbjtie/jtie/jtie_tconv_ptrbybb_impl.hpp
=== modified file 'storage/ndb/src/ndbjtie/jtie/jtie_tconv_idcache_impl.hpp'
--- a/storage/ndb/src/ndbjtie/jtie/jtie_tconv_idcache_impl.hpp	2011-02-02 09:52:33 +0000
+++ b/storage/ndb/src/ndbjtie/jtie/jtie_tconv_idcache_impl.hpp	2011-07-02 10:09:08 +0000
@@ -54,7 +54,7 @@
 
 // ---------------------------------------------------------------------------
 
-// JNI helper functions
+// Local JNI helper functions
 
 template< typename T >
 inline T
@@ -108,30 +108,120 @@ jniGetMemberID< jfieldID >(JNIEnv * env,
 /**
  * Instantiates an info type describing a member of a Java class.
  */
-#define JTIE_INSTANTIATE_CLASS_MEMBER_INFO( T, CN, MN, MD )     \
-    const char * const T::class_name = CN;                      \
-    const char * const T::member_name = MN;                     \
-    const char * const T::member_descriptor = MD;               \
-    template struct MemberId< T >;                              \
+#define JTIE_INSTANTIATE_CLASS_MEMBER_INFO( T, CN, MN, MD )             \
+    const char * const T::class_name = CN;                              \
+    const char * const T::member_name = MN;                             \
+    const char * const T::member_descriptor = MD;                       \
+    template struct MemberId< T >;                                      \
     template struct MemberIdCache< T >;
 
-// XXX document these classes...
-
+/**
+ * Provides uniform access to the JNI Field/Method ID of a Java class member
+ * as described by the member info type 'C'.
+ *
+ * This base class does not cache the member ID and the class object, but
+ * it retrieves the member ID from JNI upon each access; different caching
+ * strategies are provided by derived classes.
+ *
+ * This class (and its derived classes) impose a strict usage pattern.
+ * For example, given definitions...
+ *
+ *    // Defines the field info type for MyClass.myField.
+ *    JTIE_DEFINE_FIELD_MEMBER_INFO(_MyClass_myField)
+ *
+ *    // Provides a (cached) access to field Id of MyClass.myField.
+ *    typedef JniMemberId< _MyClass_myField > MyClass_myField;
+ *
+ * any use of a member ID must be bracketed by getClass() and releaseRef():
+ *
+ *    // obtain a class reference
+ *    jclass cls = MyClass_myField::getClass(env);
+ *    if (cls == NULL) {
+ *        // exception pending
+ *    } else {
+ *        // get the field ID valid along with the class reference
+ *        jfieldID fid = MyClass_myField::getId(env, cls);
+ *        if (fid == NULL) {
+ *            // exception pending
+ *        } else {
+ *            // OK to access field using 'fid'
+ *        }
+ *        // allow for releasing the class reference
+ *        MyClass_myField::releaseRef(env, cls);
+ *    }
+ *
+ * Derived classes implement any caching underneath this usage pattern.
+ */
 template< typename C >
 struct MemberId {
     typedef typename C::memberID_t ID_t;
-    
-    // number of JNI Get<Field|Method>ID() invocations
+
+    // number of JNI Get<Field|Method>ID() invocations for statistics
     static unsigned long nIdLookUps;
 
+    /**
+     * Allows for storing a (global) class reference.
+     *
+     * Usually only called from getClass(), but enables "cache preloading"
+     * from a (native, static) function called at class initialization.
+     *
+     * Pre condition:
+     * - this thread has no pending JNI exception (!env->ExceptionCheck())
+     * - a valid local or global class reference: assert(cls != NULL)
+     */
     static void setClass(JNIEnv * env, jclass cls) {
+        assert(cls != NULL);
         (void)env; (void)cls;
     }
 
+    /**
+     * Returns a JNI Reference to the class declaring the member specified
+     * by info type 'C'.
+     *
+     * Depending upon the underlying caching strategy, a returned reference
+     * may be local or global, weak or strong; the scope of its use must be
+     * demarcated by releaseRef().
+     *
+     * Pre condition:
+     * - this thread has no pending JNI exception (!env->ExceptionCheck())
+     *
+     * Post condition:
+     * - return value is
+     *   NULL:
+     *     - this thread has a pending JNI exception (env->ExceptionCheck())
+     *   otherwise:
+     *     - this thread has no pending JNI exception (!env->ExceptionCheck())
+     *     - the returned reference is valid (at least) until releaseRef()
+     */
     static jclass getClass(JNIEnv * env) {
-        return env->FindClass(C::class_name);
+        assert(env->ExceptionCheck() == JNI_OK);
+        jclass cls = env->FindClass(C::class_name);
+        if (cls == NULL) { // break out for better diagnostics
+            assert(env->ExceptionCheck() != JNI_OK); // exception pending
+        } else {
+            assert(env->ExceptionCheck() == JNI_OK); // ok
+        }
+        return cls;
     }
 
+    /**
+     * Returns the JNI Field/Method ID of a Java class member.
+     *
+     * The member ID is only valid along with a class object obtained by
+     * getClass() and before releaseRef().
+     *
+     * Pre condition:
+     * - this thread has no pending JNI exception (!env->ExceptionCheck())
+     * - a valid class reference obtained by getClass(): assert(cls != NULL)
+     *
+     * Post condition:
+     * - return value is
+     *   NULL:
+     *     - this thread has a pending JNI exception (env->ExceptionCheck())
+     *   otherwise:
+     *     - this thread has no pending JNI exception (!env->ExceptionCheck())
+     *     - the returned member ID is valid (at least) until releaseRef()
+     */
     static ID_t getId(JNIEnv * env, jclass cls) {
         assert(cls != NULL);
         // multithreaded access ok, inaccurate if non-atomic increment
@@ -139,71 +229,104 @@ struct MemberId {
         return jniGetMemberID< ID_t >(env, cls,
                                       C::member_name, C::member_descriptor);
     }
-    
+
+    /**
+     * Allows for a class reference to be released along with any member IDs.
+     *
+     * Pre condition:
+     * - a valid class reference obtained by getClass(): assert(cls != NULL)
+     * - this thread may have a pending JNI exception (env->ExceptionCheck())
+     */
     static void releaseRef(JNIEnv * env, jclass cls) {
+        assert(cls != NULL);
         env->DeleteLocalRef(cls);
     }
 };
 
+/**
+ * Base class for caching of JNI Field/Method IDs.
+ */
 template< typename C >
 struct MemberIdCache : MemberId< C > {
     typedef typename C::memberID_t ID_t;
 
     static ID_t getId(JNIEnv * env, jclass cls) {
-        assert (cls != NULL);
+        assert(cls != NULL);
+        // the cached member id is only valid along with global class ref
+        assert(env->IsSameObject(gClassRef, NULL) == JNI_FALSE);
         (void)env; (void)cls;
         return mid;
     }
 
 protected:
+    // the cached global (weak or strong) class ref
     static jclass gClassRef;
+
+    // the cached member id (only valid along with global class ref)
     static ID_t mid;
 };
 
+/**
+ * Provides caching of JNI Field/Method IDs using weak class references,
+ * allowing classes to be unloaded when no longer used by Java code.
+ */
 template< typename C >
 struct MemberIdWeakCache : MemberIdCache< C > {
     typedef MemberId< C > A;
     typedef MemberIdCache< C > Base;
 
     static void setClass(JNIEnv * env, jclass cls) {
-        assert (cls != NULL);
+        assert(cls != NULL);
 
         // multithreaded access ok, sets same class/member object
-        Base::gClassRef = static_cast<jclass>(env->NewWeakGlobalRef(cls));
+        Base::gClassRef = static_cast< jclass >(env->NewWeakGlobalRef(cls));
         Base::mid = A::getId(env, cls);
     }
 
-    using Base::getId;
-    
+    using Base::getId; // use as inherited (some compiler wanted this)
+
     static jclass getClass(JNIEnv * env) {
-        jclass cls = static_cast<jclass>(env->NewLocalRef(Base::gClassRef));
+        // a weak global class ref may refer to a freed object at any time
+        //   (i.e.: env->IsSameObject(Base::gClassRef, NULL))
+        // unless we've obtained a strong (local or global) non-NULL class ref
+        jclass cls = static_cast< jclass >(env->NewLocalRef(Base::gClassRef));
         if (cls == NULL) {
+            // global class ref was NULL or referencing a freed object
             cls = A::getClass(env);
-            setClass(env, cls);
+            if (cls == NULL) {
+                // exception pending
+            } else {
+                setClass(env, cls);
+            }
         }
         return cls;
     }
-    
+
     static void releaseRef(JNIEnv * env, jclass cls) {
+        assert(cls != NULL);
         env->DeleteLocalRef(cls);
     }
 };
 
+/**
+ * Provides caching of JNI Field/Method IDs using strong class references,
+ * preventing classes from being unloaded even if no longer used by Java code.
+ */
 template< typename C >
 struct MemberIdStrongCache : MemberIdCache< C > {
     typedef MemberId< C > A;
     typedef MemberIdCache< C > Base;
-    
+
     static void setClass(JNIEnv * env, jclass cls) {
-        assert (cls != NULL);
+        assert(cls != NULL);
 
         // multithreaded access ok, sets same class/member object
-        Base::gClassRef = static_cast<jclass>(env->NewGlobalRef(cls));
+        Base::gClassRef = static_cast< jclass >(env->NewGlobalRef(cls));
         Base::mid = A::getId(env, cls);
     }
 
-    using Base::getId;
-    
+    using Base::getId; // use as inherited (some compiler wanted this)
+
     static jclass getClass(JNIEnv * env) {
         jclass cls = Base::gClassRef;
         if (cls == NULL) {
@@ -212,48 +335,61 @@ struct MemberIdStrongCache : MemberIdCac
         }
         return cls;
     }
-    
+
     static void releaseRef(JNIEnv * env, jclass cls) {
+        assert(cls != NULL);
+        (void)env; (void)cls;
     }
 };
 
+/**
+ * Provides caching of JNI Field/Method IDs using weak class references
+ * with preloading (at class initialization) -- VERY TRICKY, NOT SUPPORTED.
+ */
 template< typename C >
 struct MemberIdPreloadedWeakCache : MemberIdWeakCache< C > {
     typedef MemberIdWeakCache< C > Base;
-    
-    using Base::setClass;
 
-    using Base::getId;
-    
+    using Base::setClass; // use as inherited (some compiler wanted this)
+
+    using Base::getId; // use as inherited (some compiler wanted this)
+
     static jclass getClass(JNIEnv * env) {
+        // weak global class ref is assumed to be preloaded and valid
         jclass cls = Base::gClassRef;
-        assert (cls != NULL);
+        assert(env->IsSameObject(cls, NULL) == JNI_FALSE);
         return cls;
     }
-    
+
     static void releaseRef(JNIEnv * env, jclass cls) {
+        assert(cls != NULL);
+        (void)env; (void)cls;
     }
 };
 
+/**
+ * Provides caching of JNI Field/Method IDs using strong class references
+ * with preloading (at class initialization) -- VERY TRICKY, NOT SUPPORTED.
+ */
 template< typename C >
 struct MemberIdPreloadedStrongCache : MemberIdStrongCache< C > {
     typedef MemberIdStrongCache< C > Base;
-    
-    using Base::setClass;
 
-    using Base::getId;
-    
+    using Base::setClass; // use as inherited (some compiler wanted this)
+
+    using Base::getId; // use as inherited (some compiler wanted this)
+
     static jclass getClass(JNIEnv * env) {
+        // strong global class ref is assumed to be preloaded and valid
         jclass cls = Base::gClassRef;
-        assert (cls != NULL);
+        assert(env->IsSameObject(cls, NULL) == JNI_FALSE);
         return cls;
-    }    
+    }
 
-    using Base::releaseRef;
+    using Base::releaseRef; // use as inherited (some compiler wanted this)
 };
 
-// XXX test with multiple compilation units <-> jtie_lib.hpp
-
+// XXX static initialization <-> multiple compilation units <-> jtie_lib.hpp
 template< typename C > unsigned long MemberId< C >
     ::nIdLookUps = 0;
 
@@ -265,14 +401,22 @@ template< typename C > typename C::membe
 
 // XXX document
 
+/**
+ * The supported caching strategies for member IDs and class references.
+ */
 enum JniMemberIdCaching {
-    NO_CACHING,
-    WEAK_CACHING,
-    STRONG_CACHING,
-    WEAK_CACHING_PRELOAD,
-    STRONG_CACHING_PRELOAD
+    NO_CACHING
+    ,WEAK_CACHING
+    ,STRONG_CACHING
+#if 0 // preloaded caching very tricky, not supported at this time
+    ,WEAK_CACHING_PRELOAD
+    ,STRONG_CACHING_PRELOAD
+#endif // preloaded caching very tricky, not supported at this time
 };
 
+/**
+ * Generic class for member ID access with selection of caching strategy.
+ */
 template< JniMemberIdCaching M, typename C >
 struct JniMemberId;
 
@@ -288,6 +432,7 @@ template< typename C >
 struct JniMemberId< STRONG_CACHING, C >
     : MemberIdStrongCache< C > {};
 
+#if 0 // preloaded caching very tricky, not supported at this time
 template< typename C >
 struct JniMemberId< WEAK_CACHING_PRELOAD, C >
     : MemberIdPreloadedWeakCache< C > {};
@@ -295,6 +440,7 @@ struct JniMemberId< WEAK_CACHING_PRELOAD
 template< typename C >
 struct JniMemberId< STRONG_CACHING_PRELOAD, C >
     : MemberIdPreloadedStrongCache< C > {};
+#endif // preloaded caching very tricky, not supported at this time
 
 // ---------------------------------------------------------------------------
 

=== modified file 'storage/ndb/src/ndbjtie/jtie/jtie_tconv_object.hpp'
--- a/storage/ndb/src/ndbjtie/jtie/jtie_tconv_object.hpp	2011-02-02 09:52:33 +0000
+++ b/storage/ndb/src/ndbjtie/jtie/jtie_tconv_object.hpp	2011-07-02 10:09:08 +0000
@@ -44,6 +44,13 @@ struct _jtie_Object : _jobject {
 // XXX, document: type specifying an Object mapping with a class name
 
 // trait type wrapping named-parametrized Object mappings for specialization
+// XXX make use of
+//   JTIE_DEFINE_METHOD_MEMBER_INFO( _jtie_ObjectMapper< T > )
+// to replace
+//   static const char * const class_name;
+//   static const char * const member_name;
+//   static const char * const member_descriptor;
+//   typedef _jmethodID * memberID_t;
 template< typename J >
 struct _jtie_ObjectMapper : _jtie_Object {
     // the name of the Java peer class in the JVM format (i.e., '/'-separated)
@@ -55,11 +62,10 @@ struct _jtie_ObjectMapper : _jtie_Object
     typedef _jmethodID * memberID_t;
 };
 
-// XXX can/should these definitions be moves to _lib ?
-
+// XXX static initialization <-> multiple compilation units <-> jtie_lib.hpp
 template< typename J >
 const char * const _jtie_ObjectMapper< J >::class_name
-    = J::class_name;
+    = J::class_name; // XXX static initialization order dependency?
 
 template< typename J >
 const char * const _jtie_ObjectMapper< J >::member_name
@@ -214,6 +220,13 @@ const char * const _jtie_ObjectMapper< J
 #endif // XXX cleanup this unsupported mapping
 
 // XXX to document
+// XXX static initialization <-> multiple compilation units <-> jtie_lib.hpp
+// XXX replace
+//   template struct MemberId< _jtie_ObjectMapper< T > >;
+//   template struct MemberIdCache< _jtie_ObjectMapper< T > >;
+// with
+//   JTIE_INSTANTIATE_CLASS_MEMBER_INFO_X(_jtie_ObjectMapper< T >,
+//                                        JCN, "<init>", "()V")
 #define JTIE_INSTANTIATE_PEER_CLASS_MAPPING( T, JCN )           \
     const char * const T::class_name = JCN;                     \
     template struct _jtie_ObjectMapper< T >;                    \

=== modified file 'storage/ndb/src/ndbjtie/jtie/jtie_tconv_object_impl.hpp'
--- a/storage/ndb/src/ndbjtie/jtie/jtie_tconv_object_impl.hpp	2011-02-02 09:52:33 +0000
+++ b/storage/ndb/src/ndbjtie/jtie/jtie_tconv_object_impl.hpp	2011-07-02 10:09:08 +0000
@@ -40,14 +40,10 @@
 // Defines the field info type for Wrapper.cdelegate.
 JTIE_DEFINE_FIELD_MEMBER_INFO(_Wrapper_cdelegate)
 
-// XXX fix and test _PRELOAD caching
-
-// Provides a (cached) access to field Id  of Wrapper.cdelegate.
+// Provides a (cached) access to field Id of Wrapper.cdelegate.
 //typedef JniMemberId< NO_CACHING, _Wrapper_cdelegate > Wrapper_cdelegate;
 typedef JniMemberId< WEAK_CACHING, _Wrapper_cdelegate > Wrapper_cdelegate;
 //typedef JniMemberId< STRONG_CACHING, _Wrapper_cdelegate > Wrapper_cdelegate;
-//typedef JniMemberId< WEAK_CACHING_PRELOAD, _Wrapper_cdelegate > Wrapper_cdelegate;
-//typedef JniMemberId< STRONG_CACHING_PRELOAD, _Wrapper_cdelegate > Wrapper_cdelegate;
 
 // XXX consider changing
 //template< typename C > struct ObjectParam< _jtie_Object *, C * > {

=== modified file 'storage/ndb/src/ndbjtie/jtie/jtie_tconv_ptrbybb_impl.hpp'
--- a/storage/ndb/src/ndbjtie/jtie/jtie_tconv_ptrbybb_impl.hpp	2011-02-02 09:52:33 +0000
+++ b/storage/ndb/src/ndbjtie/jtie/jtie_tconv_ptrbybb_impl.hpp	2011-07-02 10:09:08 +0000
@@ -132,7 +132,7 @@ struct ByteBufferPtrParam {
                     } else {
                         // ok
                         s = 0;
-                        c = static_cast<C *>(a);
+                        c = static_cast< C * >(a);
                     }
                 }
             }
@@ -333,7 +333,7 @@ getBufferPosition(jtie_j_n_ByteBuffer jb
 inline void *
 getByteBufferAddress(jtie_j_n_ByteBuffer jbb, JNIEnv * env) {
     // get the internal buffer address of direct ByteBuffer
-    char * a = static_cast<char *>(env->GetDirectBufferAddress(jbb));
+    char * a = static_cast< char * >(env->GetDirectBufferAddress(jbb));
     if (a == NULL) {
 #ifndef JTIE_BYTEBUFFER_NO_ZERO_CAPACITY_MAPPING
         // check for direct ByteBuffer of zero-capacity


Attachment: [text/bzr-bundle] bzr/martin.zaun@oracle.com-20110702100908-j66g79miigd89o8f.bundle
Thread
bzr commit into mysql-5.1-telco-7.1 branch (martin.zaun:4277) Martin Zaun4 Jul