1%module db_java
2
3%include "various.i"
4%include "typemaps.i"
5
6%include "java_util.i"
7%include "java_except.i"
8%include "java_typemaps.i"
9%include "java_stat.i"
10%include "java_callbacks.i"
11
12/*
13 * No finalize methods in general - most classes have "destructor" methods
14 * that applications must call explicitly.
15 */
16%typemap(javafinalize) SWIGTYPE ""
17
18/*
19 * These are the exceptions - when there is no "close" method, we need to free
20 * the native part at finalization time.  These are exactly the cases where C
21 * applications manage the memory for the handles.
22 */
23%typemap(javafinalize) struct DbLsn, struct DbLock %{
24  protected void finalize() {
25    try {
26      delete();
27    } catch(Exception e) {
28      System.err.println("Exception during finalization: " + e);
29      e.printStackTrace(System.err);
30    }
31  }
32%}
33
34%typemap(javaimports) SWIGTYPE %{
35import com.sleepycat.db.*;
36import java.util.Comparator;
37%}
38
39/* Class names */
40%rename(LogSequenceNumber) DbLsn;
41
42/* Destructors */
43%rename(close0) close;
44%rename(remove0) remove;
45%rename(rename0) rename;
46%rename(verify0) verify;
47%rename(abort0) abort;
48%rename(commit0) commit;
49%rename(discard0) discard;
50
51/* Special case methods */
52%rename(set_tx_timestamp0) set_tx_timestamp;
53
54/* Extra code in the Java classes */
55%typemap(javacode) struct DbEnv %{
56	/*
57	 * Internally, the JNI layer creates a global reference to each DbEnv,
58	 * which can potentially be different to this.  We keep a copy here so
59	 * we can clean up after destructors.
60	 */
61	private long dbenv_ref;
62	public Environment wrapper;
63
64	private LogRecordHandler app_dispatch_handler;
65	private EventHandler event_notify_handler;
66	private FeedbackHandler env_feedback_handler;
67	private ErrorHandler error_handler;
68	private String errpfx;
69	private MessageHandler message_handler;
70	private PanicHandler panic_handler;
71	private ReplicationTransport rep_transport_handler;
72	private java.io.OutputStream error_stream;
73	private java.io.OutputStream message_stream;
74	private ThreadLocal errBuf;
75
76	public static class RepProcessMessage {
77		public int envid;
78	}
79
80	/*
81	 * Called by the public DbEnv constructor and for private environments
82	 * by the Db constructor.
83	 */
84	void initialize() {
85		dbenv_ref = db_java.initDbEnvRef0(this, this);
86		errBuf = new ThreadLocal();
87		/* Start with System.err as the default error stream. */
88		set_error_stream(System.err);
89		set_message_stream(System.out);
90	}
91
92	void cleanup() {
93		swigCPtr = 0;
94		db_java.deleteRef0(dbenv_ref);
95		dbenv_ref = 0L;
96	}
97
98	public synchronized void close(int flags) throws DatabaseException {
99		try {
100			close0(flags);
101		} finally {
102			cleanup();
103		}
104	}
105
106	private final int handle_app_dispatch(DatabaseEntry dbt,
107					      LogSequenceNumber lsn,
108					      int recops) {
109		return app_dispatch_handler.handleLogRecord(wrapper, dbt, lsn,
110		    RecoveryOperation.fromFlag(recops));
111	}
112
113	public LogRecordHandler get_app_dispatch() {
114		return app_dispatch_handler;
115	}
116
117	private final void handle_panic_event_notify() {
118		event_notify_handler.handlePanicEvent();
119	}
120
121	private final void handle_rep_client_event_notify() {
122		event_notify_handler.handleRepClientEvent();
123	}
124
125	private final void handle_rep_elected_event_notify() {
126		event_notify_handler.handleRepElectedEvent();
127	}
128
129	private final void handle_rep_master_event_notify() {
130		event_notify_handler.handleRepMasterEvent();
131	}
132
133	private final void handle_rep_new_master_event_notify(int envid) {
134		event_notify_handler.handleRepNewMasterEvent(envid);
135	}
136
137	private final void handle_rep_perm_failed_event_notify() {
138		event_notify_handler.handleRepPermFailedEvent();
139	}
140
141	private final void handle_rep_startup_done_event_notify() {
142		event_notify_handler.handleRepStartupDoneEvent();
143	}
144
145	private final void handle_write_failed_event_notify(int errno) {
146		event_notify_handler.handleWriteFailedEvent(errno);
147	}
148
149	public EventHandler get_event_notify() {
150		return event_notify_handler;
151	}
152
153	private final void handle_env_feedback(int opcode, int percent) {
154		if (opcode == DbConstants.DB_RECOVER)
155			env_feedback_handler.recoveryFeedback(wrapper, percent);
156		/* No other environment feedback type supported. */
157	}
158
159	public FeedbackHandler get_feedback() {
160		return env_feedback_handler;
161	}
162
163	public void set_errpfx(String errpfx) {
164		this.errpfx = errpfx;
165	}
166
167	public String get_errpfx() {
168		return errpfx;
169	}
170
171	private final void handle_error(String msg) {
172		com.sleepycat.util.ErrorBuffer ebuf = (com.sleepycat.util.ErrorBuffer)errBuf.get();
173		if (ebuf == null) {
174			/*
175			 * Populate the errBuf ThreadLocal on demand, since the
176			 * callback can be made from different threads.
177			 */
178			ebuf = new com.sleepycat.util.ErrorBuffer(3);
179			errBuf.set(ebuf);
180		}
181		ebuf.append(msg);
182		error_handler.error(wrapper, this.errpfx, msg);
183	}
184
185	private final String get_err_msg(String orig_msg) {
186		com.sleepycat.util.ErrorBuffer ebuf = (com.sleepycat.util.ErrorBuffer)errBuf.get();
187		String ret = null;
188		if (ebuf != null) {
189			ret = ebuf.get();
190			ebuf.clear();
191		}
192		if (ret != null && ret.length() > 0)
193			return orig_msg + ": " + ret;
194		return orig_msg;
195	}
196
197	public ErrorHandler get_errcall() {
198		return error_handler;
199	}
200
201	private final void handle_message(String msg) {
202		message_handler.message(wrapper, msg);
203	}
204
205	public MessageHandler get_msgcall() {
206		return message_handler;
207	}
208
209	private final void handle_panic(DatabaseException e) {
210		panic_handler.panic(wrapper, e);
211	}
212
213	public PanicHandler get_paniccall() {
214		return panic_handler;
215	}
216
217	private final int handle_rep_transport(DatabaseEntry control,
218					       DatabaseEntry rec,
219					       LogSequenceNumber lsn,
220					       int envid, int flags)
221	    throws DatabaseException {
222		return rep_transport_handler.send(wrapper,
223		    control, rec, lsn, envid,
224		    (flags & DbConstants.DB_REP_NOBUFFER) != 0,
225		    (flags & DbConstants.DB_REP_PERMANENT) != 0,
226		    (flags & DbConstants.DB_REP_ANYWHERE) != 0,
227		    (flags & DbConstants.DB_REP_REREQUEST) != 0);
228	}
229
230	public void lock_vec(/*u_int32_t*/ int locker, int flags,
231			     LockRequest[] list, int offset, int count)
232	    throws DatabaseException {
233		db_javaJNI.DbEnv_lock_vec(swigCPtr, this, locker, flags, list,
234		    offset, count);
235	}
236
237	public synchronized void remove(String db_home, int flags)
238	    throws DatabaseException, java.io.FileNotFoundException {
239		try {
240			remove0(db_home, flags);
241		} finally {
242			cleanup();
243		}
244	}
245
246	public void set_error_stream(java.io.OutputStream stream) {
247		error_stream = stream;
248		final java.io.PrintWriter pw = new java.io.PrintWriter(stream);
249		set_errcall(new ErrorHandler() {
250			public void error(Environment env,
251			    String prefix, String buf) /* no exception */ {
252				if (prefix != null)
253					pw.print(prefix + ": ");
254				pw.println(buf);
255				pw.flush();
256			}
257		});
258	}
259
260	public java.io.OutputStream get_error_stream() {
261		return error_stream;
262	}
263
264	public void set_message_stream(java.io.OutputStream stream) {
265		message_stream = stream;
266		final java.io.PrintWriter pw = new java.io.PrintWriter(stream);
267		set_msgcall(new MessageHandler() {
268			public void message(Environment env, String msg)
269			    /* no exception */ {
270				pw.println(msg);
271				pw.flush();
272			}
273		});
274	}
275
276	public java.io.OutputStream get_message_stream() {
277		return message_stream;
278	}
279
280	public void set_tx_timestamp(java.util.Date timestamp) {
281		set_tx_timestamp0(timestamp.getTime()/1000);
282	}
283%}
284
285%typemap(javacode) struct Db %{
286	/* package */ static final int GIGABYTE = 1 << 30;
287	/*
288	 * Internally, the JNI layer creates a global reference to each Db,
289	 * which can potentially be different to this.  We keep a copy here so
290	 * we can clean up after destructors.
291	 */
292	private long db_ref;
293	private DbEnv dbenv;
294	private boolean private_dbenv;
295
296	public Database wrapper;
297	private RecordNumberAppender append_recno_handler;
298	private Comparator bt_compare_handler;
299	private BtreePrefixCalculator bt_prefix_handler;
300	private Comparator dup_compare_handler;
301	private FeedbackHandler db_feedback_handler;
302	private Comparator h_compare_handler;
303	private Hasher h_hash_handler;
304	private SecondaryKeyCreator seckey_create_handler;
305	private SecondaryMultiKeyCreator secmultikey_create_handler;
306	private ForeignKeyNullifier foreignkey_nullify_handler;
307	private ForeignMultiKeyNullifier foreignmultikey_nullify_handler;
308
309	/* Called by the Db constructor */
310	private void initialize(DbEnv dbenv) {
311		if (dbenv == null) {
312			private_dbenv = true;
313			dbenv = db_java.getDbEnv0(this);
314			dbenv.initialize();
315		}
316		this.dbenv = dbenv;
317		db_ref = db_java.initDbRef0(this, this);
318	}
319
320	private void cleanup() {
321		swigCPtr = 0;
322		db_java.deleteRef0(db_ref);
323		db_ref = 0L;
324		if (private_dbenv)
325			dbenv.cleanup();
326		dbenv = null;
327	}
328
329	public boolean getPrivateDbEnv() {
330		return private_dbenv;
331	}
332
333	public synchronized void close(int flags) throws DatabaseException {
334		try {
335			close0(flags);
336		} finally {
337			cleanup();
338		}
339	}
340
341	public DbEnv get_env() throws DatabaseException {
342		return dbenv;
343	}
344
345	private final void handle_append_recno(DatabaseEntry data, int recno)
346	    throws DatabaseException {
347		append_recno_handler.appendRecordNumber(wrapper, data, recno);
348	}
349
350	public RecordNumberAppender get_append_recno() {
351		return append_recno_handler;
352	}
353
354	private final int handle_bt_compare(byte[] arr1, byte[] arr2) {
355		return bt_compare_handler.compare(arr1, arr2);
356	}
357
358	public Comparator get_bt_compare() {
359		return bt_compare_handler;
360	}
361
362	private final int handle_bt_prefix(DatabaseEntry dbt1,
363					   DatabaseEntry dbt2) {
364		return bt_prefix_handler.prefix(wrapper, dbt1, dbt2);
365	}
366
367	public BtreePrefixCalculator get_bt_prefix() {
368		return bt_prefix_handler;
369	}
370
371	private final void handle_db_feedback(int opcode, int percent) {
372		if (opcode == DbConstants.DB_UPGRADE)
373			db_feedback_handler.upgradeFeedback(wrapper, percent);
374		else if (opcode == DbConstants.DB_VERIFY)
375			db_feedback_handler.upgradeFeedback(wrapper, percent);
376		/* No other database feedback types known. */
377	}
378
379	public FeedbackHandler get_feedback() {
380		return db_feedback_handler;
381	}
382
383	private final int handle_h_compare(byte[] arr1, byte[] arr2) {
384		return h_compare_handler.compare(arr1, arr2);
385	}
386
387	public Comparator get_h_compare() {
388		return h_compare_handler;
389	}
390
391	private final int handle_dup_compare(byte[] arr1, byte[] arr2) {
392		return dup_compare_handler.compare(arr1, arr2);
393	}
394
395	public Comparator get_dup_compare() {
396		return dup_compare_handler;
397	}
398
399	private final int handle_h_hash(byte[] data, int len) {
400		return h_hash_handler.hash(wrapper, data, len);
401	}
402
403	public Hasher get_h_hash() {
404		return h_hash_handler;
405	}
406
407	private final boolean handle_foreignkey_nullify(
408					       DatabaseEntry key,
409					       DatabaseEntry data,
410					       DatabaseEntry seckey)
411	    throws DatabaseException {
412		if (foreignmultikey_nullify_handler != null)
413			return foreignmultikey_nullify_handler.nullifyForeignKey(
414			    (SecondaryDatabase)wrapper, key, data, seckey);
415		else
416			return foreignkey_nullify_handler.nullifyForeignKey(
417			    (SecondaryDatabase)wrapper, data);
418	}
419
420	private final DatabaseEntry[] handle_seckey_create(
421					       DatabaseEntry key,
422					       DatabaseEntry data)
423	    throws DatabaseException {
424
425		if (secmultikey_create_handler != null) {
426			java.util.HashSet keySet = new java.util.HashSet();
427			secmultikey_create_handler.createSecondaryKeys(
428			    (SecondaryDatabase)wrapper, key, data, keySet);
429			if (!keySet.isEmpty())
430				return (DatabaseEntry[])keySet.toArray(
431				    new DatabaseEntry[keySet.size()]);
432		} else {
433			DatabaseEntry result = new DatabaseEntry();
434			if (seckey_create_handler.createSecondaryKey(
435			    (SecondaryDatabase)wrapper, key, data, result)) {
436				DatabaseEntry[] results = { result };
437				return results;
438			}
439		}
440
441		return null;
442	}
443
444	public SecondaryKeyCreator get_seckey_create() {
445		return seckey_create_handler;
446	}
447
448	public SecondaryMultiKeyCreator get_secmultikey_create() {
449		return secmultikey_create_handler;
450	}
451
452	public void set_secmultikey_create(
453	    SecondaryMultiKeyCreator secmultikey_create_handler) {
454		this.secmultikey_create_handler = secmultikey_create_handler;
455	}
456
457	public void set_foreignmultikey_nullifier(ForeignMultiKeyNullifier nullify){
458		this.foreignmultikey_nullify_handler = nullify;
459	}
460
461	public synchronized void remove(String file, String database, int flags)
462	    throws DatabaseException, java.io.FileNotFoundException {
463		try {
464			remove0(file, database, flags);
465		} finally {
466			cleanup();
467		}
468	}
469
470	public synchronized void rename(String file, String database,
471	    String newname, int flags)
472	    throws DatabaseException, java.io.FileNotFoundException {
473		try {
474			rename0(file, database, newname, flags);
475		} finally {
476			cleanup();
477		}
478	}
479
480	public synchronized boolean verify(String file, String database,
481	    java.io.OutputStream outfile, int flags)
482	    throws DatabaseException, java.io.FileNotFoundException {
483		try {
484			return verify0(file, database, outfile, flags);
485		} finally {
486			cleanup();
487		}
488	}
489
490	public ErrorHandler get_errcall() {
491		return dbenv.get_errcall();
492	}
493
494	public void set_errcall(ErrorHandler db_errcall_fcn) {
495		dbenv.set_errcall(db_errcall_fcn);
496	}
497
498	public java.io.OutputStream get_error_stream() {
499		return dbenv.get_error_stream();
500	}
501
502	public void set_error_stream(java.io.OutputStream stream) {
503		dbenv.set_error_stream(stream);
504	}
505
506	public void set_errpfx(String errpfx) {
507		dbenv.set_errpfx(errpfx);
508	}
509
510	public String get_errpfx() {
511		return dbenv.get_errpfx();
512	}
513
514	public java.io.OutputStream get_message_stream() {
515		return dbenv.get_message_stream();
516	}
517
518	public void set_message_stream(java.io.OutputStream stream) {
519		dbenv.set_message_stream(stream);
520	}
521
522	public MessageHandler get_msgcall() {
523		return dbenv.get_msgcall();
524	}
525
526	public void set_msgcall(MessageHandler db_msgcall_fcn) {
527		dbenv.set_msgcall(db_msgcall_fcn);
528	}
529
530	public void set_paniccall(PanicHandler db_panic_fcn)
531	    throws DatabaseException {
532		dbenv.set_paniccall(db_panic_fcn);
533	}
534
535	public PanicHandler get_paniccall() {
536		return dbenv.get_paniccall();
537	}
538%}
539
540%typemap(javacode) struct Dbc %{
541	public synchronized void close() throws DatabaseException {
542		try {
543			close0();
544		} finally {
545			swigCPtr = 0;
546		}
547	}
548%}
549
550%typemap(javacode) struct DbLock %{
551	public Lock wrapper;
552%}
553
554%typemap(javacode) struct DbLogc %{
555	public synchronized void close(int flags) throws DatabaseException {
556		try {
557			close0(flags);
558		} finally {
559			swigCPtr = 0;
560		}
561	}
562%}
563
564%typemap(javacode) struct DbSequence %{
565	public Sequence wrapper;
566
567	public synchronized void close(int flags) throws DatabaseException {
568		try {
569			close0(flags);
570		} finally {
571			swigCPtr = 0;
572		}
573	}
574
575	public synchronized void remove(DbTxn txn, int flags)
576	    throws DatabaseException {
577		try {
578			remove0(txn, flags);
579		} finally {
580			swigCPtr = 0;
581		}
582	}
583%}
584
585%typemap(javacode) struct DbTxn %{
586	public void abort() throws DatabaseException {
587		try {
588			abort0();
589		} finally {
590			swigCPtr = 0;
591		}
592	}
593
594	public void commit(int flags) throws DatabaseException {
595		try {
596			commit0(flags);
597		} finally {
598			swigCPtr = 0;
599		}
600	}
601
602	public void discard(int flags) throws DatabaseException {
603		try {
604			discard0(flags);
605		} finally {
606			swigCPtr = 0;
607		}
608	}
609
610	/*
611	 * We override Object.equals because it is possible for the Java API to
612	 * create multiple DbTxns that reference the same underlying object.
613	 * This can happen for example during DbEnv.txn_recover().
614	 */
615	public boolean equals(Object obj)
616	{
617		if (this == obj)
618			return true;
619
620		if (obj != null && (obj instanceof DbTxn)) {
621			DbTxn that = (DbTxn)obj;
622			return (this.swigCPtr == that.swigCPtr);
623		}
624		return false;
625	}
626
627	/*
628	 * We must override Object.hashCode whenever we override
629	 * Object.equals() to enforce the maxim that equal objects have the
630	 * same hashcode.
631	 */
632	public int hashCode()
633	{
634		return ((int)swigCPtr ^ (int)(swigCPtr >> 32));
635	}
636%}
637
638%native(initDbEnvRef0) jlong initDbEnvRef0(DB_ENV *self, void *handle);
639%native(initDbRef0) jlong initDbRef0(DB *self, void *handle);
640%native(deleteRef0) void deleteRef0(jlong ref);
641%native(getDbEnv0) DB_ENV *getDbEnv0(DB *self);
642
643%{
644SWIGEXPORT jlong JNICALL
645Java_com_sleepycat_db_internal_db_1javaJNI_initDbEnvRef0(
646    JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jobject jarg2) {
647	DB_ENV *self = *(DB_ENV **)(void *)&jarg1;
648	jlong ret;
649	COMPQUIET(jcls, NULL);
650	COMPQUIET(jarg1_, NULL);
651
652	DB_ENV_INTERNAL(self) = (void *)(*jenv)->NewGlobalRef(jenv, jarg2);
653	*(jobject *)(void *)&ret = (jobject)DB_ENV_INTERNAL(self);
654	return (ret);
655}
656
657SWIGEXPORT jlong JNICALL
658Java_com_sleepycat_db_internal_db_1javaJNI_initDbRef0(
659    JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jobject jarg2) {
660	DB *self = *(DB **)(void *)&jarg1;
661	jlong ret;
662	COMPQUIET(jcls, NULL);
663	COMPQUIET(jarg1_, NULL);
664
665	DB_INTERNAL(self) = (void *)(*jenv)->NewGlobalRef(jenv, jarg2);
666	*(jobject *)(void *)&ret = (jobject)DB_INTERNAL(self);
667	return (ret);
668}
669
670SWIGEXPORT void JNICALL
671Java_com_sleepycat_db_internal_db_1javaJNI_deleteRef0(
672    JNIEnv *jenv, jclass jcls, jlong jarg1) {
673	jobject jref = *(jobject *)(void *)&jarg1;
674	COMPQUIET(jcls, NULL);
675
676	if (jref != 0L)
677		(*jenv)->DeleteGlobalRef(jenv, jref);
678}
679
680SWIGEXPORT jlong JNICALL
681Java_com_sleepycat_db_internal_db_1javaJNI_getDbEnv0(
682    JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
683	DB *self = *(DB **)(void *)&jarg1;
684	jlong ret;
685
686	COMPQUIET(jenv, NULL);
687	COMPQUIET(jcls, NULL);
688	COMPQUIET(jarg1_, NULL);
689
690	*(DB_ENV **)(void *)&ret = self->dbenv;
691	return (ret);
692}
693
694SWIGEXPORT jboolean JNICALL
695Java_com_sleepycat_db_internal_DbUtil_is_1big_1endian(
696    JNIEnv *jenv, jclass clazz)
697{
698	COMPQUIET(jenv, NULL);
699	COMPQUIET(clazz, NULL);
700
701	return (__db_isbigendian() ? JNI_TRUE : JNI_FALSE);
702}
703%}
704