writebatchhandlerjnicallback.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  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. #include "rocksjni/writebatchhandlerjnicallback.h"
  9. #include "rocksjni/portal.h"
  10. namespace ROCKSDB_NAMESPACE {
  11. WriteBatchHandlerJniCallback::WriteBatchHandlerJniCallback(
  12. JNIEnv* env, jobject jWriteBatchHandler)
  13. : JniCallback(env, jWriteBatchHandler), m_env(env) {
  14. m_jPutCfMethodId = WriteBatchHandlerJni::getPutCfMethodId(env);
  15. if (m_jPutCfMethodId == nullptr) {
  16. // exception thrown
  17. return;
  18. }
  19. m_jPutMethodId = WriteBatchHandlerJni::getPutMethodId(env);
  20. if (m_jPutMethodId == nullptr) {
  21. // exception thrown
  22. return;
  23. }
  24. m_jMergeCfMethodId = WriteBatchHandlerJni::getMergeCfMethodId(env);
  25. if (m_jMergeCfMethodId == nullptr) {
  26. // exception thrown
  27. return;
  28. }
  29. m_jMergeMethodId = WriteBatchHandlerJni::getMergeMethodId(env);
  30. if (m_jMergeMethodId == nullptr) {
  31. // exception thrown
  32. return;
  33. }
  34. m_jDeleteCfMethodId = WriteBatchHandlerJni::getDeleteCfMethodId(env);
  35. if (m_jDeleteCfMethodId == nullptr) {
  36. // exception thrown
  37. return;
  38. }
  39. m_jDeleteMethodId = WriteBatchHandlerJni::getDeleteMethodId(env);
  40. if (m_jDeleteMethodId == nullptr) {
  41. // exception thrown
  42. return;
  43. }
  44. m_jSingleDeleteCfMethodId =
  45. WriteBatchHandlerJni::getSingleDeleteCfMethodId(env);
  46. if (m_jSingleDeleteCfMethodId == nullptr) {
  47. // exception thrown
  48. return;
  49. }
  50. m_jSingleDeleteMethodId = WriteBatchHandlerJni::getSingleDeleteMethodId(env);
  51. if (m_jSingleDeleteMethodId == nullptr) {
  52. // exception thrown
  53. return;
  54. }
  55. m_jDeleteRangeCfMethodId =
  56. WriteBatchHandlerJni::getDeleteRangeCfMethodId(env);
  57. if (m_jDeleteRangeCfMethodId == nullptr) {
  58. // exception thrown
  59. return;
  60. }
  61. m_jDeleteRangeMethodId = WriteBatchHandlerJni::getDeleteRangeMethodId(env);
  62. if (m_jDeleteRangeMethodId == nullptr) {
  63. // exception thrown
  64. return;
  65. }
  66. m_jLogDataMethodId = WriteBatchHandlerJni::getLogDataMethodId(env);
  67. if (m_jLogDataMethodId == nullptr) {
  68. // exception thrown
  69. return;
  70. }
  71. m_jPutBlobIndexCfMethodId =
  72. WriteBatchHandlerJni::getPutBlobIndexCfMethodId(env);
  73. if (m_jPutBlobIndexCfMethodId == nullptr) {
  74. // exception thrown
  75. return;
  76. }
  77. m_jMarkBeginPrepareMethodId =
  78. WriteBatchHandlerJni::getMarkBeginPrepareMethodId(env);
  79. if (m_jMarkBeginPrepareMethodId == nullptr) {
  80. // exception thrown
  81. return;
  82. }
  83. m_jMarkEndPrepareMethodId =
  84. WriteBatchHandlerJni::getMarkEndPrepareMethodId(env);
  85. if (m_jMarkEndPrepareMethodId == nullptr) {
  86. // exception thrown
  87. return;
  88. }
  89. m_jMarkNoopMethodId = WriteBatchHandlerJni::getMarkNoopMethodId(env);
  90. if (m_jMarkNoopMethodId == nullptr) {
  91. // exception thrown
  92. return;
  93. }
  94. m_jMarkRollbackMethodId = WriteBatchHandlerJni::getMarkRollbackMethodId(env);
  95. if (m_jMarkRollbackMethodId == nullptr) {
  96. // exception thrown
  97. return;
  98. }
  99. m_jMarkCommitMethodId = WriteBatchHandlerJni::getMarkCommitMethodId(env);
  100. if (m_jMarkCommitMethodId == nullptr) {
  101. // exception thrown
  102. return;
  103. }
  104. m_jMarkCommitWithTimestampMethodId =
  105. WriteBatchHandlerJni::getMarkCommitWithTimestampMethodId(env);
  106. if (m_jMarkCommitWithTimestampMethodId == nullptr) {
  107. // exception thrown
  108. return;
  109. }
  110. m_jContinueMethodId = WriteBatchHandlerJni::getContinueMethodId(env);
  111. if (m_jContinueMethodId == nullptr) {
  112. // exception thrown
  113. return;
  114. }
  115. }
  116. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::PutCF(
  117. uint32_t column_family_id, const Slice& key, const Slice& value) {
  118. auto put = [this, column_family_id](jbyteArray j_key, jbyteArray j_value) {
  119. m_env->CallVoidMethod(m_jcallback_obj, m_jPutCfMethodId,
  120. static_cast<jint>(column_family_id), j_key, j_value);
  121. };
  122. auto status = WriteBatchHandlerJniCallback::kv_op(key, value, put);
  123. if (status == nullptr) {
  124. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  125. // an Exception but we don't know
  126. // the ROCKSDB_NAMESPACE::Status?
  127. } else {
  128. return ROCKSDB_NAMESPACE::Status(*status);
  129. }
  130. }
  131. void WriteBatchHandlerJniCallback::Put(const Slice& key, const Slice& value) {
  132. auto put = [this](jbyteArray j_key, jbyteArray j_value) {
  133. m_env->CallVoidMethod(m_jcallback_obj, m_jPutMethodId, j_key, j_value);
  134. };
  135. WriteBatchHandlerJniCallback::kv_op(key, value, put);
  136. }
  137. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::MergeCF(
  138. uint32_t column_family_id, const Slice& key, const Slice& value) {
  139. auto merge = [this, column_family_id](jbyteArray j_key, jbyteArray j_value) {
  140. m_env->CallVoidMethod(m_jcallback_obj, m_jMergeCfMethodId,
  141. static_cast<jint>(column_family_id), j_key, j_value);
  142. };
  143. auto status = WriteBatchHandlerJniCallback::kv_op(key, value, merge);
  144. if (status == nullptr) {
  145. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  146. // an Exception but we don't know
  147. // the ROCKSDB_NAMESPACE::Status?
  148. } else {
  149. return ROCKSDB_NAMESPACE::Status(*status);
  150. }
  151. }
  152. void WriteBatchHandlerJniCallback::Merge(const Slice& key, const Slice& value) {
  153. auto merge = [this](jbyteArray j_key, jbyteArray j_value) {
  154. m_env->CallVoidMethod(m_jcallback_obj, m_jMergeMethodId, j_key, j_value);
  155. };
  156. WriteBatchHandlerJniCallback::kv_op(key, value, merge);
  157. }
  158. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::DeleteCF(
  159. uint32_t column_family_id, const Slice& key) {
  160. auto remove = [this, column_family_id](jbyteArray j_key) {
  161. m_env->CallVoidMethod(m_jcallback_obj, m_jDeleteCfMethodId,
  162. static_cast<jint>(column_family_id), j_key);
  163. };
  164. auto status = WriteBatchHandlerJniCallback::k_op(key, remove);
  165. if (status == nullptr) {
  166. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  167. // an Exception but we don't know
  168. // the ROCKSDB_NAMESPACE::Status?
  169. } else {
  170. return ROCKSDB_NAMESPACE::Status(*status);
  171. }
  172. }
  173. void WriteBatchHandlerJniCallback::Delete(const Slice& key) {
  174. auto remove = [this](jbyteArray j_key) {
  175. m_env->CallVoidMethod(m_jcallback_obj, m_jDeleteMethodId, j_key);
  176. };
  177. WriteBatchHandlerJniCallback::k_op(key, remove);
  178. }
  179. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::SingleDeleteCF(
  180. uint32_t column_family_id, const Slice& key) {
  181. auto singleDelete = [this, column_family_id](jbyteArray j_key) {
  182. m_env->CallVoidMethod(m_jcallback_obj, m_jSingleDeleteCfMethodId,
  183. static_cast<jint>(column_family_id), j_key);
  184. };
  185. auto status = WriteBatchHandlerJniCallback::k_op(key, singleDelete);
  186. if (status == nullptr) {
  187. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  188. // an Exception but we don't know
  189. // the ROCKSDB_NAMESPACE::Status?
  190. } else {
  191. return ROCKSDB_NAMESPACE::Status(*status);
  192. }
  193. }
  194. void WriteBatchHandlerJniCallback::SingleDelete(const Slice& key) {
  195. auto singleDelete = [this](jbyteArray j_key) {
  196. m_env->CallVoidMethod(m_jcallback_obj, m_jSingleDeleteMethodId, j_key);
  197. };
  198. WriteBatchHandlerJniCallback::k_op(key, singleDelete);
  199. }
  200. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::DeleteRangeCF(
  201. uint32_t column_family_id, const Slice& beginKey, const Slice& endKey) {
  202. auto deleteRange = [this, column_family_id](jbyteArray j_beginKey,
  203. jbyteArray j_endKey) {
  204. m_env->CallVoidMethod(m_jcallback_obj, m_jDeleteRangeCfMethodId,
  205. static_cast<jint>(column_family_id), j_beginKey,
  206. j_endKey);
  207. };
  208. auto status =
  209. WriteBatchHandlerJniCallback::kv_op(beginKey, endKey, deleteRange);
  210. if (status == nullptr) {
  211. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  212. // an Exception but we don't know
  213. // the ROCKSDB_NAMESPACE::Status?
  214. } else {
  215. return ROCKSDB_NAMESPACE::Status(*status);
  216. }
  217. }
  218. void WriteBatchHandlerJniCallback::DeleteRange(const Slice& beginKey,
  219. const Slice& endKey) {
  220. auto deleteRange = [this](jbyteArray j_beginKey, jbyteArray j_endKey) {
  221. m_env->CallVoidMethod(m_jcallback_obj, m_jDeleteRangeMethodId, j_beginKey,
  222. j_endKey);
  223. };
  224. WriteBatchHandlerJniCallback::kv_op(beginKey, endKey, deleteRange);
  225. }
  226. void WriteBatchHandlerJniCallback::LogData(const Slice& blob) {
  227. auto logData = [this](jbyteArray j_blob) {
  228. m_env->CallVoidMethod(m_jcallback_obj, m_jLogDataMethodId, j_blob);
  229. };
  230. WriteBatchHandlerJniCallback::k_op(blob, logData);
  231. }
  232. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::PutBlobIndexCF(
  233. uint32_t column_family_id, const Slice& key, const Slice& value) {
  234. auto putBlobIndex = [this, column_family_id](jbyteArray j_key,
  235. jbyteArray j_value) {
  236. m_env->CallVoidMethod(m_jcallback_obj, m_jPutBlobIndexCfMethodId,
  237. static_cast<jint>(column_family_id), j_key, j_value);
  238. };
  239. auto status = WriteBatchHandlerJniCallback::kv_op(key, value, putBlobIndex);
  240. if (status == nullptr) {
  241. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  242. // an Exception but we don't know
  243. // the ROCKSDB_NAMESPACE::Status?
  244. } else {
  245. return ROCKSDB_NAMESPACE::Status(*status);
  246. }
  247. }
  248. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::MarkBeginPrepare(
  249. bool unprepare) {
  250. #ifndef DEBUG
  251. (void)unprepare;
  252. #else
  253. assert(!unprepare);
  254. #endif
  255. m_env->CallVoidMethod(m_jcallback_obj, m_jMarkBeginPrepareMethodId);
  256. // check for Exception, in-particular RocksDBException
  257. if (m_env->ExceptionCheck()) {
  258. // exception thrown
  259. jthrowable exception = m_env->ExceptionOccurred();
  260. std::unique_ptr<ROCKSDB_NAMESPACE::Status> status =
  261. ROCKSDB_NAMESPACE::RocksDBExceptionJni::toCppStatus(m_env, exception);
  262. if (status == nullptr) {
  263. // unkown status or exception occurred extracting status
  264. m_env->ExceptionDescribe();
  265. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) probably need a
  266. // better error code here
  267. } else {
  268. m_env->ExceptionClear(); // clear the exception, as we have extracted the
  269. // status
  270. return ROCKSDB_NAMESPACE::Status(*status);
  271. }
  272. }
  273. return ROCKSDB_NAMESPACE::Status::OK();
  274. }
  275. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::MarkEndPrepare(
  276. const Slice& xid) {
  277. auto markEndPrepare = [this](jbyteArray j_xid) {
  278. m_env->CallVoidMethod(m_jcallback_obj, m_jMarkEndPrepareMethodId, j_xid);
  279. };
  280. auto status = WriteBatchHandlerJniCallback::k_op(xid, markEndPrepare);
  281. if (status == nullptr) {
  282. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  283. // an Exception but we don't know
  284. // the ROCKSDB_NAMESPACE::Status?
  285. } else {
  286. return ROCKSDB_NAMESPACE::Status(*status);
  287. }
  288. }
  289. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::MarkNoop(
  290. bool empty_batch) {
  291. m_env->CallVoidMethod(m_jcallback_obj, m_jMarkNoopMethodId,
  292. static_cast<jboolean>(empty_batch));
  293. // check for Exception, in-particular RocksDBException
  294. if (m_env->ExceptionCheck()) {
  295. // exception thrown
  296. jthrowable exception = m_env->ExceptionOccurred();
  297. std::unique_ptr<ROCKSDB_NAMESPACE::Status> status =
  298. ROCKSDB_NAMESPACE::RocksDBExceptionJni::toCppStatus(m_env, exception);
  299. if (status == nullptr) {
  300. // unkown status or exception occurred extracting status
  301. m_env->ExceptionDescribe();
  302. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) probably need a
  303. // better error code here
  304. } else {
  305. m_env->ExceptionClear(); // clear the exception, as we have extracted the
  306. // status
  307. return ROCKSDB_NAMESPACE::Status(*status);
  308. }
  309. }
  310. return ROCKSDB_NAMESPACE::Status::OK();
  311. }
  312. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::MarkRollback(
  313. const Slice& xid) {
  314. auto markRollback = [this](jbyteArray j_xid) {
  315. m_env->CallVoidMethod(m_jcallback_obj, m_jMarkRollbackMethodId, j_xid);
  316. };
  317. auto status = WriteBatchHandlerJniCallback::k_op(xid, markRollback);
  318. if (status == nullptr) {
  319. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  320. // an Exception but we don't know
  321. // the ROCKSDB_NAMESPACE::Status?
  322. } else {
  323. return ROCKSDB_NAMESPACE::Status(*status);
  324. }
  325. }
  326. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::MarkCommit(
  327. const Slice& xid) {
  328. auto markCommit = [this](jbyteArray j_xid) {
  329. m_env->CallVoidMethod(m_jcallback_obj, m_jMarkCommitMethodId, j_xid);
  330. };
  331. auto status = WriteBatchHandlerJniCallback::k_op(xid, markCommit);
  332. if (status == nullptr) {
  333. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  334. // an Exception but we don't know
  335. // the ROCKSDB_NAMESPACE::Status?
  336. } else {
  337. return ROCKSDB_NAMESPACE::Status(*status);
  338. }
  339. }
  340. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::MarkCommitWithTimestamp(
  341. const Slice& xid, const Slice& ts) {
  342. auto markCommitWithTimestamp = [this](jbyteArray j_xid, jbyteArray j_ts) {
  343. m_env->CallVoidMethod(m_jcallback_obj, m_jMarkCommitWithTimestampMethodId,
  344. j_xid, j_ts);
  345. };
  346. auto status =
  347. WriteBatchHandlerJniCallback::kv_op(xid, ts, markCommitWithTimestamp);
  348. if (status == nullptr) {
  349. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  350. // an Exception but we don't know
  351. // the ROCKSDB_NAMESPACE::Status?
  352. } else {
  353. return ROCKSDB_NAMESPACE::Status(*status);
  354. }
  355. }
  356. bool WriteBatchHandlerJniCallback::Continue() {
  357. jboolean jContinue =
  358. m_env->CallBooleanMethod(m_jcallback_obj, m_jContinueMethodId);
  359. if (m_env->ExceptionCheck()) {
  360. // exception thrown
  361. m_env->ExceptionDescribe();
  362. }
  363. return static_cast<bool>(jContinue == JNI_TRUE);
  364. }
  365. std::unique_ptr<ROCKSDB_NAMESPACE::Status> WriteBatchHandlerJniCallback::kv_op(
  366. const Slice& key, const Slice& value,
  367. std::function<void(jbyteArray, jbyteArray)> kvFn) {
  368. const jbyteArray j_key = JniUtil::copyBytes(m_env, key);
  369. if (j_key == nullptr) {
  370. // exception thrown
  371. if (m_env->ExceptionCheck()) {
  372. m_env->ExceptionDescribe();
  373. }
  374. return nullptr;
  375. }
  376. const jbyteArray j_value = JniUtil::copyBytes(m_env, value);
  377. if (j_value == nullptr) {
  378. // exception thrown
  379. if (m_env->ExceptionCheck()) {
  380. m_env->ExceptionDescribe();
  381. }
  382. if (j_key != nullptr) {
  383. m_env->DeleteLocalRef(j_key);
  384. }
  385. return nullptr;
  386. }
  387. kvFn(j_key, j_value);
  388. // check for Exception, in-particular RocksDBException
  389. if (m_env->ExceptionCheck()) {
  390. if (j_value != nullptr) {
  391. m_env->DeleteLocalRef(j_value);
  392. }
  393. if (j_key != nullptr) {
  394. m_env->DeleteLocalRef(j_key);
  395. }
  396. // exception thrown
  397. jthrowable exception = m_env->ExceptionOccurred();
  398. std::unique_ptr<ROCKSDB_NAMESPACE::Status> status =
  399. ROCKSDB_NAMESPACE::RocksDBExceptionJni::toCppStatus(m_env, exception);
  400. if (status == nullptr) {
  401. // unkown status or exception occurred extracting status
  402. m_env->ExceptionDescribe();
  403. return nullptr;
  404. } else {
  405. m_env->ExceptionClear(); // clear the exception, as we have extracted the
  406. // status
  407. return status;
  408. }
  409. }
  410. if (j_value != nullptr) {
  411. m_env->DeleteLocalRef(j_value);
  412. }
  413. if (j_key != nullptr) {
  414. m_env->DeleteLocalRef(j_key);
  415. }
  416. // all OK
  417. return std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
  418. new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::OK()));
  419. }
  420. std::unique_ptr<ROCKSDB_NAMESPACE::Status> WriteBatchHandlerJniCallback::k_op(
  421. const Slice& key, std::function<void(jbyteArray)> kFn) {
  422. const jbyteArray j_key = JniUtil::copyBytes(m_env, key);
  423. if (j_key == nullptr) {
  424. // exception thrown
  425. if (m_env->ExceptionCheck()) {
  426. m_env->ExceptionDescribe();
  427. }
  428. return nullptr;
  429. }
  430. kFn(j_key);
  431. // check for Exception, in-particular RocksDBException
  432. if (m_env->ExceptionCheck()) {
  433. if (j_key != nullptr) {
  434. m_env->DeleteLocalRef(j_key);
  435. }
  436. // exception thrown
  437. jthrowable exception = m_env->ExceptionOccurred();
  438. std::unique_ptr<ROCKSDB_NAMESPACE::Status> status =
  439. ROCKSDB_NAMESPACE::RocksDBExceptionJni::toCppStatus(m_env, exception);
  440. if (status == nullptr) {
  441. // unkown status or exception occurred extracting status
  442. m_env->ExceptionDescribe();
  443. return nullptr;
  444. } else {
  445. m_env->ExceptionClear(); // clear the exception, as we have extracted the
  446. // status
  447. return status;
  448. }
  449. }
  450. if (j_key != nullptr) {
  451. m_env->DeleteLocalRef(j_key);
  452. }
  453. // all OK
  454. return std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
  455. new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::OK()));
  456. }
  457. } // namespace ROCKSDB_NAMESPACE