/* Callbacks */ %define JAVA_CALLBACK(_sig, _jclass, _name) JAVA_TYPEMAP(_sig, _jclass, jboolean) %typemap(jtype) _sig "boolean" %typemap(javain) _sig %{ (_name##_handler = $javainput) != null %} /* * The Java object is stored in the Db or DbEnv class. * Here we only care whether it is non-NULL. */ %typemap(in) _sig %{ $1 = ($input == JNI_TRUE) ? __dbj_##_name : NULL; %} %enddef %{ static void __dbj_error(const DB_ENV *dbenv, const char *prefix, const char *msg) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv); jobject jmsg; COMPQUIET(prefix, NULL); if (jdbenv != NULL){ jmsg = (*jenv)->NewStringUTF(jenv, msg); (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class, errcall_method, jmsg); (*jenv)->DeleteLocalRef(jenv, jmsg); } } static void __dbj_env_feedback(DB_ENV *dbenv, int opcode, int percent) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv); if (jdbenv != NULL) (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class, env_feedback_method, opcode, percent); } static void __dbj_message(const DB_ENV *dbenv, const char *msg) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv); jobject jmsg; if (jdbenv != NULL){ jmsg = (*jenv)->NewStringUTF(jenv, msg); (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class, msgcall_method, jmsg); (*jenv)->DeleteLocalRef(jenv, jmsg); } } static void __dbj_panic(DB_ENV *dbenv, int err) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv); if (jdbenv != NULL) (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class, paniccall_method, __dbj_get_except(jenv, err, NULL, NULL, jdbenv)); } static int __dbj_app_dispatch(DB_ENV *dbenv, DBT *dbt, DB_LSN *lsn, db_recops recops) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv); jobject jdbt, jlsn; jbyteArray jdbtarr; int ret; if (jdbenv == NULL) return (EINVAL); jdbt = (*jenv)->NewObject(jenv, dbt_class, dbt_construct); __dbj_dbt_copyout(jenv, dbt, &jdbtarr, jdbt); if (jdbt == NULL) return (ENOMEM); /* An exception is pending */ jlsn = (lsn == NULL) ? NULL : __dbj_wrap_DB_LSN(jenv, lsn); ret = (*jenv)->CallNonvirtualIntMethod(jenv, jdbenv, dbenv_class, app_dispatch_method, jdbt, jlsn, recops); if ((*jenv)->ExceptionOccurred(jenv)) { /* The exception will be thrown, so this could be any error. */ ret = EINVAL; } (*jenv)->DeleteLocalRef(jenv, jdbtarr); (*jenv)->DeleteLocalRef(jenv, jdbt); if (jlsn != NULL) (*jenv)->DeleteLocalRef(jenv, jlsn); return (ret); } static void __dbj_event_notify(DB_ENV *dbenv, u_int32_t event_id, void * info) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv); if (jdbenv == NULL) return ; switch (event_id) { case DB_EVENT_PANIC: (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class, panic_event_notify_method); break; case DB_EVENT_REP_CLIENT: (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class, rep_client_event_notify_method); break; case DB_EVENT_REP_ELECTED: (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class, rep_elected_event_notify_method); break; case DB_EVENT_REP_MASTER: (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class, rep_master_event_notify_method); break; case DB_EVENT_REP_NEWMASTER: (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class, rep_new_master_event_notify_method, *(int*)info); break; case DB_EVENT_REP_PERM_FAILED: (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class, rep_perm_failed_event_notify_method); break; case DB_EVENT_REP_STARTUPDONE: (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class, rep_startup_done_event_notify_method); break; case DB_EVENT_WRITE_FAILED: (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class, write_failed_event_notify_method, *(int*)info); break; default: dbenv->errx(dbenv, "Unhandled event callback in the Java API"); DB_ASSERT(dbenv->env, 0); } } static int __dbj_rep_transport(DB_ENV *dbenv, const DBT *control, const DBT *rec, const DB_LSN *lsn, int envid, u_int32_t flags) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv); jobject jcontrol, jrec, jlsn; jbyteArray jcontrolarr, jrecarr; int ret; if (jdbenv == NULL) return (EINVAL); jcontrol = (*jenv)->NewObject(jenv, dbt_class, dbt_construct); jrec = (*jenv)->NewObject(jenv, dbt_class, dbt_construct); if (jcontrol == NULL || jrec == NULL) return (ENOMEM); /* An exception is pending */ __dbj_dbt_copyout(jenv, control, &jcontrolarr, jcontrol); __dbj_dbt_copyout(jenv, rec, &jrecarr, jrec); jlsn = (lsn == NULL) ? NULL : __dbj_wrap_DB_LSN(jenv, (DB_LSN *)lsn); if (jcontrolarr == NULL || jrecarr == NULL) return (ENOMEM); /* An exception is pending */ ret = (*jenv)->CallNonvirtualIntMethod(jenv, jdbenv, dbenv_class, rep_transport_method, jcontrol, jrec, jlsn, envid, flags); if ((*jenv)->ExceptionOccurred(jenv)) { /* The exception will be thrown, so this could be any error. */ ret = EINVAL; } (*jenv)->DeleteLocalRef(jenv, jrecarr); (*jenv)->DeleteLocalRef(jenv, jcontrolarr); (*jenv)->DeleteLocalRef(jenv, jrec); (*jenv)->DeleteLocalRef(jenv, jcontrol); if (jlsn != NULL) (*jenv)->DeleteLocalRef(jenv, jlsn); return (ret); } static int __dbj_foreignkey_nullify(DB *db, const DBT *key, DBT *data, const DBT *skey, int *changed) { DBT_LOCKED lresult; JNIEnv *jenv = __dbj_get_jnienv(); jobject jdb = (jobject)DB_INTERNAL(db); jobject jkey, jdata, jskey; jbyteArray jkeyarr, jdataarr, jskeyarr; jboolean jresult; int ret; if (jdb == NULL) return (EINVAL); jkey = (key->app_data != NULL) ? ((DBT_LOCKED *)key->app_data)->jdbt : (*jenv)->NewObject(jenv, dbt_class, dbt_construct); jdata = (data->app_data != NULL) ? ((DBT_LOCKED *)data->app_data)->jdbt : (*jenv)->NewObject(jenv, dbt_class, dbt_construct); jskey = (skey->app_data != NULL) ? ((DBT_LOCKED *)skey->app_data)->jdbt : (*jenv)->NewObject(jenv, dbt_class, dbt_construct); if (jkey == NULL || jdata == NULL || jskey == NULL) return (ENOMEM); /* An exception is pending */ if (key->app_data == NULL) { __dbj_dbt_copyout(jenv, key, &jkeyarr, jkey); if (jkeyarr == NULL) return (ENOMEM); /* An exception is pending */ } if (data->app_data == NULL) { __dbj_dbt_copyout(jenv, data, &jdataarr, jdata); if (jdataarr == NULL) return (ENOMEM); /* An exception is pending */ } if (skey->app_data == NULL) { __dbj_dbt_copyout(jenv, skey, &jskeyarr, jskey); if (jskeyarr == NULL) return (ENOMEM); /* An exception is pending */ } jresult = (*jenv)->CallNonvirtualBooleanMethod(jenv, jdb, db_class, foreignkey_nullify_method, jkey, jdata, jskey); if ((*jenv)->ExceptionOccurred(jenv)) { /* The exception will be thrown, so this could be any error. */ ret = EINVAL; goto err; } if (jresult == JNI_FALSE) *changed = ret = 0; else{ *changed = 1; /* copy jdata into data */ if ((ret = __dbj_dbt_copyin(jenv, &lresult, NULL, jdata, 0)) != 0) goto err; if (lresult.dbt.size != 0){ data->size = lresult.dbt.size; if ((ret = __os_umalloc( NULL, data->size, &data->data)) != 0) goto err; if ((ret = __dbj_dbt_memcopy(&lresult.dbt, 0, data->data, data->size, DB_USERCOPY_GETDATA)) != 0) goto err; __dbj_dbt_release(jenv, jdata, &lresult.dbt, &lresult); (*jenv)->DeleteLocalRef(jenv, lresult.jarr); F_SET(data, DB_DBT_APPMALLOC); } } err: if (key->app_data == NULL) { (*jenv)->DeleteLocalRef(jenv, jkeyarr); (*jenv)->DeleteLocalRef(jenv, jkey); } if (data->app_data == NULL) { (*jenv)->DeleteLocalRef(jenv, jdataarr); (*jenv)->DeleteLocalRef(jenv, jdata); } return ret; } static int __dbj_seckey_create(DB *db, const DBT *key, const DBT *data, DBT *result) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdb = (jobject)DB_INTERNAL(db); jobject jkey, jdata, jresult; jobjectArray jskeys; jsize i, num_skeys; jbyteArray jkeyarr, jdataarr; DBT_LOCKED lresult; DBT *tresult; int ret; if (jdb == NULL) return (EINVAL); jkey = (key->app_data != NULL) ? ((DBT_LOCKED *)key->app_data)->jdbt : (*jenv)->NewObject(jenv, dbt_class, dbt_construct); jdata = (data->app_data != NULL) ? ((DBT_LOCKED *)data->app_data)->jdbt : (*jenv)->NewObject(jenv, dbt_class, dbt_construct); if (jkey == NULL || jdata == NULL) return (ENOMEM); /* An exception is pending */ if (key->app_data == NULL) { __dbj_dbt_copyout(jenv, key, &jkeyarr, jkey); if (jkeyarr == NULL) return (ENOMEM); /* An exception is pending */ } if (data->app_data == NULL) { __dbj_dbt_copyout(jenv, data, &jdataarr, jdata); if (jdataarr == NULL) return (ENOMEM); /* An exception is pending */ } jskeys = (jobjectArray)(*jenv)->CallNonvirtualObjectMethod(jenv, jdb, db_class, seckey_create_method, jkey, jdata); if (jskeys == NULL || (num_skeys = (*jenv)->GetArrayLength(jenv, jskeys)) == 0) { ret = DB_DONOTINDEX; goto err; } else if (num_skeys == 1) { memset(result, 0, sizeof (DBT)); tresult = result; } else { if ((ret = __os_umalloc(db->env, num_skeys * sizeof (DBT), &result->data)) != 0) goto err; memset(result->data, 0, num_skeys * sizeof (DBT)); result->size = num_skeys; F_SET(result, DB_DBT_APPMALLOC | DB_DBT_MULTIPLE); tresult = (DBT *)result->data; } if ((*jenv)->ExceptionOccurred(jenv)) { /* The exception will be thrown, so this could be any error. */ ret = EINVAL; goto err; } for (i = 0; i < num_skeys; i++, tresult++) { jresult = (*jenv)->GetObjectArrayElement(jenv, jskeys, i); if ((ret = __dbj_dbt_copyin(jenv, &lresult, NULL, jresult, 0)) != 0) goto err; if (lresult.dbt.size != 0) { /* If there's data, we need to take a copy of it. */ tresult->size = lresult.dbt.size; if ((ret = __os_umalloc(NULL, tresult->size, &tresult->data)) != 0) goto err; if ((ret = __dbj_dbt_memcopy(&lresult.dbt, 0, tresult->data, tresult->size, DB_USERCOPY_GETDATA)) != 0) goto err; __dbj_dbt_release(jenv, jresult, &lresult.dbt, &lresult); (*jenv)->DeleteLocalRef(jenv, lresult.jarr); F_SET(tresult, DB_DBT_APPMALLOC); } (*jenv)->DeleteLocalRef(jenv, jresult); } err: if (key->app_data == NULL) { (*jenv)->DeleteLocalRef(jenv, jkeyarr); (*jenv)->DeleteLocalRef(jenv, jkey); } if (data->app_data == NULL) { (*jenv)->DeleteLocalRef(jenv, jdataarr); (*jenv)->DeleteLocalRef(jenv, jdata); } return (ret); } static int __dbj_append_recno(DB *db, DBT *dbt, db_recno_t recno) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdb = (jobject)DB_INTERNAL(db); jobject jdbt; DBT_LOCKED lresult; jbyteArray jdbtarr; int ret; if (jdb == NULL) return (EINVAL); /* * The dbt we're passed will be from the application, but we can't * just reuse it, since we will have already taken a copy of the data. * Make a new DatabaseEntry object here for the callback. */ jdbt = (*jenv)->NewObject(jenv, dbt_class, dbt_construct); if (jdbt == NULL) return (ENOMEM); /* An exception is pending */ __dbj_dbt_copyout(jenv, dbt, &jdbtarr, jdbt); if (jdbtarr == NULL) return (ENOMEM); /* An exception is pending */ ret = 0; (*jenv)->CallNonvirtualVoidMethod(jenv, jdb, db_class, append_recno_method, jdbt, recno); if ((*jenv)->ExceptionOccurred(jenv)) { /* The exception will be thrown, so this could be any error. */ return (EINVAL); } ret = __dbj_dbt_copyin(jenv, &lresult, NULL, jdbt, 0); memset(dbt, 0, sizeof (DBT)); if (ret == 0 && lresult.dbt.size != 0) { /* If there's data, we need to take a copy of it. */ dbt->size = lresult.dbt.size; if ((ret = __os_umalloc(NULL, dbt->size, &dbt->data)) != 0) goto err; if ((ret = __dbj_dbt_memcopy(&lresult.dbt, 0, dbt->data, dbt->size, DB_USERCOPY_GETDATA)) != 0) goto err; __dbj_dbt_release(jenv, jdbt, &lresult.dbt, &lresult); (*jenv)->DeleteLocalRef(jenv, lresult.jarr); F_SET(dbt, DB_DBT_APPMALLOC); } err: (*jenv)->DeleteLocalRef(jenv, jdbtarr); (*jenv)->DeleteLocalRef(jenv, jdbt); return (ret); } /* * Shared by __dbj_bt_compare and __dbj_h_compare */ static int __dbj_am_compare(DB *db, const DBT *dbt1, const DBT *dbt2, jmethodID compare_method) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdb = (jobject)DB_INTERNAL(db); jbyteArray jdbtarr1, jdbtarr2; int ret; if (jdb == NULL) return (EINVAL); if (dbt1->app_data != NULL) jdbtarr1 = ((DBT_LOCKED *)dbt1->app_data)->jarr; else { jdbtarr1 = (*jenv)->NewByteArray(jenv, (jsize)dbt1->size); if (jdbtarr1 == NULL) return (ENOMEM); (*jenv)->SetByteArrayRegion(jenv, jdbtarr1, 0, (jsize)dbt1->size, (jbyte *)dbt1->data); } if (dbt2->app_data != NULL) jdbtarr2 = ((DBT_LOCKED *)dbt2->app_data)->jarr; else { jdbtarr2 = (*jenv)->NewByteArray(jenv, (jsize)dbt2->size); if (jdbtarr2 == NULL) return (ENOMEM); (*jenv)->SetByteArrayRegion(jenv, jdbtarr2, 0, (jsize)dbt2->size, (jbyte *)dbt2->data); } ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class, compare_method, jdbtarr1, jdbtarr2); if ((*jenv)->ExceptionOccurred(jenv)) { /* The exception will be thrown, so this could be any error. */ ret = EINVAL; } if (dbt1->app_data == NULL) (*jenv)->DeleteLocalRef(jenv, jdbtarr1); if (dbt2->app_data == NULL) (*jenv)->DeleteLocalRef(jenv, jdbtarr2); return (ret); } static int __dbj_bt_compare(DB *db, const DBT *dbt1, const DBT *dbt2) { return __dbj_am_compare(db, dbt1, dbt2, bt_compare_method); } static size_t __dbj_bt_prefix(DB *db, const DBT *dbt1, const DBT *dbt2) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdb = (jobject)DB_INTERNAL(db); jobject jdbt1, jdbt2; jbyteArray jdbtarr1, jdbtarr2; int ret; if (jdb == NULL) return (EINVAL); if (dbt1->app_data != NULL) jdbt1 = ((DBT_LOCKED *)dbt1->app_data)->jdbt; else { if ((jdbt1 = (*jenv)->NewObject(jenv, dbt_class, dbt_construct)) == NULL) return (ENOMEM); /* An exception is pending */ __dbj_dbt_copyout(jenv, dbt1, &jdbtarr1, jdbt1); if (jdbtarr1 == NULL) return (ENOMEM); /* An exception is pending */ } if (dbt2->app_data != NULL) jdbt2 = ((DBT_LOCKED *)dbt2->app_data)->jdbt; else { if ((jdbt2 = (*jenv)->NewObject(jenv, dbt_class, dbt_construct)) == NULL) return (ENOMEM); /* An exception is pending */ __dbj_dbt_copyout(jenv, dbt2, &jdbtarr2, jdbt2); if (jdbtarr2 == NULL) return (ENOMEM); /* An exception is pending */ } ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class, bt_prefix_method, jdbt1, jdbt2); if (dbt1->app_data == NULL) { (*jenv)->DeleteLocalRef(jenv, jdbtarr1); (*jenv)->DeleteLocalRef(jenv, jdbt1); } if (dbt2->app_data == NULL) { (*jenv)->DeleteLocalRef(jenv, jdbtarr2); (*jenv)->DeleteLocalRef(jenv, jdbt2); } return (ret); } static int __dbj_dup_compare(DB *db, const DBT *dbt1, const DBT *dbt2) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdb = (jobject)DB_INTERNAL(db); jbyteArray jdbtarr1, jdbtarr2; int ret; if (jdb == NULL) return (EINVAL); jdbtarr1 = (*jenv)->NewByteArray(jenv, (jsize)dbt1->size); if (jdbtarr1 == NULL) return (ENOMEM); (*jenv)->SetByteArrayRegion(jenv, jdbtarr1, 0, (jsize)dbt1->size, (jbyte *)dbt1->data); jdbtarr2 = (*jenv)->NewByteArray(jenv, (jsize)dbt2->size); if (jdbtarr2 == NULL) return (ENOMEM); (*jenv)->SetByteArrayRegion(jenv, jdbtarr2, 0, (jsize)dbt2->size, (jbyte *)dbt2->data); ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class, dup_compare_method, jdbtarr1, jdbtarr2); if ((*jenv)->ExceptionOccurred(jenv)) { /* The exception will be thrown, so this could be any error. */ ret = EINVAL; } (*jenv)->DeleteLocalRef(jenv, jdbtarr2); (*jenv)->DeleteLocalRef(jenv, jdbtarr1); return (ret); } static void __dbj_db_feedback(DB *db, int opcode, int percent) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdb = (jobject)DB_INTERNAL(db); if (jdb != NULL) (*jenv)->CallNonvirtualVoidMethod(jenv, jdb, db_class, db_feedback_method, opcode, percent); } static int __dbj_h_compare(DB *db, const DBT *dbt1, const DBT *dbt2) { return __dbj_am_compare(db, dbt1, dbt2, h_compare_method); } static u_int32_t __dbj_h_hash(DB *db, const void *data, u_int32_t len) { JNIEnv *jenv = __dbj_get_jnienv(); jobject jdb = (jobject)DB_INTERNAL(db); jbyteArray jarr = (*jenv)->NewByteArray(jenv, (jsize)len); int ret; if (jdb == NULL) return (EINVAL); if ((jarr = (*jenv)->NewByteArray(jenv, (jsize)len)) == NULL) return (ENOMEM); /* An exception is pending */ (*jenv)->SetByteArrayRegion(jenv, jarr, 0, (jsize)len, (jbyte *)data); ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class, h_hash_method, jarr, len); (*jenv)->DeleteLocalRef(jenv, jarr); return (ret); } %} JAVA_CALLBACK(void (*db_errcall_fcn)(const DB_ENV *, const char *, const char *), com.sleepycat.db.ErrorHandler, error) JAVA_CALLBACK(void (*env_feedback_fcn)(DB_ENV *, int, int), com.sleepycat.db.FeedbackHandler, env_feedback) JAVA_CALLBACK(void (*db_msgcall_fcn)(const DB_ENV *, const char *), com.sleepycat.db.MessageHandler, message) JAVA_CALLBACK(void (*db_panic_fcn)(DB_ENV *, int), com.sleepycat.db.PanicHandler, panic) JAVA_CALLBACK(void (*event_notify)(DB_ENV *, u_int32_t, void *), com.sleepycat.db.EventHandler, event_notify) JAVA_CALLBACK(int (*tx_recover)(DB_ENV *, DBT *, DB_LSN *, db_recops), com.sleepycat.db.LogRecordHandler, app_dispatch) JAVA_CALLBACK(int (*send)(DB_ENV *, const DBT *, const DBT *, const DB_LSN *, int, u_int32_t), com.sleepycat.db.ReplicationTransport, rep_transport) /* * Db.associate is a special case, because the handler must be set in the * secondary DB - that's what we have in the callback. In addition, there * are two flavors of callback (single key and multi-key), so we need to * check for both types when working out whether the C callback should * be NULL. Note that this implies that the multi-key callback will be set * on the secondary database *before* associate is called. */ JAVA_CALLBACK(int (*callback)(DB *, const DBT *, const DBT *, DBT *), com.sleepycat.db.SecondaryKeyCreator, seckey_create) %typemap(javain) int (*callback)(DB *, const DBT *, const DBT *, DBT *) %{ (secondary.seckey_create_handler = $javainput) != null || (secondary.secmultikey_create_handler != null) %} JAVA_CALLBACK(int (*callback)(DB *, const DBT *, DBT *, const DBT *, int *), com.sleepycat.db.ForeignKeyNullifier, foreignkey_nullify) %typemap(javain) int (*callback)(DB *, const DBT *, DBT *, const DBT *, int *) %{ (primary.foreignkey_nullify_handler = $javainput) != null || (primary.foreignmultikey_nullify_handler != null) %} JAVA_CALLBACK(int (*db_append_recno_fcn)(DB *, DBT *, db_recno_t), com.sleepycat.db.RecordNumberAppender, append_recno) JAVA_CALLBACK(int (*bt_compare_fcn)(DB *, const DBT *, const DBT *), java.util.Comparator, bt_compare) JAVA_CALLBACK(size_t (*bt_prefix_fcn)(DB *, const DBT *, const DBT *), com.sleepycat.db.BtreePrefixCalculator, bt_prefix) JAVA_CALLBACK(int (*dup_compare_fcn)(DB *, const DBT *, const DBT *), java.util.Comparator, dup_compare) JAVA_CALLBACK(void (*db_feedback_fcn)(DB *, int, int), com.sleepycat.db.FeedbackHandler, db_feedback) JAVA_CALLBACK(int (*h_compare_fcn)(DB *, const DBT *, const DBT *), java.util.Comparator, h_compare) JAVA_CALLBACK(u_int32_t (*h_hash_fcn)(DB *, const void *, u_int32_t), com.sleepycat.db.Hasher, h_hash)