]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Remove a superfluous level of indirection in the JNI internals.
authorstephan <stephan@noemail.net>
Sat, 2 Sep 2023 10:18:10 +0000 (10:18 +0000)
committerstephan <stephan@noemail.net>
Sat, 2 Sep 2023 10:18:10 +0000 (10:18 +0000)
FossilOrigin-Name: 8dca6f7660c15eacbda20da1c66c9ef1de36864f78750658226b1a7baf22b726

ext/jni/src/c/sqlite3-jni.c
ext/jni/src/org/sqlite/jni/Tester1.java
manifest
manifest.uuid

index d54cc1ca9c19df70dc56b76f468ecd3bb6526926..a9e1552cf8bb3ca27cb4dd0a90c9eaf712d610f5 100644 (file)
@@ -294,43 +294,66 @@ static inline void s3jni_unref_local(JNIEnv * const env, jobject const v){
 #define S3JniUnrefLocal(VAR) s3jni_unref_local(env, (VAR))
 
 /*
-** Lookup key type for use with s3jni_nph().
+** Lookup key type for use with s3jni_nphop() and a cache of a
+** frequently-needed Java-side class reference and one or two Java
+** class member IDs.
 */
-typedef struct S3JniNphRef S3JniNphRef;
-struct S3JniNphRef {
+typedef struct S3JniNphOp S3JniNphOp;
+struct S3JniNphOp {
   const int index             /* index into S3JniGlobal.nph[] */;
   const char * const zName    /* Full Java name of the class */;
   const char * const zMember  /* Name of member property */;
   const char * const zTypeSig /* JNI type signature of zMember */;
+  /*
+  ** klazz is a global ref to the class represented by pRef.
+  **
+  ** According to:
+  **
+  **   https://developer.ibm.com/articles/j-jni/
+  **
+  ** > ... the IDs returned for a given class don't change for the
+  **   lifetime of the JVM process. But the call to get the field or
+  **   method can require significant work in the JVM, because fields
+  **   and methods might have been inherited from superclasses, making
+  **   the JVM walk up the class hierarchy to find them. Because the
+  **   IDs are the same for a given class, you should look them up
+  **   once and then reuse them. Similarly, looking up class objects
+  **   can be expensive, so they should be cached as well.
+  */
+  jclass klazz;
+  volatile jfieldID fidValue  /* NativePointerHolder.nativePointer or
+                              ** OutputPointer.T.value */;
+  volatile jmethodID midCtor  /* klazz's no-arg constructor. Used by
+                              ** NativePointerHolder_new(). */;
 };
 
 /*
 ** Cache keys for each concrete NativePointerHolder subclasses and
-** OutputPointer.T types. The members are to be used with s3jni_nph()
+** OutputPointer.T types. The members are to be used with s3jni_nphop()
 ** and friends, and each one's member->index corresponds to its index
 ** in the S3JniGlobal.nph[] array.
 */
 static const struct {
-  const S3JniNphRef sqlite3;
-  const S3JniNphRef sqlite3_stmt;
-  const S3JniNphRef sqlite3_context;
-  const S3JniNphRef sqlite3_value;
-  const S3JniNphRef OutputPointer_Bool;
-  const S3JniNphRef OutputPointer_Int32;
-  const S3JniNphRef OutputPointer_Int64;
-  const S3JniNphRef OutputPointer_sqlite3;
-  const S3JniNphRef OutputPointer_sqlite3_stmt;
-  const S3JniNphRef OutputPointer_sqlite3_value;
-  const S3JniNphRef OutputPointer_String;
+  const S3JniNphOp sqlite3;
+  const S3JniNphOp sqlite3_stmt;
+  const S3JniNphOp sqlite3_context;
+  const S3JniNphOp sqlite3_value;
+  const S3JniNphOp OutputPointer_Bool;
+  const S3JniNphOp OutputPointer_Int32;
+  const S3JniNphOp OutputPointer_Int64;
+  const S3JniNphOp OutputPointer_sqlite3;
+  const S3JniNphOp OutputPointer_sqlite3_stmt;
+  const S3JniNphOp OutputPointer_sqlite3_value;
+  const S3JniNphOp OutputPointer_String;
 #ifdef SQLITE_ENABLE_FTS5
-  const S3JniNphRef OutputPointer_ByteArray;
-  const S3JniNphRef Fts5Context;
-  const S3JniNphRef Fts5ExtensionApi;
-  const S3JniNphRef fts5_api;
-  const S3JniNphRef fts5_tokenizer;
-  const S3JniNphRef Fts5Tokenizer;
+  const S3JniNphOp OutputPointer_ByteArray;
+  const S3JniNphOp Fts5Context;
+  const S3JniNphOp Fts5ExtensionApi;
+  const S3JniNphOp fts5_api;
+  const S3JniNphOp fts5_tokenizer;
+  const S3JniNphOp Fts5Tokenizer;
 #endif
-} S3JniNphRefs = {
+} S3JniNphOps = {
 #define MkRef(INDEX, KLAZZ, MEMBER, SIG) \
   { INDEX, "org/sqlite/jni/" KLAZZ, MEMBER, SIG }
 /* NativePointerHolder ref */
@@ -364,51 +387,17 @@ static const struct {
 #undef RefO
 };
 
-#define S3JniNph(T) &S3JniNphRefs.T
+#define S3JniNph(T) &S3JniNphOps.T
 
 enum {
   /*
   ** Size of the NativePointerHolder cache.  Need enough space for
   ** (only) the library's NativePointerHolder and OutputPointer types,
   ** a fixed count known at build-time.  This value needs to be
-  ** exactly the number of S3JniNphRef entries in the S3JniNphRefs
+  ** exactly the number of S3JniNphOp entries in the S3JniNphOps
   ** object.
   */
-  S3Jni_NphCache_size = sizeof(S3JniNphRefs) / sizeof(S3JniNphRef)
-};
-
-/*
-** Cache entry for NativePointerHolder subclasses and OutputPointer
-** types. The pRef and klazz fields are set up the first time the
-** entry is fetched using s3jni_nph(). The other fields are
-** populated as needed by the routines which use them.
-*/
-typedef struct S3JniNphClass S3JniNphClass;
-struct S3JniNphClass {
-  volatile const S3JniNphRef * pRef /* Entry from S3JniNphRefs */;
-  /*
-  ** klazz is a global ref to the class represented by pRef.
-  **
-  ** According to:
-  **
-  **   https://developer.ibm.com/articles/j-jni/
-  **
-  ** > ... the IDs returned for a given class don't change for the
-  **   lifetime of the JVM process. But the call to get the field or
-  **   method can require significant work in the JVM, because fields
-  **   and methods might have been inherited from superclasses, making
-  **   the JVM walk up the class hierarchy to find them. Because the
-  **   IDs are the same for a given class, you should look them up
-  **   once and then reuse them. Similarly, looking up class objects
-  **   can be expensive, so they should be cached as well.
-  */
-  jclass klazz;
-  volatile jmethodID midCtor  /* klazz's no-arg constructor. Used by
-                              ** NativePointerHolder_new(). */;
-  volatile jfieldID fidValue  /* NativePointerHolder.nativePointer or
-                              ** OutputPointer.T.value */;
-  volatile jfieldID fidAggCtx /* sqlite3_context.aggregateContext, used only
-                              ** by the sqlite3_context binding. */;
+  S3Jni_NphCache_size = sizeof(S3JniNphOps) / sizeof(S3JniNphOp)
 };
 
 /*
@@ -420,7 +409,9 @@ struct S3JniHook{
   jmethodID midCallback   /* callback method. Signature depends on
                           ** jObj's type */;
   /* We lookup the jObj.xDestroy() method as-needed for contexts which
-  ** have custom finalizers. */
+  ** support custom finalizers. Fundamentally we can support them for
+  ** any Java type, but we only want to expose support for them where
+  ** the C API does. */
   jobject jExtra          /* Global ref to a per-hook-type value */;
   int doXDestroy          /* If true then S3JniHook_unref() will call
                              jObj->xDestroy() if it's available. */;
@@ -590,10 +581,10 @@ struct S3JniGlobalType {
   ** NativePointerHolder subclasses and OutputPointer.T types.
   */
   struct {
-    S3JniNphClass list[S3Jni_NphCache_size];
+    S3JniNphOp list[S3Jni_NphCache_size];
     sqlite3_mutex * mutex;    /* mutex for this->list */
-    void const * locker;      /* sanity-checking-only context object
-                                 for this->mutex */
+    volatile void const * locker;  /* sanity-checking-only context object
+                                      for this->mutex */
   } nph;
   /*
   ** Cache of per-thread state.
@@ -602,8 +593,9 @@ struct S3JniGlobalType {
     S3JniEnv * aHead      /* Linked list of in-use instances */;
     S3JniEnv * aFree      /* Linked list of free instances */;
     sqlite3_mutex * mutex /* mutex for aHead and aFree. */;
-    void const * locker   /* env mutex is held on this object's behalf.
-                             Used only for sanity checking. */;
+    volatile void const * locker  /* env mutex is held on this
+                                     object's behalf.  Used only for
+                                     sanity checking. */;
   } envCache;
   /*
   ** Per-db state. This can move into the core library once we can tie
@@ -612,8 +604,10 @@ struct S3JniGlobalType {
   struct {
     S3JniDb * aFree  /* Linked list of free instances */;
     sqlite3_mutex * mutex /* mutex for aHead and aFree */;
-    void const * locker /* perDb mutex is held on this object's
-                           behalf. Used only for sanity checking. */;
+    volatile void const * locker
+    /* perDb mutex is held on this object's behalf. Used only for
+       sanity checking. Note that the mutex is at the class level, not
+       instance level. */;
   } perDb;
   struct {
     S3JniUdf * aFree    /* Head of the free-item list. Guarded by global
@@ -646,8 +640,9 @@ struct S3JniGlobalType {
     int nExt                 /* number of active entries in aExt, all in the
                                 first nExt'th array elements. */;
     sqlite3_mutex * mutex    /* mutex for manipulation/traversal of aExt */;
-    const void * locker      /* object on whose behalf the mutex is held.
-                                Only for sanity checking in debug builds. */;
+    volatile const void * locker /* object on whose behalf the mutex
+                                    is held.  Only for sanity checking
+                                    in debug builds. */;
   } autoExt;
 #ifdef SQLITE_ENABLE_FTS5
   struct {
@@ -1316,23 +1311,20 @@ static int S3JniEnv_uncache(JNIEnv * const env){
 ** This simple cache catches >99% of searches in the current
 ** (2023-07-31) tests.
 */
-static S3JniNphClass * s3jni__nph(JNIEnv * const env, S3JniNphRef const* pRef){
-  S3JniNphClass * const pNC = &SJG.nph.list[pRef->index];
+static S3JniNphOp * s3jni__nphop(JNIEnv * const env, S3JniNphOp const* pRef){
+  S3JniNphOp * const pNC = &SJG.nph.list[pRef->index];
 
-  assert( (void*)pRef>=(void*)&S3JniNphRefs && (void*)pRef<(void*)(&S3JniNphRefs + 1)
+  assert( (void*)pRef>=(void*)&S3JniNphOps && (void*)pRef<(void*)(&S3JniNphOps + 1)
           && "pRef is out of range" );
   assert( pRef->index>=0
-          && (pRef->index < (sizeof(S3JniNphRefs) / sizeof(S3JniNphRef)))
+          && (pRef->index < (sizeof(S3JniNphOps) / sizeof(S3JniNphOp)))
           && "pRef->index is out of range" );
-  if( !pNC->pRef ){
+  if( !pNC->klazz ){
     S3JniNph_mutex_enter;
-    if( !pNC->pRef ){
+    if( !pNC->klazz ){
       jclass const klazz = (*env)->FindClass(env, pRef->zName);
       S3JniExceptionIsFatal("FindClass() unexpectedly threw");
       pNC->klazz = S3JniRefGlobal(klazz);
-      pNC->pRef = pRef
-        /* Must come last to avoid a race condition where pNC->klass
-           can be NULL after this function returns. */;
     }
     S3JniNph_mutex_leave;
   }
@@ -1340,11 +1332,11 @@ static S3JniNphClass * s3jni__nph(JNIEnv * const env, S3JniNphRef const* pRef){
   return pNC;
 }
 
-#define s3jni_nph(PRef) s3jni__nph(env, PRef)
+#define s3jni_nphop(PRef) s3jni__nphop(env, PRef)
 
 /*
 ** Common code for accessor functions for NativePointerHolder and
-** OutputPointer types. pRef must be a pointer from S3JniNphRefs. jOut
+** OutputPointer types. pRef must be a pointer from S3JniNphOps. jOut
 ** must be an instance of that class (Java's type safety takes care of
 ** that requirement). If necessary, this fetches the jfieldID for
 ** jOut's pRef->zMember, which must be of the type represented by the
@@ -1354,8 +1346,8 @@ static S3JniNphClass * s3jni__nph(JNIEnv * const env, S3JniNphRef const* pRef){
 **
 ** Property lookups are cached on a per-pRef basis.
 */
-static jfieldID s3jni_nphop_field(JNIEnv * const env, S3JniNphRef const* pRef){
-  S3JniNphClass * const pNC = s3jni_nph(pRef);
+static jfieldID s3jni_nphop_field(JNIEnv * const env, S3JniNphOp const* pRef){
+  S3JniNphOp * const pNC = s3jni_nphop(pRef);
 
   if( !pNC->fidValue ){
     S3JniNph_mutex_enter;
@@ -1363,7 +1355,7 @@ static jfieldID s3jni_nphop_field(JNIEnv * const env, S3JniNphRef const* pRef){
       pNC->fidValue = (*env)->GetFieldID(env, pNC->klazz,
                                          pRef->zMember, pRef->zTypeSig);
       S3JniExceptionIsFatal("Code maintenance required: missing "
-                            "required S3JniNphClass::fidValue.");
+                            "required S3JniNphOp::fidValue.");
     }
     S3JniNph_mutex_leave;
   }
@@ -1376,7 +1368,7 @@ static jfieldID s3jni_nphop_field(JNIEnv * const env, S3JniNphRef const* pRef){
 ** zClassName must be a static string so we can use its address
 ** as a cache key.
 */
-static void NativePointerHolder__set(JNIEnv * const env, S3JniNphRef const* pRef,
+static void NativePointerHolder__set(JNIEnv * const env, S3JniNphOp const* pRef,
                                      jobject ppOut, const void * p){
   assert( ppOut );
   (*env)->SetLongField(env, ppOut, s3jni_nphop_field(env, pRef), (jlong)p);
@@ -1392,7 +1384,7 @@ static void NativePointerHolder__set(JNIEnv * const env, S3JniNphRef const* pRef
 ** no-op if pObj is NULL.
 */
 static void * NativePointerHolder__get(JNIEnv * env, jobject pObj,
-                                       S3JniNphRef const* pRef){
+                                       S3JniNphOp const* pRef){
   void * rv = 0;
   if( pObj ){
     rv = (void*)(*env)->GetLongField(env, pObj, s3jni_nphop_field(env, pRef));
@@ -1570,7 +1562,7 @@ static void OutputPointer_set_Int64(JNIEnv * const env, jobject const jOut,
 ** Object type.
 */
 static void OutputPointer_set_obj(JNIEnv * const env,
-                                  S3JniNphRef const * const pRef,
+                                  S3JniNphOp const * const pRef,
                                   jobject const jOut,
                                   jobject v){
   (*env)->SetObjectField(env, jOut, s3jni_nphop_field(env, pRef), v);
@@ -1666,14 +1658,14 @@ static void ResultJavaValue_finalizer(void *v){
 ** if Java fails to allocate, but the JNI docs are not entirely clear
 ** on that detail.
 **
-** Always use a static pointer from the S3JniNphRefs struct for the
+** Always use a static pointer from the S3JniNphOps struct for the
 ** 2nd argument.
 */
 static jobject NativePointerHolder_new(JNIEnv * const env,
-                                       S3JniNphRef const * pRef,
+                                       S3JniNphOp const * pRef,
                                        const void * pNative){
   jobject rv = 0;
-  S3JniNphClass * const pNC = s3jni_nph(pRef);
+  S3JniNphOp * const pNC = s3jni_nphop(pRef);
   if( !pNC->midCtor ){
     S3JniNph_mutex_enter;
     if( !pNC->midCtor ){
@@ -1826,7 +1818,7 @@ static int udf_args(JNIEnv *env,
   *jArgv = 0;
   if( !jcx ) goto error_oom;
   ja = (*env)->NewObjectArray(
-    env, argc, s3jni_nph(S3JniNph(sqlite3_value))->klazz,
+    env, argc, s3jni_nphop(S3JniNph(sqlite3_value))->klazz,
     NULL);
   s3jni_oom_check( ja );
   if( !ja ) goto error_oom;
@@ -2113,12 +2105,12 @@ static int s3jni_run_java_auto_extensions(sqlite3 *pDb, const char **pzErr,
   if( 0==SJG.autoExt.nExt ) return 0;
   env = s3jni_env();
   jc = S3JniEnv_get();
-  S3JniAutoExt_mutex_enter;
+  S3JniDb_mutex_enter;
   ps = jc->pdbOpening ? jc->pdbOpening : S3JniDb_from_c(pDb);
   if( !ps ){
     *pzErr = sqlite3_mprintf("Unexpected arrival of null S3JniDb in "
                              "auto-extension runner.");
-    S3JniAutoExt_mutex_leave;
+    S3JniDb_mutex_leave;
     return SQLITE_ERROR;
   }
   assert( ps->jDb );
@@ -2128,7 +2120,7 @@ static int s3jni_run_java_auto_extensions(sqlite3 *pDb, const char **pzErr,
                                 ps, 0/* we'll re-set this after open()
                                         completes. */);
     if( rc ){
-      S3JniAutoExt_mutex_leave;
+      S3JniDb_mutex_leave;
       return rc;
     }
   }
@@ -2136,7 +2128,7 @@ static int s3jni_run_java_auto_extensions(sqlite3 *pDb, const char **pzErr,
     assert( ps == jc->pdbOpening );
     jc->pdbOpening = 0;
   }
-  S3JniAutoExt_mutex_leave;
+  S3JniDb_mutex_leave;
   NativePointerHolder_set(S3JniNph(sqlite3), ps->jDb, pDb)
     /* As of here, the Java/C connection is complete except for the
        (temporary) lack of finalizer for the ps object. */;
@@ -4442,10 +4434,12 @@ JniDecl(void,1jni_1internal_1details)(JniArgsEnvClass){
   SO(S3JniEnv);
   SO(S3JniHook);
   SO(S3JniDb);
-  SO(S3JniNphRefs);
+  SO(S3JniNphOps);
   printf("\t(^^^ %u NativePointerHolder/OutputPointer.T types)\n",
          (unsigned)S3Jni_NphCache_size);
   SO(S3JniGlobal);
+  SO(S3JniGlobal.nph);
+  SO(S3JniGlobal.metrics);
   SO(S3JniAutoExtension);
   SO(S3JniUdf);
 #undef SO
@@ -4457,7 +4451,7 @@ JniDecl(void,1jni_1internal_1details)(JniArgsEnvClass){
   printf("Mutex entry:"
          "\n\tglobal       = %u"
          "\n\tenv          = %u"
-         "\n\tnph          = %u for S3JniNphClass init"
+         "\n\tnph          = %u for S3JniNphOp init"
          "\n\tperDb        = %u"
          "\n\tautoExt list = %u"
          "\n\tS3JniUdf     = %u (free-list)"
@@ -5034,7 +5028,7 @@ static int s3jni_xTokenize_xToken(void *p, int tFlags, const char* z,
 ** Proxy for Fts5ExtensionApi.xTokenize() and
 ** fts5_tokenizer.xTokenize()
 */
-static jint s3jni_fts5_xTokenize(JniArgsEnvObj, S3JniNphRef const *pRef,
+static jint s3jni_fts5_xTokenize(JniArgsEnvObj, S3JniNphOp const *pRef,
                                  jint tokFlags, jobject jFcx,
                                  jbyteArray jbaText, jobject jCallback){
   Fts5ExtDecl;
index a0aaa82bbda08dd3f0b2cdbb4d2664b7c7336cb4..e396c94c3b534e8d89e6ee8d3297cbb2bceb64a7 100644 (file)
@@ -122,7 +122,7 @@ public class Tester1 implements Runnable {
     affirm(v, "Affirmation failed.");
   }
 
-  @ManualTest /* because testing this for threading is pointless */
+  @SingleThreadOnly /* because it's thread-agnostic */
   private void test1(){
     affirm(sqlite3_libversion_number() == SQLITE_VERSION_NUMBER);
   }
@@ -610,7 +610,7 @@ public class Tester1 implements Runnable {
     affirm( 1 == xDestroyCalled.value );
   }
 
-  @ManualTest /* because threading is meaningless here */
+  @SingleThreadOnly /* because it's thread-agnostic */
   private void testToUtf8(){
     /**
        https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html
@@ -978,8 +978,8 @@ public class Tester1 implements Runnable {
     affirm( 7 == counter.value );
   }
 
-  @ManualTest /* because threads inherently break this test */
-  private void testBusy(){
+  @SingleThreadOnly /* because threads inherently break this test */
+  private static void testBusy(){
     final String dbName = "_busy-handler.db";
     final OutputPointer.sqlite3 outDb = new OutputPointer.sqlite3();
     final OutputPointer.sqlite3_stmt outStmt = new OutputPointer.sqlite3_stmt();
@@ -1482,7 +1482,7 @@ public class Tester1 implements Runnable {
   }
 
 
-  @ManualTest /* we really only want to run this test manually. */
+  @ManualTest /* we really only want to run this test manually */
   private void testSleep(){
     out("Sleeping briefly... ");
     sqlite3_sleep(600);
@@ -1525,8 +1525,6 @@ public class Tester1 implements Runnable {
         outln();
       }
     }
-    testToUtf8();
-    test1();
     for(java.lang.reflect.Method m : mlist){
       nap();
       try{
@@ -1536,9 +1534,6 @@ public class Tester1 implements Runnable {
         throw e;
       }
     }
-    if( !fromThread ){
-      testBusy();
-    }
     synchronized( this.getClass() ){
       ++nTestRuns;
     }
index 4f091a5f465eebd67ab28608a58b66c12809919c..32c1abd2c74efd0c064f9be5c992598764b93bf7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Further\sJNI\scleanups.
-D 2023-09-02T08:51:14.022
+C Remove\sa\ssuperfluous\slevel\sof\sindirection\sin\sthe\sJNI\sinternals.
+D 2023-09-02T10:18:10.477
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -237,7 +237,7 @@ F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a3
 F ext/jni/GNUmakefile dc6e78f9717470d262b4b3ec17c337834295f9df81717c1539da84106324fd1e
 F ext/jni/README.md 1332b1fa27918bd5d9ca2d0d4f3ac3a6ab86b9e3699dc5bfe32904a027f3d2a9
 F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
-F ext/jni/src/c/sqlite3-jni.c d98030bb7f502b42990eeb0f2bd103af0b1f1312ba82892949c5ced85262e036
+F ext/jni/src/c/sqlite3-jni.c 1ce08538c568ec47ccf9e88e8b6d0e5b8a874520238d809adbfc93feb9f54d27
 F ext/jni/src/c/sqlite3-jni.h c22f0189254abe26fad3ba132b484785b19a1aa96d34d30d7d8c5ffe6a9b25d1
 F ext/jni/src/org/sqlite/jni/AbstractCollationCallback.java 95e88ba04f4aac51ffec65693e878e234088b2f21b387f4e4285c8b72b33e436
 F ext/jni/src/org/sqlite/jni/AggregateFunction.java 7312486bc65fecdb91753c0a4515799194e031f45edbe16a6373cea18f404dc4
@@ -264,7 +264,7 @@ F ext/jni/src/org/sqlite/jni/SQLFunction.java 544a875d33fd160467d82e2397ac33157b
 F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 98f8d62492e2d6693336dd42c12267ea7f21eefe219aa85b8dd399bd6b0732bd
 F ext/jni/src/org/sqlite/jni/ScalarFunction.java 6d387bb499fbe3bc13c53315335233dbf6a0c711e8fa7c521683219b041c614c
 F ext/jni/src/org/sqlite/jni/TableColumnMetadata.java 54511b4297fa28dcb3f49b24035e34ced10e3fd44fd0e458e784f4d6b0096dab
-F ext/jni/src/org/sqlite/jni/Tester1.java 93e89c4f72065bf28625cf435c47ed2bd3d937fe5c2431e6e7c3407f09f3f9bc
+F ext/jni/src/org/sqlite/jni/Tester1.java e62b0e855ef19a703dc53c1eb8395ff49f5dc4c9471627f5ba71b9b831a18b37
 F ext/jni/src/org/sqlite/jni/TesterFts5.java 2b2d6f3cc9f508358c103b774aee296c0f3d8c2f387d6abae9b8b9055f62c800
 F ext/jni/src/org/sqlite/jni/TraceV2Callback.java beb0b064c1a5f8bfe585a324ed39a4e33edbe379a3fc60f1401661620d3ca7c0
 F ext/jni/src/org/sqlite/jni/UpdateHookCallback.java 8376f4a931f2d5612b295c003c9515ba933ee76d8f95610e89c339727376e36c
@@ -2115,8 +2115,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P f9c1f9cad1ad22f689a4afa13d59bf9969ddaed6624cbc16cb1bf5d1fd0c8a5b
-R 215167a378a1f1105562740ffd0f1842
+P 30e38173c3ece0c9f8e7a9710f46cb5e8e8ef101c04531318a7adb070242f5dd
+R 5b531d67a390c107642befa040c21413
 U stephan
-Z 15dc34b47fe3ed21ed7cc58408f87312
+Z 11b0834dd4cedde9630a4a43d0bbc08f
 # Remove this line to create a well-formed Fossil manifest.
index bbd378b4fe90e7996371e1b8bb2b67f36c18859f..96a63aefce7cf11eaddafcaa62ccfd38603e0503 100644 (file)
@@ -1 +1 @@
-30e38173c3ece0c9f8e7a9710f46cb5e8e8ef101c04531318a7adb070242f5dd
\ No newline at end of file
+8dca6f7660c15eacbda20da1c66c9ef1de36864f78750658226b1a7baf22b726
\ No newline at end of file