writebatchhandlerjnicallback.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  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_jContinueMethodId = WriteBatchHandlerJni::getContinueMethodId(env);
  105. if(m_jContinueMethodId == nullptr) {
  106. // exception thrown
  107. return;
  108. }
  109. }
  110. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::PutCF(
  111. uint32_t column_family_id, const Slice& key, const Slice& value) {
  112. auto put = [this, column_family_id] (
  113. jbyteArray j_key, jbyteArray j_value) {
  114. m_env->CallVoidMethod(
  115. m_jcallback_obj,
  116. m_jPutCfMethodId,
  117. static_cast<jint>(column_family_id),
  118. j_key,
  119. j_value);
  120. };
  121. auto status = WriteBatchHandlerJniCallback::kv_op(key, value, put);
  122. if(status == nullptr) {
  123. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  124. // an Exception but we don't know
  125. // the ROCKSDB_NAMESPACE::Status?
  126. } else {
  127. return ROCKSDB_NAMESPACE::Status(*status);
  128. }
  129. }
  130. void WriteBatchHandlerJniCallback::Put(const Slice& key, const Slice& value) {
  131. auto put = [this] (
  132. jbyteArray j_key, jbyteArray j_value) {
  133. m_env->CallVoidMethod(
  134. m_jcallback_obj,
  135. m_jPutMethodId,
  136. j_key,
  137. j_value);
  138. };
  139. WriteBatchHandlerJniCallback::kv_op(key, value, put);
  140. }
  141. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::MergeCF(
  142. uint32_t column_family_id, const Slice& key, const Slice& value) {
  143. auto merge = [this, column_family_id] (
  144. jbyteArray j_key, jbyteArray j_value) {
  145. m_env->CallVoidMethod(
  146. m_jcallback_obj,
  147. m_jMergeCfMethodId,
  148. static_cast<jint>(column_family_id),
  149. j_key,
  150. j_value);
  151. };
  152. auto status = WriteBatchHandlerJniCallback::kv_op(key, value, merge);
  153. if(status == nullptr) {
  154. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  155. // an Exception but we don't know
  156. // the ROCKSDB_NAMESPACE::Status?
  157. } else {
  158. return ROCKSDB_NAMESPACE::Status(*status);
  159. }
  160. }
  161. void WriteBatchHandlerJniCallback::Merge(const Slice& key, const Slice& value) {
  162. auto merge = [this] (
  163. jbyteArray j_key, jbyteArray j_value) {
  164. m_env->CallVoidMethod(
  165. m_jcallback_obj,
  166. m_jMergeMethodId,
  167. j_key,
  168. j_value);
  169. };
  170. WriteBatchHandlerJniCallback::kv_op(key, value, merge);
  171. }
  172. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::DeleteCF(
  173. uint32_t column_family_id, const Slice& key) {
  174. auto remove = [this, column_family_id] (jbyteArray j_key) {
  175. m_env->CallVoidMethod(
  176. m_jcallback_obj,
  177. m_jDeleteCfMethodId,
  178. static_cast<jint>(column_family_id),
  179. j_key);
  180. };
  181. auto status = WriteBatchHandlerJniCallback::k_op(key, remove);
  182. if(status == nullptr) {
  183. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  184. // an Exception but we don't know
  185. // the ROCKSDB_NAMESPACE::Status?
  186. } else {
  187. return ROCKSDB_NAMESPACE::Status(*status);
  188. }
  189. }
  190. void WriteBatchHandlerJniCallback::Delete(const Slice& key) {
  191. auto remove = [this] (jbyteArray j_key) {
  192. m_env->CallVoidMethod(
  193. m_jcallback_obj,
  194. m_jDeleteMethodId,
  195. j_key);
  196. };
  197. WriteBatchHandlerJniCallback::k_op(key, remove);
  198. }
  199. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::SingleDeleteCF(
  200. uint32_t column_family_id, const Slice& key) {
  201. auto singleDelete = [this, column_family_id] (jbyteArray j_key) {
  202. m_env->CallVoidMethod(
  203. m_jcallback_obj,
  204. m_jSingleDeleteCfMethodId,
  205. static_cast<jint>(column_family_id),
  206. j_key);
  207. };
  208. auto status = WriteBatchHandlerJniCallback::k_op(key, singleDelete);
  209. if(status == nullptr) {
  210. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  211. // an Exception but we don't know
  212. // the ROCKSDB_NAMESPACE::Status?
  213. } else {
  214. return ROCKSDB_NAMESPACE::Status(*status);
  215. }
  216. }
  217. void WriteBatchHandlerJniCallback::SingleDelete(const Slice& key) {
  218. auto singleDelete = [this] (jbyteArray j_key) {
  219. m_env->CallVoidMethod(
  220. m_jcallback_obj,
  221. m_jSingleDeleteMethodId,
  222. j_key);
  223. };
  224. WriteBatchHandlerJniCallback::k_op(key, singleDelete);
  225. }
  226. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::DeleteRangeCF(
  227. uint32_t column_family_id, const Slice& beginKey, const Slice& endKey) {
  228. auto deleteRange = [this, column_family_id] (
  229. jbyteArray j_beginKey, jbyteArray j_endKey) {
  230. m_env->CallVoidMethod(
  231. m_jcallback_obj,
  232. m_jDeleteRangeCfMethodId,
  233. static_cast<jint>(column_family_id),
  234. j_beginKey,
  235. j_endKey);
  236. };
  237. auto status = WriteBatchHandlerJniCallback::kv_op(beginKey, endKey, deleteRange);
  238. if(status == nullptr) {
  239. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  240. // an Exception but we don't know
  241. // the ROCKSDB_NAMESPACE::Status?
  242. } else {
  243. return ROCKSDB_NAMESPACE::Status(*status);
  244. }
  245. }
  246. void WriteBatchHandlerJniCallback::DeleteRange(const Slice& beginKey,
  247. const Slice& endKey) {
  248. auto deleteRange = [this] (
  249. jbyteArray j_beginKey, jbyteArray j_endKey) {
  250. m_env->CallVoidMethod(
  251. m_jcallback_obj,
  252. m_jDeleteRangeMethodId,
  253. j_beginKey,
  254. j_endKey);
  255. };
  256. WriteBatchHandlerJniCallback::kv_op(beginKey, endKey, deleteRange);
  257. }
  258. void WriteBatchHandlerJniCallback::LogData(const Slice& blob) {
  259. auto logData = [this] (jbyteArray j_blob) {
  260. m_env->CallVoidMethod(
  261. m_jcallback_obj,
  262. m_jLogDataMethodId,
  263. j_blob);
  264. };
  265. WriteBatchHandlerJniCallback::k_op(blob, logData);
  266. }
  267. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::PutBlobIndexCF(
  268. uint32_t column_family_id, const Slice& key, const Slice& value) {
  269. auto putBlobIndex = [this, column_family_id] (
  270. jbyteArray j_key, jbyteArray j_value) {
  271. m_env->CallVoidMethod(
  272. m_jcallback_obj,
  273. m_jPutBlobIndexCfMethodId,
  274. static_cast<jint>(column_family_id),
  275. j_key,
  276. j_value);
  277. };
  278. auto status = WriteBatchHandlerJniCallback::kv_op(key, value, putBlobIndex);
  279. if(status == nullptr) {
  280. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  281. // an Exception but we don't know
  282. // the ROCKSDB_NAMESPACE::Status?
  283. } else {
  284. return ROCKSDB_NAMESPACE::Status(*status);
  285. }
  286. }
  287. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::MarkBeginPrepare(
  288. bool unprepare) {
  289. #ifndef DEBUG
  290. (void) unprepare;
  291. #else
  292. assert(!unprepare);
  293. #endif
  294. m_env->CallVoidMethod(m_jcallback_obj, m_jMarkBeginPrepareMethodId);
  295. // check for Exception, in-particular RocksDBException
  296. if (m_env->ExceptionCheck()) {
  297. // exception thrown
  298. jthrowable exception = m_env->ExceptionOccurred();
  299. std::unique_ptr<ROCKSDB_NAMESPACE::Status> status =
  300. ROCKSDB_NAMESPACE::RocksDBExceptionJni::toCppStatus(m_env, exception);
  301. if (status == nullptr) {
  302. // unkown status or exception occurred extracting status
  303. m_env->ExceptionDescribe();
  304. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) probably need a
  305. // better error code here
  306. } else {
  307. m_env->ExceptionClear(); // clear the exception, as we have extracted the status
  308. return ROCKSDB_NAMESPACE::Status(*status);
  309. }
  310. }
  311. return ROCKSDB_NAMESPACE::Status::OK();
  312. }
  313. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::MarkEndPrepare(
  314. const Slice& xid) {
  315. auto markEndPrepare = [this] (
  316. jbyteArray j_xid) {
  317. m_env->CallVoidMethod(
  318. m_jcallback_obj,
  319. m_jMarkEndPrepareMethodId,
  320. j_xid);
  321. };
  322. auto status = WriteBatchHandlerJniCallback::k_op(xid, markEndPrepare);
  323. if(status == nullptr) {
  324. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  325. // an Exception but we don't know
  326. // the ROCKSDB_NAMESPACE::Status?
  327. } else {
  328. return ROCKSDB_NAMESPACE::Status(*status);
  329. }
  330. }
  331. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::MarkNoop(
  332. bool empty_batch) {
  333. m_env->CallVoidMethod(m_jcallback_obj, m_jMarkNoopMethodId, static_cast<jboolean>(empty_batch));
  334. // check for Exception, in-particular RocksDBException
  335. if (m_env->ExceptionCheck()) {
  336. // exception thrown
  337. jthrowable exception = m_env->ExceptionOccurred();
  338. std::unique_ptr<ROCKSDB_NAMESPACE::Status> status =
  339. ROCKSDB_NAMESPACE::RocksDBExceptionJni::toCppStatus(m_env, exception);
  340. if (status == nullptr) {
  341. // unkown status or exception occurred extracting status
  342. m_env->ExceptionDescribe();
  343. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) probably need a
  344. // better error code here
  345. } else {
  346. m_env->ExceptionClear(); // clear the exception, as we have extracted the status
  347. return ROCKSDB_NAMESPACE::Status(*status);
  348. }
  349. }
  350. return ROCKSDB_NAMESPACE::Status::OK();
  351. }
  352. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::MarkRollback(
  353. const Slice& xid) {
  354. auto markRollback = [this] (
  355. jbyteArray j_xid) {
  356. m_env->CallVoidMethod(
  357. m_jcallback_obj,
  358. m_jMarkRollbackMethodId,
  359. j_xid);
  360. };
  361. auto status = WriteBatchHandlerJniCallback::k_op(xid, markRollback);
  362. if(status == nullptr) {
  363. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  364. // an Exception but we don't know
  365. // the ROCKSDB_NAMESPACE::Status?
  366. } else {
  367. return ROCKSDB_NAMESPACE::Status(*status);
  368. }
  369. }
  370. ROCKSDB_NAMESPACE::Status WriteBatchHandlerJniCallback::MarkCommit(
  371. const Slice& xid) {
  372. auto markCommit = [this] (
  373. jbyteArray j_xid) {
  374. m_env->CallVoidMethod(
  375. m_jcallback_obj,
  376. m_jMarkCommitMethodId,
  377. j_xid);
  378. };
  379. auto status = WriteBatchHandlerJniCallback::k_op(xid, markCommit);
  380. if(status == nullptr) {
  381. return ROCKSDB_NAMESPACE::Status::OK(); // TODO(AR) what to do if there is
  382. // an Exception but we don't know
  383. // the ROCKSDB_NAMESPACE::Status?
  384. } else {
  385. return ROCKSDB_NAMESPACE::Status(*status);
  386. }
  387. }
  388. bool WriteBatchHandlerJniCallback::Continue() {
  389. jboolean jContinue = m_env->CallBooleanMethod(
  390. m_jcallback_obj,
  391. m_jContinueMethodId);
  392. if(m_env->ExceptionCheck()) {
  393. // exception thrown
  394. m_env->ExceptionDescribe();
  395. }
  396. return static_cast<bool>(jContinue == JNI_TRUE);
  397. }
  398. std::unique_ptr<ROCKSDB_NAMESPACE::Status> WriteBatchHandlerJniCallback::kv_op(
  399. const Slice& key, const Slice& value,
  400. std::function<void(jbyteArray, jbyteArray)> kvFn) {
  401. const jbyteArray j_key = JniUtil::copyBytes(m_env, key);
  402. if (j_key == nullptr) {
  403. // exception thrown
  404. if (m_env->ExceptionCheck()) {
  405. m_env->ExceptionDescribe();
  406. }
  407. return nullptr;
  408. }
  409. const jbyteArray j_value = JniUtil::copyBytes(m_env, value);
  410. if (j_value == nullptr) {
  411. // exception thrown
  412. if (m_env->ExceptionCheck()) {
  413. m_env->ExceptionDescribe();
  414. }
  415. if (j_key != nullptr) {
  416. m_env->DeleteLocalRef(j_key);
  417. }
  418. return nullptr;
  419. }
  420. kvFn(j_key, j_value);
  421. // check for Exception, in-particular RocksDBException
  422. if (m_env->ExceptionCheck()) {
  423. if (j_value != nullptr) {
  424. m_env->DeleteLocalRef(j_value);
  425. }
  426. if (j_key != nullptr) {
  427. m_env->DeleteLocalRef(j_key);
  428. }
  429. // exception thrown
  430. jthrowable exception = m_env->ExceptionOccurred();
  431. std::unique_ptr<ROCKSDB_NAMESPACE::Status> status =
  432. ROCKSDB_NAMESPACE::RocksDBExceptionJni::toCppStatus(m_env, exception);
  433. if (status == nullptr) {
  434. // unkown status or exception occurred extracting status
  435. m_env->ExceptionDescribe();
  436. return nullptr;
  437. } else {
  438. m_env->ExceptionClear(); // clear the exception, as we have extracted the status
  439. return status;
  440. }
  441. }
  442. if (j_value != nullptr) {
  443. m_env->DeleteLocalRef(j_value);
  444. }
  445. if (j_key != nullptr) {
  446. m_env->DeleteLocalRef(j_key);
  447. }
  448. // all OK
  449. return std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
  450. new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::OK()));
  451. }
  452. std::unique_ptr<ROCKSDB_NAMESPACE::Status> WriteBatchHandlerJniCallback::k_op(
  453. const Slice& key, std::function<void(jbyteArray)> kFn) {
  454. const jbyteArray j_key = JniUtil::copyBytes(m_env, key);
  455. if (j_key == nullptr) {
  456. // exception thrown
  457. if (m_env->ExceptionCheck()) {
  458. m_env->ExceptionDescribe();
  459. }
  460. return nullptr;
  461. }
  462. kFn(j_key);
  463. // check for Exception, in-particular RocksDBException
  464. if (m_env->ExceptionCheck()) {
  465. if (j_key != nullptr) {
  466. m_env->DeleteLocalRef(j_key);
  467. }
  468. // exception thrown
  469. jthrowable exception = m_env->ExceptionOccurred();
  470. std::unique_ptr<ROCKSDB_NAMESPACE::Status> status =
  471. ROCKSDB_NAMESPACE::RocksDBExceptionJni::toCppStatus(m_env, exception);
  472. if (status == nullptr) {
  473. // unkown status or exception occurred extracting status
  474. m_env->ExceptionDescribe();
  475. return nullptr;
  476. } else {
  477. m_env->ExceptionClear(); // clear the exception, as we have extracted the status
  478. return status;
  479. }
  480. }
  481. if (j_key != nullptr) {
  482. m_env->DeleteLocalRef(j_key);
  483. }
  484. // all OK
  485. return std::unique_ptr<ROCKSDB_NAMESPACE::Status>(
  486. new ROCKSDB_NAMESPACE::Status(ROCKSDB_NAMESPACE::Status::OK()));
  487. }
  488. } // namespace ROCKSDB_NAMESPACE