1 /* Typemaps */
2 %define JAVA_TYPEMAP(_ctype, _jtype, _jnitype)
3 %typemap(jstype) _ctype #_jtype
4 %typemap(jtype) _ctype #_jtype
5 %typemap(jni) _ctype #_jnitype
6 %typemap(out) _ctype %{ $result = (_jnitype)$1; %}
7 %typemap(javain) _ctype "$javainput"
8 %typemap(javaout) _ctype { return $jnicall; }
9 %enddef
10
11 JAVA_TYPEMAP(int32_t, int, jint)
12 JAVA_TYPEMAP(u_int32_t, int, jint)
13 JAVA_TYPEMAP(u_int32_t pagesize, long, jlong)
14 JAVA_TYPEMAP(long, long, jlong)
15 JAVA_TYPEMAP(db_seq_t, long, jlong)
16 JAVA_TYPEMAP(db_size_t, long, jlong)
17 JAVA_TYPEMAP(db_ssize_t, long, jlong)
18 JAVA_TYPEMAP(pid_t, long, jlong)
19 JAVA_TYPEMAP(roff_t, long, jlong)
20 #ifndef SWIGJAVA
21 JAVA_TYPEMAP(db_threadid_t, long, jlong)
22 #endif
23 JAVA_TYPEMAP(db_timeout_t, long, jlong)
24 JAVA_TYPEMAP(size_t, long, jlong)
25 JAVA_TYPEMAP(db_ret_t, void, void)
26 %typemap(javaout) db_ret_t { $jnicall; }
27 %typemap(out) db_ret_t ""
28
29 JAVA_TYPEMAP(int_bool, boolean, jboolean)
30 %typemap(in) int_bool %{ $1 = ($input == JNI_TRUE); %}
31 %typemap(out) int_bool %{ $result = ($1) ? JNI_TRUE : JNI_FALSE; %}
32
33 /* Fake typedefs for SWIG */
34 typedef int db_ret_t; /* An int that is mapped to a void */
35 typedef int int_bool; /* An int that is mapped to a boolean */
36
37 %{
38 typedef int db_ret_t;
39 typedef int int_bool;
40
41 struct __db_lk_conflicts {
42 u_int8_t *lk_conflicts;
43 int lk_modes;
44 };
45
46 struct __db_out_stream {
47 void *handle;
48 int (*callback) __P((void *, const void *));
49 };
50
51 struct __db_repmgr_site_address {
52 const char *host;
53 u_int port;
54 };
55
56 struct __db_repmgr_sites {
57 DB_REPMGR_SITE *sites;
58 u_int32_t nsites;
59 };
60
61 #define Db __db
62 #define Dbc __dbc
63 #define Dbt __db_dbt
64 #define DbChannel __db_channel
65 #define DbEnv __db_env
66 #define DbLock __db_lock_u
67 #define DbLogc __db_log_cursor
68 #define DbLsn __db_lsn
69 #define DbMpoolFile __db_mpoolfile
70 #define DbSequence __db_sequence
71 #define DbSite __db_site
72 #define DbTxn __db_txn
73
74 /* Suppress a compilation warning for an unused symbol */
75 void *unused = (void *)SWIG_JavaThrowException;
76 %}
77
78 /* Dbt handling */
79 JAVA_TYPEMAP(DBT *, com.sleepycat.db.DatabaseEntry, jobject)
80
81 %{
82 typedef struct __dbt_locked {
83 JNIEnv *jenv;
84 jobject jdbt;
85 DBT dbt;
86 jobject jdata_nio;
87 jbyteArray jarr;
88 jint offset;
89 int reuse;
90 u_int32_t orig_size;
91 jsize array_len;
92 } DBT_LOCKED;
93
__dbj_dbt_memcopy(DBT * dbt,u_int32_t offset,void * buf,u_int32_t size,u_int32_t flags)94 static int __dbj_dbt_memcopy(DBT *dbt, u_int32_t offset, void *buf, u_int32_t size, u_int32_t flags) {
95 DBT_LOCKED *ldbt = dbt->app_data;
96 JNIEnv *jenv = ldbt->jenv;
97
98 if (size == 0)
99 return (0);
100 else if (!F_ISSET(dbt, DB_DBT_USERCOPY)) {
101 /*
102 * For simplicity, the Java API calls this function directly,
103 * so it needs to work with regular DBTs.
104 */
105 switch (flags) {
106 case DB_USERCOPY_GETDATA:
107 memcpy(buf, (u_int8_t *)dbt->data + offset, size);
108 return (0);
109 case DB_USERCOPY_SETDATA:
110 memcpy((u_int8_t *)dbt->data + offset, buf, size);
111 return (0);
112 default:
113 return (EINVAL);
114 }
115 }
116
117 switch (flags) {
118 case DB_USERCOPY_GETDATA:
119 (*jenv)->GetByteArrayRegion(jenv, ldbt->jarr, ldbt->offset +
120 offset, size, buf);
121 break;
122 case DB_USERCOPY_SETDATA:
123 /*
124 * Check whether this is the first time through the callback by relying
125 * on the offset being zero.
126 */
127 if (offset == 0 && (!ldbt->reuse ||
128 (jsize)(ldbt->offset + dbt->size) > ldbt->array_len)) {
129 if (ldbt->jarr != NULL)
130 (*jenv)->DeleteLocalRef(jenv, ldbt->jarr);
131 ldbt->jarr = (*jenv)->NewByteArray(jenv, (jsize)dbt->size);
132 if (ldbt->jarr == NULL)
133 return (ENOMEM);
134 (*jenv)->SetObjectField(jenv, ldbt->jdbt, dbt_data_fid, ldbt->jarr);
135 /* We've allocated a new array, start from the beginning. */
136 ldbt->offset = 0;
137 }
138 (*jenv)->SetByteArrayRegion(jenv, ldbt->jarr, ldbt->offset +
139 offset, size, buf);
140 break;
141 default:
142 return (EINVAL);
143 }
144 return ((*jenv)->ExceptionOccurred(jenv) ? EINVAL : 0);
145 }
146
__dbj_dbt_copyout(JNIEnv * jenv,const DBT * dbt,jbyteArray * jarr,jobject jdbt)147 static void __dbj_dbt_copyout(
148 JNIEnv *jenv, const DBT *dbt, jbyteArray *jarr, jobject jdbt)
149 {
150 jbyteArray newarr = (*jenv)->NewByteArray(jenv, (jsize)dbt->size);
151 if (newarr == NULL)
152 return; /* An exception is pending */
153 (*jenv)->SetByteArrayRegion(jenv, newarr, 0, (jsize)dbt->size,
154 (jbyte *)dbt->data);
155 (*jenv)->SetObjectField(jenv, jdbt, dbt_data_fid, newarr);
156 (*jenv)->SetIntField(jenv, jdbt, dbt_offset_fid, 0);
157 (*jenv)->SetIntField(jenv, jdbt, dbt_size_fid, (jint)dbt->size);
158 if (jarr != NULL)
159 *jarr = newarr;
160 else
161 (*jenv)->DeleteLocalRef(jenv, newarr);
162 }
163
__dbj_dbt_copyin(JNIEnv * jenv,DBT_LOCKED * ldbt,DBT ** dbtp,jobject jdbt,int allow_null)164 static int __dbj_dbt_copyin(
165 JNIEnv *jenv, DBT_LOCKED *ldbt, DBT **dbtp, jobject jdbt, int allow_null)
166 {
167 DBT *dbt;
168 jlong capacity;
169
170 memset(ldbt, 0, sizeof (*ldbt));
171 ldbt->jenv = jenv;
172 ldbt->jdbt = jdbt;
173
174 if (jdbt == NULL) {
175 if (allow_null) {
176 *dbtp = NULL;
177 return (0);
178 } else {
179 return (__dbj_throw(jenv, EINVAL,
180 "DatabaseEntry must not be null", NULL, NULL));
181 }
182 }
183
184 dbt = &ldbt->dbt;
185 if (dbtp != NULL)
186 *dbtp = dbt;
187
188 ldbt->jdata_nio = (*jenv)->GetObjectField(jenv, jdbt, dbt_data_nio_fid);
189 if (ldbt->jdata_nio != NULL)
190 F_SET(dbt, DB_DBT_USERMEM);
191 else
192 ldbt->jarr = (jbyteArray)(*jenv)->GetObjectField(jenv, jdbt, dbt_data_fid);
193 ldbt->offset = (*jenv)->GetIntField(jenv, jdbt, dbt_offset_fid);
194 dbt->size = (*jenv)->GetIntField(jenv, jdbt, dbt_size_fid);
195 ldbt->orig_size = dbt->size;
196 dbt->flags = (*jenv)->GetIntField(jenv, jdbt, dbt_flags_fid);
197
198 if (F_ISSET(dbt, DB_DBT_USERMEM))
199 dbt->ulen = (*jenv)->GetIntField(jenv, jdbt, dbt_ulen_fid);
200 if (F_ISSET(dbt, DB_DBT_PARTIAL)) {
201 dbt->dlen = (*jenv)->GetIntField(jenv, jdbt, dbt_dlen_fid);
202 dbt->doff = (*jenv)->GetIntField(jenv, jdbt, dbt_doff_fid);
203
204 if ((jint)dbt->doff < 0)
205 return (__dbj_throw(jenv, EINVAL, "DatabaseEntry doff illegal",
206 NULL, NULL));
207 }
208
209 /*
210 * We don't support DB_DBT_REALLOC - map anything that's not USERMEM to
211 * MALLOC.
212 */
213 if (!F_ISSET(dbt, DB_DBT_USERMEM)) {
214 ldbt->reuse = !F_ISSET(dbt, DB_DBT_MALLOC);
215 F_CLR(dbt, DB_DBT_MALLOC | DB_DBT_REALLOC);
216 }
217
218 /* Verify parameters before allocating or locking data. */
219 if (ldbt->jdata_nio != NULL) {
220 capacity = (*jenv)->GetDirectBufferCapacity(jenv,
221 ldbt->jdata_nio);
222 if (capacity > (jlong)UINT32_MAX)
223 return (__dbj_throw(jenv, EINVAL,
224 "DirectBuffer may not be larger than 4GB",
225 NULL, NULL));
226 ldbt->array_len = (u_int32_t)capacity;
227 } else if (ldbt->jarr == NULL) {
228 /*
229 * Some code makes the assumption that if a DBT's size or ulen
230 * is non-zero, there is data to copy from dbt->data.
231 *
232 * Clean up the dbt fields so we don't run into trouble.
233 * (Note that doff, dlen, and flags all may contain
234 * meaningful values.)
235 */
236 dbt->data = NULL;
237 ldbt->array_len = ldbt->offset = dbt->size = dbt->ulen = 0;
238 } else
239 ldbt->array_len = (*jenv)->GetArrayLength(jenv, ldbt->jarr);
240
241 if (F_ISSET(dbt, DB_DBT_USERMEM)) {
242 if (ldbt->offset < 0)
243 return (__dbj_throw(jenv, EINVAL,
244 "offset cannot be negative",
245 NULL, NULL));
246 if (dbt->size > dbt->ulen)
247 return (__dbj_throw(jenv, EINVAL,
248 "size must be less than or equal to ulen",
249 NULL, NULL));
250 if ((jsize)(ldbt->offset + dbt->ulen) > ldbt->array_len)
251 return (__dbj_throw(jenv, EINVAL,
252 "offset + ulen greater than array length",
253 NULL, NULL));
254 }
255
256 if (ldbt->jdata_nio) {
257 dbt->data = (*jenv)->GetDirectBufferAddress(jenv,
258 ldbt->jdata_nio);
259 dbt->data = (u_int8_t *)dbt->data + ldbt->offset;
260 } else if (F_ISSET(dbt, DB_DBT_USERMEM)) {
261 if (ldbt->jarr != NULL &&
262 (dbt->data = (*jenv)->GetByteArrayElements(jenv,
263 ldbt->jarr, NULL)) == NULL)
264 return (EINVAL); /* an exception will be pending */
265 dbt->data = (u_int8_t *)dbt->data + ldbt->offset;
266 } else
267 F_SET(dbt, DB_DBT_USERCOPY);
268 dbt->app_data = ldbt;
269
270 return (0);
271 }
272
__dbj_dbt_release(JNIEnv * jenv,jobject jdbt,DBT * dbt,DBT_LOCKED * ldbt)273 static void __dbj_dbt_release(
274 JNIEnv *jenv, jobject jdbt, DBT *dbt, DBT_LOCKED *ldbt) {
275 jthrowable t;
276
277 if (dbt == NULL)
278 return;
279
280 if (dbt->size != ldbt->orig_size)
281 (*jenv)->SetIntField(jenv, jdbt, dbt_size_fid, (jint)dbt->size);
282
283 if (F_ISSET(dbt, DB_DBT_USERMEM)) {
284 if (ldbt->jarr != NULL)
285 (*jenv)->ReleaseByteArrayElements(jenv, ldbt->jarr,
286 (jbyte *)dbt->data - ldbt->offset, 0);
287
288 if (dbt->size > dbt->ulen &&
289 (t = (*jenv)->ExceptionOccurred(jenv)) != NULL &&
290 (*jenv)->IsInstanceOf(jenv, t, memex_class)) {
291 (*jenv)->CallNonvirtualVoidMethod(jenv, t, memex_class,
292 memex_update_method, jdbt);
293 /*
294 * We have to rethrow the exception because calling
295 * into Java clears it.
296 */
297 (*jenv)->Throw(jenv, t);
298 }
299 }
300 }
301 %}
302
303 %typemap(in) DBT * (DBT_LOCKED ldbt) %{
304 if (__dbj_dbt_copyin(jenv, &ldbt, &$1, $input, 0) != 0) {
305 return $null; /* An exception will be pending. */
306 }%}
307
308 /* Special cases for DBTs that may be null: DbEnv.rep_start, Db.compact Db.set_partition */
309 %typemap(in) DBT *data_or_null (DBT_LOCKED ldbt) %{
310 if (__dbj_dbt_copyin(jenv, &ldbt, &$1, $input, 1) != 0) {
311 return $null; /* An exception will be pending. */
312 }%}
313
314 %apply DBT *data_or_null {DBT *cdata, DBT *start, DBT *stop, DBT *end, DBT *db_put_data, DBT *keys};
315
316 %typemap(freearg) DBT * %{ __dbj_dbt_release(jenv, $input, $1, &ldbt$argnum); %}
317
318 /* DB_TXN_TOKEN handling */
319 JAVA_TYPEMAP(DB_TXN_TOKEN *, byte[], jobject)
320
321 %typemap(check) DB_TXN_TOKEN * %{
322 if ($1 == NULL) {
323 __dbj_throw(jenv, EINVAL, "null txn commit token", NULL, NULL);
324 return $null;
325 }
326 %}
327
328
329 %typemap(in) DB_TXN_TOKEN * (DB_TXN_TOKEN token) %{
330 if ($input == NULL) {
331 $1 = NULL;
332 } else {
333 $1 = &token;
334 (*jenv)->GetByteArrayRegion(jenv, (jbyteArray)$input, 0, DB_TXN_TOKEN_SIZE, $1->buf);
335 }
336 %}
337
338 %typemap(out) DB_TXN_TOKEN * %{
339 if ($input != NULL) {
340 (*jenv)->SetByteArrayRegion(jenv, (jbyteArray)$input, 0, DB_TXN_TOKEN_SIZE, $1->buf);
341 }
342 %}
343
344 /* DbLsn handling */
345 JAVA_TYPEMAP(DB_LSN *, com.sleepycat.db.LogSequenceNumber, jobject)
346
347 %typemap(check) DB_LSN *lsn_or_null ""
348
349 %typemap(check) DB_LSN * %{
350 if ($1 == NULL) {
351 __dbj_throw(jenv, EINVAL, "null LogSequenceNumber", NULL, NULL);
352 return $null;
353 }
354 %}
355
356 %typemap(in) DB_LSN * (DB_LSN lsn) %{
357 if ($input == NULL) {
358 $1 = NULL;
359 } else {
360 $1 = &lsn;
361 $1->file = (*jenv)->GetIntField(jenv, $input, dblsn_file_fid);
362 $1->offset = (*jenv)->GetIntField(jenv, $input,
363 dblsn_offset_fid);
364 }
365 %}
366
367 %typemap(freearg) DB_LSN * %{
368 if ($input != NULL) {
369 (*jenv)->SetIntField(jenv, $input, dblsn_file_fid, $1->file);
370 (*jenv)->SetIntField(jenv, $input,
371 dblsn_offset_fid, $1->offset);
372 }
373 %}
374
375 /* Various typemaps */
376 JAVA_TYPEMAP(time_t, long, jlong)
377 JAVA_TYPEMAP(time_t *, long, jlong)
378 %typemap(in) time_t * (time_t time) %{
379 time = (time_t)$input;
380 $1 = &time;
381 %}
382
383 %typemap(in) time_t %{
384 $1 = $input;
385 %}
386
387 JAVA_TYPEMAP(u_int, long, jlong)
388 JAVA_TYPEMAP(u_int *, long, jlong)
389 %typemap(in) u_int * (u_int value) %{
390 value = (u_int)$input;
391 $1 = &value;
392 %}
393
394 %typemap(in) u_int %{
395 $1 = $input;
396 %}
397
398 JAVA_TYPEMAP(DB_KEY_RANGE *, com.sleepycat.db.KeyRange, jobject)
399 %typemap(in) DB_KEY_RANGE * (DB_KEY_RANGE range) {
400 $1 = ⦥
401 }
402 %typemap(argout) DB_KEY_RANGE * {
403 (*jenv)->SetDoubleField(jenv, $input, kr_less_fid, $1->less);
404 (*jenv)->SetDoubleField(jenv, $input, kr_equal_fid, $1->equal);
405 (*jenv)->SetDoubleField(jenv, $input, kr_greater_fid, $1->greater);
406 }
407
408 JAVA_TYPEMAP(DBC **, Dbc[], jobjectArray)
409 %typemap(in) DBC ** {
410 int i, count, ret;
411
412 count = (*jenv)->GetArrayLength(jenv, $input);
413 if ((ret = __os_malloc(NULL, (count + 1) * sizeof(DBC *), &$1)) != 0) {
414 __dbj_throw(jenv, ret, NULL, NULL, DB2JDBENV);
415 return $null;
416 }
417 for (i = 0; i < count; i++) {
418 jobject jobj = (*jenv)->GetObjectArrayElement(jenv, $input, i);
419 /*
420 * A null in the array is treated as an endpoint.
421 */
422 if (jobj == NULL) {
423 $1[i] = NULL;
424 break;
425 } else {
426 jlong jptr = (*jenv)->GetLongField(jenv, jobj,
427 dbc_cptr_fid);
428 $1[i] = *(DBC **)(void *)&jptr;
429 }
430 }
431 $1[count] = NULL;
432 }
433
434 %typemap(freearg) DBC ** %{
435 __os_free(NULL, $1);
436 %}
437
438 JAVA_TYPEMAP(u_int8_t *gid, byte[], jbyteArray)
439 %typemap(check) u_int8_t *gid %{
440 if ((*jenv)->GetArrayLength(jenv, $input) < DB_GID_SIZE) {
441 __dbj_throw(jenv, EINVAL,
442 "DbTxn.prepare gid array must be >= 128 bytes", NULL,
443 TXN2JDBENV);
444 return $null;
445 }
446 %}
447
448 %typemap(in) u_int8_t *gid %{
449 $1 = (u_int8_t *)(*jenv)->GetByteArrayElements(jenv, $input, NULL);
450 %}
451
452 %typemap(freearg) u_int8_t *gid %{
453 (*jenv)->ReleaseByteArrayElements(jenv, $input, (jbyte *)$1, 0);
454 %}
455
456 %define STRING_ARRAY_OUT
457 int i, len;
458
459 len = 0;
460 while ($1[len] != NULL)
461 len++;
462 if (($result = (*jenv)->NewObjectArray(jenv, (jsize)len, string_class,
463 NULL)) == NULL)
464 return $null; /* an exception is pending */
465 for (i = 0; i < len; i++) {
466 jstring str = (*jenv)->NewStringUTF(jenv, $1[i]);
467 (*jenv)->SetObjectArrayElement(jenv, $result, (jsize)i, str);
468 }
469 %enddef
470
471 JAVA_TYPEMAP(char **, String[], jobjectArray)
472 %typemap(out) const char ** {
473 if ($1 != NULL) {
474 STRING_ARRAY_OUT
475 }
476 }
477 %typemap(out) char ** {
478 if ($1 != NULL) {
479 STRING_ARRAY_OUT
480 __os_ufree(NULL, $1);
481 }
482 }
483
484 JAVA_TYPEMAP(char **hostp, String, jobjectArray)
485
486 JAVA_TYPEMAP(struct __db_lk_conflicts, byte[][], jobjectArray)
487 %typemap(in) struct __db_lk_conflicts {
488 int i, len, ret;
489 size_t bytesize;
490
491 len = $1.lk_modes = (*jenv)->GetArrayLength(jenv, $input);
492 bytesize = sizeof(u_char) * len * len;
493
494 if ((ret = __os_malloc(NULL, bytesize, &$1.lk_conflicts)) != 0) {
495 __dbj_throw(jenv, ret, NULL, NULL, JDBENV);
496 return $null;
497 }
498
499 for (i = 0; i < len; i++) {
500 jobject sub_array = (*jenv)->GetObjectArrayElement(jenv,
501 $input, i);
502 (*jenv)->GetByteArrayRegion(jenv,(jbyteArray)sub_array, 0, len,
503 (jbyte *)&$1.lk_conflicts[i * len]);
504 }
505 }
506
507 %typemap(freearg) struct __db_lk_conflicts %{
508 __os_free(NULL, $1.lk_conflicts);
509 %}
510
511 %typemap(out) struct __db_lk_conflicts {
512 int i;
513 jbyteArray bytes;
514
515 $result = (*jenv)->NewObjectArray(jenv,
516 (jsize)$1.lk_modes, bytearray_class, NULL);
517 if ($result == NULL)
518 return $null; /* an exception is pending */
519 for (i = 0; i < $1.lk_modes; i++) {
520 bytes = (*jenv)->NewByteArray(jenv, (jsize)$1.lk_modes);
521 if (bytes == NULL)
522 return $null; /* an exception is pending */
523 (*jenv)->SetByteArrayRegion(jenv, bytes, 0, (jsize)$1.lk_modes,
524 (jbyte *)($1.lk_conflicts + i * $1.lk_modes));
525 (*jenv)->SetObjectArrayElement(jenv, $result, (jsize)i, bytes);
526 }
527 }
528
529 %{
530 struct __dbj_verify_data {
531 JNIEnv *jenv;
532 jobject streamobj;
533 jbyteArray bytes;
534 int nbytes;
535 };
536
__dbj_verify_callback(void * handle,const void * str_arg)537 static int __dbj_verify_callback(void *handle, const void *str_arg) {
538 char *str;
539 struct __dbj_verify_data *vd;
540 int len;
541 JNIEnv *jenv;
542
543 str = (char *)str_arg;
544 vd = (struct __dbj_verify_data *)handle;
545 jenv = vd->jenv;
546 len = (int)strlen(str) + 1;
547 if (len > vd->nbytes) {
548 vd->nbytes = len;
549 if (vd->bytes != NULL)
550 (*jenv)->DeleteLocalRef(jenv, vd->bytes);
551 if ((vd->bytes = (*jenv)->NewByteArray(jenv, (jsize)len))
552 == NULL)
553 return (ENOMEM);
554 }
555
556 if (vd->bytes != NULL) {
557 (*jenv)->SetByteArrayRegion(jenv, vd->bytes, 0, (jsize)len,
558 (jbyte*)str);
559 (*jenv)->CallVoidMethod(jenv, vd->streamobj,
560 outputstream_write_method, vd->bytes, 0, len - 1);
561 }
562
563 if ((*jenv)->ExceptionOccurred(jenv) != NULL)
564 return (EIO);
565
566 return (0);
567 }
568 %}
569
570 JAVA_TYPEMAP(struct __db_out_stream, java.io.OutputStream, jobject)
571 %typemap(in) struct __db_out_stream (struct __dbj_verify_data data) {
572 data.jenv = jenv;
573 data.streamobj = $input;
574 data.bytes = NULL;
575 data.nbytes = 0;
576 $1.handle = &data;
577 $1.callback = __dbj_verify_callback;
578 }
579
580 JAVA_TYPEMAP(DB_PREPLIST *, com.sleepycat.db.PreparedTransaction[],
581 jobjectArray)
582 %typemap(out) DB_PREPLIST * {
583 int i, len;
584
585 if ($1 == NULL)
586 $result = NULL;
587 else {
588 len = 0;
589 while ($1[len].txn != NULL)
590 len++;
591 $result = (*jenv)->NewObjectArray(jenv, (jsize)len, dbpreplist_class,
592 NULL);
593 if ($result == NULL)
594 return $null; /* an exception is pending */
595 for (i = 0; i < len; i++) {
596 jobject jtxn = (*jenv)->NewObject(jenv, dbtxn_class,
597 dbtxn_construct, $1[i].txn, JNI_FALSE);
598 jobject bytearr = (*jenv)->NewByteArray(jenv,
599 (jsize)sizeof($1[i].gid));
600 jobject obj = (*jenv)->NewObject(jenv, dbpreplist_class,
601 dbpreplist_construct, jtxn, bytearr);
602
603 if (jtxn == NULL || bytearr == NULL || obj == NULL)
604 return $null; /* An exception is pending */
605
606 (*jenv)->SetByteArrayRegion(jenv, bytearr, 0,
607 (jsize)sizeof($1[i].gid), (jbyte *)$1[i].gid);
608 (*jenv)->SetObjectArrayElement(jenv, $result, i, obj);
609 }
610 __os_ufree(NULL, $1);
611 }
612 }
613
614 JAVA_TYPEMAP(DB_LOCKREQ *, com.sleepycat.db.LockRequest[], jobjectArray)
615
616 %native(DbEnv_lock_vec) void DbEnv_lock_vec(DB_ENV *dbenv, u_int32_t locker,
617 u_int32_t flags, DB_LOCKREQ *list, int offset, int nlist);
618 %{
619 SWIGEXPORT void JNICALL
Java_com_sleepycat_db_internal_db_1javaJNI_DbEnv_1lock_1vec(JNIEnv * jenv,jclass jcls,jlong jdbenvp,jobject jdbenv,jint locker,jint flags,jobjectArray list,jint offset,jint count)620 Java_com_sleepycat_db_internal_db_1javaJNI_DbEnv_1lock_1vec(JNIEnv *jenv,
621 jclass jcls, jlong jdbenvp, jobject jdbenv, jint locker, jint flags,
622 jobjectArray list, jint offset, jint count) {
623 DB_ENV *dbenv;
624 DB_LOCKREQ *lockreq;
625 DB_LOCKREQ *prereq; /* preprocessed requests */
626 DB_LOCKREQ *failedreq;
627 DB_LOCK *lockp;
628 DBT_LOCKED *locked_dbts;
629 DBT *obj;
630 ENV *env;
631 int alloc_err, i, ret;
632 size_t bytesize, ldbtsize;
633 jobject jlockreq;
634 db_lockop_t op;
635 jobject jobj, jlock;
636 jlong jlockp;
637 int completed;
638
639 /*
640 * We can't easily #include "dbinc/db_ext.h" because of name
641 * clashes, so we declare this explicitly.
642 */
643 extern int __dbt_usercopy __P((ENV *, DBT *));
644 extern void __dbt_userfree __P((ENV *, DBT *, DBT *, DBT *));
645
646 COMPQUIET(jcls, NULL);
647 dbenv = *(DB_ENV **)(void *)&jdbenvp;
648 env = dbenv->env;
649 locked_dbts = NULL;
650 lockreq = NULL;
651
652 if (dbenv == NULL) {
653 __dbj_throw(jenv, EINVAL, "null object", NULL, jdbenv);
654 return;
655 }
656
657 if ((*jenv)->GetArrayLength(jenv, list) < offset + count) {
658 __dbj_throw(jenv, EINVAL,
659 "DbEnv.lock_vec array not large enough", NULL, jdbenv);
660 return;
661 }
662
663 bytesize = sizeof(DB_LOCKREQ) * count;
664 if ((ret = __os_malloc(env, bytesize, &lockreq)) != 0) {
665 __dbj_throw(jenv, ret, NULL, NULL, jdbenv);
666 return;
667 }
668 memset(lockreq, 0, bytesize);
669
670 ldbtsize = sizeof(DBT_LOCKED) * count;
671 if ((ret = __os_malloc(env, ldbtsize, &locked_dbts)) != 0) {
672 __dbj_throw(jenv, ret, NULL, NULL, jdbenv);
673 goto err;
674 }
675 memset(locked_dbts, 0, ldbtsize);
676 prereq = &lockreq[0];
677
678 /* fill in the lockreq array */
679 for (i = 0, prereq = &lockreq[0]; i < count; i++, prereq++) {
680 jlockreq = (*jenv)->GetObjectArrayElement(jenv, list,
681 offset + i);
682 if (jlockreq == NULL) {
683 __dbj_throw(jenv, EINVAL,
684 "DbEnv.lock_vec list entry is null", NULL, jdbenv);
685 goto err;
686 }
687 op = (db_lockop_t)(*jenv)->GetIntField(
688 jenv, jlockreq, lockreq_op_fid);
689 prereq->op = op;
690
691 switch (op) {
692 case DB_LOCK_GET_TIMEOUT:
693 /* Needed: mode, timeout, obj. Returned: lock. */
694 prereq->op = (db_lockop_t)(*jenv)->GetIntField(
695 jenv, jlockreq, lockreq_timeout_fid);
696 /* FALLTHROUGH */
697 case DB_LOCK_GET:
698 /* Needed: mode, obj. Returned: lock. */
699 prereq->mode = (db_lockmode_t)(*jenv)->GetIntField(
700 jenv, jlockreq, lockreq_modeflag_fid);
701 jobj = (*jenv)->GetObjectField(jenv, jlockreq,
702 lockreq_obj_fid);
703 if ((ret = __dbj_dbt_copyin(jenv,
704 &locked_dbts[i], &obj, jobj, 0)) != 0 ||
705 (ret = __dbt_usercopy(env, obj)) != 0)
706 goto err;
707 prereq->obj = obj;
708 break;
709 case DB_LOCK_PUT:
710 /* Needed: lock. Ignored: mode, obj. */
711 jlock = (*jenv)->GetObjectField(jenv, jlockreq,
712 lockreq_lock_fid);
713 if (jlock == NULL ||
714 (jlockp = (*jenv)->GetLongField(jenv, jlock,
715 lock_cptr_fid)) == 0L) {
716 __dbj_throw(jenv, EINVAL,
717 "LockRequest lock field is NULL", NULL,
718 jdbenv);
719 goto err;
720 }
721 lockp = *(DB_LOCK **)(void *)&jlockp;
722 prereq->lock = *lockp;
723 break;
724 case DB_LOCK_PUT_ALL:
725 case DB_LOCK_TIMEOUT:
726 /* Needed: (none). Ignored: lock, mode, obj. */
727 break;
728 case DB_LOCK_PUT_OBJ:
729 /* Needed: obj. Ignored: lock, mode. */
730 jobj = (*jenv)->GetObjectField(jenv, jlockreq,
731 lockreq_obj_fid);
732 if ((ret = __dbj_dbt_copyin(jenv,
733 &locked_dbts[i], &obj, jobj, 0)) != 0 ||
734 (ret = __dbt_usercopy(env, obj)) != 0)
735 goto err;
736 prereq->obj = obj;
737 break;
738 default:
739 __dbj_throw(jenv, EINVAL,
740 "DbEnv.lock_vec bad op value", NULL, jdbenv);
741 goto err;
742 }
743 }
744
745 ret = dbenv->lock_vec(dbenv, (u_int32_t)locker, (u_int32_t)flags,
746 lockreq, count, &failedreq);
747 if (ret == 0)
748 completed = count;
749 else
750 completed = (int)(failedreq - lockreq);
751
752 /* do post processing for any and all requests that completed */
753 for (i = 0; i < completed; i++) {
754 op = lockreq[i].op;
755 if (op == DB_LOCK_PUT) {
756 /*
757 * After a successful put, the DbLock can no longer be
758 * used, so we release the storage related to it.
759 */
760 jlockreq = (*jenv)->GetObjectArrayElement(jenv,
761 list, i + offset);
762 jlock = (*jenv)->GetObjectField(jenv, jlockreq,
763 lockreq_lock_fid);
764 jlockp = (*jenv)->GetLongField(jenv, jlock,
765 lock_cptr_fid);
766 lockp = *(DB_LOCK **)(void *)&jlockp;
767 __os_free(NULL, lockp);
768 (*jenv)->SetLongField(jenv, jlock, lock_cptr_fid,
769 (jlong)0);
770 } else if (op == DB_LOCK_GET_TIMEOUT || op == DB_LOCK_GET) {
771 /*
772 * Store the lock that was obtained. We need to create
773 * storage for it since the lockreq array only exists
774 * during this method call.
775 */
776 if ((alloc_err =
777 __os_malloc(env, sizeof(DB_LOCK), &lockp)) != 0) {
778 __dbj_throw(jenv, alloc_err, NULL, NULL,
779 jdbenv);
780 goto err;
781 }
782
783 *lockp = lockreq[i].lock;
784 *(DB_LOCK **)(void *)&jlockp = lockp;
785
786 jlockreq = (*jenv)->GetObjectArrayElement(jenv,
787 list, i + offset);
788 jlock = (*jenv)->NewObject(jenv, lock_class,
789 lock_construct, jlockp, JNI_TRUE);
790 if (jlock == NULL)
791 goto err; /* An exception is pending */
792 (*jenv)->SetLongField(jenv, jlock, lock_cptr_fid,
793 jlockp);
794 (*jenv)->SetObjectField(jenv, jlockreq,
795 lockreq_lock_fid, jlock);
796 }
797 }
798
799 /* If one of the locks was not granted, build the exception now. */
800 if (ret == DB_LOCK_NOTGRANTED && i < count) {
801 jlockreq = (*jenv)->GetObjectArrayElement(jenv, list,
802 i + offset);
803 jobj = (*jenv)->GetObjectField(jenv, jlockreq, lockreq_obj_fid);
804 jlock = (*jenv)->GetObjectField(jenv, jlockreq,
805 lockreq_lock_fid);
806 (*jenv)->Throw(jenv,
807 (*jenv)->NewObject(jenv, lockex_class, lockex_construct,
808 (*jenv)->NewStringUTF(jenv, "DbEnv.lock_vec incomplete"),
809 lockreq[i].op, lockreq[i].mode, jobj, jlock, i, jdbenv));
810 } else if (ret != 0)
811 __dbj_throw(jenv, ret, NULL, NULL, jdbenv);
812
813 err: for (i = 0, prereq = &lockreq[0]; i < count; i++, prereq++)
814 if (prereq->op == DB_LOCK_GET_TIMEOUT ||
815 prereq->op == DB_LOCK_GET ||
816 prereq->op == DB_LOCK_PUT_OBJ) {
817 jlockreq = (*jenv)->GetObjectArrayElement(jenv,
818 list, i + offset);
819 jobj = (*jenv)->GetObjectField(jenv,
820 jlockreq, lockreq_obj_fid);
821 __dbt_userfree(env, prereq->obj, NULL, NULL);
822 __dbj_dbt_release(jenv, jobj, prereq->obj, &locked_dbts[i]);
823 }
824 if (locked_dbts != NULL)
825 __os_free(env, locked_dbts);
826 if (lockreq != NULL)
827 __os_free(env, lockreq);
828 }
829 %}
830
831 %native(DbTxn_commit) void DbTxn_commit(DB_TXN *txn, u_int32_t flags);
832 %{
833 SWIGEXPORT void JNICALL
Java_com_sleepycat_db_internal_db_1javaJNI_DbTxn_1commit(JNIEnv * jenv,jclass jcls,jlong jarg1,jobject jarg1_,jint jarg2)834 Java_com_sleepycat_db_internal_db_1javaJNI_DbTxn_1commit(JNIEnv *jenv,
835 jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2) {
836 struct DbTxn *txn = (struct DbTxn *) 0 ;
837 ENV *env = (ENV *) 0 ;
838 u_int32_t flags;
839 DB_TXN_TOKEN token;
840 db_ret_t result;
841 db_ret_t result1;
842 int is_nested, is_logging_enabled, is_rep_client, commit_token_enabled;
843
844 (void)jcls;
845 txn = *(struct DbTxn **)&jarg1;
846 flags = (u_int32_t)jarg2;
847
848 if (jarg1 == 0) {
849 __dbj_throw(jenv, EINVAL, "call on closed handle", NULL, NULL);
850 return ;
851 }
852
853 /*
854 * The Java API uses set_commit_token in a different way to the C API.
855 * In Java a commit token is always generated, unless doing so would
856 * generate an error from the C API.
857 * The checks below are based on those in place in the implementation
858 * of set_commit_token in the C API. It is invalid to set a commit
859 * token for a subtransaction, or if logging is disabled, or on a rep
860 * client node.
861 */
862 env = txn->mgrp->env;
863 is_nested = (txn->parent != NULL);
864 is_logging_enabled = env->lg_handle != NULL;
865 is_rep_client = (env->rep_handle != NULL &&
866 env->rep_handle->region != NULL &&
867 F_ISSET((env->rep_handle->region), REP_F_CLIENT));
868 commit_token_enabled = (!is_nested && is_logging_enabled && !is_rep_client);
869
870 if (commit_token_enabled) {
871 result1 = (db_ret_t)txn->set_commit_token(txn, &token);
872 }
873
874 result = (db_ret_t)txn->commit(txn, flags);
875 if (!DB_RETOK_STD(result)) {
876 __dbj_throw(jenv, result, NULL, NULL, NULL);
877 }
878
879 /*
880 * Set the commit token in the Java Transaction class object only if
881 * the Core has generated a valid token for this transaction
882 */
883 if (commit_token_enabled && DB_RETOK_STD(result1)) {
884 jbyteArray newarr = (*jenv)->NewByteArray(jenv, (jsize)DB_TXN_TOKEN_SIZE);
885 if (newarr == NULL) {
886 return; /* An exception is pending */
887 }
888 (*jenv)->SetByteArrayRegion(jenv, newarr, 0, (jsize)DB_TXN_TOKEN_SIZE,
889 (jbyte *)&token);
890 (*jenv)->SetObjectField(jenv, jarg1_, txn_commit_token, newarr);
891 }
892 }
893 %}
894
895 JAVA_TYPEMAP(struct __db_repmgr_site_address,
896 com.sleepycat.db.ReplicationHostAddress, jobject)
897 %typemap(out) struct __db_repmgr_site_address
898 {
899 jstring addr_host;
900 if ($1.host == NULL)
901 return $null;
902 addr_host = (*jenv)->NewStringUTF(jenv, $1.host);
903 if (addr_host == NULL)
904 return $null; /* An exception is pending. */
905 $result = (*jenv)->NewObject(jenv,
906 rephost_class, rephost_construct, addr_host, $1.port);
907 if ($result == NULL)
908 return $null; /* An exception is pending */
909 }
910
911 JAVA_TYPEMAP(struct __db_repmgr_sites,
912 com.sleepycat.db.ReplicationManagerSiteInfo[], jobjectArray)
913 %typemap(out) struct __db_repmgr_sites
914 {
915 int i, len;
916 jobject jrep_addr, jrep_info;
917
918 len = $1.nsites;
919 $result = (*jenv)->NewObjectArray(jenv, (jsize)len, repmgr_siteinfo_class,
920 NULL);
921 if ($result == NULL)
922 return $null; /* an exception is pending */
923 for (i = 0; i < len; i++) {
924 jstring addr_host = (*jenv)->NewStringUTF(jenv, $1.sites[i].host);
925 if (addr_host == NULL)
926 return $null; /* An exception is pending */
927 jrep_addr = (*jenv)->NewObject(jenv,
928 rephost_class, rephost_construct, addr_host, $1.sites[i].port);
929 if (jrep_addr == NULL)
930 return $null; /* An exception is pending */
931
932 jrep_info = (*jenv)->NewObject(jenv,
933 repmgr_siteinfo_class, repmgr_siteinfo_construct, jrep_addr, $1.sites[i].eid);
934 if (jrep_info == NULL)
935 return $null; /* An exception is pending */
936 (*jenv)->SetIntField(jenv, jrep_info, repmgr_siteinfo_flags_fid,
937 $1.sites[i].flags);
938 (*jenv)->SetIntField(jenv, jrep_info, repmgr_siteinfo_status_fid,
939 $1.sites[i].status);
940
941 (*jenv)->SetObjectArrayElement(jenv, $result, i, jrep_info);
942 }
943 __os_ufree(NULL, $1.sites);
944 }
945
946 JAVA_TYPEMAP(void *, Object, jobject)
947
948 JAVA_TYPEMAP(DBT *chan_msgs, com.sleepycat.db.DatabaseEntry[], jobjectArray)
949 %typemap(in) DBT *chan_msgs {
950 DBT_LOCKED lresult;
951 int count, i, ret;
952
953 count = (*jenv)->GetArrayLength(jenv, $input);
954 if ((ret = __os_malloc(NULL, count * sizeof(DBT), &$1)) != 0) {
955 __dbj_throw(jenv, ret, NULL, NULL, NULL);
956 return $null;
957 }
958 memset($1, 0, count * sizeof(DBT));
959 for (i = 0; i < count; i++) {
960 jobject jresult = (*jenv)->GetObjectArrayElement(jenv, $input, i);
961 if ((ret =
962 __dbj_dbt_copyin(jenv, &lresult, NULL, jresult, 0)) != 0) {
963 return $null; /* An exception will be pending. */
964 }
965 if (lresult.dbt.size != 0) {
966 /* If there's data, we need to take a copy of it. */
967 $1[i].size = lresult.dbt.size;
968 if ((ret = __os_malloc(
969 NULL, $1[i].size, $1[i].data)) != 0) {
970 __dbj_throw(jenv, ret, NULL, NULL, NULL);
971 return $null;
972 }
973
974 if ((ret = __dbj_dbt_memcopy(&lresult.dbt, 0,
975 $1[i].data, $1[i].size, DB_USERCOPY_GETDATA)) != 0) {
976 __dbj_throw(jenv, ret, NULL, NULL, NULL);
977 return $null;
978 }
979
980 __dbj_dbt_release(jenv, jresult, &lresult.dbt, &lresult);
981 (*jenv)->DeleteLocalRef(jenv, lresult.jarr);
982 }
983 (*jenv)->DeleteLocalRef(jenv, jresult);
984 }
985 }
986
987 %typemap(freearg) DBT *chan_msgs %{
988 {
989 int count, i;
990
991 count = (*jenv)->GetArrayLength(jenv, $input);
992 for (i = 0; i < count; i++)
993 __os_free(NULL, $1[i].data);
994 __os_free(NULL, $1);
995 }
996 %}
997
998