summaryrefslogtreecommitdiff
path: root/libdb_java/java_callbacks.i
diff options
context:
space:
mode:
Diffstat (limited to 'libdb_java/java_callbacks.i')
-rw-r--r--libdb_java/java_callbacks.i930
1 files changed, 930 insertions, 0 deletions
diff --git a/libdb_java/java_callbacks.i b/libdb_java/java_callbacks.i
new file mode 100644
index 0000000..b854fd1
--- /dev/null
+++ b/libdb_java/java_callbacks.i
@@ -0,0 +1,930 @@
+/* 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)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ 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);
+ }
+
+ if (detach)
+ __dbj_detach();
+}
+
+static void __dbj_env_feedback(DB_ENV *dbenv, int opcode, int percent)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv);
+
+ if (jdbenv != NULL)
+ (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class,
+ env_feedback_method, opcode, percent);
+
+ if (detach)
+ __dbj_detach();
+}
+
+static void __dbj_message(const DB_ENV *dbenv, const char *msg)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ 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);
+ }
+
+ if (detach)
+ __dbj_detach();
+}
+
+static void __dbj_panic(DB_ENV *dbenv, int err)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ 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));
+
+ if (detach)
+ __dbj_detach();
+}
+
+static int __dbj_app_dispatch(DB_ENV *dbenv,
+ DBT *dbt, DB_LSN *lsn, db_recops recops)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv);
+ jobject jdbt, jlsn;
+ jbyteArray jdbtarr;
+ int ret;
+
+ if (jdbenv == NULL) {
+ ret = EINVAL;
+ goto err;
+ }
+
+ jdbt = (*jenv)->NewObject(jenv, dbt_class, dbt_construct);
+ __dbj_dbt_copyout(jenv, dbt, &jdbtarr, jdbt);
+ if (jdbt == NULL) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+
+ 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);
+
+err: if (detach)
+ __dbj_detach();
+ return (ret);
+}
+
+static void __dbj_event_notify(DB_ENV *dbenv, u_int32_t event_id, void * info)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv);
+
+ if (jdbenv == NULL)
+ goto done;
+
+ 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);
+ }
+
+done: if (detach)
+ __dbj_detach();
+}
+
+static int __dbj_rep_transport(DB_ENV *dbenv,
+ const DBT *control, const DBT *rec, const DB_LSN *lsn, int envid,
+ u_int32_t flags)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv);
+ jobject jcontrol, jrec, jlsn;
+ jbyteArray jcontrolarr, jrecarr;
+ int ret;
+
+ if (jdbenv == NULL) {
+ ret = EINVAL;
+ goto err;
+ }
+
+ jcontrol = (*jenv)->NewObject(jenv, dbt_class, dbt_construct);
+ jrec = (*jenv)->NewObject(jenv, dbt_class, dbt_construct);
+ if (jcontrol == NULL || jrec == NULL) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+
+ __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) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+
+ 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);
+
+err: if (detach)
+ __dbj_detach();
+ return (ret);
+}
+
+static int __dbj_foreignkey_nullify(DB *db,
+ const DBT *key, DBT *data, const DBT *skey, int *changed)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ DBT_LOCKED lresult;
+ jobject jdb = (jobject)DB_INTERNAL(db);
+ jobject jkey, jdata, jskey;
+ jbyteArray jkeyarr, jdataarr, jskeyarr;
+ jboolean jresult;
+ int ret;
+
+ if (jdb == NULL) {
+ ret = EINVAL;
+ goto err;
+ }
+
+ 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) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+
+ if (key->app_data == NULL) {
+ __dbj_dbt_copyout(jenv, key, &jkeyarr, jkey);
+ if (jkeyarr == NULL) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+ }
+ if (data->app_data == NULL) {
+ __dbj_dbt_copyout(jenv, data, &jdataarr, jdata);
+ if (jdataarr == NULL) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+ }
+ if (skey->app_data == NULL) {
+ __dbj_dbt_copyout(jenv, skey, &jskeyarr, jskey);
+ if (jskeyarr == NULL) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+ }
+
+ 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);
+ }
+
+ if (detach)
+ __dbj_detach();
+ return ret;
+}
+
+static int __dbj_seckey_create(DB *db,
+ const DBT *key, const DBT *data, DBT *result)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ 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) {
+ ret = EINVAL;
+ goto err;
+ }
+
+ 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) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+
+ if (key->app_data == NULL) {
+ __dbj_dbt_copyout(jenv, key, &jkeyarr, jkey);
+ if (jkeyarr == NULL) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+ }
+ if (data->app_data == NULL) {
+ __dbj_dbt_copyout(jenv, data, &jdataarr, jdata);
+ if (jdataarr == NULL) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+ }
+
+ 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);
+ }
+ if (jskeys != NULL) {
+ (*jenv)->DeleteLocalRef(jenv, jskeys);
+ }
+
+ if (detach)
+ __dbj_detach();
+ return (ret);
+}
+
+static int __dbj_append_recno(DB *db, DBT *dbt, db_recno_t recno)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ jobject jdb = (jobject)DB_INTERNAL(db);
+ jobject jdbt;
+ DBT_LOCKED lresult;
+ jbyteArray jdbtarr;
+ int ret;
+
+ if (jdb == NULL) {
+ ret = EINVAL;
+ goto err;
+ }
+
+ /*
+ * 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) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+
+ __dbj_dbt_copyout(jenv, dbt, &jdbtarr, jdbt);
+ if (jdbtarr == NULL) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+
+ 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. */
+ ret = EINVAL;
+ goto err;
+ }
+
+ 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);
+
+ if (detach)
+ __dbj_detach();
+ 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)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ jobject jdb = (jobject)DB_INTERNAL(db);
+ jbyteArray jdbtarr1, jdbtarr2;
+ int ret;
+
+ if (jdb == NULL) {
+ ret = EINVAL;
+ goto err;
+ }
+
+ if (dbt1->app_data != NULL)
+ jdbtarr1 = ((DBT_LOCKED *)dbt1->app_data)->jarr;
+ else {
+ jdbtarr1 = (*jenv)->NewByteArray(jenv, (jsize)dbt1->size);
+ if (jdbtarr1 == NULL) {
+ ret = ENOMEM;
+ goto err;
+ }
+ (*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) {
+ ret = ENOMEM;
+ goto err;
+ }
+ (*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;
+ }
+
+err: if (dbt1->app_data == NULL)
+ (*jenv)->DeleteLocalRef(jenv, jdbtarr1);
+ if (dbt2->app_data == NULL)
+ (*jenv)->DeleteLocalRef(jenv, jdbtarr2);
+
+ if (detach)
+ __dbj_detach();
+ 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);
+}
+
+#define DBT_COPYOUT(num) \
+ if (dbt##num->app_data != NULL) \
+ jdbt##num = ((DBT_LOCKED *)dbt##num->app_data)->jdbt; \
+ else { \
+ if ((jdbt##num = (*jenv)->NewObject( \
+ jenv, dbt_class, dbt_construct)) == NULL) { \
+ ret = ENOMEM; /* An exception is pending */ \
+ goto err; \
+ } \
+ __dbj_dbt_copyout(jenv, dbt##num, &jdbtarr##num, jdbt##num);\
+ if (jdbtarr##num == NULL) { \
+ ret = ENOMEM; /* An exception is pending */ \
+ goto err; \
+ } \
+ }
+
+#define DBT_COPIED_FREE(num) \
+ if (dbt##num->app_data == NULL) { \
+ (*jenv)->DeleteLocalRef(jenv, jdbtarr##num); \
+ (*jenv)->DeleteLocalRef(jenv, jdbt##num); \
+ }
+
+#define DBT_COPYIN_DATA(num) \
+ ret = __dbj_dbt_copyin(jenv, &lresult, NULL, jdbt##num, 0); \
+ memset(dbt##num, 0, sizeof (DBT)); \
+ if (ret == 0 && lresult.dbt.size != 0) { \
+ /* If there's data, we need to take a copy of it. */ \
+ dbt##num->size = lresult.dbt.size; \
+ if ((ret = __os_umalloc( \
+ NULL, dbt##num->size, &dbt##num->data)) != 0) \
+ goto err; \
+ if ((ret = __dbj_dbt_memcopy(&lresult.dbt, 0, \
+ dbt##num->data, dbt##num->size, \
+ DB_USERCOPY_GETDATA)) != 0) \
+ goto err; \
+ __dbj_dbt_release(jenv, jdbt##num, &lresult.dbt, &lresult);\
+ (*jenv)->DeleteLocalRef(jenv, lresult.jarr); \
+ F_SET(dbt##num, DB_DBT_APPMALLOC); \
+ }
+
+static int __dbj_bt_compress(DB *db, const DBT *dbt1, const DBT *dbt2,
+ const DBT *dbt3, const DBT *dbt4, DBT *dbt5)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ jobject jdb = (jobject)DB_INTERNAL(db);
+ jobject jdbt1, jdbt2, jdbt3, jdbt4, jdbt5;
+ jbyteArray jdbtarr1, jdbtarr2, jdbtarr3, jdbtarr4, jdbtarr5;
+ DBT_LOCKED lresult;
+ int ret;
+
+ if (jdb == NULL) {
+ ret = EINVAL;
+ goto err;
+ }
+
+ DBT_COPYOUT(1)
+ DBT_COPYOUT(2)
+ DBT_COPYOUT(3)
+ DBT_COPYOUT(4)
+ DBT_COPYOUT(5)
+
+ ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class,
+ bt_compress_method, jdbt1, jdbt2, jdbt3, jdbt4, jdbt5);
+
+ if ((*jenv)->ExceptionOccurred(jenv)) {
+ /* The exception will be thrown, so this could be any error. */
+ ret = EINVAL;
+ goto err;
+ }
+
+ DBT_COPYIN_DATA(5)
+
+err: DBT_COPIED_FREE(1)
+ DBT_COPIED_FREE(2)
+ DBT_COPIED_FREE(3)
+ DBT_COPIED_FREE(4)
+ DBT_COPIED_FREE(5)
+ if (detach)
+ __dbj_detach();
+ return (ret);
+}
+
+static int __dbj_bt_decompress(DB *db, const DBT *dbt1, const DBT *dbt2,
+ DBT *dbt3, DBT *dbt4, DBT *dbt5)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ jobject jdb = (jobject)DB_INTERNAL(db);
+ jobject jdbt1, jdbt2, jdbt3, jdbt4, jdbt5;
+ jbyteArray jdbtarr1, jdbtarr2, jdbtarr3, jdbtarr4, jdbtarr5;
+ DBT_LOCKED lresult;
+ int ret;
+
+ if (jdb == NULL) {
+ ret = EINVAL;
+ goto err;
+ }
+
+ DBT_COPYOUT(1)
+ DBT_COPYOUT(2)
+ DBT_COPYOUT(3)
+ DBT_COPYOUT(4)
+ DBT_COPYOUT(5)
+
+ ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class,
+ bt_decompress_method, jdbt1, jdbt2, jdbt3, jdbt4, jdbt5);
+
+ if ((*jenv)->ExceptionOccurred(jenv)) {
+ /* The exception will be thrown, so this could be any error. */
+ ret = EINVAL;
+ goto err;
+ }
+
+ DBT_COPYIN_DATA(3)
+ DBT_COPYIN_DATA(4)
+ DBT_COPYIN_DATA(5)
+
+err: DBT_COPIED_FREE(1)
+ DBT_COPIED_FREE(2)
+ DBT_COPIED_FREE(3)
+ DBT_COPIED_FREE(4)
+ DBT_COPIED_FREE(5)
+ if (detach)
+ __dbj_detach();
+ return (ret);
+}
+
+static size_t __dbj_bt_prefix(DB *db, const DBT *dbt1, const DBT *dbt2)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ jobject jdb = (jobject)DB_INTERNAL(db);
+ jobject jdbt1, jdbt2;
+ jbyteArray jdbtarr1, jdbtarr2;
+ int ret;
+
+ if (jdb == NULL) {
+ ret = EINVAL;
+ goto err;
+ }
+
+ if (dbt1->app_data != NULL)
+ jdbt1 = ((DBT_LOCKED *)dbt1->app_data)->jdbt;
+ else {
+ if ((jdbt1 =
+ (*jenv)->NewObject(jenv, dbt_class, dbt_construct)) == NULL) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+ __dbj_dbt_copyout(jenv, dbt1, &jdbtarr1, jdbt1);
+ if (jdbtarr1 == NULL) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+ }
+
+ if (dbt2->app_data != NULL)
+ jdbt2 = ((DBT_LOCKED *)dbt2->app_data)->jdbt;
+ else {
+ if ((jdbt2 =
+ (*jenv)->NewObject(jenv, dbt_class, dbt_construct)) == NULL) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+ __dbj_dbt_copyout(jenv, dbt2, &jdbtarr2, jdbt2);
+ if (jdbtarr2 == NULL) {
+ ret = ENOMEM; /* An exception is pending */
+ goto err;
+ }
+ }
+
+ ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class,
+ bt_prefix_method, jdbt1, jdbt2);
+
+err: 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);
+ }
+
+ if (detach)
+ __dbj_detach();
+ return (ret);
+}
+
+static int __dbj_dup_compare(DB *db, const DBT *dbt1, const DBT *dbt2)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ 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);
+
+ if (detach)
+ __dbj_detach();
+ return (ret);
+}
+
+static void __dbj_db_feedback(DB *db, int opcode, int percent)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ jobject jdb = (jobject)DB_INTERNAL(db);
+
+ if (jdb != NULL)
+ (*jenv)->CallNonvirtualVoidMethod(jenv, jdb, db_class,
+ db_feedback_method, opcode, percent);
+
+ if (detach)
+ __dbj_detach();
+}
+
+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)
+{
+ int detach;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ 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);
+
+ if (detach)
+ __dbj_detach();
+ return (ret);
+}
+
+static u_int32_t __dbj_partition(DB *db, DBT *dbt1)
+{
+ int detach, ret;
+ JNIEnv *jenv = __dbj_get_jnienv(&detach);
+ jobject jdb = (jobject)DB_INTERNAL(db);
+ jobject jdbt1;
+ jbyteArray jdbtarr1;
+ DBT_LOCKED lresult;
+
+ DBT_COPYOUT(1)
+
+ ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class,
+ partition_method, jdbt1);
+ if ((*jenv)->ExceptionOccurred(jenv)) {
+ /* The exception will be thrown, so this could be any error. */
+ ret = EINVAL;
+ goto err;
+ }
+
+ DBT_COPYIN_DATA(1)
+err: DBT_COPIED_FREE(1)
+
+ if (detach)
+ __dbj_detach();
+ 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(int (*bt_compress_fcn)(DB *, const DBT *, const DBT *,
+ const DBT *, const DBT *, DBT *),
+ com.sleepycat.db.BtreeCompressor, bt_compress)
+JAVA_CALLBACK(int (*bt_decompress_fcn)(DB *, const DBT *, const DBT *,
+ DBT *, DBT *, DBT *), com.sleepycat.db.BtreeCompressor, bt_decompress)
+JAVA_CALLBACK(u_int32_t (*db_partition_fcn)(DB *, DBT *),
+ com.sleepycat.db.PartitionHandler, partition)
+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)