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
11JAVA_TYPEMAP(int32_t, int, jint)
12JAVA_TYPEMAP(u_int32_t, int, jint)
13JAVA_TYPEMAP(u_int32_t pagesize, long, jlong)
14JAVA_TYPEMAP(long, long, jlong)
15JAVA_TYPEMAP(db_seq_t, long, jlong)
16JAVA_TYPEMAP(pid_t, long, jlong)
17#ifndef SWIGJAVA
18JAVA_TYPEMAP(db_threadid_t, long, jlong)
19#endif
20JAVA_TYPEMAP(db_timeout_t, long, jlong)
21JAVA_TYPEMAP(size_t, long, jlong)
22JAVA_TYPEMAP(db_ret_t, void, void)
23%typemap(javaout) db_ret_t { $jnicall; }
24%typemap(out) db_ret_t ""
25
26JAVA_TYPEMAP(int_bool, boolean, jboolean)
27%typemap(in) int_bool %{ $1 = ($input == JNI_TRUE); %}
28%typemap(out) int_bool %{ $result = ($1) ? JNI_TRUE : JNI_FALSE; %}
29
30/* Dbt handling */
31JAVA_TYPEMAP(DBT *, com.sleepycat.db.DatabaseEntry, jobject)
32
33%{
34typedef struct __dbt_locked {
35	JNIEnv *jenv;
36	jobject jdbt;
37	DBT dbt;
38	jobject jdata_nio;
39	jbyteArray jarr;
40	jint offset;
41	int reuse;
42	u_int32_t orig_size;
43	jsize array_len;
44} DBT_LOCKED;
45
46static int __dbj_dbt_memcopy(DBT *dbt, u_int32_t offset, void *buf, u_int32_t size, u_int32_t flags) {
47	DBT_LOCKED *ldbt = dbt->app_data;
48	JNIEnv *jenv = ldbt->jenv;
49
50	if (size == 0)
51		return (0);
52	else if (!F_ISSET(dbt, DB_DBT_USERCOPY)) {
53		/*
54		  * For simplicity, the Java API calls this function directly,
55		  * so it needs to work with regular DBTs.
56		  */
57		switch (flags) {
58		case DB_USERCOPY_GETDATA:
59			memcpy(buf, (u_int8_t *)dbt->data + offset, size);
60			return (0);
61		case DB_USERCOPY_SETDATA:
62			memcpy((u_int8_t *)dbt->data + offset, buf, size);
63			return (0);
64		default:
65			return (EINVAL);
66		}
67	}
68
69	switch (flags) {
70	case DB_USERCOPY_GETDATA:
71		(*jenv)->GetByteArrayRegion(jenv, ldbt->jarr, ldbt->offset +
72					    offset, size, buf);
73		break;
74	case DB_USERCOPY_SETDATA:
75		/*
76		 * Check whether this is the first time through the callback by relying
77		 * on the offset being zero.
78		 */
79		if (offset == 0 && (!ldbt->reuse ||
80		    (jsize)(ldbt->offset + dbt->size) > ldbt->array_len)) {
81			if (ldbt->jarr != NULL)
82				(*jenv)->DeleteLocalRef(jenv, ldbt->jarr);
83			ldbt->jarr = (*jenv)->NewByteArray(jenv, (jsize)dbt->size);
84			if (ldbt->jarr == NULL)
85				return (ENOMEM);
86			(*jenv)->SetObjectField(jenv, ldbt->jdbt, dbt_data_fid, ldbt->jarr);
87			/* We've allocated a new array, start from the beginning. */
88			ldbt->offset = 0;
89		}
90		(*jenv)->SetByteArrayRegion(jenv, ldbt->jarr, ldbt->offset +
91					    offset, size, buf);
92		break;
93	default:
94		return (EINVAL);
95	}
96	return ((*jenv)->ExceptionOccurred(jenv) ? EINVAL : 0);
97}
98
99static void __dbj_dbt_copyout(
100    JNIEnv *jenv, const DBT *dbt, jbyteArray *jarr, jobject jdbt)
101{
102	jbyteArray newarr = (*jenv)->NewByteArray(jenv, (jsize)dbt->size);
103	if (newarr == NULL)
104		return; /* An exception is pending */
105	(*jenv)->SetByteArrayRegion(jenv, newarr, 0, (jsize)dbt->size,
106	    (jbyte *)dbt->data);
107	(*jenv)->SetObjectField(jenv, jdbt, dbt_data_fid, newarr);
108	(*jenv)->SetIntField(jenv, jdbt, dbt_offset_fid, 0);
109	(*jenv)->SetIntField(jenv, jdbt, dbt_size_fid, (jint)dbt->size);
110	if (jarr != NULL)
111		*jarr = newarr;
112	else
113		(*jenv)->DeleteLocalRef(jenv, newarr);
114}
115
116static int __dbj_dbt_copyin(
117    JNIEnv *jenv, DBT_LOCKED *ldbt, DBT **dbtp, jobject jdbt, int allow_null)
118{
119	DBT *dbt;
120	jlong capacity;
121
122	memset(ldbt, 0, sizeof (*ldbt));
123	ldbt->jenv = jenv;
124	ldbt->jdbt = jdbt;
125
126	if (jdbt == NULL) {
127		if (allow_null) {
128			*dbtp = NULL;
129			return (0);
130		} else {
131			return (__dbj_throw(jenv, EINVAL,
132			    "DatabaseEntry must not be null", NULL, NULL));
133		}
134	}
135
136	dbt = &ldbt->dbt;
137	if (dbtp != NULL)
138		*dbtp = dbt;
139
140	ldbt->jdata_nio = (*jenv)->GetObjectField(jenv, jdbt, dbt_data_nio_fid);
141	if (ldbt->jdata_nio != NULL)
142		F_SET(dbt, DB_DBT_USERMEM);
143	else
144		ldbt->jarr = (jbyteArray)(*jenv)->GetObjectField(jenv, jdbt, dbt_data_fid);
145	ldbt->offset = (*jenv)->GetIntField(jenv, jdbt, dbt_offset_fid);
146	dbt->size = (*jenv)->GetIntField(jenv, jdbt, dbt_size_fid);
147	ldbt->orig_size = dbt->size;
148	dbt->flags = (*jenv)->GetIntField(jenv, jdbt, dbt_flags_fid);
149
150	if (F_ISSET(dbt, DB_DBT_USERMEM))
151		dbt->ulen = (*jenv)->GetIntField(jenv, jdbt, dbt_ulen_fid);
152	if (F_ISSET(dbt, DB_DBT_PARTIAL)) {
153		dbt->dlen = (*jenv)->GetIntField(jenv, jdbt, dbt_dlen_fid);
154		dbt->doff = (*jenv)->GetIntField(jenv, jdbt, dbt_doff_fid);
155
156		if ((jint)dbt->doff < 0)
157			return (__dbj_throw(jenv, EINVAL, "DatabaseEntry doff illegal",
158			    NULL, NULL));
159	}
160
161	/*
162	 * We don't support DB_DBT_REALLOC - map anything that's not USERMEM to
163	 * MALLOC.
164	 */
165	if (!F_ISSET(dbt, DB_DBT_USERMEM)) {
166		ldbt->reuse = !F_ISSET(dbt, DB_DBT_MALLOC);
167		F_CLR(dbt, DB_DBT_MALLOC | DB_DBT_REALLOC);
168	}
169
170	/* Verify parameters before allocating or locking data. */
171	if (ldbt->jdata_nio != NULL) {
172		capacity = (*jenv)->GetDirectBufferCapacity(jenv,
173				ldbt->jdata_nio);
174		if (capacity > (jlong)UINT32_MAX)
175			return (__dbj_throw(jenv, EINVAL,
176			    "DirectBuffer may not be larger than 4GB",
177			    NULL, NULL));
178		ldbt->array_len = (u_int32_t)capacity;
179	} else if (ldbt->jarr == NULL) {
180		/*
181		 * Some code makes the assumption that if a DBT's size or ulen
182		 * is non-zero, there is data to copy from dbt->data.
183		 *
184		 * Clean up the dbt fields so we don't run into trouble.
185		 * (Note that doff, dlen, and flags all may contain
186		 * meaningful values.)
187		 */
188		dbt->data = NULL;
189		ldbt->array_len = ldbt->offset = dbt->size = dbt->ulen = 0;
190	} else
191		ldbt->array_len = (*jenv)->GetArrayLength(jenv, ldbt->jarr);
192
193	if (F_ISSET(dbt, DB_DBT_USERMEM)) {
194		if (ldbt->offset < 0)
195			return (__dbj_throw(jenv, EINVAL,
196			    "offset cannot be negative",
197			    NULL, NULL));
198		if (dbt->size > dbt->ulen)
199			return (__dbj_throw(jenv, EINVAL,
200			    "size must be less than or equal to ulen",
201			    NULL, NULL));
202		if ((jsize)(ldbt->offset + dbt->ulen) > ldbt->array_len)
203			return (__dbj_throw(jenv, EINVAL,
204			    "offset + ulen greater than array length",
205			    NULL, NULL));
206	}
207
208	if (ldbt->jdata_nio) {
209		dbt->data = (*jenv)->GetDirectBufferAddress(jenv,
210				ldbt->jdata_nio);
211		dbt->data = (u_int8_t *)dbt->data + ldbt->offset;
212	} else if (F_ISSET(dbt, DB_DBT_USERMEM)) {
213		if (ldbt->jarr != NULL &&
214		    (dbt->data = (*jenv)->GetByteArrayElements(jenv,
215		    ldbt->jarr, NULL)) == NULL)
216			return (EINVAL); /* an exception will be pending */
217		dbt->data = (u_int8_t *)dbt->data + ldbt->offset;
218	} else
219		F_SET(dbt, DB_DBT_USERCOPY);
220	dbt->app_data = ldbt;
221
222	return (0);
223}
224
225static void __dbj_dbt_release(
226    JNIEnv *jenv, jobject jdbt, DBT *dbt, DBT_LOCKED *ldbt) {
227	jthrowable t;
228
229	if (dbt == NULL)
230		return;
231
232	if (dbt->size != ldbt->orig_size)
233		(*jenv)->SetIntField(jenv, jdbt, dbt_size_fid, (jint)dbt->size);
234
235	if (F_ISSET(dbt, DB_DBT_USERMEM)) {
236		if (ldbt->jarr != NULL)
237			(*jenv)->ReleaseByteArrayElements(jenv, ldbt->jarr,
238			    (jbyte *)dbt->data - ldbt->offset, 0);
239
240		if (dbt->size > dbt->ulen &&
241		    (t = (*jenv)->ExceptionOccurred(jenv)) != NULL &&
242		    (*jenv)->IsInstanceOf(jenv, t, memex_class)) {
243			(*jenv)->CallNonvirtualVoidMethod(jenv, t, memex_class,
244			    memex_update_method, jdbt);
245			/*
246			 * We have to rethrow the exception because calling
247			 * into Java clears it.
248			 */
249			(*jenv)->Throw(jenv, t);
250		}
251	}
252}
253%}
254
255%typemap(in) DBT * (DBT_LOCKED ldbt) %{
256	if (__dbj_dbt_copyin(jenv, &ldbt, &$1, $input, 0) != 0) {
257		return $null; /* An exception will be pending. */
258	}%}
259
260/* Special cases for DBTs that may be null: DbEnv.rep_start and Db.compact */
261%typemap(in) DBT *data_or_null (DBT_LOCKED ldbt) %{
262	if (__dbj_dbt_copyin(jenv, &ldbt, &$1, $input, 1) != 0) {
263		return $null; /* An exception will be pending. */
264	}%}
265
266%apply DBT *data_or_null {DBT *cdata, DBT *start, DBT *stop, DBT *end};
267
268%typemap(freearg) DBT * %{ __dbj_dbt_release(jenv, $input, $1, &ldbt$argnum); %}
269
270/* DbLsn handling */
271JAVA_TYPEMAP(DB_LSN *, com.sleepycat.db.LogSequenceNumber, jobject)
272
273%typemap(check) DB_LSN *lsn_or_null ""
274
275%typemap(check) DB_LSN * %{
276	if ($1 == NULL) {
277		__dbj_throw(jenv, EINVAL, "null LogSequenceNumber", NULL, NULL);
278		return $null;
279	}
280%}
281
282%typemap(in) DB_LSN * (DB_LSN lsn) %{
283	if ($input == NULL) {
284		$1 = NULL;
285	} else {
286		$1 = &lsn;
287		$1->file = (*jenv)->GetIntField(jenv, $input, dblsn_file_fid);
288		$1->offset = (*jenv)->GetIntField(jenv, $input,
289		    dblsn_offset_fid);
290	}
291%}
292
293%typemap(freearg) DB_LSN * %{
294	if ($input != NULL) {
295		(*jenv)->SetIntField(jenv, $input, dblsn_file_fid, $1->file);
296		(*jenv)->SetIntField(jenv, $input,
297		    dblsn_offset_fid, $1->offset);
298	}
299%}
300
301/* Various typemaps */
302JAVA_TYPEMAP(time_t, long, jlong)
303JAVA_TYPEMAP(time_t *, long, jlong)
304%typemap(in) time_t * (time_t time) %{
305	time = (time_t)$input;
306	$1 = &time;
307%}
308
309JAVA_TYPEMAP(DB_KEY_RANGE *, com.sleepycat.db.KeyRange, jobject)
310%typemap(in) DB_KEY_RANGE * (DB_KEY_RANGE range) {
311	$1 = &range;
312}
313%typemap(argout) DB_KEY_RANGE * {
314	(*jenv)->SetDoubleField(jenv, $input, kr_less_fid, $1->less);
315	(*jenv)->SetDoubleField(jenv, $input, kr_equal_fid, $1->equal);
316	(*jenv)->SetDoubleField(jenv, $input, kr_greater_fid, $1->greater);
317}
318
319JAVA_TYPEMAP(DBC **, Dbc[], jobjectArray)
320%typemap(in) DBC ** {
321	int i, count, err;
322
323	count = (*jenv)->GetArrayLength(jenv, $input);
324	if ((err = __os_malloc(NULL, (count + 1) * sizeof(DBC *), &$1)) != 0) {
325		__dbj_throw(jenv, err, NULL, NULL, DB2JDBENV);
326		return $null;
327	}
328	for (i = 0; i < count; i++) {
329		jobject jobj = (*jenv)->GetObjectArrayElement(jenv, $input, i);
330		/*
331		 * A null in the array is treated as an endpoint.
332		 */
333		if (jobj == NULL) {
334			$1[i] = NULL;
335			break;
336		} else {
337			jlong jptr = (*jenv)->GetLongField(jenv, jobj,
338			    dbc_cptr_fid);
339			$1[i] = *(DBC **)(void *)&jptr;
340		}
341	}
342	$1[count] = NULL;
343}
344
345%typemap(freearg) DBC ** %{
346	__os_free(NULL, $1);
347%}
348
349JAVA_TYPEMAP(u_int8_t *gid, byte[], jbyteArray)
350%typemap(check) u_int8_t *gid %{
351	if ((*jenv)->GetArrayLength(jenv, $input) < DB_XIDDATASIZE) {
352		__dbj_throw(jenv, EINVAL,
353		    "DbTxn.prepare gid array must be >= 128 bytes", NULL,
354		    TXN2JDBENV);
355		return $null;
356	}
357%}
358
359%typemap(in) u_int8_t *gid %{
360	$1 = (u_int8_t *)(*jenv)->GetByteArrayElements(jenv, $input, NULL);
361%}
362
363%typemap(freearg) u_int8_t *gid %{
364	(*jenv)->ReleaseByteArrayElements(jenv, $input, (jbyte *)$1, 0);
365%}
366
367%define STRING_ARRAY_OUT
368	int i, len;
369
370	len = 0;
371	while ($1[len] != NULL)
372		len++;
373	if (($result = (*jenv)->NewObjectArray(jenv, (jsize)len, string_class,
374	    NULL)) == NULL)
375		return $null; /* an exception is pending */
376	for (i = 0; i < len; i++) {
377		jstring str = (*jenv)->NewStringUTF(jenv, $1[i]);
378		(*jenv)->SetObjectArrayElement(jenv, $result, (jsize)i, str);
379	}
380%enddef
381
382JAVA_TYPEMAP(char **, String[], jobjectArray)
383%typemap(out) const char ** {
384	if ($1 != NULL) {
385		STRING_ARRAY_OUT
386	}
387}
388%typemap(out) char ** {
389	if ($1 != NULL) {
390		STRING_ARRAY_OUT
391		__os_ufree(NULL, $1);
392	}
393}
394
395JAVA_TYPEMAP(struct __db_lk_conflicts, byte[][], jobjectArray)
396%typemap(in) struct __db_lk_conflicts {
397	int i, len, err;
398	size_t bytesize;
399
400	len = $1.lk_modes = (*jenv)->GetArrayLength(jenv, $input);
401	bytesize = sizeof(u_char) * len * len;
402
403	if ((err = __os_malloc(NULL, bytesize, &$1.lk_conflicts)) != 0) {
404		__dbj_throw(jenv, err, NULL, NULL, JDBENV);
405		return $null;
406	}
407
408	for (i = 0; i < len; i++) {
409		jobject sub_array = (*jenv)->GetObjectArrayElement(jenv,
410		    $input, i);
411		(*jenv)->GetByteArrayRegion(jenv,(jbyteArray)sub_array, 0, len,
412		    (jbyte *)&$1.lk_conflicts[i * len]);
413	}
414}
415
416%typemap(freearg) struct __db_lk_conflicts %{
417	__os_free(NULL, $1.lk_conflicts);
418%}
419
420%typemap(out) struct __db_lk_conflicts {
421	int i;
422	jbyteArray bytes;
423
424	$result = (*jenv)->NewObjectArray(jenv,
425	    (jsize)$1.lk_modes, bytearray_class, NULL);
426	if ($result == NULL)
427		return $null; /* an exception is pending */
428	for (i = 0; i < $1.lk_modes; i++) {
429		bytes = (*jenv)->NewByteArray(jenv, (jsize)$1.lk_modes);
430		if (bytes == NULL)
431			return $null; /* an exception is pending */
432		(*jenv)->SetByteArrayRegion(jenv, bytes, 0, (jsize)$1.lk_modes,
433		    (jbyte *)($1.lk_conflicts + i * $1.lk_modes));
434		(*jenv)->SetObjectArrayElement(jenv, $result, (jsize)i, bytes);
435	}
436}
437
438%{
439struct __dbj_verify_data {
440	JNIEnv *jenv;
441	jobject streamobj;
442	jbyteArray bytes;
443	int nbytes;
444};
445
446static int __dbj_verify_callback(void *handle, const void *str_arg) {
447	char *str;
448	struct __dbj_verify_data *vd;
449	int len;
450	JNIEnv *jenv;
451
452	str = (char *)str_arg;
453	vd = (struct __dbj_verify_data *)handle;
454	jenv = vd->jenv;
455	len = strlen(str) + 1;
456	if (len > vd->nbytes) {
457		vd->nbytes = len;
458		if (vd->bytes != NULL)
459			(*jenv)->DeleteLocalRef(jenv, vd->bytes);
460		if ((vd->bytes = (*jenv)->NewByteArray(jenv, (jsize)len))
461		    == NULL)
462			return (ENOMEM);
463	}
464
465	if (vd->bytes != NULL) {
466		(*jenv)->SetByteArrayRegion(jenv, vd->bytes, 0, (jsize)len,
467		    (jbyte*)str);
468		(*jenv)->CallVoidMethod(jenv, vd->streamobj,
469		    outputstream_write_method, vd->bytes, 0, len - 1);
470	}
471
472	if ((*jenv)->ExceptionOccurred(jenv) != NULL)
473		return (EIO);
474
475	return (0);
476}
477%}
478
479JAVA_TYPEMAP(struct __db_out_stream, java.io.OutputStream, jobject)
480%typemap(in) struct __db_out_stream (struct __dbj_verify_data data) {
481	data.jenv = jenv;
482	data.streamobj = $input;
483	data.bytes = NULL;
484	data.nbytes = 0;
485	$1.handle = &data;
486	$1.callback = __dbj_verify_callback;
487}
488
489JAVA_TYPEMAP(DB_PREPLIST *, com.sleepycat.db.PreparedTransaction[],
490    jobjectArray)
491%typemap(out) DB_PREPLIST * {
492	int i, len;
493
494	len = 0;
495	while ($1[len].txn != NULL)
496		len++;
497	$result = (*jenv)->NewObjectArray(jenv, (jsize)len, dbpreplist_class,
498	    NULL);
499	if ($result == NULL)
500		return $null; /* an exception is pending */
501	for (i = 0; i < len; i++) {
502		jobject jtxn = (*jenv)->NewObject(jenv, dbtxn_class,
503		    dbtxn_construct, $1[i].txn, JNI_FALSE);
504		jobject bytearr = (*jenv)->NewByteArray(jenv,
505		    (jsize)sizeof($1[i].gid));
506		jobject obj = (*jenv)->NewObject(jenv, dbpreplist_class,
507		    dbpreplist_construct, jtxn, bytearr);
508
509		if (jtxn == NULL || bytearr == NULL || obj == NULL)
510			return $null; /* An exception is pending */
511
512		(*jenv)->SetByteArrayRegion(jenv, bytearr, 0,
513		    (jsize)sizeof($1[i].gid), (jbyte *)$1[i].gid);
514		(*jenv)->SetObjectArrayElement(jenv, $result, i, obj);
515	}
516	__os_ufree(NULL, $1);
517}
518
519JAVA_TYPEMAP(DB_LOCKREQ *, com.sleepycat.db.LockRequest[], jobjectArray)
520
521%native(DbEnv_lock_vec) void DbEnv_lock_vec(DB_ENV *dbenv, u_int32_t locker,
522    u_int32_t flags, DB_LOCKREQ *list, int offset, int nlist);
523%{
524SWIGEXPORT void JNICALL
525Java_com_sleepycat_db_internal_db_1javaJNI_DbEnv_1lock_1vec(JNIEnv *jenv,
526    jclass jcls, jlong jdbenvp, jobject jdbenv, jint locker, jint flags,
527    jobjectArray list, jint offset, jint count) {
528	DB_ENV *dbenv;
529	DB_LOCKREQ *lockreq;
530	DB_LOCKREQ *prereq;	/* preprocessed requests */
531	DB_LOCKREQ *failedreq;
532	DB_LOCK *lockp;
533	DBT_LOCKED *locked_dbts;
534	DBT *obj;
535	ENV *env;
536	int err, alloc_err, i;
537	size_t bytesize, ldbtsize;
538	jobject jlockreq;
539	db_lockop_t op;
540	jobject jobj, jlock;
541	jlong jlockp;
542	int completed;
543
544	COMPQUIET(jcls, NULL);
545	dbenv = *(DB_ENV **)(void *)&jdbenvp;
546	env = dbenv->env;
547
548	if (dbenv == NULL) {
549		__dbj_throw(jenv, EINVAL, "null object", NULL, jdbenv);
550		return;
551	}
552
553	if ((*jenv)->GetArrayLength(jenv, list) < offset + count) {
554		__dbj_throw(jenv, EINVAL,
555		    "DbEnv.lock_vec array not large enough", NULL, jdbenv);
556		goto out0;
557	}
558
559	bytesize = sizeof(DB_LOCKREQ) * count;
560	if ((err = __os_malloc(env, bytesize, &lockreq)) != 0) {
561		__dbj_throw(jenv, err, NULL, NULL, jdbenv);
562		goto out0;
563	}
564	memset(lockreq, 0, bytesize);
565
566	ldbtsize = sizeof(DBT_LOCKED) * count;
567	if ((err = __os_malloc(env, ldbtsize, &locked_dbts)) != 0) {
568		__dbj_throw(jenv, err, NULL, NULL, jdbenv);
569		goto out1;
570	}
571	memset(locked_dbts, 0, ldbtsize);
572	prereq = &lockreq[0];
573
574	/* fill in the lockreq array */
575	for (i = 0, prereq = &lockreq[0]; i < count; i++, prereq++) {
576		jlockreq = (*jenv)->GetObjectArrayElement(jenv, list,
577		    offset + i);
578		if (jlockreq == NULL) {
579			__dbj_throw(jenv, EINVAL,
580			    "DbEnv.lock_vec list entry is null", NULL, jdbenv);
581			goto out2;
582		}
583		op = (*jenv)->GetIntField(jenv, jlockreq, lockreq_op_fid);
584		prereq->op = op;
585
586		switch (op) {
587		case DB_LOCK_GET_TIMEOUT:
588			/* Needed: mode, timeout, obj.  Returned: lock. */
589			prereq->op = (*jenv)->GetIntField(jenv, jlockreq,
590			    lockreq_timeout_fid);
591			/* FALLTHROUGH */
592		case DB_LOCK_GET:
593			/* Needed: mode, obj.  Returned: lock. */
594			prereq->mode = (*jenv)->GetIntField(jenv, jlockreq,
595			    lockreq_modeflag_fid);
596			jobj = (*jenv)->GetObjectField(jenv, jlockreq,
597			    lockreq_obj_fid);
598			if ((err = __dbj_dbt_copyin(jenv,
599			    &locked_dbts[i], &obj, jobj, 0)) != 0 ||
600			    (err =
601			    __os_umalloc(env, obj->size, &obj->data)) != 0 ||
602			    (err = __dbj_dbt_memcopy(obj, 0,
603				obj->data, obj->size, DB_USERCOPY_GETDATA)) != 0)
604				goto out2;
605			prereq->obj = obj;
606			break;
607		case DB_LOCK_PUT:
608			/* Needed: lock.  Ignored: mode, obj. */
609			jlock = (*jenv)->GetObjectField(jenv, jlockreq,
610				lockreq_lock_fid);
611			if (jlock == NULL ||
612			    (jlockp = (*jenv)->GetLongField(jenv, jlock,
613			    lock_cptr_fid)) == 0L) {
614				__dbj_throw(jenv, EINVAL,
615				    "LockRequest lock field is NULL", NULL,
616				    jdbenv);
617				goto out2;
618			}
619			lockp = *(DB_LOCK **)(void *)&jlockp;
620			prereq->lock = *lockp;
621			break;
622		case DB_LOCK_PUT_ALL:
623		case DB_LOCK_TIMEOUT:
624			/* Needed: (none).  Ignored: lock, mode, obj. */
625			break;
626		case DB_LOCK_PUT_OBJ:
627			/* Needed: obj.  Ignored: lock, mode. */
628			jobj = (*jenv)->GetObjectField(jenv, jlockreq,
629			    lockreq_obj_fid);
630			if ((err = __dbj_dbt_copyin(jenv,
631			    &locked_dbts[i], &obj, jobj, 0)) != 0 ||
632			    (err =
633			    __os_umalloc(env, obj->size, &obj->data)) != 0 ||
634			    (err = __dbj_dbt_memcopy(obj, 0,
635				obj->data, obj->size, DB_USERCOPY_GETDATA)) != 0)
636				goto out2;
637			prereq->obj = obj;
638			break;
639		default:
640			__dbj_throw(jenv, EINVAL,
641			    "DbEnv.lock_vec bad op value", NULL, jdbenv);
642			goto out2;
643		}
644	}
645
646	err = dbenv->lock_vec(dbenv, (u_int32_t)locker, (u_int32_t)flags,
647	    lockreq, count, &failedreq);
648	if (err == 0)
649		completed = count;
650	else
651		completed = failedreq - lockreq;
652
653	/* do post processing for any and all requests that completed */
654	for (i = 0; i < completed; i++) {
655		op = lockreq[i].op;
656		if (op == DB_LOCK_PUT) {
657			/*
658			 * After a successful put, the DbLock can no longer be
659			 * used, so we release the storage related to it.
660			 */
661			jlockreq = (*jenv)->GetObjectArrayElement(jenv,
662			    list, i + offset);
663			jlock = (*jenv)->GetObjectField(jenv, jlockreq,
664			    lockreq_lock_fid);
665			jlockp = (*jenv)->GetLongField(jenv, jlock,
666			    lock_cptr_fid);
667			lockp = *(DB_LOCK **)(void *)&jlockp;
668			__os_free(NULL, lockp);
669			(*jenv)->SetLongField(jenv, jlock, lock_cptr_fid,
670			    (jlong)0);
671		}
672		else if (op == DB_LOCK_GET) {
673			/*
674			 * Store the lock that was obtained.  We need to create
675			 * storage for it since the lockreq array only exists
676			 * during this method call.
677			 */
678			if ((alloc_err =
679			    __os_malloc(env, sizeof(DB_LOCK), &lockp)) != 0) {
680				__dbj_throw(jenv, alloc_err, NULL, NULL,
681				    jdbenv);
682				goto out2;
683			}
684
685			*lockp = lockreq[i].lock;
686			*(DB_LOCK **)(void *)&jlockp = lockp;
687
688			jlockreq = (*jenv)->GetObjectArrayElement(jenv,
689			    list, i + offset);
690			jlock = (*jenv)->NewObject(jenv, lock_class,
691			    lock_construct, jlockp, JNI_TRUE);
692			if (jlock == NULL)
693				goto out2; /* An exception is pending */
694			(*jenv)->SetLongField(jenv, jlock, lock_cptr_fid,
695			    jlockp);
696			(*jenv)->SetObjectField(jenv, jlockreq,
697			    lockreq_lock_fid, jlock);
698		}
699	}
700
701	/* If one of the locks was not granted, build the exception now. */
702	if (err == DB_LOCK_NOTGRANTED && i < count) {
703		jlockreq = (*jenv)->GetObjectArrayElement(jenv, list,
704		    i + offset);
705		jobj = (*jenv)->GetObjectField(jenv, jlockreq,
706		    lockreq_obj_fid);
707		jlock = (*jenv)->GetObjectField(jenv, jlockreq,
708		    lockreq_lock_fid);
709		(*jenv)->Throw(jenv,
710		    (*jenv)->NewObject(jenv, lockex_class, lockex_construct,
711		    (*jenv)->NewStringUTF(jenv, "DbEnv.lock_vec incomplete"),
712		    lockreq[i].op, lockreq[i].mode, jobj, jlock, i, jdbenv));
713	} else if (err != 0)
714		__dbj_throw(jenv, err, NULL, NULL, jdbenv);
715
716out2:	__os_free(env, locked_dbts);
717out1:	for (i = 0, prereq = &lockreq[0]; i < count; i++, prereq++)
718		if ((prereq->op == DB_LOCK_GET || prereq->op == DB_LOCK_PUT) &&
719		    prereq->obj->data != NULL)
720			__os_ufree(env, prereq->obj->data);
721	__os_free(env, lockreq);
722out0:	return;
723}
724%}
725
726JAVA_TYPEMAP(struct __db_repmgr_sites,
727    com.sleepycat.db.ReplicationManagerSiteInfo[], jobjectArray)
728%typemap(out) struct __db_repmgr_sites
729{
730	int i, len;
731	jobject jrep_addr, jrep_info;
732
733	len = $1.nsites;
734	$result = (*jenv)->NewObjectArray(jenv, (jsize)len, repmgr_siteinfo_class,
735	    NULL);
736	if ($result == NULL)
737		return $null; /* an exception is pending */
738	for (i = 0; i < len; i++) {
739		jstring addr_host = (*jenv)->NewStringUTF(jenv, $1.sites[i].host);
740		if (addr_host == NULL)
741			return $null; /* An exception is pending */
742		jrep_addr = (*jenv)->NewObject(jenv,
743		    rephost_class, rephost_construct, addr_host, $1.sites[i].port);
744		if (jrep_addr == NULL)
745			return $null; /* An exception is pending */
746
747		jrep_info = (*jenv)->NewObject(jenv,
748		    repmgr_siteinfo_class, repmgr_siteinfo_construct, jrep_addr, $1.sites[i].eid);
749		(*jenv)->SetIntField(jenv, jrep_info, repmgr_siteinfo_status_fid,
750		    $1.sites[i].status);
751		if (jrep_info == NULL)
752			return $null; /* An exception is pending */
753
754		(*jenv)->SetObjectArrayElement(jenv, $result, i, jrep_info);
755	}
756	__os_ufree(NULL, $1.sites);
757}
758
759JAVA_TYPEMAP(void *, Object, jobject)
760