diff options
author | tim@threads.polyesthetic.msg <> | 2001-03-04 19:42:05 -0500 |
---|---|---|
committer | tim@threads.polyesthetic.msg <> | 2001-03-04 19:42:05 -0500 |
commit | 89dad52004ecba5a380aeebb0e2a9beaae88eb86 (patch) | |
tree | 9dd732e08dba156ee3d7635caedc0dc3107ecac6 /bdb/libdb_java | |
parent | 639a1069d313843288ba6d9cb54b290073a748a7 (diff) | |
download | mariadb-git-89dad52004ecba5a380aeebb0e2a9beaae88eb86.tar.gz |
Import changeset
Diffstat (limited to 'bdb/libdb_java')
-rw-r--r-- | bdb/libdb_java/checkapi.prl | 132 | ||||
-rw-r--r-- | bdb/libdb_java/com_sleepycat_db_Db.h | 349 | ||||
-rw-r--r-- | bdb/libdb_java/com_sleepycat_db_DbEnv.h | 509 | ||||
-rw-r--r-- | bdb/libdb_java/com_sleepycat_db_DbLock.h | 29 | ||||
-rw-r--r-- | bdb/libdb_java/com_sleepycat_db_DbLsn.h | 29 | ||||
-rw-r--r-- | bdb/libdb_java/com_sleepycat_db_DbTxn.h | 53 | ||||
-rw-r--r-- | bdb/libdb_java/com_sleepycat_db_Dbc.h | 69 | ||||
-rw-r--r-- | bdb/libdb_java/com_sleepycat_db_Dbt.h | 157 | ||||
-rw-r--r-- | bdb/libdb_java/java_Db.c | 964 | ||||
-rw-r--r-- | bdb/libdb_java/java_DbEnv.c | 1300 | ||||
-rw-r--r-- | bdb/libdb_java/java_DbLock.c | 55 | ||||
-rw-r--r-- | bdb/libdb_java/java_DbLsn.c | 43 | ||||
-rw-r--r-- | bdb/libdb_java/java_DbTxn.c | 82 | ||||
-rw-r--r-- | bdb/libdb_java/java_Dbc.c | 196 | ||||
-rw-r--r-- | bdb/libdb_java/java_Dbt.c | 176 | ||||
-rw-r--r-- | bdb/libdb_java/java_info.c | 1001 | ||||
-rw-r--r-- | bdb/libdb_java/java_info.h | 200 | ||||
-rw-r--r-- | bdb/libdb_java/java_locked.c | 294 | ||||
-rw-r--r-- | bdb/libdb_java/java_locked.h | 98 | ||||
-rw-r--r-- | bdb/libdb_java/java_util.c | 556 | ||||
-rw-r--r-- | bdb/libdb_java/java_util.h | 359 |
21 files changed, 6651 insertions, 0 deletions
diff --git a/bdb/libdb_java/checkapi.prl b/bdb/libdb_java/checkapi.prl new file mode 100644 index 00000000000..25882c056cc --- /dev/null +++ b/bdb/libdb_java/checkapi.prl @@ -0,0 +1,132 @@ +# +# Released to public domain by Donald Anderson dda@world.std.com +# No warranties. +# +# Perl script to check for matching of JNI interfaces to implementation. +# We check all .cpp arguments and .h arguments and make sure that for +# each .h declaration (marked by JNIEXPORT keyword), there is a .cpp +# definition for the same function (also marked by JNIEXPORT keyword), +# and vice versa. Definitions and declarations are determined solely +# by whether they are in a .h or .cpp file - we don't do any further +# analysis. +# +# Some additions made to help with Berkeley DB sources: +# +# Berkeley DB Java sources use JAVADB_*_ACCESS #defines +# to quickly define routine access functions. + +foreach $file (<@ARGV>) { # glob allows direct use from Win* makefiles + open (FILE, $file) || die "$file: cannot open\n"; + $dot_h = 0; + if ($file =~ /.*[hH]$/) { + $dot_h = 1; + } + $in_def = 0; +nextline: + while (<FILE>) { + chop; + if (/JNIEXPORT/ || /^JAVADB_.*_ACCESS/) { + $in_def = 1; + $def = ""; + } + if ($in_def == 1) { + $def .= $_; + } + if (/\)/) { + $line = ""; + $in_def = 0; + if ($def eq "") { + next nextline; + } + $_ = $def; + # remove comments + s@/\*[^*]*\*/@@g; + s@[ ][ ]*@ @g; + s@JNIEnv *\* *@JNIEnv @g; + s@([,*()]) @\1@g; + s@ ([,*()])@\1@g; + + s/JAVADB_WO_ACCESS_METHOD/JAVADB_WO_ACCESS/; + + if (/^JAVADB_.*_ACCESS/) { + s@ *@ @g; + s@_ACCESS_STRING\(([^,]*),@_ACCESS(\1,jstring,@; + s@_ACCESS_BEFORE_APPINIT@_ACCESS@; + s@_ACCESS\(@,normal,@; + s@JAVADB_@@; + s@\)@,@; + @vars = split(/,/); + $get = 0; + $set = 0; + if (@vars[0] eq "RW") { + $get = 1; + $set = 1; + } + if (@vars[0] eq "RO") { + $get = 1; + } + if (@vars[0] eq "WO") { + $set = 1; + } + if ($get == 0 && $set == 0) { + print "Invalid use of JAVADB_ macro\n"; + } + if ($set == 1) { + $line = "JNIEXPORT void JNICALL Java_com_sleepycat_db_@vars[2]_set_1@vars[4](JNIEnv,jobject,@vars[3])"; + } + if ($get == 1) { + $line2 = "JNIEXPORT @vars[3] JNICALL Java_com_sleepycat_db_@vars[2]_get_1@vars[4](JNIEnv,jobject)"; + } + } + else { + s@([,(][a-zA-Z0-9_]*) [a-zA-Z0-9_]*@\1@g; + s@;$@@g; + $line = $_; + } + + $def = ""; + + if ($line ne "") { + if ($lines{$line} eq "") { + $lines{$line} = 0; + } + if ($dot_h == 1) { + $lines{$line} += 1; + } + else { + $lines{$line} -= 1; + } + $line = ""; + } + if ($line2 ne "") { + if ($lines{$line2} eq "") { + $lines{$line2} = 0; + } + if ($dot_h == 1) { + $lines{$line2} += 1; + } + else { + $lines{$line2} -= 1; + } + $line2 = ""; + } + } + } + close (FILE); +} + +$status = 0; +foreach $key (sort keys %lines) { + if ($lines{$key} != 0) { + if ($lines{$key} > 0) { + print "Missing .cpp implementation: $lines${key}\n"; + $status = 1; + } + else { + print "Missing .h declaration: $lines${key}\n"; + $status = 1; + } + } +} + +exit ($status); diff --git a/bdb/libdb_java/com_sleepycat_db_Db.h b/bdb/libdb_java/com_sleepycat_db_Db.h new file mode 100644 index 00000000000..d9e1f1cbbc7 --- /dev/null +++ b/bdb/libdb_java/com_sleepycat_db_Db.h @@ -0,0 +1,349 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class com_sleepycat_db_Db */ + +#ifndef _Included_com_sleepycat_db_Db +#define _Included_com_sleepycat_db_Db +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_sleepycat_db_Db + * Method: _init + * Signature: (Lcom/sleepycat/db/DbEnv;I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1init + (JNIEnv *, jobject, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: _notify_internal + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1notify_1internal + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Db + * Method: _close + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db__1close + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: cursor + * Signature: (Lcom/sleepycat/db/DbTxn;I)Lcom/sleepycat/db/Dbc; + */ +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Db_cursor + (JNIEnv *, jobject, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: del + * Signature: (Lcom/sleepycat/db/DbTxn;Lcom/sleepycat/db/Dbt;I)I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_del + (JNIEnv *, jobject, jobject, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: err + * Signature: (ILjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_err + (JNIEnv *, jobject, jint, jstring); + +/* + * Class: com_sleepycat_db_Db + * Method: errx + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_errx + (JNIEnv *, jobject, jstring); + +/* + * Class: com_sleepycat_db_Db + * Method: fd + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_fd + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Db + * Method: _finalize + * Signature: (Lcom/sleepycat/db/DbErrcall;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1finalize + (JNIEnv *, jobject, jobject, jstring); + +/* + * Class: com_sleepycat_db_Db + * Method: get + * Signature: (Lcom/sleepycat/db/DbTxn;Lcom/sleepycat/db/Dbt;Lcom/sleepycat/db/Dbt;I)I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_get + (JNIEnv *, jobject, jobject, jobject, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: get_byteswapped + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_sleepycat_db_Db_get_1byteswapped + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Db + * Method: get_type + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_get_1type + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Db + * Method: join + * Signature: ([Lcom/sleepycat/db/Dbc;I)Lcom/sleepycat/db/Dbc; + */ +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Db_join + (JNIEnv *, jobject, jobjectArray, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: key_range + * Signature: (Lcom/sleepycat/db/DbTxn;Lcom/sleepycat/db/Dbt;Lcom/sleepycat/db/DbKeyRange;I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_key_1range + (JNIEnv *, jobject, jobject, jobject, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: _open + * Signature: (Ljava/lang/String;Ljava/lang/String;III)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1open + (JNIEnv *, jobject, jstring, jstring, jint, jint, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: put + * Signature: (Lcom/sleepycat/db/DbTxn;Lcom/sleepycat/db/Dbt;Lcom/sleepycat/db/Dbt;I)I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_put + (JNIEnv *, jobject, jobject, jobject, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: rename + * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_rename + (JNIEnv *, jobject, jstring, jstring, jstring, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: remove + * Signature: (Ljava/lang/String;Ljava/lang/String;I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_remove + (JNIEnv *, jobject, jstring, jstring, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: append_recno_changed + * Signature: (Lcom/sleepycat/db/DbAppendRecno;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_append_1recno_1changed + (JNIEnv *, jobject, jobject); + +/* + * Class: com_sleepycat_db_Db + * Method: bt_compare_changed + * Signature: (Lcom/sleepycat/db/DbBtreeCompare;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_bt_1compare_1changed + (JNIEnv *, jobject, jobject); + +/* + * Class: com_sleepycat_db_Db + * Method: set_bt_maxkey + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1bt_1maxkey + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: set_bt_minkey + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1bt_1minkey + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: bt_prefix_changed + * Signature: (Lcom/sleepycat/db/DbBtreePrefix;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_bt_1prefix_1changed + (JNIEnv *, jobject, jobject); + +/* + * Class: com_sleepycat_db_Db + * Method: set_cachesize + * Signature: (III)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1cachesize + (JNIEnv *, jobject, jint, jint, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: dup_compare_changed + * Signature: (Lcom/sleepycat/db/DbDupCompare;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_dup_1compare_1changed + (JNIEnv *, jobject, jobject); + +/* + * Class: com_sleepycat_db_Db + * Method: feedback_changed + * Signature: (Lcom/sleepycat/db/DbFeedback;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_feedback_1changed + (JNIEnv *, jobject, jobject); + +/* + * Class: com_sleepycat_db_Db + * Method: set_flags + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1flags + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: set_h_ffactor + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1h_1ffactor + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: hash_changed + * Signature: (Lcom/sleepycat/db/DbHash;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_hash_1changed + (JNIEnv *, jobject, jobject); + +/* + * Class: com_sleepycat_db_Db + * Method: set_h_nelem + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1h_1nelem + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: set_lorder + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1lorder + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: set_pagesize + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1pagesize + (JNIEnv *, jobject, jlong); + +/* + * Class: com_sleepycat_db_Db + * Method: set_re_delim + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1re_1delim + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: set_re_len + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1re_1len + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: set_re_pad + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1re_1pad + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: set_re_source + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1re_1source + (JNIEnv *, jobject, jstring); + +/* + * Class: com_sleepycat_db_Db + * Method: set_q_extentsize + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_set_1q_1extentsize + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: stat + * Signature: (I)Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Db_stat + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: sync + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_sync + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: upgrade + * Signature: (Ljava/lang/String;I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_upgrade + (JNIEnv *, jobject, jstring, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: verify + * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/io/OutputStream;I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_verify + (JNIEnv *, jobject, jstring, jstring, jobject, jint); + +/* + * Class: com_sleepycat_db_Db + * Method: one_time_init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_one_1time_1init + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/bdb/libdb_java/com_sleepycat_db_DbEnv.h b/bdb/libdb_java/com_sleepycat_db_DbEnv.h new file mode 100644 index 00000000000..4168ea9abe2 --- /dev/null +++ b/bdb/libdb_java/com_sleepycat_db_DbEnv.h @@ -0,0 +1,509 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class com_sleepycat_db_DbEnv */ + +#ifndef _Included_com_sleepycat_db_DbEnv +#define _Included_com_sleepycat_db_DbEnv +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_sleepycat_db_DbEnv + * Method: _close + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1close + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: err + * Signature: (ILjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_err + (JNIEnv *, jobject, jint, jstring); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: errx + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_errx + (JNIEnv *, jobject, jstring); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: _finalize + * Signature: (Lcom/sleepycat/db/DbErrcall;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1finalize + (JNIEnv *, jobject, jobject, jstring); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: _init + * Signature: (Lcom/sleepycat/db/DbErrcall;I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1init + (JNIEnv *, jobject, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: _init_using_db + * Signature: (Lcom/sleepycat/db/DbErrcall;Lcom/sleepycat/db/Db;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1init_1using_1db + (JNIEnv *, jobject, jobject, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: _notify_db_close + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1notify_1db_1close + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: open + * Signature: (Ljava/lang/String;II)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_open + (JNIEnv *, jobject, jstring, jint, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: remove + * Signature: (Ljava/lang/String;I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_remove + (JNIEnv *, jobject, jstring, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_cachesize + * Signature: (III)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1cachesize + (JNIEnv *, jobject, jint, jint, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: _set_errcall + * Signature: (Lcom/sleepycat/db/DbErrcall;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1set_1errcall + (JNIEnv *, jobject, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: _set_errpfx + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1set_1errpfx + (JNIEnv *, jobject, jstring); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: feedback_changed + * Signature: (Lcom/sleepycat/db/DbFeedback;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_feedback_1changed + (JNIEnv *, jobject, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_verbose + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1verbose + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_data_dir + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1data_1dir + (JNIEnv *, jobject, jstring); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_lg_bsize + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lg_1bsize + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_lg_dir + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lg_1dir + (JNIEnv *, jobject, jstring); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_lg_max + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lg_1max + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_lk_conflicts + * Signature: ([[B)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lk_1conflicts + (JNIEnv *, jobject, jobjectArray); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_lk_detect + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lk_1detect + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_lk_max + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lk_1max + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_lk_max_lockers + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lk_1max_1lockers + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_lk_max_locks + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lk_1max_1locks + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_lk_max_objects + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lk_1max_1objects + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_mp_mmapsize + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1mp_1mmapsize + (JNIEnv *, jobject, jlong); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_mutexlocks + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1mutexlocks + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_pageyield + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1pageyield + (JNIEnv *, jclass, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_panicstate + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1panicstate + (JNIEnv *, jclass, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: recovery_init_changed + * Signature: (Lcom/sleepycat/db/DbRecoveryInit;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_recovery_1init_1changed + (JNIEnv *, jobject, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_region_init + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1region_1init + (JNIEnv *, jclass, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_flags + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1flags + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_server + * Signature: (Ljava/lang/String;JJI)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1server + (JNIEnv *, jobject, jstring, jlong, jlong, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_shm_key + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1shm_1key + (JNIEnv *, jobject, jlong); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_tas_spins + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1tas_1spins + (JNIEnv *, jclass, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_tmp_dir + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1tmp_1dir + (JNIEnv *, jobject, jstring); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: tx_recover_changed + * Signature: (Lcom/sleepycat/db/DbTxnRecover;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_tx_1recover_1changed + (JNIEnv *, jobject, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: set_tx_max + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1tx_1max + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: _set_tx_timestamp + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1set_1tx_1timestamp + (JNIEnv *, jobject, jlong); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: get_version_major + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_get_1version_1major + (JNIEnv *, jclass); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: get_version_minor + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_get_1version_1minor + (JNIEnv *, jclass); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: get_version_patch + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_get_1version_1patch + (JNIEnv *, jclass); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: get_version_string + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_sleepycat_db_DbEnv_get_1version_1string + (JNIEnv *, jclass); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: strerror + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_sleepycat_db_DbEnv_strerror + (JNIEnv *, jclass, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: lock_detect + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_lock_1detect + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: lock_get + * Signature: (IILcom/sleepycat/db/Dbt;I)Lcom/sleepycat/db/DbLock; + */ +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_lock_1get + (JNIEnv *, jobject, jint, jint, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: lock_id + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_lock_1id + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: lock_stat + * Signature: ()Lcom/sleepycat/db/DbLockStat; + */ +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_lock_1stat + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: log_archive + * Signature: (I)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_DbEnv_log_1archive + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: log_compare + * Signature: (Lcom/sleepycat/db/DbLsn;Lcom/sleepycat/db/DbLsn;)I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_log_1compare + (JNIEnv *, jclass, jobject, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: log_file + * Signature: (Lcom/sleepycat/db/DbLsn;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_sleepycat_db_DbEnv_log_1file + (JNIEnv *, jobject, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: log_flush + * Signature: (Lcom/sleepycat/db/DbLsn;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1flush + (JNIEnv *, jobject, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: log_get + * Signature: (Lcom/sleepycat/db/DbLsn;Lcom/sleepycat/db/Dbt;I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1get + (JNIEnv *, jobject, jobject, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: log_put + * Signature: (Lcom/sleepycat/db/DbLsn;Lcom/sleepycat/db/Dbt;I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1put + (JNIEnv *, jobject, jobject, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: log_stat + * Signature: ()Lcom/sleepycat/db/DbLogStat; + */ +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_log_1stat + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: log_register + * Signature: (Lcom/sleepycat/db/Db;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1register + (JNIEnv *, jobject, jobject, jstring); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: log_unregister + * Signature: (Lcom/sleepycat/db/Db;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1unregister + (JNIEnv *, jobject, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: memp_stat + * Signature: ()Lcom/sleepycat/db/DbMpoolStat; + */ +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_memp_1stat + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: memp_fstat + * Signature: ()[Lcom/sleepycat/db/DbMpoolFStat; + */ +JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_DbEnv_memp_1fstat + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: memp_trickle + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_memp_1trickle + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: txn_begin + * Signature: (Lcom/sleepycat/db/DbTxn;I)Lcom/sleepycat/db/DbTxn; + */ +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_txn_1begin + (JNIEnv *, jobject, jobject, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: txn_checkpoint + * Signature: (III)I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_txn_1checkpoint + (JNIEnv *, jobject, jint, jint, jint); + +/* + * Class: com_sleepycat_db_DbEnv + * Method: txn_stat + * Signature: ()Lcom/sleepycat/db/DbTxnStat; + */ +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_txn_1stat + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/bdb/libdb_java/com_sleepycat_db_DbLock.h b/bdb/libdb_java/com_sleepycat_db_DbLock.h new file mode 100644 index 00000000000..8a1c135bb3b --- /dev/null +++ b/bdb/libdb_java/com_sleepycat_db_DbLock.h @@ -0,0 +1,29 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class com_sleepycat_db_DbLock */ + +#ifndef _Included_com_sleepycat_db_DbLock +#define _Included_com_sleepycat_db_DbLock +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_sleepycat_db_DbLock + * Method: finalize + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLock_finalize + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_DbLock + * Method: put + * Signature: (Lcom/sleepycat/db/DbEnv;)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLock_put + (JNIEnv *, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/bdb/libdb_java/com_sleepycat_db_DbLsn.h b/bdb/libdb_java/com_sleepycat_db_DbLsn.h new file mode 100644 index 00000000000..093eaf372b5 --- /dev/null +++ b/bdb/libdb_java/com_sleepycat_db_DbLsn.h @@ -0,0 +1,29 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class com_sleepycat_db_DbLsn */ + +#ifndef _Included_com_sleepycat_db_DbLsn +#define _Included_com_sleepycat_db_DbLsn +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_sleepycat_db_DbLsn + * Method: finalize + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLsn_finalize + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_DbLsn + * Method: init_lsn + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLsn_init_1lsn + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/bdb/libdb_java/com_sleepycat_db_DbTxn.h b/bdb/libdb_java/com_sleepycat_db_DbTxn.h new file mode 100644 index 00000000000..4dcf47405c0 --- /dev/null +++ b/bdb/libdb_java/com_sleepycat_db_DbTxn.h @@ -0,0 +1,53 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class com_sleepycat_db_DbTxn */ + +#ifndef _Included_com_sleepycat_db_DbTxn +#define _Included_com_sleepycat_db_DbTxn +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_sleepycat_db_DbTxn + * Method: abort + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_abort + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_DbTxn + * Method: commit + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_commit + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_DbTxn + * Method: id + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbTxn_id + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_DbTxn + * Method: prepare + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_prepare + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_DbTxn + * Method: finalize + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_finalize + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/bdb/libdb_java/com_sleepycat_db_Dbc.h b/bdb/libdb_java/com_sleepycat_db_Dbc.h new file mode 100644 index 00000000000..e62679c6f66 --- /dev/null +++ b/bdb/libdb_java/com_sleepycat_db_Dbc.h @@ -0,0 +1,69 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class com_sleepycat_db_Dbc */ + +#ifndef _Included_com_sleepycat_db_Dbc +#define _Included_com_sleepycat_db_Dbc +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_sleepycat_db_Dbc + * Method: close + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbc_close + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Dbc + * Method: count + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_count + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Dbc + * Method: del + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_del + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Dbc + * Method: dup + * Signature: (I)Lcom/sleepycat/db/Dbc; + */ +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Dbc_dup + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Dbc + * Method: get + * Signature: (Lcom/sleepycat/db/Dbt;Lcom/sleepycat/db/Dbt;I)I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_get + (JNIEnv *, jobject, jobject, jobject, jint); + +/* + * Class: com_sleepycat_db_Dbc + * Method: put + * Signature: (Lcom/sleepycat/db/Dbt;Lcom/sleepycat/db/Dbt;I)I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_put + (JNIEnv *, jobject, jobject, jobject, jint); + +/* + * Class: com_sleepycat_db_Dbc + * Method: finalize + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbc_finalize + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/bdb/libdb_java/com_sleepycat_db_Dbt.h b/bdb/libdb_java/com_sleepycat_db_Dbt.h new file mode 100644 index 00000000000..cdb58c682c9 --- /dev/null +++ b/bdb/libdb_java/com_sleepycat_db_Dbt.h @@ -0,0 +1,157 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class com_sleepycat_db_Dbt */ + +#ifndef _Included_com_sleepycat_db_Dbt +#define _Included_com_sleepycat_db_Dbt +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_sleepycat_db_Dbt + * Method: finalize + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_finalize + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Dbt + * Method: get_data + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_sleepycat_db_Dbt_get_1data + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Dbt + * Method: internal_set_data + * Signature: ([B)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_internal_1set_1data + (JNIEnv *, jobject, jbyteArray); + +/* + * Class: com_sleepycat_db_Dbt + * Method: set_offset + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1offset + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Dbt + * Method: get_offset + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1offset + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Dbt + * Method: get_size + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1size + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Dbt + * Method: set_size + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1size + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Dbt + * Method: get_ulen + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1ulen + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Dbt + * Method: set_ulen + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1ulen + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Dbt + * Method: get_dlen + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1dlen + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Dbt + * Method: set_dlen + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1dlen + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Dbt + * Method: get_doff + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1doff + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Dbt + * Method: set_doff + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1doff + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Dbt + * Method: get_flags + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1flags + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Dbt + * Method: set_flags + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1flags + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Dbt + * Method: set_recno_key_data + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1recno_1key_1data + (JNIEnv *, jobject, jint); + +/* + * Class: com_sleepycat_db_Dbt + * Method: get_recno_key_data + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1recno_1key_1data + (JNIEnv *, jobject); + +/* + * Class: com_sleepycat_db_Dbt + * Method: init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_init + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/bdb/libdb_java/java_Db.c b/bdb/libdb_java/java_Db.c new file mode 100644 index 00000000000..5b01e5068d6 --- /dev/null +++ b/bdb/libdb_java/java_Db.c @@ -0,0 +1,964 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 1998, 1999, 2000 + * Sleepycat Software. All rights reserved. + */ +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: java_Db.c,v 11.34 2000/11/30 00:58:38 ubell Exp $"; +#endif /* not lint */ + +#include <jni.h> +#include <stdlib.h> +#include <string.h> + +#include "db.h" +#include "db_int.h" +#include "db_page.h" +#include "db_ext.h" +#include "java_util.h" +#include "com_sleepycat_db_Db.h" + +/* This struct is used in Db.verify and its callback */ +struct verify_callback_struct { + JNIEnv *env; + jobject streamobj; + jbyteArray bytes; + int nbytes; + jmethodID writemid; +}; + +JAVADB_WO_ACCESS_METHOD(Db, jint, flags, DB, flags) +JAVADB_WO_ACCESS_METHOD(Db, jint, h_1ffactor, DB, h_ffactor) +JAVADB_WO_ACCESS_METHOD(Db, jint, h_1nelem, DB, h_nelem) +JAVADB_WO_ACCESS_METHOD(Db, jint, lorder, DB, lorder) +JAVADB_WO_ACCESS_METHOD(Db, jint, re_1delim, DB, re_delim) +JAVADB_WO_ACCESS_METHOD(Db, jint, re_1len, DB, re_len) +JAVADB_WO_ACCESS_METHOD(Db, jint, re_1pad, DB, re_pad) +JAVADB_WO_ACCESS_METHOD(Db, jint, q_1extentsize, DB, q_extentsize) +JAVADB_WO_ACCESS_METHOD(Db, jint, bt_1maxkey, DB, bt_maxkey) +JAVADB_WO_ACCESS_METHOD(Db, jint, bt_1minkey, DB, bt_minkey) + +/* This only gets called once ever, at the beginning of execution + * and can be used to initialize unchanging methodIds, fieldIds, etc. + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_one_1time_1init + (JNIEnv *jnienv, /*Db.class*/ jclass jthisclass) +{ + COMPQUIET(jnienv, NULL); + COMPQUIET(jthisclass, NULL); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1init + (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbEnv*/ jobject jdbenv, jint flags) +{ + int err; + DB *db; + DB_JAVAINFO *dbinfo; + DB_ENV *dbenv; + + dbenv = get_DB_ENV(jnienv, jdbenv); + dbinfo = get_DB_JAVAINFO(jnienv, jthis); + DB_ASSERT(dbinfo == NULL); + + err = db_create(&db, dbenv, flags); + if (verify_return(jnienv, err, 0)) { + set_private_dbobj(jnienv, name_DB, jthis, db); + dbinfo = dbji_construct(jnienv, flags); + set_private_info(jnienv, name_DB, jthis, dbinfo); + db->cj_internal = dbinfo; + } +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db__1close + (JNIEnv *jnienv, /*Db*/ jobject jthis, jint flags) +{ + int err; + DB *db; + DB_JAVAINFO *dbinfo; + + db = get_DB(jnienv, jthis); + dbinfo = get_DB_JAVAINFO(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + return (0); + + JAVADB_API_BEGIN(db, jthis); + + /* Null out the private data to indicate the DB is invalid. + * We do this in advance to help guard against multithreading + * issues. + */ + set_private_dbobj(jnienv, name_DB, jthis, 0); + + err = db->close(db, flags); + if (err != DB_INCOMPLETE) + verify_return(jnienv, err, 0); + dbji_dealloc(dbinfo, jnienv); + + /* don't call JAVADB_API_END - db cannot be used */ + return (err); +} + +/* We are being notified that the parent DbEnv has closed. + * Zero out the pointer to the DB, since it is no longer + * valid, to prevent mistakes. The user will get a null + * pointer exception if they try to use this Db again. + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1notify_1internal + (JNIEnv *jnienv, /*Db*/ jobject jthis) +{ + set_private_dbobj(jnienv, name_DB, jthis, 0); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_append_1recno_1changed + (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbAppendRecno*/ jobject jcallback) +{ + DB *db; + DB_JAVAINFO *dbinfo; + + db = get_DB(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + return; + + JAVADB_API_BEGIN(db, jthis); + dbinfo = (DB_JAVAINFO*)db->cj_internal; + dbji_set_append_recno_object(dbinfo, jnienv, db, jcallback); + JAVADB_API_END(db); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_bt_1compare_1changed + (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbBtreeCompare*/ jobject jbtcompare) +{ + DB *db; + DB_JAVAINFO *dbinfo; + + db = get_DB(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + return; + + JAVADB_API_BEGIN(db, jthis); + dbinfo = (DB_JAVAINFO*)db->cj_internal; + dbji_set_bt_compare_object(dbinfo, jnienv, db, jbtcompare); + JAVADB_API_END(db); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_bt_1prefix_1changed + (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbBtreePrefix*/ jobject jbtprefix) +{ + DB *db; + DB_JAVAINFO *dbinfo; + + db = get_DB(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + return; + + JAVADB_API_BEGIN(db, jthis); + dbinfo = (DB_JAVAINFO*)db->cj_internal; + dbji_set_bt_prefix_object(dbinfo, jnienv, db, jbtprefix); + JAVADB_API_END(db); +} + +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Db_cursor + (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbTxn*/ jobject txnid, jint flags) +{ + int err; + DBC *dbc; + DB *db = get_DB(jnienv, jthis); + DB_TXN *dbtxnid = get_DB_TXN(jnienv, txnid); + + if (!verify_non_null(jnienv, db)) + return (NULL); + err = db->cursor(db, dbtxnid, &dbc, flags); + verify_return(jnienv, err, 0); + return (get_Dbc(jnienv, dbc)); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_del + (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbTxn*/ jobject txnid, + /*Dbt*/ jobject key, jint dbflags) +{ + int err; + DB_TXN *dbtxnid; + DB *db; + JDBT dbkey; + + err = 0; + db = get_DB(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + return (0); + + JAVADB_API_BEGIN(db, jthis); + dbtxnid = get_DB_TXN(jnienv, txnid); + if (jdbt_lock(&dbkey, jnienv, key, inOp) != 0) + goto out; + + err = db->del(db, dbtxnid, &dbkey.dbt->dbt, dbflags); + if (err != DB_NOTFOUND) { + verify_return(jnienv, err, 0); + } + + out: + jdbt_unlock(&dbkey, jnienv); + JAVADB_API_END(db); + return (err); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_dup_1compare_1changed + (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbDupCompare*/ jobject jdupcompare) +{ + DB *db; + DB_JAVAINFO *dbinfo; + + db = get_DB(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + return; + + JAVADB_API_BEGIN(db, jthis); + dbinfo = (DB_JAVAINFO*)db->cj_internal; + dbji_set_dup_compare_object(dbinfo, jnienv, db, jdupcompare); + JAVADB_API_END(db); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_err + (JNIEnv *jnienv, /*Db*/ jobject jthis, jint ecode, jstring msg) +{ + DB *db; + JSTR msg_string; + + if (jstr_lock(&msg_string, jnienv, msg) != 0) + goto out; + db = get_DB(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + goto out; + + JAVADB_API_BEGIN(db, jthis); + db->err(db, ecode, msg_string.string); + JAVADB_API_END(db); + + out: + jstr_unlock(&msg_string, jnienv); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_errx + (JNIEnv *jnienv, /*Db*/ jobject jthis, jstring msg) +{ + JSTR msg_string; + DB *db = get_DB(jnienv, jthis); + + if (jstr_lock(&msg_string, jnienv, msg) != 0) + goto out; + if (!verify_non_null(jnienv, db)) + goto out; + + JAVADB_API_BEGIN(db, jthis); + db->errx(db, msg_string.string); + JAVADB_API_END(db); + + out: + jstr_unlock(&msg_string, jnienv); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_fd + (JNIEnv *jnienv, /*Db*/ jobject jthis) +{ + int err; + int return_value = 0; + DB *db = get_DB(jnienv, jthis); + + if (!verify_non_null(jnienv, db)) + return (0); + + JAVADB_API_BEGIN(db, jthis); + err = db->fd(db, &return_value); + verify_return(jnienv, err, 0); + JAVADB_API_END(db); + + return (return_value); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_feedback_1changed + (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbFeedback*/ jobject jfeedback) +{ + DB *db; + DB_JAVAINFO *dbinfo; + + db = get_DB(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + return; + + JAVADB_API_BEGIN(db, jthis); + dbinfo = (DB_JAVAINFO*)db->cj_internal; + dbji_set_feedback_object(dbinfo, jnienv, db, jfeedback); + JAVADB_API_END(db); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_get + (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbTxn*/ jobject txnid, + /*Dbt*/ jobject key, /*Dbt*/ jobject data, jint flags) +{ + int err, op_flags, retry; + DB *db; + OpKind keyop, dataop; + DB_TXN *dbtxnid; + JDBT dbkey, dbdata; + + err = 0; + db = get_DB(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + goto out3; + + JAVADB_API_BEGIN(db, jthis); + + /* Depending on flags, the key may be input/output. */ + keyop = inOp; + dataop = outOp; + op_flags = flags & DB_OPFLAGS_MASK; + if (op_flags == DB_SET_RECNO) { + keyop = inOutOp; + } + else if (op_flags == DB_GET_BOTH) { + keyop = inOutOp; + dataop = inOutOp; + } + + dbtxnid = get_DB_TXN(jnienv, txnid); + + if (jdbt_lock(&dbkey, jnienv, key, keyop) != 0) + goto out2; + if (jdbt_lock(&dbdata, jnienv, data, dataop) != 0) + goto out1; + for (retry = 0; retry < 3; retry++) { + err = db->get(db, dbtxnid, &dbkey.dbt->dbt, &dbdata.dbt->dbt, flags); + + /* If we failed due to lack of memory in our DBT arrays, + * retry. + */ + if (err != ENOMEM) + break; + if (!jdbt_realloc(&dbdata, jnienv)) + break; + } + if (err != DB_NOTFOUND) { + verify_return(jnienv, err, 0); + } + out1: + jdbt_unlock(&dbdata, jnienv); + out2: + jdbt_unlock(&dbkey, jnienv); + out3: + JAVADB_API_END(db); + return (err); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_hash_1changed + (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbHash*/ jobject jhash) +{ + DB *db; + DB_JAVAINFO *dbinfo; + + db = get_DB(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + return; + + JAVADB_API_BEGIN(db, jthis); + dbinfo = (DB_JAVAINFO*)db->cj_internal; + dbji_set_h_hash_object(dbinfo, jnienv, db, jhash); + JAVADB_API_END(db); +} + +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Db_join + (JNIEnv *jnienv, /*Db*/ jobject jthis, /*Dbc[]*/ jobjectArray curslist, + jint flags) +{ + int err; + DB *db = get_DB(jnienv, jthis); + int count = (*jnienv)->GetArrayLength(jnienv, curslist); + DBC **newlist = (DBC **)malloc(sizeof(DBC *) * (count+1)); + DBC *dbc; + int i; + + /* Convert the java array of Dbc's to a C array of DBC's. */ + for (i=0; i<count; i++) { + jobject jobj = (*jnienv)->GetObjectArrayElement(jnienv, curslist, i); + if (jobj == 0) { + /* + * An embedded null in the array is treated + * as an endpoint. + */ + newlist[i] = 0; + break; + } + else { + newlist[i] = get_DBC(jnienv, jobj); + } + } + newlist[count] = 0; + + if (!verify_non_null(jnienv, db)) + return (NULL); + JAVADB_API_BEGIN(db, jthis); + + err = db->join(db, newlist, &dbc, flags); + free(newlist); + verify_return(jnienv, err, 0); + + JAVADB_API_END(db); + return (get_Dbc(jnienv, dbc)); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_key_1range + (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbTxn*/ jobject jtxn, + /*Dbt*/ jobject jkey, jobject /*DbKeyRange*/ range, jint flags) +{ + int err; + DB *db = get_DB(jnienv, jthis); + DB_TXN *txn = get_DB_TXN(jnienv, jtxn); + JDBT dbkey; + DB_KEY_RANGE result; + jfieldID fid; + jclass krclass; + + if (!verify_non_null(jnienv, db)) + return; + JAVADB_API_BEGIN(db, jthis); + if (!verify_non_null(jnienv, range)) + return; + if (jdbt_lock(&dbkey, jnienv, jkey, inOp) != 0) + goto out; + err = db->key_range(db, txn, &dbkey.dbt->dbt, &result, flags); + if (verify_return(jnienv, err, 0)) { + /* fill in the values of the DbKeyRange structure */ + krclass = get_class(jnienv, "DbKeyRange"); + fid = (*jnienv)->GetFieldID(jnienv, krclass, "less", "D"); + (*jnienv)->SetDoubleField(jnienv, range, fid, result.less); + fid = (*jnienv)->GetFieldID(jnienv, krclass, "equal", "D"); + (*jnienv)->SetDoubleField(jnienv, range, fid, result.equal); + fid = (*jnienv)->GetFieldID(jnienv, krclass, "greater", "D"); + (*jnienv)->SetDoubleField(jnienv, range, fid, result.greater); + } + out: + jdbt_unlock(&dbkey, jnienv); + JAVADB_API_END(db); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_put + (JNIEnv *jnienv, /*Db*/ jobject jthis, /*DbTxn*/ jobject txnid, + /*Dbt*/ jobject key, /*Dbt*/ jobject data, jint flags) +{ + int err; + DB *db; + DB_TXN *dbtxnid; + JDBT dbkey, dbdata; + + err = 0; + db = get_DB(jnienv, jthis); + dbtxnid = get_DB_TXN(jnienv, txnid); + if (!verify_non_null(jnienv, db)) + return (0); /* error will be thrown, retval doesn't matter */ + JAVADB_API_BEGIN(db, jthis); + + if (jdbt_lock(&dbkey, jnienv, key, inOp) != 0) + goto out2; + if (jdbt_lock(&dbdata, jnienv, data, inOp) != 0) + goto out1; + + if (!verify_non_null(jnienv, db)) + goto out1; + err = db->put(db, dbtxnid, &dbkey.dbt->dbt, &dbdata.dbt->dbt, flags); + if (err != DB_KEYEXIST) { + verify_return(jnienv, err, 0); + } + out1: + jdbt_unlock(&dbdata, jnienv); + out2: + jdbt_unlock(&dbkey, jnienv); + JAVADB_API_END(db); + return (err); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_rename + (JNIEnv *jnienv, /*Db*/ jobject jthis, jstring file, + jstring database, jstring newname, jint flags) +{ + int err; + DB *db; + DB_JAVAINFO *dbinfo; + JSTR j_file; + JSTR j_database; + JSTR j_newname; + + db = get_DB(jnienv, jthis); + dbinfo = get_DB_JAVAINFO(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + return; + JAVADB_API_BEGIN(db, jthis); + if (jstr_lock(&j_file, jnienv, file) != 0) + goto out3; + if (jstr_lock(&j_database, jnienv, database) != 0) + goto out2; + if (jstr_lock(&j_newname, jnienv, newname) != 0) + goto out1; + + err = db->rename(db, j_file.string, j_database.string, + j_newname.string, flags); + + verify_return(jnienv, err, EXCEPTION_FILE_NOT_FOUND); + dbji_dealloc(dbinfo, jnienv); + set_private_dbobj(jnienv, name_DB, jthis, 0); + + out1: + jstr_unlock(&j_newname, jnienv); + out2: + jstr_unlock(&j_database, jnienv); + out3: + jstr_unlock(&j_file, jnienv); + /* don't call JAVADB_API_END - db cannot be used */ +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_remove + (JNIEnv *jnienv, /*Db*/ jobject jthis, jstring file, + jstring database, jint flags) +{ + int err; + DB *db = get_DB(jnienv, jthis); + DB_JAVAINFO *dbinfo = get_DB_JAVAINFO(jnienv, jthis); + JSTR j_file; + JSTR j_database; + + dbinfo = get_DB_JAVAINFO(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + return; + JAVADB_API_BEGIN(db, jthis); + if (jstr_lock(&j_file, jnienv, file) != 0) + goto out2; + if (jstr_lock(&j_database, jnienv, database) != 0) + goto out1; + err = db->remove(db, j_file.string, j_database.string, flags); + + set_private_dbobj(jnienv, name_DB, jthis, 0); + verify_return(jnienv, err, EXCEPTION_FILE_NOT_FOUND); + dbji_dealloc(dbinfo, jnienv); + + out1: + jstr_unlock(&j_database, jnienv); + out2: + jstr_unlock(&j_file, jnienv); + /* don't call JAVADB_API_END - db cannot be used */ +} + +JNIEXPORT void JNICALL + Java_com_sleepycat_db_Db_set_1pagesize + (JNIEnv *jnienv, /*Db*/ jobject jthis, jlong value) +{ + int err; + DB *db; + + db = get_DB(jnienv, jthis); + if (verify_non_null(jnienv, db)) { + JAVADB_API_BEGIN(db, jthis); + err = db->set_pagesize(db, (u_int32_t)value); + verify_return(jnienv, err, 0); + JAVADB_API_END(db); + } +} + +JNIEXPORT void JNICALL + Java_com_sleepycat_db_Db_set_1cachesize + (JNIEnv *jnienv, /*Db*/ jobject jthis, jint gbytes, jint bytes, + jint ncaches) +{ + int err; + DB *db; + + db = get_DB(jnienv, jthis); + if (verify_non_null(jnienv, db)) { + JAVADB_API_BEGIN(db, jthis); + err = db->set_cachesize(db, gbytes, bytes, ncaches); + verify_return(jnienv, err, 0); + JAVADB_API_END(db); + } +} + +JNIEXPORT void JNICALL + Java_com_sleepycat_db_Db_set_1re_1source + (JNIEnv *jnienv, /*Db*/ jobject jthis, jstring re_source) +{ + int err; + DB *db; + + db = get_DB(jnienv, jthis); + if (verify_non_null(jnienv, db)) { + JAVADB_API_BEGIN(db, jthis); + + /* XXX does the string from get_c_string ever get freed? */ + if (re_source != NULL) + err = db->set_re_source(db, get_c_string(jnienv, re_source)); + else + err = db->set_re_source(db, 0); + + verify_return(jnienv, err, 0); + JAVADB_API_END(db); + } +} + +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Db_stat + (JNIEnv *jnienv, jobject jthis, jint flags) +{ + int err; + DB *db = get_DB(jnienv, jthis); + jobject retval = NULL; + jclass dbclass; + void *statp = 0; + DB_BTREE_STAT *bstp; + DB_HASH_STAT *hstp; + DB_QUEUE_STAT *qstp; + + if (!verify_non_null(jnienv, db)) + return (NULL); + + JAVADB_API_BEGIN(db, jthis); + + err = db->stat(db, &statp, NULL, flags); + if (verify_return(jnienv, err, 0)) { + DBTYPE dbtype = db->get_type(db); + switch (dbtype) { + + /* Btree and recno share the same stat structure */ + case DB_BTREE: + case DB_RECNO: + bstp = (DB_BTREE_STAT *)statp; + retval = create_default_object(jnienv, + name_DB_BTREE_STAT); + dbclass = get_class(jnienv, name_DB_BTREE_STAT); + + /* Set the individual fields */ + set_int_field(jnienv, dbclass, retval, + "bt_magic", bstp->bt_magic); + set_int_field(jnienv, dbclass, retval, + "bt_version", bstp->bt_version); + set_int_field(jnienv, dbclass, retval, + "bt_metaflags", bstp->bt_metaflags); + set_int_field(jnienv, dbclass, retval, + "bt_nkeys", bstp->bt_nkeys); + set_int_field(jnienv, dbclass, retval, + "bt_ndata", bstp->bt_ndata); + set_int_field(jnienv, dbclass, retval, + "bt_pagesize", bstp->bt_pagesize); + set_int_field(jnienv, dbclass, retval, + "bt_maxkey", bstp->bt_maxkey); + set_int_field(jnienv, dbclass, retval, + "bt_minkey", bstp->bt_minkey); + set_int_field(jnienv, dbclass, retval, + "bt_re_len", bstp->bt_re_len); + set_int_field(jnienv, dbclass, retval, + "bt_re_pad", bstp->bt_re_pad); + set_int_field(jnienv, dbclass, retval, + "bt_levels", bstp->bt_levels); + set_int_field(jnienv, dbclass, retval, + "bt_int_pg", bstp->bt_int_pg); + set_int_field(jnienv, dbclass, retval, + "bt_leaf_pg", bstp->bt_leaf_pg); + set_int_field(jnienv, dbclass, retval, + "bt_dup_pg", bstp->bt_dup_pg); + set_int_field(jnienv, dbclass, retval, + "bt_over_pg", bstp->bt_over_pg); + set_int_field(jnienv, dbclass, retval, + "bt_free", bstp->bt_free); + set_int_field(jnienv, dbclass, retval, + "bt_int_pgfree", bstp->bt_int_pgfree); + set_int_field(jnienv, dbclass, retval, + "bt_leaf_pgfree", bstp->bt_leaf_pgfree); + set_int_field(jnienv, dbclass, retval, + "bt_dup_pgfree", bstp->bt_dup_pgfree); + set_int_field(jnienv, dbclass, retval, + "bt_over_pgfree", bstp->bt_over_pgfree); + + break; + + /* Hash stat structure */ + case DB_HASH: + hstp = (DB_HASH_STAT *)statp; + retval = create_default_object(jnienv, + name_DB_HASH_STAT); + dbclass = get_class(jnienv, name_DB_HASH_STAT); + + /* Set the individual fields */ + set_int_field(jnienv, dbclass, retval, + "hash_magic", hstp->hash_magic); + set_int_field(jnienv, dbclass, retval, + "hash_version", hstp->hash_version); + set_int_field(jnienv, dbclass, retval, + "hash_metaflags", hstp->hash_metaflags); + set_int_field(jnienv, dbclass, retval, + "hash_nkeys", hstp->hash_nkeys); + set_int_field(jnienv, dbclass, retval, + "hash_ndata", hstp->hash_ndata); + set_int_field(jnienv, dbclass, retval, + "hash_pagesize", hstp->hash_pagesize); + set_int_field(jnienv, dbclass, retval, + "hash_nelem", hstp->hash_nelem); + set_int_field(jnienv, dbclass, retval, + "hash_ffactor", hstp->hash_ffactor); + set_int_field(jnienv, dbclass, retval, + "hash_buckets", hstp->hash_buckets); + set_int_field(jnienv, dbclass, retval, + "hash_free", hstp->hash_free); + set_int_field(jnienv, dbclass, retval, + "hash_bfree", hstp->hash_bfree); + set_int_field(jnienv, dbclass, retval, + "hash_bigpages", hstp->hash_bigpages); + set_int_field(jnienv, dbclass, retval, + "hash_big_bfree", hstp->hash_big_bfree); + set_int_field(jnienv, dbclass, retval, + "hash_overflows", hstp->hash_overflows); + set_int_field(jnienv, dbclass, retval, + "hash_ovfl_free", hstp->hash_ovfl_free); + set_int_field(jnienv, dbclass, retval, + "hash_dup", hstp->hash_dup); + set_int_field(jnienv, dbclass, retval, + "hash_dup_free", hstp->hash_dup_free); + + break; + + case DB_QUEUE: + qstp = (DB_QUEUE_STAT *)statp; + retval = create_default_object(jnienv, + name_DB_QUEUE_STAT); + dbclass = get_class(jnienv, name_DB_QUEUE_STAT); + + /* Set the individual fields */ + set_int_field(jnienv, dbclass, retval, + "qs_magic", qstp->qs_magic); + set_int_field(jnienv, dbclass, retval, + "qs_version", qstp->qs_version); + set_int_field(jnienv, dbclass, retval, + "qs_metaflags", qstp->qs_metaflags); + set_int_field(jnienv, dbclass, retval, + "qs_nkeys", qstp->qs_nkeys); + set_int_field(jnienv, dbclass, retval, + "qs_ndata", qstp->qs_ndata); + set_int_field(jnienv, dbclass, retval, + "qs_pagesize", qstp->qs_pagesize); + set_int_field(jnienv, dbclass, retval, + "qs_pages", qstp->qs_pages); + set_int_field(jnienv, dbclass, retval, + "qs_re_len", qstp->qs_re_len); + set_int_field(jnienv, dbclass, retval, + "qs_re_pad", qstp->qs_re_pad); + set_int_field(jnienv, dbclass, retval, + "qs_pgfree", qstp->qs_pgfree); + set_int_field(jnienv, dbclass, retval, + "qs_first_recno", qstp->qs_first_recno); + set_int_field(jnienv, dbclass, retval, + "qs_cur_recno", qstp->qs_cur_recno); + break; + + /* That's all the database types we're aware of! */ + default: + report_exception(jnienv, + "Db.stat not implemented for types" + "other than HASH, BTREE and RECNO", + EINVAL, 0); + break; + } + free(statp); + } + JAVADB_API_END(db); + return (retval); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_sync + (JNIEnv *jnienv, /*Db*/ jobject jthis, jint flags) +{ + int err; + DB *db = get_DB(jnienv, jthis); + + if (!verify_non_null(jnienv, db)) + return (0); + JAVADB_API_BEGIN(db, jthis); + err = db->sync(db, flags); + if (err != DB_INCOMPLETE) + verify_return(jnienv, err, 0); + JAVADB_API_END(db); + return (err); +} + +JNIEXPORT jboolean JNICALL Java_com_sleepycat_db_Db_get_1byteswapped + (JNIEnv *jnienv, /*Db*/ jobject jthis) +{ + DB *db; + jboolean retval; + + db = get_DB(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + return (0); + + JAVADB_API_BEGIN(db, jthis); + retval = db->get_byteswapped(db) ? 1 : 0; + JAVADB_API_END(db); + return (retval); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Db_get_1type + (JNIEnv *jnienv, /*Db*/ jobject jthis) +{ + DB *db; + + db = get_DB(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + return (0); + + return ((jint)db->type); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1open + (JNIEnv *jnienv, /*Db*/ jobject jthis, jstring file, jstring database, + jint type, jint flags, jint mode) +{ + int err; + DB *db; + JSTR dbfile; + JSTR dbdatabase; + + /* Java is assumed to be threaded. */ + flags |= DB_THREAD; + + db = get_DB(jnienv, jthis); + if (jstr_lock(&dbfile, jnienv, file) != 0) + goto out2; + if (jstr_lock(&dbdatabase, jnienv, database) != 0) + goto out1; + if (verify_non_null(jnienv, db)) { + JAVADB_API_BEGIN(db, jthis); + err = db->open(db, dbfile.string, dbdatabase.string, + (DBTYPE)type, flags, mode); + verify_return(jnienv, err, EXCEPTION_FILE_NOT_FOUND); + JAVADB_API_END(db); + } + out1: + jstr_unlock(&dbdatabase, jnienv); + out2: + jstr_unlock(&dbfile, jnienv); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_upgrade + (JNIEnv *jnienv, /*Db*/ jobject jthis, jstring name, + jint flags) +{ + int err; + DB *db = get_DB(jnienv, jthis); + JSTR j_name; + + if (verify_non_null(jnienv, db)) { + JAVADB_API_BEGIN(db, jthis); + if (jstr_lock(&j_name, jnienv, name) != 0) + goto out; + err = db->upgrade(db, j_name.string, flags); + verify_return(jnienv, err, 0); + JAVADB_API_END(db); + } + out: + jstr_unlock(&j_name, jnienv); +} + +static int java_verify_callback(void *handle, const void *str_arg) +{ + char *str; + struct verify_callback_struct *vc; + int len; + jthrowable except; + JNIEnv *jnienv; + + str = (char *)str_arg; + vc = (struct verify_callback_struct *)handle; + jnienv = vc->env; + len = strlen(str)+1; + if (len > vc->nbytes) { + vc->nbytes = len; + vc->bytes = (*jnienv)->NewByteArray(jnienv, len); + } + (*jnienv)->SetByteArrayRegion(jnienv, vc->bytes, 0, len, (jbyte*)str); + (*jnienv)->CallVoidMethod(jnienv, vc->streamobj, + vc->writemid, vc->bytes, 0, len-1); + + if ((except = (*jnienv)->ExceptionOccurred(jnienv)) != NULL) + return (EIO); + + return (0); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db_verify + (JNIEnv *jnienv, /*Db*/ jobject jthis, jstring name, + jstring subdb, jobject stream, jint flags) +{ + int err; + DB *db; + JSTR j_name; + JSTR j_subdb; + struct verify_callback_struct vcs; + jclass streamclass; + + db = get_DB(jnienv, jthis); + if (!verify_non_null(jnienv, db)) + return; + JAVADB_API_BEGIN(db, jthis); + + if (jstr_lock(&j_name, jnienv, name) != 0) + goto out2; + if (jstr_lock(&j_subdb, jnienv, subdb) != 0) + goto out1; + + /* set up everything we need for the callbacks */ + vcs.env = jnienv; + vcs.streamobj = stream; + vcs.nbytes = 100; + vcs.bytes = (*jnienv)->NewByteArray(jnienv, vcs.nbytes); + + /* get the method ID for OutputStream.write(byte[], int, int); */ + streamclass = (*jnienv)->FindClass(jnienv, "java/io/OutputStream"); + vcs.writemid = (*jnienv)->GetMethodID(jnienv, streamclass, + "write", "([BII)V"); + + /* invoke verify - this will invoke the callback repeatedly. */ + err = __db_verify_internal(db, j_name.string, j_subdb.string, + &vcs, java_verify_callback, flags); + verify_return(jnienv, err, 0); + +out1: + jstr_unlock(&j_subdb, jnienv); +out2: + jstr_unlock(&j_name, jnienv); + JAVADB_API_END(db); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Db__1finalize + (JNIEnv *jnienv, jobject jthis, + jobject /*DbErrcall*/ errcall, jstring errpfx) +{ + DB_JAVAINFO *dbinfo; + DB *db; + + dbinfo = get_DB_JAVAINFO(jnienv, jthis); + db = get_DB(jnienv, jthis); + DB_ASSERT(dbinfo != NULL); + + /* Note: We can never be sure if the underlying DB is attached to + * a DB_ENV that was already closed. Sure, that's a user error, + * but it shouldn't crash the VM. Therefore, we cannot just + * automatically close if the handle indicates we are not yet + * closed. The best we can do is detect this and report it. + */ + if (db != NULL) { + /* If this error occurs, this object was never closed. */ + report_errcall(jnienv, errcall, errpfx, + "Db.finalize: open Db object destroyed"); + } + + /* Shouldn't see this object again, but just in case */ + set_private_dbobj(jnienv, name_DB, jthis, 0); + set_private_info(jnienv, name_DB, jthis, 0); + + dbji_destroy(dbinfo, jnienv); +} diff --git a/bdb/libdb_java/java_DbEnv.c b/bdb/libdb_java/java_DbEnv.c new file mode 100644 index 00000000000..ff9207dd2c8 --- /dev/null +++ b/bdb/libdb_java/java_DbEnv.c @@ -0,0 +1,1300 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 1998, 1999, 2000 + * Sleepycat Software. All rights reserved. + */ +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: java_DbEnv.c,v 11.37 2001/01/11 18:19:52 bostic Exp $"; +#endif /* not lint */ + +#include <jni.h> +#include <stdlib.h> +#include <string.h> + +#include "db.h" +#include "db_int.h" +#include "java_util.h" +#include "com_sleepycat_db_DbEnv.h" + +/* We keep these lined up, and alphabetical by field name, + * for comparison with C++'s list. + */ +JAVADB_WO_ACCESS_STRING(DbEnv, data_1dir, DB_ENV, data_dir) +JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lg_1bsize, DB_ENV, lg_bsize) +JAVADB_WO_ACCESS_STRING(DbEnv, lg_1dir, DB_ENV, lg_dir) +JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lg_1max, DB_ENV, lg_max) +JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lk_1detect, DB_ENV, lk_detect) +JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lk_1max, DB_ENV, lk_max) +JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lk_1max_1locks, DB_ENV, lk_max_locks) +JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lk_1max_1lockers, DB_ENV, lk_max_lockers) +JAVADB_WO_ACCESS_METHOD(DbEnv, jint, lk_1max_1objects, DB_ENV, lk_max_objects) +/* mp_mmapsize is declared below, it needs an extra cast */ +JAVADB_WO_ACCESS_METHOD(DbEnv, jint, mutexlocks, DB_ENV, mutexlocks) +JAVADB_WO_ACCESS_STRING(DbEnv, tmp_1dir, DB_ENV, tmp_dir) +JAVADB_WO_ACCESS_METHOD(DbEnv, jint, tx_1max, DB_ENV, tx_max) + +static void DbEnv_errcall_callback(const char *prefix, char *message) +{ + JNIEnv *jnienv; + DB_ENV_JAVAINFO *envinfo = (DB_ENV_JAVAINFO *)prefix; + jstring pre; + + /* Note: these error cases are "impossible", and would + * normally warrant an exception. However, without + * a jnienv, we cannot throw an exception... + * We don't want to trap or exit, since the point of + * this facility is for the user to completely control + * error situations. + */ + if (envinfo == NULL) { + /* Something is *really* wrong here, the + * prefix is set in every environment created. + */ + fprintf(stderr, "Error callback failed!\n"); + fprintf(stderr, "error: %s\n", message); + return; + } + + /* Should always succeed... */ + jnienv = dbjie_get_jnienv(envinfo); + + if (jnienv == NULL) { + + /* But just in case... */ + fprintf(stderr, "Cannot attach to current thread!\n"); + fprintf(stderr, "error: %s\n", message); + return; + } + + pre = dbjie_get_errpfx(envinfo, jnienv); + report_errcall(jnienv, dbjie_get_errcall(envinfo), pre, message); +} + +static void DbEnv_initialize(JNIEnv *jnienv, DB_ENV *dbenv, + /*DbEnv*/ jobject jenv, + /*DbErrcall*/ jobject jerrcall, + int is_dbopen) +{ + DB_ENV_JAVAINFO *envinfo; + + envinfo = get_DB_ENV_JAVAINFO(jnienv, jenv); + DB_ASSERT(envinfo == NULL); + envinfo = dbjie_construct(jnienv, jerrcall, is_dbopen); + set_private_info(jnienv, name_DB_ENV, jenv, envinfo); + dbenv->set_errpfx(dbenv, (const char*)envinfo); + dbenv->set_errcall(dbenv, DbEnv_errcall_callback); + dbenv->cj_internal = envinfo; + set_private_dbobj(jnienv, name_DB_ENV, jenv, dbenv); +} + +/* This is called when this DbEnv was made on behalf of a Db + * created directly (without a parent DbEnv), and the Db is + * being closed. We'll zero out the pointer to the DB_ENV, + * since it is no longer valid, to prevent mistakes. + */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1notify_1db_1close + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis) +{ + DB_ENV_JAVAINFO *dbenvinfo; + + set_private_dbobj(jnienv, name_DB_ENV, jthis, 0); + dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis); + if (dbenvinfo != NULL) + dbjie_dealloc(dbenvinfo, jnienv); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_feedback_1changed + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbFeedback*/ jobject jfeedback) +{ + DB_ENV *dbenv; + DB_ENV_JAVAINFO *dbenvinfo; + + dbenv = get_DB_ENV(jnienv, jthis); + dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv) || + !verify_non_null(jnienv, dbenvinfo)) + return; + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + dbjie_set_feedback_object(dbenvinfo, jnienv, dbenv, jfeedback); + JAVADB_ENV_API_END(dbenv); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1init + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jobject /*DbErrcall*/ jerrcall, + jint flags) +{ + int err; + DB_ENV *dbenv; + + err = db_env_create(&dbenv, flags); + if (verify_return(jnienv, err, 0)) + DbEnv_initialize(jnienv, dbenv, jthis, jerrcall, 0); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1init_1using_1db + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jobject /*DbErrcall*/ jerrcall, + /*Db*/ jobject jdb) +{ + DB_ENV *dbenv; + DB *db; + + db = get_DB(jnienv, jdb); + dbenv = db->dbenv; + DbEnv_initialize(jnienv, dbenv, jthis, jerrcall, 1); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_open + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jstring db_home, + jint flags, jint mode) +{ + int err; + DB_ENV *dbenv; + JSTR j_home; + DB_ENV_JAVAINFO *dbenvinfo; + + dbenv = get_DB_ENV(jnienv, jthis); + dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv) || + !verify_non_null(jnienv, dbenvinfo)) + return; + JAVADB_ENV_API_BEGIN(dbenv, jthis); + if (jstr_lock(&j_home, jnienv, db_home) != 0) + goto out; + + /* Java is assumed to be threaded. */ + flags |= DB_THREAD; + + err = dbenv->open(dbenv, j_home.string, flags, mode); + verify_return(jnienv, err, EXCEPTION_FILE_NOT_FOUND); + out: + jstr_unlock(&j_home, jnienv); + JAVADB_ENV_API_END(dbenv); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_remove + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jstring db_home, jint flags) +{ + DB_ENV *dbenv; + DB_ENV_JAVAINFO *dbenvinfo; + JSTR j_home; + int err = 0; + + dbenv = get_DB_ENV(jnienv, jthis); + dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv)) + return; + JAVADB_ENV_API_BEGIN(dbenv, jthis); + if (jstr_lock(&j_home, jnienv, db_home) != 0) + goto out; + + err = dbenv->remove(dbenv, j_home.string, flags); + set_private_dbobj(jnienv, name_DB_ENV, jthis, 0); + + if (dbenvinfo != NULL) + dbjie_dealloc(dbenvinfo, jnienv); + + verify_return(jnienv, err, 0); + out: + jstr_unlock(&j_home, jnienv); + /* don't call JAVADB_ENV_API_END - env cannot be used */ +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1close + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint flags) +{ + int err; + DB_ENV *dbenv; + DB_ENV_JAVAINFO *dbenvinfo; + + dbenv = get_DB_ENV(jnienv, jthis); + dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv)) + return; + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + err = dbenv->close(dbenv, flags); + set_private_dbobj(jnienv, name_DB_ENV, jthis, 0); + + if (dbenvinfo != NULL) + dbjie_dealloc(dbenvinfo, jnienv); + + /* Throw an exception if the close failed. */ + verify_return(jnienv, err, 0); + + /* don't call JAVADB_ENV_API_END - env cannot be used */ +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_err + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint ecode, jstring msg) +{ + JSTR msg_string; + DB_ENV *dbenv; + + dbenv = get_DB_ENV(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv)) + return; + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + if (jstr_lock(&msg_string, jnienv, msg) != 0) + goto out; + + dbenv->err(dbenv, ecode, msg_string.string); + out: + jstr_unlock(&msg_string, jnienv); + JAVADB_ENV_API_END(dbenv); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_errx + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jstring msg) +{ + JSTR msg_string; + DB_ENV *dbenv; + + dbenv = get_DB_ENV(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv)) + return; + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + if (jstr_lock(&msg_string, jnienv, msg) != 0) + goto out; + + dbenv->errx(dbenv, msg_string.string); + out: + jstr_unlock(&msg_string, jnienv); + JAVADB_ENV_API_END(dbenv); +} + +/*static*/ +JNIEXPORT jstring JNICALL Java_com_sleepycat_db_DbEnv_strerror + (JNIEnv *jnienv, jclass jthis_class, jint ecode) +{ + const char *message; + + COMPQUIET(jthis_class, NULL); + message = db_strerror(ecode); + return (get_java_string(jnienv, message)); +} + +JNIEXPORT void JNICALL + Java_com_sleepycat_db_DbEnv_set_1cachesize + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint gbytes, jint bytes, + jint ncaches) +{ + DB_ENV *dbenv; + int err; + + dbenv = get_DB_ENV(jnienv, jthis); + if (verify_non_null(jnienv, dbenv)) { + JAVADB_ENV_API_BEGIN(dbenv, jthis); + err = dbenv->set_cachesize(dbenv, gbytes, bytes, ncaches); + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); + } +} + +JNIEXPORT void JNICALL + Java_com_sleepycat_db_DbEnv_set_1flags + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint flags, jint onoff) +{ + DB_ENV *dbenv; + int err; + + dbenv = get_DB_ENV(jnienv, jthis); + if (verify_non_null(jnienv, dbenv)) { + JAVADB_ENV_API_BEGIN(dbenv, jthis); + err = dbenv->set_flags(dbenv, flags, onoff); + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); + } +} + +JNIEXPORT void JNICALL + Java_com_sleepycat_db_DbEnv_set_1mp_1mmapsize + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jlong value) +{ + DB_ENV *dbenv; + int err; + + dbenv = get_DB_ENV(jnienv, jthis); + if (verify_non_null(jnienv, dbenv)) { + JAVADB_ENV_API_BEGIN(dbenv, jthis); + err = dbenv->set_mp_mmapsize(dbenv, (size_t)value); + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); + } +} + +/*static*/ +JNIEXPORT void JNICALL + Java_com_sleepycat_db_DbEnv_set_1pageyield + (JNIEnv *jnienv, jclass jthis_class, jint value) +{ + int err; + + COMPQUIET(jthis_class, NULL); + err = db_env_set_pageyield(value); + verify_return(jnienv, err, 0); +} + +/*static*/ +JNIEXPORT void JNICALL + Java_com_sleepycat_db_DbEnv_set_1panicstate + (JNIEnv *jnienv, jclass jthis_class, jint value) +{ + int err; + + COMPQUIET(jthis_class, NULL); + err = db_env_set_panicstate(value); + verify_return(jnienv, err, 0); +} + +/*static*/ +JNIEXPORT void JNICALL + Java_com_sleepycat_db_DbEnv_set_1region_1init + (JNIEnv *jnienv, jclass jthis_class, jint value) +{ + int err; + + COMPQUIET(jthis_class, NULL); + err = db_env_set_region_init(value); + verify_return(jnienv, err, 0); +} + +/*static*/ +JNIEXPORT void JNICALL + Java_com_sleepycat_db_DbEnv_set_1tas_1spins + (JNIEnv *jnienv, jclass jthis_class, jint value) +{ + int err; + + COMPQUIET(jthis_class, NULL); + err = db_env_set_tas_spins(value); + verify_return(jnienv, err, 0); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_recovery_1init_1changed + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbRecoveryInit*/ jobject jrecoveryinit) +{ + DB_ENV *dbenv; + DB_ENV_JAVAINFO *dbenvinfo; + + dbenv = get_DB_ENV(jnienv, jthis); + dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv) || + !verify_non_null(jnienv, dbenv)) + return; + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + dbjie_set_recovery_init_object(dbenvinfo, jnienv, dbenv, jrecoveryinit); + JAVADB_ENV_API_END(dbenv); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_set_1lk_1conflicts + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jobjectArray array) +{ + DB_ENV *dbenv; + DB_ENV_JAVAINFO *dbenvinfo; + int err; + jsize i, len; + unsigned char *newarr; + + dbenv = get_DB_ENV(jnienv, jthis); + dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv) || + !verify_non_null(jnienv, dbenvinfo)) + return; + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + len = (*jnienv)->GetArrayLength(jnienv, array); + + newarr = (unsigned char *)malloc(sizeof(unsigned char) * len * len); + + for (i=0; i<len; i++) { + jobject subArray = + (*jnienv)->GetObjectArrayElement(jnienv, array, i); + (*jnienv)->GetByteArrayRegion(jnienv, (jbyteArray)subArray, + 0, len, + (jbyte *)&newarr[i*len]); + } + dbjie_set_conflict(dbenvinfo, newarr); + err = dbenv->set_lk_conflicts(dbenv, newarr, len); + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); +} + +JNIEXPORT void JNICALL + Java_com_sleepycat_db_DbEnv_set_1server + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jstring jhost, jlong tsec, + jlong ssec, jint flags) +{ + int err; + DB_ENV *dbenv = get_DB_ENV(jnienv, jthis); + const char *host = (*jnienv)->GetStringUTFChars(jnienv, jhost, NULL); + + if (verify_non_null(jnienv, dbenv)) { + JAVADB_ENV_API_BEGIN(dbenv, jthis); + err = dbenv->set_server(dbenv, (char *)host, + (long)tsec, (long)ssec, flags); + + /* Throw an exception if the call failed. */ + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); + } +} + +JNIEXPORT void JNICALL + Java_com_sleepycat_db_DbEnv_set_1shm_1key + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jlong shm_key) +{ + int err; + DB_ENV *dbenv = get_DB_ENV(jnienv, jthis); + + if (verify_non_null(jnienv, dbenv)) { + JAVADB_ENV_API_BEGIN(dbenv, jthis); + err = dbenv->set_shm_key(dbenv, (long)shm_key); + + /* Throw an exception if the call failed. */ + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); + } +} + +JNIEXPORT void JNICALL + Java_com_sleepycat_db_DbEnv__1set_1tx_1timestamp + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jlong seconds) +{ + int err; + DB_ENV *dbenv = get_DB_ENV(jnienv, jthis); + time_t time = seconds; + + if (verify_non_null(jnienv, dbenv)) { + JAVADB_ENV_API_BEGIN(dbenv, jthis); + err = dbenv->set_tx_timestamp(dbenv, &time); + + /* Throw an exception if the call failed. */ + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); + } +} + +JNIEXPORT void JNICALL + Java_com_sleepycat_db_DbEnv_set_1verbose + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint which, jint onoff) +{ + int err; + DB_ENV *dbenv = get_DB_ENV(jnienv, jthis); + + if (verify_non_null(jnienv, dbenv)) { + JAVADB_ENV_API_BEGIN(dbenv, jthis); + err = dbenv->set_verbose(dbenv, which, onoff); + + /* Throw an exception if the call failed. */ + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); + } +} + +/*static*/ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_get_1version_1major + (JNIEnv * jnienv, jclass this_class) +{ + COMPQUIET(jnienv, NULL); + COMPQUIET(this_class, NULL); + + return (DB_VERSION_MAJOR); +} + +/*static*/ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_get_1version_1minor + (JNIEnv * jnienv, jclass this_class) +{ + COMPQUIET(jnienv, NULL); + COMPQUIET(this_class, NULL); + + return (DB_VERSION_MINOR); +} + +/*static*/ +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_get_1version_1patch + (JNIEnv * jnienv, jclass this_class) +{ + COMPQUIET(jnienv, NULL); + COMPQUIET(this_class, NULL); + + return (DB_VERSION_PATCH); +} + +/*static*/ +JNIEXPORT jstring JNICALL Java_com_sleepycat_db_DbEnv_get_1version_1string + (JNIEnv *jnienv, jclass this_class) +{ + COMPQUIET(this_class, NULL); + + return ((*jnienv)->NewStringUTF(jnienv, DB_VERSION_STRING)); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_lock_1id + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis) +{ + int err; + u_int32_t id; + DB_ENV *dbenv = get_DB_ENV(jnienv, jthis); + + if (!verify_non_null(jnienv, dbenv)) + return (-1); + JAVADB_ENV_API_BEGIN(dbenv, jthis); + err = lock_id(dbenv, &id); + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); + return (id); +} + +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_lock_1stat + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis) +{ + int err; + DB_ENV *dbenv = get_DB_ENV(jnienv, jthis); + DB_LOCK_STAT *statp = NULL; + jobject retval = NULL; + jclass dbclass; + + if (!verify_non_null(jnienv, dbenv)) + return (NULL); + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + /* We cannot use the default allocator (on Win* platforms anyway) + * because it often causes problems when we free storage + * in a DLL that was allocated in another DLL. Using + * our own allocator (ours just calls malloc!) ensures + * that there is no mismatch. + */ + err = lock_stat(dbenv, &statp, NULL); + if (verify_return(jnienv, err, 0)) { + retval = create_default_object(jnienv, name_DB_LOCK_STAT); + dbclass = get_class(jnienv, name_DB_LOCK_STAT); + + /* Set the individual fields */ + set_int_field(jnienv, dbclass, retval, + "st_maxlocks", statp->st_maxlocks); + set_int_field(jnienv, dbclass, retval, + "st_nmodes", statp->st_nmodes); + set_int_field(jnienv, dbclass, retval, + "st_nlockers", statp->st_nlockers); + set_int_field(jnienv, dbclass, retval, + "st_nconflicts", statp->st_nconflicts); + set_int_field(jnienv, dbclass, retval, + "st_nrequests", statp->st_nrequests); + set_int_field(jnienv, dbclass, retval, + "st_nreleases", statp->st_nreleases); + set_int_field(jnienv, dbclass, retval, + "st_ndeadlocks", statp->st_ndeadlocks); + set_int_field(jnienv, dbclass, retval, + "st_region_wait", statp->st_region_wait); + set_int_field(jnienv, dbclass, retval, + "st_region_nowait", statp->st_region_nowait); + set_int_field(jnienv, dbclass, retval, + "st_regsize", statp->st_regsize); + + free(statp); + } + JAVADB_ENV_API_END(dbenv); + return (retval); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_lock_1detect + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint atype, jint flags) +{ + int err; + DB_ENV *dbenv = get_DB_ENV(jnienv, jthis); + int aborted; + + if (!verify_non_null(jnienv, dbenv)) + return (0); + JAVADB_ENV_API_BEGIN(dbenv, jthis); + err = lock_detect(dbenv, atype, flags, &aborted); + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); + return (aborted); +} + +JNIEXPORT /*DbLock*/ jobject JNICALL Java_com_sleepycat_db_DbEnv_lock_1get + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*u_int32_t*/ jint locker, + jint flags, /*const Dbt*/ jobject obj, /*db_lockmode_t*/ jint lock_mode) +{ + int err; + DB_ENV *dbenv; + DB_LOCK *dblock; + JDBT dbobj; + /*DbLock*/ jobject retval; + + dbenv = get_DB_ENV(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv)) + return (NULL); + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + dblock = (DB_LOCK*)malloc(sizeof(DB_LOCK)); + memset(dblock, 0, sizeof(DB_LOCK)); + err = 0; + retval = NULL; + if (jdbt_lock(&dbobj, jnienv, obj, inOp) != 0) + goto out; + + err = lock_get(dbenv, locker, flags, &dbobj.dbt->dbt, + (db_lockmode_t)lock_mode, dblock); + if (verify_return(jnienv, err, 0)) { + retval = create_default_object(jnienv, name_DB_LOCK); + set_private_dbobj(jnienv, name_DB_LOCK, retval, dblock); + } + out: + jdbt_unlock(&dbobj, jnienv); + JAVADB_ENV_API_END(dbenv); + return (retval); +} + +JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_DbEnv_log_1archive + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint flags) +{ + int err, len, i; + char** ret; + jclass stringClass; + jobjectArray strarray; + DB_ENV *dbenv; + + dbenv = get_DB_ENV(jnienv, jthis); + strarray = NULL; + if (!verify_non_null(jnienv, dbenv)) + return (0); + JAVADB_ENV_API_BEGIN(dbenv, jthis); + err = log_archive(dbenv, &ret, flags, 0); + if (!verify_return(jnienv, err, 0)) + return (0); + + if (ret != NULL) { + len = 0; + while (ret[len] != NULL) + len++; + stringClass = (*jnienv)->FindClass(jnienv, "java/lang/String"); + strarray = (*jnienv)->NewObjectArray(jnienv, len, + stringClass, 0); + for (i=0; i<len; i++) { + jstring str = (*jnienv)->NewStringUTF(jnienv, ret[i]); + (*jnienv)->SetObjectArrayElement(jnienv, strarray, + i, str); + } + } + JAVADB_ENV_API_END(dbenv); + return (strarray); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_log_1compare + (JNIEnv *jnienv, jclass jthis_class, + /*DbLsn*/ jobject lsn0, /*DbLsn*/ jobject lsn1) +{ + DB_LSN *dblsn0; + DB_LSN *dblsn1; + + COMPQUIET(jthis_class, NULL); + dblsn0 = get_DB_LSN(jnienv, lsn0); + dblsn1 = get_DB_LSN(jnienv, lsn1); + + return (log_compare(dblsn0, dblsn1)); +} + +JNIEXPORT jstring JNICALL Java_com_sleepycat_db_DbEnv_log_1file + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbLsn*/ jobject lsn) +{ + int err; + DB_ENV *dbenv = get_DB_ENV(jnienv, jthis); + DB_LSN *dblsn = get_DB_LSN(jnienv, lsn); + char filename[FILENAME_MAX+1] = ""; + + if (!verify_non_null(jnienv, dbenv)) + return (NULL); + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + err = log_file(dbenv, dblsn, filename, FILENAME_MAX); + verify_return(jnienv, err, 0); + filename[FILENAME_MAX] = '\0'; /* just to be sure */ + JAVADB_ENV_API_END(dbenv); + return (get_java_string(jnienv, filename)); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1flush + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbLsn*/ jobject lsn) +{ + int err; + DB_ENV *dbenv = get_DB_ENV(jnienv, jthis); + DB_LSN *dblsn = get_DB_LSN(jnienv, lsn); + + if (!verify_non_null(jnienv, dbenv)) + return; + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + err = log_flush(dbenv, dblsn); + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1get + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbLsn*/ jobject lsn, + /*DbDbt*/ jobject data, jint flags) +{ + int err, retry; + DB_ENV *dbenv; + DB_LSN *dblsn; + JDBT dbdata; + + dbenv = get_DB_ENV(jnienv, jthis); + dblsn = get_DB_LSN(jnienv, lsn); + + if (!verify_non_null(jnienv, dbenv)) + return; + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + if (jdbt_lock(&dbdata, jnienv, data, outOp) != 0) + goto out; + + for (retry = 0; retry < 3; retry++) { + err = log_get(dbenv, dblsn, &dbdata.dbt->dbt, flags); + /* If we failed due to lack of memory in our DBT arrays, + * retry. + */ + if (err != ENOMEM) + break; + if (!jdbt_realloc(&dbdata, jnienv)) + break; + } + + verify_return(jnienv, err, 0); + + out: + jdbt_unlock(&dbdata, jnienv); + JAVADB_ENV_API_END(dbenv); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1put + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbLsn*/ jobject lsn, + /*DbDbt*/ jobject data, jint flags) +{ + int err; + DB_ENV *dbenv; + DB_LSN *dblsn; + JDBT dbdata; + + dbenv = get_DB_ENV(jnienv, jthis); + dblsn = get_DB_LSN(jnienv, lsn); + if (!verify_non_null(jnienv, dbenv)) + return; + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + if (jdbt_lock(&dbdata, jnienv, data, inOp) != 0) + goto out; + + err = log_put(dbenv, dblsn, &dbdata.dbt->dbt, flags); + verify_return(jnienv, err, 0); + out: + jdbt_unlock(&dbdata, jnienv); + JAVADB_ENV_API_END(dbenv); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1register + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*Db*/ jobject dbp, + jstring name) +{ + int err; + DB_ENV *dbenv; + DB *dbdb; + JSTR dbname; + + dbenv = get_DB_ENV(jnienv, jthis); + dbdb = get_DB(jnienv, dbp); + if (!verify_non_null(jnienv, dbenv)) + return; + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + if (jstr_lock(&dbname, jnienv, name) != 0) + goto out; + + err = log_register(dbenv, dbdb, dbname.string); + verify_return(jnienv, err, 0); + out: + jstr_unlock(&dbname, jnienv); + JAVADB_ENV_API_END(dbenv); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_log_1unregister + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*Db*/ jobject dbp) +{ + int err; + DB_ENV *dbenv; + DB *dbdb; + + dbenv = get_DB_ENV(jnienv, jthis); + dbdb = get_DB(jnienv, dbp); + if (!verify_non_null(jnienv, dbenv)) + return; + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + err = log_unregister(dbenv, dbdb); + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); +} + +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_log_1stat + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis) +{ + int err; + DB_ENV *dbenv; + DB_LOG_STAT *statp; + jobject retval; + jclass dbclass; + + retval = NULL; + statp = NULL; + dbenv = get_DB_ENV(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv)) + return (NULL); + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + /* We cannot use the default allocator (on Win* platforms anyway) + * because it often causes problems when we free storage + * in a DLL that was allocated in another DLL. Using + * our own allocator (ours just calls malloc!) ensures + * that there is no mismatch. + */ + err = log_stat(dbenv, &statp, NULL); + if (verify_return(jnienv, err, 0)) { + retval = create_default_object(jnienv, name_DB_LOG_STAT); + dbclass = get_class(jnienv, name_DB_LOG_STAT); + + /* Set the individual fields */ + set_int_field(jnienv, dbclass, retval, + "st_magic", statp->st_magic); + set_int_field(jnienv, dbclass, retval, + "st_version", statp->st_version); + set_int_field(jnienv, dbclass, retval, + "st_mode", statp->st_mode); + set_int_field(jnienv, dbclass, retval, + "st_lg_max", statp->st_lg_max); + set_int_field(jnienv, dbclass, retval, + "st_w_bytes", statp->st_w_bytes); + set_int_field(jnienv, dbclass, retval, + "st_w_mbytes", statp->st_w_mbytes); + set_int_field(jnienv, dbclass, retval, + "st_wc_bytes", statp->st_wc_bytes); + set_int_field(jnienv, dbclass, retval, + "st_wc_mbytes", statp->st_wc_mbytes); + set_int_field(jnienv, dbclass, retval, + "st_wcount", statp->st_wcount); + set_int_field(jnienv, dbclass, retval, + "st_scount", statp->st_scount); + set_int_field(jnienv, dbclass, retval, + "st_region_wait", statp->st_region_wait); + set_int_field(jnienv, dbclass, retval, + "st_region_nowait", statp->st_region_nowait); + set_int_field(jnienv, dbclass, retval, + "st_cur_file", statp->st_cur_file); + set_int_field(jnienv, dbclass, retval, + "st_cur_offset", statp->st_cur_offset); + set_int_field(jnienv, dbclass, retval, + "st_regsize", statp->st_regsize); + + free(statp); + } + JAVADB_ENV_API_END(dbenv); + return (retval); +} + +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_memp_1stat + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis) +{ + int err; + jclass dbclass; + DB_ENV *dbenv; + DB_MPOOL_STAT *statp; + jobject retval; + + retval = NULL; + statp = NULL; + dbenv = get_DB_ENV(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv)) + return (NULL); + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + /* We cannot use the default allocator (on Win* platforms anyway) + * because it often causes problems when we free storage + * in a DLL that was allocated in another DLL. Using + * our own allocator (ours just calls malloc!) ensures + * that there is no mismatch. + */ + err = memp_stat(dbenv, &statp, 0, NULL); + if (verify_return(jnienv, err, 0)) { + retval = create_default_object(jnienv, name_DB_MPOOL_STAT); + dbclass = get_class(jnienv, name_DB_MPOOL_STAT); + + set_int_field(jnienv, dbclass, retval, "st_cachesize", 0); + set_int_field(jnienv, dbclass, retval, + "st_cache_hit", statp->st_cache_hit); + set_int_field(jnienv, dbclass, retval, + "st_cache_miss", statp->st_cache_miss); + set_int_field(jnienv, dbclass, retval, + "st_map", statp->st_map); + set_int_field(jnienv, dbclass, retval, + "st_page_create", statp->st_page_create); + set_int_field(jnienv, dbclass, retval, + "st_page_in", statp->st_page_in); + set_int_field(jnienv, dbclass, retval, + "st_page_out", statp->st_page_out); + set_int_field(jnienv, dbclass, retval, + "st_ro_evict", statp->st_ro_evict); + set_int_field(jnienv, dbclass, retval, + "st_rw_evict", statp->st_rw_evict); + set_int_field(jnienv, dbclass, retval, + "st_hash_buckets", statp->st_hash_buckets); + set_int_field(jnienv, dbclass, retval, + "st_hash_searches", statp->st_hash_searches); + set_int_field(jnienv, dbclass, retval, + "st_hash_longest", statp->st_hash_longest); + set_int_field(jnienv, dbclass, retval, + "st_hash_examined", statp->st_hash_examined); + set_int_field(jnienv, dbclass, retval, + "st_page_clean", statp->st_page_clean); + set_int_field(jnienv, dbclass, retval, + "st_page_dirty", statp->st_page_dirty); + set_int_field(jnienv, dbclass, retval, + "st_page_trickle", statp->st_page_trickle); + set_int_field(jnienv, dbclass, retval, + "st_region_wait", statp->st_region_wait); + set_int_field(jnienv, dbclass, retval, + "st_region_nowait", statp->st_region_nowait); + set_int_field(jnienv, dbclass, retval, + "st_regsize", statp->st_regsize); + + free(statp); + } + JAVADB_ENV_API_END(dbenv); + return (retval); +} + +JNIEXPORT jobjectArray JNICALL Java_com_sleepycat_db_DbEnv_memp_1fstat + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis) +{ + int err, i, len; + jclass fstat_class; + DB_ENV *dbenv; + DB_MPOOL_FSTAT **fstatp; + jobjectArray retval; + jfieldID filename_id; + jstring jfilename; + + fstatp = NULL; + retval = NULL; + dbenv = get_DB_ENV(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv)) + return (NULL); + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + /* We cannot use the default allocator (on Win* platforms anyway) + * because it often causes problems when we free storage + * in a DLL that was allocated in another DLL. Using + * our own allocator (ours just calls malloc!) ensures + * that there is no mismatch. + */ + err = memp_stat(dbenv, 0, &fstatp, NULL); + if (verify_return(jnienv, err, 0)) { + len = 0; + while (fstatp[len]) + len++; + fstat_class = get_class(jnienv, name_DB_MPOOL_FSTAT); + retval = (*jnienv)->NewObjectArray(jnienv, len, + fstat_class, 0); + for (i=0; i<len; i++) { + jobject obj = create_default_object(jnienv, + name_DB_MPOOL_FSTAT); + (*jnienv)->SetObjectArrayElement(jnienv, retval, + i, obj); + + /* Set the string field. */ + filename_id = + (*jnienv)->GetFieldID(jnienv, fstat_class, + "file_name", + string_signature); + jfilename = + get_java_string(jnienv, fstatp[i]->file_name); + (*jnienv)->SetObjectField(jnienv, obj, + filename_id, jfilename); + + set_int_field(jnienv, fstat_class, obj, + "st_pagesize", fstatp[i]->st_pagesize); + set_int_field(jnienv, fstat_class, obj, + "st_cache_hit", fstatp[i]->st_cache_hit); + set_int_field(jnienv, fstat_class, obj, + "st_cache_miss", fstatp[i]->st_cache_miss); + set_int_field(jnienv, fstat_class, obj, + "st_map", fstatp[i]->st_map); + set_int_field(jnienv, fstat_class, obj, + "st_page_create", fstatp[i]->st_page_create); + set_int_field(jnienv, fstat_class, obj, + "st_page_in", fstatp[i]->st_page_in); + set_int_field(jnienv, fstat_class, obj, + "st_page_out", fstatp[i]->st_page_out); + free(fstatp[i]); + } + free(fstatp); + } + JAVADB_ENV_API_END(dbenv); + return (retval); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_memp_1trickle + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint pct) +{ + int err; + DB_ENV *dbenv = get_DB_ENV(jnienv, jthis); + int result = 0; + + if (verify_non_null(jnienv, dbenv)) { + JAVADB_ENV_API_BEGIN(dbenv, jthis); + err = memp_trickle(dbenv, pct, &result); + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); + } + return (result); +} + +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_txn_1begin + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbTxn*/ jobject pid, jint flags) +{ + int err; + DB_TXN *dbpid, *result; + DB_ENV *dbenv; + + dbenv = get_DB_ENV(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv)) + return (0); + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + dbpid = get_DB_TXN(jnienv, pid); + result = 0; + + err = txn_begin(dbenv, dbpid, &result, flags); + if (!verify_return(jnienv, err, 0)) + return (0); + JAVADB_ENV_API_END(dbenv); + return (get_DbTxn(jnienv, result)); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbEnv_txn_1checkpoint + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jint kbyte, jint min, jint flags) +{ + int err; + DB_ENV *dbenv = get_DB_ENV(jnienv, jthis); + + if (!verify_non_null(jnienv, dbenv)) + return (0); + JAVADB_ENV_API_BEGIN(dbenv, jthis); + err = txn_checkpoint(dbenv, kbyte, min, flags); + if (err != DB_INCOMPLETE) + verify_return(jnienv, err, 0); + JAVADB_ENV_API_END(dbenv); + return (err); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv_tx_1recover_1changed + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, /*DbFeedback*/ jobject jtxrecover) +{ + DB_ENV *dbenv; + DB_ENV_JAVAINFO *dbenvinfo; + + dbenv = get_DB_ENV(jnienv, jthis); + dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv) || + !verify_non_null(jnienv, dbenvinfo)) + return; + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + dbjie_set_tx_recover_object(dbenvinfo, jnienv, dbenv, jtxrecover); + JAVADB_ENV_API_END(dbenv); +} + +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_DbEnv_txn_1stat + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis) +{ + int err; + DB_ENV *dbenv; + DB_TXN_STAT *statp; + jobject retval, obj; + jclass dbclass, active_class; + char active_signature[512]; + jfieldID arrid; + jobjectArray actives; + unsigned int i; + + retval = NULL; + statp = NULL; + dbenv = get_DB_ENV(jnienv, jthis); + if (!verify_non_null(jnienv, dbenv)) + return (NULL); + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + + /* We cannot use the default allocator (on Win* platforms anyway) + * because it often causes problems when we free storage + * in a DLL that was allocated in another DLL. Using + * our own allocator (ours just calls malloc!) ensures + * that there is no mismatch. + */ + err = txn_stat(dbenv, &statp, NULL); + if (verify_return(jnienv, err, 0)) { + retval = create_default_object(jnienv, name_DB_TXN_STAT); + dbclass = get_class(jnienv, name_DB_TXN_STAT); + + /* Set the individual fields */ + + set_lsn_field(jnienv, dbclass, retval, + "st_last_ckp", statp->st_last_ckp); + set_lsn_field(jnienv, dbclass, retval, + "st_pending_ckp", statp->st_pending_ckp); + set_long_field(jnienv, dbclass, retval, + "st_time_ckp", statp->st_time_ckp); + set_int_field(jnienv, dbclass, retval, + "st_last_txnid", statp->st_last_txnid); + set_int_field(jnienv, dbclass, retval, + "st_maxtxns", statp->st_maxtxns); + set_int_field(jnienv, dbclass, retval, + "st_naborts", statp->st_naborts); + set_int_field(jnienv, dbclass, retval, + "st_nbegins", statp->st_nbegins); + set_int_field(jnienv, dbclass, retval, + "st_ncommits", statp->st_ncommits); + set_int_field(jnienv, dbclass, retval, + "st_nactive", statp->st_nactive); + set_int_field(jnienv, dbclass, retval, + "st_maxnactive", statp->st_maxnactive); + + active_class = get_class(jnienv, name_DB_TXN_STAT_ACTIVE); + actives = + (*jnienv)->NewObjectArray(jnienv, statp->st_nactive, + active_class, 0); + + /* Set the st_txnarray field. This is a little more involved + * than other fields, since the type is an array, so none + * of our utility functions help. + */ + strncpy(active_signature, "[L", sizeof(active_signature)); + strncat(active_signature, DB_PACKAGE_NAME, + sizeof(active_signature)); + strncat(active_signature, name_DB_TXN_STAT_ACTIVE, + sizeof(active_signature)); + strncat(active_signature, ";", sizeof(active_signature)); + + arrid = (*jnienv)->GetFieldID(jnienv, dbclass, "st_txnarray", + active_signature); + (*jnienv)->SetObjectField(jnienv, retval, arrid, actives); + + /* Now fill the in the elements of st_txnarray. */ + for (i=0; i<statp->st_nactive; i++) { + obj = create_default_object(jnienv, name_DB_TXN_STAT_ACTIVE); + (*jnienv)->SetObjectArrayElement(jnienv, actives, i, obj); + + set_int_field(jnienv, active_class, obj, + "txnid", statp->st_txnarray[i].txnid); + set_int_field(jnienv, active_class, obj, + "parentid", statp->st_txnarray[i].parentid); + set_lsn_field(jnienv, active_class, obj, + "lsn", statp->st_txnarray[i].lsn); + } + set_int_field(jnienv, dbclass, retval, + "st_region_wait", statp->st_region_wait); + set_int_field(jnienv, dbclass, retval, + "st_region_nowait", statp->st_region_nowait); + set_int_field(jnienv, dbclass, retval, + "st_regsize", statp->st_regsize); + + free(statp); + } + JAVADB_ENV_API_END(dbenv); + return (retval); +} + +/* See discussion on errpfx, errcall in DB_ENV_JAVAINFO */ +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1set_1errcall + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jobject errcall) +{ + DB_ENV *dbenv; + DB_ENV_JAVAINFO *dbenvinfo; + + dbenv = get_DB_ENV(jnienv, jthis); + dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis); + + if (verify_non_null(jnienv, dbenv) && + verify_non_null(jnienv, dbenvinfo)) { + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + dbjie_set_errcall(dbenvinfo, jnienv, errcall); + JAVADB_ENV_API_END(dbenv); + } +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1set_1errpfx + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, jstring str) +{ + DB_ENV *dbenv; + DB_ENV_JAVAINFO *dbenvinfo; + + dbenv = get_DB_ENV(jnienv, jthis); + dbenvinfo = get_DB_ENV_JAVAINFO(jnienv, jthis); + + if (verify_non_null(jnienv, dbenv) && + verify_non_null(jnienv, dbenvinfo)) { + + JAVADB_ENV_API_BEGIN(dbenv, jthis); + dbjie_set_errpfx(dbenvinfo, jnienv, str); + JAVADB_ENV_API_END(dbenv); + } +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbEnv__1finalize + (JNIEnv *jnienv, /*DbEnv*/ jobject jthis, + jobject /*DbErrcall*/ errcall, jstring errpfx) +{ + DB_ENV *dbenv; + DB_ENV_JAVAINFO *envinfo; + + dbenv = get_DB_ENV(jnienv, jthis); + envinfo = get_DB_ENV_JAVAINFO(jnienv, jthis); + DB_ASSERT(envinfo != NULL); + + /* Note: We detect unclosed DbEnvs and report it. + */ + if (dbenv != NULL && envinfo != NULL && !dbjie_is_dbopen(envinfo)) { + + /* If this error occurs, this object was never closed. */ + report_errcall(jnienv, errcall, errpfx, + "DbEnv.finalize: open DbEnv object destroyed"); + } + + /* Shouldn't see this object again, but just in case */ + set_private_dbobj(jnienv, name_DB_ENV, jthis, 0); + set_private_info(jnienv, name_DB_ENV, jthis, 0); + + dbjie_destroy(envinfo, jnienv); +} diff --git a/bdb/libdb_java/java_DbLock.c b/bdb/libdb_java/java_DbLock.c new file mode 100644 index 00000000000..287ca6622e5 --- /dev/null +++ b/bdb/libdb_java/java_DbLock.c @@ -0,0 +1,55 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 1998, 1999, 2000 + * Sleepycat Software. All rights reserved. + */ +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: java_DbLock.c,v 11.4 2000/11/30 00:58:39 ubell Exp $"; +#endif /* not lint */ + +#include <jni.h> +#include <stdlib.h> +#include <string.h> + +#include "db.h" +#include "java_util.h" +#include "com_sleepycat_db_DbLock.h" + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLock_put + (JNIEnv *jnienv, jobject jthis, /*DbEnv*/ jobject env) +{ + int err; + DB_LOCK *dblock = get_DB_LOCK(jnienv, jthis); + DB_ENV *dbenv = get_DB_ENV(jnienv, env); + + if (!verify_non_null(jnienv, dbenv)) + return; + + if (!verify_non_null(jnienv, dblock)) + return; + + err = lock_put(dbenv, dblock); + if (verify_return(jnienv, err, 0)) { + /* After a successful put, the DbLock can no longer + * be used, so we release the storage related to it + * (allocated in DbEnv.lock_get() or lock_tget()). + */ + free(dblock); + + set_private_dbobj(jnienv, name_DB_LOCK, jthis, 0); + } +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLock_finalize + (JNIEnv *jnienv, jobject jthis) +{ + DB_LOCK *dblock = get_DB_LOCK(jnienv, jthis); + if (dblock) { + /* Free any data related to DB_LOCK here */ + free(dblock); + } + set_private_dbobj(jnienv, name_DB_LOCK, jthis, 0); /* paranoia */ +} diff --git a/bdb/libdb_java/java_DbLsn.c b/bdb/libdb_java/java_DbLsn.c new file mode 100644 index 00000000000..8f26f2ecb58 --- /dev/null +++ b/bdb/libdb_java/java_DbLsn.c @@ -0,0 +1,43 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 1998, 1999, 2000 + * Sleepycat Software. All rights reserved. + */ +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: java_DbLsn.c,v 11.5 2000/11/30 00:58:39 ubell Exp $"; +#endif /* not lint */ + +#include <jni.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> /* needed for FILENAME_MAX */ + +#include "db.h" +#include "db_int.h" +#include "java_util.h" +#include "com_sleepycat_db_DbLsn.h" + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLsn_init_1lsn + (JNIEnv *jnienv, /*DbLsn*/ jobject jthis) +{ + /* Note: the DB_LSN object stored in the private_dbobj_ + * is allocated in get_DbLsn(). + */ + + COMPQUIET(jnienv, NULL); + COMPQUIET(jthis, NULL); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbLsn_finalize + (JNIEnv *jnienv, jobject jthis) +{ + DB_LSN *dblsn; + + dblsn = get_DB_LSN(jnienv, jthis); + if (dblsn) { + free(dblsn); + } +} diff --git a/bdb/libdb_java/java_DbTxn.c b/bdb/libdb_java/java_DbTxn.c new file mode 100644 index 00000000000..67c2599a6fc --- /dev/null +++ b/bdb/libdb_java/java_DbTxn.c @@ -0,0 +1,82 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 1998, 1999, 2000 + * Sleepycat Software. All rights reserved. + */ +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: java_DbTxn.c,v 11.3 2000/09/18 18:32:25 dda Exp $"; +#endif /* not lint */ + +#include <jni.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "db.h" +#include "java_util.h" +#include "com_sleepycat_db_DbTxn.h" + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_abort + (JNIEnv *jnienv, jobject jthis) +{ + int err; + DB_TXN *dbtxn = get_DB_TXN(jnienv, jthis); + if (!verify_non_null(jnienv, dbtxn)) + return; + + err = txn_abort(dbtxn); + verify_return(jnienv, err, 0); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_commit + (JNIEnv *jnienv, jobject jthis, jint flags) +{ + int err; + DB_TXN *dbtxn = get_DB_TXN(jnienv, jthis); + if (!verify_non_null(jnienv, dbtxn)) + return; + + err = txn_commit(dbtxn, flags); + verify_return(jnienv, err, 0); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_DbTxn_id + (JNIEnv *jnienv, jobject jthis) +{ + int retval = 0; + DB_TXN *dbtxn = get_DB_TXN(jnienv, jthis); + if (!verify_non_null(jnienv, dbtxn)) + return (-1); + + /* No error to check for from txn_id */ + retval = txn_id(dbtxn); + return (retval); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_prepare + (JNIEnv *jnienv, jobject jthis) +{ + int err; + DB_TXN *dbtxn = get_DB_TXN(jnienv, jthis); + if (!verify_non_null(jnienv, dbtxn)) + return; + + err = txn_prepare(dbtxn); + verify_return(jnienv, err, 0); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_DbTxn_finalize + (JNIEnv *jnienv, jobject jthis) +{ + DB_TXN *dbtxn = get_DB_TXN(jnienv, jthis); + if (dbtxn) { + /* Free any data related to DB_TXN here + * Note: we don't make a policy of doing + * a commit or abort here. The txnmgr + * should be closed, and DB will clean up. + */ + } +} diff --git a/bdb/libdb_java/java_Dbc.c b/bdb/libdb_java/java_Dbc.c new file mode 100644 index 00000000000..f1d0acdec85 --- /dev/null +++ b/bdb/libdb_java/java_Dbc.c @@ -0,0 +1,196 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 1998, 1999, 2000 + * Sleepycat Software. All rights reserved. + */ +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: java_Dbc.c,v 11.10 2000/10/25 19:54:55 dda Exp $"; +#endif /* not lint */ + +#include <jni.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#ifdef DIAGNOSTIC +#include <stdio.h> +#endif + +#include "db.h" +#include "db_int.h" +#include "java_util.h" +#include "com_sleepycat_db_Dbc.h" + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbc_close + (JNIEnv *jnienv, jobject jthis) +{ + int err; + DBC *dbc = get_DBC(jnienv, jthis); + + if (!verify_non_null(jnienv, dbc)) + return; + err = dbc->c_close(dbc); + if (verify_return(jnienv, err, 0)) { + set_private_dbobj(jnienv, name_DBC, jthis, 0); + } +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_count + (JNIEnv *jnienv, jobject jthis, jint flags) +{ + int err; + DBC *dbc = get_DBC(jnienv, jthis); + db_recno_t count; + + if (!verify_non_null(jnienv, dbc)) + return (0); + err = dbc->c_count(dbc, &count, flags); + verify_return(jnienv, err, 0); + return (count); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_del + (JNIEnv *jnienv, jobject jthis, jint flags) +{ + int err; + DBC *dbc = get_DBC(jnienv, jthis); + + if (!verify_non_null(jnienv, dbc)) + return (0); + err = dbc->c_del(dbc, flags); + if (err != DB_KEYEMPTY) { + verify_return(jnienv, err, 0); + } + return (err); +} + +JNIEXPORT jobject JNICALL Java_com_sleepycat_db_Dbc_dup + (JNIEnv *jnienv, jobject jthis, jint flags) +{ + int err; + DBC *dbc = get_DBC(jnienv, jthis); + DBC *dbc_ret = NULL; + + if (!verify_non_null(jnienv, dbc)) + return (0); + err = dbc->c_dup(dbc, &dbc_ret, flags); + if (!verify_return(jnienv, err, 0)) + return (0); + + return (get_Dbc(jnienv, dbc_ret)); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_get + (JNIEnv *jnienv, jobject jthis, + /*Dbt*/ jobject key, /*Dbt*/ jobject data, jint flags) +{ + int err, retry, op_flags; + DBC *dbc; + JDBT dbkey, dbdata; + OpKind keyop, dataop; + + /* Depending on flags, the user may be supplying the key, + * or else we may have to retrieve it. + */ + err = 0; + keyop = outOp; + dataop = outOp; + + op_flags = flags & DB_OPFLAGS_MASK; + if (op_flags == DB_SET) { + keyop = inOp; + } + else if (op_flags == DB_SET_RANGE || + op_flags == DB_SET_RECNO) { + keyop = inOutOp; + } + else if (op_flags == DB_GET_BOTH) { + keyop = inOutOp; + dataop = inOutOp; + } + + dbc = get_DBC(jnienv, jthis); + if (jdbt_lock(&dbkey, jnienv, key, keyop) != 0) + goto out2; + if (jdbt_lock(&dbdata, jnienv, data, dataop) != 0) + goto out1; + + if (!verify_non_null(jnienv, dbc)) + goto out1; + + for (retry = 0; retry < 3; retry++) { + err = dbc->c_get(dbc, &dbkey.dbt->dbt, &dbdata.dbt->dbt, flags); + + /* If we failed due to lack of memory in our DBT arrays, + * retry. + */ + if (err != ENOMEM) + break; + if (!jdbt_realloc(&dbkey, jnienv) && !jdbt_realloc(&dbdata, jnienv)) + break; + } + if (err != DB_NOTFOUND) { + verify_return(jnienv, err, 0); + } + out1: + jdbt_unlock(&dbdata, jnienv); + out2: + jdbt_unlock(&dbkey, jnienv); + return (err); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbc_put + (JNIEnv *jnienv, jobject jthis, + /*Dbt*/ jobject key, /*Dbt*/ jobject data, jint flags) +{ + int err; + DBC *dbc; + JDBT dbkey, dbdata; + + err = 0; + dbc = get_DBC(jnienv, jthis); + if (jdbt_lock(&dbkey, jnienv, key, inOp) != 0) + goto out2; + if (jdbt_lock(&dbdata, jnienv, data, inOp) != 0) + goto out1; + + if (!verify_non_null(jnienv, dbc)) + goto out1; + err = dbc->c_put(dbc, &dbkey.dbt->dbt, &dbdata.dbt->dbt, flags); + if (err != DB_KEYEXIST) { + verify_return(jnienv, err, 0); + } + out1: + jdbt_unlock(&dbdata, jnienv); + out2: + jdbt_unlock(&dbkey, jnienv); + return (err); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbc_finalize + (JNIEnv *jnienv, jobject jthis) +{ + /* Free any data related to DBC here. + * If we ever have java-only data embedded in the DBC + * and need to do this, we'll have to track Dbc's + * according to which Db owns them, just as + * we track Db's according to which DbEnv owns them. + * That's necessary to avoid double freeing that + * comes about when closes interact with GC. + */ + +#ifdef DIAGNOSTIC + DBC *dbc; + + dbc = get_DBC(jnienv, jthis); + if (dbc != NULL) + fprintf(stderr, "Java API: Dbc has not been closed\n"); +#else + + COMPQUIET(jnienv, NULL); + COMPQUIET(jthis, NULL); + +#endif +} diff --git a/bdb/libdb_java/java_Dbt.c b/bdb/libdb_java/java_Dbt.c new file mode 100644 index 00000000000..0e094da6a2d --- /dev/null +++ b/bdb/libdb_java/java_Dbt.c @@ -0,0 +1,176 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 1998, 1999, 2000 + * Sleepycat Software. All rights reserved. + */ +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: java_Dbt.c,v 11.10 2000/10/25 19:54:55 dda Exp $"; +#endif /* not lint */ + +#include <jni.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "db.h" +#include "java_util.h" +#include "com_sleepycat_db_Dbt.h" + +JAVADB_RW_ACCESS(Dbt, jint, size, DBT, size) +JAVADB_RW_ACCESS(Dbt, jint, ulen, DBT, ulen) +JAVADB_RW_ACCESS(Dbt, jint, dlen, DBT, dlen) +JAVADB_RW_ACCESS(Dbt, jint, doff, DBT, doff) +JAVADB_RW_ACCESS(Dbt, jint, flags, DBT, flags) + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_init + (JNIEnv *jnienv, jobject jthis) +{ + DBT_JAVAINFO *dbtji; + + dbtji = dbjit_construct(); + set_private_dbobj(jnienv, name_DBT, jthis, dbtji); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_internal_1set_1data + (JNIEnv *jnienv, jobject jthis, jbyteArray array) +{ + DBT_JAVAINFO *db_this; + + db_this = get_DBT_JAVAINFO(jnienv, jthis); + if (verify_non_null(jnienv, db_this)) { + + /* If we previously allocated an array for java, + * must release reference. + */ + dbjit_release(db_this, jnienv); + + /* Make the array a global ref, + * it won't be GC'd till we release it. + */ + if (array) + array = (jbyteArray)NEW_GLOBAL_REF(jnienv, array); + db_this->array_ = array; + } +} + +JNIEXPORT jbyteArray JNICALL Java_com_sleepycat_db_Dbt_get_1data + (JNIEnv *jnienv, jobject jthis) +{ + DBT_JAVAINFO *db_this; + jbyteArray arr; + int len; + + db_this = get_DBT_JAVAINFO(jnienv, jthis); + if (verify_non_null(jnienv, db_this)) { + /* XXX this will copy the data on each call to get_data, + * even if it is unchanged. + */ + if (db_this->create_array_ != 0) { + /* XXX we should reuse the existing array if we can */ + len = db_this->dbt.size; + if (db_this->array_ != NULL) + DELETE_GLOBAL_REF(jnienv, db_this->array_); + arr = (*jnienv)->NewByteArray(jnienv, len); + db_this->array_ = + (jbyteArray)NEW_GLOBAL_REF(jnienv, arr); + (*jnienv)->SetByteArrayRegion(jnienv, arr, 0, len, + db_this->dbt.data); + } + return (db_this->array_); + } + return (0); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1offset + (JNIEnv *jnienv, jobject jthis, jint offset) +{ + DBT_JAVAINFO *db_this; + + db_this = get_DBT_JAVAINFO(jnienv, jthis); + if (verify_non_null(jnienv, db_this)) { + db_this->offset_ = offset; + } +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1offset + (JNIEnv *jnienv, jobject jthis) +{ + DBT_JAVAINFO *db_this; + + db_this = get_DBT_JAVAINFO(jnienv, jthis); + if (verify_non_null(jnienv, db_this)) { + return db_this->offset_; + } + return (0); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_set_1recno_1key_1data(JNIEnv *jnienv, jobject jthis, jint value) +{ + JDBT jdbt; + + if (jdbt_lock(&jdbt, jnienv, jthis, inOp) != 0) + goto out; + + if (!jdbt.dbt->dbt.data || + jdbt.java_array_len_ < sizeof(db_recno_t)) { + char buf[200]; + sprintf(buf, "set_recno_key_data error: %p %p %d %d", + &jdbt.dbt->dbt, jdbt.dbt->dbt.data, + jdbt.dbt->dbt.ulen, sizeof(db_recno_t)); + report_exception(jnienv, buf, 0, 0); + } + else { + *(db_recno_t*)(jdbt.dbt->dbt.data) = value; + } + out: + jdbt_unlock(&jdbt, jnienv); +} + +JNIEXPORT jint JNICALL Java_com_sleepycat_db_Dbt_get_1recno_1key_1data(JNIEnv *jnienv, jobject jthis) +{ + jint ret; + JDBT jdbt; + + ret = 0; + + /* Although this is kind of like "retrieve", we don't support + * DB_DBT_MALLOC for this operation, so we tell jdbt_lock + * that is not a retrieve. + */ + if (jdbt_lock(&jdbt, jnienv, jthis, inOp) != 0) + goto out; + + if (!jdbt.dbt->dbt.data || + jdbt.java_array_len_ < sizeof(db_recno_t)) { + char buf[200]; + sprintf(buf, "get_recno_key_data error: %p %p %d %d", + &jdbt.dbt->dbt, jdbt.dbt->dbt.data, + jdbt.dbt->dbt.ulen, sizeof(db_recno_t)); + report_exception(jnienv, buf, 0, 0); + } + else { + ret = *(db_recno_t*)(jdbt.dbt->dbt.data); + } + out: + jdbt_unlock(&jdbt, jnienv); + return (ret); +} + +JNIEXPORT void JNICALL Java_com_sleepycat_db_Dbt_finalize + (JNIEnv *jnienv, jobject jthis) +{ + DBT_JAVAINFO *dbtji; + + dbtji = get_DBT_JAVAINFO(jnienv, jthis); + if (dbtji) { + /* Free any data related to DBT here */ + dbjit_release(dbtji, jnienv); + + /* Extra paranoia */ + memset(dbtji, 0, sizeof(DBT_JAVAINFO)); + free(dbtji); + } +} diff --git a/bdb/libdb_java/java_info.c b/bdb/libdb_java/java_info.c new file mode 100644 index 00000000000..ccd469fa256 --- /dev/null +++ b/bdb/libdb_java/java_info.c @@ -0,0 +1,1001 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 1998, 1999, 2000 + * Sleepycat Software. All rights reserved. + */ +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: java_info.c,v 11.18 2000/10/28 13:09:39 dda Exp $"; +#endif /* not lint */ + +#include <jni.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "db.h" +#include "db_int.h" +#include "java_util.h" + +/**************************************************************** + * + * Callback functions + * + */ + +static void Db_feedback_callback(DB *db, int opcode, int percent) +{ + DB_JAVAINFO *dbinfo; + + DB_ASSERT(db != NULL); + dbinfo = (DB_JAVAINFO *)db->cj_internal; + dbji_call_feedback(dbinfo, db, dbinfo->jdbref_, opcode, percent); +} + +static int Db_append_recno_callback(DB *db, DBT *dbt, db_recno_t recno) +{ + DB_JAVAINFO *dbinfo; + + dbinfo = (DB_JAVAINFO *)db->cj_internal; + return (dbji_call_append_recno(dbinfo, db, dbinfo->jdbref_, dbt, recno)); +} + +static int Db_bt_compare_callback(DB *db, const DBT *dbt1, const DBT *dbt2) +{ + DB_JAVAINFO *dbinfo; + + dbinfo = (DB_JAVAINFO *)db->cj_internal; + return (dbji_call_bt_compare(dbinfo, db, dbinfo->jdbref_, dbt1, dbt2)); +} + +static size_t Db_bt_prefix_callback(DB *db, const DBT *dbt1, const DBT *dbt2) +{ + DB_JAVAINFO *dbinfo; + + dbinfo = (DB_JAVAINFO *)db->cj_internal; + return (dbji_call_bt_prefix(dbinfo, db, dbinfo->jdbref_, dbt1, dbt2)); +} + +static int Db_dup_compare_callback(DB *db, const DBT *dbt1, const DBT *dbt2) +{ + DB_JAVAINFO *dbinfo; + + dbinfo = (DB_JAVAINFO *)db->cj_internal; + return (dbji_call_dup_compare(dbinfo, db, dbinfo->jdbref_, dbt1, dbt2)); +} + +static u_int32_t Db_h_hash_callback(DB *db, const void *data, u_int32_t len) +{ + DB_JAVAINFO *dbinfo; + + dbinfo = (DB_JAVAINFO *)db->cj_internal; + return (dbji_call_h_hash(dbinfo, db, dbinfo->jdbref_, data, len)); +} + +static void DbEnv_feedback_callback(DB_ENV *dbenv, int opcode, int percent) +{ + DB_ENV_JAVAINFO *dbinfo; + + DB_ASSERT(dbenv != NULL); + dbinfo = (DB_ENV_JAVAINFO *)dbenv->cj_internal; + dbjie_call_feedback(dbinfo, dbenv, dbinfo->jenvref_, opcode, percent); +} + +static int DbEnv_recovery_init_callback(DB_ENV *dbenv) +{ + DB_ENV_JAVAINFO *dbinfo; + + dbinfo = (DB_ENV_JAVAINFO *)dbenv->cj_internal; + return (dbjie_call_recovery_init(dbinfo, dbenv, dbinfo->jenvref_)); +} + +static int DbEnv_tx_recover_callback(DB_ENV *dbenv, DBT *dbt, + DB_LSN *lsn, db_recops recops) +{ + DB_ENV_JAVAINFO *dbinfo; + + DB_ASSERT(dbenv != NULL); + dbinfo = (DB_ENV_JAVAINFO *)dbenv->cj_internal; + return dbjie_call_tx_recover(dbinfo, dbenv, dbinfo->jenvref_, dbt, + lsn, recops); +} + +/**************************************************************** + * + * Implementation of class DBT_javainfo + * + */ +DBT_JAVAINFO * +dbjit_construct() +{ + DBT_JAVAINFO *dbjit; + + dbjit = (DBT_JAVAINFO *)malloc(sizeof(DBT_JAVAINFO)); + memset(dbjit, 0, sizeof(DBT_JAVAINFO)); + return (dbjit); +} + +void dbjit_destroy(DBT_JAVAINFO *dbjit) +{ + /* Sanity check: + * We cannot delete the global ref because we don't have a JNIEnv. + */ + if (dbjit->array_ != NULL) { + fprintf(stderr, "object is not freed\n"); + } + + /* Extra paranoia */ + memset(dbjit, 0, sizeof(DB_JAVAINFO)); + free(dbjit); +} + +void dbjit_release(DBT_JAVAINFO *dbjit, JNIEnv *jnienv) +{ + if (dbjit->array_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbjit->array_); + dbjit->array_ = NULL; + } +} + +/**************************************************************** + * + * Implementation of class DB_ENV_JAVAINFO + * + */ + +/* create/initialize an object */ +DB_ENV_JAVAINFO * +dbjie_construct(JNIEnv *jnienv, + jobject default_errcall, + int is_dbopen) +{ + DB_ENV_JAVAINFO *dbjie; + + dbjie = (DB_ENV_JAVAINFO *)malloc(sizeof(DB_ENV_JAVAINFO)); + memset(dbjie, 0, sizeof(DB_ENV_JAVAINFO)); + dbjie->is_dbopen_ = is_dbopen; + + if ((*jnienv)->GetJavaVM(jnienv, &dbjie->javavm_) != 0) { + free(dbjie); + report_exception(jnienv, "cannot get Java VM", 0, 0); + return (NULL); + } + + /* The default error call just prints to the 'System.err' + * stream. If the user does set_errcall to null, we'll + * want to have a reference to set it back to. + * + * Why do we have always set db_errcall to our own callback? + * Because it makes the interaction between setting the + * error prefix, error stream, and user's error callback + * that much easier. + */ + dbjie->default_errcall_ = NEW_GLOBAL_REF(jnienv, default_errcall); + dbjie->errcall_ = NEW_GLOBAL_REF(jnienv, default_errcall); + return (dbjie); +} + +/* release all objects held by this this one */ +void dbjie_dealloc(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv) +{ + if (dbjie->recovery_init_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbjie->recovery_init_); + dbjie->recovery_init_ = NULL; + } + if (dbjie->feedback_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbjie->feedback_); + dbjie->feedback_ = NULL; + } + if (dbjie->tx_recover_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbjie->tx_recover_); + dbjie->tx_recover_ = NULL; + } + if (dbjie->errcall_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbjie->errcall_); + dbjie->errcall_ = NULL; + } + if (dbjie->default_errcall_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbjie->default_errcall_); + dbjie->default_errcall_ = NULL; + } + + if (dbjie->conflict_ != NULL) { + free(dbjie->conflict_); + dbjie->conflict_ = NULL; + } + if (dbjie->errpfx_ != NULL) { + free(dbjie->errpfx_); + dbjie->errpfx_ = NULL; + } +} + +/* free this object, releasing anything allocated on its behalf */ +void dbjie_destroy(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv) +{ + dbjie_dealloc(dbjie, jnienv); + + /* Extra paranoia */ + memset(dbjie, 0, sizeof(DB_ENV_JAVAINFO)); + free(dbjie); +} + +/* Attach to the current thread that is running and + * return that. We use the java virtual machine + * that we saved in the constructor. + */ +JNIEnv * +dbjie_get_jnienv(DB_ENV_JAVAINFO *dbjie) +{ + /* Note: + * Different versions of the JNI disagree on the signature + * for AttachCurrentThread. The most recent documentation + * seems to say that (JNIEnv **) is correct, but newer + * JNIs seem to use (void **), oddly enough. + */ +#ifdef JNI_VERSION_1_2 + void *attachret = 0; +#else + JNIEnv *attachret = 0; +#endif + + /* This should always succeed, as we are called via + * some Java activity. I think therefore I am (a thread). + */ + if ((*dbjie->javavm_)->AttachCurrentThread(dbjie->javavm_, &attachret, 0) != 0) + return (0); + + return ((JNIEnv *)attachret); +} + +jstring +dbjie_get_errpfx(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv) +{ + return (get_java_string(jnienv, dbjie->errpfx_)); +} + +void +dbjie_set_errcall(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv, jobject new_errcall) +{ + /* If the new_errcall is null, we'll set the error call + * to the default one. + */ + if (new_errcall == NULL) + new_errcall = dbjie->default_errcall_; + + DELETE_GLOBAL_REF(jnienv, dbjie->errcall_); + dbjie->errcall_ = NEW_GLOBAL_REF(jnienv, new_errcall); +} + +void +dbjie_set_errpfx(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv, jstring errpfx) +{ + if (dbjie->errpfx_ != NULL) + free(dbjie->errpfx_); + + if (errpfx) + dbjie->errpfx_ = get_c_string(jnienv, errpfx); + else + dbjie->errpfx_ = NULL; +} + +void +dbjie_set_conflict(DB_ENV_JAVAINFO *dbjie, unsigned char *newarr) +{ + if (dbjie->conflict_) + free(dbjie->conflict_); + dbjie->conflict_ = newarr; +} + +void dbjie_set_feedback_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv, + DB_ENV *dbenv, jobject jfeedback) +{ + int err; + + if (dbjie->feedback_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbjie->feedback_); + } + if (jfeedback == NULL) { + if ((err = dbenv->set_feedback(dbenv, NULL)) != 0) + report_exception(jnienv, "set_feedback failed", + err, 0); + } + else { + if ((err = dbenv->set_feedback(dbenv, + DbEnv_feedback_callback)) != 0) + report_exception(jnienv, "set_feedback failed", + err, 0); + } + + dbjie->feedback_ = NEW_GLOBAL_REF(jnienv, jfeedback); +} + +void dbjie_call_feedback(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv, jobject jenv, + int opcode, int percent) +{ + JNIEnv *jnienv; + jclass feedback_class; + jmethodID id; + + COMPQUIET(dbenv, NULL); + jnienv = dbjie_get_jnienv(dbjie); + if (jnienv == NULL) { + fprintf(stderr, "Cannot attach to current thread!\n"); + return; + } + + feedback_class = get_class(jnienv, name_DbEnvFeedback); + id = (*jnienv)->GetMethodID(jnienv, feedback_class, + "feedback", + "(Lcom/sleepycat/db/DbEnv;II)V"); + if (!id) { + fprintf(stderr, "Cannot find callback class\n"); + return; + } + + (*jnienv)->CallVoidMethod(jnienv, dbjie->feedback_, id, + jenv, (jint)opcode, (jint)percent); +} + +void dbjie_set_recovery_init_object(DB_ENV_JAVAINFO *dbjie, + JNIEnv *jnienv, DB_ENV *dbenv, + jobject jrecovery_init) +{ + int err; + + if (dbjie->recovery_init_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbjie->recovery_init_); + } + if (jrecovery_init == NULL) { + if ((err = dbenv->set_recovery_init(dbenv, NULL)) != 0) + report_exception(jnienv, "set_recovery_init failed", + err, 0); + } + else { + if ((err = dbenv->set_recovery_init(dbenv, + DbEnv_recovery_init_callback)) != 0) + report_exception(jnienv, "set_recovery_init failed", + err, 0); + } + + dbjie->recovery_init_ = NEW_GLOBAL_REF(jnienv, jrecovery_init); +} + +int dbjie_call_recovery_init(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv, + jobject jenv) +{ + JNIEnv *jnienv; + jclass recovery_init_class; + jmethodID id; + + COMPQUIET(dbenv, NULL); + jnienv = dbjie_get_jnienv(dbjie); + if (jnienv == NULL) { + fprintf(stderr, "Cannot attach to current thread!\n"); + return (EINVAL); + } + + recovery_init_class = get_class(jnienv, name_DbRecoveryInit); + id = (*jnienv)->GetMethodID(jnienv, recovery_init_class, + "recovery_init", + "(Lcom/sleepycat/db/DbEnv;)V"); + if (!id) { + fprintf(stderr, "Cannot find callback class\n"); + return (EINVAL); + } + return (*jnienv)->CallIntMethod(jnienv, dbjie->recovery_init_, + id, jenv); +} + +void dbjie_set_tx_recover_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv, + DB_ENV *dbenv, jobject jtx_recover) +{ + int err; + + if (dbjie->tx_recover_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbjie->tx_recover_); + } + if (jtx_recover == NULL) { + if ((err = dbenv->set_tx_recover(dbenv, NULL)) != 0) + report_exception(jnienv, "set_tx_recover failed", + err, 0); + } + else { + if ((err = dbenv->set_tx_recover(dbenv, + DbEnv_tx_recover_callback)) != 0) + report_exception(jnienv, "set_tx_recover failed", + err, 0); + } + + dbjie->tx_recover_ = NEW_GLOBAL_REF(jnienv, jtx_recover); +} + +int dbjie_call_tx_recover(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv, jobject jenv, + DBT *dbt, DB_LSN *lsn, int recops) +{ + JNIEnv *jnienv; + jclass tx_recover_class; + jmethodID id; + jobject jdbt; + jobject jlsn; + + COMPQUIET(dbenv, NULL); + jnienv = dbjie_get_jnienv(dbjie); + if (jnienv == NULL) { + fprintf(stderr, "Cannot attach to current thread!\n"); + return (0); + } + + tx_recover_class = get_class(jnienv, name_DbTxnRecover); + id = (*jnienv)->GetMethodID(jnienv, tx_recover_class, + "tx_recover", + "(Lcom/sleepycat/db/DbEnv;" + "Lcom/sleepycat/db/Dbt;" + "Lcom/sleepycat/db/DbLsn;" + "I)I"); + if (!id) { + fprintf(stderr, "Cannot find callback class\n"); + return (0); + } + + if (dbt == NULL) + jdbt = NULL; + else + jdbt = get_Dbt(jnienv, dbt); + + if (lsn == NULL) + jlsn = NULL; + else + jlsn = get_DbLsn(jnienv, *lsn); + + return (*jnienv)->CallIntMethod(jnienv, dbjie->tx_recover_, id, jenv, + jdbt, jlsn, recops); +} + +jobject dbjie_get_errcall(DB_ENV_JAVAINFO *dbjie) +{ + return (dbjie->errcall_); +} + +int dbjie_is_dbopen(DB_ENV_JAVAINFO *dbjie) +{ + return (dbjie->is_dbopen_); +} + +/**************************************************************** + * + * Implementation of class DB_JAVAINFO + * + */ + +DB_JAVAINFO *dbji_construct(JNIEnv *jnienv, jint flags) +{ + DB_JAVAINFO *dbji; + + dbji = (DB_JAVAINFO *)malloc(sizeof(DB_JAVAINFO)); + memset(dbji, 0, sizeof(DB_JAVAINFO)); + + if ((*jnienv)->GetJavaVM(jnienv, &dbji->javavm_) != 0) { + report_exception(jnienv, "cannot get Java VM", 0, 0); + free(dbji); + return (NULL); + } + dbji->construct_flags_ = flags; + return (dbji); +} + +void +dbji_dealloc(DB_JAVAINFO *dbji, JNIEnv *jnienv) +{ + if (dbji->append_recno_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbji->append_recno_); + dbji->append_recno_ = NULL; + } + if (dbji->bt_compare_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbji->bt_compare_); + dbji->bt_compare_ = NULL; + } + if (dbji->bt_prefix_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbji->bt_prefix_); + dbji->bt_prefix_ = NULL; + } + if (dbji->dup_compare_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbji->dup_compare_); + dbji->dup_compare_ = NULL; + } + if (dbji->feedback_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbji->feedback_); + dbji->feedback_ = NULL; + } + if (dbji->h_hash_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbji->h_hash_); + dbji->h_hash_ = NULL; + } +} + +void +dbji_destroy(DB_JAVAINFO *dbji, JNIEnv *jnienv) +{ + dbji_dealloc(dbji, jnienv); + free(dbji); +} + +JNIEnv *dbji_get_jnienv(DB_JAVAINFO *dbji) +{ + /* Note: + * Different versions of the JNI disagree on the signature + * for AttachCurrentThread. The most recent documentation + * seems to say that (JNIEnv **) is correct, but newer + * JNIs seem to use (void **), oddly enough. + */ +#ifdef JNI_VERSION_1_2 + void *attachret = 0; +#else + JNIEnv *attachret = 0; +#endif + + /* This should always succeed, as we are called via + * some Java activity. I think therefore I am (a thread). + */ + if ((*dbji->javavm_)->AttachCurrentThread(dbji->javavm_, &attachret, 0) != 0) + return (0); + + return ((JNIEnv *)attachret); +} + +jint dbji_get_flags(DB_JAVAINFO *dbji) +{ + return (dbji->construct_flags_); +} + +void dbji_set_feedback_object(DB_JAVAINFO *dbji, JNIEnv *jnienv, + DB *db, jobject jfeedback) +{ + jclass feedback_class; + + if (dbji->feedback_method_id_ == NULL) { + feedback_class = get_class(jnienv, name_DbFeedback); + dbji->feedback_method_id_ = + (*jnienv)->GetMethodID(jnienv, feedback_class, + "feedback", + "(Lcom/sleepycat/db/Db;II)V"); + if (dbji->feedback_method_id_ != NULL) { + /* XXX + * We should really have a better way + * to translate this to a Java exception class. + * In theory, it shouldn't happen. + */ + report_exception(jnienv, "Cannot find callback method", + EFAULT, 0); + return; + } + } + + if (dbji->feedback_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbji->feedback_); + } + if (jfeedback == NULL) { + db->set_feedback(db, NULL); + } + else { + db->set_feedback(db, Db_feedback_callback); + } + + dbji->feedback_ = NEW_GLOBAL_REF(jnienv, jfeedback); + +} + +void dbji_call_feedback(DB_JAVAINFO *dbji, DB *db, jobject jdb, + int opcode, int percent) +{ + JNIEnv *jnienv; + + COMPQUIET(db, NULL); + jnienv = dbji_get_jnienv(dbji); + if (jnienv == NULL) { + fprintf(stderr, "Cannot attach to current thread!\n"); + return; + } + + DB_ASSERT(dbji->feedback_method_id_ != NULL); + (*jnienv)->CallVoidMethod(jnienv, dbji->feedback_, + dbji->feedback_method_id_, + jdb, (jint)opcode, (jint)percent); +} + +void dbji_set_append_recno_object(DB_JAVAINFO *dbji, JNIEnv *jnienv, + DB *db, jobject jcallback) +{ + jclass append_recno_class; + + if (dbji->append_recno_method_id_ == NULL) { + append_recno_class = get_class(jnienv, name_DbAppendRecno); + dbji->append_recno_method_id_ = + (*jnienv)->GetMethodID(jnienv, append_recno_class, + "db_append_recno", + "(Lcom/sleepycat/db/Db;" + "Lcom/sleepycat/db/Dbt;I)V"); + if (dbji->append_recno_method_id_ == NULL) { + /* XXX + * We should really have a better way + * to translate this to a Java exception class. + * In theory, it shouldn't happen. + */ + report_exception(jnienv, "Cannot find callback method", + EFAULT, 0); + return; + } + } + + if (dbji->append_recno_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbji->append_recno_); + } + if (jcallback == NULL) { + db->set_append_recno(db, NULL); + } + else { + db->set_append_recno(db, Db_append_recno_callback); + } + + dbji->append_recno_ = NEW_GLOBAL_REF(jnienv, jcallback); +} + +extern int dbji_call_append_recno(DB_JAVAINFO *dbji, DB *db, jobject jdb, + DBT *dbt, jint recno) +{ + JNIEnv *jnienv; + jobject jdbt; + DBT_JAVAINFO *dbtji; + jbyteArray arr; + unsigned int arraylen; + unsigned char *data; + + COMPQUIET(db, NULL); + jnienv = dbji_get_jnienv(dbji); + if (jnienv == NULL) { + fprintf(stderr, "Cannot attach to current thread!\n"); + return (0); + } + + /* XXX + * We should have a pool of Dbt objects used for this purpose + * instead of creating new ones each time. Because of + * multithreading, we may need an arbitrary number (more than two). + * We might also have a byte arrays that grow as needed, + * so we don't need to allocate those either. + * + * Note, we do not set the 'create_array_' flag as on other + * callbacks as we are creating the array here. + */ + jdbt = create_default_object(jnienv, name_DBT); + dbtji = get_DBT_JAVAINFO(jnienv, jdbt); + memcpy(&dbtji->dbt, dbt, sizeof(DBT)); + dbtji->dbt.data = NULL; + arr = (*jnienv)->NewByteArray(jnienv, dbt->size); + (*jnienv)->SetByteArrayRegion(jnienv, arr, 0, dbt->size, + (jbyte *)dbt->data); + dbtji->array_ = (jbyteArray)NEW_GLOBAL_REF(jnienv, arr); + + DB_ASSERT(dbji->append_recno_method_id_ != NULL); + (*jnienv)->CallVoidMethod(jnienv, dbji->append_recno_, + dbji->append_recno_method_id_, + jdb, jdbt, recno); + + /* The underlying C API requires that an errno be returned + * on error. Java users know nothing of errnos, so we + * allow them to throw exceptions instead. We leave the + * exception in place and return DB_JAVA_CALLBACK to the C API + * that called us. Eventually the DB->get will fail and + * when java prepares to throw an exception in + * report_exception(), this will be spotted as a special case, + * and the original exception will be preserved. + * + * Note: we have sometimes noticed strange behavior with + * exceptions under Linux 1.1.7 JVM. (i.e. multiple calls + * to ExceptionOccurred() may report different results). + * Currently we don't know of any problems related to this + * in our code, but if it pops up in the future, users are + * encouranged to get a more recent JVM. + */ + if ((*jnienv)->ExceptionOccurred(jnienv) != NULL) + return (DB_JAVA_CALLBACK); + + if (dbtji->array_ == NULL) { + report_exception(jnienv, "Dbt.data is null", 0, 0); + return (EFAULT); + } + + arraylen = (*jnienv)->GetArrayLength(jnienv, dbtji->array_); + if (dbtji->offset_ < 0 ) { + report_exception(jnienv, "Dbt.offset illegal", 0, 0); + return (EFAULT); + } + if (dbt->ulen + dbtji->offset_ > arraylen) { + report_exception(jnienv, + "Dbt.ulen + Dbt.offset greater than array length", 0, 0); + return (EFAULT); + } + + data = (*jnienv)->GetByteArrayElements(jnienv, dbtji->array_, + (jboolean *)0); + dbt->data = data + dbtji->offset_; + return (0); +} + +void dbji_set_bt_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv, + DB *db, jobject jcompare) +{ + jclass bt_compare_class; + + if (dbji->bt_compare_method_id_ == NULL) { + bt_compare_class = get_class(jnienv, name_DbBtreeCompare); + dbji->bt_compare_method_id_ = + (*jnienv)->GetMethodID(jnienv, bt_compare_class, + "bt_compare", + "(Lcom/sleepycat/db/Db;" + "Lcom/sleepycat/db/Dbt;" + "Lcom/sleepycat/db/Dbt;)I"); + if (dbji->bt_compare_method_id_ == NULL) { + /* XXX + * We should really have a better way + * to translate this to a Java exception class. + * In theory, it shouldn't happen. + */ + report_exception(jnienv, "Cannot find callback method", + EFAULT, 0); + return; + } + } + + if (dbji->bt_compare_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbji->bt_compare_); + } + if (jcompare == NULL) { + db->set_bt_compare(db, NULL); + } + else { + db->set_bt_compare(db, Db_bt_compare_callback); + } + + dbji->bt_compare_ = NEW_GLOBAL_REF(jnienv, jcompare); +} + +int dbji_call_bt_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb, + const DBT *dbt1, const DBT *dbt2) +{ + JNIEnv *jnienv; + jobject jdbt1, jdbt2; + DBT_JAVAINFO *dbtji1, *dbtji2; + + COMPQUIET(db, NULL); + jnienv = dbji_get_jnienv(dbji); + if (jnienv == NULL) { + fprintf(stderr, "Cannot attach to current thread!\n"); + return (0); + } + + /* XXX + * We should have a pool of Dbt objects used for this purpose + * instead of creating new ones each time. Because of + * multithreading, we may need an arbitrary number (more than two). + * We might also have a byte arrays that grow as needed, + * so we don't need to allocate those either. + */ + jdbt1 = create_default_object(jnienv, name_DBT); + jdbt2 = create_default_object(jnienv, name_DBT); + dbtji1 = get_DBT_JAVAINFO(jnienv, jdbt1); + memcpy(&dbtji1->dbt, dbt1, sizeof(DBT)); + dbtji1->create_array_ = 1; + dbtji2 = get_DBT_JAVAINFO(jnienv, jdbt2); + memcpy(&dbtji2->dbt, dbt2, sizeof(DBT)); + dbtji2->create_array_ = 1; + + DB_ASSERT(dbji->bt_compare_method_id_ != NULL); + return (*jnienv)->CallIntMethod(jnienv, dbji->bt_compare_, + dbji->bt_compare_method_id_, + jdb, jdbt1, jdbt2); +} + +void dbji_set_bt_prefix_object(DB_JAVAINFO *dbji, JNIEnv *jnienv, + DB *db, jobject jprefix) +{ + jclass bt_prefix_class; + + if (dbji->bt_prefix_method_id_ == NULL) { + bt_prefix_class = get_class(jnienv, name_DbBtreePrefix); + dbji->bt_prefix_method_id_ = + (*jnienv)->GetMethodID(jnienv, bt_prefix_class, + "bt_prefix", + "(Lcom/sleepycat/db/Db;" + "Lcom/sleepycat/db/Dbt;" + "Lcom/sleepycat/db/Dbt;)I"); + if (dbji->bt_prefix_method_id_ == NULL) { + /* XXX + * We should really have a better way + * to translate this to a Java exception class. + * In theory, it shouldn't happen. + */ + report_exception(jnienv, "Cannot find callback method", + EFAULT, 0); + return; + } + } + + if (dbji->bt_prefix_ != NULL) { + DELETE_GLOBAL_REF(jnienv, dbji->bt_prefix_); + } + if (jprefix == NULL) { + db->set_bt_prefix(db, NULL); + } + else { + db->set_bt_prefix(db, Db_bt_prefix_callback); + } + + dbji->bt_prefix_ = NEW_GLOBAL_REF(jnienv, jprefix); +} + +size_t dbji_call_bt_prefix(DB_JAVAINFO *dbji, DB *db, jobject jdb, + const DBT *dbt1, const DBT *dbt2) +{ + JNIEnv *jnienv; + jobject jdbt1, jdbt2; + DBT_JAVAINFO *dbtji1, *dbtji2; + + COMPQUIET(db, NULL); + jnienv = dbji_get_jnienv(dbji); + if (jnienv == NULL) { + fprintf(stderr, "Cannot attach to current thread!\n"); + return (0); + } + + /* XXX + * We should have a pool of Dbt objects used for this purpose + * instead of creating new ones each time. Because of + * multithreading, we may need an arbitrary number (more than two). + * We might also have a byte arrays that grow as needed, + * so we don't need to allocate those either. + */ + jdbt1 = create_default_object(jnienv, name_DBT); + jdbt2 = create_default_object(jnienv, name_DBT); + dbtji1 = get_DBT_JAVAINFO(jnienv, jdbt1); + memcpy(&dbtji1->dbt, dbt1, sizeof(DBT)); + dbtji1->create_array_ = 1; + dbtji2 = get_DBT_JAVAINFO(jnienv, jdbt2); + memcpy(&dbtji2->dbt, dbt2, sizeof(DBT)); + dbtji2->create_array_ = 1; + + DB_ASSERT(dbji->bt_prefix_method_id_ != NULL); + return (size_t)(*jnienv)->CallIntMethod(jnienv, dbji->bt_prefix_, + dbji->bt_prefix_method_id_, + jdb, jdbt1, jdbt2); +} + +void dbji_set_dup_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv, + DB *db, jobject jcompare) +{ + jclass dup_compare_class; + + if (dbji->dup_compare_method_id_ == NULL) { + dup_compare_class = get_class(jnienv, name_DbDupCompare); + dbji->dup_compare_method_id_ = + (*jnienv)->GetMethodID(jnienv, dup_compare_class, + "dup_compare", + "(Lcom/sleepycat/db/Db;" + "Lcom/sleepycat/db/Dbt;" + "Lcom/sleepycat/db/Dbt;)I"); + if (dbji->dup_compare_method_id_ == NULL) { + /* XXX + * We should really have a better way + * to translate this to a Java exception class. + * In theory, it shouldn't happen. + */ + report_exception(jnienv, "Cannot find callback method", + EFAULT, 0); + return; + } + } + + if (dbji->dup_compare_ != NULL) + DELETE_GLOBAL_REF(jnienv, dbji->dup_compare_); + + if (jcompare == NULL) + db->set_dup_compare(db, NULL); + else + db->set_dup_compare(db, Db_dup_compare_callback); + + dbji->dup_compare_ = NEW_GLOBAL_REF(jnienv, jcompare); +} + +int dbji_call_dup_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb, + const DBT *dbt1, const DBT *dbt2) +{ + JNIEnv *jnienv; + jobject jdbt1, jdbt2; + DBT_JAVAINFO *dbtji1, *dbtji2; + + COMPQUIET(db, NULL); + jnienv = dbji_get_jnienv(dbji); + if (jnienv == NULL) { + fprintf(stderr, "Cannot attach to current thread!\n"); + return (0); + } + + /* XXX + * We should have a pool of Dbt objects used for this purpose + * instead of creating new ones each time. Because of + * multithreading, we may need an arbitrary number (more than two). + * We might also have a byte arrays that grow as needed, + * so we don't need to allocate those either. + */ + jdbt1 = create_default_object(jnienv, name_DBT); + jdbt2 = create_default_object(jnienv, name_DBT); + dbtji1 = get_DBT_JAVAINFO(jnienv, jdbt1); + memcpy(&dbtji1->dbt, dbt1, sizeof(DBT)); + dbtji1->create_array_ = 1; + dbtji2 = get_DBT_JAVAINFO(jnienv, jdbt2); + memcpy(&dbtji2->dbt, dbt2, sizeof(DBT)); + dbtji2->create_array_ = 1; + + DB_ASSERT(dbji->dup_compare_method_id_ != NULL); + return (*jnienv)->CallIntMethod(jnienv, dbji->dup_compare_, + dbji->dup_compare_method_id_, + jdb, jdbt1, jdbt2); +} + +void dbji_set_h_hash_object(DB_JAVAINFO *dbji, JNIEnv *jnienv, + DB *db, jobject jhash) +{ + jclass h_hash_class; + + if (dbji->h_hash_method_id_ == NULL) { + h_hash_class = get_class(jnienv, name_DbHash); + dbji->h_hash_method_id_ = + (*jnienv)->GetMethodID(jnienv, h_hash_class, + "hash", + "(Lcom/sleepycat/db/Db;" + "[BI)I"); + if (dbji->h_hash_method_id_ == NULL) { + /* XXX + * We should really have a better way + * to translate this to a Java exception class. + * In theory, it shouldn't happen. + */ + report_exception(jnienv, "Cannot find callback method", + EFAULT, 0); + return; + } + } + + if (dbji->h_hash_ != NULL) + DELETE_GLOBAL_REF(jnienv, dbji->h_hash_); + + if (jhash == NULL) + db->set_h_hash(db, NULL); + else + db->set_h_hash(db, Db_h_hash_callback); + + dbji->h_hash_ = NEW_GLOBAL_REF(jnienv, jhash); +} + +int dbji_call_h_hash(DB_JAVAINFO *dbji, DB *db, jobject jdb, + const void *data, int len) +{ + JNIEnv *jnienv; + jbyteArray jarray; + + COMPQUIET(db, NULL); + jnienv = dbji_get_jnienv(dbji); + if (jnienv == NULL) { + fprintf(stderr, "Cannot attach to current thread!\n"); + return (0); + } + + DB_ASSERT(dbji->h_hash_method_id_ != NULL); + + jarray = (*jnienv)->NewByteArray(jnienv, len); + (*jnienv)->SetByteArrayRegion(jnienv, jarray, 0, len, (void *)data); + return (*jnienv)->CallIntMethod(jnienv, dbji->h_hash_, + dbji->h_hash_method_id_, + jdb, jarray, len); +} diff --git a/bdb/libdb_java/java_info.h b/bdb/libdb_java/java_info.h new file mode 100644 index 00000000000..69032be80e6 --- /dev/null +++ b/bdb/libdb_java/java_info.h @@ -0,0 +1,200 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 1998, 1999, 2000 + * Sleepycat Software. All rights reserved. + * + * $Id: java_info.h,v 11.17 2000/07/31 20:28:30 dda Exp $ + */ + +#ifndef _JAVA_INFO_H_ +#define _JAVA_INFO_H_ + +/* + * "Info" classes for Java implementation of Berkeley DB API. + * These classes hold extra information for which there is + * no room or counterpart in the base classes used in the C API. + * In the case of a DBT, the DBT_javainfo class is stored in the + * 'private' variable of the java Dbt, and the DBT_javainfo is subclassed + * from a DBT. In the case of DB and DB_ENV, the appropriate + * info objects are pointed to by the DB and DB_ENV objects. + * This is convenient to implement callbacks. + */ + +/**************************************************************** + * + * Declaration of class DBT_javainfo + * + * A DBT_javainfo is created whenever a Dbt (java) object is created, + * and a pointer to it is stored in its private info storage. + * It is subclassed from DBT, because we must retain some extra + * information in it while it is in use. In particular, when + * a java array is associated with it, we need to keep a Globally + * Locked reference to it so it is not GC'd. This reference is + * destroyed when the Dbt is GC'd. + */ +typedef struct _dbt_javainfo +{ + DBT dbt; + DB *db_; /* associated DB */ + jobject dbtref_; /* the java Dbt object */ + jbyteArray array_; + int offset_; + int create_array_; /* flag to create the array as needed */ +} +DBT_JAVAINFO; /* used with all 'dbtji' functions */ + +extern DBT_JAVAINFO *dbjit_construct(); +extern void dbjit_release(DBT_JAVAINFO *dbjit, JNIEnv *jnienv); + +/**************************************************************** + * + * Declaration of class DB_ENV_JAVAINFO + * + * A DB_ENV_JAVAINFO is allocated and stuffed into the cj_internal + * and the db_errpfx for every DB_ENV created. It holds a + * little extra info that is needed to support callbacks. + * + * There's a bit of trickery here, because we have built this + * above a layer that has a C function callback that gets + * invoked when an error occurs. One of the C callback's arguments + * is the prefix from the DB_ENV, but since we stuffed a pointer + * to our own DB_ENV_JAVAINFO into the prefix, we get that object as an + * argument to the C callback. Thus, the C callback can have + * access to much more than just the prefix, and it needs that + * to call back into the Java enviroment. + * + * The DB_ENV_JAVAINFO object holds a copy of the Java Virtual Machine, + * which is needed to attach to the current running thread + * whenever we need to make a callback. (This is more reliable + * than our previous approach, which was to save the thread + * that created the DbEnv). It also has the Java callback object, + * as well as a 'default' callback object that is used when the + * caller sets the callback to null. It also has the original + * error prefix, since we overwrote the one in the DB_ENV. + * There are also fields that are unrelated to the handling + * of callbacks, but are convenient to attach to a DB_ENV. + * + * Note: We assume that the Java layer is the only one + * fiddling with the contents of db_errpfx, db_errcall, cj_internal + * for a DB_ENV that was created via Java. Since the Java layer should + * have the only pointer to such a DB_ENV, this should be true. + */ +typedef struct _db_env_javainfo +{ + JavaVM *javavm_; + int is_dbopen_; + char *errpfx_; + jobject jdbref_; /* temporary reference */ + jobject jenvref_; /* temporary reference */ + jobject default_errcall_; /* global reference */ + jobject errcall_; /* global reference */ + jobject feedback_; /* global reference */ + jobject tx_recover_; /* global reference */ + jobject recovery_init_; /* global reference */ + unsigned char *conflict_; +} +DB_ENV_JAVAINFO; /* used with all 'dbjie' functions */ + +/* create/initialize an object */ +extern DB_ENV_JAVAINFO *dbjie_construct(JNIEnv *jnienv, + jobject default_errcall, + int is_dbopen); + +/* release all objects held by this this one */ +extern void dbjie_dealloc(DB_ENV_JAVAINFO *, JNIEnv *jnienv); + +/* free this object, releasing anything allocated on its behalf */ +extern void dbjie_destroy(DB_ENV_JAVAINFO *, JNIEnv *jnienv); + +/* This gets the environment for the current thread */ +extern JNIEnv *dbjie_get_jnienv(DB_ENV_JAVAINFO *); + +extern void dbjie_set_errpfx(DB_ENV_JAVAINFO *, JNIEnv *jnienv, + jstring errpfx); +extern jstring dbjie_get_errpfx(DB_ENV_JAVAINFO *, JNIEnv *jnienv); +extern void dbjie_set_errcall(DB_ENV_JAVAINFO *, JNIEnv *jnienv, + jobject new_errcall); +extern void dbjie_set_conflict(DB_ENV_JAVAINFO *, unsigned char *v); +extern void dbjie_set_feedback_object(DB_ENV_JAVAINFO *, JNIEnv *jnienv, + DB_ENV *dbenv, jobject value); +extern void dbjie_call_feedback(DB_ENV_JAVAINFO *, DB_ENV *dbenv, jobject jenv, + int opcode, int percent); +extern void dbjie_set_recovery_init_object(DB_ENV_JAVAINFO *, JNIEnv *jnienv, + DB_ENV *dbenv, jobject value); +extern int dbjie_call_recovery_init(DB_ENV_JAVAINFO *, DB_ENV *dbenv, + jobject jenv); +extern void dbjie_set_tx_recover_object(DB_ENV_JAVAINFO *, JNIEnv *jnienv, + DB_ENV *dbenv, jobject value); +extern int dbjie_call_tx_recover(DB_ENV_JAVAINFO *, + DB_ENV *dbenv, jobject jenv, + DBT *dbt, DB_LSN *lsn, int recops); +extern jobject dbjie_get_errcall(DB_ENV_JAVAINFO *) ; +extern int dbjie_is_dbopen(DB_ENV_JAVAINFO *); + +/**************************************************************** + * + * Declaration of class DB_JAVAINFO + * + * A DB_JAVAINFO is allocated and stuffed into the cj_internal field + * for every DB created. It holds a little extra info that is needed + * to support callbacks. + * + * Note: We assume that the Java layer is the only one + * fiddling with the contents of cj_internal + * for a DB that was created via Java. Since the Java layer should + * have the only pointer to such a DB, this should be true. + */ +typedef struct _db_javainfo +{ + JavaVM *javavm_; + jobject jdbref_; /* temporary reference during callback */ + jobject feedback_; /* global reference */ + jobject append_recno_; /* global reference */ + jobject bt_compare_; /* global reference */ + jobject bt_prefix_; /* global reference */ + jobject dup_compare_; /* global reference */ + jobject h_hash_; /* global reference */ + jmethodID feedback_method_id_; + jmethodID append_recno_method_id_; + jmethodID bt_compare_method_id_; + jmethodID bt_prefix_method_id_; + jmethodID dup_compare_method_id_; + jmethodID h_hash_method_id_; + jint construct_flags_; +} DB_JAVAINFO; + +/* create/initialize an object */ +extern DB_JAVAINFO *dbji_construct(JNIEnv *jnienv, jint flags); + +/* release all objects held by this this one */ +extern void dbji_dealloc(DB_JAVAINFO *, JNIEnv *jnienv); + +/* free this object, releasing anything allocated on its behalf */ +extern void dbji_destroy(DB_JAVAINFO *, JNIEnv *jnienv); + +/* This gets the environment for the current thread */ +extern JNIEnv *dbji_get_jnienv(); +extern jint dbji_get_flags(); + +extern void dbji_set_feedback_object(DB_JAVAINFO *, JNIEnv *jnienv, DB *db, jobject value); +extern void dbji_call_feedback(DB_JAVAINFO *, DB *db, jobject jdb, + int opcode, int percent); + +extern void dbji_set_append_recno_object(DB_JAVAINFO *, JNIEnv *jnienv, DB *db, jobject value); +extern int dbji_call_append_recno(DB_JAVAINFO *, DB *db, jobject jdb, + DBT *dbt, jint recno); +extern void dbji_set_bt_compare_object(DB_JAVAINFO *, JNIEnv *jnienv, DB *db, jobject value); +extern int dbji_call_bt_compare(DB_JAVAINFO *, DB *db, jobject jdb, + const DBT *dbt1, const DBT *dbt2); +extern void dbji_set_bt_prefix_object(DB_JAVAINFO *, JNIEnv *jnienv, DB *db, jobject value); +extern size_t dbji_call_bt_prefix(DB_JAVAINFO *, DB *db, jobject jdb, + const DBT *dbt1, const DBT *dbt2); +extern void dbji_set_dup_compare_object(DB_JAVAINFO *, JNIEnv *jnienv, DB *db, jobject value); +extern int dbji_call_dup_compare(DB_JAVAINFO *, DB *db, jobject jdb, + const DBT *dbt1, const DBT *dbt2); +extern void dbji_set_h_hash_object(DB_JAVAINFO *, JNIEnv *jnienv, DB *db, jobject value); +extern int dbji_call_h_hash(DB_JAVAINFO *, DB *db, jobject jdb, + const void *data, int len); + +#endif /* !_JAVA_INFO_H_ */ diff --git a/bdb/libdb_java/java_locked.c b/bdb/libdb_java/java_locked.c new file mode 100644 index 00000000000..a5603df5d60 --- /dev/null +++ b/bdb/libdb_java/java_locked.c @@ -0,0 +1,294 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 1998, 1999, 2000 + * Sleepycat Software. All rights reserved. + */ +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: java_locked.c,v 11.11 2000/10/25 19:54:55 dda Exp $"; +#endif /* not lint */ + +#include <jni.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "db.h" +#include "java_util.h" + +/**************************************************************** + * + * Implementation of class LockedDBT + * + */ +int +jdbt_lock(JDBT *jdbt, JNIEnv *jnienv, jobject obj, OpKind kind) +{ + DBT *dbt; + + jdbt->obj_ = obj; + jdbt->do_realloc_ = 0; + jdbt->kind_ = kind; + jdbt->java_array_len_= 0; + jdbt->java_data_ = 0; + jdbt->before_data_ = 0; + jdbt->has_error_ = 0; + jdbt->dbt = (DBT_JAVAINFO *)get_private_dbobj(jnienv, name_DBT, obj); + + if (!verify_non_null(jnienv, jdbt->dbt)) { + jdbt->has_error_ = 1; + return (EINVAL); + } + dbt = &jdbt->dbt->dbt; + + if (kind == outOp && + (dbt->flags & (DB_DBT_USERMEM | DB_DBT_MALLOC | DB_DBT_REALLOC)) == 0) { + report_exception(jnienv, + "Dbt.flags must be set to Db.DB_DBT_USERMEM, " + "Db.DB_DBT_MALLOC or Db.DB_DBT_REALLOC", + 0, 0); + jdbt->has_error_ = 1; + return (EINVAL); + } + + /* If this is requested to be realloc, we cannot use the + * underlying realloc, because the array we will pass in + * is not allocated by us, but the Java VM, so it cannot + * be successfully realloced. We simulate the reallocation, + * by using USERMEM and reallocating the java array when a + * ENOMEM error occurs. We change the flags during the operation, + * and they are reset when the operation completes (in the + * LockedDBT destructor. + */ + if ((dbt->flags & DB_DBT_REALLOC) != 0) { + dbt->flags &= ~DB_DBT_REALLOC; + dbt->flags |= DB_DBT_USERMEM; + jdbt->do_realloc_ = 1; + } + + if ((dbt->flags & DB_DBT_USERMEM) || kind != outOp) { + + /* If writing with DB_DBT_USERMEM/REALLOC + * or it's a set (or get/set) operation, + * then the data should point to a java array. + * Note that outOp means data is coming out of the database + * (it's a get). inOp means data is going into the database + * (either a put, or a key input). + */ + if (!jdbt->dbt->array_) { + report_exception(jnienv, "Dbt.data is null", 0, 0); + jdbt->has_error_ = 1; + return (EINVAL); + } + + /* Verify other parameters */ + jdbt->java_array_len_ = (*jnienv)->GetArrayLength(jnienv, jdbt->dbt->array_); + if (jdbt->dbt->offset_ < 0 ) { + report_exception(jnienv, "Dbt.offset illegal", 0, 0); + jdbt->has_error_ = 1; + return (EINVAL); + } + if (dbt->ulen + jdbt->dbt->offset_ > jdbt->java_array_len_) { + report_exception(jnienv, + "Dbt.ulen + Dbt.offset greater than array length", 0, 0); + jdbt->has_error_ = 1; + return (EINVAL); + } + + jdbt->java_data_ = (*jnienv)->GetByteArrayElements(jnienv, jdbt->dbt->array_, + (jboolean *)0); + dbt->data = jdbt->before_data_ = jdbt->java_data_ + jdbt->dbt->offset_; + } + else { + + /* If writing with DB_DBT_MALLOC, then the data is + * allocated by DB. + */ + dbt->data = jdbt->before_data_ = 0; + } + return (0); +} + +/* The LockedDBT destructor is called when the java handler returns + * to the user, since that's when the LockedDBT objects go out of scope. + * Since it is thus called after any call to the underlying database, + * it copies any information from temporary structures back to user + * accessible arrays, and of course must free memory and remove references. + */ +void +jdbt_unlock(JDBT *jdbt, JNIEnv *jnienv) +{ + DBT *dbt; + + dbt = &jdbt->dbt->dbt; + + /* Fix up the flags if we changed them. */ + if (jdbt->do_realloc_) { + dbt->flags &= ~DB_DBT_USERMEM; + dbt->flags |= DB_DBT_REALLOC; + } + + if ((dbt->flags & (DB_DBT_USERMEM | DB_DBT_REALLOC)) || + jdbt->kind_ == inOp) { + + /* If writing with DB_DBT_USERMEM/REALLOC or it's a set + * (or get/set) operation, then the data may be already in + * the java array, in which case, we just need to release it. + * If DB didn't put it in the array (indicated by the + * dbt->data changing), we need to do that + */ + if (jdbt->before_data_ != jdbt->java_data_) { + (*jnienv)->SetByteArrayRegion(jnienv, + jdbt->dbt->array_, + jdbt->dbt->offset_, + dbt->ulen, + jdbt->before_data_); + } + (*jnienv)->ReleaseByteArrayElements(jnienv, jdbt->dbt->array_, jdbt->java_data_, 0); + dbt->data = 0; + } + if ((dbt->flags & DB_DBT_MALLOC) && jdbt->kind_ != inOp) { + + /* If writing with DB_DBT_MALLOC, then the data was allocated + * by DB. If dbt->data is zero, it means an error occurred + * (and should have been already reported). + */ + if (dbt->data) { + + /* Release any old references. */ + dbjit_release(jdbt->dbt, jnienv); + + /* In the case of SET_RANGE, the key is inOutOp + * and when not found, its data will be left as + * its original value. Only copy and free it + * here if it has been allocated by DB + * (dbt->data has changed). + */ + if (dbt->data != jdbt->before_data_) { + jdbt->dbt->array_ = (jbyteArray) + NEW_GLOBAL_REF(jnienv, + (*jnienv)->NewByteArray(jnienv, + dbt->size)); + jdbt->dbt->offset_ = 0; + (*jnienv)->SetByteArrayRegion(jnienv, + jdbt->dbt->array_, 0, dbt->size, + (jbyte *)dbt->data); + free(dbt->data); + dbt->data = 0; + } + } + } +} + +/* Realloc the java array to receive data if the DBT was marked + * for realloc, and the last operation set the size field to an + * amount greater than ulen. + */ +int jdbt_realloc(JDBT *jdbt, JNIEnv *jnienv) +{ + DBT *dbt; + + dbt = &jdbt->dbt->dbt; + + if (!jdbt->do_realloc_ || jdbt->has_error_ || dbt->size <= dbt->ulen) + return (0); + + (*jnienv)->ReleaseByteArrayElements(jnienv, jdbt->dbt->array_, jdbt->java_data_, 0); + dbjit_release(jdbt->dbt, jnienv); + + /* We allocate a new array of the needed size. + * We'll set the offset to 0, as the old offset + * really doesn't make any sense. + */ + jdbt->java_array_len_ = dbt->ulen = dbt->size; + jdbt->dbt->offset_ = 0; + jdbt->dbt->array_ = (jbyteArray) + NEW_GLOBAL_REF(jnienv, (*jnienv)->NewByteArray(jnienv, dbt->size)); + + jdbt->java_data_ = (*jnienv)->GetByteArrayElements(jnienv, + jdbt->dbt->array_, + (jboolean *)0); + dbt->data = jdbt->before_data_ = jdbt->java_data_; + return (1); +} + +/**************************************************************** + * + * Implementation of class JSTR + * + */ +int +jstr_lock(JSTR *js, JNIEnv *jnienv, jstring jstr) +{ + js->jstr_ = jstr; + + if (jstr == 0) + js->string = 0; + else + js->string = (*jnienv)->GetStringUTFChars(jnienv, jstr, + (jboolean *)0); + return (0); +} + +void jstr_unlock(JSTR *js, JNIEnv *jnienv) +{ + if (js->jstr_) + (*jnienv)->ReleaseStringUTFChars(jnienv, js->jstr_, js->string); +} + +/**************************************************************** + * + * Implementation of class JSTRARRAY + * + */ +int +jstrarray_lock(JSTRARRAY *jsa, JNIEnv *jnienv, jobjectArray arr) +{ + int i; + + jsa->arr_ = arr; + jsa->array = 0; + + if (arr != 0) { + int count = (*jnienv)->GetArrayLength(jnienv, arr); + const char **new_array = + (const char **)malloc((sizeof(const char *))*(count+1)); + for (i=0; i<count; i++) { + jstring jstr = (jstring)(*jnienv)->GetObjectArrayElement(jnienv, arr, i); + if (jstr == 0) { + /* + * An embedded null in the string array + * is treated as an endpoint. + */ + new_array[i] = 0; + break; + } + else { + new_array[i] = + (*jnienv)->GetStringUTFChars(jnienv, jstr, (jboolean *)0); + } + } + new_array[count] = 0; + jsa->array = new_array; + } + return (0); +} + +void jstrarray_unlock(JSTRARRAY *jsa, JNIEnv *jnienv) +{ + int i; + jstring jstr; + + if (jsa->arr_) { + int count = (*jnienv)->GetArrayLength(jnienv, jsa->arr_); + for (i=0; i<count; i++) { + if (jsa->array[i] == 0) + break; + jstr = (jstring)(*jnienv)->GetObjectArrayElement(jnienv, jsa->arr_, i); + (*jnienv)->ReleaseStringUTFChars(jnienv, jstr, jsa->array[i]); + } + free((void*)jsa->array); + } +} diff --git a/bdb/libdb_java/java_locked.h b/bdb/libdb_java/java_locked.h new file mode 100644 index 00000000000..9b88cdd0619 --- /dev/null +++ b/bdb/libdb_java/java_locked.h @@ -0,0 +1,98 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 1998, 1999, 2000 + * Sleepycat Software. All rights reserved. + * + * $Id: java_locked.h,v 11.9 2000/10/25 19:54:55 dda Exp $ + */ + +#ifndef _JAVA_LOCKED_H_ +#define _JAVA_LOCKED_H_ + +/* + * Used internally by LockedDBT constructor. + */ +typedef enum _OpKind { + inOp, /* setting data in database (passing data in) */ + outOp, /* getting data from database to user memory */ + inOutOp /* both getting/setting data */ +} OpKind; + +/* + * + * Declaration of JDBT + * + * A JDBT object exists during a + * single native call to the DB API. Its constructor's job is + * to temporarily convert any java array found in the DBT_JAVAINFO + * to actual bytes in memory that remain locked in place. These + * bytes are used during the call to the underlying DB C layer, + * and are released and/or copied back by the destructor. + * Thus, a LockedDBT must be declared as a stack object to + * function properly. + */ +typedef struct _jdbt +{ + /* these are accessed externally to ldbt_ functions */ + DBT_JAVAINFO *dbt; + unsigned int java_array_len_; + + /* these are for used internally by ldbt_ functions */ + jobject obj_; + jbyte *java_data_; + jbyte *before_data_; + int has_error_; + int do_realloc_; + OpKind kind_; +} JDBT; + +extern int jdbt_lock(JDBT *, JNIEnv *jnienv, jobject obj, OpKind kind); +extern void jdbt_unlock(JDBT *, JNIEnv *jnienv); /* this unlocks and frees the memory */ +extern int jdbt_realloc(JDBT *, JNIEnv *jnienv); /* returns 1 if reallocation took place */ + +/**************************************************************** + * + * Declaration of JSTR + * + * A JSTR exists temporarily to convert a java jstring object + * to a char *. Because the memory for the char * string is + * managed by the JVM, it must be released when we are done + * looking at it. Typically, jstr_lock() is called at the + * beginning of a function for each jstring object, and jstr_unlock + * is called at the end of each function for each JSTR. + */ +typedef struct _jstr +{ + /* this accessed externally to jstr_ functions */ + const char *string; + + /* this is used internally by jstr_ functions */ + jstring jstr_; +} JSTR; + +extern int jstr_lock(JSTR *, JNIEnv *jnienv, jstring jstr); +extern void jstr_unlock(JSTR *, JNIEnv *jnienv); /* this unlocks and frees mem */ + +/**************************************************************** + * + * Declaration of class LockedStrarray + * + * Given a java jobjectArray object (that must be a String[]), + * we extract the individual strings and build a const char ** + * When the LockedStrarray object is destroyed, the individual + * strings are released. + */ +typedef struct _jstrarray +{ + /* this accessed externally to jstrarray_ functions */ + const char **array; + + /* this is used internally by jstrarray_ functions */ + jobjectArray arr_; +} JSTRARRAY; + +extern int jstrarray_lock(JSTRARRAY *, JNIEnv *jnienv, jobjectArray arr); +extern void jstrarray_unlock(JSTRARRAY *, JNIEnv *jnienv); /* this unlocks and frees mem */ + +#endif /* !_JAVA_LOCKED_H_ */ diff --git a/bdb/libdb_java/java_util.c b/bdb/libdb_java/java_util.c new file mode 100644 index 00000000000..f42ceafbee8 --- /dev/null +++ b/bdb/libdb_java/java_util.c @@ -0,0 +1,556 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 1998, 1999, 2000 + * Sleepycat Software. All rights reserved. + */ +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: java_util.c,v 11.17 2000/10/28 13:09:39 dda Exp $"; +#endif /* not lint */ + +#include <jni.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "db.h" +#include "java_util.h" + +#ifdef DB_WIN32 +#define sys_errlist _sys_errlist +#define sys_nerr _sys_nerr +#endif + +const char * const name_DB = "Db"; +const char * const name_DB_BTREE_STAT = "DbBtreeStat"; +const char * const name_DBC = "Dbc"; +const char * const name_DB_DEADLOCK_EX = "DbDeadlockException"; +const char * const name_DB_ENV = "DbEnv"; +const char * const name_DB_EXCEPTION = "DbException"; +const char * const name_DB_HASH_STAT = "DbHashStat"; +const char * const name_DB_LOCK = "DbLock"; +const char * const name_DB_LOCK_STAT = "DbLockStat"; +const char * const name_DB_LOG_STAT = "DbLogStat"; +const char * const name_DB_LSN = "DbLsn"; +const char * const name_DB_MEMORY_EX = "DbMemoryException"; +const char * const name_DB_MPOOL_FSTAT = "DbMpoolFStat"; +const char * const name_DB_MPOOL_STAT = "DbMpoolStat"; +const char * const name_DB_QUEUE_STAT = "DbQueueStat"; +const char * const name_DB_RUNRECOVERY_EX = "DbRunRecoveryException"; +const char * const name_DBT = "Dbt"; +const char * const name_DB_TXN = "DbTxn"; +const char * const name_DB_TXN_STAT = "DbTxnStat"; +const char * const name_DB_TXN_STAT_ACTIVE = "DbTxnStat$Active"; +const char * const name_DbAppendRecno = "DbAppendRecno"; +const char * const name_DbBtreeCompare = "DbBtreeCompare"; +const char * const name_DbBtreePrefix = "DbBtreePrefix"; +const char * const name_DbDupCompare = "DbDupCompare"; +const char * const name_DbEnvFeedback = "DbEnvFeedback"; +const char * const name_DbErrcall = "DbErrcall"; +const char * const name_DbHash = "DbHash"; +const char * const name_DbFeedback = "DbFeedback"; +const char * const name_DbRecoveryInit = "DbRecoveryInit"; +const char * const name_DbTxnRecover = "DbTxnRecover"; + +const char * const string_signature = "Ljava/lang/String;"; + +/**************************************************************** + * + * Utility functions used by "glue" functions. + * + */ + +/* Get the private data from a Db* object that points back to a C DB_* object. + * The private data is stored in the object as a Java long (64 bits), + * which is long enough to store a pointer on current architectures. + */ +void *get_private_dbobj(JNIEnv *jnienv, const char *classname, + jobject obj) +{ + jclass dbClass; + jfieldID id; + long_to_ptr lp; + + if (!obj) + return (0); + + dbClass = get_class(jnienv, classname); + id = (*jnienv)->GetFieldID(jnienv, dbClass, "private_dbobj_", "J"); + lp.java_long = (*jnienv)->GetLongField(jnienv, obj, id); + return (lp.ptr); +} + +/* Set the private data in a Db* object that points back to a C DB_* object. + * The private data is stored in the object as a Java long (64 bits), + * which is long enough to store a pointer on current architectures. + */ +void set_private_dbobj(JNIEnv *jnienv, const char *classname, + jobject obj, void *value) +{ + long_to_ptr lp; + jclass dbClass; + jfieldID id; + + lp.java_long = 0; /* no junk in case sizes mismatch */ + lp.ptr = value; + dbClass = get_class(jnienv, classname); + id = (*jnienv)->GetFieldID(jnienv, dbClass, "private_dbobj_", "J"); + (*jnienv)->SetLongField(jnienv, obj, id, lp.java_long); +} + +/* Get the private data in a Db/DbEnv object that holds additional 'side data'. + * The private data is stored in the object as a Java long (64 bits), + * which is long enough to store a pointer on current architectures. + */ +void *get_private_info(JNIEnv *jnienv, const char *classname, + jobject obj) +{ + jclass dbClass; + jfieldID id; + long_to_ptr lp; + + if (!obj) + return (0); + + dbClass = get_class(jnienv, classname); + id = (*jnienv)->GetFieldID(jnienv, dbClass, "private_info_", "J"); + lp.java_long = (*jnienv)->GetLongField(jnienv, obj, id); + return (lp.ptr); +} + +/* Set the private data in a Db/DbEnv object that holds additional 'side data'. + * The private data is stored in the object as a Java long (64 bits), + * which is long enough to store a pointer on current architectures. + */ +void set_private_info(JNIEnv *jnienv, const char *classname, + jobject obj, void *value) +{ + long_to_ptr lp; + jclass dbClass; + jfieldID id; + + lp.java_long = 0; /* no junk in case sizes mismatch */ + lp.ptr = value; + dbClass = get_class(jnienv, classname); + id = (*jnienv)->GetFieldID(jnienv, dbClass, "private_info_", "J"); + (*jnienv)->SetLongField(jnienv, obj, id, lp.java_long); +} + +/* + * Given a non-qualified name (e.g. "foo"), get the class handle + * for the fully qualified name (e.g. "com.sleepycat.db.foo") + */ +jclass get_class(JNIEnv *jnienv, const char *classname) +{ + /* Note: PERFORMANCE: It should be possible to cache jclass's. + * If we do a NewGlobalRef on each one, we can keep them + * around in a table. A jclass is a jobject, and + * since NewGlobalRef returns a jobject, it isn't + * technically right, but it would likely work with + * most implementations. Possibly make it configurable. + */ + char fullname[128] = DB_PACKAGE_NAME; + strncat(fullname, classname, sizeof(fullname)); + return ((*jnienv)->FindClass(jnienv, fullname)); +} + +/* Set an individual field in a Db* object. + * The field must be a DB object type. + */ +void set_object_field(JNIEnv *jnienv, jclass class_of_this, + jobject jthis, const char *object_classname, + const char *name_of_field, jobject obj) +{ + char signature[512]; + jfieldID id; + + strncpy(signature, "L", sizeof(signature)); + strncat(signature, DB_PACKAGE_NAME, sizeof(signature)); + strncat(signature, object_classname, sizeof(signature)); + strncat(signature, ";", sizeof(signature)); + + id = (*jnienv)->GetFieldID(jnienv, class_of_this, name_of_field, signature); + (*jnienv)->SetObjectField(jnienv, jthis, id, obj); +} + +/* Set an individual field in a Db* object. + * The field must be an integer type. + */ +void set_int_field(JNIEnv *jnienv, jclass class_of_this, + jobject jthis, const char *name_of_field, jint value) +{ + jfieldID id = (*jnienv)->GetFieldID(jnienv, class_of_this, name_of_field, "I"); + (*jnienv)->SetIntField(jnienv, jthis, id, value); +} + +/* Set an individual field in a Db* object. + * The field must be an integer type. + */ +void set_long_field(JNIEnv *jnienv, jclass class_of_this, + jobject jthis, const char *name_of_field, jlong value) +{ + jfieldID id = (*jnienv)->GetFieldID(jnienv, class_of_this, name_of_field, "J"); + (*jnienv)->SetLongField(jnienv, jthis, id, value); +} + +/* Set an individual field in a Db* object. + * The field must be an integer type. + */ +void set_lsn_field(JNIEnv *jnienv, jclass class_of_this, + jobject jthis, const char *name_of_field, DB_LSN value) +{ + set_object_field(jnienv, class_of_this, jthis, name_DB_LSN, + name_of_field, get_DbLsn(jnienv, value)); +} + +/* Report an exception back to the java side. + */ +void report_exception(JNIEnv *jnienv, const char *text, int err, + unsigned long expect_mask) +{ + jstring textString; + jclass dbexcept; + jclass javaexcept; + jmethodID constructId; + jthrowable obj; + + textString = NULL; + dbexcept = NULL; + javaexcept = NULL; + constructId = NULL; + obj = NULL; + + switch (err) { + /* DB_JAVA_CALLBACK is returned by dbji_call_append_recno() + * (the append_recno callback) when the Java version of the + * callback has thrown an exception, and we want to pass the + * exception on. The exception has already been thrown, we + * don't want to throw a new one. + */ + case DB_JAVA_CALLBACK: + break; + case ENOMEM: + dbexcept = get_class(jnienv, name_DB_MEMORY_EX); + break; + case ENOENT: + /* In this case there is a corresponding standard java + * exception type that we'll use. First we make sure + * that the calling function expected this kind of error, + * if not we give an 'internal error' DbException, since + * we must not throw an exception type that isn't + * declared in the signature. + * + * We'll make this a little more general if/when we add + * more java standard exceptions. + */ + if ((expect_mask & EXCEPTION_FILE_NOT_FOUND) == 0) { + char errstr[1024]; + + strncpy(errstr, "internal error: unexpected errno: ", + sizeof(errstr)); + strncat(errstr, text, sizeof(errstr)); + textString = get_java_string(jnienv, errstr); + dbexcept = get_class(jnienv, name_DB_EXCEPTION); + } + else { + javaexcept = + (*jnienv)->FindClass(jnienv, "java/io/FileNotFoundException"); + } + break; + case DB_RUNRECOVERY: + dbexcept = get_class(jnienv, name_DB_RUNRECOVERY_EX); + break; + case DB_LOCK_DEADLOCK: + dbexcept = get_class(jnienv, name_DB_DEADLOCK_EX); + break; + default: + dbexcept = get_class(jnienv, name_DB_EXCEPTION); + break; + } + if (dbexcept != NULL) { + if (textString == NULL) + textString = get_java_string(jnienv, text); + constructId = (*jnienv)->GetMethodID(jnienv, dbexcept, + "<init>", + "(Ljava/lang/String;I)V"); + obj = (jthrowable)(*jnienv)->NewObject(jnienv, dbexcept, + constructId, textString, + err); + (*jnienv)->Throw(jnienv, obj); + } + else if (javaexcept != NULL) { + javaexcept = + (*jnienv)->FindClass(jnienv, "java/io/FileNotFoundException"); + (*jnienv)->ThrowNew(jnienv, javaexcept, text); + } +} + +/* Report an error via the errcall mechanism. + */ +void report_errcall(JNIEnv *jnienv, jobject errcall, + jstring prefix, const char *message) +{ + jmethodID id; + jclass errcall_class; + jstring msg; + + errcall_class = get_class(jnienv, name_DbErrcall); + msg = get_java_string(jnienv, message); + + id = (*jnienv)->GetMethodID(jnienv, errcall_class, + "errcall", + "(Ljava/lang/String;Ljava/lang/String;)V"); + if (id == NULL) { + fprintf(stderr, "Cannot get errcall methodID!\n"); + fprintf(stderr, "error: %s\n", message); + return; + } + + (*jnienv)->CallVoidMethod(jnienv, errcall, id, prefix, msg); +} + +/* If the object is null, report an exception and return false (0), + * otherwise return true (1). + */ +int verify_non_null(JNIEnv *jnienv, void *obj) +{ + if (obj == NULL) { + report_exception(jnienv, "null object", EINVAL, 0); + return (0); + } + return (1); +} + +/* If the error code is non-zero, report an exception and return false (0), + * otherwise return true (1). + */ +int verify_return(JNIEnv *jnienv, int err, unsigned long expect_mask) +{ + if (err == 0) + return 1; + + report_exception(jnienv, db_strerror(err), err, expect_mask); + return 0; +} + +/* Create an object of the given class, calling its default constructor. + */ +jobject create_default_object(JNIEnv *jnienv, const char *class_name) +{ + jclass dbclass = get_class(jnienv, class_name); + jmethodID id = (*jnienv)->GetMethodID(jnienv, dbclass, "<init>", "()V"); + jobject object = (*jnienv)->NewObject(jnienv, dbclass, id); + return (object); +} + +/* Convert an DB object to a Java encapsulation of that object. + * Note: This implementation creates a new Java object on each call, + * so it is generally useful when a new DB object has just been created. + */ +jobject convert_object(JNIEnv *jnienv, const char *class_name, void *dbobj) +{ + jobject jo; + + if (!dbobj) + return (0); + + jo = create_default_object(jnienv, class_name); + set_private_dbobj(jnienv, class_name, jo, dbobj); + return (jo); +} + +/* Create a copy of the string + */ +char *dup_string(const char *str) +{ + int len; + char *retval; + + len = strlen(str) + 1; + retval = (char *)malloc(sizeof(char)*len); + strncpy(retval, str, len); + return (retval); +} + +/* Create a java string from the given string + */ +jstring get_java_string(JNIEnv *jnienv, const char* string) +{ + if (string == 0) + return (0); + return ((*jnienv)->NewStringUTF(jnienv, string)); +} + +/* Create a malloc'ed copy of the java string. + * Caller must free it. + */ +char *get_c_string(JNIEnv *jnienv, jstring jstr) +{ + const jbyte *utf; + char *retval; + + utf = (*jnienv)->GetStringUTFChars(jnienv, jstr, NULL); + retval = dup_string((const char *)utf); + (*jnienv)->ReleaseStringUTFChars(jnienv, jstr, utf); + return retval; +} + +/* Convert a java object to the various C pointers they represent. + */ +DB *get_DB(JNIEnv *jnienv, jobject obj) +{ + return ((DB *)get_private_dbobj(jnienv, name_DB, obj)); +} + +DB_BTREE_STAT *get_DB_BTREE_STAT(JNIEnv *jnienv, jobject obj) +{ + return ((DB_BTREE_STAT *)get_private_dbobj(jnienv, name_DB_BTREE_STAT, obj)); +} + +DBC *get_DBC(JNIEnv *jnienv, jobject obj) +{ + return ((DBC *)get_private_dbobj(jnienv, name_DBC, obj)); +} + +DB_ENV *get_DB_ENV(JNIEnv *jnienv, jobject obj) +{ + return ((DB_ENV *)get_private_dbobj(jnienv, name_DB_ENV, obj)); +} + +DB_ENV_JAVAINFO *get_DB_ENV_JAVAINFO(JNIEnv *jnienv, jobject obj) +{ + return ((DB_ENV_JAVAINFO *)get_private_info(jnienv, name_DB_ENV, obj)); +} + +DB_HASH_STAT *get_DB_HASH_STAT(JNIEnv *jnienv, jobject obj) +{ + return ((DB_HASH_STAT *)get_private_dbobj(jnienv, name_DB_HASH_STAT, obj)); +} + +DB_JAVAINFO *get_DB_JAVAINFO(JNIEnv *jnienv, jobject obj) +{ + return ((DB_JAVAINFO *)get_private_info(jnienv, name_DB, obj)); +} + +DB_LOCK *get_DB_LOCK(JNIEnv *jnienv, jobject obj) +{ + return ((DB_LOCK *)get_private_dbobj(jnienv, name_DB_LOCK, obj)); +} + +DB_LOG_STAT *get_DB_LOG_STAT(JNIEnv *jnienv, jobject obj) +{ + return ((DB_LOG_STAT *)get_private_dbobj(jnienv, name_DB_LOG_STAT, obj)); +} + +DB_LSN *get_DB_LSN(JNIEnv *jnienv, jobject obj) +{ + return ((DB_LSN *)get_private_dbobj(jnienv, name_DB_LSN, obj)); +} + +DB_MPOOL_FSTAT *get_DB_MPOOL_FSTAT(JNIEnv *jnienv, jobject obj) +{ + return ((DB_MPOOL_FSTAT *)get_private_dbobj(jnienv, name_DB_MPOOL_FSTAT, obj)); +} + +DB_MPOOL_STAT *get_DB_MPOOL_STAT(JNIEnv *jnienv, jobject obj) +{ + return ((DB_MPOOL_STAT *)get_private_dbobj(jnienv, name_DB_MPOOL_STAT, obj)); +} + +DB_QUEUE_STAT *get_DB_QUEUE_STAT(JNIEnv *jnienv, jobject obj) +{ + return ((DB_QUEUE_STAT *)get_private_dbobj(jnienv, name_DB_QUEUE_STAT, obj)); +} + +DB_TXN *get_DB_TXN(JNIEnv *jnienv, jobject obj) +{ + return ((DB_TXN *)get_private_dbobj(jnienv, name_DB_TXN, obj)); +} + +DB_TXN_STAT *get_DB_TXN_STAT(JNIEnv *jnienv, jobject obj) +{ + return ((DB_TXN_STAT *)get_private_dbobj(jnienv, name_DB_TXN_STAT, obj)); +} + +DBT *get_DBT(JNIEnv *jnienv, jobject obj) +{ + DBT_JAVAINFO *ji; + + ji = (DBT_JAVAINFO *)get_private_dbobj(jnienv, name_DBT, obj); + if (ji == NULL) + return (NULL); + else + return (&ji->dbt); +} + +DBT_JAVAINFO *get_DBT_JAVAINFO(JNIEnv *jnienv, jobject obj) +{ + return ((DBT_JAVAINFO *)get_private_dbobj(jnienv, name_DBT, obj)); +} + +/* Convert a C pointer to the various Java objects they represent. + */ +jobject get_DbBtreeStat(JNIEnv *jnienv, DB_BTREE_STAT *dbobj) +{ + return (convert_object(jnienv, name_DB_BTREE_STAT, dbobj)); +} + +jobject get_Dbc(JNIEnv *jnienv, DBC *dbobj) +{ + return (convert_object(jnienv, name_DBC, dbobj)); +} + +jobject get_DbHashStat(JNIEnv *jnienv, DB_HASH_STAT *dbobj) +{ + return (convert_object(jnienv, name_DB_HASH_STAT, dbobj)); +} + +jobject get_DbLogStat(JNIEnv *jnienv, DB_LOG_STAT *dbobj) +{ + return (convert_object(jnienv, name_DB_LOG_STAT, dbobj)); +} + +/* LSNs are different since they are really normally + * treated as by-value objects. We actually create + * a pointer to the LSN and store that, deleting it + * when the LSN is GC'd. + */ +jobject get_DbLsn(JNIEnv *jnienv, DB_LSN dbobj) +{ + DB_LSN *lsnp = (DB_LSN *)malloc(sizeof(DB_LSN)); + memset(lsnp, 0, sizeof(DB_LSN)); + *lsnp = dbobj; + return (convert_object(jnienv, name_DB_LSN, lsnp)); +} + +jobject get_Dbt(JNIEnv *jnienv, DBT *dbt) +{ + return (convert_object(jnienv, name_DBT, dbt)); +} + +jobject get_DbMpoolFStat(JNIEnv *jnienv, DB_MPOOL_FSTAT *dbobj) +{ + return (convert_object(jnienv, name_DB_MPOOL_FSTAT, dbobj)); +} + +jobject get_DbMpoolStat(JNIEnv *jnienv, DB_MPOOL_STAT *dbobj) +{ + return (convert_object(jnienv, name_DB_MPOOL_STAT, dbobj)); +} + +jobject get_DbQueueStat(JNIEnv *jnienv, DB_QUEUE_STAT *dbobj) +{ + return (convert_object(jnienv, name_DB_QUEUE_STAT, dbobj)); +} + +jobject get_DbTxn(JNIEnv *jnienv, DB_TXN *dbobj) +{ + return (convert_object(jnienv, name_DB_TXN, dbobj)); +} + +jobject get_DbTxnStat(JNIEnv *jnienv, DB_TXN_STAT *dbobj) +{ + return (convert_object(jnienv, name_DB_TXN_STAT, dbobj)); +} diff --git a/bdb/libdb_java/java_util.h b/bdb/libdb_java/java_util.h new file mode 100644 index 00000000000..eb47dc67629 --- /dev/null +++ b/bdb/libdb_java/java_util.h @@ -0,0 +1,359 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 1998, 1999, 2000 + * Sleepycat Software. All rights reserved. + * + * $Id: java_util.h,v 11.22 2001/01/11 18:19:53 bostic Exp $ + */ + +#ifndef _JAVA_UTIL_H_ +#define _JAVA_UTIL_H_ + +#ifdef _MSC_VER + +/* These are level 4 warnings that are explicitly disabled. + * With Visual C++, by default you do not see above level 3 unless + * you use /W4. But we like to compile with the highest level + * warnings to catch other errors. + * + * 4201: nameless struct/union + * triggered by standard include file <winnt.h> + * + * 4244: '=' : convert from '__int64' to 'unsigned int', possible loss of data + * results from making size_t data members correspond to jlongs + * + * 4514: unreferenced inline function has been removed + * jni.h defines methods that are not called + * + * 4127: conditional expression is constant + * occurs because of arg in JAVADB_RW_ACCESS_STRING macro + */ +#pragma warning(disable: 4244 4201 4514 4127) + +#endif + +#include "db_config.h" +#include "db.h" +#include "java_info.h" +#include "java_locked.h" +#include <jni.h> +#include <string.h> /* needed for memset */ + +#define DB_PACKAGE_NAME "com/sleepycat/db/" + +/* Union to convert longs to pointers (see {get,set}_private_dbobj). + */ +typedef union { + jlong java_long; + void *ptr; +} long_to_ptr; + +/**************************************************************** + * + * Utility functions and definitions used by "glue" functions. + * + */ + +#define NOT_IMPLEMENTED(str) \ + report_exception(jnienv, str /*concatenate*/ ": not implemented", 0) + +/* Get, delete a global reference. + * Making this operation a function call allows for + * easier tracking for debugging. Global references + * are mostly grabbed at 'open' and 'close' points, + * so there shouldn't be a big performance hit. + * + * Macro-izing this makes it easier to add debugging code + * to track unreleased references. + */ +#ifdef DBJAVA_DEBUG +#include <unistd.h> +static void wrdebug(const char *str) +{ + write(2, str, strlen(str)); + write(2, "\n", 1); +} + +static jobject debug_new_global_ref(JNIEnv *jnienv, jobject obj, const char *s) +{ + wrdebug(s); + return (*jnienv)->NewGlobalRef(jnienv, obj); +} + +static void debug_delete_global_ref(JNIEnv *jnienv, jobject obj, const char *s) +{ + wrdebug(s); + (*jnienv)->DeleteGlobalRef(jnienv, obj); +} + +#define NEW_GLOBAL_REF(jnienv, obj) \ + debug_new_global_ref(jnienv, obj, "+Ref: " #obj) +#define DELETE_GLOBAL_REF(jnienv, obj) \ + debug_delete_global_ref(jnienv, obj, "-Ref: " #obj) +#else +#define NEW_GLOBAL_REF(jnienv, obj) (*jnienv)->NewGlobalRef(jnienv, obj) +#define DELETE_GLOBAL_REF(jnienv, obj) (*jnienv)->DeleteGlobalRef(jnienv, obj) +#define wrdebug(x) +#endif + +/* Get the private data from a Db* object that points back to a C DB_* object. + * The private data is stored in the object as a Java long (64 bits), + * which is long enough to store a pointer on current architectures. + */ +void *get_private_dbobj(JNIEnv *jnienv, const char *classname, + jobject obj); + +/* Set the private data in a Db* object that points back to a C DB_* object. + * The private data is stored in the object as a Java long (64 bits), + * which is long enough to store a pointer on current architectures. + */ +void set_private_dbobj(JNIEnv *jnienv, const char *classname, + jobject obj, void *value); + +/* Get the private data in a Db/DbEnv object that holds additional 'side data'. + * The private data is stored in the object as a Java long (64 bits), + * which is long enough to store a pointer on current architectures. + */ +void *get_private_info(JNIEnv *jnienv, const char *classname, + jobject obj); + +/* Set the private data in a Db/DbEnv object that holds additional 'side data'. + * The private data is stored in the object as a Java long (64 bits), + * which is long enough to store a pointer on current architectures. + */ +void set_private_info(JNIEnv *jnienv, const char *classname, + jobject obj, void *value); + +/* + * Given a non-qualified name (e.g. "foo"), get the class handl + * for the fully qualified name (e.g. "com.sleepycat.db.foo") + */ +jclass get_class(JNIEnv *jnienv, const char *classname); + +/* Set an individual field in a Db* object. + * The field must be a DB object type. + */ +void set_object_field(JNIEnv *jnienv, jclass class_of_this, + jobject jthis, const char *object_classname, + const char *name_of_field, jobject obj); + +/* Set an individual field in a Db* object. + * The field must be an integer type. + */ +void set_int_field(JNIEnv *jnienv, jclass class_of_this, + jobject jthis, const char *name_of_field, jint value); + +/* Set an individual field in a Db* object. + * The field must be an integer type. + */ +void set_long_field(JNIEnv *jnienv, jclass class_of_this, + jobject jthis, const char *name_of_field, jlong value); + +/* Set an individual field in a Db* object. + * The field must be an DbLsn type. + */ +void set_lsn_field(JNIEnv *jnienv, jclass class_of_this, + jobject jthis, const char *name_of_field, DB_LSN value); + +/* Values of expect_mask + */ +static const int EXCEPTION_FILE_NOT_FOUND = 0x0001; + +/* Report an exception back to the java side. + */ +void report_exception(JNIEnv *jnienv, const char *text, int err, + unsigned long expect_mask); + +/* Report an error via the errcall mechanism. + */ +void report_errcall(JNIEnv *jnienv, jobject errcall, + jstring prefix, const char *message); + +/* If the object is null, report an exception and return false (0), + * otherwise return true (1). + */ +int verify_non_null(JNIEnv *jnienv, void *obj); + +/* If the error code is non-zero, report an exception and return false (0), + * otherwise return true (1). + */ +int verify_return(JNIEnv *jnienv, int err, unsigned long expect_mask); + +/* Create an object of the given class, calling its default constructor. + */ +jobject create_default_object(JNIEnv *jnienv, const char *class_name); + +/* Convert an DB object to a Java encapsulation of that object. + * Note: This implementation creates a new Java object on each call, + * so it is generally useful when a new DB object has just been created. + */ +jobject convert_object(JNIEnv *jnienv, const char *class_name, void *dbobj); + +/* Create a copy of the string + */ +char *dup_string(const char *str); + +/* Create a malloc'ed copy of the java string. + * Caller must free it. + */ +char *get_c_string(JNIEnv *jnienv, jstring jstr); + +/* Create a java string from the given string + */ +jstring get_java_string(JNIEnv *jnienv, const char* string); + +/* Convert a java object to the various C pointers they represent. + */ +DB *get_DB (JNIEnv *jnienv, jobject obj); +DB_BTREE_STAT *get_DB_BTREE_STAT (JNIEnv *jnienv, jobject obj); +DBC *get_DBC (JNIEnv *jnienv, jobject obj); +DB_ENV *get_DB_ENV (JNIEnv *jnienv, jobject obj); +DB_ENV_JAVAINFO *get_DB_ENV_JAVAINFO (JNIEnv *jnienv, jobject obj); +DB_HASH_STAT *get_DB_HASH_STAT (JNIEnv *jnienv, jobject obj); +DB_JAVAINFO *get_DB_JAVAINFO (JNIEnv *jnienv, jobject obj); +DB_LOCK *get_DB_LOCK (JNIEnv *jnienv, jobject obj); +DB_LOG_STAT *get_DB_LOG_STAT (JNIEnv *jnienv, jobject obj); +DB_LSN *get_DB_LSN (JNIEnv *jnienv, jobject obj); +DB_MPOOL_FSTAT *get_DB_MPOOL_FSTAT(JNIEnv *jnienv, jobject obj); +DB_MPOOL_STAT *get_DB_MPOOL_STAT (JNIEnv *jnienv, jobject obj); +DB_QUEUE_STAT *get_DB_QUEUE_STAT (JNIEnv *jnienv, jobject obj); +DB_TXN *get_DB_TXN (JNIEnv *jnienv, jobject obj); +DB_TXN_STAT *get_DB_TXN_STAT (JNIEnv *jnienv, jobject obj); +DBT *get_DBT (JNIEnv *jnienv, jobject obj); +DBT_JAVAINFO *get_DBT_JAVAINFO (JNIEnv *jnienv, jobject obj); + +/* From a C object, create a Java object. + */ +jobject get_DbBtreeStat (JNIEnv *jnienv, DB_BTREE_STAT *dbobj); +jobject get_Dbc (JNIEnv *jnienv, DBC *dbobj); +jobject get_DbHashStat (JNIEnv *jnienv, DB_HASH_STAT *dbobj); +jobject get_DbLogStat (JNIEnv *jnienv, DB_LOG_STAT *dbobj); +jobject get_DbLsn (JNIEnv *jnienv, DB_LSN dbobj); +jobject get_DbMpoolStat (JNIEnv *jnienv, DB_MPOOL_STAT *dbobj); +jobject get_DbMpoolFStat (JNIEnv *jnienv, DB_MPOOL_FSTAT *dbobj); +jobject get_DbQueueStat (JNIEnv *jnienv, DB_QUEUE_STAT *dbobj); +jobject get_Dbt (JNIEnv *jnienv, DBT *dbt); +jobject get_DbTxn (JNIEnv *jnienv, DB_TXN *dbobj); +jobject get_DbTxnStat (JNIEnv *jnienv, DB_TXN_STAT *dbobj); + +/* The java names of DB classes */ +extern const char * const name_DB; +extern const char * const name_DB_BTREE_STAT; +extern const char * const name_DBC; +extern const char * const name_DB_DEADLOCK_EX; +extern const char * const name_DB_ENV; +extern const char * const name_DB_EXCEPTION; +extern const char * const name_DB_HASH_STAT; +extern const char * const name_DB_LOCK; +extern const char * const name_DB_LOCK_STAT; +extern const char * const name_DB_LOG_STAT; +extern const char * const name_DB_LSN; +extern const char * const name_DB_MEMORY_EX; +extern const char * const name_DB_MPOOL_FSTAT; +extern const char * const name_DB_MPOOL_STAT; +extern const char * const name_DB_QUEUE_STAT; +extern const char * const name_DB_RUNRECOVERY_EX; +extern const char * const name_DBT; +extern const char * const name_DB_TXN; +extern const char * const name_DB_TXN_STAT; +extern const char * const name_DB_TXN_STAT_ACTIVE; +extern const char * const name_DbAppendRecno; +extern const char * const name_DbBtreeCompare; +extern const char * const name_DbBtreePrefix; +extern const char * const name_DbDupCompare; +extern const char * const name_DbEnvFeedback; +extern const char * const name_DbErrcall; +extern const char * const name_DbFeedback; +extern const char * const name_DbHash; +extern const char * const name_DbRecoveryInit; +extern const char * const name_DbTxnRecover; + +extern const char * const string_signature; + +#define JAVADB_RO_ACCESS(j_class, j_fieldtype, j_field, c_type, c_field) \ +JNIEXPORT j_fieldtype JNICALL \ + Java_com_sleepycat_db_##j_class##_get_1##j_field \ + (JNIEnv *jnienv, jobject jthis) \ +{ \ + c_type *db_this = get_##c_type(jnienv, jthis); \ + \ + if (verify_non_null(jnienv, db_this)) { \ + return db_this->c_field; \ + } \ + return 0; \ +} + +#define JAVADB_WO_ACCESS(j_class, j_fieldtype, j_field, c_type, c_field) \ +JNIEXPORT void JNICALL \ + Java_com_sleepycat_db_##j_class##_set_1##j_field \ + (JNIEnv *jnienv, jobject jthis, j_fieldtype value) \ +{ \ + c_type *db_this = get_##c_type(jnienv, jthis); \ + \ + if (verify_non_null(jnienv, db_this)) { \ + db_this->c_field = value; \ + } \ +} + +/* This is a variant of the JAVADB_WO_ACCESS macro to define a simple set_ + * method using a C "method" call. These should be used with set_ + * methods that cannot invoke java 'callbacks' (no set_ method currently + * does that). That assumption allows us to optimize (and simplify) + * by not calling API_BEGIN/END macros. + */ +#define JAVADB_WO_ACCESS_METHOD(j_class, j_fieldtype, \ + j_field, c_type, c_field) \ +JNIEXPORT void JNICALL \ + Java_com_sleepycat_db_##j_class##_set_1##j_field \ + (JNIEnv *jnienv, jobject jthis, j_fieldtype value) \ +{ \ + c_type *db_this; \ + int err; \ + \ + db_this = get_##c_type(jnienv, jthis); \ + if (verify_non_null(jnienv, db_this)) { \ + err = db_this->set_##c_field(db_this, value); \ + verify_return(jnienv, err, 0); \ + } \ +} + +#define JAVADB_RW_ACCESS(j_class, j_fieldtype, j_field, c_type, c_field) \ + JAVADB_RO_ACCESS(j_class, j_fieldtype, j_field, c_type, c_field) \ + JAVADB_WO_ACCESS(j_class, j_fieldtype, j_field, c_type, c_field) + +#define JAVADB_WO_ACCESS_STRING(j_class, j_field, c_type, c_field) \ +JNIEXPORT void JNICALL \ + Java_com_sleepycat_db_##j_class##_set_1##j_field \ + (JNIEnv *jnienv, jobject jthis, jstring value) \ +{ \ + c_type *db_this; \ + int err; \ + \ + db_this = get_##c_type(jnienv, jthis); \ + if (verify_non_null(jnienv, db_this)) { \ + err = db_this->set_##c_field(db_this, \ + (*jnienv)->GetStringUTFChars(jnienv, value, NULL)); \ + verify_return(jnienv, err, 0); \ + } \ +} + +#define JAVADB_API_BEGIN(db, jthis) \ + if ((db) != NULL) \ + ((DB_JAVAINFO*)(db)->cj_internal)->jdbref_ = \ + ((DB_ENV_JAVAINFO*)((db)->dbenv->cj_internal))->jdbref_ = (jthis) + +#define JAVADB_API_END(db) \ + if ((db) != NULL) \ + ((DB_JAVAINFO*)(db)->cj_internal)->jdbref_ = \ + ((DB_ENV_JAVAINFO*)((db)->dbenv->cj_internal))->jdbref_ = 0 + +#define JAVADB_ENV_API_BEGIN(dbenv, jthis) \ + if ((dbenv) != NULL) \ + ((DB_ENV_JAVAINFO*)((dbenv)->cj_internal))->jenvref_ = (jthis) + +#define JAVADB_ENV_API_END(dbenv) \ + if ((dbenv) != NULL) \ + ((DB_ENV_JAVAINFO*)((dbenv)->cj_internal))->jenvref_ = 0 + +#endif /* !_JAVA_UTIL_H_ */ |