1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-12-24 14:17:58 +03:00

More work on the JNI multi-threaded test runner.

FossilOrigin-Name: 9a74ad716bded1e14333bf7c72392916f800d58a96240eabe4988ca5fc9e8752
This commit is contained in:
stephan
2023-08-22 20:10:28 +00:00
parent 87bb103038
commit d1c7216b2f
5 changed files with 101 additions and 50 deletions

View File

@@ -599,8 +599,6 @@ static S3JniGlobalType S3JniGlobal = {};
/*MARKER(("Leaving PerDb mutex@%p %s.\n", env));*/ \
SJG.perDb.locker = 0; \
sqlite3_mutex_leave( SJG.perDb.mutex )
#define MUTEX_PDB_ASSERT_LOCKED \
assert( 0 != SJG.perDb.locker && "Misuse of S3JniGlobal.perDb.mutex" )
#define OOM_CHECK(VAR) if(!(VAR)) s3jni_oom(env)
static inline void s3jni_oom(JNIEnv * const env){
@@ -903,12 +901,12 @@ static void S3JniHook_unref(JNIEnv * const env, S3JniHook * const s, int doXDest
}
/**
Clears s's state and moves it to the free-list.
Clears s's state and moves it to the free-list. Requires that
S3JniGlobal.perDb.mutex be unlocked.
*/
static void S3JniDb_set_aside(S3JniDb * const s){
static void S3JniDb_set_aside(JNIEnv * env, S3JniDb * const s){
if(s){
LocalJniGetEnv;
MUTEX_PDB_ASSERT_LOCKED;
MUTEX_PDB_ENTER;
//MARKER(("state@%p for db@%p setting aside\n", s, s->pDb));
assert(s->pPrev != s);
assert(s->pNext != s);
@@ -938,6 +936,7 @@ static void S3JniDb_set_aside(S3JniDb * const s){
SJG.perDb.aFree = s;
//MARKER(("%p->pPrev@%p, pNext@%p\n", s, s->pPrev, s->pNext));
//if(s->pNext) MARKER(("next: %p->pPrev@%p\n", s->pNext, s->pNext->pPrev));
MUTEX_PDB_LEAVE;
}
}
@@ -1962,10 +1961,8 @@ static jint s3jni_close_db(JNIEnv * const env, jobject jDb, int version){
if(ps){
rc = 1==version ? (jint)sqlite3_close(ps->pDb) : (jint)sqlite3_close_v2(ps->pDb);
if( 0==rc ){
MUTEX_PDB_ENTER;
S3JniDb_set_aside(ps)
S3JniDb_set_aside(env, ps)
/* MUST come after close() because of ps->trace. */;
MUTEX_PDB_LEAVE;
NativePointerHolder_set(env, jDb, 0, &S3NphRefs.sqlite3);
}
}
@@ -2537,9 +2534,7 @@ static int s3jni_open_post(JNIEnv * const env, S3JniEnv * const jc,
assert( ps->pDb == *ppDb /* set up via s3jni_run_java_auto_extensions() */);
}
}else{
MUTEX_PDB_ENTER;
S3JniDb_set_aside(ps);
MUTEX_PDB_LEAVE;
S3JniDb_set_aside(env, ps);
ps = 0;
}
OutputPointer_set_sqlite3(env, jOut, ps ? ps->jDb : 0);
@@ -3306,7 +3301,8 @@ JDECL(jbyteArray,1value_1text16be)(JENV_CSELF, jobject jpSVal){
}
JDECL(void,1do_1something_1for_1developer)(JENV_CSELF){
MARKER(("\nVarious bits of internal info:\n"));
MARKER(("\nVarious bits of internal info:\n"
"Any metrics here are invalid in multi-thread use.\n"));
puts("FTS5 is "
#ifdef SQLITE_ENABLE_FTS5
"available"
@@ -3338,7 +3334,7 @@ JDECL(void,1do_1something_1for_1developer)(JENV_CSELF){
"\n\tenv %u"
"\n\tnph inits %u"
"\n\tperDb %u"
"\n\tautoExt %u container access\n",
"\n\tautoExt %u list accesses\n",
SJG.metrics.nMutexEnv, SJG.metrics.nMutexEnv2,
SJG.metrics.nMutexPerDb, SJG.metrics.nMutexAutoExt);
printf("S3JniDb: %u alloced (*%u = %u bytes), %u recycled\n",

View File

@@ -28,6 +28,6 @@ package org.sqlite.jni;
*/
public class NativePointerHolder<ContextType> {
//! Only set from JNI, where access permissions don't matter.
private long nativePointer = 0;
private volatile long nativePointer = 0;
public final long getNativePointer(){ return nativePointer; }
}

View File

@@ -25,7 +25,9 @@ public class Tester1 implements Runnable {
//! True when running in multi-threaded mode.
private static boolean mtMode = false;
private static boolean takeNaps = false;
private static boolean shuffle = false;
private static boolean listRunTests = false;
private static List<java.lang.reflect.Method> testMethods = null;
private static final class Metrics {
int dbOpen;
}
@@ -159,7 +161,7 @@ public class Tester1 implements Runnable {
return rv;
}
private void testCompileOption(){
private void showCompileOption(){
int i = 0;
String optName;
outln("compile options:");
@@ -1175,31 +1177,41 @@ public class Tester1 implements Runnable {
}
private void runTests(boolean fromThread) throws Exception {
if(false) testCompileOption();
if(false) showCompileOption();
List<java.lang.reflect.Method> mlist = testMethods;
affirm( null!=mlist );
if( shuffle ){
mlist = new ArrayList<>( testMethods.subList(0, testMethods.size()) );
java.util.Collections.shuffle(
mlist
//java.util.concurrent.ThreadLocalRandom.current()
);
}
if( listRunTests ){
synchronized(this.getClass()){
out("Initial test"," list: ");
for(java.lang.reflect.Method m : testMethods){
out(m.getName()+" ");
}
outln();
out("Running"," tests: ");
for(java.lang.reflect.Method m : mlist){
out(m.getName()+" ");
}
outln();
out("(That list excludes some which are hard-coded to run.)\n");
}
}
testToUtf8();
test1();
nap(); testOpenDb1();
nap(); testOpenDb2();
nap(); testCollation();
nap(); testPrepare123();
nap(); testBindFetchInt();
nap(); testBindFetchInt64();
nap(); testBindFetchDouble();
nap(); testBindFetchText();
nap(); testBindFetchBlob();
nap(); testSql();
nap(); testStatus();
nap(); testUdf1();
nap(); testUdfJavaObject();
nap(); testUdfAggregate();
nap(); testUdfWindow();
nap(); testTrace();
nap(); testProgress();
nap(); testCommitHook();
nap(); testRollbackHook();
nap(); testUpdateHook();
nap(); testAuthorizer();
nap(); testAutoExtension();
int n = 0;
for(java.lang.reflect.Method m : mlist){
++n;
nap();
m.invoke(this);
}
affirm( n == mlist.size() );
if(!fromThread){
testBusy();
if( !mtMode ){
@@ -1219,6 +1231,27 @@ public class Tester1 implements Runnable {
}
}
/**
Runs the basic sqlite3 JNI binding sanity-check suite.
CLI flags:
-t|-thread N: runs the tests in N threads
concurrently. Default=1.
-r|-repeat N: repeats the tests in a loop N times, each one
consisting of the -thread value's threads.
-shuffle: randomizes the order of most of the test functions.
-naps: sleep small random intervals between tests in order to add
some chaos for cross-thread contention.
-list-tests: outputs the list of tests being run, minus some
which are hard-coded,
-v: emit some developer-mode info at the end.
*/
public static void main(String[] args) throws Exception {
Integer nThread = null;
boolean doSomethingForDev = false;
@@ -1232,8 +1265,12 @@ public class Tester1 implements Runnable {
//listBoundMethods();
}else if(arg.equals("t") || arg.equals("thread")){
nThread = Integer.parseInt(args[i++]);
}else if(arg.equals("r") || arg.equals("runs")){
}else if(arg.equals("r") || arg.equals("repeat")){
nRepeat = Integer.parseInt(args[i++]);
}else if(arg.equals("shuffle")){
shuffle = true;
}else if(arg.equals("list-tests")){
listRunTests = true;
}else if(arg.equals("naps")){
takeNaps = true;
}else{
@@ -1242,6 +1279,24 @@ public class Tester1 implements Runnable {
}
}
{
// Build list of tests to run from the methods named test*().
testMethods = new ArrayList<>();
final List<String> excludes = new ArrayList<>();
// Tests we want to control the order of:
excludes.add("testSleep");
excludes.add("testToUtf8");
excludes.add("test1");
excludes.add("testBusy");
excludes.add("testFts5");
for(java.lang.reflect.Method m : Tester1.class.getDeclaredMethods()){
final String name = m.getName();
if( name.startsWith("test") && excludes.indexOf(name)<0 ){
testMethods.add(m);
}
}
}
final long timeStart = System.currentTimeMillis();
int nLoop = 0;
outln("libversion_number: ",

View File

@@ -1,5 +1,5 @@
C Disassociate\sJNI\sdb\shandles\sfrom\sthe\sthread\sthat\screated\sthem,\sas\sit's\sno\slonger\srelevant.
D 2023-08-22T18:36:30.981
C More\swork\son\sthe\sJNI\smulti-threaded\stest\srunner.
D 2023-08-22T20:10:28.237
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -235,7 +235,7 @@ F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a3
F ext/jni/GNUmakefile 1ccd09095447709ffd7a4f32514fd586512491c6bed06d009bab4294b451ed62
F ext/jni/README.md 975b35173debbbf3a4ab7166e14d2ffa2bacff9b6850414f09cc919805e81ba4
F ext/jni/jar-dist.make 9a03d10dbb5a74c724bfec4b76fd9e4c9865cbbc858d731cb48f38ac897d73a3
F ext/jni/src/c/sqlite3-jni.c 50edc462e8fdf54f9b8ede692a7c865c5e4315930899276664dd6744764d4723
F ext/jni/src/c/sqlite3-jni.c c38c18875b946a3bdc4eda0b2f19ad53b895118979ec85a630706c1c5575079b
F ext/jni/src/c/sqlite3-jni.h 8b0ab1a3f0f92b75d4ff50db4a88b66a137cfb561268eb15bb3993ed174dbb74
F ext/jni/src/org/sqlite/jni/Authorizer.java 1308988f7f40579ea0e4deeaec3c6be971630566bd021c31367fe3f5140db892
F ext/jni/src/org/sqlite/jni/AutoExtension.java 3b62c915e45ce73f63343ca9195ec63592244d616a1908b7587bdd45de1b97dd
@@ -249,14 +249,14 @@ F ext/jni/src/org/sqlite/jni/Fts5ExtensionApi.java 10cb2e0eb4dc5cf4241a7ccc0442a
F ext/jni/src/org/sqlite/jni/Fts5Function.java 65cde7151e441fee012250a5e03277de7babcd11a0c308a832b7940574259bcc
F ext/jni/src/org/sqlite/jni/Fts5PhraseIter.java 6642beda341c0b1b46af4e2d7f6f9ab03a7aede43277b2c92859176d6bce3be9
F ext/jni/src/org/sqlite/jni/Fts5Tokenizer.java 91489893596b6528c0df5cd7180bd5b55809c26e2b797fb321dfcdbc1298c060
F ext/jni/src/org/sqlite/jni/NativePointerHolder.java 9c5d901cce4f7e57c3d623f4e2476f9f79a8eed6e51b2a603f37866018e040ee
F ext/jni/src/org/sqlite/jni/NativePointerHolder.java 8110d4cfb20884e8ed241de7420c615b040a9f9c441d9cff06f34833399244a8
F ext/jni/src/org/sqlite/jni/OutputPointer.java 464ea85c3eba673a7b575545f69fcd8aeb398477a26d155d88cee3e2459e7802
F ext/jni/src/org/sqlite/jni/ProgressHandler.java 6f62053a828a572de809828b1ee495380677e87daa29a1c57a0e2c06b0a131dc
F ext/jni/src/org/sqlite/jni/ResultCode.java ba701f20213a5f259e94cfbfdd36eb7ac7ce7797f2c6c7fca2004ff12ce20f86
F ext/jni/src/org/sqlite/jni/RollbackHook.java b04c8abcc6ade44a8a57129e33765793f69df0ba909e49ba18d73f4268d92564
F ext/jni/src/org/sqlite/jni/SQLFunction.java 8c1ad92c35bcc1b2f7256cf6e229b31340ed6d1a404d487f0a9adb28ba7fc332
F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 2f36370cfdec01d309720392b2c3e4af6afce0b6ece8188b5c3ed688a5a1e63a
F ext/jni/src/org/sqlite/jni/Tester1.java 58a058f718215ff32fbdf8026a2d4eb88f9d7e939a5640d5a944efafdfda4b7c
F ext/jni/src/org/sqlite/jni/Tester1.java da8bc65f52d310ae17b372eeaef25726be47d3a2052e8a33ce44606a7dc451d7
F ext/jni/src/org/sqlite/jni/TesterFts5.java c729d5b3cb91888b7e2a3a3ef450852f184697df78721574f6c0bf9043e4b84c
F ext/jni/src/org/sqlite/jni/Tracer.java a5cece9f947b0af27669b8baec300b6dd7ff859c3e6a6e4a1bd8b50f9714775d
F ext/jni/src/org/sqlite/jni/UpdateHook.java e58645a1727f8a9bbe72dc072ec5b40d9f9362cb0aa24acfe93f49ff56a9016d
@@ -2092,8 +2092,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 02e868690f97ca728b0f2dd018aa79a9d13c85dd85b164caa895d319ae8f3ff5
R 4fc9fbe1829e4bd8b0e17e9933291453
P 8b78b737e66a399b04e555a8197f63a73198a4105cb2f37ffd5b0e6014302caf
R 31a03bd5ee6de6309ec09a8781691d85
U stephan
Z 9fda786e7e193bbf92304385fbc27c96
Z 973ac484c97d56f1bb0793972fc0262a
# Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
8b78b737e66a399b04e555a8197f63a73198a4105cb2f37ffd5b0e6014302caf
9a74ad716bded1e14333bf7c72392916f800d58a96240eabe4988ca5fc9e8752