#endif
/* Helpers for working with specific mutexes. */
-#define S3JniMutex_Env_assertLocked \
+#define S3JniMutex_Env_assertLocked \
assert( 0 != SJG.envCache.locker && "Misuse of S3JniGlobal.envCache.mutex" )
-#define S3JniMutex_Env_assertLocker \
+#define S3JniMutex_Env_assertLocker \
assert( (env) == SJG.envCache.locker && "Misuse of S3JniGlobal.envCache.mutex" )
-#define S3JniMutex_Env_assertNotLocker \
+#define S3JniMutex_Env_assertNotLocker \
assert( (env) != SJG.envCache.locker && "Misuse of S3JniGlobal.envCache.mutex" )
-#define S3JniMutex_Env_enter \
- S3JniMutex_Env_assertNotLocker; \
+#define S3JniMutex_Env_enter \
+ S3JniMutex_Env_assertNotLocker; \
/*MARKER(("Entering ENV mutex@%p %s.\n", env));*/ \
sqlite3_mutex_enter( SJG.envCache.mutex ); \
++SJG.metrics.nMutexEnv; \
SJG.envCache.locker = env
-#define S3JniMutex_Env_leave \
+#define S3JniMutex_Env_leave \
/*MARKER(("Leaving ENV mutex @%p %s.\n", env));*/ \
- S3JniMutex_Env_assertLocker; \
+ S3JniMutex_Env_assertLocker; \
SJG.envCache.locker = 0; \
sqlite3_mutex_leave( SJG.envCache.mutex )
-#define S3JniMutex_Ext_enter \
+#define S3JniMutex_Ext_enter \
/*MARKER(("Entering autoExt mutex@%p %s.\n", env));*/ \
sqlite3_mutex_enter( SJG.autoExt.mutex ); \
++SJG.metrics.nMutexAutoExt
-#define S3JniMutex_Ext_leave \
+#define S3JniMutex_Ext_leave \
/*MARKER(("Leaving autoExt mutex@%p %s.\n", env));*/ \
sqlite3_mutex_leave( SJG.autoExt.mutex )
-#define S3JniMutex_Nph_enter \
- S3JniMutex_Env_assertNotLocker; \
+#define S3JniMutex_Nph_enter \
+ S3JniMutex_Env_assertNotLocker; \
/*MARKER(("Entering NPH mutex@%p %s.\n", env));*/ \
sqlite3_mutex_enter( SJG.envCache.mutex ); \
++SJG.metrics.nMutexEnv2; \
SJG.envCache.locker = env
-#define S3JniMutex_Nph_leave \
+#define S3JniMutex_Nph_leave \
/*MARKER(("Leaving NPH mutex @%p %s.\n", env));*/ \
S3JniMutex_Env_assertLocker; \
SJG.envCache.locker = 0; \
sqlite3_mutex_leave( SJG.envCache.mutex )
-#define S3JniMutex_Pdb_enter \
- /*MARKER(("Entering PerDb mutex@%p %s.\n", env));*/ \
+#define S3JniMutex_S3JniDb_enter \
sqlite3_mutex_enter( SJG.perDb.mutex ); \
+ assert( 0==SJG.perDb.locker ); \
++SJG.metrics.nMutexPerDb; \
SJG.perDb.locker = env;
-#define S3JniMutex_Pdb_leave \
+#define S3JniMutex_S3JniDb_leave \
/*MARKER(("Leaving PerDb mutex@%p %s.\n", env));*/ \
+ assert( env == SJG.perDb.locker ); \
SJG.perDb.locker = 0; \
sqlite3_mutex_leave( SJG.perDb.mutex )
** references.
*/
static void S3JniHook_unref(JNIEnv * const env, S3JniHook * const s, int doXDestroy){
- if(doXDestroy && s->jObj){
+ if( doXDestroy && s->jObj ){
s3jni_call_xDestroy(env, s->jObj);
}
UNREF_G(s->jObj);
/*
** Clears s's state and moves it to the free-list.
*/
-static void S3JniDb_set_aside(JNIEnv * env, S3JniDb * const s){
- if(s){
- S3JniMutex_Pdb_enter;
+static void S3JniDb_set_aside_unlocked(JNIEnv * env, S3JniDb * const s){
+ if( s ){
+ assert( S3JniGlobal.perDb.locker == env );
assert(s->pPrev != s);
assert(s->pNext != s);
assert(s->pPrev ? (s->pPrev!=s->pNext) : 1);
s->pNext = SJG.perDb.aFree;
if(s->pNext) s->pNext->pPrev = s;
SJG.perDb.aFree = s;
- S3JniMutex_Pdb_leave;
+ }
+}
+static void S3JniDb_set_aside(JNIEnv * env, S3JniDb * const s){
+ if( s ){
+ S3JniMutex_S3JniDb_enter;
+ S3JniDb_set_aside_unlocked(env, s);
+ S3JniMutex_S3JniDb_leave;
}
}
static S3JniDb * S3JniDb_alloc(JNIEnv * const env, sqlite3 *pDb,
jobject jDb){
S3JniDb * rv;
- S3JniMutex_Pdb_enter;
+ S3JniMutex_S3JniDb_enter;
if( SJG.perDb.aFree ){
rv = SJG.perDb.aFree;
SJG.perDb.aFree = rv->pNext;
rv->jDb = REF_G(jDb);
rv->pDb = pDb;
}
- S3JniMutex_Pdb_leave;
+ S3JniMutex_S3JniDb_leave;
return rv;
}
static S3JniDb * S3JniDb_for_db(JNIEnv * const env, jobject jDb, sqlite3 *pDb){
S3JniDb * s = 0;
if( jDb || pDb ){
- S3JniMutex_Pdb_enter;
+ S3JniMutex_S3JniDb_enter;
s = SJG.perDb.aUsed;
if( !pDb ){
assert( jDb );
break;
}
}
- S3JniMutex_Pdb_leave;
+ S3JniMutex_S3JniDb_leave;
}
return s;
}
return rc ? JNI_TRUE : JNI_FALSE;
}
+/*
+** Uncaches the current JNIEnv from the S3JniGlobal state, clearing any
+** resources owned by that cache entry and making that slot available
+** for re-use. It is important that the Java-side decl of this
+** function be declared as synchronous.
+*/
+JniDecl(jboolean,1java_1uncache_1thread)(JniArgsEnvClass){
+ int rc;
+ S3JniMutex_Env_enter;
+ rc = S3JniGlobal_env_uncache(env);
+ S3JniMutex_Env_leave;
+ return rc ? JNI_TRUE : JNI_FALSE;
+}
+
+
S3JniApi(sqlite3_last_insert_rowid(),jlong,1last_1insert_1rowid)(
JniArgsEnvClass, jobject jpDb
){
S3JniGlobal_env_uncache( SJG.envCache.aHead->env );
}
S3JniMutex_Env_leave;
- /* Do not clear S3JniGlobal.jvm: it's legal to call
- sqlite3_initialize() again to restart the lib. */
+#if 0
+ /*
+ ** Is this a good idea? We will get rid of the perDb list once
+ ** sqlite3 gets a per-db client state, at which point we won't have
+ ** a central list of databases to close.
+ */
+ S3JniMutex_S3JniDb_enter;
+ while( SJG.perDb.pHead ){
+ s3jni_close_db(env, SJG.perDb.pHead->jDb, 2);
+ }
+ S3JniMutex_S3JniDb_leave;
+#endif
+ /* Do not clear S3JniGlobal.jvm: it's legal to restart the lib. */
return sqlite3_shutdown();
}
// End of SQLTester bindings. Start of lower-level bits.
////////////////////////////////////////////////////////////////////////
-
-/*
-** Uncaches the current JNIEnv from the S3JniGlobal state, clearing any
-** resources owned by that cache entry and making that slot available
-** for re-use. It is important that the Java-side decl of this
-** function be declared as synchronous.
-*/
-JNIEXPORT jboolean JNICALL
-Java_org_sqlite_jni_SQLite3Jni_uncacheJniEnv(JniArgsEnvClass){
- int rc;
- S3JniMutex_Env_enter;
- rc = S3JniGlobal_env_uncache(env);
- S3JniMutex_Env_leave;
- return rc ? JNI_TRUE : JNI_FALSE;
-}
-
/*
** Called during static init of the SQLite3Jni class to sync certain
** compile-time constants to Java-space.
/**
Each thread which uses the SQLite3 JNI APIs should call
- uncacheJniEnv() when it is done with the library - either right
- before it terminates or when it is finished using the SQLite API.
- This will clean up any cached per-JNIEnv info. Calling into the
- library will re-initialize the cache on demand.
+ sqlite3_jni_uncache_thread() when it is done with the library -
+ either right before it terminates or when it finishes using the
+ SQLite API. This will clean up any cached per-thread info.
<p>This process does not close any databases or finalize
any prepared statements because their ownership does not depend on
all databases before calling this function.
<p>Calling this from the main application thread is not strictly
- required but is "polite." Additional threads must call this
- before ending or they will leak cache entries in the C heap,
- which in turn may keep numerous Java-side global references
- active.
+ required. Additional threads must call this before ending or they
+ will leak cache entries in the C heap, which in turn may keep
+ numerous Java-side global references active.
<p>This routine returns false without side effects if the current
JNIEnv is not cached, else returns true, but this information is
which client-level code should use to make any informed
decisions.
*/
- public static synchronized native boolean uncacheJniEnv();
+ public static native boolean sqlite3_java_uncache_thread();
//////////////////////////////////////////////////////////////////////
// Maintenance reminder: please keep the sqlite3_.... functions
);
/**
- Cleans up all per-JNIEnv and per-db state managed by the library,
- as well as any registered auto-extensions, then calls the
- C-native sqlite3_shutdown().
+ Cleans up all stale per-thread state managed by the library, as
+ well as any registered auto-extensions, then calls the C-native
+ sqlite3_shutdown(). Calling this while database handles or
+ prepared statements are still active will leak resources. Trying
+ to use those objects after this routine is called invoked
+ undefined behavior.
*/
public static synchronized native int sqlite3_shutdown();
-C Update\ssome\soutdated\sJNI\sdocs\sand\saccount\sfor\sa\sfunction\srenamed\searlier\sthis\sevening.
-D 2023-08-24T21:45:30.722
+C Re-frame\sthe\sincongruous\sSQLite3Jni.uncacheThread()\sAPI\sas\ssqlite3_java_uncache_thread().
+D 2023-08-24T22:28:44.239
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/jni/GNUmakefile 6aeafa0ebcf0f0d834c814ae8b450b54135ea11a2a7868f90b6286ec1bf6020f
F ext/jni/README.md 9d3caa2e038bfe5e8356a9e8ff66f93ca0647ac278339eeea296f10017f5cf35
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
-F ext/jni/src/c/sqlite3-jni.c c15bd15c895ec698a669c7058cb19e8bfccdcab88dc6345357f698fbfe9544aa
-F ext/jni/src/c/sqlite3-jni.h 7e9f36434b919cd8b6aa66c61e3910e9f112e252f52d1ac8a9811c52710aefcb
+F ext/jni/src/c/sqlite3-jni.c e4bdcd17e8f8e825f206e1c6ab5adf7f507d70b64b0f795c0cde141077fb68b2
+F ext/jni/src/c/sqlite3-jni.h 91c2eeee22d3594e6652d51edcce0cd94d258a768802fcfac13a78f900127b72
F ext/jni/src/org/sqlite/jni/Authorizer.java 1308988f7f40579ea0e4deeaec3c6be971630566bd021c31367fe3f5140db892
F ext/jni/src/org/sqlite/jni/AutoExtension.java bcc1849b2fccbe5e2d7ac9e9ac7f8d05a6d7088a8fedbaad90e39569745a61e6
F ext/jni/src/org/sqlite/jni/BusyHandler.java 1b1d3e5c86cd796a0580c81b6af6550ad943baa25e47ada0dcca3aff3ebe978c
F ext/jni/src/org/sqlite/jni/RollbackHook.java b04c8abcc6ade44a8a57129e33765793f69df0ba909e49ba18d73f4268d92564
F ext/jni/src/org/sqlite/jni/SQLFunction.java 4d6291fa14fcca1a040609378f9f00a193145d79c3abbda98ba32c340904cbeb
F ext/jni/src/org/sqlite/jni/SQLLog.java c60610b35208416940822e834d61f08fbbe5d6e06b374b541b49e41fd56c9798
-F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 1e791b79e96cc98a37659ea6f578ce595e1a38fb89b05e3560aa28462b283f6d
-F ext/jni/src/org/sqlite/jni/Tester1.java 239eb0133547d4a23317a6dd5bc456172cfb1f2547fd15ba8408871c2776a721
+F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 5fddc34787b26a494dc9843ea2530cd319dc7a6bd369fd4e86dc713f20640fa6
+F ext/jni/src/org/sqlite/jni/Tester1.java e9b82c561ec8771b3e4ea537ebd7c16dd096928b6b8221967a4726104c7c6cb2
F ext/jni/src/org/sqlite/jni/TesterFts5.java 6f135c60e24c89e8eecb9fe61dde0f3bb2906de668ca6c9186bcf34bdaf94629
F ext/jni/src/org/sqlite/jni/Tracer.java a5cece9f947b0af27669b8baec300b6dd7ff859c3e6a6e4a1bd8b50f9714775d
F ext/jni/src/org/sqlite/jni/UpdateHook.java e58645a1727f8a9bbe72dc072ec5b40d9f9362cb0aa24acfe93f49ff56a9016d
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P e8308f0c6ec2d8999c8a2502fb130cb3501ba326f23f71f2cd8d452debae79b5
-R 3d26ad0e6ed454d9e8adb86ee7670851
+P 3f684ef5018116f4be46a07779451c8983ac87a5db182477f71ee7bf28287a04
+R ce1f562cc06444ed73ad1cad9371c48a
U stephan
-Z 11f2caacf45a97bd14e07afe2fb5856c
+Z fbdf5ee5d7ecf00150898b00dcd91489
# Remove this line to create a well-formed Fossil manifest.