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

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_locked.c,v 11.32 2002/08/06 05:19:07 bostic 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.  * Implementation of functions to manipulate LOCKED_DBT.
  20.  */
  21. int
  22. locked_dbt_get(LOCKED_DBT *ldbt, JNIEnv *jnienv, DB_ENV *dbenv,
  23.        jobject jdbt, OpKind kind)
  24. {
  25. DBT *dbt;
  26. COMPQUIET(dbenv, NULL);
  27. ldbt->jdbt = jdbt;
  28. ldbt->java_array_len = 0;
  29. ldbt->flags = 0;
  30. ldbt->kind = kind;
  31. ldbt->java_data = 0;
  32. ldbt->before_data = 0;
  33. ldbt->javainfo =
  34. (DBT_JAVAINFO *)get_private_dbobj(jnienv, name_DBT, jdbt);
  35. if (!verify_non_null(jnienv, ldbt->javainfo)) {
  36. report_exception(jnienv, "Dbt is gc'ed?", 0, 0);
  37. F_SET(ldbt, LOCKED_ERROR);
  38. return (EINVAL);
  39. }
  40. if (F_ISSET(ldbt->javainfo, DBT_JAVAINFO_LOCKED)) {
  41. report_exception(jnienv, "Dbt is already in use", 0, 0);
  42. F_SET(ldbt, LOCKED_ERROR);
  43. return (EINVAL);
  44. }
  45. dbt = &ldbt->javainfo->dbt;
  46. if ((*jnienv)->GetBooleanField(jnienv,
  47.     jdbt, fid_Dbt_must_create_data) != 0)
  48. F_SET(ldbt, LOCKED_CREATE_DATA);
  49. else
  50. ldbt->javainfo->array =
  51. (*jnienv)->GetObjectField(jnienv, jdbt, fid_Dbt_data);
  52. dbt->size = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_size);
  53. dbt->ulen = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_ulen);
  54. dbt->dlen = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_dlen);
  55. dbt->doff = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_doff);
  56. dbt->flags = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_flags);
  57. ldbt->javainfo->offset = (*jnienv)->GetIntField(jnienv, jdbt,
  58.     fid_Dbt_offset);
  59. /*
  60.  * If no flags are set, use default behavior of DB_DBT_MALLOC.
  61.  * We can safely set dbt->flags because flags will never be copied
  62.  * back to the Java Dbt.
  63.  */
  64. if (kind != inOp &&
  65.     !F_ISSET(dbt, DB_DBT_USERMEM | DB_DBT_MALLOC | DB_DBT_REALLOC))
  66. F_SET(dbt, DB_DBT_MALLOC);
  67. /*
  68.  * If this is requested to be realloc with an existing array,
  69.  * we cannot use the underlying realloc, because the array we
  70.  * will pass in is allocated by the Java VM, not us, so it
  71.  * cannot be realloced.  We simulate the reallocation by using
  72.  * USERMEM and reallocating the java array when a ENOMEM error
  73.  * occurs.  We change the flags during the operation, and they
  74.  * are reset when the operation completes (in locked_dbt_put).
  75.  */
  76. if (F_ISSET(dbt, DB_DBT_REALLOC) && ldbt->javainfo->array != NULL) {
  77. F_CLR(dbt, DB_DBT_REALLOC);
  78. F_SET(dbt, DB_DBT_USERMEM);
  79. F_SET(ldbt, LOCKED_REALLOC_NONNULL);
  80. }
  81. if ((F_ISSET(dbt, DB_DBT_USERMEM) || kind != outOp) &&
  82.     !F_ISSET(ldbt, LOCKED_CREATE_DATA)) {
  83. /*
  84.  * If writing with DB_DBT_USERMEM
  85.  * or it's a set (or get/set) operation,
  86.  * then the data should point to a java array.
  87.  * Note that outOp means data is coming out of the database
  88.  * (it's a get).  inOp means data is going into the database
  89.  * (either a put, or a key input).
  90.  */
  91. if (!ldbt->javainfo->array) {
  92. report_exception(jnienv, "Dbt.data is null", 0, 0);
  93. F_SET(ldbt, LOCKED_ERROR);
  94. return (EINVAL);
  95. }
  96. /* Verify other parameters */
  97. ldbt->java_array_len = (*jnienv)->GetArrayLength(jnienv,
  98. ldbt->javainfo->array);
  99. if (ldbt->javainfo->offset < 0 ) {
  100. report_exception(jnienv, "Dbt.offset illegal", 0, 0);
  101. F_SET(ldbt, LOCKED_ERROR);
  102. return (EINVAL);
  103. }
  104. if (dbt->size + ldbt->javainfo->offset > ldbt->java_array_len) {
  105. report_exception(jnienv,
  106.  "Dbt.size + Dbt.offset greater than array length",
  107.  0, 0);
  108. F_SET(ldbt, LOCKED_ERROR);
  109. return (EINVAL);
  110. }
  111. ldbt->java_data = (*jnienv)->GetByteArrayElements(jnienv,
  112. ldbt->javainfo->array,
  113. (jboolean *)0);
  114. dbt->data = ldbt->before_data = ldbt->java_data +
  115. ldbt->javainfo->offset;
  116. }
  117. else if (!F_ISSET(ldbt, LOCKED_CREATE_DATA)) {
  118. /*
  119.  * If writing with DB_DBT_MALLOC or DB_DBT_REALLOC with
  120.  * a null array, then the data is allocated by DB.
  121.  */
  122. dbt->data = ldbt->before_data = 0;
  123. }
  124. /*
  125.  * RPC makes the assumption that if dbt->size is non-zero, there
  126.  * is data to copy from dbt->data.  We may have set dbt->size
  127.  * to a non-zero integer above but decided not to point
  128.  * dbt->data at anything.  (One example is if we're doing an outOp
  129.  * with an already-used Dbt whose values we expect to just
  130.  * overwrite.)
  131.  *
  132.  * Clean up the dbt fields so we don't run into trouble.
  133.  * (Note that doff, dlen, and flags all may contain meaningful
  134.  * values.)
  135.  */
  136. if (dbt->data == NULL)
  137. dbt->size = dbt->ulen = 0;
  138. F_SET(ldbt->javainfo, DBT_JAVAINFO_LOCKED);
  139. return (0);
  140. }
  141. /*
  142.  * locked_dbt_put must be called for any LOCKED_DBT struct before a
  143.  * java handler returns to the user.  It can be thought of as the
  144.  * LOCKED_DBT destructor.  It copies any information from temporary
  145.  * structures back to user accessible arrays, and of course must free
  146.  * memory and remove references.  The LOCKED_DBT itself is not freed,
  147.  * as it is expected to be a stack variable.
  148.  *
  149.  * Note that after this call, the LOCKED_DBT can still be used in
  150.  * limited ways, e.g. to look at values in the C DBT.
  151.  */
  152. void
  153. locked_dbt_put(LOCKED_DBT *ldbt, JNIEnv *jnienv, DB_ENV *dbenv)
  154. {
  155. DBT *dbt;
  156. dbt = &ldbt->javainfo->dbt;
  157. /*
  158.  * If the error flag was set, we never succeeded
  159.  * in allocating storage.
  160.  */
  161. if (F_ISSET(ldbt, LOCKED_ERROR))
  162. return;
  163. if (((F_ISSET(dbt, DB_DBT_USERMEM) ||
  164.       F_ISSET(ldbt, LOCKED_REALLOC_NONNULL)) ||
  165.      ldbt->kind == inOp) && !F_ISSET(ldbt, LOCKED_CREATE_DATA)) {
  166. /*
  167.  * If writing with DB_DBT_USERMEM or it's a set
  168.  * (or get/set) operation, then the data may be already in
  169.  * the java array, in which case, we just need to release it.
  170.  * If DB didn't put it in the array (indicated by the
  171.  * dbt->data changing), we need to do that
  172.  */
  173. if (ldbt->before_data != ldbt->java_data) {
  174. (*jnienv)->SetByteArrayRegion(jnienv,
  175.       ldbt->javainfo->array,
  176.       ldbt->javainfo->offset,
  177.       dbt->ulen,
  178.       ldbt->before_data);
  179. }
  180. (*jnienv)->ReleaseByteArrayElements(jnienv,
  181.     ldbt->javainfo->array,
  182.     ldbt->java_data, 0);
  183. dbt->data = 0;
  184. }
  185. else if (F_ISSET(dbt, DB_DBT_MALLOC | DB_DBT_REALLOC) &&
  186.     ldbt->kind != inOp && !F_ISSET(ldbt, LOCKED_CREATE_DATA)) {
  187. /*
  188.  * If writing with DB_DBT_MALLOC, or DB_DBT_REALLOC
  189.  * with a zero buffer, then the data was allocated by
  190.  * DB.  If dbt->data is zero, it means an error
  191.  * occurred (and should have been already reported).
  192.  */
  193. if (dbt->data) {
  194. /*
  195.  * In the case of SET_RANGE, the key is inOutOp
  196.  * and when not found, its data will be left as
  197.  * its original value.  Only copy and free it
  198.  * here if it has been allocated by DB
  199.  * (dbt->data has changed).
  200.  */
  201. if (dbt->data != ldbt->before_data) {
  202. jbyteArray newarr;
  203. if ((newarr = (*jnienv)->NewByteArray(jnienv,
  204.     dbt->size)) == NULL) {
  205. /* The JVM has posted an exception. */
  206. F_SET(ldbt, LOCKED_ERROR);
  207. return;
  208. }
  209. (*jnienv)->SetObjectField(jnienv, ldbt->jdbt,
  210.   fid_Dbt_data,
  211.   newarr);
  212. ldbt->javainfo->offset = 0;
  213. (*jnienv)->SetByteArrayRegion(jnienv,
  214.       newarr, 0, dbt->size,
  215.       (jbyte *)dbt->data);
  216. (void)__os_ufree(dbenv, dbt->data);
  217. dbt->data = 0;
  218. }
  219. }
  220. }
  221. /*
  222.  * The size field may have changed after a DB API call,
  223.  * so we set that back too.
  224.  */
  225. (*jnienv)->SetIntField(jnienv, ldbt->jdbt, fid_Dbt_size, dbt->size);
  226. ldbt->javainfo->array = NULL;
  227. F_CLR(ldbt->javainfo, DBT_JAVAINFO_LOCKED);
  228. }
  229. /*
  230.  * Realloc the java array to receive data if the DBT used
  231.  * DB_DBT_REALLOC flag with a non-null data array, and the last
  232.  * operation set the size field to an amount greater than ulen.
  233.  * Return 1 if these conditions are met, otherwise 0.  This is used
  234.  * internally to simulate the operations needed for DB_DBT_REALLOC.
  235.  */
  236. int locked_dbt_realloc(LOCKED_DBT *ldbt, JNIEnv *jnienv, DB_ENV *dbenv)
  237. {
  238. DBT *dbt;
  239. COMPQUIET(dbenv, NULL);
  240. dbt = &ldbt->javainfo->dbt;
  241. if (!F_ISSET(ldbt, LOCKED_REALLOC_NONNULL) ||
  242.     F_ISSET(ldbt, LOCKED_ERROR) || dbt->size <= dbt->ulen)
  243. return (0);
  244. (*jnienv)->ReleaseByteArrayElements(jnienv, ldbt->javainfo->array,
  245.     ldbt->java_data, 0);
  246. /*
  247.  * We allocate a new array of the needed size.
  248.  * We'll set the offset to 0, as the old offset
  249.  * really doesn't make any sense.
  250.  */
  251. if ((ldbt->javainfo->array = (*jnienv)->NewByteArray(jnienv,
  252.     dbt->size)) == NULL) {
  253. F_SET(ldbt, LOCKED_ERROR);
  254. return (0);
  255. }
  256. ldbt->java_array_len = dbt->ulen = dbt->size;
  257. ldbt->javainfo->offset = 0;
  258. (*jnienv)->SetObjectField(jnienv, ldbt->jdbt, fid_Dbt_data,
  259.     ldbt->javainfo->array);
  260. ldbt->java_data = (*jnienv)->GetByteArrayElements(jnienv,
  261.     ldbt->javainfo->array, (jboolean *)0);
  262. memcpy(ldbt->java_data, ldbt->before_data, dbt->ulen);
  263. dbt->data = ldbt->before_data = ldbt->java_data;
  264. return (1);
  265. }
  266. /****************************************************************
  267.  *
  268.  * Implementation of functions to manipulate LOCKED_STRING.
  269.  */
  270. int
  271. locked_string_get(LOCKED_STRING *ls, JNIEnv *jnienv, jstring jstr)
  272. {
  273. ls->jstr = jstr;
  274. if (jstr == 0)
  275. ls->string = 0;
  276. else
  277. ls->string = (*jnienv)->GetStringUTFChars(jnienv, jstr,
  278.   (jboolean *)0);
  279. return (0);
  280. }
  281. void locked_string_put(LOCKED_STRING *ls, JNIEnv *jnienv)
  282. {
  283. if (ls->jstr)
  284. (*jnienv)->ReleaseStringUTFChars(jnienv, ls->jstr, ls->string);
  285. }