diff options
author | stephan <stephan@noemail.net> | 2023-11-15 04:55:38 +0000 |
---|---|---|
committer | stephan <stephan@noemail.net> | 2023-11-15 04:55:38 +0000 |
commit | d7ef0e8f87fd5dcff55f14a95a3d3dc9a59c1d9c (patch) | |
tree | 79c13a05de1d24d3481b13bfb5844f23b1e9aeac /ext/jni/src | |
parent | 253727b33d78443e53f4b6f3ec5ffa7d879e082a (diff) | |
download | sqlite-d7ef0e8f87fd5dcff55f14a95a3d3dc9a59c1d9c.tar.gz sqlite-d7ef0e8f87fd5dcff55f14a95a3d3dc9a59c1d9c.zip |
JNI: add CONFIG_LOG and CONFIG_SQLLOG support to wrapper1. Code-adjacent cleanups.
FossilOrigin-Name: 83c49b9e71e5ae8852bab60a6fa630e22164c8efbf074c85450136781d0fffd3
Diffstat (limited to 'ext/jni/src')
-rw-r--r-- | ext/jni/src/c/sqlite3-jni.h | 2 | ||||
-rw-r--r-- | ext/jni/src/org/sqlite/jni/capi/CApi.java | 6 | ||||
-rw-r--r-- | ext/jni/src/org/sqlite/jni/capi/ConfigSqlLogCallback.java (renamed from ext/jni/src/org/sqlite/jni/capi/ConfigSqllogCallback.java) | 4 | ||||
-rw-r--r-- | ext/jni/src/org/sqlite/jni/capi/Tester1.java | 4 | ||||
-rw-r--r-- | ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java | 114 | ||||
-rw-r--r-- | ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java | 64 |
6 files changed, 135 insertions, 59 deletions
diff --git a/ext/jni/src/c/sqlite3-jni.h b/ext/jni/src/c/sqlite3-jni.h index f691197f8..082a20212 100644 --- a/ext/jni/src/c/sqlite3-jni.h +++ b/ext/jni/src/c/sqlite3-jni.h @@ -1300,7 +1300,7 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1config_1_1CONFIG_1 /* * Class: org_sqlite_jni_capi_CApi * Method: sqlite3_config__SQLLOG - * Signature: (Lorg/sqlite/jni/capi/ConfigSqllogCallback;)I + * Signature: (Lorg/sqlite/jni/capi/ConfigSqlLogCallback;)I */ JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1config_1_1SQLLOG (JNIEnv *, jclass, jobject); diff --git a/ext/jni/src/org/sqlite/jni/capi/CApi.java b/ext/jni/src/org/sqlite/jni/capi/CApi.java index 59d025b96..9f1daa4a2 100644 --- a/ext/jni/src/org/sqlite/jni/capi/CApi.java +++ b/ext/jni/src/org/sqlite/jni/capi/CApi.java @@ -1052,10 +1052,10 @@ public final class CApi { ); /** - Internal level of indirection for sqlite3_config(ConfigSqllogCallback). + Internal level of indirection for sqlite3_config(ConfigSqlLogCallback). */ private static native int sqlite3_config__SQLLOG( - @Nullable ConfigSqllogCallback logger + @Nullable ConfigSqlLogCallback logger ); /** @@ -1091,7 +1091,7 @@ public final class CApi { the rest of the library. This must not be called when any other library APIs are being called. */ - public static int sqlite3_config( @Nullable ConfigSqllogCallback logger ){ + public static int sqlite3_config( @Nullable ConfigSqlLogCallback logger ){ return sqlite3_config__SQLLOG(logger); } diff --git a/ext/jni/src/org/sqlite/jni/capi/ConfigSqllogCallback.java b/ext/jni/src/org/sqlite/jni/capi/ConfigSqlLogCallback.java index df753e651..a5530b49a 100644 --- a/ext/jni/src/org/sqlite/jni/capi/ConfigSqllogCallback.java +++ b/ext/jni/src/org/sqlite/jni/capi/ConfigSqlLogCallback.java @@ -16,10 +16,10 @@ package org.sqlite.jni.capi; /** A callback for use with sqlite3_config(). */ -public interface ConfigSqllogCallback { +public interface ConfigSqlLogCallback { /** Must function as described for a C-level callback for - {@link CApi#sqlite3_config(ConfigSqllogCallback)}, with the slight signature change. + {@link CApi#sqlite3_config(ConfigSqlLogCallback)}, with the slight signature change. */ void call(sqlite3 db, String msg, int msgType ); } diff --git a/ext/jni/src/org/sqlite/jni/capi/Tester1.java b/ext/jni/src/org/sqlite/jni/capi/Tester1.java index 3ff93a9ce..d21d75e3b 100644 --- a/ext/jni/src/org/sqlite/jni/capi/Tester1.java +++ b/ext/jni/src/org/sqlite/jni/capi/Tester1.java @@ -2007,7 +2007,7 @@ public class Tester1 implements Runnable { if( sqlLog ){ if( sqlite3_compileoption_used("ENABLE_SQLLOG") ){ - final ConfigSqllogCallback log = new ConfigSqllogCallback() { + final ConfigSqlLogCallback log = new ConfigSqlLogCallback() { @Override public void call(sqlite3 db, String msg, int op){ switch(op){ case 0: outln("Opening db: ",db); break; @@ -2018,7 +2018,7 @@ public class Tester1 implements Runnable { }; int rc = sqlite3_config( log ); affirm( 0==rc ); - rc = sqlite3_config( (ConfigSqllogCallback)null ); + rc = sqlite3_config( (ConfigSqlLogCallback)null ); affirm( 0==rc ); rc = sqlite3_config( log ); affirm( 0==rc ); diff --git a/ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java b/ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java index 0b18676b4..5dbf79466 100644 --- a/ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java +++ b/ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java @@ -209,6 +209,10 @@ public final class Sqlite implements AutoCloseable { public static final int DBCONFIG_STMT_SCANSTATUS = CApi.SQLITE_DBCONFIG_STMT_SCANSTATUS; public static final int DBCONFIG_REVERSE_SCANORDER = CApi.SQLITE_DBCONFIG_REVERSE_SCANORDER; + public static final int CONFIG_SINGLETHREAD = CApi.SQLITE_CONFIG_SINGLETHREAD; + public static final int CONFIG_MULTITHREAD = CApi.SQLITE_CONFIG_MULTITHREAD; + public static final int CONFIG_SERIALIZED = CApi.SQLITE_CONFIG_SERIALIZED; + public static final int UTF8 = CApi.SQLITE_UTF8; public static final int UTF16 = CApi.SQLITE_UTF16; public static final int UTF16LE = CApi.SQLITE_UTF16LE; @@ -261,6 +265,32 @@ public final class Sqlite implements AutoCloseable { private static final java.util.Map<org.sqlite.jni.capi.sqlite3, Sqlite> nativeToWrapper = new java.util.HashMap<>(); + + /** + When any given thread is done using the SQLite library, calling + this will free up any native-side resources which may be + associated specifically with that thread. This is not strictly + necessary, in particular in applications which only use SQLite + from a single thread, but may help free some otherwise errant + resources. + + Calling into SQLite from a given thread after this has been + called in that thread is harmless. The library will simply start + to re-cache certain state for that thread. + + Contrariwise, failing to call this will effectively leak a small + amount of cached state for the thread, which may add up to + significant amounts if the application uses SQLite from many + threads. + + This must never be called while actively using SQLite from this + thread, e.g. from within a query loop or a callback which is + operating on behalf of the library. + */ + static void uncacheThread(){ + CApi.sqlite3_java_uncache_thread(); + } + /** Returns the Sqlite object associated with the given sqlite3 object, or null if there is no such mapping. @@ -342,6 +372,9 @@ public final class Sqlite implements AutoCloseable { private static boolean hasNormalizeSql = compileOptionUsed("ENABLE_NORMALIZE"); + private static boolean hasSqlLog = + compileOptionUsed("ENABLE_SQLLOG"); + /** Throws UnsupportedOperationException if check is false. flag is expected to be the name of an SQLITE_ENABLE_... @@ -410,7 +443,7 @@ public final class Sqlite implements AutoCloseable { new org.sqlite.jni.capi.OutputPointer.Int64(); org.sqlite.jni.capi.OutputPointer.Int64 pHighwater = new org.sqlite.jni.capi.OutputPointer.Int64(); - checkRc2( CApi.sqlite3_status64(op, pCurrent, pHighwater, resetStats) ); + checkRcStatic( CApi.sqlite3_status64(op, pCurrent, pHighwater, resetStats) ); final Status s = new Status(); s.current = pCurrent.value; s.peak = pHighwater.value; @@ -489,7 +522,7 @@ public final class Sqlite implements AutoCloseable { Like checkRc() but behaves as if that function were called with a null db object. */ - private static void checkRc2(int rc){ + private static void checkRcStatic(int rc){ if( 0!=rc ){ if( CApi.SQLITE_NOMEM==rc ){ throw new OutOfMemoryError(); @@ -1859,4 +1892,81 @@ public final class Sqlite implements AutoCloseable { return new Blob(this, out.take()); } + /** + Callback for use with libConfigLog(). + */ + public interface ConfigLog { + /** + Must function as described for a C-level callback for + sqlite3_config()'s SQLITE_CONFIG_LOG callback, with the slight + signature change. Any exceptions thrown from this callback are + necessarily suppressed. + */ + void call(int errCode, String msg); + } + + /** + Analog to sqlite3_config() with the SQLITE_CONFIG_LOG option, + this sets or (if log is null) clears the current logger. + */ + public static void libConfigLog(ConfigLog log){ + final org.sqlite.jni.capi.ConfigLogCallback l = + null==log + ? null + : new org.sqlite.jni.capi.ConfigLogCallback() { + @Override public void call(int errCode, String msg){ + log.call(errCode, msg); + } + }; + checkRcStatic(CApi.sqlite3_config(l)); + } + + /** + Callback for use with libConfigSqlLog(). + */ + public interface ConfigSqlLog { + /** + Must function as described for a C-level callback for + sqlite3_config()'s SQLITE_CONFIG_SQLLOG callback, with the + slight signature change. Any exceptions thrown from this + callback are necessarily suppressed. + */ + void call(Sqlite db, String msg, int msgType); + } + + /** + Analog to sqlite3_config() with the SQLITE_CONFIG_SQLLOG option, + this sets or (if log is null) clears the current logger. + + If SQLite is built without SQLITE_ENABLE_SQLLOG defined then this + will throw an UnsupportedOperationException. + */ + public static void libConfigSqlLog(ConfigSqlLog log){ + Sqlite.checkSupported(hasNormalizeSql, "SQLITE_ENABLE_SQLLOG"); + final org.sqlite.jni.capi.ConfigSqlLogCallback l = + null==log + ? null + : new org.sqlite.jni.capi.ConfigSqlLogCallback() { + @Override public void call(sqlite3 db, String msg, int msgType){ + try{ + log.call(fromNative(db), msg, msgType); + }catch(Exception e){ + /* Suppressed */ + } + } + }; + checkRcStatic(CApi.sqlite3_config(l)); + } + + /** + Analog to the C-level sqlite3_config() with one of the + SQLITE_CONFIG_... constants defined as CONFIG_... in this + class. Throws on error, including passing of an unknown option or + if a specified option is not supported by the underlying build of + the SQLite library. + */ + public static void libConfigOp( int op ){ + checkRcStatic(CApi.sqlite3_config(op)); + } + } diff --git a/ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java b/ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java index e6b665fcc..681712f96 100644 --- a/ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java +++ b/ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java @@ -762,9 +762,9 @@ public class Tester2 implements Runnable { affirm( newHook == oldHook ); execSql(db, "BEGIN; update t set a='i' where a='h'; COMMIT;"); affirm( 5 == counter.value ); - hookResult.value = CApi.SQLITE_ERROR; + hookResult.value = Sqlite.ERROR; int rc = execSql(db, false, "BEGIN; update t set a='j' where a='i'; COMMIT;"); - affirm( CApi.SQLITE_CONSTRAINT_COMMITHOOK == rc ); + affirm( Sqlite.CONSTRAINT_COMMITHOOK == rc ); affirm( 6 == counter.value ); db.close(); } @@ -994,8 +994,7 @@ public class Tester2 implements Runnable { listErrors.add(e); } }finally{ - affirm( CApi.sqlite3_java_uncache_thread() ); - affirm( !CApi.sqlite3_java_uncache_thread() ); + Sqlite.uncacheThread(); } } @@ -1068,38 +1067,28 @@ public class Tester2 implements Runnable { if( sqlLog ){ if( Sqlite.compileOptionUsed("ENABLE_SQLLOG") ){ - final ConfigSqllogCallback log = new ConfigSqllogCallback() { - @Override public void call(sqlite3 db, String msg, int op){ + Sqlite.libConfigSqlLog( new Sqlite.ConfigSqlLog() { + @Override public void call(Sqlite db, String msg, int op){ switch(op){ case 0: outln("Opening db: ",db); break; case 1: outln("SQL ",db,": ",msg); break; case 2: outln("Closing db: ",db); break; } } - }; - int rc = CApi.sqlite3_config( log ); - affirm( 0==rc ); - rc = CApi.sqlite3_config( (ConfigSqllogCallback)null ); - affirm( 0==rc ); - rc = CApi.sqlite3_config( log ); - affirm( 0==rc ); + } + ); }else{ outln("WARNING: -sqllog is not active because library was built ", "without SQLITE_ENABLE_SQLLOG."); } } if( configLog ){ - final ConfigLogCallback log = new ConfigLogCallback() { + Sqlite.libConfigLog( new Sqlite.ConfigLog() { @Override public void call(int code, String msg){ - outln("ConfigLogCallback: ",ResultCode.getEntryForInt(code),": ", msg); + outln("ConfigLog: ",Sqlite.errstr(code),": ", msg); }; - }; - int rc = CApi.sqlite3_config( log ); - affirm( 0==rc ); - rc = CApi.sqlite3_config( (ConfigLogCallback)null ); - affirm( 0==rc ); - rc = CApi.sqlite3_config( log ); - affirm( 0==rc ); + } + ); } quietMode = squelchTestOutput; @@ -1132,39 +1121,16 @@ public class Tester2 implements Runnable { } final long timeStart = System.currentTimeMillis(); - int nLoop = 0; - switch( CApi.sqlite3_threadsafe() ){ /* Sanity checking */ - case 0: - affirm( CApi.SQLITE_ERROR==CApi.sqlite3_config( CApi.SQLITE_CONFIG_SINGLETHREAD ), - "Could not switch to single-thread mode." ); - affirm( CApi.SQLITE_ERROR==CApi.sqlite3_config( CApi.SQLITE_CONFIG_MULTITHREAD ), - "Could switch to multithread mode." ); - affirm( CApi.SQLITE_ERROR==CApi.sqlite3_config( CApi.SQLITE_CONFIG_SERIALIZED ), - "Could not switch to serialized threading mode." ); - outln("This is a single-threaded build. Not using threads."); - nThread = 1; - break; - case 1: - case 2: - affirm( 0==CApi.sqlite3_config( CApi.SQLITE_CONFIG_SINGLETHREAD ), - "Could not switch to single-thread mode." ); - affirm( 0==CApi.sqlite3_config( CApi.SQLITE_CONFIG_MULTITHREAD ), - "Could not switch to multithread mode." ); - affirm( 0==CApi.sqlite3_config( CApi.SQLITE_CONFIG_SERIALIZED ), - "Could not switch to serialized threading mode." ); - break; - default: - affirm( false, "Unhandled SQLITE_THREADSAFE value." ); - } outln("libversion_number: ", - CApi.sqlite3_libversion_number(),"\n", - CApi.sqlite3_libversion(),"\n",CApi.SQLITE_SOURCE_ID,"\n", + Sqlite.libVersionNumber(),"\n", + Sqlite.libVersion(),"\n",Sqlite.libSourceId(),"\n", "SQLITE_THREADSAFE=",CApi.sqlite3_threadsafe()); final boolean showLoopCount = (nRepeat>1 && nThread>1); if( showLoopCount ){ outln("Running ",nRepeat," loop(s) with ",nThread," thread(s) each."); } if( takeNaps ) outln("Napping between tests is enabled."); + int nLoop = 0; for( int n = 0; n < nRepeat; ++n ){ ++nLoop; if( showLoopCount ) out((1==nLoop ? "" : " ")+nLoop); @@ -1206,7 +1172,7 @@ public class Tester2 implements Runnable { if( doSomethingForDev ){ CApi.sqlite3_jni_internal_details(); } - affirm( 0==CApi.sqlite3_release_memory(1) ); + affirm( 0==Sqlite.libReleaseMemory(1) ); CApi.sqlite3_shutdown(); int nMethods = 0; int nNatives = 0; |