An initial attempt at protecting the JNI global state via mutexes at the C level instead of relying on Java's synchronized keyword. It seems to work but increases the run time of the single-threaded batch tester by roughly 3 times.

FossilOrigin-Name: c64e6a52ac79164be37fe643a4a39bd187af198a379410def8b8419f7c2224d4
This commit is contained in:
stephan
2023-08-13 09:53:27 +00:00
parent 0c07549fd6
commit 71e5694cd5
5 changed files with 277 additions and 272 deletions
+137 -132
View File
@@ -498,10 +498,14 @@ static struct {
struct {
S3JniEnvCache * aHead /* Linked list of in-use instances */;
S3JniEnvCache * aFree /* Linked list of free instances */;
sqlite3_mutex * mutex /* mutex for aHead and aFree */;
void const * locker /* env mutex is held on this object's behalf */;
} envCache;
struct {
S3JniDb * aUsed /* Linked list of in-use instances */;
S3JniDb * aFree /* Linked list of free instances */;
sqlite3_mutex * mutex /* mutex for aUsed and aFree */;
void const * locker /* perDb mutex is held on this object's behalf */;
} perDb;
struct {
unsigned nphCacheHits;
@@ -521,21 +525,50 @@ static struct {
#if S3JNI_ENABLE_AUTOEXT
struct {
S3JniAutoExtension *pHead /* Head of the auto-extension list */;
S3JniDb * psOpening /* handle to the being-opened db. We
need this so that auto extensions
can have a consistent view of the
cross-language db connection and
behave property if they call further
db APIs. */;
int isRunning /* True while auto extensions are
running. This is used to prohibit
manipulation of the auto-extension
list while extensions are
running. */;
S3JniDb * psOpening /* FIXME: move into envCache. Handle to the
being-opened db. We need this so that auto
extensions can have a consistent view of
the cross-language db connection and
behave property if they call further db
APIs. */;
int isRunning /* True while auto extensions are
running. This is used to prohibit
manipulation of the auto-extension
list while extensions are
running. */;
} autoExt;
#endif
} S3JniGlobal;
#define MUTEX_ASSERT_LOCKER_ENV \
assert( (env) == S3JniGlobal.envCache.locker && "Misuse of S3JniGlobal.envCache.mutex" )
#define MUTEX_ASSERT_LOCKER_PDB \
assert( 0 != S3JniGlobal.perDb.locker && "Misuse of S3JniGlobal.perDb.mutex" )
#define MUTEX_ASSERT_NOTLOCKER_ENV \
assert( (env) != S3JniGlobal.envCache.locker && "Misuse of S3JniGlobal.envCache.mutex" )
#define MUTEX_ASSERT_NOTLOCKER_PDB \
assert( 0 == S3JniGlobal.perDb.locker && "Misuse of S3JniGlobal.perDb.mutex" )
#define MUTEX_ENTER_ENV \
/*MARKER(("Entering ENV mutex@%p %s.\n", env, __func__));*/ \
MUTEX_ASSERT_NOTLOCKER_ENV; \
sqlite3_mutex_enter( S3JniGlobal.envCache.mutex ); \
S3JniGlobal.envCache.locker = env
#define MUTEX_LEAVE_ENV \
/*MARKER(("Leaving ENV mutex @%p %s.\n", env, __func__));*/ \
MUTEX_ASSERT_LOCKER_ENV; \
S3JniGlobal.envCache.locker = 0; \
sqlite3_mutex_leave( S3JniGlobal.envCache.mutex )
#define MUTEX_ENTER_PDB \
/*MARKER(("Entering PerDb mutex@%p %s.\n", env, __func__));*/ \
MUTEX_ASSERT_NOTLOCKER_PDB; \
sqlite3_mutex_enter( S3JniGlobal.perDb.mutex ); \
S3JniGlobal.perDb.locker = env;
#define MUTEX_LEAVE_PDB \
/*MARKER(("Leaving PerDb mutex@%p %s.\n", env, __func__));*/ \
MUTEX_ASSERT_LOCKER_PDB; \
S3JniGlobal.perDb.locker = 0; \
sqlite3_mutex_leave( S3JniGlobal.perDb.mutex )
#define OOM_CHECK(VAR) if(!(VAR)) s3jni_oom(env)
static void s3jni_oom(JNIEnv * const env){
(*env)->FatalError(env, "Out of memory.") /* does not return */;
@@ -559,12 +592,14 @@ static void * s3jni_malloc(JNIEnv * const env, size_t n){
insofar as possible. Calls (*env)->FatalError() if allocation of
an entry fails. That's hypothetically possible but "shouldn't happen."
*/
FIXME_THREADING(S3JniEnvCache)
static S3JniEnvCache * S3JniGlobal_env_cache(JNIEnv * const env){
struct S3JniEnvCache * row = S3JniGlobal.envCache.aHead;
struct S3JniEnvCache * row;
MUTEX_ENTER_ENV;
row = S3JniGlobal.envCache.aHead;
for( ; row; row = row->pNext ){
if( row->env == env ){
++S3JniGlobal.metrics.envCacheHits;
MUTEX_LEAVE_ENV;
return row;
}
}
@@ -576,11 +611,7 @@ static S3JniEnvCache * S3JniGlobal_env_cache(JNIEnv * const env){
if( row->pNext ) row->pNext->pPrev = 0;
}else{
row = sqlite3_malloc(sizeof(S3JniEnvCache));
if( !row ){
(*env)->FatalError(env, "Maintenance required: S3JniEnvCache is full.")
/* Does not return, but cc doesn't know that */;
return NULL;
}
OOM_CHECK(row);
}
memset(row, 0, sizeof(*row));
row->pNext = S3JniGlobal.envCache.aHead;
@@ -616,11 +647,12 @@ static S3JniEnvCache * S3JniGlobal_env_cache(JNIEnv * const env){
EXCEPTION_IS_FATAL("Error getting reference to StndardCharsets class.");
fUtf8 = (*env)->GetStaticFieldID(env, klazzSC, "UTF_8",
"Ljava/nio/charset/Charset;");
EXCEPTION_IS_FATAL("Error getting StndardCharsets.UTF_8 field.");
EXCEPTION_IS_FATAL("Error getting StandardCharsets.UTF_8 field.");
row->g.oCharsetUtf8 =
REF_G((*env)->GetStaticObjectField(env, klazzSC, fUtf8));
EXCEPTION_IS_FATAL("Error getting reference to StandardCharsets.UTF_8.");
}
MUTEX_LEAVE_ENV;
return row;
}
@@ -765,7 +797,6 @@ static jstring s3jni_text16_to_jstring(JNIEnv * const env, const void * const p,
System.out.println(e.getMessage()); // Hi
}
*/
FIXME_THREADING(S3JniEnvCache)
static char * s3jni_exception_error_msg(JNIEnv * const env, jthrowable jx ){
S3JniEnvCache * const jc = S3JniGlobal_env_cache(env);
jmethodID mid;
@@ -865,10 +896,10 @@ static void S3JniHook_unref(JNIEnv * const env, S3JniHook * const s, int doXDest
/**
Clears s's state and moves it to the free-list.
*/
FIXME_THREADING(perDb)
static void S3JniDb_set_aside(S3JniDb * const s){
if(s){
JNIEnv * const env = s->env;
MUTEX_ASSERT_LOCKER_PDB;
assert(s->pDb && "Else this object is already in the free-list.");
//MARKER(("state@%p for db@%p setting aside\n", s, s->pDb));
assert(s->pPrev != s);
@@ -904,39 +935,16 @@ static void S3JniDb_set_aside(S3JniDb * const s){
//if(s->pNext) MARKER(("next: %p->pPrev@%p\n", s->pNext, s->pNext->pPrev));
}
}
/**
Requires that p has been snipped from any linked list it is
in. Clears all Java refs p holds and zeroes out p.
*/
static void S3JniEnvCache_clear(S3JniEnvCache * const p){
JNIEnv * const env = p->env;
if(env){
int i;
UNREF_G(p->g.cObj);
UNREF_G(p->g.cLong);
UNREF_G(p->g.cString);
UNREF_G(p->g.oCharsetUtf8);
#ifdef SQLITE_ENABLE_FTS5
UNREF_G(p->jFtsExt);
UNREF_G(p->jPhraseIter.klazz);
#endif
for( i = 0; i < NphCache_SIZE; ++i ){
S3JniNphCache_clear(env, &p->nph[i]);
}
memset(p, 0, sizeof(S3JniEnvCache));
}
}
/**
Cleans up all state in S3JniGlobal.perDb for th given JNIEnv.
Results are undefined if a Java-side db uses the API
from the given JNIEnv after this call.
*/
FIXME_THREADING(perDb)
static void S3JniDb_free_for_env(JNIEnv *env){
S3JniDb * ps = S3JniGlobal.perDb.aUsed;
S3JniDb * ps;
S3JniDb * pNext = 0;
MUTEX_ENTER_PDB;
ps = S3JniGlobal.perDb.aUsed;
for( ; ps; ps = pNext ){
pNext = ps->pNext;
if(ps->env == env){
@@ -946,6 +954,7 @@ static void S3JniDb_free_for_env(JNIEnv *env){
pNext = pPrev;
}
}
MUTEX_LEAVE_PDB;
}
/**
@@ -957,35 +966,43 @@ static void S3JniDb_free_for_env(JNIEnv *env){
what would otherwise be stale references.
*/
static int S3JniGlobal_env_uncache(JNIEnv * const env){
struct S3JniEnvCache * row = S3JniGlobal.envCache.aHead;
struct S3JniEnvCache * row;
int i;
assert( 0!=S3JniGlobal.envCache.mutex && "Env mutex misuse.");
row = S3JniGlobal.envCache.aHead;
for( ; row; row = row->pNext ){
if( row->env == env ){
break;
}
}
if( !row ) return 0;
if( !row ){
return 0;
}
if( row->pNext ) row->pNext->pPrev = row->pPrev;
if( row->pPrev ) row->pPrev->pNext = row->pNext;
if( S3JniGlobal.envCache.aHead == row ){
assert( !row->pPrev );
S3JniGlobal.envCache.aHead = row->pNext;
}
S3JniEnvCache_clear(row);
assert( !row->pNext );
assert( !row->pPrev );
S3JniDb_free_for_env(env);
UNREF_G(row->g.cObj);
UNREF_G(row->g.cLong);
UNREF_G(row->g.cString);
UNREF_G(row->g.oCharsetUtf8);
#ifdef SQLITE_ENABLE_FTS5
UNREF_G(row->jFtsExt);
UNREF_G(row->jPhraseIter.klazz);
#endif
for( i = 0; i < NphCache_SIZE; ++i ){
S3JniNphCache_clear(env, &row->nph[i]);
}
memset(row, 0, sizeof(S3JniEnvCache));
row->pNext = S3JniGlobal.envCache.aFree;
if( row->pNext ) row->pNext->pPrev = row;
S3JniGlobal.envCache.aFree = row;
S3JniDb_free_for_env(env);
return 1;
}
static void S3JniGlobal_S3JniEnvCache_clear(void){
while( S3JniGlobal.envCache.aHead ){
S3JniGlobal_env_uncache( S3JniGlobal.envCache.aHead->env );
}
}
/**
Searches the NativePointerHolder cache for the given combination.
If it finds one, it returns it as-is. If it doesn't AND the cache
@@ -1128,14 +1145,15 @@ static void * NativePointerHolder_get(JNIEnv * env, jobject pObj, const char *zC
}
/**
Extracts the new S3JniDb instance from the free-list, or
allocates one if needed, associats it with pDb, and returns.
Returns NULL on OOM. pDb MUST be associated with jDb via
NativePointerHolder_set().
Extracts the new S3JniDb instance from the free-list, or allocates
one if needed, associats it with pDb, and returns. Returns NULL on
OOM. pDb MUST, on success of the calling operation, subsequently be
associated with jDb via NativePointerHolder_set().
*/
static S3JniDb * S3JniDb_alloc(JNIEnv * const env, sqlite3 *pDb,
jobject jDb){
S3JniDb * rv;
MUTEX_ASSERT_LOCKER_PDB;
if(S3JniGlobal.perDb.aFree){
rv = S3JniGlobal.perDb.aFree;
//MARKER(("state@%p for db allocating for db@%p from free-list\n", rv, pDb));
@@ -1185,62 +1203,37 @@ static void S3JniDb_dump(S3JniDb *s){
#endif
/**
Returns the S3JniDb 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.
Returns the S3JniDb object for the given db.
The 3rd and 4th args should normally only be non-0 for
sqlite3_open(_v2)(). For most other cases, they must be 0, in which
case the db handle will be fished out of the jDb object and NULL is
returned if jDb does not have any associated S3JniDb.
The 3rd argument should normally only be non-0 for routines which
are called from the C library and pass a native db handle instead of
a Java handle. In normal usage, the 2nd argument is a Java-side sqlite3
object, from which the db is fished out.
If called with a NULL jDb and non-NULL pDb then allocIfNeeded MUST
be false and it will look for a matching db object. That usage is
required for functions, like sqlite3_context_db_handle(), which
return a (sqlite3*) but do not take one as an argument.
Returns NULL if jDb and pDb are both NULL or if there is no
matching S3JniDb entry for pDb or the pointer fished out of jDb.
*/
FIXME_THREADING(S3JniEnvCache)
FIXME_THREADING(perDb)
static S3JniDb * S3JniDb_for_db(JNIEnv * const env, jobject jDb,
sqlite3 *pDb, int allocIfNeeded){
S3JniDb * s = S3JniGlobal.perDb.aUsed;
if(!jDb){
if(pDb){
assert(!allocIfNeeded);
}else{
return 0;
static S3JniDb * S3JniDb_for_db(JNIEnv * const env, jobject jDb, sqlite3 *pDb){
S3JniDb * s = 0;
if(jDb || pDb){
MUTEX_ENTER_PDB;
s = S3JniGlobal.perDb.aUsed;
if(!pDb){
assert( jDb );
pDb = PtrGet_sqlite3(jDb);
}
}
assert(allocIfNeeded ? !!pDb : 1);
if(!allocIfNeeded && !pDb){
pDb = PtrGet_sqlite3(jDb);
}
for( ; pDb && s; s = s->pNext){
if(s->pDb == pDb) return s;
}
if(allocIfNeeded){
s = S3JniDb_alloc(env, pDb, jDb);
for( ; pDb && s; s = s->pNext){
if(s->pDb == pDb){
break;
}
}
MUTEX_LEAVE_PDB;
}
return s;
}
#if 0
/**
An alternative form which searches for the S3JniDb instance for
pDb with no JNIEnv-specific info. This can be (but _should_ it be?)
called from the context of a separate JNIEnv than the one mapped
to in the returned object. Returns 0 if no match is found.
*/
FIXME_THREADING(perDb)
static S3JniDb * S3JniDb_for_db2(sqlite3 *pDb){
S3JniDb * s = S3JniGlobal.perDb.aUsed;
for( ; pDb && s; s = s->pNext){
if(s->pDb == pDb) return s;
}
return 0;
}
#endif
#if S3JNI_ENABLE_AUTOEXT
/**
Unlink ax from S3JniGlobal.autoExt and free it.
@@ -2048,7 +2041,7 @@ static int s3jni_busy_handler(void* pState, int n){
FIXME_THREADING(S3JniEnvCache)
JDECL(jint,1busy_1handler)(JENV_CSELF, jobject jDb, jobject jBusy){
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0, 0);
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0);
int rc = 0;
if(!ps) return (jint)SQLITE_NOMEM;
if(jBusy){
@@ -2079,7 +2072,7 @@ JDECL(jint,1busy_1handler)(JENV_CSELF, jobject jDb, jobject jBusy){
FIXME_THREADING(S3JniEnvCache)
FIXME_THREADING(perDb)
JDECL(jint,1busy_1timeout)(JENV_CSELF, jobject jDb, jint ms){
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0, 0);
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0);
if( ps ){
S3JniHook_unref(env, &ps->busyHandler, 1);
return sqlite3_busy_timeout(ps->pDb, (int)ms);
@@ -2110,12 +2103,13 @@ static jint s3jni_close_db(JNIEnv * const env, jobject jDb, int version){
int rc = 0;
S3JniDb * ps = 0;
assert(version == 1 || version == 2);
ps = S3JniDb_for_db(env, jDb, 0, 0);
ps = S3JniDb_for_db(env, jDb, 0);
if(ps){
//MARKER(("close()ing db@%p\n", ps->pDb));
rc = 1==version ? (jint)sqlite3_close(ps->pDb) : (jint)sqlite3_close_v2(ps->pDb);
MUTEX_ENTER_PDB;
S3JniDb_set_aside(ps)
/* MUST come after close() because of ps->trace. */;
MUTEX_LEAVE_PDB;
NativePointerHolder_set(env, jDb, 0, S3JniClassNames.sqlite3);
}
return (jint)rc;
@@ -2170,7 +2164,7 @@ static void s3jni_collation_needed_impl16(void *pState, sqlite3 *pDb,
FIXME_THREADING(S3JniEnvCache)
FIXME_THREADING(perDb)
JDECL(jint,1collation_1needed)(JENV_CSELF, jobject jDb, jobject jHook){
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0, 0);
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0);
jclass klazz;
jobject pOld = 0;
jmethodID xCallback;
@@ -2288,7 +2282,7 @@ static void s3jni_rollback_hook_impl(void *pP){
FIXME_THREADING(perDb)
static jobject s3jni_commit_rollback_hook(int isCommit, JNIEnv * const env,jobject jDb,
jobject jHook){
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0, 0);
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0);
jclass klazz;
jobject pOld = 0;
jmethodID xCallback;
@@ -2357,14 +2351,14 @@ JDECL(jboolean,1compileoption_1used)(JENV_CSELF, jstring name){
FIXME_THREADING(perDb)
JDECL(jobject,1context_1db_1handle)(JENV_CSELF, jobject jpCx){
sqlite3 * const pDb = sqlite3_context_db_handle(PtrGet_sqlite3_context(jpCx));
S3JniDb * const ps = pDb ? S3JniDb_for_db(env, 0, pDb, 0) : 0;
S3JniDb * const ps = pDb ? S3JniDb_for_db(env, 0, pDb) : 0;
return ps ? ps->jDb : 0;
}
JDECL(jint,1create_1collation)(JENV_CSELF, jobject jDb,
jstring name, jint eTextRep,
jobject oCollation){
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0, 0);
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0);
jclass klazz;
int rc;
const char *zName;
@@ -2457,7 +2451,7 @@ JDECL(jint,1create_1function)(JENV_CSELF, jobject jDb, jstring jFuncName,
JDECL(int,1db_1config__Lorg_sqlite_jni_sqlite3_2ILjava_lang_String_2)(
JENV_CSELF, jobject jDb, jint op, jstring jStr
){
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0, 0);
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0);
int rc;
char *zStr;
@@ -2489,7 +2483,7 @@ FIXME_THREADING(perDb)
JDECL(jint,1db_1config__Lorg_sqlite_jni_sqlite3_2IILorg_sqlite_jni_OutputPointer_Int32_2)(
JENV_CSELF, jobject jDb, jint op, jint onOff, jobject jOut
){
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0, 0);
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0);
int rc;
switch( ps ? op : 0 ){
case SQLITE_DBCONFIG_ENABLE_FKEY:
@@ -2538,7 +2532,7 @@ JDECL(jint,1db_1config__Lorg_sqlite_jni_sqlite3_2IILorg_sqlite_jni_OutputPointer
}
JDECL(jstring,1db_1filename)(JENV_CSELF, jobject jDb, jstring jDbName){
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0, 0);
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0);
S3JniEnvCache * const jc = S3JniGlobal_env_cache(env);
char *zDbName;
jstring jRv = 0;
@@ -2657,7 +2651,9 @@ static int s3jni_open_pre(JNIEnv * const env, S3JniEnvCache **jc,
*zDbName = 0;
return SQLITE_NOMEM;
}
MUTEX_ENTER_PDB;
*ps = S3JniDb_alloc(env, 0, *jDb);
MUTEX_LEAVE_PDB;
#if S3JNI_ENABLE_AUTOEXT
if(*ps){
assert(!S3JniGlobal.autoExt.psOpening);
@@ -2688,15 +2684,12 @@ static int s3jni_open_post(JNIEnv * const env, S3JniDb * ps,
#endif
if(*ppDb){
assert(ps->jDb);
#if S3JNI_ENABLE_AUTOEXT
//MARKER(("*autoExt.pHead=%p, ppDb=%p, ps->pDb=%p\n", S3JniGlobal.autoExt.pHead, *ppDb, ps->pDb));
// invalid when an autoext triggers another open():
// assert( S3JniGlobal.autoExt.pHead ? *ppDb==ps->pDb : 0==ps->pDb );
#endif
ps->pDb = *ppDb;
NativePointerHolder_set(env, ps->jDb, *ppDb, S3JniClassNames.sqlite3);
}else{
MUTEX_ENTER_PDB;
S3JniDb_set_aside(ps);
MUTEX_LEAVE_PDB;
ps = 0;
}
OutputPointer_set_sqlite3(env, jOut, ps ? ps->jDb : 0);
@@ -2845,7 +2838,7 @@ static int s3jni_progress_handler_impl(void *pP){
}
JDECL(void,1progress_1handler)(JENV_CSELF,jobject jDb, jint n, jobject jProgress){
S3JniDb * ps = S3JniDb_for_db(env, jDb, 0, 0);
S3JniDb * ps = S3JniDb_for_db(env, jDb, 0);
jclass klazz;
jmethodID xCallback;
if( n<1 || !jProgress ){
@@ -3101,7 +3094,7 @@ static int s3jni_xAuth(void* pState, int op,const char*z0, const char*z1,
}
JDECL(jint,1set_1authorizer)(JENV_CSELF,jobject jDb, jobject jHook){
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0, 0);
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0);
S3JniHook * const pHook = ps ? &ps->authHook : 0;
if( !ps ) return SQLITE_MISUSE;
@@ -3195,7 +3188,11 @@ JDECL(jint,1strlike)(JENV_CSELF, jbyteArray baG, jbyteArray baT, jint escChar){
}
JDECL(jint,1shutdown)(JENV_CSELF){
S3JniGlobal_S3JniEnvCache_clear();
MUTEX_ENTER_ENV;
while( S3JniGlobal.envCache.aHead ){
S3JniGlobal_env_uncache( S3JniGlobal.envCache.aHead->env );
}
MUTEX_LEAVE_ENV;
/* Do not clear S3JniGlobal.jvm: it's legal to call
sqlite3_initialize() again to restart the lib. */
return sqlite3_shutdown();
@@ -3279,7 +3276,7 @@ static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){
}
JDECL(jint,1trace_1v2)(JENV_CSELF,jobject jDb, jint traceMask, jobject jTracer){
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0, 0);
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0);
jclass klazz;
if( !traceMask || !jTracer ){
if(ps){
@@ -3330,7 +3327,7 @@ static void s3jni_update_hook_impl(void * pState, int opId, const char *zDb,
JDECL(jobject,1update_1hook)(JENV_CSELF, jobject jDb, jobject jHook){
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0, 0);
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0);
jclass klazz;
jobject pOld = 0;
jmethodID xCallback;
@@ -3635,7 +3632,7 @@ static fts5_api *s3jni_fts5_api_from_db(sqlite3 *db){
}
JDECLFtsApi(jobject,getInstanceForDb)(JENV_CSELF,jobject jDb){
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0, 0);
S3JniDb * const ps = S3JniDb_for_db(env, jDb, 0);
jobject rv = 0;
if(!ps) return 0;
else if(ps->jFtsApi){
@@ -4338,7 +4335,11 @@ Java_org_sqlite_jni_tester_SQLTester_installCustomExtensions(JENV_CSELF){
*/
JNIEXPORT jboolean JNICALL
Java_org_sqlite_jni_SQLite3Jni_uncacheJniEnv(JENV_CSELF){
return S3JniGlobal_env_uncache(env) ? JNI_TRUE : JNI_FALSE;
int rc;
MUTEX_ENTER_ENV;
rc = S3JniGlobal_env_uncache(env);
MUTEX_LEAVE_ENV;
return rc ? JNI_TRUE : JNI_FALSE;
}
/**
@@ -4402,6 +4403,10 @@ Java_org_sqlite_jni_SQLite3Jni_init(JENV_CSELF){
(*env)->FatalError(env, "GetJavaVM() failure shouldn't be possible.");
return;
}
S3JniGlobal.envCache.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
OOM_CHECK( S3JniGlobal.envCache.mutex );
S3JniGlobal.perDb.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
OOM_CHECK( S3JniGlobal.perDb.mutex );
#if 0
/* Just for sanity checking... */
(void)S3JniGlobal_env_cache(env);
+8 -8
View File
@@ -1443,6 +1443,14 @@ JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1text
JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1result_1text64
(JNIEnv *, jclass, jobject, jbyteArray, jlong, jint);
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_shutdown
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1shutdown
(JNIEnv *, jclass);
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_status
@@ -1731,14 +1739,6 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1frombind
JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1value_1subtype
(JNIEnv *, jclass, jobject);
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_shutdown
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1shutdown
(JNIEnv *, jclass);
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_do_something_for_developer
+123 -123
View File
@@ -195,7 +195,7 @@ public final class SQLite3Jni {
Achtung: it is as yet unknown whether auto extensions registered
from one JNIEnv (thread) can be safely called from another.
*/
public static synchronized native int sqlite3_auto_extension(@NotNull AutoExtension callback);
public static native int sqlite3_auto_extension(@NotNull AutoExtension callback);
public static int sqlite3_bind_blob(
@NotNull sqlite3_stmt stmt, int ndx, @Nullable byte[] data
@@ -205,27 +205,27 @@ public final class SQLite3Jni {
: sqlite3_bind_blob(stmt, ndx, data, data.length);
}
private static synchronized native int sqlite3_bind_blob(
private static native int sqlite3_bind_blob(
@NotNull sqlite3_stmt stmt, int ndx, @Nullable byte[] data, int n
);
public static synchronized native int sqlite3_bind_double(
public static native int sqlite3_bind_double(
@NotNull sqlite3_stmt stmt, int ndx, double v
);
public static synchronized native int sqlite3_bind_int(
public static native int sqlite3_bind_int(
@NotNull sqlite3_stmt stmt, int ndx, int v
);
public static synchronized native int sqlite3_bind_int64(
public static native int sqlite3_bind_int64(
@NotNull sqlite3_stmt stmt, int ndx, long v
);
public static synchronized native int sqlite3_bind_null(
public static native int sqlite3_bind_null(
@NotNull sqlite3_stmt stmt, int ndx
);
public static synchronized native int sqlite3_bind_parameter_count(
public static native int sqlite3_bind_parameter_count(
@NotNull sqlite3_stmt stmt
);
@@ -233,7 +233,7 @@ public final class SQLite3Jni {
/** A level of indirection required to ensure that the input to the
C-level function of the same name is a NUL-terminated UTF-8
string. */
private static synchronized native int sqlite3_bind_parameter_index(
private static native int sqlite3_bind_parameter_index(
@NotNull sqlite3_stmt stmt, byte[] paramName
);
@@ -265,15 +265,15 @@ public final class SQLite3Jni {
SQLITE_TRANSIENT for the final parameter and (B) behaves like
sqlite3_bind_null() if the data argument is null.
*/
private static synchronized native int sqlite3_bind_text(
private static native int sqlite3_bind_text(
@NotNull sqlite3_stmt stmt, int ndx, @Nullable byte[] data, int maxBytes
);
public static synchronized native int sqlite3_bind_zeroblob(
public static native int sqlite3_bind_zeroblob(
@NotNull sqlite3_stmt stmt, int ndx, int n
);
public static synchronized native int sqlite3_bind_zeroblob64(
public static native int sqlite3_bind_zeroblob64(
@NotNull sqlite3_stmt stmt, int ndx, long n
);
@@ -283,11 +283,11 @@ public final class SQLite3Jni {
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 synchronized native int sqlite3_busy_handler(
public static native int sqlite3_busy_handler(
@NotNull sqlite3 db, @Nullable BusyHandler handler
);
public static synchronized native int sqlite3_busy_timeout(
public static native int sqlite3_busy_timeout(
@NotNull sqlite3 db, int ms
);
@@ -296,63 +296,63 @@ public final class SQLite3Jni {
effects, if auto extensions are currently running. (The JNI-level
list of extensions cannot be manipulated while it is being traversed.)
*/
public static synchronized native boolean sqlite3_cancel_auto_extension(
public static native boolean sqlite3_cancel_auto_extension(
@NotNull AutoExtension ax
);
public static synchronized native int sqlite3_changes(
public static native int sqlite3_changes(
@NotNull sqlite3 db
);
public static synchronized native long sqlite3_changes64(
public static native long sqlite3_changes64(
@NotNull sqlite3 db
);
public static synchronized native int sqlite3_clear_bindings(
public static native int sqlite3_clear_bindings(
@NotNull sqlite3_stmt stmt
);
public static synchronized native int sqlite3_close(
public static native int sqlite3_close(
@NotNull sqlite3 db
);
public static synchronized native int sqlite3_close_v2(
public static native int sqlite3_close_v2(
@NotNull sqlite3 db
);
public static synchronized native byte[] sqlite3_column_blob(
public static native byte[] sqlite3_column_blob(
@NotNull sqlite3_stmt stmt, int ndx
);
public static synchronized native int sqlite3_column_bytes(
public static native int sqlite3_column_bytes(
@NotNull sqlite3_stmt stmt, int ndx
);
public static synchronized native int sqlite3_column_bytes16(
public static native int sqlite3_column_bytes16(
@NotNull sqlite3_stmt stmt, int ndx
);
public static synchronized native int sqlite3_column_count(
public static native int sqlite3_column_count(
@NotNull sqlite3_stmt stmt
);
public static synchronized native double sqlite3_column_double(
public static native double sqlite3_column_double(
@NotNull sqlite3_stmt stmt, int ndx
);
public static synchronized native int sqlite3_column_int(
public static native int sqlite3_column_int(
@NotNull sqlite3_stmt stmt, int ndx
);
public static synchronized native long sqlite3_column_int64(
public static native long sqlite3_column_int64(
@NotNull sqlite3_stmt stmt, int ndx
);
public static synchronized native String sqlite3_column_name(
public static native String sqlite3_column_name(
@NotNull sqlite3_stmt stmt, int ndx
);
public static synchronized native String sqlite3_column_database_name(
public static native String sqlite3_column_database_name(
@NotNull sqlite3_stmt stmt, int ndx
);
@@ -385,11 +385,11 @@ public final class SQLite3Jni {
return type.isInstance(o) ? (T)o : null;
}
public static synchronized native String sqlite3_column_origin_name(
public static native String sqlite3_column_origin_name(
@NotNull sqlite3_stmt stmt, int ndx
);
public static synchronized native String sqlite3_column_table_name(
public static native String sqlite3_column_table_name(
@NotNull sqlite3_stmt stmt, int ndx
);
@@ -398,7 +398,7 @@ public final class SQLite3Jni {
This API includes no functions for working with Java's Modified
UTF-8.
*/
public static synchronized native String sqlite3_column_text16(
public static native String sqlite3_column_text16(
@NotNull sqlite3_stmt stmt, int ndx
);
@@ -406,7 +406,7 @@ public final class SQLite3Jni {
Returns the given column's contents as UTF-8-encoded (not MUTF-8) text.
Use sqlite3_column_text16() to fetch the text
*/
public static synchronized native byte[] sqlite3_column_text(
public static native byte[] sqlite3_column_text(
@NotNull sqlite3_stmt stmt, int ndx
);
@@ -447,11 +447,11 @@ public final class SQLite3Jni {
// return rv;
// }
public static synchronized native int sqlite3_column_type(
public static native int sqlite3_column_type(
@NotNull sqlite3_stmt stmt, int ndx
);
public static synchronized native sqlite3_value sqlite3_column_value(
public static native sqlite3_value sqlite3_column_value(
@NotNull sqlite3_stmt stmt, int ndx
);
@@ -459,7 +459,7 @@ public final class SQLite3Jni {
This functions like C's sqlite3_collation_needed16() because
Java's string type is compatible with that interface.
*/
public static synchronized native int sqlite3_collation_needed(
public static native int sqlite3_collation_needed(
@NotNull sqlite3 db, @Nullable CollationNeeded callback
);
@@ -467,11 +467,11 @@ public final class SQLite3Jni {
Returns the db handle passed to sqlite3_open() or
sqlite3_open_v2(), as opposed to a new wrapper object.
*/
public static synchronized native sqlite3 sqlite3_context_db_handle(
public static native sqlite3 sqlite3_context_db_handle(
@NotNull sqlite3_context cx
);
public static synchronized native CommitHook sqlite3_commit_hook(
public static native CommitHook sqlite3_commit_hook(
@NotNull sqlite3 db, @Nullable CommitHook hook
);
@@ -483,7 +483,7 @@ public final class SQLite3Jni {
@NotNull String optName
);
public static synchronized native int sqlite3_create_collation(
public static native int sqlite3_create_collation(
@NotNull sqlite3 db, @NotNull String name, int eTextRep,
@NotNull Collation col
);
@@ -496,16 +496,16 @@ public final class SQLite3Jni {
SQLFunction's inner classes (Scalar, Aggregate<T>, and Window<T>)
for details.
*/
public static synchronized native int sqlite3_create_function(
public static native int sqlite3_create_function(
@NotNull sqlite3 db, @NotNull String functionName,
int nArg, int eTextRep, @NotNull SQLFunction func
);
public static synchronized native int sqlite3_data_count(
public static native int sqlite3_data_count(
@NotNull sqlite3_stmt stmt
);
public static synchronized native String sqlite3_db_filename(
public static native String sqlite3_db_filename(
@NotNull sqlite3 db, @NotNull String dbName
);
@@ -514,7 +514,7 @@ public final class SQLite3Jni {
variadic arguments. Returns SQLITE_MISUSE if op is not one of the
SQLITE_DBCONFIG_... options which uses this call form.
*/
public static synchronized native int sqlite3_db_config(
public static native int sqlite3_db_config(
@NotNull sqlite3 db, int op, int onOff, @Nullable OutputPointer.Int32 out
);
@@ -525,37 +525,37 @@ public final class SQLite3Jni {
SQLITE_DBCONFIG_MAINDBNAME, but that set of options may be
extended in future versions.
*/
public static synchronized native int sqlite3_db_config(
public static native int sqlite3_db_config(
@NotNull sqlite3 db, int op, @NotNull String val
);
public static synchronized native int sqlite3_db_status(
public static native int sqlite3_db_status(
@NotNull sqlite3 db, int op, @NotNull OutputPointer.Int32 pCurrent,
@NotNull OutputPointer.Int32 pHighwater, boolean reset
);
public static synchronized native int sqlite3_errcode(@NotNull sqlite3 db);
public static native int sqlite3_errcode(@NotNull sqlite3 db);
public static synchronized native String sqlite3_expanded_sql(@NotNull sqlite3_stmt stmt);
public static native String sqlite3_expanded_sql(@NotNull sqlite3_stmt stmt);
public static synchronized native int sqlite3_extended_errcode(@NotNull sqlite3 db);
public static native int sqlite3_extended_errcode(@NotNull sqlite3 db);
public static synchronized native boolean sqlite3_extended_result_codes(
public static native boolean sqlite3_extended_result_codes(
@NotNull sqlite3 db, boolean onoff
);
public static synchronized native String sqlite3_errmsg(@NotNull sqlite3 db);
public static native String sqlite3_errmsg(@NotNull sqlite3 db);
public static synchronized native String sqlite3_errstr(int resultCode);
public static native String sqlite3_errstr(int resultCode);
/**
Note that the offset values assume UTF-8-encoded SQL.
*/
public static synchronized native int sqlite3_error_offset(@NotNull sqlite3 db);
public static native int sqlite3_error_offset(@NotNull sqlite3 db);
public static synchronized native int sqlite3_finalize(@NotNull sqlite3_stmt stmt);
public static native int sqlite3_finalize(@NotNull sqlite3_stmt stmt);
public static synchronized native int sqlite3_initialize();
public static native int sqlite3_initialize();
/**
Design note/FIXME: we have a problem vis-a-vis 'synchronized'
@@ -576,11 +576,11 @@ public final class SQLite3Jni {
//! See sqlite3_interrupt() for threading concerns.
public static native boolean sqlite3_is_interrupted(@NotNull sqlite3 db);
public static synchronized native long sqlite3_last_insert_rowid(@NotNull sqlite3 db);
public static native long sqlite3_last_insert_rowid(@NotNull sqlite3 db);
public static synchronized native String sqlite3_libversion();
public static native String sqlite3_libversion();
public static synchronized native int sqlite3_libversion_number();
public static native int sqlite3_libversion_number();
/**
Works like its C counterpart and makes the native pointer of the
@@ -601,11 +601,11 @@ public final class SQLite3Jni {
or sqlite3_open_v2() so that they have a predictible object to
pass to, e.g., the sqlite3_collation_needed() callback.
*/
public static synchronized native int sqlite3_open(
public static native int sqlite3_open(
@Nullable String filename, @NotNull OutputPointer.sqlite3 ppDb
);
public static synchronized native int sqlite3_open_v2(
public static native int sqlite3_open_v2(
@Nullable String filename, @NotNull OutputPointer.sqlite3 ppDb,
int flags, @Nullable String zVfs
);
@@ -629,7 +629,7 @@ public final class SQLite3Jni {
necessary, however, and overloads are provided which gloss over
that.
*/
private static synchronized native int sqlite3_prepare(
private static native int sqlite3_prepare(
@NotNull sqlite3 db, @NotNull byte[] sqlUtf8, int maxBytes,
@NotNull OutputPointer.sqlite3_stmt outStmt,
@Nullable OutputPointer.Int32 pTailOffset
@@ -658,7 +658,7 @@ public final class SQLite3Jni {
return sqlite3_prepare(db, utf8, utf8.length, outStmt, null);
}
private static synchronized native int sqlite3_prepare_v2(
private static native int sqlite3_prepare_v2(
@NotNull sqlite3 db, @NotNull byte[] sqlUtf8, int maxBytes,
@NotNull OutputPointer.sqlite3_stmt outStmt,
@Nullable OutputPointer.Int32 pTailOffset
@@ -687,7 +687,7 @@ public final class SQLite3Jni {
return sqlite3_prepare_v2(db, utf8, utf8.length, outStmt, null);
}
private static synchronized native int sqlite3_prepare_v3(
private static native int sqlite3_prepare_v3(
@NotNull sqlite3 db, @NotNull byte[] sqlUtf8, int maxBytes,
int prepFlags, @NotNull OutputPointer.sqlite3_stmt outStmt,
@Nullable OutputPointer.Int32 pTailOffset
@@ -716,22 +716,22 @@ public final class SQLite3Jni {
return sqlite3_prepare_v3(db, utf8, utf8.length, prepFlags, outStmt, null);
}
public static synchronized native void sqlite3_progress_handler(
public static native void sqlite3_progress_handler(
@NotNull sqlite3 db, int n, @Nullable ProgressHandler h
);
//TODO??? void *sqlite3_preupdate_hook(...) and friends
public static synchronized native int sqlite3_reset(@NotNull sqlite3_stmt stmt);
public static native int sqlite3_reset(@NotNull sqlite3_stmt stmt);
/**
Works like the C API except that it has no side effects if auto
extensions are currently running. (The JNI-level list of
extensions cannot be manipulated while it is being traversed.)
*/
public static synchronized native void sqlite3_reset_auto_extension();
public static native void sqlite3_reset_auto_extension();
public static synchronized native void sqlite3_result_double(
public static native void sqlite3_result_double(
@NotNull sqlite3_context cx, double v
);
@@ -742,7 +742,7 @@ public final class SQLite3Jni {
results in the C-level sqlite3_result_error() being called with
a complaint about the invalid argument.
*/
private static synchronized native void sqlite3_result_error(
private static native void sqlite3_result_error(
@NotNull sqlite3_context cx, @Nullable byte[] msg,
int eTextRep
);
@@ -785,27 +785,27 @@ public final class SQLite3Jni {
sqlite3_result_error16(cx, e.getMessage());
}
public static synchronized native void sqlite3_result_error_toobig(
public static native void sqlite3_result_error_toobig(
@NotNull sqlite3_context cx
);
public static synchronized native void sqlite3_result_error_nomem(
public static native void sqlite3_result_error_nomem(
@NotNull sqlite3_context cx
);
public static synchronized native void sqlite3_result_error_code(
public static native void sqlite3_result_error_code(
@NotNull sqlite3_context cx, int c
);
public static synchronized native void sqlite3_result_null(
public static native void sqlite3_result_null(
@NotNull sqlite3_context cx
);
public static synchronized native void sqlite3_result_int(
public static native void sqlite3_result_int(
@NotNull sqlite3_context cx, int v
);
public static synchronized native void sqlite3_result_int64(
public static native void sqlite3_result_int64(
@NotNull sqlite3_context cx, long v
);
@@ -825,7 +825,7 @@ public final class SQLite3Jni {
Note that there is no sqlite3_bind_java_object() counterpart.
*/
public static synchronized native void sqlite3_result_java_object(
public static native void sqlite3_result_java_object(
@NotNull sqlite3_context cx, @NotNull Object o
);
@@ -883,19 +883,19 @@ public final class SQLite3Jni {
sqlite3_result_text(cx, v);
}
public static synchronized native void sqlite3_result_value(
public static native void sqlite3_result_value(
@NotNull sqlite3_context cx, @NotNull sqlite3_value v
);
public static synchronized native void sqlite3_result_zeroblob(
public static native void sqlite3_result_zeroblob(
@NotNull sqlite3_context cx, int n
);
public static synchronized native int sqlite3_result_zeroblob64(
public static native int sqlite3_result_zeroblob64(
@NotNull sqlite3_context cx, long n
);
private static synchronized native void sqlite3_result_blob(
private static native void sqlite3_result_blob(
@NotNull sqlite3_context cx, @Nullable byte[] blob, int maxLen
);
@@ -915,7 +915,7 @@ public final class SQLite3Jni {
If maxLen is larger than blob.length, it is truncated to that
value. If it is negative, results are undefined.
*/
private static synchronized native void sqlite3_result_blob64(
private static native void sqlite3_result_blob64(
@NotNull sqlite3_context cx, @Nullable byte[] blob, long maxLen
);
@@ -925,7 +925,7 @@ public final class SQLite3Jni {
sqlite3_result_blob64(cx, blob, (long)(null==blob ? 0 : blob.length));
}
private static synchronized native void sqlite3_result_text(
private static native void sqlite3_result_text(
@NotNull sqlite3_context cx, @Nullable byte[] text, int maxLen
);
@@ -959,17 +959,23 @@ public final class SQLite3Jni {
text.length, it is silently truncated to text.length. If it is
negative, results are undefined.
*/
private static synchronized native void sqlite3_result_text64(
private static native void sqlite3_result_text64(
@NotNull sqlite3_context cx, @Nullable byte[] text,
long maxLength, int encoding
);
public static synchronized native int sqlite3_status(
/**
Cleans up all per-JNIEnv and per-db state managed by the library
then calls the C-native sqlite3_shutdown().
*/
public static synchronized native int sqlite3_shutdown();
public static native int sqlite3_status(
int op, @NotNull OutputPointer.Int32 pCurrent,
@NotNull OutputPointer.Int32 pHighwater, boolean reset
);
public static synchronized native int sqlite3_status64(
public static native int sqlite3_status64(
int op, @NotNull OutputPointer.Int64 pCurrent,
@NotNull OutputPointer.Int64 pHighwater, boolean reset
);
@@ -1025,32 +1031,32 @@ public final class SQLite3Jni {
sqlite3_result_text64(cx, b, b.length, SQLITE_UTF16BE);
}
public static synchronized native RollbackHook sqlite3_rollback_hook(
public static native RollbackHook sqlite3_rollback_hook(
@NotNull sqlite3 db, @Nullable RollbackHook hook
);
//! Sets or unsets (if auth is null) the current authorizer.
public static synchronized native int sqlite3_set_authorizer(
public static native int sqlite3_set_authorizer(
@NotNull sqlite3 db, @Nullable Authorizer auth
);
public static synchronized native void sqlite3_set_last_insert_rowid(
public static native void sqlite3_set_last_insert_rowid(
@NotNull sqlite3 db, long rowid
);
public static synchronized native int sqlite3_sleep(int ms);
public static native int sqlite3_sleep(int ms);
public static synchronized native String sqlite3_sourceid();
public static native String sqlite3_sourceid();
public static synchronized native String sqlite3_sql(@NotNull sqlite3_stmt stmt);
public static native String sqlite3_sql(@NotNull sqlite3_stmt stmt);
public static synchronized native int sqlite3_step(@NotNull sqlite3_stmt stmt);
public static native int sqlite3_step(@NotNull sqlite3_stmt stmt);
/**
Internal impl of the public sqlite3_strglob() method. Neither argument
may be NULL and both _MUST_ be NUL-terminated.
*/
private static synchronized native int sqlite3_strglob(
private static native int sqlite3_strglob(
@NotNull byte[] glob, @NotNull byte[] txt
);
@@ -1067,7 +1073,7 @@ public final class SQLite3Jni {
Internal impl of the public sqlite3_strlike() method. Neither
argument may be NULL and both _MUST_ be NUL-terminated.
*/
private static synchronized native int sqlite3_strlike(
private static native int sqlite3_strlike(
@NotNull byte[] glob, @NotNull byte[] txt, int escChar
);
@@ -1081,11 +1087,11 @@ public final class SQLite3Jni {
);
}
public static synchronized native int sqlite3_threadsafe();
public static native int sqlite3_threadsafe();
public static synchronized native int sqlite3_total_changes(@NotNull sqlite3 db);
public static native int sqlite3_total_changes(@NotNull sqlite3 db);
public static synchronized native long sqlite3_total_changes64(@NotNull sqlite3 db);
public static native long sqlite3_total_changes64(@NotNull sqlite3 db);
/**
Works like C's sqlite3_trace_v2() except that the 3rd argument to that
@@ -1097,33 +1103,33 @@ public final class SQLite3Jni {
mapping state fails and SQLITE_ERROR if the given callback object
cannot be processed propertly (i.e. an internal error).
*/
public static synchronized native int sqlite3_trace_v2(
public static native int sqlite3_trace_v2(
@NotNull sqlite3 db, int traceMask, @Nullable Tracer tracer
);
public static synchronized native UpdateHook sqlite3_update_hook(
public static native UpdateHook sqlite3_update_hook(
sqlite3 db, UpdateHook hook
);
public static synchronized native byte[] sqlite3_value_blob(@NotNull sqlite3_value v);
public static native byte[] sqlite3_value_blob(@NotNull sqlite3_value v);
public static synchronized native int sqlite3_value_bytes(@NotNull sqlite3_value v);
public static native int sqlite3_value_bytes(@NotNull sqlite3_value v);
public static synchronized native int sqlite3_value_bytes16(@NotNull sqlite3_value v);
public static native int sqlite3_value_bytes16(@NotNull sqlite3_value v);
public static synchronized native double sqlite3_value_double(@NotNull sqlite3_value v);
public static native double sqlite3_value_double(@NotNull sqlite3_value v);
public static synchronized native sqlite3_value sqlite3_value_dupe(
public static native sqlite3_value sqlite3_value_dupe(
@NotNull sqlite3_value v
);
public static synchronized native int sqlite3_value_encoding(@NotNull sqlite3_value v);
public static native int sqlite3_value_encoding(@NotNull sqlite3_value v);
public static synchronized native void sqlite3_value_free(@Nullable sqlite3_value v);
public static native void sqlite3_value_free(@Nullable sqlite3_value v);
public static synchronized native int sqlite3_value_int(@NotNull sqlite3_value v);
public static native int sqlite3_value_int(@NotNull sqlite3_value v);
public static synchronized native long sqlite3_value_int64(@NotNull sqlite3_value v);
public static native long sqlite3_value_int64(@NotNull sqlite3_value v);
/**
If the given value was set using sqlite3_result_java_value() then
@@ -1132,7 +1138,7 @@ public final class SQLite3Jni {
It is up to the caller to inspect the object to determine its
type, and cast it if necessary.
*/
public static synchronized native Object sqlite3_value_java_object(
public static native Object sqlite3_value_java_object(
@NotNull sqlite3_value v
);
@@ -1153,41 +1159,35 @@ public final class SQLite3Jni {
See sqlite3_value_text_utf8() for how to extract text in standard
UTF-8.
*/
public static synchronized native String sqlite3_value_text(@NotNull sqlite3_value v);
public static native String sqlite3_value_text(@NotNull sqlite3_value v);
/**
The sqlite3_value counterpart of sqlite3_column_text_utf8().
*/
public static synchronized native byte[] sqlite3_value_text_utf8(@NotNull sqlite3_value v);
public static native byte[] sqlite3_value_text_utf8(@NotNull sqlite3_value v);
public static synchronized native byte[] sqlite3_value_text16(@NotNull sqlite3_value v);
public static native byte[] sqlite3_value_text16(@NotNull sqlite3_value v);
public static synchronized native byte[] sqlite3_value_text16le(@NotNull sqlite3_value v);
public static native byte[] sqlite3_value_text16le(@NotNull sqlite3_value v);
public static synchronized native byte[] sqlite3_value_text16be(@NotNull sqlite3_value v);
public static native byte[] sqlite3_value_text16be(@NotNull sqlite3_value v);
public static synchronized native int sqlite3_value_type(@NotNull sqlite3_value v);
public static native int sqlite3_value_type(@NotNull sqlite3_value v);
public static synchronized native int sqlite3_value_numeric_type(@NotNull sqlite3_value v);
public static native int sqlite3_value_numeric_type(@NotNull sqlite3_value v);
public static synchronized native int sqlite3_value_nochange(@NotNull sqlite3_value v);
public static native int sqlite3_value_nochange(@NotNull sqlite3_value v);
public static synchronized native int sqlite3_value_frombind(@NotNull sqlite3_value v);
public static native int sqlite3_value_frombind(@NotNull sqlite3_value v);
public static synchronized native int sqlite3_value_subtype(@NotNull sqlite3_value v);
/**
Cleans up all per-JNIEnv and per-db state managed by the library
then calls the C-native sqlite3_shutdown().
*/
public static synchronized native int sqlite3_shutdown();
public static native int sqlite3_value_subtype(@NotNull sqlite3_value v);
/**
This is NOT part of the public API. It exists solely as a place
to hook in arbitrary C-side code during development and testing
of this library.
*/
public static synchronized native void sqlite3_do_something_for_developer();
public static native void sqlite3_do_something_for_developer();
//////////////////////////////////////////////////////////////////////
// SQLITE_... constants follow...
+8 -8
View File
@@ -1,5 +1,5 @@
C Bind\ssqlite3_interrupt()\sand\ssqlite3_is_interrupted()\sto\sJNI\sbut\swith\scaveats\sregarding\smutexing\sof\sthe\sJNIEnv\scache.\sAdd\sa\sloud\swarning\sto\sthe\sJNI\s'dist'\starget\sthat\sit\sshould\sbe\sbuilt\swith\sJDK8\s(a.k.a.\sJava\s1.8)\sfor\scompatibility\sreasons.
D 2023-08-12T23:47:58.408
C An\sinitial\sattempt\sat\sprotecting\sthe\sJNI\sglobal\sstate\svia\smutexes\sat\sthe\sC\slevel\sinstead\sof\srelying\son\sJava's\ssynchronized\skeyword.\sIt\sseems\sto\swork\sbut\sincreases\sthe\srun\stime\sof\sthe\ssingle-threaded\sbatch\stester\sby\sroughly\s3\stimes.
D 2023-08-13T09:53:27.824
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -234,8 +234,8 @@ F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a3
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 1d3bb5113ba4dd7f8645fcc4c669155931e44e234816f528642a738914dd45a4
F ext/jni/src/c/sqlite3-jni.h 11bf3ab9682f5c393e6ac6a3ddb0fdf7b8dd40f7c77f9ef122d3e5c011a5d329
F ext/jni/src/c/sqlite3-jni.c 93fbeed06441352df68f6c0e4bc2cd895e81d8550dc9972cafb30621958b4784
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/BusyHandler.java 1b1d3e5c86cd796a0580c81b6af6550ad943baa25e47ada0dcca3aff3ebe978c
@@ -254,7 +254,7 @@ F ext/jni/src/org/sqlite/jni/ProgressHandler.java 6f62053a828a572de809828b1ee495
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 09ce81c1c637e31c3a830d4c859cce95d65f5e02ff45f8bd1985b3479381bc46
F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 1652af40fc0acb7a140dbe32e3146f980c37c28454b5115a4d0856cbdbc52696
F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 7933fabc267dbfdccb784563d8c404f90275fe9418e8cd6c43c584bc9c57f70f
F ext/jni/src/org/sqlite/jni/Tester1.java fc2ec1f1be58474112b9df8284f0157b64872107f446154c3d0bf1742b924d2b
F ext/jni/src/org/sqlite/jni/TesterFts5.java 59e22dd24af033ea8827d36225a2f3297908fb6af8818ead8850c6c6847557b1
F ext/jni/src/org/sqlite/jni/Tracer.java a5cece9f947b0af27669b8baec300b6dd7ff859c3e6a6e4a1bd8b50f9714775d
@@ -2091,8 +2091,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 48b13edcec6935bf125b265b41a3e6f7b2407afff89d5b4daa2939e3c5679ca0
R 122775c5939e6f1540fadefe535658be
P fbf99a2423dd20e4544bdeea85f714e9368ce3b92fefe97efb39a0fb4a557abe
R 42a3d0d4c63d13c26ffa7bd8f71380ed
U stephan
Z a13d97b8681eef4145a4ab842cd3a9d2
Z 5906c49c68c9155fc27b7d9430c5551e
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
fbf99a2423dd20e4544bdeea85f714e9368ce3b92fefe97efb39a0fb4a557abe
c64e6a52ac79164be37fe643a4a39bd187af198a379410def8b8419f7c2224d4