Logo Search packages:      
Sourcecode: db4.1 version File versions

java_util.c

/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 1997-2002
 *    Sleepycat Software.  All rights reserved.
 */
#include "db_config.h"

#ifndef lint
static 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
#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_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);
}

/*
 * 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;

      if ((errcall_class = get_class(jnienv, name_DbErrcall)) == NULL)
            return;     /* An exception has been posted. */
      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);
}

/*
 * Verify that there was no memory error due to undersized Dbt.
 * If there is report a DbMemoryException, with the Dbt attached
 * and return false (0), otherwise return true (1).
 */
int verify_dbt(JNIEnv *jnienv, int err, LOCKED_DBT *ldbt)
{
      DBT *dbt;
      jobject exception;
      jstring text;
      jclass dbexcept;
      jmethodID mid;

      if (err != ENOMEM)
            return (1);

      dbt = &ldbt->javainfo->dbt;
      if (!F_ISSET(dbt, DB_DBT_USERMEM) || dbt->size <= dbt->ulen)
            return (1);

      /* Create/throw an exception of type DbMemoryException */
      if ((dbexcept = get_class(jnienv, name_DB_MEMORY_EX)) == NULL)
            return (1); /* An exception has been posted. */
      text = get_java_string(jnienv,
                         "Dbt not large enough for available data");
      exception = create_exception(jnienv, text, ENOMEM, dbexcept);

      /* Attach the dbt to the exception */
      mid = (*jnienv)->GetMethodID(jnienv, dbexcept, "set_dbt",
                             "(L" DB_PACKAGE_NAME "Dbt;)V");
      (*jnienv)->CallVoidMethod(jnienv, exception, mid, ldbt->jdbt);
      (*jnienv)->Throw(jnienv, exception);
      return (0);
}

/*
 * Create an object of the given class, calling its default constructor.
 */
jobject create_default_object(JNIEnv *jnienv, const char *class_name)
{
      jmethodID id;
      jclass dbclass;

      if ((dbclass = get_class(jnienv, class_name)) == NULL)
            return (NULL);    /* An exception has been posted. */
      id = (*jnienv)->GetMethodID(jnienv, dbclass, "<init>", "()V");
      return ((*jnienv)->NewObject(jnienv, dbclass, id));
}

/*
 * 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;
      int err;

      len = strlen(str) + 1;
      if ((err = __os_malloc(NULL, sizeof(char)*len, &retval)) != 0)
            return (NULL);
      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 copy of the java string using __os_malloc.
 * Caller must free it.
 */
char *get_c_string(JNIEnv *jnienv, jstring jstr)
{
      const char *utf;
      char *retval;

      utf = (*jnienv)->GetStringUTFChars(jnienv, jstr, NULL);
      retval = dup_string(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_LOGC *get_DB_LOGC(JNIEnv *jnienv, jobject obj)
{
      return ((DB_LOGC *)get_private_dbobj(jnienv, name_DB_LOGC, 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, /* DbLsn */ jobject obj) {
      /*
       * DbLsns that are created from within java (new DbLsn()) rather
       * than from within C (get_DbLsn()) may not have a "private" DB_LSN
       * structure allocated for them yet.  We can't do this in the
       * actual constructor (init_lsn()), because there's no way to pass
       * in an initializing value in, and because the get_DbLsn()/
       * convert_object() code path needs a copy of the pointer before
       * the constructor gets called.  Thus, get_DbLsn() allocates and
       * fills a DB_LSN for the object it's about to create.
       *
       * Since "new DbLsn()" may reasonably be passed as an argument to
       * functions such as DbEnv.log_put(), though, we need to make sure
       * that DB_LSN's get allocated when the object was created from
       * Java, too.  Here, we lazily allocate a new private DB_LSN if
       * and only if it turns out that we don't already have one.
       *
       * The only exception is if the DbLsn object is a Java null
       * (in which case the jobject will also be NULL). Then a NULL
       * DB_LSN is legitimate.
       */
      DB_LSN *lsnp;
      int err;

      if (obj == NULL)
            return (NULL);

      lsnp = (DB_LSN *)get_private_dbobj(jnienv, name_DB_LSN, obj);
      if (lsnp == NULL) {
            if ((err = __os_malloc(NULL, sizeof(DB_LSN), &lsnp)) != 0)
                  return (NULL);
            memset(lsnp, 0, sizeof(DB_LSN));
            set_private_dbobj(jnienv, name_DB_LSN, obj, lsnp);
      }

      return (lsnp);
}

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_DbLogc(JNIEnv *jnienv, DB_LOGC *dbobj)
{
      return (convert_object(jnienv, name_DB_LOGC, 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;
      int err;

      if ((err = __os_malloc(NULL, sizeof(DB_LSN), &lsnp)) != 0)
            return (NULL);

      memset(lsnp, 0, sizeof(DB_LSN));
      *lsnp = dbobj;
      return (convert_object(jnienv, name_DB_LSN, lsnp));
}

/*
 * Shared code for get_Dbt and get_const_Dbt.
 *
 * XXX
 * Currently we make no distinction in implementation of these
 * two kinds of Dbts, although in the future we may want to.
 * (It's probably easier to make the optimizations listed below
 * with readonly Dbts).
 *
 * Dbt's created via this function are only used for a short lifetime,
 * during callback functions.  In the future, we should consider taking
 * advantage of this by having a pool of Dbt objects instead of creating
 * new ones each time.   Because of multithreading, we may need an
 * arbitrary number.  We might also have sharing of the byte arrays
 * used by the Dbts.
 */
static jobject get_Dbt_shared(JNIEnv *jnienv, const DBT *dbt, int readonly,
                        DBT_JAVAINFO **ret_info)
{
      jobject jdbt;
      DBT_JAVAINFO *dbtji;

      COMPQUIET(readonly, 0);

      /* A NULL DBT should become a null Dbt. */
      if (dbt == NULL)
            return (NULL);

      /*
       * Note that a side effect of creating a Dbt object
       * is the creation of the attached DBT_JAVAINFO object
       * (see the native implementation of Dbt.init())
       * A DBT_JAVAINFO object contains its own DBT.
       */
      jdbt = create_default_object(jnienv, name_DBT);
      dbtji = get_DBT_JAVAINFO(jnienv, jdbt);
      memcpy(&dbtji->dbt, dbt, sizeof(DBT));

      /*
       * Set the boolean indicator so that the Java side knows to
       * call back when it wants to look at the array.  This avoids
       * needlessly creating/copying arrays that may never be looked at.
       */
      (*jnienv)->SetBooleanField(jnienv, jdbt, fid_Dbt_must_create_data, 1);
      (*jnienv)->SetIntField(jnienv, jdbt, fid_Dbt_size, dbt->size);

      if (ret_info != NULL)
          *ret_info = dbtji;
      return (jdbt);
}

/*
 * Get a writeable Dbt.
 *
 * Currently we're sharing code with get_const_Dbt.
 * It really shouldn't be this way, we have a DBT that we can
 * change, and have some mechanism for copying back
 * any changes to the original DBT.
 */
jobject get_Dbt(JNIEnv *jnienv, DBT *dbt,
            DBT_JAVAINFO **ret_info)
{
      return (get_Dbt_shared(jnienv, dbt, 0, ret_info));
}

/*
 * Get a Dbt that we promise not to change, or at least
 * if there are changes, they don't matter and won't get
 * seen by anyone.
 */
jobject get_const_Dbt(JNIEnv *jnienv, const DBT *dbt,
                  DBT_JAVAINFO **ret_info)
{
      return (get_Dbt_shared(jnienv, dbt, 1, ret_info));
}

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));
}

Generated by  Doxygen 1.6.0   Back to index