mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Make JNI sqlite3_trace_v2() thread-safe. Re-add a piece removed in [bae4d022aad9b] to work around a JVM crash which is unpredictably triggered by its substitute. Fix the THREADMODE=0 JNI build. Further internal API simplifications.
FossilOrigin-Name: 3f9f7a9cb08b0687ad206605a5109306762df9ae8bdeab2d8d60bf9373c9ad32
This commit is contained in:
@ -297,9 +297,12 @@ tests: tester
|
|||||||
########################################################################
|
########################################################################
|
||||||
# Build each SQLITE_THREADMODE variant and run all tests against them.
|
# Build each SQLITE_THREADMODE variant and run all tests against them.
|
||||||
multitest: clean
|
multitest: clean
|
||||||
$(MAKE) opt.threadsafe=0 tests clean
|
$(MAKE) opt.threadsafe=0 opt.oom=1 tests clean
|
||||||
$(MAKE) opt.threadsafe=1 tests clean
|
$(MAKE) opt.threadsafe=0 opt.oom=0 tests clean
|
||||||
$(MAKE) opt.threadsafe=2 tests clean
|
$(MAKE) opt.threadsafe=1 opt.oom=1 tests clean
|
||||||
|
$(MAKE) opt.threadsafe=1 opt.oom=0 tests clean
|
||||||
|
$(MAKE) opt.threadsafe=2 opt.oom=1 tests clean
|
||||||
|
$(MAKE) opt.threadsafe=2 opt.oom=0 tests clean
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
@ -404,9 +404,8 @@ struct S3JniHook{
|
|||||||
/* We lookup the jObj.xDestroy() method as-needed for contexts which
|
/* We lookup the jObj.xDestroy() method as-needed for contexts which
|
||||||
** have custom finalizers. */
|
** have custom finalizers. */
|
||||||
};
|
};
|
||||||
#if !defined(SQLITE_ENABLE_PREUPDATE_HOOK) || defined(SQLITE_ENABLE_SQLLOG)
|
/* For clean bitwise-copy init of local instances. */
|
||||||
static const S3JniHook S3JniHook_empty = {0,0};
|
static const S3JniHook S3JniHook_empty = {0,0};
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Per-(sqlite3*) state for various JNI bindings. This state is
|
** Per-(sqlite3*) state for various JNI bindings. This state is
|
||||||
@ -456,10 +455,10 @@ struct S3JniEnv {
|
|||||||
JNIEnv *env /* env in which this cache entry was created */;
|
JNIEnv *env /* env in which this cache entry was created */;
|
||||||
/*
|
/*
|
||||||
** pdbOpening is used to coordinate the Java/DB connection of a
|
** pdbOpening is used to coordinate the Java/DB connection of a
|
||||||
** being-open()'d db in the face of auto-extensions. "The problem"
|
** being-open()'d db in the face of auto-extensions.
|
||||||
** is that auto-extensions run before we can bind the C db to its
|
** Auto-extensions run before we can bind the C db to its Java
|
||||||
** Java representation, but auto-extensions require that binding. We
|
** representation, but auto-extensions require that binding to pass
|
||||||
** handle this as follows:
|
** on to their Java-side callbacks. We handle this as follows:
|
||||||
**
|
**
|
||||||
** - In the JNI side of sqlite3_open(), allocate the Java side of
|
** - In the JNI side of sqlite3_open(), allocate the Java side of
|
||||||
** that connection and set pdbOpening to point to that
|
** that connection and set pdbOpening to point to that
|
||||||
@ -497,8 +496,8 @@ enum UDFType {
|
|||||||
UDF_WINDOW
|
UDF_WINDOW
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/*
|
||||||
State for binding Java-side UDFs.
|
** State for binding Java-side UDFs.
|
||||||
*/
|
*/
|
||||||
typedef struct S3JniUdf S3JniUdf;
|
typedef struct S3JniUdf S3JniUdf;
|
||||||
struct S3JniUdf {
|
struct S3JniUdf {
|
||||||
@ -506,11 +505,11 @@ struct S3JniUdf {
|
|||||||
char * zFuncName /* Only for error reporting and debug logging */;
|
char * zFuncName /* Only for error reporting and debug logging */;
|
||||||
enum UDFType type;
|
enum UDFType type;
|
||||||
/** Method IDs for the various UDF methods. */
|
/** Method IDs for the various UDF methods. */
|
||||||
jmethodID jmidxFunc /* Java ID of xFunc method */;
|
jmethodID jmidxFunc /* xFunc method */;
|
||||||
jmethodID jmidxStep /* Java ID of xStep method */;
|
jmethodID jmidxStep /* xStep method */;
|
||||||
jmethodID jmidxFinal /* Java ID of xFinal method */;
|
jmethodID jmidxFinal /* xFinal method */;
|
||||||
jmethodID jmidxValue /* Java ID of xValue method */;
|
jmethodID jmidxValue /* xValue method */;
|
||||||
jmethodID jmidxInverse /* Java ID of xInverse method */;
|
jmethodID jmidxInverse /* xInverse method */;
|
||||||
S3JniUdf * pNext /* Next entry in SJG.udf.aFree. */;
|
S3JniUdf * pNext /* Next entry in SJG.udf.aFree. */;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -592,6 +591,7 @@ struct S3JniGlobalType {
|
|||||||
** and never released.
|
** and never released.
|
||||||
*/
|
*/
|
||||||
struct {
|
struct {
|
||||||
|
jclass cObj /* global ref to java.lang.Object */;
|
||||||
jclass cLong /* global ref to java.lang.Long */;
|
jclass cLong /* global ref to java.lang.Long */;
|
||||||
jclass cString /* global ref to java.lang.String */;
|
jclass cString /* global ref to java.lang.String */;
|
||||||
jobject oCharsetUtf8 /* global ref to StandardCharset.UTF_8 */;
|
jobject oCharsetUtf8 /* global ref to StandardCharset.UTF_8 */;
|
||||||
@ -729,10 +729,10 @@ static void s3jni_incr( volatile unsigned int * const p ){
|
|||||||
SJG.autoExt.locker = env; \
|
SJG.autoExt.locker = env; \
|
||||||
s3jni_incr( &SJG.metrics.nMutexAutoExt )
|
s3jni_incr( &SJG.metrics.nMutexAutoExt )
|
||||||
#define S3JniMutex_Ext_leave \
|
#define S3JniMutex_Ext_leave \
|
||||||
assert( env == SJG.autoExt.locker ); \
|
assert( env == SJG.autoExt.locker && "Misuse of S3JniGlobal.autoExt.mutex" ); \
|
||||||
sqlite3_mutex_leave( SJG.autoExt.mutex )
|
sqlite3_mutex_leave( SJG.autoExt.mutex )
|
||||||
#define S3JniMutex_Ext_assertLocker \
|
#define S3JniMutex_Ext_assertLocker \
|
||||||
assert( env == SJG.autoExt.locker )
|
assert( env == SJG.autoExt.locker && "Misuse of S3JniGlobal.autoExt.mutex" )
|
||||||
|
|
||||||
#define S3JniMutex_Global_enter \
|
#define S3JniMutex_Global_enter \
|
||||||
sqlite3_mutex_enter( SJG.mutex ); \
|
sqlite3_mutex_enter( SJG.mutex ); \
|
||||||
@ -775,6 +775,7 @@ static void s3jni_incr( volatile unsigned int * const p ){
|
|||||||
#define S3JniMutex_Global_leave
|
#define S3JniMutex_Global_leave
|
||||||
#define S3JniMutex_Nph_enter
|
#define S3JniMutex_Nph_enter
|
||||||
#define S3JniMutex_Nph_leave
|
#define S3JniMutex_Nph_leave
|
||||||
|
#define S3JniMutex_S3JniDb_assertLocker
|
||||||
#define S3JniMutex_S3JniDb_enter
|
#define S3JniMutex_S3JniDb_enter
|
||||||
#define S3JniMutex_S3JniDb_leave
|
#define S3JniMutex_S3JniDb_leave
|
||||||
#endif
|
#endif
|
||||||
@ -1090,8 +1091,8 @@ static void s3jni_call_xDestroy(JNIEnv * const env, jobject jObj){
|
|||||||
** cleared. It is legal to call this when the object has no Java
|
** cleared. It is legal to call this when the object has no Java
|
||||||
** references.
|
** references.
|
||||||
*/
|
*/
|
||||||
static void S3JniHook_unref(JNIEnv * const env, S3JniHook * const s,
|
static void S3JniHook_unref_impl(JNIEnv * const env, S3JniHook * const s,
|
||||||
int doXDestroy){
|
int doXDestroy){
|
||||||
if( s->jObj ){
|
if( s->jObj ){
|
||||||
if( doXDestroy ){
|
if( doXDestroy ){
|
||||||
s3jni_call_xDestroy(env, s->jObj);
|
s3jni_call_xDestroy(env, s->jObj);
|
||||||
@ -1100,17 +1101,20 @@ static void S3JniHook_unref(JNIEnv * const env, S3JniHook * const s,
|
|||||||
}
|
}
|
||||||
memset(s, 0, sizeof(*s));
|
memset(s, 0, sizeof(*s));
|
||||||
}
|
}
|
||||||
|
#define S3JniHook_unref(H,X) S3JniHook_unref_impl(env, (H), (X))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Internal helper for many hook callback impls. Locks the S3JniDb
|
** Internal helper for many hook callback impls. Locks the S3JniDb
|
||||||
** mutex, makes a copy of src into dest, with one change: if src->jObj
|
** mutex, makes a copy of src into dest, with one change: if src->jObj
|
||||||
** is not NULL then dest->jObj will be a new LOCAL ref to src->jObj
|
** is not NULL then dest->jObj will be a new LOCAL ref to src->jObj
|
||||||
** instead of a copy of the prior GLOBAL ref. Then it unlocks the
|
** instead of a copy of the prior GLOBAL ref. Then it unlocks the
|
||||||
** mutex. If dest->jObj is not NULL when this returns then the caller
|
** mutex.
|
||||||
** is obligated to eventually free the new ref by passing dest->jObj
|
**
|
||||||
** to S3JniUnrefLocal(). The dest pointer must NOT be passed to
|
** If dest->jObj is not NULL when this returns then the caller is
|
||||||
** S3JniHook_unref(), as that one assumes that dest->jObj is a GLOBAL
|
** obligated to eventually free the new ref by passing *dest to
|
||||||
** ref (it's illegal to try to unref the wrong ref type)..
|
** S3JniHook_localundup(). The dest pointer must NOT be passed to
|
||||||
|
** S3JniHook_unref(), as that routine assumes that dest->jObj is a
|
||||||
|
** GLOBAL ref (it's illegal to try to unref the wrong ref type)..
|
||||||
**
|
**
|
||||||
** Background: when running a hook we need a call-local copy lest
|
** Background: when running a hook we need a call-local copy lest
|
||||||
** another thread modify the hook while we're running it. That copy
|
** another thread modify the hook while we're running it. That copy
|
||||||
@ -1123,6 +1127,7 @@ static void S3JniHook_localdup( JNIEnv * const env, S3JniHook const * const src,
|
|||||||
if(dest->jObj) dest->jObj = S3JniRefLocal(dest->jObj);
|
if(dest->jObj) dest->jObj = S3JniRefLocal(dest->jObj);
|
||||||
S3JniMutex_S3JniDb_leave;
|
S3JniMutex_S3JniDb_leave;
|
||||||
}
|
}
|
||||||
|
#define S3JniHook_localundup(HOOK) S3JniUnrefLocal(HOOK.jObj)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Clears all of s's state. Requires that that the caller has locked
|
** Clears all of s's state. Requires that that the caller has locked
|
||||||
@ -1132,7 +1137,7 @@ static void S3JniHook_localdup( JNIEnv * const env, S3JniHook const * const src,
|
|||||||
static void S3JniDb_clear(JNIEnv * const env, S3JniDb * const s){
|
static void S3JniDb_clear(JNIEnv * const env, S3JniDb * const s){
|
||||||
S3JniMutex_S3JniDb_assertLocker;
|
S3JniMutex_S3JniDb_assertLocker;
|
||||||
sqlite3_free( s->zMainDbName );
|
sqlite3_free( s->zMainDbName );
|
||||||
#define UNHOOK(MEMBER) S3JniHook_unref(env, &s->hooks.MEMBER, 0)
|
#define UNHOOK(MEMBER) S3JniHook_unref(&s->hooks.MEMBER, 0)
|
||||||
UNHOOK(auth);
|
UNHOOK(auth);
|
||||||
UNHOOK(busyHandler);
|
UNHOOK(busyHandler);
|
||||||
UNHOOK(collation);
|
UNHOOK(collation);
|
||||||
@ -1380,7 +1385,7 @@ static S3JniDb * S3JniDb_get(JNIEnv * const env, jobject jDb, sqlite3 *pDb){
|
|||||||
** Unref any Java-side state in (S3JniAutoExtension*) AX and zero out
|
** Unref any Java-side state in (S3JniAutoExtension*) AX and zero out
|
||||||
** AX.
|
** AX.
|
||||||
*/
|
*/
|
||||||
#define S3JniAutoExtension_clear(AX) S3JniHook_unref(env, AX, 0);
|
#define S3JniAutoExtension_clear(AX) S3JniHook_unref(AX, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Initializes a pre-allocated S3JniAutoExtension object. Returns
|
** Initializes a pre-allocated S3JniAutoExtension object. Returns
|
||||||
@ -1561,7 +1566,7 @@ static int CollationState_xCompare(void *pArg, int nLhs, const void *lhs,
|
|||||||
S3JniExceptionIgnore;
|
S3JniExceptionIgnore;
|
||||||
S3JniUnrefLocal(jbaLhs);
|
S3JniUnrefLocal(jbaLhs);
|
||||||
S3JniUnrefLocal(jbaRhs);
|
S3JniUnrefLocal(jbaRhs);
|
||||||
S3JniUnrefLocal(hook.jObj);
|
S3JniHook_localundup(hook);
|
||||||
}
|
}
|
||||||
return (int)rc;
|
return (int)rc;
|
||||||
}
|
}
|
||||||
@ -1572,7 +1577,7 @@ static void CollationState_xDestroy(void *pArg){
|
|||||||
S3JniDeclLocal_env;
|
S3JniDeclLocal_env;
|
||||||
|
|
||||||
S3JniMutex_S3JniDb_enter;
|
S3JniMutex_S3JniDb_enter;
|
||||||
S3JniHook_unref( env, &ps->hooks.collation, 1 );
|
S3JniHook_unref(&ps->hooks.collation, 1);
|
||||||
S3JniMutex_S3JniDb_leave;
|
S3JniMutex_S3JniDb_leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1750,12 +1755,14 @@ static int udf_args(JNIEnv *env,
|
|||||||
jobjectArray ja = 0;
|
jobjectArray ja = 0;
|
||||||
jobject jcx = new_sqlite3_context_wrapper(env, cx);
|
jobject jcx = new_sqlite3_context_wrapper(env, cx);
|
||||||
jint i;
|
jint i;
|
||||||
S3JniNphClass * const pNC =
|
|
||||||
S3JniGlobal_nph(env, &S3NphRefs.sqlite3_value);
|
|
||||||
*jCx = 0;
|
*jCx = 0;
|
||||||
*jArgv = 0;
|
*jArgv = 0;
|
||||||
if( !jcx ) goto error_oom;
|
if( !jcx ) goto error_oom;
|
||||||
ja = (*env)->NewObjectArray(env, argc, pNC->klazz, NULL);
|
ja = (*env)->NewObjectArray(
|
||||||
|
env, argc, SJG.g.cObj
|
||||||
|
/* S3JniGlobal_nph(env,&S3NphRefs.sqlite3_value)->klazz would be
|
||||||
|
more correct, but it unpredictably triggers an assert in the
|
||||||
|
JVM. */, NULL);
|
||||||
s3jni_oom_check( ja );
|
s3jni_oom_check( ja );
|
||||||
if( !ja ) goto error_oom;
|
if( !ja ) goto error_oom;
|
||||||
for(i = 0; i < argc; ++i){
|
for(i = 0; i < argc; ++i){
|
||||||
@ -2240,7 +2247,7 @@ static int s3jni_busy_handler(void* pState, int n){
|
|||||||
rc = s3jni_db_exception(env, ps, SQLITE_ERROR,
|
rc = s3jni_db_exception(env, ps, SQLITE_ERROR,
|
||||||
"sqlite3_busy_handler() callback threw.");
|
"sqlite3_busy_handler() callback threw.");
|
||||||
}
|
}
|
||||||
S3JniUnrefLocal(hook.jObj);
|
S3JniHook_localundup(hook);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -2260,17 +2267,17 @@ S3JniApi(sqlite3_busy_handler(),jint,1busy_1handler)(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
jclass klazz;
|
jclass klazz;
|
||||||
S3JniHook_unref(env, pHook, 0);
|
S3JniHook_unref(pHook, 0);
|
||||||
pHook->jObj = S3JniRefGlobal(jBusy);
|
pHook->jObj = S3JniRefGlobal(jBusy);
|
||||||
klazz = (*env)->GetObjectClass(env, jBusy);
|
klazz = (*env)->GetObjectClass(env, jBusy);
|
||||||
pHook->midCallback = (*env)->GetMethodID(env, klazz, "call", "(I)I");
|
pHook->midCallback = (*env)->GetMethodID(env, klazz, "call", "(I)I");
|
||||||
S3JniUnrefLocal(klazz);
|
S3JniUnrefLocal(klazz);
|
||||||
S3JniIfThrew {
|
S3JniIfThrew {
|
||||||
S3JniHook_unref(env, pHook, 0);
|
S3JniHook_unref(pHook, 0);
|
||||||
rc = SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
S3JniHook_unref(env, pHook, 0);
|
S3JniHook_unref(pHook, 0);
|
||||||
}
|
}
|
||||||
if( 0==rc ){
|
if( 0==rc ){
|
||||||
rc = jBusy
|
rc = jBusy
|
||||||
@ -2288,7 +2295,7 @@ S3JniApi(sqlite3_busy_timeout(),jint,1busy_1timeout)(
|
|||||||
int rc = SQLITE_MISUSE;
|
int rc = SQLITE_MISUSE;
|
||||||
if( ps ){
|
if( ps ){
|
||||||
S3JniMutex_S3JniDb_enter;
|
S3JniMutex_S3JniDb_enter;
|
||||||
S3JniHook_unref(env, &ps->hooks.busyHandler, 0);
|
S3JniHook_unref(&ps->hooks.busyHandler, 0);
|
||||||
rc = sqlite3_busy_timeout(ps->pDb, (int)ms);
|
rc = sqlite3_busy_timeout(ps->pDb, (int)ms);
|
||||||
S3JniMutex_S3JniDb_leave;
|
S3JniMutex_S3JniDb_leave;
|
||||||
}
|
}
|
||||||
@ -2387,7 +2394,7 @@ static void s3jni_collation_needed_impl16(void *pState, sqlite3 *pDb,
|
|||||||
}
|
}
|
||||||
S3JniUnrefLocal(jName);
|
S3JniUnrefLocal(jName);
|
||||||
}
|
}
|
||||||
S3JniUnrefLocal(hook.jObj);
|
S3JniHook_localundup(hook);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2404,7 +2411,7 @@ S3JniApi(sqlite3_collation_needed(),jint,1collation_1needed)(
|
|||||||
(*env)->IsSameObject(env, pHook->jObj, jHook) ){
|
(*env)->IsSameObject(env, pHook->jObj, jHook) ){
|
||||||
/* no-op */
|
/* no-op */
|
||||||
}else if( !jHook ){
|
}else if( !jHook ){
|
||||||
S3JniHook_unref(env, pHook, 0);
|
S3JniHook_unref(pHook, 0);
|
||||||
sqlite3_collation_needed(ps->pDb, 0, 0);
|
sqlite3_collation_needed(ps->pDb, 0, 0);
|
||||||
}else{
|
}else{
|
||||||
jclass const klazz = (*env)->GetObjectClass(env, jHook);
|
jclass const klazz = (*env)->GetObjectClass(env, jHook);
|
||||||
@ -2420,7 +2427,7 @@ S3JniApi(sqlite3_collation_needed(),jint,1collation_1needed)(
|
|||||||
rc = sqlite3_collation_needed16(ps->pDb, ps, s3jni_collation_needed_impl16);
|
rc = sqlite3_collation_needed16(ps->pDb, ps, s3jni_collation_needed_impl16);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
}else{
|
}else{
|
||||||
S3JniHook_unref(env, pHook, 0);
|
S3JniHook_unref(pHook, 0);
|
||||||
pHook->midCallback = xCallback;
|
pHook->midCallback = xCallback;
|
||||||
pHook->jObj = S3JniRefGlobal(jHook);
|
pHook->jObj = S3JniRefGlobal(jHook);
|
||||||
}
|
}
|
||||||
@ -2501,7 +2508,7 @@ static int s3jni_commit_rollback_hook_impl(int isCommit,
|
|||||||
S3JniExceptionClear;
|
S3JniExceptionClear;
|
||||||
rc = s3jni_db_error(ps->pDb, SQLITE_ERROR, "hook callback threw.");
|
rc = s3jni_db_error(ps->pDb, SQLITE_ERROR, "hook callback threw.");
|
||||||
}
|
}
|
||||||
S3JniUnrefLocal(hook.jObj);
|
S3JniHook_localundup(hook);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -2634,7 +2641,7 @@ static void s3jni_config_sqllog(void *ignored, sqlite3 *pDb, const char *z, int
|
|||||||
S3JniExceptionWarnCallbackThrew("SQLITE_CONFIG_SQLLOG callback");
|
S3JniExceptionWarnCallbackThrew("SQLITE_CONFIG_SQLLOG callback");
|
||||||
S3JniExceptionClear;
|
S3JniExceptionClear;
|
||||||
}
|
}
|
||||||
S3JniUnrefLocal(hook.jObj);
|
S3JniHook_localundup(hook);
|
||||||
S3JniUnrefLocal(jArg0);
|
S3JniUnrefLocal(jArg0);
|
||||||
S3JniUnrefLocal(jArg1);
|
S3JniUnrefLocal(jArg1);
|
||||||
}
|
}
|
||||||
@ -2656,7 +2663,7 @@ S3JniApi(sqlite3_config() /* for SQLLOG */,
|
|||||||
|
|
||||||
S3JniMutex_Global_enter;
|
S3JniMutex_Global_enter;
|
||||||
if( !jLog ){
|
if( !jLog ){
|
||||||
S3JniHook_unref(env, pHook, 0);
|
S3JniHook_unref(pHook, 0);
|
||||||
}else if( pHook->jObj && (*env)->IsSameObject(env, jLog, pHook->jObj) ){
|
}else if( pHook->jObj && (*env)->IsSameObject(env, jLog, pHook->jObj) ){
|
||||||
/* No-op */
|
/* No-op */
|
||||||
}else {
|
}else {
|
||||||
@ -2669,7 +2676,7 @@ S3JniApi(sqlite3_config() /* for SQLLOG */,
|
|||||||
if( midCallback ){
|
if( midCallback ){
|
||||||
rc = sqlite3_config( SQLITE_CONFIG_SQLLOG, s3jni_config_sqllog, 0 );
|
rc = sqlite3_config( SQLITE_CONFIG_SQLLOG, s3jni_config_sqllog, 0 );
|
||||||
if( 0==rc ){
|
if( 0==rc ){
|
||||||
S3JniHook_unref(env, pHook, 0);
|
S3JniHook_unref(pHook, 0);
|
||||||
pHook->midCallback = midCallback;
|
pHook->midCallback = midCallback;
|
||||||
pHook->jObj = S3JniRefGlobal(jLog);
|
pHook->jObj = S3JniRefGlobal(jLog);
|
||||||
}
|
}
|
||||||
@ -2718,7 +2725,7 @@ S3JniApi(sqlite3_create_collation() sqlite3_create_collation_v2(),
|
|||||||
CollationState_xDestroy);
|
CollationState_xDestroy);
|
||||||
sqlite3_free(zName);
|
sqlite3_free(zName);
|
||||||
if( 0==rc ){
|
if( 0==rc ){
|
||||||
S3JniHook_unref( env, &ps->hooks.collation, 1 );
|
S3JniHook_unref( &ps->hooks.collation, 1 );
|
||||||
ps->hooks.collation.midCallback = midCallback;
|
ps->hooks.collation.midCallback = midCallback;
|
||||||
ps->hooks.collation.jObj = S3JniRefGlobal(oCollation);
|
ps->hooks.collation.jObj = S3JniRefGlobal(oCollation);
|
||||||
}
|
}
|
||||||
@ -3080,7 +3087,8 @@ static int s3jni_open_post(JNIEnv * const env, S3JniEnv * const jc,
|
|||||||
NativePointerHolder_set(env, &S3NphRefs.sqlite3, ps->jDb, *ppDb)
|
NativePointerHolder_set(env, &S3NphRefs.sqlite3, ps->jDb, *ppDb)
|
||||||
/* As of here, the Java/C connection is complete */;
|
/* As of here, the Java/C connection is complete */;
|
||||||
}else{
|
}else{
|
||||||
assert( ps->pDb == *ppDb /* set up via s3jni_run_java_auto_extensions() */);
|
assert( ps->pDb==*ppDb
|
||||||
|
&& "Set up via s3jni_run_java_auto_extensions()" );
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
S3JniDb_set_aside(env, ps);
|
S3JniDb_set_aside(env, ps);
|
||||||
@ -3100,8 +3108,8 @@ S3JniApi(sqlite3_open(),jint,1open)(
|
|||||||
int rc;
|
int rc;
|
||||||
rc = s3jni_open_pre(env, &jc, strName, &zName, &ps);
|
rc = s3jni_open_pre(env, &jc, strName, &zName, &ps);
|
||||||
if( 0==rc ){
|
if( 0==rc ){
|
||||||
rc = sqlite3_open(zName, &pOut);
|
rc = s3jni_open_post(env, jc, ps, &pOut, jOut,
|
||||||
rc = s3jni_open_post(env, jc, ps, &pOut, jOut, rc);
|
sqlite3_open(zName, &pOut));
|
||||||
assert(rc==0 ? pOut!=0 : 1);
|
assert(rc==0 ? pOut!=0 : 1);
|
||||||
sqlite3_free(zName);
|
sqlite3_free(zName);
|
||||||
}
|
}
|
||||||
@ -3270,7 +3278,7 @@ static void s3jni_updatepre_hook_impl(void * pState, sqlite3 *pDb, int opId,
|
|||||||
}
|
}
|
||||||
S3JniUnrefLocal(jDbName);
|
S3JniUnrefLocal(jDbName);
|
||||||
S3JniUnrefLocal(jTable);
|
S3JniUnrefLocal(jTable);
|
||||||
S3JniUnrefLocal(hook.jObj);
|
S3JniHook_localundup(hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||||
@ -3436,7 +3444,7 @@ static int s3jni_progress_handler_impl(void *pP){
|
|||||||
rc = s3jni_db_exception(env, ps, rc,
|
rc = s3jni_db_exception(env, ps, rc,
|
||||||
"sqlite3_progress_handler() callback threw");
|
"sqlite3_progress_handler() callback threw");
|
||||||
}
|
}
|
||||||
S3JniUnrefLocal(hook.jObj);
|
S3JniHook_localundup(hook);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -3452,7 +3460,7 @@ S3JniApi(sqlite3_progress_handler(),void,1progress_1handler)(
|
|||||||
if( !ps ) return;
|
if( !ps ) return;
|
||||||
S3JniMutex_S3JniDb_enter;
|
S3JniMutex_S3JniDb_enter;
|
||||||
if( n<1 || !jProgress ){
|
if( n<1 || !jProgress ){
|
||||||
S3JniHook_unref(env, pHook, 0);
|
S3JniHook_unref(pHook, 0);
|
||||||
sqlite3_progress_handler(ps->pDb, 0, 0, 0);
|
sqlite3_progress_handler(ps->pDb, 0, 0, 0);
|
||||||
S3JniMutex_S3JniDb_leave;
|
S3JniMutex_S3JniDb_leave;
|
||||||
return;
|
return;
|
||||||
@ -3738,7 +3746,7 @@ int s3jni_xAuth(void* pState, int op,const char*z0, const char*z1,
|
|||||||
S3JniUnrefLocal(s1);
|
S3JniUnrefLocal(s1);
|
||||||
S3JniUnrefLocal(s2);
|
S3JniUnrefLocal(s2);
|
||||||
S3JniUnrefLocal(s3);
|
S3JniUnrefLocal(s3);
|
||||||
S3JniUnrefLocal(hook.jObj);
|
S3JniHook_localundup(hook);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -3753,7 +3761,7 @@ S3JniApi(sqlite3_set_authorizer(),jint,1set_1authorizer)(
|
|||||||
if( !ps ) return SQLITE_MISUSE;
|
if( !ps ) return SQLITE_MISUSE;
|
||||||
S3JniMutex_S3JniDb_enter;
|
S3JniMutex_S3JniDb_enter;
|
||||||
if( !jHook ){
|
if( !jHook ){
|
||||||
S3JniHook_unref(env, pHook, 0);
|
S3JniHook_unref(pHook, 0);
|
||||||
rc = sqlite3_set_authorizer( ps->pDb, 0, 0 );
|
rc = sqlite3_set_authorizer( ps->pDb, 0, 0 );
|
||||||
}else{
|
}else{
|
||||||
jclass klazz;
|
jclass klazz;
|
||||||
@ -3763,7 +3771,7 @@ S3JniApi(sqlite3_set_authorizer(),jint,1set_1authorizer)(
|
|||||||
S3JniMutex_S3JniDb_leave;
|
S3JniMutex_S3JniDb_leave;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
S3JniHook_unref(env, pHook, 0);
|
S3JniHook_unref(pHook, 0);
|
||||||
}
|
}
|
||||||
pHook->jObj = S3JniRefGlobal(jHook);
|
pHook->jObj = S3JniRefGlobal(jHook);
|
||||||
klazz = (*env)->GetObjectClass(env, jHook);
|
klazz = (*env)->GetObjectClass(env, jHook);
|
||||||
@ -3782,7 +3790,7 @@ S3JniApi(sqlite3_set_authorizer(),jint,1set_1authorizer)(
|
|||||||
}else{
|
}else{
|
||||||
rc = sqlite3_set_authorizer(ps->pDb, s3jni_xAuth, ps);
|
rc = sqlite3_set_authorizer(ps->pDb, s3jni_xAuth, ps);
|
||||||
}
|
}
|
||||||
if( rc ) S3JniHook_unref(env, pHook, 0);
|
if( rc ) S3JniHook_unref(pHook, 0);
|
||||||
}
|
}
|
||||||
S3JniMutex_S3JniDb_leave;
|
S3JniMutex_S3JniDb_leave;
|
||||||
return rc;
|
return rc;
|
||||||
@ -3978,7 +3986,7 @@ static int s3jni_trace_impl(unsigned traceflag, void *pC, void *pP, void *pX){
|
|||||||
}
|
}
|
||||||
S3JniUnrefLocal(jPUnref);
|
S3JniUnrefLocal(jPUnref);
|
||||||
S3JniUnrefLocal(jX);
|
S3JniUnrefLocal(jX);
|
||||||
S3JniUnrefLocal(hook.jObj);
|
S3JniHook_localundup(hook);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3986,27 +3994,40 @@ S3JniApi(sqlite3_trace_v2(),jint,1trace_1v2)(
|
|||||||
JniArgsEnvClass,jobject jDb, jint traceMask, jobject jTracer
|
JniArgsEnvClass,jobject jDb, jint traceMask, jobject jTracer
|
||||||
){
|
){
|
||||||
S3JniDb * const ps = S3JniDb_from_java(jDb);
|
S3JniDb * const ps = S3JniDb_from_java(jDb);
|
||||||
S3JniHook * const pHook = ps ? &ps->hooks.trace : 0;
|
int rc;
|
||||||
jclass klazz;
|
|
||||||
|
|
||||||
if( !ps ) return SQLITE_MISUSE;
|
if( !ps ) return SQLITE_MISUSE;
|
||||||
else if( !traceMask || !jTracer ){
|
if( !traceMask || !jTracer ){
|
||||||
S3JniHook_unref(env, pHook, 0);
|
S3JniMutex_S3JniDb_enter;
|
||||||
return (jint)sqlite3_trace_v2(ps->pDb, 0, 0, 0);
|
rc = (jint)sqlite3_trace_v2(ps->pDb, 0, 0, 0);
|
||||||
|
S3JniHook_unref(&ps->hooks.trace, 0);
|
||||||
|
S3JniMutex_S3JniDb_leave;
|
||||||
|
}else{
|
||||||
|
jclass const klazz = (*env)->GetObjectClass(env, jTracer);
|
||||||
|
S3JniHook hook = S3JniHook_empty;
|
||||||
|
hook.midCallback = (*env)->GetMethodID(
|
||||||
|
env, klazz, "call", "(ILjava/lang/Object;Ljava/lang/Object;)I"
|
||||||
|
);
|
||||||
|
S3JniUnrefLocal(klazz);
|
||||||
|
S3JniIfThrew {
|
||||||
|
S3JniExceptionClear;
|
||||||
|
rc = s3jni_db_error(ps->pDb, SQLITE_ERROR,
|
||||||
|
"Cannot not find matching call() on "
|
||||||
|
"TracerCallback object.");
|
||||||
|
}else{
|
||||||
|
S3JniMutex_S3JniDb_enter;
|
||||||
|
hook.jObj = S3JniRefGlobal(jTracer);
|
||||||
|
rc = sqlite3_trace_v2(ps->pDb, (unsigned)traceMask, s3jni_trace_impl, ps);
|
||||||
|
if( 0==rc ){
|
||||||
|
S3JniHook_unref(&ps->hooks.trace, 0);
|
||||||
|
ps->hooks.trace = hook;
|
||||||
|
}else{
|
||||||
|
S3JniHook_unref(&hook, 0);
|
||||||
|
}
|
||||||
|
S3JniMutex_S3JniDb_leave;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
klazz = (*env)->GetObjectClass(env, jTracer);
|
return rc;
|
||||||
pHook->midCallback = (*env)->GetMethodID(
|
|
||||||
env, klazz, "call", "(ILjava/lang/Object;Ljava/lang/Object;)I"
|
|
||||||
);
|
|
||||||
S3JniUnrefLocal(klazz);
|
|
||||||
S3JniIfThrew {
|
|
||||||
S3JniExceptionClear;
|
|
||||||
S3JniHook_unref(env, pHook, 0);
|
|
||||||
return s3jni_db_error(ps->pDb, SQLITE_ERROR,
|
|
||||||
"Cannot not find matching xCallback() on Tracer object.");
|
|
||||||
}
|
|
||||||
pHook->jObj = S3JniRefGlobal(jTracer);
|
|
||||||
return sqlite3_trace_v2(ps->pDb, (unsigned)traceMask, s3jni_trace_impl, ps);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
S3JniApi(sqlite3_update_hook(),jobject,1update_1hook)(
|
S3JniApi(sqlite3_update_hook(),jobject,1update_1hook)(
|
||||||
@ -5023,6 +5044,8 @@ Java_org_sqlite_jni_SQLite3Jni_init(JniArgsEnvClass){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Grab references to various global classes and objects... */
|
/* Grab references to various global classes and objects... */
|
||||||
|
SJG.g.cObj = S3JniRefGlobal((*env)->FindClass(env,"java/lang/Object"));
|
||||||
|
S3JniExceptionIsFatal("Error getting reference to Object class.");
|
||||||
|
|
||||||
SJG.g.cLong = S3JniRefGlobal((*env)->FindClass(env,"java/lang/Long"));
|
SJG.g.cLong = S3JniRefGlobal((*env)->FindClass(env,"java/lang/Long"));
|
||||||
S3JniExceptionIsFatal("Error getting reference to Long class.");
|
S3JniExceptionIsFatal("Error getting reference to Long class.");
|
||||||
|
@ -1151,7 +1151,7 @@ public final class SQLite3Jni {
|
|||||||
/**
|
/**
|
||||||
In addition to calling the C-level sqlite3_shutdown(), the JNI
|
In addition to calling the C-level sqlite3_shutdown(), the JNI
|
||||||
binding also cleans up all stale per-thread state managed by the
|
binding also cleans up all stale per-thread state managed by the
|
||||||
library, as well as any registered auto-extensions and free up
|
library, as well as any registered auto-extensions, and frees up
|
||||||
various bits of memory. Calling this while database handles or
|
various bits of memory. Calling this while database handles or
|
||||||
prepared statements are still active will leak resources. Trying
|
prepared statements are still active will leak resources. Trying
|
||||||
to use those objects after this routine is called invoked
|
to use those objects after this routine is called invoked
|
||||||
@ -1179,8 +1179,8 @@ public final class SQLite3Jni {
|
|||||||
public static 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
|
Internal impl of the public sqlite3_strglob() method. Neither
|
||||||
may be NULL and both MUST be NUL-terminated.
|
argument may be NULL and both MUST be NUL-terminated UTF-8.
|
||||||
*/
|
*/
|
||||||
private static native int sqlite3_strglob(
|
private static native int sqlite3_strglob(
|
||||||
@NotNull byte[] glob, @NotNull byte[] txt
|
@NotNull byte[] glob, @NotNull byte[] txt
|
||||||
@ -1197,7 +1197,7 @@ public final class SQLite3Jni {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Internal impl of the public sqlite3_strlike() method. Neither
|
Internal impl of the public sqlite3_strlike() method. Neither
|
||||||
argument may be NULL and both MUST be NUL-terminated.
|
argument may be NULL and both MUST be NUL-terminated UTF-8.
|
||||||
*/
|
*/
|
||||||
private static native int sqlite3_strlike(
|
private static native int sqlite3_strlike(
|
||||||
@NotNull byte[] glob, @NotNull byte[] txt, int escChar
|
@NotNull byte[] glob, @NotNull byte[] txt, int escChar
|
||||||
@ -1225,9 +1225,8 @@ public final class SQLite3Jni {
|
|||||||
arguments are encapsulated in the final argument to this function.
|
arguments are encapsulated in the final argument to this function.
|
||||||
|
|
||||||
Unlike the C API, which is documented as always returning 0, this
|
Unlike the C API, which is documented as always returning 0, this
|
||||||
implementation returns SQLITE_NOMEM if allocation of per-db
|
implementation returns non-0 if initialization of the tracer
|
||||||
mapping state fails and SQLITE_ERROR if the given callback object
|
mapping state fails.
|
||||||
cannot be processed propertly (i.e. an internal error).
|
|
||||||
*/
|
*/
|
||||||
public static native int sqlite3_trace_v2(
|
public static native int sqlite3_trace_v2(
|
||||||
@NotNull sqlite3 db, int traceMask, @Nullable TraceV2Callback tracer
|
@NotNull sqlite3 db, int traceMask, @Nullable TraceV2Callback tracer
|
||||||
|
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
|||||||
C Factor\sout\san\sunnecessary\sstruct\smember.\sJNI\ssqlite3_shutdown()\snow\sfrees\sup\sthe\svarious\sobject-recycling\sbins.\sDoc\stouchups.
|
C Make\sJNI\ssqlite3_trace_v2()\sthread-safe.\sRe-add\sa\spiece\sremoved\sin\s[bae4d022aad9b]\sto\swork\saround\sa\sJVM\scrash\swhich\sis\sunpredictably\striggered\sby\sits\ssubstitute.\sFix\sthe\sTHREADMODE=0\sJNI\sbuild.\sFurther\sinternal\sAPI\ssimplifications.
|
||||||
D 2023-08-27T09:12:50.224
|
D 2023-08-27T10:40:00.984
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@ -233,10 +233,10 @@ F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
|
|||||||
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
|
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
|
||||||
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
|
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
|
||||||
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
|
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
|
||||||
F ext/jni/GNUmakefile 05a756bb7a579b7d6570cb590567e9f0d12270529a2e7e50523284e5a3684838
|
F ext/jni/GNUmakefile 527f7c72360ba081c9ad120a9a00834973dac0115c6272fad94963651ed15bab
|
||||||
F ext/jni/README.md 1332b1fa27918bd5d9ca2d0d4f3ac3a6ab86b9e3699dc5bfe32904a027f3d2a9
|
F ext/jni/README.md 1332b1fa27918bd5d9ca2d0d4f3ac3a6ab86b9e3699dc5bfe32904a027f3d2a9
|
||||||
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
|
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
|
||||||
F ext/jni/src/c/sqlite3-jni.c b0b86b214477ee1604caf358fd1f232ee6649d327527063dddc22216026c20d2
|
F ext/jni/src/c/sqlite3-jni.c 79360ee5b71ce2d90e712768456756e5d57c63bce4e8238c23417caabb790a92
|
||||||
F ext/jni/src/c/sqlite3-jni.h a410d05ca47a676b75ff7b8980e75ad604ea15f3c29965f88989703abc2eeaf6
|
F ext/jni/src/c/sqlite3-jni.h a410d05ca47a676b75ff7b8980e75ad604ea15f3c29965f88989703abc2eeaf6
|
||||||
F ext/jni/src/org/sqlite/jni/AggregateFunction.java 0a5a74bea5ee12a99407e9432d0ca393525af912c2b0ca55c7ee5dbd019c00ef
|
F ext/jni/src/org/sqlite/jni/AggregateFunction.java 0a5a74bea5ee12a99407e9432d0ca393525af912c2b0ca55c7ee5dbd019c00ef
|
||||||
F ext/jni/src/org/sqlite/jni/AuthorizerCallback.java c374bb76409cce7a0bdba94877706b59ac6127fa5d9e6af3e8058c99ce99c030
|
F ext/jni/src/org/sqlite/jni/AuthorizerCallback.java c374bb76409cce7a0bdba94877706b59ac6127fa5d9e6af3e8058c99ce99c030
|
||||||
@ -262,7 +262,7 @@ F ext/jni/src/org/sqlite/jni/ResultCode.java ba701f20213a5f259e94cfbfdd36eb7ac7c
|
|||||||
F ext/jni/src/org/sqlite/jni/RollbackHookCallback.java be7f7a26d1102fb514d835e11198d51302af8053d97188bfb2e34c2133208568
|
F ext/jni/src/org/sqlite/jni/RollbackHookCallback.java be7f7a26d1102fb514d835e11198d51302af8053d97188bfb2e34c2133208568
|
||||||
F ext/jni/src/org/sqlite/jni/SQLFunction.java d060f302b2cc4cf7a4f5a6b2d36458a2e6fc9648374b5d09c36a43665af41207
|
F ext/jni/src/org/sqlite/jni/SQLFunction.java d060f302b2cc4cf7a4f5a6b2d36458a2e6fc9648374b5d09c36a43665af41207
|
||||||
F ext/jni/src/org/sqlite/jni/SQLite3CallbackProxy.java 13c4ea6f35871261eba63fa4117715515e0beecbdebfb879ec5b1f340ed36904
|
F ext/jni/src/org/sqlite/jni/SQLite3CallbackProxy.java 13c4ea6f35871261eba63fa4117715515e0beecbdebfb879ec5b1f340ed36904
|
||||||
F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 1ae75149383cd8b9fde175aa87855d18e425e32af2bc5e81bf56a95e92155195
|
F ext/jni/src/org/sqlite/jni/SQLite3Jni.java e27b7b75f561a8a04b222b6306c59e65dcf7c1fc9408523da0d65c1ffb0e1590
|
||||||
F ext/jni/src/org/sqlite/jni/ScalarFunction.java 21301a947e49f0dd9c682dfe2cc8a6518226c837253dd791cd512f847eeca52c
|
F ext/jni/src/org/sqlite/jni/ScalarFunction.java 21301a947e49f0dd9c682dfe2cc8a6518226c837253dd791cd512f847eeca52c
|
||||||
F ext/jni/src/org/sqlite/jni/Tester1.java 37b46dc15ac8fbeb916dcf1f7771023d2be025d05422d725d5891935eda506ac
|
F ext/jni/src/org/sqlite/jni/Tester1.java 37b46dc15ac8fbeb916dcf1f7771023d2be025d05422d725d5891935eda506ac
|
||||||
F ext/jni/src/org/sqlite/jni/TesterFts5.java 6f135c60e24c89e8eecb9fe61dde0f3bb2906de668ca6c9186bcf34bdaf94629
|
F ext/jni/src/org/sqlite/jni/TesterFts5.java 6f135c60e24c89e8eecb9fe61dde0f3bb2906de668ca6c9186bcf34bdaf94629
|
||||||
@ -2103,8 +2103,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 0f37f27148dfa93ecc42381ad3455a9059285d1af2df027429044942dc4d861b
|
P bae4d022aad9bbeb78cb027ecad799af87afe331e697add44ec22297c873141d
|
||||||
R e62c13b2db81e23df4398b126d6aa9e9
|
R 3800367f7606fbafc862156daf2d0dd5
|
||||||
U stephan
|
U stephan
|
||||||
Z aca6efed8b8717dbec6b53005671b2cd
|
Z e92f2dfe5d2f02a04f8aac3861297f02
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
bae4d022aad9bbeb78cb027ecad799af87afe331e697add44ec22297c873141d
|
3f9f7a9cb08b0687ad206605a5109306762df9ae8bdeab2d8d60bf9373c9ad32
|
Reference in New Issue
Block a user