/**
Initializes a pre-allocated S3JniAutoExtension object. Returns
non-0 if there is an error collecting the required state from
- jAutoExt (which must be an AutoExtension object).
+ jAutoExt (which must be an AutoExtension object). On error, it
+ passes ax to S3JniAutoExtension_clear().
*/
static int S3JniAutoExtension_init(JNIEnv *const env,
S3JniAutoExtension * const ax,
jobject const jAutoExt){
jclass klazz;
klazz = (*env)->GetObjectClass(env, jAutoExt);
+ IFTHREW{
+ EXCEPTION_REPORT;
+ EXCEPTION_CLEAR;
+ assert(!klazz);
+ }
if(!klazz){
S3JniAutoExtension_clear(env, ax);
return SQLITE_ERROR;
for( i = 0; go && 0==rc; ++i ){
S3JniAutoExtension const * ax;
MUTEX_EXT_ENTER;
- if( i >= S3JniGlobal.autoExt.nAlloc ){
+ if( i >= S3JniGlobal.autoExt.nExt ){
ax = 0;
go = 0;
}else{
UNREF_L(ex);
*pzErr = sqlite3_mprintf("auto-extension threw: %s", zMsg);
sqlite3_free(zMsg);
- rc = rc ? rc : SQLITE_ERROR;
+ if( !rc ) rc = SQLITE_ERROR;
}
}
}
int i;
S3JniAutoExtension * ax;
int rc = 0;
- int firstEmptySlot = -1;
if( !jAutoExt ) return SQLITE_MISUSE;
MUTEX_EXT_ENTER;
- for( i = 0; i < S3JniGlobal.autoExt.nAlloc; ++i ){
+ for( i = 0; i < S3JniGlobal.autoExt.nExt; ++i ){
/* Look for match or first empty slot. */
ax = &S3JniGlobal.autoExt.pExt[i];
if( ax->jObj && (*env)->IsSameObject(env, ax->jObj, jAutoExt) ){
MUTEX_EXT_LEAVE;
return 0 /* this as a no-op. */;
- }else if( !ax->jObj && firstEmptySlot<0 ){
- firstEmptySlot = (int)i;
}
}
- if(i == S3JniGlobal.autoExt.nAlloc ){
- if( firstEmptySlot >= 0 ){
- ax = &S3JniGlobal.autoExt.pExt[firstEmptySlot];
- rc = S3JniAutoExtension_init(env, ax, jAutoExt);
- }else{
+ if(i == S3JniGlobal.autoExt.nExt ){
+ assert( S3JniGlobal.autoExt.nExt <= S3JniGlobal.autoExt.nAlloc );
+ if( S3JniGlobal.autoExt.nExt == S3JniGlobal.autoExt.nAlloc ){
unsigned n = 1 + S3JniGlobal.autoExt.nAlloc;
S3JniAutoExtension * const aNew =
sqlite3_realloc( S3JniGlobal.autoExt.pExt,
rc = SQLITE_NOMEM;
}else{
S3JniGlobal.autoExt.pExt = aNew;
- ax = &S3JniGlobal.autoExt.pExt[S3JniGlobal.autoExt.nAlloc];
++S3JniGlobal.autoExt.nAlloc;
- rc = S3JniAutoExtension_init(env, ax, jAutoExt);
- assert( rc ? 0==ax->jObj : 0!=ax->jObj );
}
}
+ if( 0==rc ){
+ ax = &S3JniGlobal.autoExt.pExt[S3JniGlobal.autoExt.nExt];
+ rc = S3JniAutoExtension_init(env, ax, jAutoExt);
+ assert( rc ? 0==ax->jObj : 0!=ax->jObj );
+ }
}
if( 0==rc ){
- ++S3JniGlobal.autoExt.nExt;
if( 0==once && ++once ){
- sqlite3_auto_extension( (void(*)(void))s3jni_run_java_auto_extensions );
+ rc = sqlite3_auto_extension( (void(*)(void))s3jni_run_java_auto_extensions );
+ if( rc ){
+ assert( ax );
+ S3JniAutoExtension_clear(env, ax);
+ }
+ }
+ if( 0==rc ){
+ ++S3JniGlobal.autoExt.nExt;
}
}
MUTEX_EXT_LEAVE;
int i;
MUTEX_EXT_ENTER;
/* This algo mirrors the one in the core. */
- for( i = S3JniGlobal.autoExt.nAlloc-1; i >= 0; --i ){
+ for( i = S3JniGlobal.autoExt.nExt-1; i >= 0; --i ){
ax = &S3JniGlobal.autoExt.pExt[i];
if( ax->jObj && (*env)->IsSameObject(env, ax->jObj, jAutoExt) ){
S3JniAutoExtension_clear(env, ax);
/* Move final entry into this slot. */
- *ax = S3JniGlobal.autoExt.pExt[S3JniGlobal.autoExt.nAlloc - 1];
- memset(&S3JniGlobal.autoExt.pExt[S3JniGlobal.autoExt.nAlloc - 1], 0,
- sizeof(S3JniAutoExtension));
--S3JniGlobal.autoExt.nExt;
+ *ax = S3JniGlobal.autoExt.pExt[S3JniGlobal.autoExt.nExt];
+ memset(&S3JniGlobal.autoExt.pExt[S3JniGlobal.autoExt.nExt], 0,
+ sizeof(S3JniAutoExtension));
+ assert(! S3JniGlobal.autoExt.pExt[S3JniGlobal.autoExt.nExt].jObj );
rc = JNI_TRUE;
break;
}
static void s3jni_reset_auto_extension(JNIEnv *env){
int i;
MUTEX_EXT_ENTER;
- for( i = 0; i < S3JniGlobal.autoExt.nAlloc; ++i ){
+ for( i = 0; i < S3JniGlobal.autoExt.nExt; ++i ){
S3JniAutoExtension_clear( env, &S3JniGlobal.autoExt.pExt[i] );
}
S3JniGlobal.autoExt.nExt = 0;
}
affirm( err!=null );
affirm( err.getMessage().indexOf(toss.value)>0 );
+ toss.value = null;
+
+ val.value = 0;
+ final AutoExtension ax2 = new AutoExtension(){
+ public synchronized int xEntryPoint(sqlite3 db){
+ ++val.value;
+ return 0;
+ }
+ };
+ rc = sqlite3_auto_extension( ax2 );
+ affirm( 0 == rc );
+ sqlite3_close(createNewDb());
+ affirm( 2 == val.value );
affirm( sqlite3_cancel_auto_extension(ax) );
+ affirm( !sqlite3_cancel_auto_extension(ax) );
+ sqlite3_close(createNewDb());
+ affirm( 3 == val.value );
+ rc = sqlite3_auto_extension( ax );
+ affirm( 0 == rc );
+ sqlite3_close(createNewDb());
+ affirm( 5 == val.value );
+ affirm( sqlite3_cancel_auto_extension(ax2) );
+ affirm( !sqlite3_cancel_auto_extension(ax2) );
+ sqlite3_close(createNewDb());
+ affirm( 6 == val.value );
+ rc = sqlite3_auto_extension( ax2 );
+ affirm( 0 == rc );
+ sqlite3_close(createNewDb());
+ affirm( 8 == val.value );
+
+ sqlite3_reset_auto_extension();
+ sqlite3_close(createNewDb());
+ affirm( 8 == val.value );
+ affirm( !sqlite3_cancel_auto_extension(ax) );
+ affirm( !sqlite3_cancel_auto_extension(ax2) );
+ sqlite3_close(createNewDb());
+ affirm( 8 == val.value );
}
private static void testSleep(){
-C Minor\sinternal\sJNI\scleanups\sand\sfixes.
-D 2023-08-17T12:44:52.096
+C Tighten\sup\sthe\sJNI\sauto-ext\shandling.
+D 2023-08-17T13:13:22.545
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/jni/GNUmakefile a9e11b92e620058558cbc1a2d49f8ec53c78d6a989b9db0b7d0b649b9f174881
F ext/jni/README.md 7a614a2fa6c561205f7a53fd8626cf93a7b5711ff454fc1814517f796df398eb
F ext/jni/jar-dist.make f90a553203a57934bf275bed86479485135a52f48ac5c1cfe6499ae07b0b35a4
-F ext/jni/src/c/sqlite3-jni.c 4af91793e92f5d195c8668cf323ca7dfd25549efa9dfc6a0344020da3c42cb4b
+F ext/jni/src/c/sqlite3-jni.c d13cceb21d449d479a7772ad004eeb3a659eebc2759ad22284a7ee6a0a4a9f62
F ext/jni/src/c/sqlite3-jni.h f10d2f38720687c70ecdd5e44f6e8db98efee2caa05fc86b2d9e0c76e6cc0a18
F ext/jni/src/org/sqlite/jni/Authorizer.java 1308988f7f40579ea0e4deeaec3c6be971630566bd021c31367fe3f5140db892
F ext/jni/src/org/sqlite/jni/AutoExtension.java 18e83f6f463e306df60b2dceb65247d32af1f78af4bbbae9155411a8c6cdb093
F ext/jni/src/org/sqlite/jni/RollbackHook.java b04c8abcc6ade44a8a57129e33765793f69df0ba909e49ba18d73f4268d92564
F ext/jni/src/org/sqlite/jni/SQLFunction.java 09ce81c1c637e31c3a830d4c859cce95d65f5e02ff45f8bd1985b3479381bc46
F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 99334f54f5f41feb4c14dc988b93219e37799e032f2bc07bda6323b1dfb99e75
-F ext/jni/src/org/sqlite/jni/Tester1.java f2f8fa157ddc42f91b6102d7ed78d1045d5072ae702bcefd868984518c97f9ae
+F ext/jni/src/org/sqlite/jni/Tester1.java 68b88b3098ce60134f4298488f890871398a77477af0a1b21797c59c911060c1
F ext/jni/src/org/sqlite/jni/TesterFts5.java 59e22dd24af033ea8827d36225a2f3297908fb6af8818ead8850c6c6847557b1
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 154ab26dc6ba2d1fd976e8fe6dc1b1a06c734f7e9a276a3edc5c2f30b0d6d36a
-R b13f61ed94c6ec470e8a131c5363f0b3
+P 0e9437de026cbfb333b90bb3400f1c015f85d49d73a25ad1000623216b88bfa0
+R 9c230dc36749890d5273d4c55c46fd59
U stephan
-Z c23fb72e5b16d04504744e0f8c1cbcfd
+Z d4ea42705a0c21f8fa4c587cb8cbbc10
# Remove this line to create a well-formed Fossil manifest.