comparatorjnicallback.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. // This file implements the callback "bridge" between Java and C++ for
  7. // ROCKSDB_NAMESPACE::Comparator
  8. #ifndef JAVA_ROCKSJNI_COMPARATORJNICALLBACK_H_
  9. #define JAVA_ROCKSJNI_COMPARATORJNICALLBACK_H_
  10. #include <jni.h>
  11. #include <memory>
  12. #include <string>
  13. #include "rocksjni/jnicallback.h"
  14. #include "rocksdb/comparator.h"
  15. #include "rocksdb/slice.h"
  16. #include "port/port.h"
  17. #include "util/thread_local.h"
  18. namespace ROCKSDB_NAMESPACE {
  19. enum ReusedSynchronisationType {
  20. /**
  21. * Standard mutex.
  22. */
  23. MUTEX,
  24. /**
  25. * Use adaptive mutex, which spins in the user space before resorting
  26. * to kernel. This could reduce context switch when the mutex is not
  27. * heavily contended. However, if the mutex is hot, we could end up
  28. * wasting spin time.
  29. */
  30. ADAPTIVE_MUTEX,
  31. /**
  32. * There is a reused buffer per-thread.
  33. */
  34. THREAD_LOCAL
  35. };
  36. struct ComparatorJniCallbackOptions {
  37. // Set the synchronisation type used to guard the reused buffers.
  38. // Only used if max_reused_buffer_size > 0.
  39. // Default: ADAPTIVE_MUTEX
  40. ReusedSynchronisationType reused_synchronisation_type =
  41. ReusedSynchronisationType::ADAPTIVE_MUTEX;
  42. // Indicates if a direct byte buffer (i.e. outside of the normal
  43. // garbage-collected heap) is used for the callbacks to Java,
  44. // as opposed to a non-direct byte buffer which is a wrapper around
  45. // an on-heap byte[].
  46. // Default: true
  47. bool direct_buffer = true;
  48. // Maximum size of a buffer (in bytes) that will be reused.
  49. // Comparators will use 5 of these buffers,
  50. // so the retained memory size will be 5 * max_reused_buffer_size.
  51. // When a buffer is needed for transferring data to a callback,
  52. // if it requires less than max_reused_buffer_size, then an
  53. // existing buffer will be reused, else a new buffer will be
  54. // allocated just for that callback. -1 to disable.
  55. // Default: 64 bytes
  56. int32_t max_reused_buffer_size = 64;
  57. };
  58. /**
  59. * This class acts as a bridge between C++
  60. * and Java. The methods in this class will be
  61. * called back from the RocksDB storage engine (C++)
  62. * we then callback to the appropriate Java method
  63. * this enables Comparators to be implemented in Java.
  64. *
  65. * The design of this Comparator caches the Java Slice
  66. * objects that are used in the compare and findShortestSeparator
  67. * method callbacks. Instead of creating new objects for each callback
  68. * of those functions, by reuse via setHandle we are a lot
  69. * faster; Unfortunately this means that we have to
  70. * introduce independent locking in regions of each of those methods
  71. * via the mutexs mtx_compare and mtx_findShortestSeparator respectively
  72. */
  73. class ComparatorJniCallback : public JniCallback, public Comparator {
  74. public:
  75. ComparatorJniCallback(
  76. JNIEnv* env, jobject jcomparator,
  77. const ComparatorJniCallbackOptions* options);
  78. ~ComparatorJniCallback();
  79. virtual const char* Name() const;
  80. virtual int Compare(const Slice& a, const Slice& b) const;
  81. virtual void FindShortestSeparator(
  82. std::string* start, const Slice& limit) const;
  83. virtual void FindShortSuccessor(std::string* key) const;
  84. const ComparatorJniCallbackOptions* m_options;
  85. private:
  86. struct ThreadLocalBuf {
  87. ThreadLocalBuf(JavaVM* _jvm, bool _direct_buffer, jobject _jbuf) :
  88. jvm(_jvm), direct_buffer(_direct_buffer), jbuf(_jbuf) {}
  89. JavaVM* jvm;
  90. bool direct_buffer;
  91. jobject jbuf;
  92. };
  93. inline void MaybeLockForReuse(const std::unique_ptr<port::Mutex>& mutex,
  94. const bool cond) const;
  95. inline void MaybeUnlockForReuse(const std::unique_ptr<port::Mutex>& mutex,
  96. const bool cond) const;
  97. jobject GetBuffer(JNIEnv* env, const Slice& src, bool reuse_buffer,
  98. ThreadLocalPtr* tl_buf, jobject jreuse_buffer) const;
  99. jobject ReuseBuffer(JNIEnv* env, const Slice& src,
  100. jobject jreuse_buffer) const;
  101. jobject NewBuffer(JNIEnv* env, const Slice& src) const;
  102. void DeleteBuffer(JNIEnv* env, jobject jbuffer) const;
  103. // used for synchronisation in compare method
  104. std::unique_ptr<port::Mutex> mtx_compare;
  105. // used for synchronisation in findShortestSeparator method
  106. std::unique_ptr<port::Mutex> mtx_shortest;
  107. // used for synchronisation in findShortSuccessor method
  108. std::unique_ptr<port::Mutex> mtx_short;
  109. std::unique_ptr<const char[]> m_name;
  110. jclass m_abstract_comparator_jni_bridge_clazz; // TODO(AR) could we make this static somehow?
  111. jclass m_jbytebuffer_clazz; // TODO(AR) we could cache this globally for the entire VM if we switch more APIs to use ByteBuffer // TODO(AR) could we make this static somehow?
  112. jmethodID m_jcompare_mid; // TODO(AR) could we make this static somehow?
  113. jmethodID m_jshortest_mid; // TODO(AR) could we make this static somehow?
  114. jmethodID m_jshort_mid; // TODO(AR) could we make this static somehow?
  115. jobject m_jcompare_buf_a;
  116. jobject m_jcompare_buf_b;
  117. jobject m_jshortest_buf_start;
  118. jobject m_jshortest_buf_limit;
  119. jobject m_jshort_buf_key;
  120. ThreadLocalPtr* m_tl_buf_a;
  121. ThreadLocalPtr* m_tl_buf_b;
  122. };
  123. } // namespace ROCKSDB_NAMESPACE
  124. #endif // JAVA_ROCKSJNI_COMPARATORJNICALLBACK_H_