📄 java_util.c
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1997-2002 * Sleepycat Software. All rights reserved. */#include "db_config.h"#ifndef lintstatic const char revid[] = "$Id: java_util.c,v 11.49 2002/09/13 03:09:30 mjc Exp $";#endif /* not lint */#include <jni.h>#include <errno.h>#include "db_int.h"#include "java_util.h"#ifdef DB_WIN32#define sys_errlist _sys_errlist#define sys_nerr _sys_nerr#endifconst 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_LOCKNOTGRANTED_EX = "DbLockNotGrantedException";const char * const name_DB_LOGC = "DbLogc";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_PREPLIST = "DbPreplist";const char * const name_DB_QUEUE_STAT = "DbQueueStat";const char * const name_DB_REP_STAT = "DbRepStat";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_DB_UTIL = "DbUtil";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_DbLockRequest = "DbLockRequest";const char * const name_DbFeedback = "DbFeedback";const char * const name_DbRecoveryInit = "DbRecoveryInit";const char * const name_DbRepTransport = "DbRepTransport";const char * const name_DbSecondaryKeyCreate = "DbSecondaryKeyCreate";const char * const name_DbTxnRecover = "DbTxnRecover";const char * const name_RepElectResult = "DbEnv$RepElectResult";const char * const name_RepProcessMessage = "DbEnv$RepProcessMessage";const char * const string_signature = "Ljava/lang/String;";jfieldID fid_Dbt_data;jfieldID fid_Dbt_offset;jfieldID fid_Dbt_size;jfieldID fid_Dbt_ulen;jfieldID fid_Dbt_dlen;jfieldID fid_Dbt_doff;jfieldID fid_Dbt_flags;jfieldID fid_Dbt_private_dbobj_;jfieldID fid_Dbt_must_create_data;jfieldID fid_DbLockRequest_op;jfieldID fid_DbLockRequest_mode;jfieldID fid_DbLockRequest_timeout;jfieldID fid_DbLockRequest_obj;jfieldID fid_DbLockRequest_lock;jfieldID fid_RepProcessMessage_envid;/**************************************************************** * * Utility functions used by "glue" functions. *//* * Do any one time initialization, especially initializing any * unchanging methodIds, fieldIds, etc. */void one_time_init(JNIEnv *jnienv){ jclass cl; if ((cl = get_class(jnienv, name_DBT)) == NULL) return; /* An exception has been posted. */ fid_Dbt_data = (*jnienv)->GetFieldID(jnienv, cl, "data", "[B"); fid_Dbt_offset = (*jnienv)->GetFieldID(jnienv, cl, "offset", "I"); fid_Dbt_size = (*jnienv)->GetFieldID(jnienv, cl, "size", "I"); fid_Dbt_ulen = (*jnienv)->GetFieldID(jnienv, cl, "ulen", "I"); fid_Dbt_dlen = (*jnienv)->GetFieldID(jnienv, cl, "dlen", "I"); fid_Dbt_doff = (*jnienv)->GetFieldID(jnienv, cl, "doff", "I"); fid_Dbt_flags = (*jnienv)->GetFieldID(jnienv, cl, "flags", "I"); fid_Dbt_must_create_data = (*jnienv)->GetFieldID(jnienv, cl, "must_create_data", "Z"); fid_Dbt_private_dbobj_ = (*jnienv)->GetFieldID(jnienv, cl, "private_dbobj_", "J"); if ((cl = get_class(jnienv, name_DbLockRequest)) == NULL) return; /* An exception has been posted. */ fid_DbLockRequest_op = (*jnienv)->GetFieldID(jnienv, cl, "op", "I"); fid_DbLockRequest_mode = (*jnienv)->GetFieldID(jnienv, cl, "mode", "I"); fid_DbLockRequest_timeout = (*jnienv)->GetFieldID(jnienv, cl, "timeout", "I"); fid_DbLockRequest_obj = (*jnienv)->GetFieldID(jnienv, cl, "obj", "Lcom/sleepycat/db/Dbt;"); fid_DbLockRequest_lock = (*jnienv)->GetFieldID(jnienv, cl, "lock", "Lcom/sleepycat/db/DbLock;"); if ((cl = get_class(jnienv, name_RepProcessMessage)) == NULL) return; /* An exception has been posted. */ fid_RepProcessMessage_envid = (*jnienv)->GetFieldID(jnienv, cl, "envid", "I");}/* * 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); if ((dbClass = get_class(jnienv, classname)) == NULL) return (NULL); /* An exception has been posted. */ 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; if ((dbClass = get_class(jnienv, classname)) == NULL) return; /* An exception has been posted. */ 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 (NULL); if ((dbClass = get_class(jnienv, classname)) == NULL) return (NULL); /* An exception has been posted. */ 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; if ((dbClass = get_class(jnienv, classname)) == NULL) return; /* An exception has been posted. */ 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]; (void)snprintf(fullname, sizeof(fullname), "%s%s", DB_PACKAGE_NAME, classname); return ((*jnienv)->FindClass(jnienv, fullname));}/* * Given a fully qualified name (e.g. "java.util.Hashtable") * return the jclass object. If it can't be found, an * exception is raised and NULL is return. * This is appropriate to be used for classes that may * not be present. */jclass get_fully_qualified_class(JNIEnv *jnienv, const char *classname){ jclass result; result = ((*jnienv)->FindClass(jnienv, classname)); if (result == NULL) { jclass cnfe; char message[1024]; cnfe = (*jnienv)->FindClass(jnienv, "java/lang/ClassNotFoundException"); strncpy(message, classname, sizeof(message)); strncat(message, ": class not found", sizeof(message)); (*jnienv)->ThrowNew(jnienv, cnfe, message); } return (result);}/* * 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; (void)snprintf(signature, sizeof(signature), "L%s%s;", DB_PACKAGE_NAME, object_classname); 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; jthrowable obj; textString = NULL; dbexcept = NULL; javaexcept = 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 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) { javaexcept = (*jnienv)->FindClass(jnienv, "java/io/FileNotFoundException"); } else { char errstr[1024]; snprintf(errstr, sizeof(errstr), "internal error: unexpected errno: %s", text); textString = get_java_string(jnienv, errstr); dbexcept = get_class(jnienv, name_DB_EXCEPTION); } 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); if ((obj = create_exception(jnienv, textString, err, dbexcept)) != NULL) (*jnienv)->Throw(jnienv, obj); /* Otherwise, an exception has been posted. */ } else if (javaexcept != NULL) (*jnienv)->ThrowNew(jnienv, javaexcept, text); else fprintf(stderr, "report_exception: failed to create an exception\n");}/* * Report an exception back to the java side, for the specific * case of DB_LOCK_NOTGRANTED, as more things are added to the * constructor of this type of exception. */void report_notgranted_exception(JNIEnv *jnienv, const char *text, db_lockop_t op, db_lockmode_t mode, jobject jdbt, jobject jlock, int index){ jstring textString; jclass dbexcept; jthrowable obj; jmethodID mid; if ((dbexcept = get_class(jnienv, name_DB_LOCKNOTGRANTED_EX)) == NULL) return; /* An exception has been posted. */ textString = get_java_string(jnienv, text); mid = (*jnienv)->GetMethodID(jnienv, dbexcept, "<init>", "(Ljava/lang/String;II" "Lcom/sleepycat/db/Dbt;" "Lcom/sleepycat/db/DbLock;I)V"); if ((obj = (jthrowable)(*jnienv)->NewObject(jnienv, dbexcept, mid, textString, op, mode, jdbt, jlock, index)) != NULL) (*jnienv)->Throw(jnienv, obj); else fprintf(stderr, "report_notgranted_exception: failed to create an exception\n");}/* * Create an exception object and return it. * The given class must have a constructor that has a * constructor with args (java.lang.String text, int errno); * DbException and its subclasses fit this bill. */jobject create_exception(JNIEnv *jnienv, jstring text, int err, jclass dbexcept){ jthrowable obj; jmethodID mid; mid = (*jnienv)->GetMethodID(jnienv, dbexcept, "<init>", "(Ljava/lang/String;I)V"); if (mid != NULL) obj = (jthrowable)(*jnienv)->NewObject(jnienv, dbexcept, mid, text, err); else { fprintf(stderr, "Cannot get exception init method ID!\n"); obj = NULL; } return (obj);}/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -