java_util.c
Upload User: tsgydb
Upload Date: 2007-04-14
Package Size: 10674k
Code Size: 16k
Category:

MySQL

Development Platform:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1997, 1998, 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: java_util.c,v 11.17 2000/10/28 13:09:39 dda Exp $";
  10. #endif /* not lint */
  11. #include <jni.h>
  12. #include <errno.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include "db.h"
  16. #include "java_util.h"
  17. #ifdef DB_WIN32
  18. #define sys_errlist _sys_errlist
  19. #define sys_nerr _sys_nerr
  20. #endif
  21. const char * const name_DB                 = "Db";
  22. const char * const name_DB_BTREE_STAT      = "DbBtreeStat";
  23. const char * const name_DBC                = "Dbc";
  24. const char * const name_DB_DEADLOCK_EX     = "DbDeadlockException";
  25. const char * const name_DB_ENV             = "DbEnv";
  26. const char * const name_DB_EXCEPTION       = "DbException";
  27. const char * const name_DB_HASH_STAT       = "DbHashStat";
  28. const char * const name_DB_LOCK            = "DbLock";
  29. const char * const name_DB_LOCK_STAT       = "DbLockStat";
  30. const char * const name_DB_LOG_STAT        = "DbLogStat";
  31. const char * const name_DB_LSN             = "DbLsn";
  32. const char * const name_DB_MEMORY_EX       = "DbMemoryException";
  33. const char * const name_DB_MPOOL_FSTAT     = "DbMpoolFStat";
  34. const char * const name_DB_MPOOL_STAT      = "DbMpoolStat";
  35. const char * const name_DB_QUEUE_STAT      = "DbQueueStat";
  36. const char * const name_DB_RUNRECOVERY_EX  = "DbRunRecoveryException";
  37. const char * const name_DBT                = "Dbt";
  38. const char * const name_DB_TXN             = "DbTxn";
  39. const char * const name_DB_TXN_STAT        = "DbTxnStat";
  40. const char * const name_DB_TXN_STAT_ACTIVE = "DbTxnStat$Active";
  41. const char * const name_DbAppendRecno      = "DbAppendRecno";
  42. const char * const name_DbBtreeCompare     = "DbBtreeCompare";
  43. const char * const name_DbBtreePrefix      = "DbBtreePrefix";
  44. const char * const name_DbDupCompare       = "DbDupCompare";
  45. const char * const name_DbEnvFeedback      = "DbEnvFeedback";
  46. const char * const name_DbErrcall          = "DbErrcall";
  47. const char * const name_DbHash             = "DbHash";
  48. const char * const name_DbFeedback         = "DbFeedback";
  49. const char * const name_DbRecoveryInit     = "DbRecoveryInit";
  50. const char * const name_DbTxnRecover       = "DbTxnRecover";
  51. const char * const string_signature    = "Ljava/lang/String;";
  52. /****************************************************************
  53.  *
  54.  * Utility functions used by "glue" functions.
  55.  *
  56.  */
  57. /* Get the private data from a Db* object that points back to a C DB_* object.
  58.  * The private data is stored in the object as a Java long (64 bits),
  59.  * which is long enough to store a pointer on current architectures.
  60.  */
  61. void *get_private_dbobj(JNIEnv *jnienv, const char *classname,
  62.        jobject obj)
  63. {
  64. jclass dbClass;
  65. jfieldID id;
  66. long_to_ptr lp;
  67. if (!obj)
  68. return (0);
  69. dbClass = get_class(jnienv, classname);
  70. id = (*jnienv)->GetFieldID(jnienv, dbClass, "private_dbobj_", "J");
  71. lp.java_long = (*jnienv)->GetLongField(jnienv, obj, id);
  72. return (lp.ptr);
  73. }
  74. /* Set the private data in a Db* object that points back to a C DB_* object.
  75.  * The private data is stored in the object as a Java long (64 bits),
  76.  * which is long enough to store a pointer on current architectures.
  77.  */
  78. void set_private_dbobj(JNIEnv *jnienv, const char *classname,
  79.       jobject obj, void *value)
  80. {
  81. long_to_ptr lp;
  82. jclass dbClass;
  83. jfieldID id;
  84. lp.java_long = 0; /* no junk in case sizes mismatch */
  85. lp.ptr = value;
  86. dbClass = get_class(jnienv, classname);
  87. id = (*jnienv)->GetFieldID(jnienv, dbClass, "private_dbobj_", "J");
  88. (*jnienv)->SetLongField(jnienv, obj, id, lp.java_long);
  89. }
  90. /* Get the private data in a Db/DbEnv object that holds additional 'side data'.
  91.  * The private data is stored in the object as a Java long (64 bits),
  92.  * which is long enough to store a pointer on current architectures.
  93.  */
  94. void *get_private_info(JNIEnv *jnienv, const char *classname,
  95.        jobject obj)
  96. {
  97. jclass dbClass;
  98. jfieldID id;
  99. long_to_ptr lp;
  100. if (!obj)
  101. return (0);
  102. dbClass = get_class(jnienv, classname);
  103. id = (*jnienv)->GetFieldID(jnienv, dbClass, "private_info_", "J");
  104. lp.java_long = (*jnienv)->GetLongField(jnienv, obj, id);
  105. return (lp.ptr);
  106. }
  107. /* Set the private data in a Db/DbEnv object that holds additional 'side data'.
  108.  * The private data is stored in the object as a Java long (64 bits),
  109.  * which is long enough to store a pointer on current architectures.
  110.  */
  111. void set_private_info(JNIEnv *jnienv, const char *classname,
  112.       jobject obj, void *value)
  113. {
  114. long_to_ptr lp;
  115. jclass dbClass;
  116. jfieldID id;
  117. lp.java_long = 0; /* no junk in case sizes mismatch */
  118. lp.ptr = value;
  119. dbClass = get_class(jnienv, classname);
  120. id = (*jnienv)->GetFieldID(jnienv, dbClass, "private_info_", "J");
  121. (*jnienv)->SetLongField(jnienv, obj, id, lp.java_long);
  122. }
  123. /*
  124.  * Given a non-qualified name (e.g. "foo"), get the class handle
  125.  * for the fully qualified name (e.g. "com.sleepycat.db.foo")
  126.  */
  127. jclass get_class(JNIEnv *jnienv, const char *classname)
  128. {
  129. /* Note: PERFORMANCE: It should be possible to cache jclass's.
  130.  * If we do a NewGlobalRef on each one, we can keep them
  131.  * around in a table.  A jclass is a jobject, and
  132.  * since NewGlobalRef returns a jobject, it isn't
  133.  * technically right, but it would likely work with
  134.  * most implementations.  Possibly make it configurable.
  135.  */
  136. char fullname[128] = DB_PACKAGE_NAME;
  137. strncat(fullname, classname, sizeof(fullname));
  138. return ((*jnienv)->FindClass(jnienv, fullname));
  139. }
  140. /* Set an individual field in a Db* object.
  141.  * The field must be a DB object type.
  142.  */
  143. void set_object_field(JNIEnv *jnienv, jclass class_of_this,
  144.       jobject jthis, const char *object_classname,
  145.       const char *name_of_field, jobject obj)
  146. {
  147. char signature[512];
  148. jfieldID id;
  149. strncpy(signature, "L", sizeof(signature));
  150. strncat(signature, DB_PACKAGE_NAME, sizeof(signature));
  151. strncat(signature, object_classname, sizeof(signature));
  152. strncat(signature, ";", sizeof(signature));
  153. id  = (*jnienv)->GetFieldID(jnienv, class_of_this, name_of_field, signature);
  154. (*jnienv)->SetObjectField(jnienv, jthis, id, obj);
  155. }
  156. /* Set an individual field in a Db* object.
  157.  * The field must be an integer type.
  158.  */
  159. void set_int_field(JNIEnv *jnienv, jclass class_of_this,
  160.    jobject jthis, const char *name_of_field, jint value)
  161. {
  162. jfieldID id  = (*jnienv)->GetFieldID(jnienv, class_of_this, name_of_field, "I");
  163. (*jnienv)->SetIntField(jnienv, jthis, id, value);
  164. }
  165. /* Set an individual field in a Db* object.
  166.  * The field must be an integer type.
  167.  */
  168. void set_long_field(JNIEnv *jnienv, jclass class_of_this,
  169.     jobject jthis, const char *name_of_field, jlong value)
  170. {
  171. jfieldID id  = (*jnienv)->GetFieldID(jnienv, class_of_this, name_of_field, "J");
  172. (*jnienv)->SetLongField(jnienv, jthis, id, value);
  173. }
  174. /* Set an individual field in a Db* object.
  175.  * The field must be an integer type.
  176.  */
  177. void set_lsn_field(JNIEnv *jnienv, jclass class_of_this,
  178.    jobject jthis, const char *name_of_field, DB_LSN value)
  179. {
  180. set_object_field(jnienv, class_of_this, jthis, name_DB_LSN,
  181.  name_of_field, get_DbLsn(jnienv, value));
  182. }
  183. /* Report an exception back to the java side.
  184.  */
  185. void report_exception(JNIEnv *jnienv, const char *text, int err,
  186.       unsigned long expect_mask)
  187. {
  188. jstring textString;
  189. jclass dbexcept;
  190. jclass javaexcept;
  191. jmethodID constructId;
  192. jthrowable obj;
  193. textString = NULL;
  194. dbexcept = NULL;
  195. javaexcept = NULL;
  196. constructId = NULL;
  197. obj = NULL;
  198. switch (err) {
  199. /* DB_JAVA_CALLBACK is returned by dbji_call_append_recno()
  200.  * (the append_recno callback) when the Java version of the
  201.  * callback has thrown an exception, and we want to pass the
  202.  * exception on.  The exception has already been thrown, we
  203.  * don't want to throw a new one.
  204.  */
  205. case DB_JAVA_CALLBACK:
  206. break;
  207. case ENOMEM:
  208. dbexcept = get_class(jnienv, name_DB_MEMORY_EX);
  209. break;
  210. case ENOENT:
  211. /* In this case there is a corresponding standard java
  212.  * exception type that we'll use.  First we make sure
  213.  * that the calling function expected this kind of error,
  214.  * if not we give an 'internal error' DbException, since
  215.  * we must not throw an exception type that isn't
  216.  * declared in the signature.
  217.  *
  218.  * We'll make this a little more general if/when we add
  219.  * more java standard exceptions.
  220.  */
  221. if ((expect_mask & EXCEPTION_FILE_NOT_FOUND) == 0) {
  222. char errstr[1024];
  223. strncpy(errstr, "internal error: unexpected errno: ",
  224. sizeof(errstr));
  225. strncat(errstr, text, sizeof(errstr));
  226. textString = get_java_string(jnienv, errstr);
  227. dbexcept = get_class(jnienv, name_DB_EXCEPTION);
  228. }
  229. else {
  230. javaexcept =
  231.   (*jnienv)->FindClass(jnienv, "java/io/FileNotFoundException");
  232. }
  233. break;
  234. case DB_RUNRECOVERY:
  235. dbexcept = get_class(jnienv, name_DB_RUNRECOVERY_EX);
  236. break;
  237. case DB_LOCK_DEADLOCK:
  238. dbexcept = get_class(jnienv, name_DB_DEADLOCK_EX);
  239. break;
  240. default:
  241. dbexcept = get_class(jnienv, name_DB_EXCEPTION);
  242. break;
  243. }
  244. if (dbexcept != NULL) {
  245. if (textString == NULL)
  246. textString = get_java_string(jnienv, text);
  247. constructId = (*jnienv)->GetMethodID(jnienv, dbexcept,
  248.      "<init>",
  249.      "(Ljava/lang/String;I)V");
  250. obj = (jthrowable)(*jnienv)->NewObject(jnienv, dbexcept,
  251.        constructId, textString,
  252.        err);
  253. (*jnienv)->Throw(jnienv, obj);
  254. }
  255. else if (javaexcept != NULL) {
  256. javaexcept =
  257. (*jnienv)->FindClass(jnienv, "java/io/FileNotFoundException");
  258. (*jnienv)->ThrowNew(jnienv, javaexcept, text);
  259. }
  260. }
  261. /* Report an error via the errcall mechanism.
  262.  */
  263. void report_errcall(JNIEnv *jnienv, jobject errcall,
  264.     jstring prefix, const char *message)
  265. {
  266. jmethodID id;
  267. jclass errcall_class;
  268. jstring msg;
  269. errcall_class = get_class(jnienv, name_DbErrcall);
  270. msg = get_java_string(jnienv, message);
  271. id = (*jnienv)->GetMethodID(jnienv, errcall_class,
  272.  "errcall",
  273.  "(Ljava/lang/String;Ljava/lang/String;)V");
  274. if (id == NULL) {
  275. fprintf(stderr, "Cannot get errcall methodID!n");
  276. fprintf(stderr, "error: %sn", message);
  277. return;
  278. }
  279. (*jnienv)->CallVoidMethod(jnienv, errcall, id, prefix, msg);
  280. }
  281. /* If the object is null, report an exception and return false (0),
  282.  * otherwise return true (1).
  283.  */
  284. int verify_non_null(JNIEnv *jnienv, void *obj)
  285. {
  286. if (obj == NULL) {
  287. report_exception(jnienv, "null object", EINVAL, 0);
  288. return (0);
  289. }
  290. return (1);
  291. }
  292. /* If the error code is non-zero, report an exception and return false (0),
  293.  * otherwise return true (1).
  294.  */
  295. int verify_return(JNIEnv *jnienv, int err, unsigned long expect_mask)
  296. {
  297. if (err == 0)
  298. return 1;
  299. report_exception(jnienv, db_strerror(err), err, expect_mask);
  300. return 0;
  301. }
  302. /* Create an object of the given class, calling its default constructor.
  303.  */
  304. jobject create_default_object(JNIEnv *jnienv, const char *class_name)
  305. {
  306. jclass dbclass = get_class(jnienv, class_name);
  307. jmethodID id = (*jnienv)->GetMethodID(jnienv, dbclass, "<init>", "()V");
  308. jobject object = (*jnienv)->NewObject(jnienv, dbclass, id);
  309. return (object);
  310. }
  311. /* Convert an DB object to a Java encapsulation of that object.
  312.  * Note: This implementation creates a new Java object on each call,
  313.  * so it is generally useful when a new DB object has just been created.
  314.  */
  315. jobject convert_object(JNIEnv *jnienv, const char *class_name, void *dbobj)
  316. {
  317. jobject jo;
  318. if (!dbobj)
  319. return (0);
  320. jo = create_default_object(jnienv, class_name);
  321. set_private_dbobj(jnienv, class_name, jo, dbobj);
  322. return (jo);
  323. }
  324. /* Create a copy of the string
  325.  */
  326. char *dup_string(const char *str)
  327. {
  328. int len;
  329. char *retval;
  330. len = strlen(str) + 1;
  331. retval = (char *)malloc(sizeof(char)*len);
  332. strncpy(retval, str, len);
  333. return (retval);
  334. }
  335. /* Create a java string from the given string
  336.  */
  337. jstring get_java_string(JNIEnv *jnienv, const char* string)
  338. {
  339. if (string == 0)
  340. return (0);
  341. return ((*jnienv)->NewStringUTF(jnienv, string));
  342. }
  343. /* Create a malloc'ed copy of the java string.
  344.  * Caller must free it.
  345.  */
  346. char *get_c_string(JNIEnv *jnienv, jstring jstr)
  347. {
  348. const jbyte *utf;
  349. char *retval;
  350. utf = (*jnienv)->GetStringUTFChars(jnienv, jstr, NULL);
  351. retval = dup_string((const char *)utf);
  352. (*jnienv)->ReleaseStringUTFChars(jnienv, jstr, utf);
  353. return retval;
  354. }
  355. /* Convert a java object to the various C pointers they represent.
  356.  */
  357. DB *get_DB(JNIEnv *jnienv, jobject obj)
  358. {
  359. return ((DB *)get_private_dbobj(jnienv, name_DB, obj));
  360. }
  361. DB_BTREE_STAT *get_DB_BTREE_STAT(JNIEnv *jnienv, jobject obj)
  362. {
  363. return ((DB_BTREE_STAT *)get_private_dbobj(jnienv, name_DB_BTREE_STAT, obj));
  364. }
  365. DBC *get_DBC(JNIEnv *jnienv, jobject obj)
  366. {
  367. return ((DBC *)get_private_dbobj(jnienv, name_DBC, obj));
  368. }
  369. DB_ENV *get_DB_ENV(JNIEnv *jnienv, jobject obj)
  370. {
  371. return ((DB_ENV *)get_private_dbobj(jnienv, name_DB_ENV, obj));
  372. }
  373. DB_ENV_JAVAINFO *get_DB_ENV_JAVAINFO(JNIEnv *jnienv, jobject obj)
  374. {
  375. return ((DB_ENV_JAVAINFO *)get_private_info(jnienv, name_DB_ENV, obj));
  376. }
  377. DB_HASH_STAT *get_DB_HASH_STAT(JNIEnv *jnienv, jobject obj)
  378. {
  379. return ((DB_HASH_STAT *)get_private_dbobj(jnienv, name_DB_HASH_STAT, obj));
  380. }
  381. DB_JAVAINFO *get_DB_JAVAINFO(JNIEnv *jnienv, jobject obj)
  382. {
  383. return ((DB_JAVAINFO *)get_private_info(jnienv, name_DB, obj));
  384. }
  385. DB_LOCK *get_DB_LOCK(JNIEnv *jnienv, jobject obj)
  386. {
  387. return ((DB_LOCK *)get_private_dbobj(jnienv, name_DB_LOCK, obj));
  388. }
  389. DB_LOG_STAT *get_DB_LOG_STAT(JNIEnv *jnienv, jobject obj)
  390. {
  391. return ((DB_LOG_STAT *)get_private_dbobj(jnienv, name_DB_LOG_STAT, obj));
  392. }
  393. DB_LSN *get_DB_LSN(JNIEnv *jnienv, jobject obj)
  394. {
  395. return ((DB_LSN *)get_private_dbobj(jnienv, name_DB_LSN, obj));
  396. }
  397. DB_MPOOL_FSTAT *get_DB_MPOOL_FSTAT(JNIEnv *jnienv, jobject obj)
  398. {
  399. return ((DB_MPOOL_FSTAT *)get_private_dbobj(jnienv, name_DB_MPOOL_FSTAT, obj));
  400. }
  401. DB_MPOOL_STAT *get_DB_MPOOL_STAT(JNIEnv *jnienv, jobject obj)
  402. {
  403. return ((DB_MPOOL_STAT *)get_private_dbobj(jnienv, name_DB_MPOOL_STAT, obj));
  404. }
  405. DB_QUEUE_STAT *get_DB_QUEUE_STAT(JNIEnv *jnienv, jobject obj)
  406. {
  407. return ((DB_QUEUE_STAT *)get_private_dbobj(jnienv, name_DB_QUEUE_STAT, obj));
  408. }
  409. DB_TXN *get_DB_TXN(JNIEnv *jnienv, jobject obj)
  410. {
  411. return ((DB_TXN *)get_private_dbobj(jnienv, name_DB_TXN, obj));
  412. }
  413. DB_TXN_STAT *get_DB_TXN_STAT(JNIEnv *jnienv, jobject obj)
  414. {
  415. return ((DB_TXN_STAT *)get_private_dbobj(jnienv, name_DB_TXN_STAT, obj));
  416. }
  417. DBT *get_DBT(JNIEnv *jnienv, jobject obj)
  418. {
  419. DBT_JAVAINFO *ji;
  420. ji = (DBT_JAVAINFO *)get_private_dbobj(jnienv, name_DBT, obj);
  421. if (ji == NULL)
  422. return (NULL);
  423. else
  424. return (&ji->dbt);
  425. }
  426. DBT_JAVAINFO *get_DBT_JAVAINFO(JNIEnv *jnienv, jobject obj)
  427. {
  428. return ((DBT_JAVAINFO *)get_private_dbobj(jnienv, name_DBT, obj));
  429. }
  430. /* Convert a C pointer to the various Java objects they represent.
  431.  */
  432. jobject get_DbBtreeStat(JNIEnv *jnienv, DB_BTREE_STAT *dbobj)
  433. {
  434. return (convert_object(jnienv, name_DB_BTREE_STAT, dbobj));
  435. }
  436. jobject get_Dbc(JNIEnv *jnienv, DBC *dbobj)
  437. {
  438. return (convert_object(jnienv, name_DBC, dbobj));
  439. }
  440. jobject get_DbHashStat(JNIEnv *jnienv, DB_HASH_STAT *dbobj)
  441. {
  442. return (convert_object(jnienv, name_DB_HASH_STAT, dbobj));
  443. }
  444. jobject get_DbLogStat(JNIEnv *jnienv, DB_LOG_STAT *dbobj)
  445. {
  446. return (convert_object(jnienv, name_DB_LOG_STAT, dbobj));
  447. }
  448. /* LSNs are different since they are really normally
  449.  * treated as by-value objects.  We actually create
  450.  * a pointer to the LSN and store that, deleting it
  451.  * when the LSN is GC'd.
  452.  */
  453. jobject get_DbLsn(JNIEnv *jnienv, DB_LSN dbobj)
  454. {
  455. DB_LSN *lsnp = (DB_LSN *)malloc(sizeof(DB_LSN));
  456. memset(lsnp, 0, sizeof(DB_LSN));
  457. *lsnp = dbobj;
  458. return (convert_object(jnienv, name_DB_LSN, lsnp));
  459. }
  460. jobject get_Dbt(JNIEnv *jnienv, DBT *dbt)
  461. {
  462. return (convert_object(jnienv, name_DBT, dbt));
  463. }
  464. jobject get_DbMpoolFStat(JNIEnv *jnienv, DB_MPOOL_FSTAT *dbobj)
  465. {
  466. return (convert_object(jnienv, name_DB_MPOOL_FSTAT, dbobj));
  467. }
  468. jobject get_DbMpoolStat(JNIEnv *jnienv, DB_MPOOL_STAT *dbobj)
  469. {
  470. return (convert_object(jnienv, name_DB_MPOOL_STAT, dbobj));
  471. }
  472. jobject get_DbQueueStat(JNIEnv *jnienv, DB_QUEUE_STAT *dbobj)
  473. {
  474. return (convert_object(jnienv, name_DB_QUEUE_STAT, dbobj));
  475. }
  476. jobject get_DbTxn(JNIEnv *jnienv, DB_TXN *dbobj)
  477. {
  478. return (convert_object(jnienv, name_DB_TXN, dbobj));
  479. }
  480. jobject get_DbTxnStat(JNIEnv *jnienv, DB_TXN_STAT *dbobj)
  481. {
  482. return (convert_object(jnienv, name_DB_TXN_STAT, dbobj));
  483. }