2016-02-10 00:12:00 +01:00
|
|
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
2017-07-16 01:03:42 +02:00
|
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
|
|
// (found in the LICENSE.Apache file in the root directory).
|
2015-01-31 20:43:09 +01:00
|
|
|
//
|
|
|
|
// This file implements the "bridge" between Java and C++ and enables
|
2020-02-20 21:07:53 +01:00
|
|
|
// calling c++ ROCKSDB_NAMESPACE::WriteBatch methods testing from Java side.
|
2015-01-31 20:43:09 +01:00
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
#include "db/memtable.h"
|
|
|
|
#include "db/write_batch_internal.h"
|
|
|
|
#include "include/org_rocksdb_WriteBatch.h"
|
|
|
|
#include "include/org_rocksdb_WriteBatchTest.h"
|
|
|
|
#include "include/org_rocksdb_WriteBatchTestInternalHelper.h"
|
2016-06-21 03:01:03 +02:00
|
|
|
#include "include/org_rocksdb_WriteBatch_Handler.h"
|
2017-04-06 04:02:00 +02:00
|
|
|
#include "options/cf_options.h"
|
2015-01-31 20:43:09 +01:00
|
|
|
#include "rocksdb/db.h"
|
|
|
|
#include "rocksdb/env.h"
|
|
|
|
#include "rocksdb/memtablerep.h"
|
|
|
|
#include "rocksdb/status.h"
|
|
|
|
#include "rocksdb/write_batch.h"
|
2016-06-21 03:01:03 +02:00
|
|
|
#include "rocksdb/write_buffer_manager.h"
|
2015-01-31 20:43:09 +01:00
|
|
|
#include "rocksjni/portal.h"
|
2015-10-13 00:06:38 +02:00
|
|
|
#include "table/scoped_arena_iterator.h"
|
2019-05-30 20:21:38 +02:00
|
|
|
#include "test_util/testharness.h"
|
2019-05-31 02:39:43 +02:00
|
|
|
#include "util/string_util.h"
|
2015-01-31 20:43:09 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Class: org_rocksdb_WriteBatchTest
|
|
|
|
* Method: getContents
|
2016-02-01 21:00:40 +01:00
|
|
|
* Signature: (J)[B
|
2015-01-31 20:43:09 +01:00
|
|
|
*/
|
2018-04-13 02:55:14 +02:00
|
|
|
jbyteArray Java_org_rocksdb_WriteBatchTest_getContents(JNIEnv* env,
|
|
|
|
jclass /*jclazz*/,
|
|
|
|
jlong jwb_handle) {
|
2020-02-20 21:07:53 +01:00
|
|
|
auto* b = reinterpret_cast<ROCKSDB_NAMESPACE::WriteBatch*>(jwb_handle);
|
2015-01-31 20:43:09 +01:00
|
|
|
assert(b != nullptr);
|
|
|
|
|
|
|
|
// todo: Currently the following code is directly copied from
|
|
|
|
// db/write_bench_test.cc. It could be implemented in java once
|
|
|
|
// all the necessary components can be accessed via jni api.
|
|
|
|
|
2020-02-20 21:07:53 +01:00
|
|
|
ROCKSDB_NAMESPACE::InternalKeyComparator cmp(
|
|
|
|
ROCKSDB_NAMESPACE::BytewiseComparator());
|
|
|
|
auto factory = std::make_shared<ROCKSDB_NAMESPACE::SkipListFactory>();
|
|
|
|
ROCKSDB_NAMESPACE::Options options;
|
|
|
|
ROCKSDB_NAMESPACE::WriteBufferManager wb(options.db_write_buffer_size);
|
2015-01-31 20:43:09 +01:00
|
|
|
options.memtable_factory = factory;
|
2020-02-20 21:07:53 +01:00
|
|
|
ROCKSDB_NAMESPACE::MemTable* mem = new ROCKSDB_NAMESPACE::MemTable(
|
|
|
|
cmp, ROCKSDB_NAMESPACE::ImmutableCFOptions(options),
|
|
|
|
ROCKSDB_NAMESPACE::MutableCFOptions(options), &wb,
|
|
|
|
ROCKSDB_NAMESPACE::kMaxSequenceNumber, 0 /* column_family_id */);
|
2015-01-31 20:43:09 +01:00
|
|
|
mem->Ref();
|
|
|
|
std::string state;
|
2020-02-20 21:07:53 +01:00
|
|
|
ROCKSDB_NAMESPACE::ColumnFamilyMemTablesDefault cf_mems_default(mem);
|
|
|
|
ROCKSDB_NAMESPACE::Status s =
|
|
|
|
ROCKSDB_NAMESPACE::WriteBatchInternal::InsertInto(b, &cf_mems_default,
|
|
|
|
nullptr, nullptr);
|
2019-09-09 20:22:28 +02:00
|
|
|
unsigned int count = 0;
|
2020-02-20 21:07:53 +01:00
|
|
|
ROCKSDB_NAMESPACE::Arena arena;
|
|
|
|
ROCKSDB_NAMESPACE::ScopedArenaIterator iter(
|
|
|
|
mem->NewIterator(ROCKSDB_NAMESPACE::ReadOptions(), &arena));
|
2015-01-31 20:43:09 +01:00
|
|
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
2020-02-20 21:07:53 +01:00
|
|
|
ROCKSDB_NAMESPACE::ParsedInternalKey ikey;
|
2017-07-24 20:28:20 +02:00
|
|
|
ikey.clear();
|
2020-10-01 04:15:42 +02:00
|
|
|
ROCKSDB_NAMESPACE::Status pikStatus =
|
|
|
|
ROCKSDB_NAMESPACE::ParseInternalKey(iter->key(), &ikey);
|
|
|
|
pikStatus.PermitUncheckedError();
|
|
|
|
assert(pikStatus.ok());
|
2015-01-31 20:43:09 +01:00
|
|
|
switch (ikey.type) {
|
2020-02-20 21:07:53 +01:00
|
|
|
case ROCKSDB_NAMESPACE::kTypeValue:
|
2015-01-31 20:43:09 +01:00
|
|
|
state.append("Put(");
|
|
|
|
state.append(ikey.user_key.ToString());
|
|
|
|
state.append(", ");
|
|
|
|
state.append(iter->value().ToString());
|
|
|
|
state.append(")");
|
|
|
|
count++;
|
|
|
|
break;
|
2020-02-20 21:07:53 +01:00
|
|
|
case ROCKSDB_NAMESPACE::kTypeMerge:
|
2015-01-31 20:43:09 +01:00
|
|
|
state.append("Merge(");
|
|
|
|
state.append(ikey.user_key.ToString());
|
|
|
|
state.append(", ");
|
|
|
|
state.append(iter->value().ToString());
|
|
|
|
state.append(")");
|
|
|
|
count++;
|
|
|
|
break;
|
2020-02-20 21:07:53 +01:00
|
|
|
case ROCKSDB_NAMESPACE::kTypeDeletion:
|
2015-01-31 20:43:09 +01:00
|
|
|
state.append("Delete(");
|
|
|
|
state.append(ikey.user_key.ToString());
|
|
|
|
state.append(")");
|
|
|
|
count++;
|
|
|
|
break;
|
2020-02-20 21:07:53 +01:00
|
|
|
case ROCKSDB_NAMESPACE::kTypeSingleDeletion:
|
2018-03-03 00:33:08 +01:00
|
|
|
state.append("SingleDelete(");
|
|
|
|
state.append(ikey.user_key.ToString());
|
|
|
|
state.append(")");
|
|
|
|
count++;
|
|
|
|
break;
|
2020-02-20 21:07:53 +01:00
|
|
|
case ROCKSDB_NAMESPACE::kTypeRangeDeletion:
|
2018-03-03 00:33:08 +01:00
|
|
|
state.append("DeleteRange(");
|
|
|
|
state.append(ikey.user_key.ToString());
|
|
|
|
state.append(", ");
|
|
|
|
state.append(iter->value().ToString());
|
|
|
|
state.append(")");
|
|
|
|
count++;
|
|
|
|
break;
|
2020-02-20 21:07:53 +01:00
|
|
|
case ROCKSDB_NAMESPACE::kTypeLogData:
|
2018-03-03 00:33:08 +01:00
|
|
|
state.append("LogData(");
|
|
|
|
state.append(ikey.user_key.ToString());
|
|
|
|
state.append(")");
|
|
|
|
count++;
|
|
|
|
break;
|
2015-01-31 20:43:09 +01:00
|
|
|
default:
|
|
|
|
assert(false);
|
2018-03-03 00:33:08 +01:00
|
|
|
state.append("Err:Expected(");
|
|
|
|
state.append(std::to_string(ikey.type));
|
|
|
|
state.append(")");
|
|
|
|
count++;
|
2015-01-31 20:43:09 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
state.append("@");
|
2020-02-20 21:07:53 +01:00
|
|
|
state.append(ROCKSDB_NAMESPACE::NumberToString(ikey.sequence));
|
2015-01-31 20:43:09 +01:00
|
|
|
}
|
|
|
|
if (!s.ok()) {
|
|
|
|
state.append(s.ToString());
|
2020-02-20 21:07:53 +01:00
|
|
|
} else if (ROCKSDB_NAMESPACE::WriteBatchInternal::Count(b) != count) {
|
2018-03-03 00:33:08 +01:00
|
|
|
state.append("Err:CountMismatch(expected=");
|
2020-02-20 21:07:53 +01:00
|
|
|
state.append(
|
|
|
|
std::to_string(ROCKSDB_NAMESPACE::WriteBatchInternal::Count(b)));
|
2018-03-03 00:33:08 +01:00
|
|
|
state.append(", actual=");
|
|
|
|
state.append(std::to_string(count));
|
|
|
|
state.append(")");
|
2015-01-31 20:43:09 +01:00
|
|
|
}
|
|
|
|
delete mem->Unref();
|
|
|
|
|
|
|
|
jbyteArray jstate = env->NewByteArray(static_cast<jsize>(state.size()));
|
2018-04-13 02:55:14 +02:00
|
|
|
if (jstate == nullptr) {
|
2017-02-28 01:26:12 +01:00
|
|
|
// exception thrown: OutOfMemoryError
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-04-13 02:55:14 +02:00
|
|
|
env->SetByteArrayRegion(
|
|
|
|
jstate, 0, static_cast<jsize>(state.size()),
|
|
|
|
const_cast<jbyte*>(reinterpret_cast<const jbyte*>(state.c_str())));
|
|
|
|
if (env->ExceptionCheck()) {
|
2017-02-28 01:26:12 +01:00
|
|
|
// exception thrown: ArrayIndexOutOfBoundsException
|
|
|
|
env->DeleteLocalRef(jstate);
|
|
|
|
return nullptr;
|
|
|
|
}
|
2015-01-31 20:43:09 +01:00
|
|
|
|
|
|
|
return jstate;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Class: org_rocksdb_WriteBatchTestInternalHelper
|
|
|
|
* Method: setSequence
|
2016-02-01 21:00:40 +01:00
|
|
|
* Signature: (JJ)V
|
2015-01-31 20:43:09 +01:00
|
|
|
*/
|
|
|
|
void Java_org_rocksdb_WriteBatchTestInternalHelper_setSequence(
|
2018-04-13 02:55:14 +02:00
|
|
|
JNIEnv* /*env*/, jclass /*jclazz*/, jlong jwb_handle, jlong jsn) {
|
2020-02-20 21:07:53 +01:00
|
|
|
auto* wb = reinterpret_cast<ROCKSDB_NAMESPACE::WriteBatch*>(jwb_handle);
|
2015-01-31 20:43:09 +01:00
|
|
|
assert(wb != nullptr);
|
|
|
|
|
2020-02-20 21:07:53 +01:00
|
|
|
ROCKSDB_NAMESPACE::WriteBatchInternal::SetSequence(
|
|
|
|
wb, static_cast<ROCKSDB_NAMESPACE::SequenceNumber>(jsn));
|
2015-01-31 20:43:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Class: org_rocksdb_WriteBatchTestInternalHelper
|
|
|
|
* Method: sequence
|
2016-02-01 21:00:40 +01:00
|
|
|
* Signature: (J)J
|
2015-01-31 20:43:09 +01:00
|
|
|
*/
|
2018-04-13 02:55:14 +02:00
|
|
|
jlong Java_org_rocksdb_WriteBatchTestInternalHelper_sequence(JNIEnv* /*env*/,
|
|
|
|
jclass /*jclazz*/,
|
|
|
|
jlong jwb_handle) {
|
2020-02-20 21:07:53 +01:00
|
|
|
auto* wb = reinterpret_cast<ROCKSDB_NAMESPACE::WriteBatch*>(jwb_handle);
|
2015-01-31 20:43:09 +01:00
|
|
|
assert(wb != nullptr);
|
|
|
|
|
2020-02-20 21:07:53 +01:00
|
|
|
return static_cast<jlong>(
|
|
|
|
ROCKSDB_NAMESPACE::WriteBatchInternal::Sequence(wb));
|
2015-01-31 20:43:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Class: org_rocksdb_WriteBatchTestInternalHelper
|
|
|
|
* Method: append
|
2016-02-01 21:00:40 +01:00
|
|
|
* Signature: (JJ)V
|
2015-01-31 20:43:09 +01:00
|
|
|
*/
|
2018-04-13 02:55:14 +02:00
|
|
|
void Java_org_rocksdb_WriteBatchTestInternalHelper_append(JNIEnv* /*env*/,
|
|
|
|
jclass /*jclazz*/,
|
|
|
|
jlong jwb_handle_1,
|
|
|
|
jlong jwb_handle_2) {
|
2020-02-20 21:07:53 +01:00
|
|
|
auto* wb1 = reinterpret_cast<ROCKSDB_NAMESPACE::WriteBatch*>(jwb_handle_1);
|
2015-01-31 20:43:09 +01:00
|
|
|
assert(wb1 != nullptr);
|
2020-02-20 21:07:53 +01:00
|
|
|
auto* wb2 = reinterpret_cast<ROCKSDB_NAMESPACE::WriteBatch*>(jwb_handle_2);
|
2015-01-31 20:43:09 +01:00
|
|
|
assert(wb2 != nullptr);
|
|
|
|
|
2020-02-20 21:07:53 +01:00
|
|
|
ROCKSDB_NAMESPACE::WriteBatchInternal::Append(wb1, wb2);
|
2015-01-31 20:43:09 +01:00
|
|
|
}
|