]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Bind sqlite3_busy_handler(). Correct mapping of pointers for, and cleanup of, JNI...
authorstephan <stephan@noemail.net>
Thu, 27 Jul 2023 22:05:39 +0000 (22:05 +0000)
committerstephan <stephan@noemail.net>
Thu, 27 Jul 2023 22:05:39 +0000 (22:05 +0000)
FossilOrigin-Name: 524747796a30a5c1c6c7567b49ffb1e35e2626c73e09c335c0ab74d4ddb5f005

ext/jni/src/c/sqlite3-jni.c
ext/jni/src/c/sqlite3-jni.h
ext/jni/src/org/sqlite/jni/BusyHandler.java [new file with mode: 0644]
ext/jni/src/org/sqlite/jni/SQLite3Jni.java
ext/jni/src/org/sqlite/jni/Tester1.java
manifest
manifest.uuid

index ba892afc5656b87b170d55750236dfdfe28c4a51..581300c9d5fe218dcb55a3ef7ca1a5ef9d8aab41 100644 (file)
@@ -316,6 +316,17 @@ static void JNIEnvCache_clear(JNIEnvCache * p){
   memset(p, 0, sizeof(JNIEnvCache));
 }
 
+/**
+   State for binding Java-side busy handlers.
+*/
+typedef struct {
+  JNIEnv * env;         /* env registered from */;
+  jobject jObj          /* BusyHandlerJni instance */;
+  jclass klazz          /* jObj's class */;
+  jmethodID jmidxCallback;
+} BusyHandlerJni;
+
+
 /**
    Per-(sqlite3*) state for bindings which do not have their own
    finalizer functions, e.g. tracing and commit/rollback hooks.  This
@@ -328,12 +339,12 @@ static void JNIEnvCache_clear(JNIEnvCache * p){
    data (since they can(?) hypothetically be set via multiple JNIEnv
    objects)?
 */
-typedef struct PerDbState PerDbState;
-struct PerDbState {
+typedef struct PerDbStateJni PerDbStateJni;
+struct PerDbStateJni {
   JNIEnv *env;
   sqlite3 * pDb;
-  PerDbState * pNext;
-  PerDbState * pPrev;
+  PerDbStateJni * pNext;
+  PerDbStateJni * pPrev;
   struct {
     jobject jObj;
     jmethodID midCallback;
@@ -350,6 +361,7 @@ struct PerDbState {
     jobject jObj;
     jmethodID midCallback;
   } rollbackHook;
+  BusyHandlerJni busyHandler;
 };
 
 static struct {
@@ -367,8 +379,8 @@ static struct {
   JavaVM * jvm;
   struct JNIEnvCache envCache;
   struct {
-    PerDbState * aUsed;
-    PerDbState * aFree;
+    PerDbStateJni * aUsed;
+    PerDbStateJni * aFree;
   } perDb;
 } S3Global;
 
@@ -389,13 +401,57 @@ static void * s3jni_malloc(JNIEnv *env, size_t n){
 static void s3jni_free(void * p){
   if(p) sqlite3_free(p);
 }
+
+/**
+   Clears s's state, releasing any Java references. Before doing so,
+   it calls s's xDestroy() method, ignoring the lack of that method or
+   any exceptions it throws. This is a no-op of s has no current
+   state.
+*/
+static void BusyHandlerJni_clear(BusyHandlerJni * const s){
+  if(s->jObj){
+    JNIEnv * const env = s->env;
+    const jmethodID method =
+      (*env)->GetMethodID(env, s->klazz, "xDestroy", "()V");
+    if(method){
+      (*env)->CallVoidMethod(env, s->jObj, method);
+      EXCEPTION_IGNORE;
+    }else{
+      EXCEPTION_CLEAR;
+    }
+    UNREF_G(s->jObj);
+    UNREF_G(s->klazz);
+    memset(s, 0, sizeof(BusyHandlerJni));
+  }
+}
+
+/**
+   Initializes s to wrap BusyHandlerJni-type object jObject, clearning
+   any current state of s beforehand. Returns 0 on success, non-0 on
+   error. On error, s's state is cleared.
+*/
+static int BusyHandlerJni_init(JNIEnv * const env, BusyHandlerJni * const s,
+                               jobject jObj){
+  const char * zSig = "(I)I" /* callback signature */;
+  if(s->jObj) BusyHandlerJni_clear(s);
+  s->env = env;
+  s->jObj = REF_G(jObj);
+  s->klazz = REF_G((*env)->GetObjectClass(env, jObj));
+  s->jmidxCallback = (*env)->GetMethodID(env, s->klazz, "xCallback", zSig);
+  IFTHREW {
+    BusyHandlerJni_clear(s);
+    return SQLITE_ERROR;
+  }
+  return 0;
+}
+
 /**
-   Extracts the new PerDbState instance from the free-list, or
+   Extracts the new PerDbStateJni instance from the free-list, or
    allocates one if needed, associats it with pDb, and returns.
    Returns NULL on OOM.
 */
-static PerDbState * PerDbState_alloc(JNIEnv *env, sqlite3 *pDb){
-  PerDbState * rv;
+static PerDbStateJni * PerDbStateJni_alloc(JNIEnv *env, sqlite3 *pDb){
+  PerDbStateJni * rv;
   assert( pDb );
   if(S3Global.perDb.aFree){
     rv = S3Global.perDb.aFree;
@@ -407,18 +463,18 @@ static PerDbState * PerDbState_alloc(JNIEnv *env, sqlite3 *pDb){
       rv->pNext = 0;
     }
   }else{
-    rv = s3jni_malloc(env, sizeof(PerDbState));
+    rv = s3jni_malloc(env, sizeof(PerDbStateJni));
     if(rv){
-      memset(rv, 0, sizeof(PerDbState));
-      rv->pNext = S3Global.perDb.aUsed;
-      S3Global.perDb.aUsed = rv;
-      if(rv->pNext){
-        assert(!rv->pNext->pPrev);
-        rv->pNext->pPrev = rv;
-      }
+      memset(rv, 0, sizeof(PerDbStateJni));
     }
   }
   if(rv){
+    rv->pNext = S3Global.perDb.aUsed;
+    S3Global.perDb.aUsed = rv;
+    if(rv->pNext){
+      assert(!rv->pNext->pPrev);
+      rv->pNext->pPrev = rv;
+    }
     rv->pDb = pDb;
     rv->env = env;
   }
@@ -429,7 +485,7 @@ static PerDbState * PerDbState_alloc(JNIEnv *env, sqlite3 *pDb){
    Clears s's state and moves it to the free-list.
 */
 FIXME_THREADING
-static void PerDbState_set_aside(PerDbState *s){
+static void PerDbStateJni_set_aside(PerDbStateJni *s){
   if(s){
     JNIEnv * const env = s->env;
     assert(s->pDb && "Else this object is already in the free-list.");
@@ -443,27 +499,38 @@ static void PerDbState_set_aside(PerDbState *s){
     UNREF_G(s->progress.jObj);
     UNREF_G(s->commitHook.jObj);
     UNREF_G(s->rollbackHook.jObj);
-    s->env = 0;
-    s->pDb = 0;
-    s->pPrev = 0;
+    BusyHandlerJni_clear(&s->busyHandler);
+    memset(s, 0, sizeof(PerDbStateJni));
     s->pNext = S3Global.perDb.aFree;
     S3Global.perDb.aFree = s;
   }
 }
 
+static void PerDbStateJni_dump(PerDbStateJni *s){
+  MARKER(("PerDbStateJni->env @ %p\n", s->env));
+  MARKER(("PerDbStateJni->pDb @ %p\n", s->pDb));
+  MARKER(("PerDbStateJni->trace.jObj @ %p\n", s->trace.jObj));
+  MARKER(("PerDbStateJni->progress.jObj @ %p\n", s->progress.jObj));
+  MARKER(("PerDbStateJni->commitHook.jObj @ %p\n", s->commitHook.jObj));
+  MARKER(("PerDbStateJni->rollbackHook.jObj @ %p\n", s->rollbackHook.jObj));
+  MARKER(("PerDbStateJni->busyHandler.env @ %p\n", s->busyHandler.env));
+  MARKER(("PerDbStateJni->busyHandler.jObj @ %p\n", s->busyHandler.jObj));
+  MARKER(("PerDbStateJni->env @ %p\n", s->env));
+}
+
 /**
-   Returns the PerDbState object for the given db. If allocIfNeeded is
+   Returns the PerDbStateJni object for the given db. If allocIfNeeded is
    true then a new instance will be allocated if no mapping currently
    exists, else NULL is returned if no mapping is found.
 
 */
 FIXME_THREADING
-static PerDbState * PerDbState_for_db(JNIEnv *env, sqlite3 *pDb, int allocIfNeeded){
-  PerDbState * s = S3Global.perDb.aUsed;
+static PerDbStateJni * PerDbStateJni_for_db(JNIEnv *env, sqlite3 *pDb, int allocIfNeeded){
+  PerDbStateJni * s = S3Global.perDb.aUsed;
   for( ; s; s = s->pNext){
     if(s->pDb == pDb) return s;
   }
-  if(allocIfNeeded) s = PerDbState_alloc(env, pDb);
+  if(allocIfNeeded) s = PerDbStateJni_alloc(env, pDb);
   return s;
 }
 
@@ -471,12 +538,12 @@ static PerDbState * PerDbState_for_db(JNIEnv *env, sqlite3 *pDb, int allocIfNeed
    Cleans up and frees all state in S3Global.perDb.
 */
 FIXME_THREADING
-static void PerDbState_free_all(void){
-  PerDbState * pS = S3Global.perDb.aUsed;
-  PerDbState * pSNext = 0;
+static void PerDbStateJni_free_all(void){
+  PerDbStateJni * pS = S3Global.perDb.aUsed;
+  PerDbStateJni * pSNext = 0;
   for( ; pS; pS = pSNext ){
     pSNext = pS->pNext;
-    PerDbState_set_aside(pS);
+    PerDbStateJni_set_aside(pS);
     assert(pSNext ? !pSNext->pPrev : 1);
   }
   assert( 0==S3Global.perDb.aUsed );
@@ -1205,8 +1272,50 @@ JDECL(jint,1bind_1zeroblob64)(JENV_JSELF, jobject jpStmt,
   return (jint)sqlite3_bind_zeroblob(PtrGet_sqlite3_stmt(jpStmt), (int)ndx, (sqlite3_uint64)n);
 }
 
-JDECL(jint,1busy_1timeout)(JENV_JSELF, jobject pDb, jint ms){
-  return sqlite3_busy_timeout(PtrGet_sqlite3(pDb), (int)ms);
+static int s3jni_busy_handler(void* pState, int n){
+  PerDbStateJni * const pS = (PerDbStateJni *)pState;
+  int rc = 0;
+  if( pS->busyHandler.jObj ){
+    JNIEnv * const env = pS->env;
+    rc = (*env)->CallIntMethod(env, pS->busyHandler.jObj,
+                               pS->busyHandler.jmidxCallback, (jint)n);
+  }
+  return rc;
+}
+
+JDECL(jint,1busy_1handler)(JENV_JSELF, jobject jDb, jobject jBusy){
+  sqlite3 * const pDb = PtrGet_sqlite3(jDb);
+  PerDbStateJni * const pS = PerDbStateJni_for_db(env, pDb, 1);
+  int rc;
+  if(!pS) return (jint)SQLITE_NOMEM;
+  if(jBusy){
+    if(pS->busyHandler.jObj &&
+       (*env)->IsSameObject(env, pS->busyHandler.jObj, jBusy)){
+      /* Same object - this is a no-op. */
+      return 0;
+    }
+    rc = BusyHandlerJni_init(env, &pS->busyHandler, jBusy);
+    if(rc){
+      assert(!pS->busyHandler.jObj);
+      return (jint)rc;
+    }
+    assert(pS->busyHandler.jObj && pS->busyHandler.klazz);
+    assert( (*env)->IsSameObject(env, pS->busyHandler.jObj, jBusy) );
+  }else{
+    BusyHandlerJni_clear(&pS->busyHandler);
+  }
+  return jBusy
+    ? sqlite3_busy_handler(pDb, s3jni_busy_handler, pS)
+    : sqlite3_busy_handler(pDb, 0, 0);
+}
+
+JDECL(jint,1busy_1timeout)(JENV_JSELF, jobject jDb, jint ms){
+  sqlite3* const pDb = PtrGet_sqlite3(jDb);
+  PerDbStateJni * const pS = PerDbStateJni_for_db(env, pDb, 0);
+  if( pS && pS->busyHandler.jObj ){
+    BusyHandlerJni_clear(&pS->busyHandler);
+  }
+  return sqlite3_busy_timeout(pDb, (int)ms);
 }
 
 /**
@@ -1215,13 +1324,19 @@ JDECL(jint,1busy_1timeout)(JENV_JSELF, jobject pDb, jint ms){
 static jint s3jni_close_db(JNIEnv *env, jobject jDb, int version){
   sqlite3 * pDb;
   int rc = 0;
-  PerDbState * pS;
+  PerDbStateJni * pS = 0;
   assert(version == 1 || version == 2);
+  if(0){
+    PerDbStateJni * s = S3Global.perDb.aUsed;
+    for( ; s; s = s->pNext){
+      PerDbStateJni_dump(s);
+    }
+  }
   pDb = PtrGet_sqlite3(jDb);
   if(!pDb) return rc;
-  pS = PerDbState_for_db(env, pDb, 0);
+  pS = PerDbStateJni_for_db(env, pDb, 0);
   rc = 1==version ? (jint)sqlite3_close(pDb) : (jint)sqlite3_close_v2(pDb);
-  if(pS) PerDbState_set_aside(pS)
+  if(pS) PerDbStateJni_set_aside(pS)
            /* MUST come after close() because of pS->trace. */;
   setNativePointer(env, jDb, 0, ClassNames.sqlite3);
   return (jint)rc;
@@ -1706,7 +1821,7 @@ JDECL(void,1set_1last_1insert_1rowid)(JENV_JSELF, jobject jpDb, jlong rowId){
 }
 
 JDECL(jint,1shutdown)(JENV_JSELF){
-  PerDbState_free_all();
+  PerDbStateJni_free_all();
   JNIEnvCache_clear(&S3Global.envCache);
   /* Do not clear S3Global.jvm: it's legal to call
      sqlite3_initialize() again to restart the lib. */
@@ -1714,7 +1829,7 @@ JDECL(jint,1shutdown)(JENV_JSELF){
 }
 
 static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){
-  PerDbState * const ps = (PerDbState *)pC;
+  PerDbStateJni * const ps = (PerDbStateJni *)pC;
   JNIEnv * const env = ps->env;
   jobject jX = NULL;
   JNIEnvCacheLine * const pEcl = S3Global_env_cache(env);
@@ -1752,12 +1867,12 @@ static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){
 
 JDECL(jint,1trace_1v2)(JENV_JSELF,jobject jDb, jint traceMask, jobject jTracer){
   sqlite3 * const pDb = PtrGet_sqlite3(jDb);
-  PerDbState * ps;
+  PerDbStateJni * ps;
   jclass klazz;
   if( !traceMask || !jTracer ){
     return (jint)sqlite3_trace_v2(pDb, 0, 0, 0);
   }
-  ps = PerDbState_for_db(env, pDb, 1);
+  ps = PerDbStateJni_for_db(env, pDb, 1);
   if(!ps) return SQLITE_NOMEM;
   klazz = (*env)->GetObjectClass(env, jTracer);
   ps->trace.midCallback = (*env)->GetMethodID(env, klazz, "xCallback",
index a55d4371525a21c38756f23754af3b0072f1ab02..524a9b407549bb0d67b94757a33b4878a2dfc589 100644 (file)
@@ -843,6 +843,14 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1bind_1zeroblob
 JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1bind_1zeroblob64
   (JNIEnv *, jclass, jobject, jint, jlong);
 
+/*
+ * Class:     org_sqlite_jni_SQLite3Jni
+ * Method:    sqlite3_busy_handler
+ * Signature: (Lorg/sqlite/jni/sqlite3;Lorg/sqlite/jni/BusyHandler;)I
+ */
+JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1busy_1handler
+  (JNIEnv *, jclass, jobject, jobject);
+
 /*
  * Class:     org_sqlite_jni_SQLite3Jni
  * Method:    sqlite3_busy_timeout
diff --git a/ext/jni/src/org/sqlite/jni/BusyHandler.java b/ext/jni/src/org/sqlite/jni/BusyHandler.java
new file mode 100644 (file)
index 0000000..d3a3675
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+** 2023-07-22
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file is part of the JNI bindings for the sqlite3 C API.
+*/
+package org.sqlite.jni;
+
+/**
+   Callback proxy for use with sqlite3_busy_handler().
+*/
+public abstract class BusyHandler {
+  /**
+     Must function as documented for the sqlite3_busy_handler()
+     callback argument, minus the (void*) argument the C-level
+     function requires.
+  */
+  public abstract int xCallback(int n);
+
+  /**
+     Optionally override to perform any cleanup when this busy
+     handler is destroyed. It is destroyed when:
+
+     - The associated db is passed to sqlite3_close() or
+       sqlite3_close_v2().
+
+     - sqlite3_busy_handler() is called to replace the handler,
+       whether it's passed a null handler or any other instance of
+       this class.
+
+     - sqlite3_busy_timeout() is called, which implicitly installs
+       a busy handler.
+  */
+  public void xDestroy(){}
+}
index 53b920f808124b3cb9fde8576a84572ae3d82bec..b0ae33c640c2ff35fb5ca219f6203a0fa4c8f3af 100644 (file)
@@ -133,7 +133,14 @@ public final class SQLite3Jni {
 
   public static native int sqlite3_bind_zeroblob64(@NotNull sqlite3_stmt stmt, int ndx, long n);
 
-  //TODO? public static native int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
+  /**
+     As for the C-level function of the same name, with a BusyHandler
+     instance in place of a callback function. Pass it a null handler
+     to clear the busy handler. Calling this multiple times with the
+     same object is a no-op on the second and subsequent calls.
+  */
+  public static native int sqlite3_busy_handler(@NotNull sqlite3 db,
+                                                @Nullable BusyHandler handler);
 
   public static native int sqlite3_busy_timeout(@NotNull sqlite3 db, int ms);
 
index 910fc85005b149920de1f74f26fe6c9be743476d..b4c3f97e8ccedc4246201495ea5fccad994518e5 100644 (file)
@@ -640,6 +640,28 @@ public class Tester1 {
     myassert( 7 == counter.value );
   }
 
+  private static void testBusy(){
+    outln("testBusy()...");
+    final sqlite3 db = createNewDb();
+    final ValueHolder<Boolean> xDestroyed = new ValueHolder<>(false);
+    BusyHandler handler = new BusyHandler(){
+        @Override public int xCallback(int n){
+          /* How do we conveniently test this? */
+          return 0;
+        }
+        @Override public void xDestroy(){
+          xDestroyed.value = true;
+        }
+      };
+    outln("setting busy handler...");
+    int rc = sqlite3_busy_handler(db, handler);
+    outln("set busy handler");
+    myassert(0 == rc);
+    myassert( false == xDestroyed.value );
+    sqlite3_close_v2(db);
+    myassert( true == xDestroyed.value );
+  }
+
   private static void testMisc(){
     outln("Sleeping...");
     sqlite3_sleep(500);
@@ -666,6 +688,7 @@ public class Tester1 {
     testUdfAggregate();
     testUdfWindow();
     testTrace();
+    testBusy();
     testMisc();
     if(liArgs.indexOf("-v")>0){
       listBoundMethods();
index 393405cc0dedd91fe0b6745aeb5cf58ce35ee85f..90de8b5efc69c0110ae3e532ae60a2d2ab96f2c4 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Replace\ssome\swww:\sinterwiki\sreferences\sin\sthe\sJNI\sreadme\swith\stheir\sfull\sURLs\sto\smake\sthe\sdoc\smore\sportable.
-D 2023-07-27T20:32:16.722
+C Bind\ssqlite3_busy_handler().\sCorrect\smapping\sof\spointers\sfor,\sand\scleanup\sof,\sJNI-level\sper-db\sstate.
+D 2023-07-27T22:05:39.096
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -232,15 +232,16 @@ F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
 F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
 F ext/jni/GNUmakefile 56a014dbff9516774d895ec1ae9df0ed442765b556f79a0fc0b5bc438217200d
 F ext/jni/README.md 042762dbf047667783a5bd0aec303535140f302debfbd259c612edf856661623
-F ext/jni/src/c/sqlite3-jni.c 55bf5624beee849b1c063bf929e6066dc95437564c3212d30e672280bec45da8
-F ext/jni/src/c/sqlite3-jni.h ef862321bb153135472ebe6be6df9db3e47448ae3ef6bb3cb7953c54971efcf8
+F ext/jni/src/c/sqlite3-jni.c 8274a016b5049651ca016486639f90abf050020cf6c880b5273f4e15b29d1ffc
+F ext/jni/src/c/sqlite3-jni.h c9bb150a38dce09cc2794d5aac8fa097288d9946fbb15250fd0a23c31957f506
+F ext/jni/src/org/sqlite/jni/BusyHandler.java aa7574dcf08500ab2334a0ce09c24593374db89815d76fee16da09641c1e32ce
 F ext/jni/src/org/sqlite/jni/Collation.java 8dffbb00938007ad0967b2ab424d3c908413af1bbd3d212b9c9899910f1218d1
 F ext/jni/src/org/sqlite/jni/NativePointerHolder.java 70dc7bc41f80352ff3d4331e2e24f45fcd23353b3641e2f68a81bd8262215861
 F ext/jni/src/org/sqlite/jni/OutputPointer.java 08a752b58a33696c5eaf0eb9361a0966b188dec40f4a3613eb133123951f6c5f
 F ext/jni/src/org/sqlite/jni/ProgressHandler.java 5a1d7b2607eb2ef596fcf4492a49d1b3a5bdea3af9918e11716831ffd2f02284
 F ext/jni/src/org/sqlite/jni/SQLFunction.java 2f5d197f6c7d73b6031ba1a19598d7e3eee5ebad467eeee62c72e585bd6556a5
-F ext/jni/src/org/sqlite/jni/SQLite3Jni.java d588c88c17290f5b0d1e4e2a1ea68cf9acab40891c98e08203f1b90ac2aaf8dd
-F ext/jni/src/org/sqlite/jni/Tester1.java 512e545357ce1a5788b250395f2b198ae862f915aee1a8b7b8fae4620d0cfc8d
+F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 3582b30c0fb1cb39e25b9069fe8c9e2fe4f2659f4d38437b610e46143e163610
+F ext/jni/src/org/sqlite/jni/Tester1.java 1b5f638c9efa0a18579fca5172f4514cd73c8202eacf002fbcc2726efe67fcf0
 F ext/jni/src/org/sqlite/jni/Tracer.java c2fe1eba4a76581b93b375a7b95ab1919e5ae60accfb06d6beb067b033e9bae1
 F ext/jni/src/org/sqlite/jni/ValueHolder.java f022873abaabf64f3dd71ab0d6037c6e71cece3b8819fa10bf26a5461dc973ee
 F ext/jni/src/org/sqlite/jni/sqlite3.java c7d0500c7269882243aafb41425928d094b2fcbdbc2fd1caffc276871cd3fae3
@@ -2066,8 +2067,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 0514fd340ae15a95760d50c747d6fb9eae5109cb5045eeabc2bc199be0a5ae35
-R fbc3a722616dae826b754c2990ee20ad
+P 63ce0c9bdde210cf2f8b6099ae5c73caac18e6debc13c2f77090b77f3de72beb
+R c101ee50ca81ac0c17b72552c1b109f1
 U stephan
-Z 82e6c4339ed3624b75f36686218f69e5
+Z 3865f2d2a0d46095d9527e301bfc90cc
 # Remove this line to create a well-formed Fossil manifest.
index 90c4a09c65fe6620738ad2718a838eee91307233..a432b84e8fa3538d349952129047916515ea4a60 100644 (file)
@@ -1 +1 @@
-63ce0c9bdde210cf2f8b6099ae5c73caac18e6debc13c2f77090b77f3de72beb
\ No newline at end of file
+524747796a30a5c1c6c7567b49ffb1e35e2626c73e09c335c0ab74d4ddb5f005
\ No newline at end of file