~ubuntu-branches/ubuntu/maverick/evolution-data-server/maverick-proposed

« back to all changes in this revision

Viewing changes to libdb/libdb_java/java_info.c

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2010-05-17 17:02:06 UTC
  • mfrom: (1.1.79 upstream) (1.6.12 experimental)
  • Revision ID: james.westby@ubuntu.com-20100517170206-4ufr52vwrhh26yh0
Tags: 2.30.1-1ubuntu1
* Merge from debian experimental. Remaining change:
  (LP: #42199, #229669, #173703, #360344, #508494)
  + debian/control:
    - add Vcs-Bzr tag
    - don't use libgnome
    - Use Breaks instead of Conflicts against evolution 2.25 and earlier.
  + debian/evolution-data-server.install,
    debian/patches/45_libcamel_providers_version.patch:
    - use the upstream versioning, not a Debian-specific one 
  + debian/libedata-book1.2-dev.install, debian/libebackend-1.2-dev.install,
    debian/libcamel1.2-dev.install, debian/libedataserverui1.2-dev.install:
    - install html documentation
  + debian/rules:
    - don't build documentation it's shipped with the tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*-
2
 
 * See the file LICENSE for redistribution information.
3
 
 *
4
 
 * Copyright (c) 1997-2002
5
 
 *      Sleepycat Software.  All rights reserved.
6
 
 */
7
 
#include "db_config.h"
8
 
 
9
 
#ifndef lint
10
 
static const char revid[] = "$Id$";
11
 
#endif /* not lint */
12
 
 
13
 
#include <jni.h>
14
 
#include <errno.h>
15
 
#include <stdlib.h>
16
 
#include <string.h>
17
 
 
18
 
#include "db_int.h"
19
 
#include "java_util.h"
20
 
 
21
 
/****************************************************************
22
 
 *
23
 
 * Callback functions
24
 
 */
25
 
 
26
 
static int Db_assoc_callback(DB *db,
27
 
                             const DBT *key,
28
 
                             const DBT *data,
29
 
                             DBT *retval)
30
 
{
31
 
        DB_JAVAINFO *dbinfo;
32
 
 
33
 
        DB_ASSERT(db != NULL);
34
 
        dbinfo = (DB_JAVAINFO *)db->api_internal;
35
 
        return (dbji_call_assoc(dbinfo, db, dbinfo->jdbref,
36
 
            key, data, retval));
37
 
}
38
 
 
39
 
static void Db_feedback_callback(DB *db, int opcode, int percent)
40
 
{
41
 
        DB_JAVAINFO *dbinfo;
42
 
 
43
 
        DB_ASSERT(db != NULL);
44
 
        dbinfo = (DB_JAVAINFO *)db->api_internal;
45
 
        dbji_call_feedback(dbinfo, db, dbinfo->jdbref, opcode, percent);
46
 
}
47
 
 
48
 
static int Db_append_recno_callback(DB *db, DBT *dbt, db_recno_t recno)
49
 
{
50
 
        DB_JAVAINFO *dbinfo;
51
 
 
52
 
        dbinfo = (DB_JAVAINFO *)db->api_internal;
53
 
        return (dbji_call_append_recno(dbinfo, db, dbinfo->jdbref, dbt, recno));
54
 
}
55
 
 
56
 
static int Db_bt_compare_callback(DB *db, const DBT *dbt1, const DBT *dbt2)
57
 
{
58
 
        DB_JAVAINFO *dbinfo;
59
 
 
60
 
        dbinfo = (DB_JAVAINFO *)db->api_internal;
61
 
        return (dbji_call_bt_compare(dbinfo, db, dbinfo->jdbref, dbt1, dbt2));
62
 
}
63
 
 
64
 
static size_t Db_bt_prefix_callback(DB *db, const DBT *dbt1, const DBT *dbt2)
65
 
{
66
 
        DB_JAVAINFO *dbinfo;
67
 
 
68
 
        dbinfo = (DB_JAVAINFO *)db->api_internal;
69
 
        return (dbji_call_bt_prefix(dbinfo, db, dbinfo->jdbref, dbt1, dbt2));
70
 
}
71
 
 
72
 
static int Db_dup_compare_callback(DB *db, const DBT *dbt1, const DBT *dbt2)
73
 
{
74
 
        DB_JAVAINFO *dbinfo;
75
 
 
76
 
        dbinfo = (DB_JAVAINFO *)db->api_internal;
77
 
        return (dbji_call_dup_compare(dbinfo, db, dbinfo->jdbref, dbt1, dbt2));
78
 
}
79
 
 
80
 
static u_int32_t Db_h_hash_callback(DB *db, const void *data, u_int32_t len)
81
 
{
82
 
        DB_JAVAINFO *dbinfo;
83
 
 
84
 
        dbinfo = (DB_JAVAINFO *)db->api_internal;
85
 
        return (dbji_call_h_hash(dbinfo, db, dbinfo->jdbref, data, len));
86
 
}
87
 
 
88
 
static void DbEnv_feedback_callback(DB_ENV *dbenv, int opcode, int percent)
89
 
{
90
 
        DB_ENV_JAVAINFO *dbinfo;
91
 
 
92
 
        DB_ASSERT(dbenv != NULL);
93
 
        dbinfo = (DB_ENV_JAVAINFO *)dbenv->api2_internal;
94
 
        dbjie_call_feedback(dbinfo, dbenv, dbinfo->jenvref, opcode, percent);
95
 
}
96
 
 
97
 
static int DbEnv_rep_transport_callback(DB_ENV *dbenv,
98
 
                                        const DBT *control, const DBT *rec,
99
 
                                        int envid, u_int32_t flags)
100
 
{
101
 
        DB_ENV_JAVAINFO *dbinfo;
102
 
 
103
 
        dbinfo = (DB_ENV_JAVAINFO *)dbenv->api2_internal;
104
 
        return (dbjie_call_rep_transport(dbinfo, dbenv,
105
 
            dbinfo->jenvref, control, rec, envid, (int)flags));
106
 
}
107
 
 
108
 
static int DbEnv_app_dispatch_callback(DB_ENV *dbenv, DBT *dbt,
109
 
                                     DB_LSN *lsn, db_recops recops)
110
 
{
111
 
        DB_ENV_JAVAINFO *dbinfo;
112
 
 
113
 
        DB_ASSERT(dbenv != NULL);
114
 
        dbinfo = (DB_ENV_JAVAINFO *)dbenv->api2_internal;
115
 
        return (dbjie_call_app_dispatch(dbinfo, dbenv, dbinfo->jenvref, dbt,
116
 
            lsn, recops));
117
 
}
118
 
 
119
 
/****************************************************************
120
 
 *
121
 
 * Implementation of class DBT_javainfo
122
 
 */
123
 
DBT_JAVAINFO *
124
 
dbjit_construct()
125
 
{
126
 
        DBT_JAVAINFO *dbjit;
127
 
        int err;
128
 
 
129
 
        /*XXX should return err*/
130
 
        if ((err = __os_malloc(NULL, sizeof(DBT_JAVAINFO), &dbjit)) != 0)
131
 
                return (NULL);
132
 
 
133
 
        memset(dbjit, 0, sizeof(DBT_JAVAINFO));
134
 
        return (dbjit);
135
 
}
136
 
 
137
 
void dbjit_destroy(DBT_JAVAINFO *dbjit)
138
 
{
139
 
        DB_ASSERT(!F_ISSET(dbjit, DBT_JAVAINFO_LOCKED));
140
 
        /* Extra paranoia */
141
 
        memset(dbjit, 0, sizeof(DBT_JAVAINFO));
142
 
        (void)__os_free(NULL, dbjit);
143
 
}
144
 
 
145
 
/****************************************************************
146
 
 *
147
 
 * Implementation of class DB_ENV_JAVAINFO
148
 
 */
149
 
 
150
 
/* create/initialize an object */
151
 
DB_ENV_JAVAINFO *
152
 
dbjie_construct(JNIEnv *jnienv,
153
 
                jobject jenv,
154
 
                jobject default_errcall,
155
 
                int is_dbopen)
156
 
{
157
 
        DB_ENV_JAVAINFO *dbjie;
158
 
        int err;
159
 
 
160
 
        /*XXX should return err*/
161
 
        if ((err = __os_malloc(NULL, sizeof(DB_ENV_JAVAINFO), &dbjie)) != 0)
162
 
                return (NULL);
163
 
        memset(dbjie, 0, sizeof(DB_ENV_JAVAINFO));
164
 
        dbjie->is_dbopen = is_dbopen;
165
 
 
166
 
        if ((*jnienv)->GetJavaVM(jnienv, &dbjie->javavm) != 0) {
167
 
                __os_free(NULL, dbjie);
168
 
                report_exception(jnienv, "cannot get Java VM", 0, 0);
169
 
                return (NULL);
170
 
        }
171
 
 
172
 
        /*
173
 
         * The default error call just prints to the 'System.err'
174
 
         * stream.  If the user does set_errcall to null, we'll
175
 
         * want to have a reference to set it back to.
176
 
         *
177
 
         * Why do we have always set db_errcall to our own callback?
178
 
         * Because it makes the interaction between setting the
179
 
         * error prefix, error stream, and user's error callback
180
 
         * that much easier.
181
 
         */
182
 
        dbjie->default_errcall = NEW_GLOBAL_REF(jnienv, default_errcall);
183
 
        dbjie->errcall = NEW_GLOBAL_REF(jnienv, default_errcall);
184
 
        dbjie->jenvref = NEW_GLOBAL_REF(jnienv, jenv);
185
 
        return (dbjie);
186
 
}
187
 
 
188
 
/* release all objects held by this this one */
189
 
void dbjie_dealloc(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv)
190
 
{
191
 
        if (dbjie->feedback != NULL) {
192
 
                DELETE_GLOBAL_REF(jnienv, dbjie->feedback);
193
 
                dbjie->feedback = NULL;
194
 
        }
195
 
        if (dbjie->app_dispatch != NULL) {
196
 
                DELETE_GLOBAL_REF(jnienv, dbjie->app_dispatch);
197
 
                dbjie->app_dispatch = NULL;
198
 
        }
199
 
        if (dbjie->errcall != NULL) {
200
 
                DELETE_GLOBAL_REF(jnienv, dbjie->errcall);
201
 
                dbjie->errcall = NULL;
202
 
        }
203
 
        if (dbjie->default_errcall != NULL) {
204
 
                DELETE_GLOBAL_REF(jnienv, dbjie->default_errcall);
205
 
                dbjie->default_errcall = NULL;
206
 
        }
207
 
        if (dbjie->jenvref != NULL) {
208
 
                DELETE_GLOBAL_REF(jnienv, dbjie->jenvref);
209
 
                dbjie->jenvref = NULL;
210
 
        }
211
 
 
212
 
        if (dbjie->conflict != NULL) {
213
 
                __os_free(NULL, dbjie->conflict);
214
 
                dbjie->conflict = NULL;
215
 
                dbjie->conflict_size = 0;
216
 
        }
217
 
        if (dbjie->errpfx != NULL) {
218
 
                __os_free(NULL, dbjie->errpfx);
219
 
                dbjie->errpfx = NULL;
220
 
        }
221
 
}
222
 
 
223
 
/* free this object, releasing anything allocated on its behalf */
224
 
void dbjie_destroy(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv)
225
 
{
226
 
        dbjie_dealloc(dbjie, jnienv);
227
 
 
228
 
        /* Extra paranoia */
229
 
        memset(dbjie, 0, sizeof(DB_ENV_JAVAINFO));
230
 
        (void)__os_free(NULL, dbjie);
231
 
}
232
 
 
233
 
/*
234
 
 * Attach to the current thread that is running and
235
 
 * return that.  We use the java virtual machine
236
 
 * that we saved in the constructor.
237
 
 */
238
 
JNIEnv *
239
 
dbjie_get_jnienv(DB_ENV_JAVAINFO *dbjie)
240
 
{
241
 
        /*
242
 
         * Note:
243
 
         * Different versions of the JNI disagree on the signature
244
 
         * for AttachCurrentThread.  The most recent documentation
245
 
         * seems to say that (JNIEnv **) is correct, but newer
246
 
         * JNIs seem to use (void **), oddly enough.
247
 
         */
248
 
#ifdef JNI_VERSION_1_2
249
 
        void *attachret = 0;
250
 
#else
251
 
        JNIEnv *attachret = 0;
252
 
#endif
253
 
 
254
 
        /*
255
 
         * This should always succeed, as we are called via
256
 
         * some Java activity.  I think therefore I am (a thread).
257
 
         */
258
 
        if ((*dbjie->javavm)->AttachCurrentThread(dbjie->javavm, &attachret, 0)
259
 
            != 0)
260
 
                return (0);
261
 
 
262
 
        return ((JNIEnv *)attachret);
263
 
}
264
 
 
265
 
jstring
266
 
dbjie_get_errpfx(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv)
267
 
{
268
 
        return (get_java_string(jnienv, dbjie->errpfx));
269
 
}
270
 
 
271
 
void
272
 
dbjie_set_errcall(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv, jobject new_errcall)
273
 
{
274
 
        /*
275
 
         * If the new_errcall is null, we'll set the error call
276
 
         * to the default one.
277
 
         */
278
 
        if (new_errcall == NULL)
279
 
                new_errcall = dbjie->default_errcall;
280
 
 
281
 
        DELETE_GLOBAL_REF(jnienv, dbjie->errcall);
282
 
        dbjie->errcall = NEW_GLOBAL_REF(jnienv, new_errcall);
283
 
}
284
 
 
285
 
void
286
 
dbjie_set_errpfx(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv, jstring errpfx)
287
 
{
288
 
        if (dbjie->errpfx != NULL)
289
 
                __os_free(NULL, dbjie->errpfx);
290
 
 
291
 
        if (errpfx)
292
 
                dbjie->errpfx = get_c_string(jnienv, errpfx);
293
 
        else
294
 
                dbjie->errpfx = NULL;
295
 
}
296
 
 
297
 
void
298
 
dbjie_set_conflict(DB_ENV_JAVAINFO *dbjie, u_char *newarr, size_t size)
299
 
{
300
 
        if (dbjie->conflict != NULL)
301
 
                (void)__os_free(NULL, dbjie->conflict);
302
 
        dbjie->conflict = newarr;
303
 
        dbjie->conflict_size = size;
304
 
}
305
 
 
306
 
void dbjie_set_feedback_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv,
307
 
                               DB_ENV *dbenv, jobject jfeedback)
308
 
{
309
 
        int err;
310
 
 
311
 
        if (dbjie->feedback != NULL) {
312
 
                DELETE_GLOBAL_REF(jnienv, dbjie->feedback);
313
 
        }
314
 
        if (jfeedback == NULL) {
315
 
                if ((err = dbenv->set_feedback(dbenv, NULL)) != 0)
316
 
                        report_exception(jnienv, "set_feedback failed",
317
 
                                         err, 0);
318
 
        }
319
 
        else {
320
 
                if ((err = dbenv->set_feedback(dbenv,
321
 
                                               DbEnv_feedback_callback)) != 0)
322
 
                        report_exception(jnienv, "set_feedback failed",
323
 
                                         err, 0);
324
 
        }
325
 
 
326
 
        dbjie->feedback = NEW_GLOBAL_REF(jnienv, jfeedback);
327
 
}
328
 
 
329
 
void dbjie_call_feedback(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv, jobject jenv,
330
 
                         int opcode, int percent)
331
 
{
332
 
        JNIEnv *jnienv;
333
 
        jclass feedback_class;
334
 
        jmethodID id;
335
 
 
336
 
        COMPQUIET(dbenv, NULL);
337
 
        jnienv = dbjie_get_jnienv(dbjie);
338
 
        if (jnienv == NULL) {
339
 
                fprintf(stderr, "Cannot attach to current thread!\n");
340
 
                return;
341
 
        }
342
 
 
343
 
        if ((feedback_class =
344
 
            get_class(jnienv, name_DbEnvFeedback)) == NULL) {
345
 
                fprintf(stderr, "Cannot find callback class %s\n",
346
 
                    name_DbEnvFeedback);
347
 
                return; /* An exception has been posted. */
348
 
        }
349
 
        id = (*jnienv)->GetMethodID(jnienv, feedback_class,
350
 
                                    "feedback",
351
 
                                    "(Lcom/sleepycat/db/DbEnv;II)V");
352
 
        if (!id) {
353
 
                fprintf(stderr, "Cannot find callback method feedback\n");
354
 
                return;
355
 
        }
356
 
 
357
 
        (*jnienv)->CallVoidMethod(jnienv, dbjie->feedback, id,
358
 
                                  jenv, (jint)opcode, (jint)percent);
359
 
}
360
 
 
361
 
void dbjie_set_rep_transport_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv,
362
 
                                    DB_ENV *dbenv, int id, jobject jtransport)
363
 
{
364
 
        int err;
365
 
 
366
 
        if (dbjie->rep_transport != NULL)
367
 
                DELETE_GLOBAL_REF(jnienv, dbjie->rep_transport);
368
 
 
369
 
        err = dbenv->set_rep_transport(dbenv, id,
370
 
            DbEnv_rep_transport_callback);
371
 
        verify_return(jnienv, err, 0);
372
 
 
373
 
        dbjie->rep_transport = NEW_GLOBAL_REF(jnienv, jtransport);
374
 
}
375
 
 
376
 
int dbjie_call_rep_transport(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv,
377
 
                             jobject jenv, const DBT *control,
378
 
                             const DBT *rec, int flags, int envid)
379
 
{
380
 
        JNIEnv *jnienv;
381
 
        jclass rep_transport_class;
382
 
        jmethodID jid;
383
 
        jobject jcdbt, jrdbt;
384
 
 
385
 
        COMPQUIET(dbenv, NULL);
386
 
        jnienv = dbjie_get_jnienv(dbjie);
387
 
        if (jnienv == NULL) {
388
 
                fprintf(stderr, "Cannot attach to current thread!\n");
389
 
                return (0);
390
 
        }
391
 
 
392
 
        if ((rep_transport_class =
393
 
            get_class(jnienv, name_DbRepTransport)) == NULL) {
394
 
                fprintf(stderr, "Cannot find callback class %s\n",
395
 
                    name_DbRepTransport);
396
 
                return (0);     /* An exception has been posted. */
397
 
        }
398
 
        jid = (*jnienv)->GetMethodID(jnienv, rep_transport_class,
399
 
                                     "send",
400
 
                                     "(Lcom/sleepycat/db/DbEnv;"
401
 
                                     "Lcom/sleepycat/db/Dbt;"
402
 
                                     "Lcom/sleepycat/db/Dbt;II)I");
403
 
 
404
 
        if (!jid) {
405
 
                fprintf(stderr, "Cannot find callback method send\n");
406
 
                return (0);
407
 
        }
408
 
 
409
 
        jcdbt = get_const_Dbt(jnienv, control, NULL);
410
 
        jrdbt = get_const_Dbt(jnienv, rec, NULL);
411
 
 
412
 
        return (*jnienv)->CallIntMethod(jnienv, dbjie->rep_transport, jid, jenv,
413
 
                                        jcdbt, jrdbt, flags, envid);
414
 
}
415
 
 
416
 
void dbjie_set_app_dispatch_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv,
417
 
                                 DB_ENV *dbenv, jobject japp_dispatch)
418
 
{
419
 
        int err;
420
 
 
421
 
        if (dbjie->app_dispatch != NULL) {
422
 
                DELETE_GLOBAL_REF(jnienv, dbjie->app_dispatch);
423
 
        }
424
 
        if (japp_dispatch == NULL) {
425
 
                if ((err = dbenv->set_app_dispatch(dbenv, NULL)) != 0)
426
 
                        report_exception(jnienv, "set_app_dispatch failed",
427
 
                                         err, 0);
428
 
        }
429
 
        else {
430
 
                if ((err = dbenv->set_app_dispatch(dbenv,
431
 
                    DbEnv_app_dispatch_callback)) != 0)
432
 
                        report_exception(jnienv, "set_app_dispatch failed",
433
 
                                         err, 0);
434
 
        }
435
 
 
436
 
        dbjie->app_dispatch = NEW_GLOBAL_REF(jnienv, japp_dispatch);
437
 
}
438
 
 
439
 
int dbjie_call_app_dispatch(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv, jobject jenv,
440
 
                          DBT *dbt, DB_LSN *lsn, int recops)
441
 
{
442
 
        JNIEnv *jnienv;
443
 
        jclass app_dispatch_class;
444
 
        jmethodID id;
445
 
        jobject jdbt;
446
 
        jobject jlsn;
447
 
 
448
 
        COMPQUIET(dbenv, NULL);
449
 
        jnienv = dbjie_get_jnienv(dbjie);
450
 
        if (jnienv == NULL) {
451
 
                fprintf(stderr, "Cannot attach to current thread!\n");
452
 
                return (0);
453
 
        }
454
 
 
455
 
        if ((app_dispatch_class =
456
 
            get_class(jnienv, name_DbTxnRecover)) == NULL) {
457
 
                fprintf(stderr, "Cannot find callback class %s\n",
458
 
                    name_DbTxnRecover);
459
 
                return (0);     /* An exception has been posted. */
460
 
        }
461
 
        id = (*jnienv)->GetMethodID(jnienv, app_dispatch_class,
462
 
                                    "app_dispatch",
463
 
                                    "(Lcom/sleepycat/db/DbEnv;"
464
 
                                    "Lcom/sleepycat/db/Dbt;"
465
 
                                    "Lcom/sleepycat/db/DbLsn;"
466
 
                                    "I)I");
467
 
        if (!id) {
468
 
                fprintf(stderr, "Cannot find callback method app_dispatch\n");
469
 
                return (0);
470
 
        }
471
 
 
472
 
        jdbt = get_Dbt(jnienv, dbt, NULL);
473
 
 
474
 
        if (lsn == NULL)
475
 
                jlsn = NULL;
476
 
        else
477
 
                jlsn = get_DbLsn(jnienv, *lsn);
478
 
 
479
 
        return (*jnienv)->CallIntMethod(jnienv, dbjie->app_dispatch, id, jenv,
480
 
                                        jdbt, jlsn, recops);
481
 
}
482
 
 
483
 
jobject dbjie_get_errcall(DB_ENV_JAVAINFO *dbjie)
484
 
{
485
 
        return (dbjie->errcall);
486
 
}
487
 
 
488
 
jint dbjie_is_dbopen(DB_ENV_JAVAINFO *dbjie)
489
 
{
490
 
        return (dbjie->is_dbopen);
491
 
}
492
 
 
493
 
/****************************************************************
494
 
 *
495
 
 * Implementation of class DB_JAVAINFO
496
 
 */
497
 
 
498
 
DB_JAVAINFO *dbji_construct(JNIEnv *jnienv, jobject jdb, jint flags)
499
 
{
500
 
        DB_JAVAINFO *dbji;
501
 
        int err;
502
 
 
503
 
        /*XXX should return err*/
504
 
        if ((err = __os_malloc(NULL, sizeof(DB_JAVAINFO), &dbji)) != 0)
505
 
                return (NULL);
506
 
 
507
 
        memset(dbji, 0, sizeof(DB_JAVAINFO));
508
 
 
509
 
        if ((*jnienv)->GetJavaVM(jnienv, &dbji->javavm) != 0) {
510
 
                report_exception(jnienv, "cannot get Java VM", 0, 0);
511
 
                (void)__os_free(NULL, dbji);
512
 
                return (NULL);
513
 
        }
514
 
        dbji->jdbref = NEW_GLOBAL_REF(jnienv, jdb);
515
 
        dbji->construct_flags = flags;
516
 
        return (dbji);
517
 
}
518
 
 
519
 
void
520
 
dbji_dealloc(DB_JAVAINFO *dbji, JNIEnv *jnienv)
521
 
{
522
 
        if (dbji->append_recno != NULL) {
523
 
                DELETE_GLOBAL_REF(jnienv, dbji->append_recno);
524
 
                dbji->append_recno = NULL;
525
 
        }
526
 
        if (dbji->assoc != NULL) {
527
 
                DELETE_GLOBAL_REF(jnienv, dbji->assoc);
528
 
                dbji->assoc = NULL;
529
 
        }
530
 
        if (dbji->bt_compare != NULL) {
531
 
                DELETE_GLOBAL_REF(jnienv, dbji->bt_compare);
532
 
                dbji->bt_compare = NULL;
533
 
        }
534
 
        if (dbji->bt_prefix != NULL) {
535
 
                DELETE_GLOBAL_REF(jnienv, dbji->bt_prefix);
536
 
                dbji->bt_prefix = NULL;
537
 
        }
538
 
        if (dbji->dup_compare != NULL) {
539
 
                DELETE_GLOBAL_REF(jnienv, dbji->dup_compare);
540
 
                dbji->dup_compare = NULL;
541
 
        }
542
 
        if (dbji->feedback != NULL) {
543
 
                DELETE_GLOBAL_REF(jnienv, dbji->feedback);
544
 
                dbji->feedback = NULL;
545
 
        }
546
 
        if (dbji->h_hash != NULL) {
547
 
                DELETE_GLOBAL_REF(jnienv, dbji->h_hash);
548
 
                dbji->h_hash = NULL;
549
 
        }
550
 
        if (dbji->jdbref != NULL) {
551
 
                DELETE_GLOBAL_REF(jnienv, dbji->jdbref);
552
 
                dbji->jdbref = NULL;
553
 
        }
554
 
}
555
 
 
556
 
void
557
 
dbji_destroy(DB_JAVAINFO *dbji, JNIEnv *jnienv)
558
 
{
559
 
        dbji_dealloc(dbji, jnienv);
560
 
        __os_free(NULL, dbji);
561
 
}
562
 
 
563
 
JNIEnv *dbji_get_jnienv(DB_JAVAINFO *dbji)
564
 
{
565
 
        /*
566
 
         * Note:
567
 
         * Different versions of the JNI disagree on the signature
568
 
         * for AttachCurrentThread.  The most recent documentation
569
 
         * seems to say that (JNIEnv **) is correct, but newer
570
 
         * JNIs seem to use (void **), oddly enough.
571
 
         */
572
 
#ifdef JNI_VERSION_1_2
573
 
        void *attachret = 0;
574
 
#else
575
 
        JNIEnv *attachret = 0;
576
 
#endif
577
 
 
578
 
        /*
579
 
         * This should always succeed, as we are called via
580
 
         * some Java activity.  I think therefore I am (a thread).
581
 
         */
582
 
        if ((*dbji->javavm)->AttachCurrentThread(dbji->javavm, &attachret, 0)
583
 
            != 0)
584
 
                return (0);
585
 
 
586
 
        return ((JNIEnv *)attachret);
587
 
}
588
 
 
589
 
jint dbji_get_flags(DB_JAVAINFO *dbji)
590
 
{
591
 
        return (dbji->construct_flags);
592
 
}
593
 
 
594
 
void dbji_set_feedback_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
595
 
                              DB *db, jobject jfeedback)
596
 
{
597
 
        jclass feedback_class;
598
 
 
599
 
        if (dbji->feedback_method_id == NULL) {
600
 
                if ((feedback_class =
601
 
                    get_class(jnienv, name_DbFeedback)) == NULL)
602
 
                        return; /* An exception has been posted. */
603
 
                dbji->feedback_method_id =
604
 
                        (*jnienv)->GetMethodID(jnienv, feedback_class,
605
 
                                               "feedback",
606
 
                                               "(Lcom/sleepycat/db/Db;II)V");
607
 
                if (dbji->feedback_method_id == NULL) {
608
 
                        /*
609
 
                         * XXX
610
 
                         * We should really have a better way
611
 
                         * to translate this to a Java exception class.
612
 
                         * In theory, it shouldn't happen.
613
 
                         */
614
 
                        report_exception(jnienv, "Cannot find callback method",
615
 
                                         EFAULT, 0);
616
 
                        return;
617
 
                }
618
 
        }
619
 
 
620
 
        if (dbji->feedback != NULL) {
621
 
                DELETE_GLOBAL_REF(jnienv, dbji->feedback);
622
 
        }
623
 
        if (jfeedback == NULL) {
624
 
                db->set_feedback(db, NULL);
625
 
        }
626
 
        else {
627
 
                db->set_feedback(db, Db_feedback_callback);
628
 
        }
629
 
 
630
 
        dbji->feedback = NEW_GLOBAL_REF(jnienv, jfeedback);
631
 
 
632
 
}
633
 
 
634
 
void dbji_call_feedback(DB_JAVAINFO *dbji, DB *db, jobject jdb,
635
 
                        int opcode, int percent)
636
 
{
637
 
        JNIEnv *jnienv;
638
 
 
639
 
        COMPQUIET(db, NULL);
640
 
        jnienv = dbji_get_jnienv(dbji);
641
 
        if (jnienv == NULL) {
642
 
                fprintf(stderr, "Cannot attach to current thread!\n");
643
 
                return;
644
 
        }
645
 
 
646
 
        DB_ASSERT(dbji->feedback_method_id != NULL);
647
 
        (*jnienv)->CallVoidMethod(jnienv, dbji->feedback,
648
 
                                  dbji->feedback_method_id,
649
 
                                  jdb, (jint)opcode, (jint)percent);
650
 
}
651
 
 
652
 
void dbji_set_append_recno_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
653
 
                                  DB *db, jobject jcallback)
654
 
{
655
 
        jclass append_recno_class;
656
 
 
657
 
        if (dbji->append_recno_method_id == NULL) {
658
 
                if ((append_recno_class =
659
 
                    get_class(jnienv, name_DbAppendRecno)) == NULL)
660
 
                        return; /* An exception has been posted. */
661
 
                dbji->append_recno_method_id =
662
 
                        (*jnienv)->GetMethodID(jnienv, append_recno_class,
663
 
                                               "db_append_recno",
664
 
                                               "(Lcom/sleepycat/db/Db;"
665
 
                                               "Lcom/sleepycat/db/Dbt;I)V");
666
 
                if (dbji->append_recno_method_id == NULL) {
667
 
                        /*
668
 
                         * XXX
669
 
                         * We should really have a better way
670
 
                         * to translate this to a Java exception class.
671
 
                         * In theory, it shouldn't happen.
672
 
                         */
673
 
                        report_exception(jnienv, "Cannot find callback method",
674
 
                                         EFAULT, 0);
675
 
                        return;
676
 
                }
677
 
        }
678
 
 
679
 
        if (dbji->append_recno != NULL) {
680
 
                DELETE_GLOBAL_REF(jnienv, dbji->append_recno);
681
 
        }
682
 
        if (jcallback == NULL) {
683
 
                db->set_append_recno(db, NULL);
684
 
        }
685
 
        else {
686
 
                db->set_append_recno(db, Db_append_recno_callback);
687
 
        }
688
 
 
689
 
        dbji->append_recno = NEW_GLOBAL_REF(jnienv, jcallback);
690
 
}
691
 
 
692
 
extern int dbji_call_append_recno(DB_JAVAINFO *dbji, DB *db, jobject jdb,
693
 
                                  DBT *dbt, jint recno)
694
 
{
695
 
        JNIEnv *jnienv;
696
 
        jobject jresult;
697
 
        DBT_JAVAINFO *dbtji;
698
 
        LOCKED_DBT lresult;
699
 
        DB_ENV *dbenv;
700
 
        u_char *bytearray;
701
 
        int err;
702
 
 
703
 
        jnienv = dbji_get_jnienv(dbji);
704
 
        dbenv = db->dbenv;
705
 
        if (jnienv == NULL) {
706
 
                fprintf(stderr, "Cannot attach to current thread!\n");
707
 
                return (0);
708
 
        }
709
 
 
710
 
        jresult = get_Dbt(jnienv, dbt, &dbtji);
711
 
 
712
 
        DB_ASSERT(dbji->append_recno_method_id != NULL);
713
 
        (*jnienv)->CallVoidMethod(jnienv, dbji->append_recno,
714
 
                                  dbji->append_recno_method_id,
715
 
                                  jdb, jresult, recno);
716
 
 
717
 
        /*
718
 
         * The underlying C API requires that an errno be returned
719
 
         * on error.  Java users know nothing of errnos, so we
720
 
         * allow them to throw exceptions instead.  We leave the
721
 
         * exception in place and return DB_JAVA_CALLBACK to the C API
722
 
         * that called us.  Eventually the DB->get will fail and
723
 
         * when java prepares to throw an exception in
724
 
         * report_exception(), this will be spotted as a special case,
725
 
         * and the original exception will be preserved.
726
 
         *
727
 
         * Note: we have sometimes noticed strange behavior with
728
 
         * exceptions under Linux 1.1.7 JVM.  (i.e. multiple calls
729
 
         * to ExceptionOccurred() may report different results).
730
 
         * Currently we don't know of any problems related to this
731
 
         * in our code, but if it pops up in the future, users are
732
 
         * encouranged to get a more recent JVM.
733
 
         */
734
 
        if ((*jnienv)->ExceptionOccurred(jnienv) != NULL)
735
 
                return (DB_JAVA_CALLBACK);
736
 
 
737
 
        /*
738
 
         * Now get the DBT back from java, because the user probably
739
 
         * changed it.  We'll have to copy back the array too and let
740
 
         * our caller free it.
741
 
         *
742
 
         * We expect that the user *has* changed the DBT (why else would
743
 
         * they set up an append_recno callback?) so we don't
744
 
         * worry about optimizing the unchanged case.
745
 
         */
746
 
        if ((err = locked_dbt_get(&lresult, jnienv, dbenv, jresult, inOp)) != 0)
747
 
                return (err);
748
 
 
749
 
        memcpy(dbt, &lresult.javainfo->dbt, sizeof(DBT));
750
 
        if ((err = __os_malloc(dbenv, dbt->size, &bytearray)) != 0)
751
 
                goto out;
752
 
 
753
 
        memcpy(bytearray, dbt->data, dbt->size);
754
 
        dbt->data = bytearray;
755
 
        dbt->flags |= DB_DBT_APPMALLOC;
756
 
 
757
 
 out:
758
 
        locked_dbt_put(&lresult, jnienv, dbenv);
759
 
        return (err);
760
 
}
761
 
 
762
 
void dbji_set_assoc_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
763
 
                               DB *db, DB_TXN *txn, DB *second,
764
 
                               jobject jcallback, int flags)
765
 
{
766
 
        jclass assoc_class;
767
 
        int err;
768
 
 
769
 
        if (dbji->assoc_method_id == NULL) {
770
 
                if ((assoc_class =
771
 
                    get_class(jnienv, name_DbSecondaryKeyCreate)) == NULL)
772
 
                        return; /* An exception has been posted. */
773
 
                dbji->assoc_method_id =
774
 
                        (*jnienv)->GetMethodID(jnienv, assoc_class,
775
 
                                               "secondary_key_create",
776
 
                                               "(Lcom/sleepycat/db/Db;"
777
 
                                               "Lcom/sleepycat/db/Dbt;"
778
 
                                               "Lcom/sleepycat/db/Dbt;"
779
 
                                               "Lcom/sleepycat/db/Dbt;)I");
780
 
                if (dbji->assoc_method_id == NULL) {
781
 
                        /*
782
 
                         * XXX
783
 
                         * We should really have a better way
784
 
                         * to translate this to a Java exception class.
785
 
                         * In theory, it shouldn't happen.
786
 
                         */
787
 
                        report_exception(jnienv, "Cannot find callback method",
788
 
                                         EFAULT, 0);
789
 
                        return;
790
 
                }
791
 
        }
792
 
 
793
 
        if (dbji->assoc != NULL) {
794
 
                DELETE_GLOBAL_REF(jnienv, dbji->assoc);
795
 
                dbji->assoc = NULL;
796
 
        }
797
 
 
798
 
        if (jcallback == NULL)
799
 
                err = db->associate(db, txn, second, NULL, flags);
800
 
        else
801
 
                err = db->associate(db, txn, second, Db_assoc_callback, flags);
802
 
 
803
 
        if (verify_return(jnienv, err, 0))
804
 
                dbji->assoc = NEW_GLOBAL_REF(jnienv, jcallback);
805
 
}
806
 
 
807
 
extern int dbji_call_assoc(DB_JAVAINFO *dbji, DB *db, jobject jdb,
808
 
                           const DBT *key, const DBT *value, DBT *result)
809
 
{
810
 
        JNIEnv *jnienv;
811
 
        jobject jresult;
812
 
        LOCKED_DBT lresult;
813
 
        DB_ENV *dbenv;
814
 
        int err;
815
 
        int sz;
816
 
        u_char *bytearray;
817
 
        jint retval;
818
 
 
819
 
        jnienv = dbji_get_jnienv(dbji);
820
 
        if (jnienv == NULL) {
821
 
                fprintf(stderr, "Cannot attach to current thread!\n");
822
 
                return (0);
823
 
        }
824
 
 
825
 
        DB_ASSERT(dbji->assoc_method_id != NULL);
826
 
 
827
 
        dbenv = db->dbenv;
828
 
        jresult = create_default_object(jnienv, name_DBT);
829
 
 
830
 
        retval = (*jnienv)->CallIntMethod(jnienv, dbji->assoc,
831
 
                                          dbji->assoc_method_id, jdb,
832
 
                                          get_const_Dbt(jnienv, key, NULL),
833
 
                                          get_const_Dbt(jnienv, value, NULL),
834
 
                                          jresult);
835
 
        if (retval != 0)
836
 
                return (retval);
837
 
 
838
 
        if ((*jnienv)->ExceptionOccurred(jnienv) != NULL)
839
 
                return (DB_JAVA_CALLBACK);
840
 
 
841
 
        if ((err = locked_dbt_get(&lresult, jnienv, dbenv, jresult, inOp)) != 0)
842
 
                return (err);
843
 
 
844
 
        sz = lresult.javainfo->dbt.size;
845
 
        if (sz > 0) {
846
 
                bytearray = (u_char *)lresult.javainfo->dbt.data;
847
 
 
848
 
                /*
849
 
                 * If the byte array is in the range of one of the
850
 
                 * arrays passed to us we can use it directly.
851
 
                 * If not, we must create our own array and
852
 
                 * fill it in with the java array.  Since
853
 
                 * the java array may disappear and we don't
854
 
                 * want to keep its memory locked indefinitely,
855
 
                 * we cannot just pin the array.
856
 
                 *
857
 
                 * XXX consider pinning the array, and having
858
 
                 * some way for the C layer to notify the java
859
 
                 * layer when it can be unpinned.
860
 
                 */
861
 
                if ((bytearray < (u_char *)key->data ||
862
 
                     bytearray + sz > (u_char *)key->data + key->size) &&
863
 
                    (bytearray < (u_char *)value->data ||
864
 
                     bytearray + sz > (u_char *)value->data + value->size)) {
865
 
 
866
 
                        result->flags |= DB_DBT_APPMALLOC;
867
 
                        if ((err = __os_malloc(dbenv, sz, &bytearray)) != 0)
868
 
                                goto out;
869
 
                        memcpy(bytearray, lresult.javainfo->dbt.data, sz);
870
 
                }
871
 
                result->data = bytearray;
872
 
                result->size = sz;
873
 
        }
874
 
 out:
875
 
        locked_dbt_put(&lresult, jnienv, dbenv);
876
 
        return (err);
877
 
}
878
 
 
879
 
void dbji_set_bt_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
880
 
                                DB *db, jobject jcompare)
881
 
{
882
 
        jclass bt_compare_class;
883
 
 
884
 
        if (dbji->bt_compare_method_id == NULL) {
885
 
                if ((bt_compare_class =
886
 
                    get_class(jnienv, name_DbBtreeCompare)) == NULL)
887
 
                        return; /* An exception has been posted. */
888
 
                dbji->bt_compare_method_id =
889
 
                        (*jnienv)->GetMethodID(jnienv, bt_compare_class,
890
 
                                               "bt_compare",
891
 
                                               "(Lcom/sleepycat/db/Db;"
892
 
                                               "Lcom/sleepycat/db/Dbt;"
893
 
                                               "Lcom/sleepycat/db/Dbt;)I");
894
 
                if (dbji->bt_compare_method_id == NULL) {
895
 
                        /*
896
 
                         * XXX
897
 
                         * We should really have a better way
898
 
                         * to translate this to a Java exception class.
899
 
                         * In theory, it shouldn't happen.
900
 
                         */
901
 
                        report_exception(jnienv, "Cannot find callback method",
902
 
                                         EFAULT, 0);
903
 
                        return;
904
 
                }
905
 
        }
906
 
 
907
 
        if (dbji->bt_compare != NULL) {
908
 
                DELETE_GLOBAL_REF(jnienv, dbji->bt_compare);
909
 
        }
910
 
        if (jcompare == NULL) {
911
 
                db->set_bt_compare(db, NULL);
912
 
        }
913
 
        else {
914
 
                db->set_bt_compare(db, Db_bt_compare_callback);
915
 
        }
916
 
 
917
 
        dbji->bt_compare = NEW_GLOBAL_REF(jnienv, jcompare);
918
 
}
919
 
 
920
 
int dbji_call_bt_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb,
921
 
                         const DBT *dbt1, const DBT *dbt2)
922
 
{
923
 
        JNIEnv *jnienv;
924
 
        jobject jdbt1, jdbt2;
925
 
 
926
 
        COMPQUIET(db, NULL);
927
 
        jnienv = dbji_get_jnienv(dbji);
928
 
        if (jnienv == NULL) {
929
 
                fprintf(stderr, "Cannot attach to current thread!\n");
930
 
                return (0);
931
 
        }
932
 
 
933
 
        jdbt1 = get_const_Dbt(jnienv, dbt1, NULL);
934
 
        jdbt2 = get_const_Dbt(jnienv, dbt2, NULL);
935
 
 
936
 
        DB_ASSERT(dbji->bt_compare_method_id != NULL);
937
 
        return (*jnienv)->CallIntMethod(jnienv, dbji->bt_compare,
938
 
                                        dbji->bt_compare_method_id,
939
 
                                        jdb, jdbt1, jdbt2);
940
 
}
941
 
 
942
 
void dbji_set_bt_prefix_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
943
 
                                DB *db, jobject jprefix)
944
 
{
945
 
        jclass bt_prefix_class;
946
 
 
947
 
        if (dbji->bt_prefix_method_id == NULL) {
948
 
                if ((bt_prefix_class =
949
 
                    get_class(jnienv, name_DbBtreePrefix)) == NULL)
950
 
                        return; /* An exception has been posted. */
951
 
                dbji->bt_prefix_method_id =
952
 
                        (*jnienv)->GetMethodID(jnienv, bt_prefix_class,
953
 
                                               "bt_prefix",
954
 
                                               "(Lcom/sleepycat/db/Db;"
955
 
                                               "Lcom/sleepycat/db/Dbt;"
956
 
                                               "Lcom/sleepycat/db/Dbt;)I");
957
 
                if (dbji->bt_prefix_method_id == NULL) {
958
 
                        /*
959
 
                         * XXX
960
 
                         * We should really have a better way
961
 
                         * to translate this to a Java exception class.
962
 
                         * In theory, it shouldn't happen.
963
 
                         */
964
 
                        report_exception(jnienv, "Cannot find callback method",
965
 
                                         EFAULT, 0);
966
 
                        return;
967
 
                }
968
 
        }
969
 
 
970
 
        if (dbji->bt_prefix != NULL) {
971
 
                DELETE_GLOBAL_REF(jnienv, dbji->bt_prefix);
972
 
        }
973
 
        if (jprefix == NULL) {
974
 
                db->set_bt_prefix(db, NULL);
975
 
        }
976
 
        else {
977
 
                db->set_bt_prefix(db, Db_bt_prefix_callback);
978
 
        }
979
 
 
980
 
        dbji->bt_prefix = NEW_GLOBAL_REF(jnienv, jprefix);
981
 
}
982
 
 
983
 
size_t dbji_call_bt_prefix(DB_JAVAINFO *dbji, DB *db, jobject jdb,
984
 
                           const DBT *dbt1, const DBT *dbt2)
985
 
{
986
 
        JNIEnv *jnienv;
987
 
        jobject jdbt1, jdbt2;
988
 
 
989
 
        COMPQUIET(db, NULL);
990
 
        jnienv = dbji_get_jnienv(dbji);
991
 
        if (jnienv == NULL) {
992
 
                fprintf(stderr, "Cannot attach to current thread!\n");
993
 
                return (0);
994
 
        }
995
 
 
996
 
        jdbt1 = get_const_Dbt(jnienv, dbt1, NULL);
997
 
        jdbt2 = get_const_Dbt(jnienv, dbt2, NULL);
998
 
 
999
 
        DB_ASSERT(dbji->bt_prefix_method_id != NULL);
1000
 
        return (size_t)(*jnienv)->CallIntMethod(jnienv, dbji->bt_prefix,
1001
 
                                                dbji->bt_prefix_method_id,
1002
 
                                                jdb, jdbt1, jdbt2);
1003
 
}
1004
 
 
1005
 
void dbji_set_dup_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
1006
 
                                DB *db, jobject jcompare)
1007
 
{
1008
 
        jclass dup_compare_class;
1009
 
 
1010
 
        if (dbji->dup_compare_method_id == NULL) {
1011
 
                if ((dup_compare_class =
1012
 
                    get_class(jnienv, name_DbDupCompare)) == NULL)
1013
 
                        return; /* An exception has been posted. */
1014
 
                dbji->dup_compare_method_id =
1015
 
                        (*jnienv)->GetMethodID(jnienv, dup_compare_class,
1016
 
                                               "dup_compare",
1017
 
                                               "(Lcom/sleepycat/db/Db;"
1018
 
                                               "Lcom/sleepycat/db/Dbt;"
1019
 
                                               "Lcom/sleepycat/db/Dbt;)I");
1020
 
                if (dbji->dup_compare_method_id == NULL) {
1021
 
                        /*
1022
 
                         * XXX
1023
 
                         * We should really have a better way
1024
 
                         * to translate this to a Java exception class.
1025
 
                         * In theory, it shouldn't happen.
1026
 
                         */
1027
 
                        report_exception(jnienv, "Cannot find callback method",
1028
 
                                         EFAULT, 0);
1029
 
                        return;
1030
 
                }
1031
 
        }
1032
 
 
1033
 
        if (dbji->dup_compare != NULL)
1034
 
                DELETE_GLOBAL_REF(jnienv, dbji->dup_compare);
1035
 
 
1036
 
        if (jcompare == NULL)
1037
 
                db->set_dup_compare(db, NULL);
1038
 
        else
1039
 
                db->set_dup_compare(db, Db_dup_compare_callback);
1040
 
 
1041
 
        dbji->dup_compare = NEW_GLOBAL_REF(jnienv, jcompare);
1042
 
}
1043
 
 
1044
 
int dbji_call_dup_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb,
1045
 
                         const DBT *dbt1, const DBT *dbt2)
1046
 
{
1047
 
        JNIEnv *jnienv;
1048
 
        jobject jdbt1, jdbt2;
1049
 
 
1050
 
        COMPQUIET(db, NULL);
1051
 
        jnienv = dbji_get_jnienv(dbji);
1052
 
        if (jnienv == NULL) {
1053
 
                fprintf(stderr, "Cannot attach to current thread!\n");
1054
 
                return (0);
1055
 
        }
1056
 
 
1057
 
        jdbt1 = get_const_Dbt(jnienv, dbt1, NULL);
1058
 
        jdbt2 = get_const_Dbt(jnienv, dbt2, NULL);
1059
 
 
1060
 
        DB_ASSERT(dbji->dup_compare_method_id != NULL);
1061
 
        return (*jnienv)->CallIntMethod(jnienv, dbji->dup_compare,
1062
 
                                        dbji->dup_compare_method_id,
1063
 
                                        jdb, jdbt1, jdbt2);
1064
 
}
1065
 
 
1066
 
void dbji_set_h_hash_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
1067
 
                                DB *db, jobject jhash)
1068
 
{
1069
 
        jclass h_hash_class;
1070
 
 
1071
 
        if (dbji->h_hash_method_id == NULL) {
1072
 
                if ((h_hash_class =
1073
 
                    get_class(jnienv, name_DbHash)) == NULL)
1074
 
                        return; /* An exception has been posted. */
1075
 
                dbji->h_hash_method_id =
1076
 
                        (*jnienv)->GetMethodID(jnienv, h_hash_class,
1077
 
                                               "hash",
1078
 
                                               "(Lcom/sleepycat/db/Db;"
1079
 
                                               "[BI)I");
1080
 
                if (dbji->h_hash_method_id == NULL) {
1081
 
                        /*
1082
 
                         * XXX
1083
 
                         * We should really have a better way
1084
 
                         * to translate this to a Java exception class.
1085
 
                         * In theory, it shouldn't happen.
1086
 
                         */
1087
 
                        report_exception(jnienv, "Cannot find callback method",
1088
 
                                         EFAULT, 0);
1089
 
                        return;
1090
 
                }
1091
 
        }
1092
 
 
1093
 
        if (dbji->h_hash != NULL)
1094
 
                DELETE_GLOBAL_REF(jnienv, dbji->h_hash);
1095
 
 
1096
 
        if (jhash == NULL)
1097
 
                db->set_h_hash(db, NULL);
1098
 
        else
1099
 
                db->set_h_hash(db, Db_h_hash_callback);
1100
 
 
1101
 
        dbji->h_hash = NEW_GLOBAL_REF(jnienv, jhash);
1102
 
}
1103
 
 
1104
 
int dbji_call_h_hash(DB_JAVAINFO *dbji, DB *db, jobject jdb,
1105
 
                     const void *data, int len)
1106
 
{
1107
 
        JNIEnv *jnienv;
1108
 
        jbyteArray jdata;
1109
 
 
1110
 
        COMPQUIET(db, NULL);
1111
 
        jnienv = dbji_get_jnienv(dbji);
1112
 
        if (jnienv == NULL) {
1113
 
                fprintf(stderr, "Cannot attach to current thread!\n");
1114
 
                return (0);
1115
 
        }
1116
 
 
1117
 
        DB_ASSERT(dbji->h_hash_method_id != NULL);
1118
 
 
1119
 
        if ((jdata = (*jnienv)->NewByteArray(jnienv, len)) == NULL)
1120
 
                return (0);     /* An exception has been posted by the JVM */
1121
 
        (*jnienv)->SetByteArrayRegion(jnienv, jdata, 0, len, (void *)data);
1122
 
        return (*jnienv)->CallIntMethod(jnienv, dbji->h_hash,
1123
 
                                        dbji->h_hash_method_id,
1124
 
                                        jdb, jdata, len);
1125
 
}