java_info.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:28k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1997-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: java_info.c,v 11.46 2002/08/29 14:22:23 margo Exp $";
  10. #endif /* not lint */
  11. #include <jni.h>
  12. #include <errno.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include "db_int.h"
  16. #include "java_util.h"
  17. /****************************************************************
  18.  *
  19.  * Callback functions
  20.  */
  21. static int Db_assoc_callback(DB *db,
  22.      const DBT *key,
  23.      const DBT *data,
  24.      DBT *retval)
  25. {
  26. DB_JAVAINFO *dbinfo;
  27. DB_ASSERT(db != NULL);
  28. dbinfo = (DB_JAVAINFO *)db->api_internal;
  29. return (dbji_call_assoc(dbinfo, db, dbinfo->jdbref,
  30.     key, data, retval));
  31. }
  32. static void Db_feedback_callback(DB *db, int opcode, int percent)
  33. {
  34. DB_JAVAINFO *dbinfo;
  35. DB_ASSERT(db != NULL);
  36. dbinfo = (DB_JAVAINFO *)db->api_internal;
  37. dbji_call_feedback(dbinfo, db, dbinfo->jdbref, opcode, percent);
  38. }
  39. static int Db_append_recno_callback(DB *db, DBT *dbt, db_recno_t recno)
  40. {
  41. DB_JAVAINFO *dbinfo;
  42. dbinfo = (DB_JAVAINFO *)db->api_internal;
  43. return (dbji_call_append_recno(dbinfo, db, dbinfo->jdbref, dbt, recno));
  44. }
  45. static int Db_bt_compare_callback(DB *db, const DBT *dbt1, const DBT *dbt2)
  46. {
  47. DB_JAVAINFO *dbinfo;
  48. dbinfo = (DB_JAVAINFO *)db->api_internal;
  49. return (dbji_call_bt_compare(dbinfo, db, dbinfo->jdbref, dbt1, dbt2));
  50. }
  51. static size_t Db_bt_prefix_callback(DB *db, const DBT *dbt1, const DBT *dbt2)
  52. {
  53. DB_JAVAINFO *dbinfo;
  54. dbinfo = (DB_JAVAINFO *)db->api_internal;
  55. return (dbji_call_bt_prefix(dbinfo, db, dbinfo->jdbref, dbt1, dbt2));
  56. }
  57. static int Db_dup_compare_callback(DB *db, const DBT *dbt1, const DBT *dbt2)
  58. {
  59. DB_JAVAINFO *dbinfo;
  60. dbinfo = (DB_JAVAINFO *)db->api_internal;
  61. return (dbji_call_dup_compare(dbinfo, db, dbinfo->jdbref, dbt1, dbt2));
  62. }
  63. static u_int32_t Db_h_hash_callback(DB *db, const void *data, u_int32_t len)
  64. {
  65. DB_JAVAINFO *dbinfo;
  66. dbinfo = (DB_JAVAINFO *)db->api_internal;
  67. return (dbji_call_h_hash(dbinfo, db, dbinfo->jdbref, data, len));
  68. }
  69. static void DbEnv_feedback_callback(DB_ENV *dbenv, int opcode, int percent)
  70. {
  71. DB_ENV_JAVAINFO *dbinfo;
  72. DB_ASSERT(dbenv != NULL);
  73. dbinfo = (DB_ENV_JAVAINFO *)dbenv->api2_internal;
  74. dbjie_call_feedback(dbinfo, dbenv, dbinfo->jenvref, opcode, percent);
  75. }
  76. static int DbEnv_rep_transport_callback(DB_ENV *dbenv,
  77. const DBT *control, const DBT *rec,
  78. int envid, u_int32_t flags)
  79. {
  80. DB_ENV_JAVAINFO *dbinfo;
  81. dbinfo = (DB_ENV_JAVAINFO *)dbenv->api2_internal;
  82. return (dbjie_call_rep_transport(dbinfo, dbenv,
  83.     dbinfo->jenvref, control, rec, envid, (int)flags));
  84. }
  85. static int DbEnv_app_dispatch_callback(DB_ENV *dbenv, DBT *dbt,
  86.      DB_LSN *lsn, db_recops recops)
  87. {
  88. DB_ENV_JAVAINFO *dbinfo;
  89. DB_ASSERT(dbenv != NULL);
  90. dbinfo = (DB_ENV_JAVAINFO *)dbenv->api2_internal;
  91. return (dbjie_call_app_dispatch(dbinfo, dbenv, dbinfo->jenvref, dbt,
  92.     lsn, recops));
  93. }
  94. /****************************************************************
  95.  *
  96.  * Implementation of class DBT_javainfo
  97.  */
  98. DBT_JAVAINFO *
  99. dbjit_construct()
  100. {
  101. DBT_JAVAINFO *dbjit;
  102. int err;
  103. /*XXX should return err*/
  104. if ((err = __os_malloc(NULL, sizeof(DBT_JAVAINFO), &dbjit)) != 0)
  105. return (NULL);
  106. memset(dbjit, 0, sizeof(DBT_JAVAINFO));
  107. return (dbjit);
  108. }
  109. void dbjit_destroy(DBT_JAVAINFO *dbjit)
  110. {
  111. DB_ASSERT(!F_ISSET(dbjit, DBT_JAVAINFO_LOCKED));
  112. /* Extra paranoia */
  113. memset(dbjit, 0, sizeof(DBT_JAVAINFO));
  114. (void)__os_free(NULL, dbjit);
  115. }
  116. /****************************************************************
  117.  *
  118.  * Implementation of class DB_ENV_JAVAINFO
  119.  */
  120. /* create/initialize an object */
  121. DB_ENV_JAVAINFO *
  122. dbjie_construct(JNIEnv *jnienv,
  123. jobject jenv,
  124. jobject default_errcall,
  125. int is_dbopen)
  126. {
  127. DB_ENV_JAVAINFO *dbjie;
  128. int err;
  129. /*XXX should return err*/
  130. if ((err = __os_malloc(NULL, sizeof(DB_ENV_JAVAINFO), &dbjie)) != 0)
  131. return (NULL);
  132. memset(dbjie, 0, sizeof(DB_ENV_JAVAINFO));
  133. dbjie->is_dbopen = is_dbopen;
  134. if ((*jnienv)->GetJavaVM(jnienv, &dbjie->javavm) != 0) {
  135. __os_free(NULL, dbjie);
  136. report_exception(jnienv, "cannot get Java VM", 0, 0);
  137. return (NULL);
  138. }
  139. /*
  140.  * The default error call just prints to the 'System.err'
  141.  * stream.  If the user does set_errcall to null, we'll
  142.  * want to have a reference to set it back to.
  143.  *
  144.  * Why do we have always set db_errcall to our own callback?
  145.  * Because it makes the interaction between setting the
  146.  * error prefix, error stream, and user's error callback
  147.  * that much easier.
  148.  */
  149. dbjie->default_errcall = NEW_GLOBAL_REF(jnienv, default_errcall);
  150. dbjie->errcall = NEW_GLOBAL_REF(jnienv, default_errcall);
  151. dbjie->jenvref = NEW_GLOBAL_REF(jnienv, jenv);
  152. return (dbjie);
  153. }
  154. /* release all objects held by this this one */
  155. void dbjie_dealloc(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv)
  156. {
  157. if (dbjie->feedback != NULL) {
  158. DELETE_GLOBAL_REF(jnienv, dbjie->feedback);
  159. dbjie->feedback = NULL;
  160. }
  161. if (dbjie->app_dispatch != NULL) {
  162. DELETE_GLOBAL_REF(jnienv, dbjie->app_dispatch);
  163. dbjie->app_dispatch = NULL;
  164. }
  165. if (dbjie->errcall != NULL) {
  166. DELETE_GLOBAL_REF(jnienv, dbjie->errcall);
  167. dbjie->errcall = NULL;
  168. }
  169. if (dbjie->default_errcall != NULL) {
  170. DELETE_GLOBAL_REF(jnienv, dbjie->default_errcall);
  171. dbjie->default_errcall = NULL;
  172. }
  173. if (dbjie->jenvref != NULL) {
  174. DELETE_GLOBAL_REF(jnienv, dbjie->jenvref);
  175. dbjie->jenvref = NULL;
  176. }
  177. if (dbjie->conflict != NULL) {
  178. __os_free(NULL, dbjie->conflict);
  179. dbjie->conflict = NULL;
  180. dbjie->conflict_size = 0;
  181. }
  182. if (dbjie->errpfx != NULL) {
  183. __os_free(NULL, dbjie->errpfx);
  184. dbjie->errpfx = NULL;
  185. }
  186. }
  187. /* free this object, releasing anything allocated on its behalf */
  188. void dbjie_destroy(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv)
  189. {
  190. dbjie_dealloc(dbjie, jnienv);
  191. /* Extra paranoia */
  192. memset(dbjie, 0, sizeof(DB_ENV_JAVAINFO));
  193. (void)__os_free(NULL, dbjie);
  194. }
  195. /*
  196.  * Attach to the current thread that is running and
  197.  * return that.  We use the java virtual machine
  198.  * that we saved in the constructor.
  199.  */
  200. JNIEnv *
  201. dbjie_get_jnienv(DB_ENV_JAVAINFO *dbjie)
  202. {
  203. /*
  204.  * Note:
  205.  * Different versions of the JNI disagree on the signature
  206.  * for AttachCurrentThread.  The most recent documentation
  207.  * seems to say that (JNIEnv **) is correct, but newer
  208.  * JNIs seem to use (void **), oddly enough.
  209.  */
  210. #ifdef JNI_VERSION_1_2
  211. void *attachret = 0;
  212. #else
  213. JNIEnv *attachret = 0;
  214. #endif
  215. /*
  216.  * This should always succeed, as we are called via
  217.  * some Java activity.  I think therefore I am (a thread).
  218.  */
  219. if ((*dbjie->javavm)->AttachCurrentThread(dbjie->javavm, &attachret, 0)
  220.     != 0)
  221. return (0);
  222. return ((JNIEnv *)attachret);
  223. }
  224. jstring
  225. dbjie_get_errpfx(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv)
  226. {
  227. return (get_java_string(jnienv, dbjie->errpfx));
  228. }
  229. void
  230. dbjie_set_errcall(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv, jobject new_errcall)
  231. {
  232. /*
  233.  * If the new_errcall is null, we'll set the error call
  234.  * to the default one.
  235.  */
  236. if (new_errcall == NULL)
  237. new_errcall = dbjie->default_errcall;
  238. DELETE_GLOBAL_REF(jnienv, dbjie->errcall);
  239. dbjie->errcall = NEW_GLOBAL_REF(jnienv, new_errcall);
  240. }
  241. void
  242. dbjie_set_errpfx(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv, jstring errpfx)
  243. {
  244. if (dbjie->errpfx != NULL)
  245. __os_free(NULL, dbjie->errpfx);
  246. if (errpfx)
  247. dbjie->errpfx = get_c_string(jnienv, errpfx);
  248. else
  249. dbjie->errpfx = NULL;
  250. }
  251. void
  252. dbjie_set_conflict(DB_ENV_JAVAINFO *dbjie, u_char *newarr, size_t size)
  253. {
  254. if (dbjie->conflict != NULL)
  255. (void)__os_free(NULL, dbjie->conflict);
  256. dbjie->conflict = newarr;
  257. dbjie->conflict_size = size;
  258. }
  259. void dbjie_set_feedback_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv,
  260.        DB_ENV *dbenv, jobject jfeedback)
  261. {
  262. int err;
  263. if (dbjie->feedback != NULL) {
  264. DELETE_GLOBAL_REF(jnienv, dbjie->feedback);
  265. }
  266. if (jfeedback == NULL) {
  267. if ((err = dbenv->set_feedback(dbenv, NULL)) != 0)
  268. report_exception(jnienv, "set_feedback failed",
  269.  err, 0);
  270. }
  271. else {
  272. if ((err = dbenv->set_feedback(dbenv,
  273.        DbEnv_feedback_callback)) != 0)
  274. report_exception(jnienv, "set_feedback failed",
  275.  err, 0);
  276. }
  277. dbjie->feedback = NEW_GLOBAL_REF(jnienv, jfeedback);
  278. }
  279. void dbjie_call_feedback(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv, jobject jenv,
  280.  int opcode, int percent)
  281. {
  282. JNIEnv *jnienv;
  283. jclass feedback_class;
  284. jmethodID id;
  285. COMPQUIET(dbenv, NULL);
  286. jnienv = dbjie_get_jnienv(dbjie);
  287. if (jnienv == NULL) {
  288. fprintf(stderr, "Cannot attach to current thread!n");
  289. return;
  290. }
  291. if ((feedback_class =
  292.     get_class(jnienv, name_DbEnvFeedback)) == NULL) {
  293. fprintf(stderr, "Cannot find callback class %sn",
  294.     name_DbEnvFeedback);
  295. return; /* An exception has been posted. */
  296. }
  297. id = (*jnienv)->GetMethodID(jnienv, feedback_class,
  298.     "feedback",
  299.     "(Lcom/sleepycat/db/DbEnv;II)V");
  300. if (!id) {
  301. fprintf(stderr, "Cannot find callback method feedbackn");
  302. return;
  303. }
  304. (*jnienv)->CallVoidMethod(jnienv, dbjie->feedback, id,
  305.   jenv, (jint)opcode, (jint)percent);
  306. }
  307. void dbjie_set_rep_transport_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv,
  308.     DB_ENV *dbenv, int id, jobject jtransport)
  309. {
  310. int err;
  311. if (dbjie->rep_transport != NULL)
  312. DELETE_GLOBAL_REF(jnienv, dbjie->rep_transport);
  313. err = dbenv->set_rep_transport(dbenv, id,
  314.     DbEnv_rep_transport_callback);
  315. verify_return(jnienv, err, 0);
  316. dbjie->rep_transport = NEW_GLOBAL_REF(jnienv, jtransport);
  317. }
  318. int dbjie_call_rep_transport(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv,
  319.      jobject jenv, const DBT *control,
  320.      const DBT *rec, int flags, int envid)
  321. {
  322. JNIEnv *jnienv;
  323. jclass rep_transport_class;
  324. jmethodID jid;
  325. jobject jcdbt, jrdbt;
  326. COMPQUIET(dbenv, NULL);
  327. jnienv = dbjie_get_jnienv(dbjie);
  328. if (jnienv == NULL) {
  329. fprintf(stderr, "Cannot attach to current thread!n");
  330. return (0);
  331. }
  332. if ((rep_transport_class =
  333.     get_class(jnienv, name_DbRepTransport)) == NULL) {
  334. fprintf(stderr, "Cannot find callback class %sn",
  335.     name_DbRepTransport);
  336. return (0); /* An exception has been posted. */
  337. }
  338. jid = (*jnienv)->GetMethodID(jnienv, rep_transport_class,
  339.      "send",
  340.      "(Lcom/sleepycat/db/DbEnv;"
  341.      "Lcom/sleepycat/db/Dbt;"
  342.      "Lcom/sleepycat/db/Dbt;II)I");
  343. if (!jid) {
  344. fprintf(stderr, "Cannot find callback method sendn");
  345. return (0);
  346. }
  347. jcdbt = get_const_Dbt(jnienv, control, NULL);
  348. jrdbt = get_const_Dbt(jnienv, rec, NULL);
  349. return (*jnienv)->CallIntMethod(jnienv, dbjie->rep_transport, jid, jenv,
  350. jcdbt, jrdbt, flags, envid);
  351. }
  352. void dbjie_set_app_dispatch_object(DB_ENV_JAVAINFO *dbjie, JNIEnv *jnienv,
  353.  DB_ENV *dbenv, jobject japp_dispatch)
  354. {
  355. int err;
  356. if (dbjie->app_dispatch != NULL) {
  357. DELETE_GLOBAL_REF(jnienv, dbjie->app_dispatch);
  358. }
  359. if (japp_dispatch == NULL) {
  360. if ((err = dbenv->set_app_dispatch(dbenv, NULL)) != 0)
  361. report_exception(jnienv, "set_app_dispatch failed",
  362.  err, 0);
  363. }
  364. else {
  365. if ((err = dbenv->set_app_dispatch(dbenv,
  366.     DbEnv_app_dispatch_callback)) != 0)
  367. report_exception(jnienv, "set_app_dispatch failed",
  368.  err, 0);
  369. }
  370. dbjie->app_dispatch = NEW_GLOBAL_REF(jnienv, japp_dispatch);
  371. }
  372. int dbjie_call_app_dispatch(DB_ENV_JAVAINFO *dbjie, DB_ENV *dbenv, jobject jenv,
  373.   DBT *dbt, DB_LSN *lsn, int recops)
  374. {
  375. JNIEnv *jnienv;
  376. jclass app_dispatch_class;
  377. jmethodID id;
  378. jobject jdbt;
  379. jobject jlsn;
  380. COMPQUIET(dbenv, NULL);
  381. jnienv = dbjie_get_jnienv(dbjie);
  382. if (jnienv == NULL) {
  383. fprintf(stderr, "Cannot attach to current thread!n");
  384. return (0);
  385. }
  386. if ((app_dispatch_class =
  387.     get_class(jnienv, name_DbTxnRecover)) == NULL) {
  388. fprintf(stderr, "Cannot find callback class %sn",
  389.     name_DbTxnRecover);
  390. return (0); /* An exception has been posted. */
  391. }
  392. id = (*jnienv)->GetMethodID(jnienv, app_dispatch_class,
  393.     "app_dispatch",
  394.     "(Lcom/sleepycat/db/DbEnv;"
  395.     "Lcom/sleepycat/db/Dbt;"
  396.     "Lcom/sleepycat/db/DbLsn;"
  397.     "I)I");
  398. if (!id) {
  399. fprintf(stderr, "Cannot find callback method app_dispatchn");
  400. return (0);
  401. }
  402. jdbt = get_Dbt(jnienv, dbt, NULL);
  403. if (lsn == NULL)
  404. jlsn = NULL;
  405. else
  406. jlsn = get_DbLsn(jnienv, *lsn);
  407. return (*jnienv)->CallIntMethod(jnienv, dbjie->app_dispatch, id, jenv,
  408. jdbt, jlsn, recops);
  409. }
  410. jobject dbjie_get_errcall(DB_ENV_JAVAINFO *dbjie)
  411. {
  412. return (dbjie->errcall);
  413. }
  414. jint dbjie_is_dbopen(DB_ENV_JAVAINFO *dbjie)
  415. {
  416. return (dbjie->is_dbopen);
  417. }
  418. /****************************************************************
  419.  *
  420.  * Implementation of class DB_JAVAINFO
  421.  */
  422. DB_JAVAINFO *dbji_construct(JNIEnv *jnienv, jobject jdb, jint flags)
  423. {
  424. DB_JAVAINFO *dbji;
  425. int err;
  426. /*XXX should return err*/
  427. if ((err = __os_malloc(NULL, sizeof(DB_JAVAINFO), &dbji)) != 0)
  428. return (NULL);
  429. memset(dbji, 0, sizeof(DB_JAVAINFO));
  430. if ((*jnienv)->GetJavaVM(jnienv, &dbji->javavm) != 0) {
  431. report_exception(jnienv, "cannot get Java VM", 0, 0);
  432. (void)__os_free(NULL, dbji);
  433. return (NULL);
  434. }
  435. dbji->jdbref = NEW_GLOBAL_REF(jnienv, jdb);
  436. dbji->construct_flags = flags;
  437. return (dbji);
  438. }
  439. void
  440. dbji_dealloc(DB_JAVAINFO *dbji, JNIEnv *jnienv)
  441. {
  442. if (dbji->append_recno != NULL) {
  443. DELETE_GLOBAL_REF(jnienv, dbji->append_recno);
  444. dbji->append_recno = NULL;
  445. }
  446. if (dbji->assoc != NULL) {
  447. DELETE_GLOBAL_REF(jnienv, dbji->assoc);
  448. dbji->assoc = NULL;
  449. }
  450. if (dbji->bt_compare != NULL) {
  451. DELETE_GLOBAL_REF(jnienv, dbji->bt_compare);
  452. dbji->bt_compare = NULL;
  453. }
  454. if (dbji->bt_prefix != NULL) {
  455. DELETE_GLOBAL_REF(jnienv, dbji->bt_prefix);
  456. dbji->bt_prefix = NULL;
  457. }
  458. if (dbji->dup_compare != NULL) {
  459. DELETE_GLOBAL_REF(jnienv, dbji->dup_compare);
  460. dbji->dup_compare = NULL;
  461. }
  462. if (dbji->feedback != NULL) {
  463. DELETE_GLOBAL_REF(jnienv, dbji->feedback);
  464. dbji->feedback = NULL;
  465. }
  466. if (dbji->h_hash != NULL) {
  467. DELETE_GLOBAL_REF(jnienv, dbji->h_hash);
  468. dbji->h_hash = NULL;
  469. }
  470. if (dbji->jdbref != NULL) {
  471. DELETE_GLOBAL_REF(jnienv, dbji->jdbref);
  472. dbji->jdbref = NULL;
  473. }
  474. }
  475. void
  476. dbji_destroy(DB_JAVAINFO *dbji, JNIEnv *jnienv)
  477. {
  478. dbji_dealloc(dbji, jnienv);
  479. __os_free(NULL, dbji);
  480. }
  481. JNIEnv *dbji_get_jnienv(DB_JAVAINFO *dbji)
  482. {
  483. /*
  484.  * Note:
  485.  * Different versions of the JNI disagree on the signature
  486.  * for AttachCurrentThread.  The most recent documentation
  487.  * seems to say that (JNIEnv **) is correct, but newer
  488.  * JNIs seem to use (void **), oddly enough.
  489.  */
  490. #ifdef JNI_VERSION_1_2
  491. void *attachret = 0;
  492. #else
  493. JNIEnv *attachret = 0;
  494. #endif
  495. /*
  496.  * This should always succeed, as we are called via
  497.  * some Java activity.  I think therefore I am (a thread).
  498.  */
  499. if ((*dbji->javavm)->AttachCurrentThread(dbji->javavm, &attachret, 0)
  500.     != 0)
  501. return (0);
  502. return ((JNIEnv *)attachret);
  503. }
  504. jint dbji_get_flags(DB_JAVAINFO *dbji)
  505. {
  506. return (dbji->construct_flags);
  507. }
  508. void dbji_set_feedback_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
  509.       DB *db, jobject jfeedback)
  510. {
  511. jclass feedback_class;
  512. if (dbji->feedback_method_id == NULL) {
  513. if ((feedback_class =
  514.     get_class(jnienv, name_DbFeedback)) == NULL)
  515. return; /* An exception has been posted. */
  516. dbji->feedback_method_id =
  517. (*jnienv)->GetMethodID(jnienv, feedback_class,
  518.        "feedback",
  519.        "(Lcom/sleepycat/db/Db;II)V");
  520. if (dbji->feedback_method_id == NULL) {
  521. /*
  522.  * XXX
  523.  * We should really have a better way
  524.  * to translate this to a Java exception class.
  525.  * In theory, it shouldn't happen.
  526.  */
  527. report_exception(jnienv, "Cannot find callback method",
  528.  EFAULT, 0);
  529. return;
  530. }
  531. }
  532. if (dbji->feedback != NULL) {
  533. DELETE_GLOBAL_REF(jnienv, dbji->feedback);
  534. }
  535. if (jfeedback == NULL) {
  536. db->set_feedback(db, NULL);
  537. }
  538. else {
  539. db->set_feedback(db, Db_feedback_callback);
  540. }
  541. dbji->feedback = NEW_GLOBAL_REF(jnienv, jfeedback);
  542. }
  543. void dbji_call_feedback(DB_JAVAINFO *dbji, DB *db, jobject jdb,
  544. int opcode, int percent)
  545. {
  546. JNIEnv *jnienv;
  547. COMPQUIET(db, NULL);
  548. jnienv = dbji_get_jnienv(dbji);
  549. if (jnienv == NULL) {
  550. fprintf(stderr, "Cannot attach to current thread!n");
  551. return;
  552. }
  553. DB_ASSERT(dbji->feedback_method_id != NULL);
  554. (*jnienv)->CallVoidMethod(jnienv, dbji->feedback,
  555.   dbji->feedback_method_id,
  556.   jdb, (jint)opcode, (jint)percent);
  557. }
  558. void dbji_set_append_recno_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
  559.   DB *db, jobject jcallback)
  560. {
  561. jclass append_recno_class;
  562. if (dbji->append_recno_method_id == NULL) {
  563. if ((append_recno_class =
  564.     get_class(jnienv, name_DbAppendRecno)) == NULL)
  565. return; /* An exception has been posted. */
  566. dbji->append_recno_method_id =
  567. (*jnienv)->GetMethodID(jnienv, append_recno_class,
  568.        "db_append_recno",
  569.        "(Lcom/sleepycat/db/Db;"
  570.        "Lcom/sleepycat/db/Dbt;I)V");
  571. if (dbji->append_recno_method_id == NULL) {
  572. /*
  573.  * XXX
  574.  * We should really have a better way
  575.  * to translate this to a Java exception class.
  576.  * In theory, it shouldn't happen.
  577.  */
  578. report_exception(jnienv, "Cannot find callback method",
  579.  EFAULT, 0);
  580. return;
  581. }
  582. }
  583. if (dbji->append_recno != NULL) {
  584. DELETE_GLOBAL_REF(jnienv, dbji->append_recno);
  585. }
  586. if (jcallback == NULL) {
  587. db->set_append_recno(db, NULL);
  588. }
  589. else {
  590. db->set_append_recno(db, Db_append_recno_callback);
  591. }
  592. dbji->append_recno = NEW_GLOBAL_REF(jnienv, jcallback);
  593. }
  594. extern int dbji_call_append_recno(DB_JAVAINFO *dbji, DB *db, jobject jdb,
  595.   DBT *dbt, jint recno)
  596. {
  597. JNIEnv *jnienv;
  598. jobject jresult;
  599. DBT_JAVAINFO *dbtji;
  600. LOCKED_DBT lresult;
  601. DB_ENV *dbenv;
  602. u_char *bytearray;
  603. int err;
  604. jnienv = dbji_get_jnienv(dbji);
  605. dbenv = db->dbenv;
  606. if (jnienv == NULL) {
  607. fprintf(stderr, "Cannot attach to current thread!n");
  608. return (0);
  609. }
  610. jresult = get_Dbt(jnienv, dbt, &dbtji);
  611. DB_ASSERT(dbji->append_recno_method_id != NULL);
  612. (*jnienv)->CallVoidMethod(jnienv, dbji->append_recno,
  613.   dbji->append_recno_method_id,
  614.   jdb, jresult, recno);
  615. /*
  616.  * The underlying C API requires that an errno be returned
  617.  * on error.  Java users know nothing of errnos, so we
  618.  * allow them to throw exceptions instead.  We leave the
  619.  * exception in place and return DB_JAVA_CALLBACK to the C API
  620.  * that called us.  Eventually the DB->get will fail and
  621.  * when java prepares to throw an exception in
  622.  * report_exception(), this will be spotted as a special case,
  623.  * and the original exception will be preserved.
  624.  *
  625.  * Note: we have sometimes noticed strange behavior with
  626.  * exceptions under Linux 1.1.7 JVM.  (i.e. multiple calls
  627.  * to ExceptionOccurred() may report different results).
  628.  * Currently we don't know of any problems related to this
  629.  * in our code, but if it pops up in the future, users are
  630.  * encouranged to get a more recent JVM.
  631.  */
  632. if ((*jnienv)->ExceptionOccurred(jnienv) != NULL)
  633. return (DB_JAVA_CALLBACK);
  634. /*
  635.  * Now get the DBT back from java, because the user probably
  636.  * changed it.  We'll have to copy back the array too and let
  637.  * our caller free it.
  638.  *
  639.  * We expect that the user *has* changed the DBT (why else would
  640.  * they set up an append_recno callback?) so we don't
  641.  * worry about optimizing the unchanged case.
  642.  */
  643. if ((err = locked_dbt_get(&lresult, jnienv, dbenv, jresult, inOp)) != 0)
  644. return (err);
  645. memcpy(dbt, &lresult.javainfo->dbt, sizeof(DBT));
  646. if ((err = __os_malloc(dbenv, dbt->size, &bytearray)) != 0)
  647. goto out;
  648. memcpy(bytearray, dbt->data, dbt->size);
  649. dbt->data = bytearray;
  650. dbt->flags |= DB_DBT_APPMALLOC;
  651.  out:
  652. locked_dbt_put(&lresult, jnienv, dbenv);
  653. return (err);
  654. }
  655. void dbji_set_assoc_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
  656.        DB *db, DB_TXN *txn, DB *second,
  657.        jobject jcallback, int flags)
  658. {
  659. jclass assoc_class;
  660. int err;
  661. if (dbji->assoc_method_id == NULL) {
  662. if ((assoc_class =
  663.     get_class(jnienv, name_DbSecondaryKeyCreate)) == NULL)
  664. return; /* An exception has been posted. */
  665. dbji->assoc_method_id =
  666. (*jnienv)->GetMethodID(jnienv, assoc_class,
  667.        "secondary_key_create",
  668.        "(Lcom/sleepycat/db/Db;"
  669.        "Lcom/sleepycat/db/Dbt;"
  670.        "Lcom/sleepycat/db/Dbt;"
  671.        "Lcom/sleepycat/db/Dbt;)I");
  672. if (dbji->assoc_method_id == NULL) {
  673. /*
  674.  * XXX
  675.  * We should really have a better way
  676.  * to translate this to a Java exception class.
  677.  * In theory, it shouldn't happen.
  678.  */
  679. report_exception(jnienv, "Cannot find callback method",
  680.  EFAULT, 0);
  681. return;
  682. }
  683. }
  684. if (dbji->assoc != NULL) {
  685. DELETE_GLOBAL_REF(jnienv, dbji->assoc);
  686. dbji->assoc = NULL;
  687. }
  688. if (jcallback == NULL)
  689. err = db->associate(db, txn, second, NULL, flags);
  690. else
  691. err = db->associate(db, txn, second, Db_assoc_callback, flags);
  692. if (verify_return(jnienv, err, 0))
  693. dbji->assoc = NEW_GLOBAL_REF(jnienv, jcallback);
  694. }
  695. extern int dbji_call_assoc(DB_JAVAINFO *dbji, DB *db, jobject jdb,
  696.    const DBT *key, const DBT *value, DBT *result)
  697. {
  698. JNIEnv *jnienv;
  699. jobject jresult;
  700. LOCKED_DBT lresult;
  701. DB_ENV *dbenv;
  702. int err;
  703. int sz;
  704. u_char *bytearray;
  705. jint retval;
  706. jnienv = dbji_get_jnienv(dbji);
  707. if (jnienv == NULL) {
  708. fprintf(stderr, "Cannot attach to current thread!n");
  709. return (0);
  710. }
  711. DB_ASSERT(dbji->assoc_method_id != NULL);
  712. dbenv = db->dbenv;
  713. jresult = create_default_object(jnienv, name_DBT);
  714. retval = (*jnienv)->CallIntMethod(jnienv, dbji->assoc,
  715.   dbji->assoc_method_id, jdb,
  716.   get_const_Dbt(jnienv, key, NULL),
  717.   get_const_Dbt(jnienv, value, NULL),
  718.   jresult);
  719. if (retval != 0)
  720. return (retval);
  721. if ((*jnienv)->ExceptionOccurred(jnienv) != NULL)
  722. return (DB_JAVA_CALLBACK);
  723. if ((err = locked_dbt_get(&lresult, jnienv, dbenv, jresult, inOp)) != 0)
  724. return (err);
  725. sz = lresult.javainfo->dbt.size;
  726. if (sz > 0) {
  727. bytearray = (u_char *)lresult.javainfo->dbt.data;
  728. /*
  729.  * If the byte array is in the range of one of the
  730.  * arrays passed to us we can use it directly.
  731.  * If not, we must create our own array and
  732.  * fill it in with the java array.  Since
  733.  * the java array may disappear and we don't
  734.  * want to keep its memory locked indefinitely,
  735.  * we cannot just pin the array.
  736.  *
  737.  * XXX consider pinning the array, and having
  738.  * some way for the C layer to notify the java
  739.  * layer when it can be unpinned.
  740.  */
  741. if ((bytearray < (u_char *)key->data ||
  742.      bytearray + sz > (u_char *)key->data + key->size) &&
  743.     (bytearray < (u_char *)value->data ||
  744.      bytearray + sz > (u_char *)value->data + value->size)) {
  745. result->flags |= DB_DBT_APPMALLOC;
  746. if ((err = __os_malloc(dbenv, sz, &bytearray)) != 0)
  747. goto out;
  748. memcpy(bytearray, lresult.javainfo->dbt.data, sz);
  749. }
  750. result->data = bytearray;
  751. result->size = sz;
  752. }
  753.  out:
  754. locked_dbt_put(&lresult, jnienv, dbenv);
  755. return (err);
  756. }
  757. void dbji_set_bt_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
  758. DB *db, jobject jcompare)
  759. {
  760. jclass bt_compare_class;
  761. if (dbji->bt_compare_method_id == NULL) {
  762. if ((bt_compare_class =
  763.     get_class(jnienv, name_DbBtreeCompare)) == NULL)
  764. return; /* An exception has been posted. */
  765. dbji->bt_compare_method_id =
  766. (*jnienv)->GetMethodID(jnienv, bt_compare_class,
  767.        "bt_compare",
  768.        "(Lcom/sleepycat/db/Db;"
  769.        "Lcom/sleepycat/db/Dbt;"
  770.        "Lcom/sleepycat/db/Dbt;)I");
  771. if (dbji->bt_compare_method_id == NULL) {
  772. /*
  773.  * XXX
  774.  * We should really have a better way
  775.  * to translate this to a Java exception class.
  776.  * In theory, it shouldn't happen.
  777.  */
  778. report_exception(jnienv, "Cannot find callback method",
  779.  EFAULT, 0);
  780. return;
  781. }
  782. }
  783. if (dbji->bt_compare != NULL) {
  784. DELETE_GLOBAL_REF(jnienv, dbji->bt_compare);
  785. }
  786. if (jcompare == NULL) {
  787. db->set_bt_compare(db, NULL);
  788. }
  789. else {
  790. db->set_bt_compare(db, Db_bt_compare_callback);
  791. }
  792. dbji->bt_compare = NEW_GLOBAL_REF(jnienv, jcompare);
  793. }
  794. int dbji_call_bt_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb,
  795.  const DBT *dbt1, const DBT *dbt2)
  796. {
  797. JNIEnv *jnienv;
  798. jobject jdbt1, jdbt2;
  799. COMPQUIET(db, NULL);
  800. jnienv = dbji_get_jnienv(dbji);
  801. if (jnienv == NULL) {
  802. fprintf(stderr, "Cannot attach to current thread!n");
  803. return (0);
  804. }
  805. jdbt1 = get_const_Dbt(jnienv, dbt1, NULL);
  806. jdbt2 = get_const_Dbt(jnienv, dbt2, NULL);
  807. DB_ASSERT(dbji->bt_compare_method_id != NULL);
  808. return (*jnienv)->CallIntMethod(jnienv, dbji->bt_compare,
  809. dbji->bt_compare_method_id,
  810. jdb, jdbt1, jdbt2);
  811. }
  812. void dbji_set_bt_prefix_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
  813. DB *db, jobject jprefix)
  814. {
  815. jclass bt_prefix_class;
  816. if (dbji->bt_prefix_method_id == NULL) {
  817. if ((bt_prefix_class =
  818.     get_class(jnienv, name_DbBtreePrefix)) == NULL)
  819. return; /* An exception has been posted. */
  820. dbji->bt_prefix_method_id =
  821. (*jnienv)->GetMethodID(jnienv, bt_prefix_class,
  822.        "bt_prefix",
  823.        "(Lcom/sleepycat/db/Db;"
  824.        "Lcom/sleepycat/db/Dbt;"
  825.        "Lcom/sleepycat/db/Dbt;)I");
  826. if (dbji->bt_prefix_method_id == NULL) {
  827. /*
  828.  * XXX
  829.  * We should really have a better way
  830.  * to translate this to a Java exception class.
  831.  * In theory, it shouldn't happen.
  832.  */
  833. report_exception(jnienv, "Cannot find callback method",
  834.  EFAULT, 0);
  835. return;
  836. }
  837. }
  838. if (dbji->bt_prefix != NULL) {
  839. DELETE_GLOBAL_REF(jnienv, dbji->bt_prefix);
  840. }
  841. if (jprefix == NULL) {
  842. db->set_bt_prefix(db, NULL);
  843. }
  844. else {
  845. db->set_bt_prefix(db, Db_bt_prefix_callback);
  846. }
  847. dbji->bt_prefix = NEW_GLOBAL_REF(jnienv, jprefix);
  848. }
  849. size_t dbji_call_bt_prefix(DB_JAVAINFO *dbji, DB *db, jobject jdb,
  850.    const DBT *dbt1, const DBT *dbt2)
  851. {
  852. JNIEnv *jnienv;
  853. jobject jdbt1, jdbt2;
  854. COMPQUIET(db, NULL);
  855. jnienv = dbji_get_jnienv(dbji);
  856. if (jnienv == NULL) {
  857. fprintf(stderr, "Cannot attach to current thread!n");
  858. return (0);
  859. }
  860. jdbt1 = get_const_Dbt(jnienv, dbt1, NULL);
  861. jdbt2 = get_const_Dbt(jnienv, dbt2, NULL);
  862. DB_ASSERT(dbji->bt_prefix_method_id != NULL);
  863. return (size_t)(*jnienv)->CallIntMethod(jnienv, dbji->bt_prefix,
  864. dbji->bt_prefix_method_id,
  865. jdb, jdbt1, jdbt2);
  866. }
  867. void dbji_set_dup_compare_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
  868. DB *db, jobject jcompare)
  869. {
  870. jclass dup_compare_class;
  871. if (dbji->dup_compare_method_id == NULL) {
  872. if ((dup_compare_class =
  873.     get_class(jnienv, name_DbDupCompare)) == NULL)
  874. return; /* An exception has been posted. */
  875. dbji->dup_compare_method_id =
  876. (*jnienv)->GetMethodID(jnienv, dup_compare_class,
  877.        "dup_compare",
  878.        "(Lcom/sleepycat/db/Db;"
  879.        "Lcom/sleepycat/db/Dbt;"
  880.        "Lcom/sleepycat/db/Dbt;)I");
  881. if (dbji->dup_compare_method_id == NULL) {
  882. /*
  883.  * XXX
  884.  * We should really have a better way
  885.  * to translate this to a Java exception class.
  886.  * In theory, it shouldn't happen.
  887.  */
  888. report_exception(jnienv, "Cannot find callback method",
  889.  EFAULT, 0);
  890. return;
  891. }
  892. }
  893. if (dbji->dup_compare != NULL)
  894. DELETE_GLOBAL_REF(jnienv, dbji->dup_compare);
  895. if (jcompare == NULL)
  896. db->set_dup_compare(db, NULL);
  897. else
  898. db->set_dup_compare(db, Db_dup_compare_callback);
  899. dbji->dup_compare = NEW_GLOBAL_REF(jnienv, jcompare);
  900. }
  901. int dbji_call_dup_compare(DB_JAVAINFO *dbji, DB *db, jobject jdb,
  902.  const DBT *dbt1, const DBT *dbt2)
  903. {
  904. JNIEnv *jnienv;
  905. jobject jdbt1, jdbt2;
  906. COMPQUIET(db, NULL);
  907. jnienv = dbji_get_jnienv(dbji);
  908. if (jnienv == NULL) {
  909. fprintf(stderr, "Cannot attach to current thread!n");
  910. return (0);
  911. }
  912. jdbt1 = get_const_Dbt(jnienv, dbt1, NULL);
  913. jdbt2 = get_const_Dbt(jnienv, dbt2, NULL);
  914. DB_ASSERT(dbji->dup_compare_method_id != NULL);
  915. return (*jnienv)->CallIntMethod(jnienv, dbji->dup_compare,
  916. dbji->dup_compare_method_id,
  917. jdb, jdbt1, jdbt2);
  918. }
  919. void dbji_set_h_hash_object(DB_JAVAINFO *dbji, JNIEnv *jnienv,
  920. DB *db, jobject jhash)
  921. {
  922. jclass h_hash_class;
  923. if (dbji->h_hash_method_id == NULL) {
  924. if ((h_hash_class =
  925.     get_class(jnienv, name_DbHash)) == NULL)
  926. return; /* An exception has been posted. */
  927. dbji->h_hash_method_id =
  928. (*jnienv)->GetMethodID(jnienv, h_hash_class,
  929.        "hash",
  930.        "(Lcom/sleepycat/db/Db;"
  931.        "[BI)I");
  932. if (dbji->h_hash_method_id == NULL) {
  933. /*
  934.  * XXX
  935.  * We should really have a better way
  936.  * to translate this to a Java exception class.
  937.  * In theory, it shouldn't happen.
  938.  */
  939. report_exception(jnienv, "Cannot find callback method",
  940.  EFAULT, 0);
  941. return;
  942. }
  943. }
  944. if (dbji->h_hash != NULL)
  945. DELETE_GLOBAL_REF(jnienv, dbji->h_hash);
  946. if (jhash == NULL)
  947. db->set_h_hash(db, NULL);
  948. else
  949. db->set_h_hash(db, Db_h_hash_callback);
  950. dbji->h_hash = NEW_GLOBAL_REF(jnienv, jhash);
  951. }
  952. int dbji_call_h_hash(DB_JAVAINFO *dbji, DB *db, jobject jdb,
  953.      const void *data, int len)
  954. {
  955. JNIEnv *jnienv;
  956. jbyteArray jdata;
  957. COMPQUIET(db, NULL);
  958. jnienv = dbji_get_jnienv(dbji);
  959. if (jnienv == NULL) {
  960. fprintf(stderr, "Cannot attach to current thread!n");
  961. return (0);
  962. }
  963. DB_ASSERT(dbji->h_hash_method_id != NULL);
  964. if ((jdata = (*jnienv)->NewByteArray(jnienv, len)) == NULL)
  965. return (0); /* An exception has been posted by the JVM */
  966. (*jnienv)->SetByteArrayRegion(jnienv, jdata, 0, len, (void *)data);
  967. return (*jnienv)->CallIntMethod(jnienv, dbji->h_hash,
  968. dbji->h_hash_method_id,
  969. jdb, jdata, len);
  970. }