📄 java_info.c
字号:
{ /* * Note: * Different versions of the JNI disagree on the signature * for AttachCurrentThread. The most recent documentation * seems to say that (JNIEnv **) is correct, but newer * JNIs seem to use (void **), oddly enough. */#ifdef JNI_VERSION_1_2 void *attachret = 0;#else JNIEnv *attachret = 0;#endif /* * This should always succeed, as we are called via * some Java activity. I think therefore I am (a thread). */ if ((*dbji->javavm)->AttachCurrentThread(dbji->javavm, &attachret, 0) != 0) return (0); return ((JNIEnv *)attachret);}jint dbji_get_flags(DB_JAVAINFO *dbji){ return (dbji->construct_flags);}void dbji_set_feedback_object(DB_JAVAINFO *dbji, JNIEnv *jnienv, DB *db, jobject jfeedback){ jclass feedback_class; if (dbji->feedback_method_id == NULL) { if ((feedback_class = get_class(jnienv, name_DbFeedback)) == NULL) return; /* An exception has been posted. */ dbji->feedback_method_id = (*jnienv)->GetMethodID(jnienv, feedback_class, "feedback", "(Lcom/sleepycat/db/Db;II)V"); if (dbji->feedback_method_id == NULL) { /* * XXX * We should really have a better way * to translate this to a Java exception class. * In theory, it shouldn't happen. */ report_exception(jnienv, "Cannot find callback method", EFAULT, 0); return; } } if (dbji->feedback != NULL) { DELETE_GLOBAL_REF(jnienv, dbji->feedback); } if (jfeedback == NULL) { db->set_feedback(db, NULL); } else { db->set_feedback(db, Db_feedback_callback); } dbji->feedback = NEW_GLOBAL_REF(jnienv, jfeedback);}void dbji_call_feedback(DB_JAVAINFO *dbji, DB *db, jobject jdb, int opcode, int percent){ JNIEnv *jnienv; COMPQUIET(db, NULL); jnienv = dbji_get_jnienv(dbji); if (jnienv == NULL) { fprintf(stderr, "Cannot attach to current thread!\n"); return; } DB_ASSERT(dbji->feedback_method_id != NULL); (*jnienv)->CallVoidMethod(jnienv, dbji->feedback, dbji->feedback_method_id, jdb, (jint)opcode, (jint)percent);}void dbji_set_append_recno_object(DB_JAVAINFO *dbji, JNIEnv *jnienv, DB *db, jobject jcallback){ jclass append_recno_class; if (dbji->append_recno_method_id == NULL) { if ((append_recno_class = get_class(jnienv, name_DbAppendRecno)) == NULL) return; /* An exception has been posted. */ dbji->append_recno_method_id = (*jnienv)->GetMethodID(jnienv, append_recno_class, "db_append_recno", "(Lcom/sleepycat/db/Db;" "Lcom/sleepycat/db/Dbt;I)V"); if (dbji->append_recno_method_id == NULL) { /* * XXX * We should really have a better way * to translate this to a Java exception class. * In theory, it shouldn't happen. */ report_exception(jnienv, "Cannot find callback method", EFAULT, 0); return; } } if (dbji->append_recno != NULL) { DELETE_GLOBAL_REF(jnienv, dbji->append_recno); } if (jcallback == NULL) { db->set_append_recno(db, NULL); } else { db->set_append_recno(db, Db_append_recno_callback); } dbji->append_recno = NEW_GLOBAL_REF(jnienv, jcallback);}extern int dbji_call_append_recno(DB_JAVAINFO *dbji, DB *db, jobject jdb, DBT *dbt, jint recno){ JNIEnv *jnienv; jobject jresult; DBT_JAVAINFO *dbtji; LOCKED_DBT lresult; DB_ENV *dbenv; u_char *bytearray; int err; jnienv = dbji_get_jnienv(dbji); dbenv = db->dbenv; if (jnienv == NULL) { fprintf(stderr, "Cannot attach to current thread!\n"); return (0); } jresult = get_Dbt(jnienv, dbt, &dbtji); DB_ASSERT(dbji->append_recno_method_id != NULL); (*jnienv)->CallVoidMethod(jnienv, dbji->append_recno, dbji->append_recno_method_id, jdb, jresult, recno); /* * The underlying C API requires that an errno be returned * on error. Java users know nothing of errnos, so we * allow them to throw exceptions instead. We leave the * exception in place and return DB_JAVA_CALLBACK to the C API * that called us. Eventually the DB->get will fail and * when java prepares to throw an exception in * report_exception(), this will be spotted as a special case, * and the original exception will be preserved. * * Note: we have sometimes noticed strange behavior with * exceptions under Linux 1.1.7 JVM. (i.e. multiple calls * to ExceptionOccurred() may report different results). * Currently we don't know of any problems related to this * in our code, but if it pops up in the future, users are * encouranged to get a more recent JVM. */ if ((*jnienv)->ExceptionOccurred(jnienv) != NULL) return (DB_JAVA_CALLBACK); /* * Now get the DBT back from java, because the user probably * changed it. We'll have to copy back the array too and let * our caller free it. * * We expect that the user *has* changed the DBT (why else would * they set up an append_recno callback?) so we don't * worry about optimizing the unchanged case. */ if ((err = locked_dbt_get(&lresult, jnienv, dbenv, jresult, inOp)) != 0) return (err); memcpy(dbt, &lresult.javainfo->dbt, sizeof(DBT)); if ((err = __os_malloc(dbenv, dbt->size, &bytearray)) != 0) goto out; memcpy(bytearray, dbt->data, dbt->size); dbt->data = bytearray; dbt->flags |= DB_DBT_APPMALLOC; out: locked_dbt_put(&lresult, jnienv, dbenv); return (err);}void dbji_set_assoc_object(DB_JAVAINFO *dbji, JNIEnv *jnienv, DB *db, DB_TXN *txn, DB *second, jobject jcallback, int flags){ jclass assoc_class; int err; if (dbji->assoc_method_id == NULL) { if ((assoc_class = get_class(jnienv, name_DbSecondaryKeyCreate)) == NULL) return; /* An exception has been posted. */ dbji->assoc_method_id = (*jnienv)->GetMethodID(jnienv, assoc_class, "secondary_key_create", "(Lcom/sleepycat/db/Db;" "Lcom/sleepycat/db/Dbt;" "Lcom/sleepycat/db/Dbt;" "Lcom/sleepycat/db/Dbt;)I"); if (dbji->assoc_method_id == NULL) { /* * XXX * We should really have a better way * to translate this to a Java exception class. * In theory, it shouldn't happen. */ report_exception(jnienv, "Cannot find callback method", EFAULT, 0); return; } } if (dbji->assoc != NULL) { DELETE_GLOBAL_REF(jnienv, dbji->assoc); dbji->assoc = NULL; } if (jcallback == NULL) err = db->associate(db, txn, second, NULL, flags); else err = db->associate(db, txn, second, Db_assoc_callback, flags); if (verify_return(jnienv, err, 0)) dbji->assoc = NEW_GLOBAL_REF(jnienv, jcallback);}extern int dbji_call_assoc(DB_JAVAINFO *dbji, DB *db, jobject jdb, const DBT *key, const DBT *value, DBT *result){ JNIEnv *jnienv; jobject jresult; LOCKED_DBT lresult; DB_ENV *dbenv; int err; int sz; u_char *bytearray; jint retval; jnienv = dbji_get_jnienv(dbji); if (jnienv == NULL) { fprintf(stderr, "Cannot attach to current thread!\n"); return (0); } DB_ASSERT(dbji->assoc_method_id != NULL); dbenv = db->dbenv; jresult = create_default_object(jnienv, name_DBT); retval = (*jnienv)->CallIntMethod(jnienv, dbji->assoc, dbji->assoc_method_id, jdb, get_const_Dbt(jnienv, key, NULL), get_const_Dbt(jnienv, value, NULL), jresult); if (retval != 0) return (retval); if ((*jnienv)->ExceptionOccurred(jnienv) != NULL) return (DB_JAVA_CALLBACK); if ((err = locked_dbt_get(&lresult, jnienv, dbenv, jresult, inOp)) != 0) return (err); sz = lresult.javainfo->dbt.size; if (sz > 0) { bytearray = (u_char *)lresult.javainfo->dbt.data; /* * If the byte array is in the range of one of the * arrays passed to us we can use it directly. * If not, we must create our own array and * fill it in with the java array. Since * the java array may disappear and we don't * want to keep its memory locked indefinitely, * we cannot just pin the array. * * XXX consider pinning the array, and having * some way for the C layer to notify the java * layer when it can be unpinned. */ if ((bytearray < (u_char *)key->data || bytearray + sz > (u_char *)key->data + key->size) && (bytearray < (u_char *)value->data || bytearray + sz > (u_char *)value->data + value->size)) { result->flags |= DB_DBT_APPMALLOC; if ((err = __os_malloc(dbenv, sz, &bytearray)) != 0) goto out; memcpy(bytearray, lresult.javainfo->dbt.data, sz); } result->data = bytearray; result->size = sz; } out: locked_dbt_put(&lresult, jnienv, dbenv); return (err);}void dbji_set_bt_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv, DB *db, jobject jcompare){ jclass bt_compare_class; if (dbji->bt_compare_method_id == NULL) { if ((bt_compare_class = get_class(jnienv, name_DbBtreeCompare)) == NULL) return; /* An exception has been posted. */ dbji->bt_compare_method_id = (*jnienv)->GetMethodID(jnienv, bt_compare_class, "bt_compare", "(Lcom/sleepycat/db/Db;" "Lcom/sleepycat/db/Dbt;" "Lcom/sleepycat/db/Dbt;)I"); if (dbji->bt_compare_method_id == NULL) { /* * XXX * We should really have a better way * to translate this to a Java exception class. * In theory, it shouldn't happen. */ report_exception(jnienv, "Cannot find callback method", EFAULT, 0); return; } } if (dbji->bt_compare != NULL) { DELETE_GLOBAL_REF(jnienv, dbji->bt_compare); } if (jcompare == NULL) { db->set_bt_compare(db, NULL); } else { db->set_bt_compare(db, Db_bt_compare_callback); } dbji->bt_compare = NEW_GLOBAL_REF(jnienv, jcompare);}int dbji_call_bt_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb, const DBT *dbt1, const DBT *dbt2){ JNIEnv *jnienv; jobject jdbt1, jdbt2; COMPQUIET(db, NULL); jnienv = dbji_get_jnienv(dbji); if (jnienv == NULL) { fprintf(stderr, "Cannot attach to current thread!\n"); return (0); } jdbt1 = get_const_Dbt(jnienv, dbt1, NULL); jdbt2 = get_const_Dbt(jnienv, dbt2, NULL); DB_ASSERT(dbji->bt_compare_method_id != NULL); return (*jnienv)->CallIntMethod(jnienv, dbji->bt_compare, dbji->bt_compare_method_id, jdb, jdbt1, jdbt2);}void dbji_set_bt_prefix_object(DB_JAVAINFO *dbji, JNIEnv *jnienv, DB *db, jobject jprefix){ jclass bt_prefix_class; if (dbji->bt_prefix_method_id == NULL) { if ((bt_prefix_class = get_class(jnienv, name_DbBtreePrefix)) == NULL) return; /* An exception has been posted. */ dbji->bt_prefix_method_id = (*jnienv)->GetMethodID(jnienv, bt_prefix_class, "bt_prefix", "(Lcom/sleepycat/db/Db;" "Lcom/sleepycat/db/Dbt;" "Lcom/sleepycat/db/Dbt;)I"); if (dbji->bt_prefix_method_id == NULL) { /* * XXX * We should really have a better way * to translate this to a Java exception class. * In theory, it shouldn't happen. */ report_exception(jnienv, "Cannot find callback method", EFAULT, 0); return; } } if (dbji->bt_prefix != NULL) { DELETE_GLOBAL_REF(jnienv, dbji->bt_prefix); } if (jprefix == NULL) { db->set_bt_prefix(db, NULL); } else { db->set_bt_prefix(db, Db_bt_prefix_callback); } dbji->bt_prefix = NEW_GLOBAL_REF(jnienv, jprefix);}size_t dbji_call_bt_prefix(DB_JAVAINFO *dbji, DB *db, jobject jdb, const DBT *dbt1, const DBT *dbt2){ JNIEnv *jnienv; jobject jdbt1, jdbt2; COMPQUIET(db, NULL); jnienv = dbji_get_jnienv(dbji); if (jnienv == NULL) { fprintf(stderr, "Cannot attach to current thread!\n"); return (0); } jdbt1 = get_const_Dbt(jnienv, dbt1, NULL); jdbt2 = get_const_Dbt(jnienv, dbt2, NULL); DB_ASSERT(dbji->bt_prefix_method_id != NULL); return (size_t)(*jnienv)->CallIntMethod(jnienv, dbji->bt_prefix, dbji->bt_prefix_method_id, jdb, jdbt1, jdbt2);}void dbji_set_dup_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv, DB *db, jobject jcompare){ jclass dup_compare_class; if (dbji->dup_compare_method_id == NULL) { if ((dup_compare_class = get_class(jnienv, name_DbDupCompare)) == NULL) return; /* An exception has been posted. */ dbji->dup_compare_method_id = (*jnienv)->GetMethodID(jnienv, dup_compare_class, "dup_compare", "(Lcom/sleepycat/db/Db;" "Lcom/sleepycat/db/Dbt;" "Lcom/sleepycat/db/Dbt;)I"); if (dbji->dup_compare_method_id == NULL) { /* * XXX * We should really have a better way * to translate this to a Java exception class. * In theory, it shouldn't happen. */ report_exception(jnienv, "Cannot find callback method", EFAULT, 0); return; } } if (dbji->dup_compare != NULL) DELETE_GLOBAL_REF(jnienv, dbji->dup_compare); if (jcompare == NULL) db->set_dup_compare(db, NULL); else db->set_dup_compare(db, Db_dup_compare_callback); dbji->dup_compare = NEW_GLOBAL_REF(jnienv, jcompare);}int dbji_call_dup_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb, const DBT *dbt1, const DBT *dbt2){ JNIEnv *jnienv; jobject jdbt1, jdbt2; COMPQUIET(db, NULL); jnienv = dbji_get_jnienv(dbji); if (jnienv == NULL) { fprintf(stderr, "Cannot attach to current thread!\n"); return (0); } jdbt1 = get_const_Dbt(jnienv, dbt1, NULL); jdbt2 = get_const_Dbt(jnienv, dbt2, NULL); DB_ASSERT(dbji->dup_compare_method_id != NULL); return (*jnienv)->CallIntMethod(jnienv, dbji->dup_compare, dbji->dup_compare_method_id, jdb, jdbt1, jdbt2);}void dbji_set_h_hash_object(DB_JAVAINFO *dbji, JNIEnv *jnienv, DB *db, jobject jhash){ jclass h_hash_class; if (dbji->h_hash_method_id == NULL) { if ((h_hash_class = get_class(jnienv, name_DbHash)) == NULL) return; /* An exception has been posted. */ dbji->h_hash_method_id = (*jnienv)->GetMethodID(jnienv, h_hash_class, "hash", "(Lcom/sleepycat/db/Db;" "[BI)I"); if (dbji->h_hash_method_id == NULL) { /* * XXX * We should really have a better way * to translate this to a Java exception class. * In theory, it shouldn't happen. */ report_exception(jnienv, "Cannot find callback method", EFAULT, 0); return; } } if (dbji->h_hash != NULL) DELETE_GLOBAL_REF(jnienv, dbji->h_hash); if (jhash == NULL) db->set_h_hash(db, NULL); else db->set_h_hash(db, Db_h_hash_callback); dbji->h_hash = NEW_GLOBAL_REF(jnienv, jhash);}int dbji_call_h_hash(DB_JAVAINFO *dbji, DB *db, jobject jdb, const void *data, int len){ JNIEnv *jnienv; jbyteArray jdata; COMPQUIET(db, NULL); jnienv = dbji_get_jnienv(dbji); if (jnienv == NULL) { fprintf(stderr, "Cannot attach to current thread!\n"); return (0); } DB_ASSERT(dbji->h_hash_method_id != NULL); if ((jdata = (*jnienv)->NewByteArray(jnienv, len)) == NULL) return (0); /* An exception has been posted by the JVM */ (*jnienv)->SetByteArrayRegion(jnienv, jdata, 0, len, (void *)data); return (*jnienv)->CallIntMethod(jnienv, dbji->h_hash, dbji->h_hash_method_id, jdb, jdata, len);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -