resetting manifest requested domain to floor
[platform/upstream/db4.git] / libdb_java / java_callbacks.i
1 /* Callbacks */
2 %define JAVA_CALLBACK(_sig, _jclass, _name)
3 JAVA_TYPEMAP(_sig, _jclass, jboolean)
4 %typemap(jtype) _sig "boolean"
5 %typemap(javain) _sig %{ (_name##_handler = $javainput) != null %}
6
7 /*
8  * The Java object is stored in the Db or DbEnv class.
9  * Here we only care whether it is non-NULL.
10  */
11 %typemap(in) _sig %{
12         $1 = ($input == JNI_TRUE) ? __dbj_##_name : NULL;
13 %}
14 %enddef
15
16 %{
17 static void __dbj_error(const DB_ENV *dbenv,
18     const char *prefix, const char *msg)
19 {
20         int detach;
21         JNIEnv *jenv = __dbj_get_jnienv(&detach);
22         jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv);
23         jobject jmsg;
24
25         COMPQUIET(prefix, NULL);
26
27         if (jdbenv != NULL){
28                 jmsg = (*jenv)->NewStringUTF(jenv, msg);
29                 (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class,
30                     errcall_method, jmsg);
31                 (*jenv)->DeleteLocalRef(jenv, jmsg);
32         }
33
34         if (detach)
35                 __dbj_detach();
36 }
37
38 static void __dbj_env_feedback(DB_ENV *dbenv, int opcode, int percent)
39 {
40         int detach;
41         JNIEnv *jenv = __dbj_get_jnienv(&detach);
42         jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv);
43
44         if (jdbenv != NULL)
45                 (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class,
46                     env_feedback_method, opcode, percent);
47
48         if (detach)
49                 __dbj_detach();
50 }
51
52 static void __dbj_message(const DB_ENV *dbenv, const char *msg)
53 {
54         int detach;
55         JNIEnv *jenv = __dbj_get_jnienv(&detach);
56         jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv);
57         jobject jmsg;
58
59         if (jdbenv != NULL){
60                 jmsg = (*jenv)->NewStringUTF(jenv, msg);
61                 (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class,
62                     msgcall_method, jmsg);
63                 (*jenv)->DeleteLocalRef(jenv, jmsg);
64         }
65
66         if (detach)
67                 __dbj_detach();
68 }
69
70 static void __dbj_panic(DB_ENV *dbenv, int err)
71 {
72         int detach;
73         JNIEnv *jenv = __dbj_get_jnienv(&detach);
74         jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv);
75
76         if (jdbenv != NULL)
77                 (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv, dbenv_class,
78                     paniccall_method,
79                     __dbj_get_except(jenv, err, NULL, NULL, jdbenv));
80
81         if (detach)
82                 __dbj_detach();
83 }
84
85 static int __dbj_app_dispatch(DB_ENV *dbenv,
86     DBT *dbt, DB_LSN *lsn, db_recops recops)
87 {
88         int detach;
89         JNIEnv *jenv = __dbj_get_jnienv(&detach);
90         jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv);
91         jobject jdbt, jlsn;
92         jbyteArray jdbtarr;
93         int ret;
94
95         if (jdbenv == NULL) {
96                 ret = EINVAL;
97                 goto err;
98         }
99
100         jdbt = (*jenv)->NewObject(jenv, dbt_class, dbt_construct);
101         __dbj_dbt_copyout(jenv, dbt, &jdbtarr, jdbt);
102         if (jdbt == NULL) {
103                 ret = ENOMEM; /* An exception is pending */
104                 goto err;
105         }
106
107         jlsn = (lsn == NULL) ? NULL : __dbj_wrap_DB_LSN(jenv, lsn);
108
109         ret = (*jenv)->CallNonvirtualIntMethod(jenv, jdbenv, dbenv_class,
110             app_dispatch_method, jdbt, jlsn, recops);
111
112         if ((*jenv)->ExceptionOccurred(jenv)) {
113                 /* The exception will be thrown, so this could be any error. */
114                 ret = EINVAL;
115         }
116
117         (*jenv)->DeleteLocalRef(jenv, jdbtarr);
118         (*jenv)->DeleteLocalRef(jenv, jdbt);
119         if (jlsn != NULL)
120                 (*jenv)->DeleteLocalRef(jenv, jlsn);
121
122 err:    if (detach)
123                 __dbj_detach();
124         return (ret);
125 }
126
127 static void __dbj_event_notify(DB_ENV *dbenv, u_int32_t event_id, void * info)
128 {
129         int detach;
130         JNIEnv *jenv = __dbj_get_jnienv(&detach);
131         jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv);
132
133         if (jdbenv == NULL)
134                 goto done;
135
136         switch (event_id) {
137         case DB_EVENT_PANIC:
138                 (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv,
139                     dbenv_class, panic_event_notify_method);
140                 break;
141         case DB_EVENT_REP_CLIENT:
142                 (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv,
143                     dbenv_class, rep_client_event_notify_method);
144                 break;
145         case DB_EVENT_REP_ELECTED:
146                 (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv,
147                     dbenv_class, rep_elected_event_notify_method);
148                 break;
149         case DB_EVENT_REP_MASTER:
150                 (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv,
151                     dbenv_class, rep_master_event_notify_method);
152                 break;
153         case DB_EVENT_REP_NEWMASTER:
154                 (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv,
155                     dbenv_class, rep_new_master_event_notify_method, 
156                     *(int*)info);
157                 break;
158         case DB_EVENT_REP_PERM_FAILED:
159                 (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv,
160                     dbenv_class, rep_perm_failed_event_notify_method);
161                 break;
162         case DB_EVENT_REP_STARTUPDONE:
163                 (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv,
164                     dbenv_class, rep_startup_done_event_notify_method);
165                 break;
166         case DB_EVENT_WRITE_FAILED:
167                 (*jenv)->CallNonvirtualVoidMethod(jenv, jdbenv,
168                     dbenv_class, write_failed_event_notify_method, 
169                     *(int*)info);
170                 break;
171         default:
172                 dbenv->errx(dbenv, "Unhandled event callback in the Java API");
173                 DB_ASSERT(dbenv->env, 0);
174         }
175
176 done:   if (detach)
177                 __dbj_detach();
178 }
179
180 static int __dbj_rep_transport(DB_ENV *dbenv,
181     const DBT *control, const DBT *rec, const DB_LSN *lsn, int envid,
182     u_int32_t flags)
183 {
184         int detach;
185         JNIEnv *jenv = __dbj_get_jnienv(&detach);
186         jobject jdbenv = (jobject)DB_ENV_INTERNAL(dbenv);
187         jobject jcontrol, jrec, jlsn;
188         jbyteArray jcontrolarr, jrecarr;
189         int ret;
190
191         if (jdbenv == NULL) {
192                 ret = EINVAL;
193                 goto err;
194         }
195
196         jcontrol = (*jenv)->NewObject(jenv, dbt_class, dbt_construct);
197         jrec = (*jenv)->NewObject(jenv, dbt_class, dbt_construct);
198         if (jcontrol == NULL || jrec == NULL) {
199                 ret = ENOMEM; /* An exception is pending */
200                 goto err;
201         }
202
203         __dbj_dbt_copyout(jenv, control, &jcontrolarr, jcontrol);
204         __dbj_dbt_copyout(jenv, rec, &jrecarr, jrec);
205         jlsn = (lsn == NULL) ? NULL : __dbj_wrap_DB_LSN(jenv, (DB_LSN *)lsn);
206
207         if (jcontrolarr == NULL || jrecarr == NULL) {
208                 ret = ENOMEM; /* An exception is pending */
209                 goto err;
210         }
211
212         ret = (*jenv)->CallNonvirtualIntMethod(jenv, jdbenv, dbenv_class,
213             rep_transport_method, jcontrol, jrec, jlsn, envid, flags);
214
215         if ((*jenv)->ExceptionOccurred(jenv)) {
216                 /* The exception will be thrown, so this could be any error. */
217                 ret = EINVAL;
218         }
219
220         (*jenv)->DeleteLocalRef(jenv, jrecarr);
221         (*jenv)->DeleteLocalRef(jenv, jcontrolarr);
222         (*jenv)->DeleteLocalRef(jenv, jrec);
223         (*jenv)->DeleteLocalRef(jenv, jcontrol);
224         if (jlsn != NULL)
225                 (*jenv)->DeleteLocalRef(jenv, jlsn);
226
227 err:    if (detach)
228                 __dbj_detach();
229         return (ret);
230 }
231
232 static int __dbj_foreignkey_nullify(DB *db, 
233     const DBT *key, DBT *data, const DBT *skey, int *changed)
234 {
235         int detach;
236         JNIEnv *jenv = __dbj_get_jnienv(&detach);
237         DBT_LOCKED lresult;
238         jobject jdb = (jobject)DB_INTERNAL(db);
239         jobject jkey, jdata, jskey;
240         jbyteArray jkeyarr, jdataarr, jskeyarr;
241         jboolean jresult;
242         int ret;
243
244         if (jdb == NULL) {
245                 ret = EINVAL;
246                 goto err;
247         }
248
249         jkey = (key->app_data != NULL) ?
250             ((DBT_LOCKED *)key->app_data)->jdbt :
251             (*jenv)->NewObject(jenv, dbt_class, dbt_construct);
252         jdata = (data->app_data != NULL) ?
253             ((DBT_LOCKED *)data->app_data)->jdbt :
254             (*jenv)->NewObject(jenv, dbt_class, dbt_construct);
255         jskey = (skey->app_data != NULL) ?
256             ((DBT_LOCKED *)skey->app_data)->jdbt :
257             (*jenv)->NewObject(jenv, dbt_class, dbt_construct);
258         if (jkey == NULL || jdata == NULL || jskey == NULL) {
259                 ret = ENOMEM; /* An exception is pending */
260                 goto err;
261         }
262
263         if (key->app_data == NULL) {
264                 __dbj_dbt_copyout(jenv, key, &jkeyarr, jkey);
265                 if (jkeyarr == NULL) {
266                         ret = ENOMEM; /* An exception is pending */
267                         goto err;
268                 }
269         }
270         if (data->app_data == NULL) {
271                 __dbj_dbt_copyout(jenv, data, &jdataarr, jdata);
272                 if (jdataarr == NULL) {
273                         ret = ENOMEM; /* An exception is pending */
274                         goto err;
275                 }
276         }
277         if (skey->app_data == NULL) {
278                 __dbj_dbt_copyout(jenv, skey, &jskeyarr, jskey);
279                 if (jskeyarr == NULL) {
280                         ret = ENOMEM; /* An exception is pending */
281                         goto err;
282                 }
283         }
284
285         jresult = (*jenv)->CallNonvirtualBooleanMethod(jenv, jdb, db_class, foreignkey_nullify_method, jkey, jdata, jskey);
286
287         if ((*jenv)->ExceptionOccurred(jenv)) {
288                 /* The exception will be thrown, so this could be any error. */
289                 ret = EINVAL;
290                 goto err;
291         }
292
293         if (jresult == JNI_FALSE)
294                 *changed = ret = 0;
295         else{
296                 *changed = 1;
297                 /* copy jdata into data */
298                 if ((ret = __dbj_dbt_copyin(jenv, &lresult, NULL, jdata, 0)) != 0)
299                         goto err;
300                 if (lresult.dbt.size != 0){
301                         data->size = lresult.dbt.size;
302                         if ((ret = __os_umalloc(
303                             NULL, data->size, &data->data)) != 0)
304                                 goto err;
305                         if ((ret = __dbj_dbt_memcopy(&lresult.dbt, 0, 
306                             data->data, data->size, DB_USERCOPY_GETDATA)) != 0)
307                                 goto err;
308                         __dbj_dbt_release(jenv, jdata,  &lresult.dbt, &lresult);
309                         (*jenv)->DeleteLocalRef(jenv, lresult.jarr);
310                         F_SET(data, DB_DBT_APPMALLOC);
311                 } 
312         }                       
313
314 err:    if (key->app_data == NULL) {
315                 (*jenv)->DeleteLocalRef(jenv, jkeyarr);
316                 (*jenv)->DeleteLocalRef(jenv, jkey);
317         }
318         if (data->app_data == NULL) {
319                 (*jenv)->DeleteLocalRef(jenv, jdataarr);
320                 (*jenv)->DeleteLocalRef(jenv, jdata);
321         }
322
323         if (detach)
324                 __dbj_detach();
325         return ret;
326 }
327
328 static int __dbj_seckey_create(DB *db,
329     const DBT *key, const DBT *data, DBT *result)
330 {
331         int detach;
332         JNIEnv *jenv = __dbj_get_jnienv(&detach);
333         jobject jdb = (jobject)DB_INTERNAL(db);
334         jobject jkey, jdata, jresult;
335         jobjectArray jskeys;
336         jsize i, num_skeys;
337         jbyteArray jkeyarr, jdataarr;
338         DBT_LOCKED lresult;
339         DBT *tresult;
340         int ret;
341
342         if (jdb == NULL) {
343                 ret = EINVAL;
344                 goto err;
345         }
346
347         jkey = (key->app_data != NULL) ?
348             ((DBT_LOCKED *)key->app_data)->jdbt :
349             (*jenv)->NewObject(jenv, dbt_class, dbt_construct);
350         jdata = (data->app_data != NULL) ?
351             ((DBT_LOCKED *)data->app_data)->jdbt :
352             (*jenv)->NewObject(jenv, dbt_class, dbt_construct);
353         if (jkey == NULL || jdata == NULL) {
354                 ret = ENOMEM; /* An exception is pending */
355                 goto err;
356         }
357
358         if (key->app_data == NULL) {
359                 __dbj_dbt_copyout(jenv, key, &jkeyarr, jkey);
360                 if (jkeyarr == NULL) {
361                         ret = ENOMEM; /* An exception is pending */
362                         goto err;
363                 }
364         }
365         if (data->app_data == NULL) {
366                 __dbj_dbt_copyout(jenv, data, &jdataarr, jdata);
367                 if (jdataarr == NULL) {
368                         ret = ENOMEM; /* An exception is pending */
369                         goto err;
370                 }
371         }
372
373         jskeys = (jobjectArray)(*jenv)->CallNonvirtualObjectMethod(jenv,
374             jdb, db_class, seckey_create_method, jkey, jdata);
375
376         if (jskeys == NULL ||
377             (num_skeys = (*jenv)->GetArrayLength(jenv, jskeys)) == 0) {
378                 ret = DB_DONOTINDEX;
379                 goto err;
380         } else if (num_skeys == 1) {
381                 memset(result, 0, sizeof (DBT));
382                 tresult = result;
383         } else {
384                 if ((ret = __os_umalloc(db->env,
385                     num_skeys * sizeof (DBT), &result->data)) != 0)
386                         goto err;
387                 memset(result->data, 0, num_skeys * sizeof (DBT));
388                 result->size = num_skeys;
389                 F_SET(result, DB_DBT_APPMALLOC | DB_DBT_MULTIPLE);
390                 tresult = (DBT *)result->data;
391         }
392
393         if ((*jenv)->ExceptionOccurred(jenv)) {
394                 /* The exception will be thrown, so this could be any error. */
395                 ret = EINVAL;
396                 goto err;
397         }
398
399         for (i = 0; i < num_skeys; i++, tresult++) {
400                 jresult = (*jenv)->GetObjectArrayElement(jenv, jskeys, i);
401
402                 if ((ret =
403                     __dbj_dbt_copyin(jenv, &lresult, NULL, jresult, 0)) != 0)
404                         goto err;
405
406                 if (lresult.dbt.size != 0) {
407                         /* If there's data, we need to take a copy of it.  */
408                         tresult->size = lresult.dbt.size;
409                         if ((ret = __os_umalloc(NULL,
410                             tresult->size, &tresult->data)) != 0)
411                                 goto err;
412                         if ((ret = __dbj_dbt_memcopy(&lresult.dbt, 0,
413                             tresult->data, tresult->size,
414                             DB_USERCOPY_GETDATA)) != 0)
415                                 goto err;
416                         __dbj_dbt_release(jenv,
417                             jresult, &lresult.dbt, &lresult);
418                         (*jenv)->DeleteLocalRef(jenv, lresult.jarr);
419                         F_SET(tresult, DB_DBT_APPMALLOC);
420                 }
421
422                 (*jenv)->DeleteLocalRef(jenv, jresult);
423         }
424
425 err:    if (key->app_data == NULL) {
426                 (*jenv)->DeleteLocalRef(jenv, jkeyarr);
427                 (*jenv)->DeleteLocalRef(jenv, jkey);
428         }
429         if (data->app_data == NULL) {
430                 (*jenv)->DeleteLocalRef(jenv, jdataarr);
431                 (*jenv)->DeleteLocalRef(jenv, jdata);
432         }
433         if (jskeys != NULL) {
434                 (*jenv)->DeleteLocalRef(jenv, jskeys);
435         }
436
437         if (detach)
438                 __dbj_detach();
439         return (ret);
440 }
441
442 static int __dbj_append_recno(DB *db, DBT *dbt, db_recno_t recno)
443 {
444         int detach;
445         JNIEnv *jenv = __dbj_get_jnienv(&detach);
446         jobject jdb = (jobject)DB_INTERNAL(db);
447         jobject jdbt;
448         DBT_LOCKED lresult;
449         jbyteArray jdbtarr;
450         int ret;
451
452         if (jdb == NULL) {
453                 ret = EINVAL;
454                 goto err;
455         }
456
457         /*
458          * The dbt we're passed will be from the application, but we can't
459          * just reuse it, since we will have already taken a copy of the data.
460          * Make a new DatabaseEntry object here for the callback.
461          */
462         jdbt = (*jenv)->NewObject(jenv, dbt_class, dbt_construct);
463         if (jdbt == NULL) {
464                 ret = ENOMEM; /* An exception is pending */
465                 goto err;
466         }
467
468         __dbj_dbt_copyout(jenv, dbt, &jdbtarr, jdbt);
469         if (jdbtarr == NULL) {
470                 ret = ENOMEM; /* An exception is pending */
471                 goto err;
472         }
473
474         ret = 0;
475         (*jenv)->CallNonvirtualVoidMethod(jenv, jdb, db_class,
476             append_recno_method, jdbt, recno);
477
478         if ((*jenv)->ExceptionOccurred(jenv)) {
479                 /* The exception will be thrown, so this could be any error. */
480                 ret = EINVAL;
481                 goto err;
482         }
483
484         ret = __dbj_dbt_copyin(jenv, &lresult, NULL, jdbt, 0);
485         memset(dbt, 0, sizeof (DBT));
486
487         if (ret == 0 && lresult.dbt.size != 0) {
488                 /* If there's data, we need to take a copy of it.  */
489                 dbt->size = lresult.dbt.size;
490                 if ((ret =
491                     __os_umalloc(NULL, dbt->size, &dbt->data)) != 0)
492                         goto err;
493                 if ((ret = __dbj_dbt_memcopy(&lresult.dbt, 0,
494                     dbt->data, dbt->size,
495                     DB_USERCOPY_GETDATA)) != 0)
496                         goto err;
497                 __dbj_dbt_release(jenv, jdbt, &lresult.dbt, &lresult);
498                 (*jenv)->DeleteLocalRef(jenv, lresult.jarr);
499                 F_SET(dbt, DB_DBT_APPMALLOC);
500         }
501
502 err:    (*jenv)->DeleteLocalRef(jenv, jdbtarr);
503         (*jenv)->DeleteLocalRef(jenv, jdbt);
504
505         if (detach)
506                 __dbj_detach();
507         return (ret);
508 }
509
510 /*
511  * Shared by __dbj_bt_compare and __dbj_h_compare
512  */
513 static int __dbj_am_compare(DB *db, const DBT *dbt1, const DBT *dbt2,
514     jmethodID compare_method)
515 {
516         int detach;
517         JNIEnv *jenv = __dbj_get_jnienv(&detach);
518         jobject jdb = (jobject)DB_INTERNAL(db);
519         jbyteArray jdbtarr1, jdbtarr2;
520         int ret;
521
522         if (jdb == NULL) {
523                 ret = EINVAL;
524                 goto err;
525         }
526
527         if (dbt1->app_data != NULL)
528                 jdbtarr1 = ((DBT_LOCKED *)dbt1->app_data)->jarr;
529         else {
530                 jdbtarr1 = (*jenv)->NewByteArray(jenv, (jsize)dbt1->size);
531                 if (jdbtarr1 == NULL) {
532                         ret = ENOMEM;
533                         goto err;
534                 }
535                 (*jenv)->SetByteArrayRegion(jenv, jdbtarr1, 0,
536                     (jsize)dbt1->size, (jbyte *)dbt1->data);
537         }
538
539         if (dbt2->app_data != NULL)
540                 jdbtarr2 = ((DBT_LOCKED *)dbt2->app_data)->jarr;
541         else {
542                 jdbtarr2 = (*jenv)->NewByteArray(jenv, (jsize)dbt2->size);
543                 if (jdbtarr2 == NULL) {
544                         ret = ENOMEM;
545                         goto err;
546                 }
547                 (*jenv)->SetByteArrayRegion(jenv, jdbtarr2, 0,
548                     (jsize)dbt2->size, (jbyte *)dbt2->data);
549         }
550
551         ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class,
552             compare_method, jdbtarr1, jdbtarr2);
553
554         if ((*jenv)->ExceptionOccurred(jenv)) {
555                 /* The exception will be thrown, so this could be any error. */
556                 ret = EINVAL;
557         }
558
559 err:    if (dbt1->app_data == NULL)
560                 (*jenv)->DeleteLocalRef(jenv, jdbtarr1);
561         if (dbt2->app_data == NULL)
562                 (*jenv)->DeleteLocalRef(jenv, jdbtarr2);
563
564         if (detach)
565                 __dbj_detach();
566         return (ret);
567 }
568
569 static int __dbj_bt_compare(DB *db, const DBT *dbt1, const DBT *dbt2)
570 {
571         return __dbj_am_compare(db, dbt1, dbt2, bt_compare_method);
572 }
573
574 #define DBT_COPYOUT(num)                                                \
575         if (dbt##num->app_data != NULL)                                 \
576                 jdbt##num = ((DBT_LOCKED *)dbt##num->app_data)->jdbt;   \
577         else {                                                          \
578                 if ((jdbt##num = (*jenv)->NewObject(                    \
579                     jenv, dbt_class, dbt_construct)) == NULL) {         \
580                         ret = ENOMEM; /* An exception is pending */     \
581                         goto err;                                       \
582                 }                                                       \
583                 __dbj_dbt_copyout(jenv, dbt##num, &jdbtarr##num, jdbt##num);\
584                 if (jdbtarr##num == NULL) {                             \
585                         ret = ENOMEM; /* An exception is pending */     \
586                         goto err;                                       \
587                 }                                                       \
588         }
589
590 #define DBT_COPIED_FREE(num)                                            \
591         if (dbt##num->app_data == NULL) {                               \
592                 (*jenv)->DeleteLocalRef(jenv, jdbtarr##num);            \
593                 (*jenv)->DeleteLocalRef(jenv, jdbt##num);               \
594         }
595
596 #define DBT_COPYIN_DATA(num)                                            \
597         ret = __dbj_dbt_copyin(jenv, &lresult, NULL, jdbt##num, 0);     \
598         memset(dbt##num, 0, sizeof (DBT));                              \
599         if (ret == 0 && lresult.dbt.size != 0) {                        \
600                 /* If there's data, we need to take a copy of it.  */   \
601                 dbt##num->size = lresult.dbt.size;                      \
602                 if ((ret = __os_umalloc(                                \
603                     NULL, dbt##num->size, &dbt##num->data)) != 0)       \
604                         goto err;                                       \
605                 if ((ret = __dbj_dbt_memcopy(&lresult.dbt, 0,           \
606                     dbt##num->data, dbt##num->size,                     \
607                     DB_USERCOPY_GETDATA)) != 0)                         \
608                         goto err;                                       \
609                 __dbj_dbt_release(jenv, jdbt##num, &lresult.dbt, &lresult);\
610                 (*jenv)->DeleteLocalRef(jenv, lresult.jarr);            \
611                 F_SET(dbt##num, DB_DBT_APPMALLOC);                      \
612         }
613
614 static int __dbj_bt_compress(DB *db, const DBT *dbt1, const DBT *dbt2,
615     const DBT *dbt3, const DBT *dbt4, DBT *dbt5)
616 {
617         int detach;
618         JNIEnv *jenv = __dbj_get_jnienv(&detach);
619         jobject jdb = (jobject)DB_INTERNAL(db);
620         jobject jdbt1, jdbt2, jdbt3, jdbt4, jdbt5;
621         jbyteArray jdbtarr1, jdbtarr2, jdbtarr3, jdbtarr4, jdbtarr5;
622         DBT_LOCKED lresult;
623         int ret;
624
625         if (jdb == NULL) {
626                 ret = EINVAL;
627                 goto err;
628         }
629
630         DBT_COPYOUT(1)
631         DBT_COPYOUT(2)
632         DBT_COPYOUT(3)
633         DBT_COPYOUT(4)
634         DBT_COPYOUT(5)
635
636         ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class,
637             bt_compress_method, jdbt1, jdbt2, jdbt3, jdbt4, jdbt5);
638
639         if ((*jenv)->ExceptionOccurred(jenv)) {
640                 /* The exception will be thrown, so this could be any error. */
641                 ret = EINVAL;
642                 goto err;
643         }
644
645         DBT_COPYIN_DATA(5)
646
647 err:    DBT_COPIED_FREE(1)
648         DBT_COPIED_FREE(2)
649         DBT_COPIED_FREE(3)
650         DBT_COPIED_FREE(4)
651         DBT_COPIED_FREE(5)
652         if (detach)
653                 __dbj_detach();
654         return (ret);
655 }
656
657 static int __dbj_bt_decompress(DB *db, const DBT *dbt1, const DBT *dbt2,
658     DBT *dbt3, DBT *dbt4, DBT *dbt5)
659 {
660         int detach;
661         JNIEnv *jenv = __dbj_get_jnienv(&detach);
662         jobject jdb = (jobject)DB_INTERNAL(db);
663         jobject jdbt1, jdbt2, jdbt3, jdbt4, jdbt5;
664         jbyteArray jdbtarr1, jdbtarr2, jdbtarr3, jdbtarr4, jdbtarr5;
665         DBT_LOCKED lresult;
666         int ret;
667
668         if (jdb == NULL) {
669                 ret = EINVAL;
670                 goto err;
671         }
672
673         DBT_COPYOUT(1)
674         DBT_COPYOUT(2)
675         DBT_COPYOUT(3)
676         DBT_COPYOUT(4)
677         DBT_COPYOUT(5)
678
679         ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class,
680             bt_decompress_method, jdbt1, jdbt2, jdbt3, jdbt4, jdbt5);
681
682         if ((*jenv)->ExceptionOccurred(jenv)) {
683                 /* The exception will be thrown, so this could be any error. */
684                 ret = EINVAL;
685                 goto err;
686         }
687
688         DBT_COPYIN_DATA(3)
689         DBT_COPYIN_DATA(4)
690         DBT_COPYIN_DATA(5)
691
692 err:    DBT_COPIED_FREE(1)
693         DBT_COPIED_FREE(2)
694         DBT_COPIED_FREE(3)
695         DBT_COPIED_FREE(4)
696         DBT_COPIED_FREE(5)
697         if (detach)
698                 __dbj_detach();
699         return (ret);
700 }
701
702 static size_t __dbj_bt_prefix(DB *db, const DBT *dbt1, const DBT *dbt2)
703 {
704         int detach;
705         JNIEnv *jenv = __dbj_get_jnienv(&detach);
706         jobject jdb = (jobject)DB_INTERNAL(db);
707         jobject jdbt1, jdbt2;
708         jbyteArray jdbtarr1, jdbtarr2;
709         int ret;
710
711         if (jdb == NULL) {
712                 ret = EINVAL;
713                 goto err;
714         }
715
716         if (dbt1->app_data != NULL)
717                 jdbt1 = ((DBT_LOCKED *)dbt1->app_data)->jdbt;
718         else {
719                 if ((jdbt1 =
720                     (*jenv)->NewObject(jenv, dbt_class, dbt_construct)) == NULL) {
721                         ret = ENOMEM; /* An exception is pending */
722                         goto err;
723                 }
724                 __dbj_dbt_copyout(jenv, dbt1, &jdbtarr1, jdbt1);
725                 if (jdbtarr1 == NULL) {
726                         ret = ENOMEM; /* An exception is pending */
727                         goto err;
728                 }
729         }
730
731         if (dbt2->app_data != NULL)
732                 jdbt2 = ((DBT_LOCKED *)dbt2->app_data)->jdbt;
733         else {
734                 if ((jdbt2 =
735                     (*jenv)->NewObject(jenv, dbt_class, dbt_construct)) == NULL) {
736                         ret = ENOMEM; /* An exception is pending */
737                         goto err;
738                 }
739                 __dbj_dbt_copyout(jenv, dbt2, &jdbtarr2, jdbt2);
740                 if (jdbtarr2 == NULL) {
741                         ret = ENOMEM; /* An exception is pending */
742                         goto err;
743                 }
744         }
745
746         ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class,
747             bt_prefix_method, jdbt1, jdbt2);
748
749 err:    if (dbt1->app_data == NULL) {
750                 (*jenv)->DeleteLocalRef(jenv, jdbtarr1);
751                 (*jenv)->DeleteLocalRef(jenv, jdbt1);
752         }
753         if (dbt2->app_data == NULL) {
754                 (*jenv)->DeleteLocalRef(jenv, jdbtarr2);
755                 (*jenv)->DeleteLocalRef(jenv, jdbt2);
756         }
757
758         if (detach)
759                 __dbj_detach();
760         return (ret);
761 }
762
763 static int __dbj_dup_compare(DB *db, const DBT *dbt1, const DBT *dbt2)
764 {
765         int detach;
766         JNIEnv *jenv = __dbj_get_jnienv(&detach);
767         jobject jdb = (jobject)DB_INTERNAL(db);
768         jbyteArray jdbtarr1, jdbtarr2;
769         int ret;
770
771         if (jdb == NULL)
772                 return (EINVAL);
773
774         jdbtarr1 = (*jenv)->NewByteArray(jenv, (jsize)dbt1->size);
775         if (jdbtarr1 == NULL)
776                 return (ENOMEM);
777         (*jenv)->SetByteArrayRegion(jenv, jdbtarr1, 0, (jsize)dbt1->size,
778             (jbyte *)dbt1->data);
779
780         jdbtarr2 = (*jenv)->NewByteArray(jenv, (jsize)dbt2->size);
781         if (jdbtarr2 == NULL)
782                 return (ENOMEM);
783         (*jenv)->SetByteArrayRegion(jenv, jdbtarr2, 0, (jsize)dbt2->size,
784             (jbyte *)dbt2->data);
785
786         ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class,
787             dup_compare_method, jdbtarr1, jdbtarr2);
788
789         if ((*jenv)->ExceptionOccurred(jenv)) {
790                 /* The exception will be thrown, so this could be any error. */
791                 ret = EINVAL;
792         }
793
794         (*jenv)->DeleteLocalRef(jenv, jdbtarr2);
795         (*jenv)->DeleteLocalRef(jenv, jdbtarr1);
796
797         if (detach)
798                 __dbj_detach();
799         return (ret);
800 }
801
802 static void __dbj_db_feedback(DB *db, int opcode, int percent)
803 {
804         int detach;
805         JNIEnv *jenv = __dbj_get_jnienv(&detach);
806         jobject jdb = (jobject)DB_INTERNAL(db);
807
808         if (jdb != NULL)
809                 (*jenv)->CallNonvirtualVoidMethod(jenv, jdb, db_class,
810                     db_feedback_method, opcode, percent);
811
812         if (detach)
813                 __dbj_detach();
814 }
815
816 static int __dbj_h_compare(DB *db, const DBT *dbt1, const DBT *dbt2)
817 {
818         return __dbj_am_compare(db, dbt1, dbt2, h_compare_method);
819 }
820
821 static u_int32_t __dbj_h_hash(DB *db, const void *data, u_int32_t len)
822 {
823         int detach;
824         JNIEnv *jenv = __dbj_get_jnienv(&detach);
825         jobject jdb = (jobject)DB_INTERNAL(db);
826         jbyteArray jarr = (*jenv)->NewByteArray(jenv, (jsize)len);
827         int ret;
828
829         if (jdb == NULL)
830                 return (EINVAL);
831
832         if ((jarr = (*jenv)->NewByteArray(jenv, (jsize)len)) == NULL)
833                 return (ENOMEM); /* An exception is pending */
834
835         (*jenv)->SetByteArrayRegion(jenv, jarr, 0, (jsize)len, (jbyte *)data);
836
837         ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class,
838             h_hash_method, jarr, len);
839
840         (*jenv)->DeleteLocalRef(jenv, jarr);
841
842         if (detach)
843                 __dbj_detach();
844         return (ret);
845 }
846
847 static u_int32_t __dbj_partition(DB *db, DBT *dbt1)
848 {
849         int detach, ret;
850         JNIEnv *jenv = __dbj_get_jnienv(&detach);
851         jobject jdb = (jobject)DB_INTERNAL(db);
852         jobject jdbt1;
853         jbyteArray jdbtarr1;
854         DBT_LOCKED lresult;
855
856         DBT_COPYOUT(1)
857
858         ret = (int)(*jenv)->CallNonvirtualIntMethod(jenv, jdb, db_class,
859             partition_method, jdbt1);
860         if ((*jenv)->ExceptionOccurred(jenv)) {
861                 /* The exception will be thrown, so this could be any error. */
862                 ret = EINVAL;
863                 goto err;
864         }
865
866         DBT_COPYIN_DATA(1)
867 err:    DBT_COPIED_FREE(1)
868
869         if (detach)
870                 __dbj_detach();
871         return (ret);
872 }
873 %}
874
875 JAVA_CALLBACK(void (*db_errcall_fcn)(const DB_ENV *,
876     const char *, const char *), com.sleepycat.db.ErrorHandler, error)
877 JAVA_CALLBACK(void (*env_feedback_fcn)(DB_ENV *, int, int),
878     com.sleepycat.db.FeedbackHandler, env_feedback)
879 JAVA_CALLBACK(void (*db_msgcall_fcn)(const DB_ENV *, const char *),
880     com.sleepycat.db.MessageHandler, message)
881 JAVA_CALLBACK(void (*db_panic_fcn)(DB_ENV *, int),
882     com.sleepycat.db.PanicHandler, panic)
883 JAVA_CALLBACK(void (*event_notify)(DB_ENV *, u_int32_t, void *),
884     com.sleepycat.db.EventHandler, event_notify)
885 JAVA_CALLBACK(int (*tx_recover)(DB_ENV *, DBT *, DB_LSN *, db_recops),
886     com.sleepycat.db.LogRecordHandler, app_dispatch)
887 JAVA_CALLBACK(int (*send)(DB_ENV *, const DBT *, const DBT *,
888                                const DB_LSN *, int, u_int32_t),
889     com.sleepycat.db.ReplicationTransport, rep_transport)
890
891 /*
892  * Db.associate is a special case, because the handler must be set in the
893  * secondary DB - that's what we have in the callback.  In addition, there
894  * are two flavors of callback (single key and multi-key), so we need to
895  * check for both types when working out whether the C callback should
896  * be NULL.  Note that this implies that the multi-key callback will be set
897  * on the secondary database *before* associate is called.
898  */
899 JAVA_CALLBACK(int (*callback)(DB *, const DBT *, const DBT *, DBT *),
900     com.sleepycat.db.SecondaryKeyCreator, seckey_create)
901 %typemap(javain) int (*callback)(DB *, const DBT *, const DBT *, DBT *)
902     %{ (secondary.seckey_create_handler = $javainput) != null ||
903         (secondary.secmultikey_create_handler != null) %}
904 JAVA_CALLBACK(int (*callback)(DB *, const DBT *, DBT *, const DBT *, int *),
905     com.sleepycat.db.ForeignKeyNullifier, foreignkey_nullify)
906 %typemap(javain) int (*callback)(DB *, const DBT *, DBT *, const DBT *, int *)
907     %{ (primary.foreignkey_nullify_handler = $javainput) != null ||
908         (primary.foreignmultikey_nullify_handler != null) %}
909
910 JAVA_CALLBACK(int (*db_append_recno_fcn)(DB *, DBT *, db_recno_t),
911     com.sleepycat.db.RecordNumberAppender, append_recno)
912 JAVA_CALLBACK(int (*bt_compare_fcn)(DB *, const DBT *, const DBT *),
913     java.util.Comparator, bt_compare)
914 JAVA_CALLBACK(int (*bt_compress_fcn)(DB *, const DBT *, const DBT *,
915     const DBT *, const DBT *, DBT *), 
916     com.sleepycat.db.BtreeCompressor, bt_compress)
917 JAVA_CALLBACK(int (*bt_decompress_fcn)(DB *, const DBT *, const DBT *,
918     DBT *, DBT *, DBT *), com.sleepycat.db.BtreeCompressor, bt_decompress)
919 JAVA_CALLBACK(u_int32_t (*db_partition_fcn)(DB *, DBT *),
920     com.sleepycat.db.PartitionHandler, partition)
921 JAVA_CALLBACK(size_t (*bt_prefix_fcn)(DB *, const DBT *, const DBT *),
922     com.sleepycat.db.BtreePrefixCalculator, bt_prefix)
923 JAVA_CALLBACK(int (*dup_compare_fcn)(DB *, const DBT *, const DBT *),
924     java.util.Comparator, dup_compare)
925 JAVA_CALLBACK(void (*db_feedback_fcn)(DB *, int, int),
926     com.sleepycat.db.FeedbackHandler, db_feedback)
927 JAVA_CALLBACK(int (*h_compare_fcn)(DB *, const DBT *, const DBT *),
928     java.util.Comparator, h_compare)
929 JAVA_CALLBACK(u_int32_t (*h_hash_fcn)(DB *, const void *, u_int32_t),
930     com.sleepycat.db.Hasher, h_hash)