Added support for SstFileReader JNI interface (#5556)
Summary: Feature request as per https://github.com/facebook/rocksdb/issues/5538 issue. Pull Request resolved: https://github.com/facebook/rocksdb/pull/5556 Differential Revision: D17219008 fbshipit-source-id: e31f18dec318416eac9dea8213bab31da96e1f3amain
parent
7af6ced14b
commit
699e1b5ede
@ -0,0 +1,186 @@ |
|||||||
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
||||||
|
// 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).
|
||||||
|
//
|
||||||
|
// This file implements the "bridge" between Java and C++ and enables
|
||||||
|
// calling c++ rocksdb::Iterator methods from Java side.
|
||||||
|
|
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <jni.h> |
||||||
|
|
||||||
|
#include "include/org_rocksdb_SstFileReaderIterator.h" |
||||||
|
#include "rocksjni/portal.h" |
||||||
|
#include "rocksdb/iterator.h" |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReaderIterator |
||||||
|
* Method: disposeInternal |
||||||
|
* Signature: (J)V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_SstFileReaderIterator_disposeInternal(JNIEnv* /*env*/, |
||||||
|
jobject /*jobj*/, |
||||||
|
jlong handle) { |
||||||
|
auto* it = reinterpret_cast<rocksdb::Iterator*>(handle); |
||||||
|
assert(it != nullptr); |
||||||
|
delete it; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReaderIterator |
||||||
|
* Method: isValid0 |
||||||
|
* Signature: (J)Z |
||||||
|
*/ |
||||||
|
jboolean Java_org_rocksdb_SstFileReaderIterator_isValid0(JNIEnv* /*env*/, |
||||||
|
jobject /*jobj*/, |
||||||
|
jlong handle) { |
||||||
|
return reinterpret_cast<rocksdb::Iterator*>(handle)->Valid(); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReaderIterator |
||||||
|
* Method: seekToFirst0 |
||||||
|
* Signature: (J)V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_SstFileReaderIterator_seekToFirst0(JNIEnv* /*env*/, |
||||||
|
jobject /*jobj*/, |
||||||
|
jlong handle) { |
||||||
|
reinterpret_cast<rocksdb::Iterator*>(handle)->SeekToFirst(); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReaderIterator |
||||||
|
* Method: seekToLast0 |
||||||
|
* Signature: (J)V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_SstFileReaderIterator_seekToLast0(JNIEnv* /*env*/, |
||||||
|
jobject /*jobj*/, |
||||||
|
jlong handle) { |
||||||
|
reinterpret_cast<rocksdb::Iterator*>(handle)->SeekToLast(); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReaderIterator |
||||||
|
* Method: next0 |
||||||
|
* Signature: (J)V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_SstFileReaderIterator_next0(JNIEnv* /*env*/, jobject /*jobj*/, |
||||||
|
jlong handle) { |
||||||
|
reinterpret_cast<rocksdb::Iterator*>(handle)->Next(); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReaderIterator |
||||||
|
* Method: prev0 |
||||||
|
* Signature: (J)V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_SstFileReaderIterator_prev0(JNIEnv* /*env*/, jobject /*jobj*/, |
||||||
|
jlong handle) { |
||||||
|
reinterpret_cast<rocksdb::Iterator*>(handle)->Prev(); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReaderIterator |
||||||
|
* Method: seek0 |
||||||
|
* Signature: (J[BI)V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_SstFileReaderIterator_seek0(JNIEnv* env, jobject /*jobj*/, |
||||||
|
jlong handle, jbyteArray jtarget, |
||||||
|
jint jtarget_len) { |
||||||
|
jbyte* target = env->GetByteArrayElements(jtarget, nullptr); |
||||||
|
if(target == nullptr) { |
||||||
|
// exception thrown: OutOfMemoryError
|
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
rocksdb::Slice target_slice( |
||||||
|
reinterpret_cast<char*>(target), jtarget_len); |
||||||
|
|
||||||
|
auto* it = reinterpret_cast<rocksdb::Iterator*>(handle); |
||||||
|
it->Seek(target_slice); |
||||||
|
|
||||||
|
env->ReleaseByteArrayElements(jtarget, target, JNI_ABORT); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReaderIterator |
||||||
|
* Method: seekForPrev0 |
||||||
|
* Signature: (J[BI)V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_SstFileReaderIterator_seekForPrev0(JNIEnv* env, jobject /*jobj*/, |
||||||
|
jlong handle, |
||||||
|
jbyteArray jtarget, |
||||||
|
jint jtarget_len) { |
||||||
|
jbyte* target = env->GetByteArrayElements(jtarget, nullptr); |
||||||
|
if(target == nullptr) { |
||||||
|
// exception thrown: OutOfMemoryError
|
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
rocksdb::Slice target_slice( |
||||||
|
reinterpret_cast<char*>(target), jtarget_len); |
||||||
|
|
||||||
|
auto* it = reinterpret_cast<rocksdb::Iterator*>(handle); |
||||||
|
it->SeekForPrev(target_slice); |
||||||
|
|
||||||
|
env->ReleaseByteArrayElements(jtarget, target, JNI_ABORT); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReaderIterator |
||||||
|
* Method: status0 |
||||||
|
* Signature: (J)V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_SstFileReaderIterator_status0(JNIEnv* env, jobject /*jobj*/, |
||||||
|
jlong handle) { |
||||||
|
auto* it = reinterpret_cast<rocksdb::Iterator*>(handle); |
||||||
|
rocksdb::Status s = it->status(); |
||||||
|
|
||||||
|
if (s.ok()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
rocksdb::RocksDBExceptionJni::ThrowNew(env, s); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReaderIterator |
||||||
|
* Method: key0 |
||||||
|
* Signature: (J)[B |
||||||
|
*/ |
||||||
|
jbyteArray Java_org_rocksdb_SstFileReaderIterator_key0(JNIEnv* env, jobject /*jobj*/, |
||||||
|
jlong handle) { |
||||||
|
auto* it = reinterpret_cast<rocksdb::Iterator*>(handle); |
||||||
|
rocksdb::Slice key_slice = it->key(); |
||||||
|
|
||||||
|
jbyteArray jkey = env->NewByteArray(static_cast<jsize>(key_slice.size())); |
||||||
|
if(jkey == nullptr) { |
||||||
|
// exception thrown: OutOfMemoryError
|
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
env->SetByteArrayRegion(jkey, 0, static_cast<jsize>(key_slice.size()), |
||||||
|
const_cast<jbyte*>(reinterpret_cast<const jbyte*>(key_slice.data()))); |
||||||
|
return jkey; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReaderIterator |
||||||
|
* Method: value0 |
||||||
|
* Signature: (J)[B |
||||||
|
*/ |
||||||
|
jbyteArray Java_org_rocksdb_SstFileReaderIterator_value0(JNIEnv* env, jobject /*jobj*/, |
||||||
|
jlong handle) { |
||||||
|
auto* it = reinterpret_cast<rocksdb::Iterator*>(handle); |
||||||
|
rocksdb::Slice value_slice = it->value(); |
||||||
|
|
||||||
|
jbyteArray jkeyValue = |
||||||
|
env->NewByteArray(static_cast<jsize>(value_slice.size())); |
||||||
|
if(jkeyValue == nullptr) { |
||||||
|
// exception thrown: OutOfMemoryError
|
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
env->SetByteArrayRegion(jkeyValue, 0, static_cast<jsize>(value_slice.size()), |
||||||
|
const_cast<jbyte*>(reinterpret_cast<const jbyte*>(value_slice.data()))); |
||||||
|
return jkeyValue; |
||||||
|
} |
@ -0,0 +1,110 @@ |
|||||||
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
||||||
|
// 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).
|
||||||
|
//
|
||||||
|
// This file implements the "bridge" between Java and C++ and enables
|
||||||
|
// calling C++ rocksdb::SstFileReader methods
|
||||||
|
// from Java side.
|
||||||
|
|
||||||
|
#include <jni.h> |
||||||
|
#include <string> |
||||||
|
|
||||||
|
#include "include/org_rocksdb_SstFileReader.h" |
||||||
|
#include "rocksdb/comparator.h" |
||||||
|
#include "rocksdb/env.h" |
||||||
|
#include "rocksdb/options.h" |
||||||
|
#include "rocksdb/sst_file_reader.h" |
||||||
|
#include "rocksjni/portal.h" |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReader |
||||||
|
* Method: newSstFileReader |
||||||
|
* Signature: (J)J |
||||||
|
*/ |
||||||
|
jlong Java_org_rocksdb_SstFileReader_newSstFileReader(JNIEnv * /*env*/, |
||||||
|
jclass /*jcls*/, |
||||||
|
jlong joptions) { |
||||||
|
auto *options = reinterpret_cast<const rocksdb::Options *>(joptions); |
||||||
|
rocksdb::SstFileReader *sst_file_reader = |
||||||
|
new rocksdb::SstFileReader(*options); |
||||||
|
return reinterpret_cast<jlong>(sst_file_reader); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReader |
||||||
|
* Method: open |
||||||
|
* Signature: (JLjava/lang/String;)V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_SstFileReader_open(JNIEnv *env, jobject /*jobj*/, |
||||||
|
jlong jhandle, jstring jfile_path) { |
||||||
|
const char *file_path = env->GetStringUTFChars(jfile_path, nullptr); |
||||||
|
if (file_path == nullptr) { |
||||||
|
// exception thrown: OutOfMemoryError
|
||||||
|
return; |
||||||
|
} |
||||||
|
rocksdb::Status s = |
||||||
|
reinterpret_cast<rocksdb::SstFileReader *>(jhandle)->Open(file_path); |
||||||
|
env->ReleaseStringUTFChars(jfile_path, file_path); |
||||||
|
|
||||||
|
if (!s.ok()) { |
||||||
|
rocksdb::RocksDBExceptionJni::ThrowNew(env, s); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReader |
||||||
|
* Method: newIterator |
||||||
|
* Signature: (JJ)J |
||||||
|
*/ |
||||||
|
jlong Java_org_rocksdb_SstFileReader_newIterator(JNIEnv* /*env*/, |
||||||
|
jobject /*jobj*/, |
||||||
|
jlong jhandle, |
||||||
|
jlong jread_options_handle) { |
||||||
|
auto* sst_file_reader = reinterpret_cast<rocksdb::SstFileReader*>(jhandle); |
||||||
|
auto* read_options = |
||||||
|
reinterpret_cast<rocksdb::ReadOptions*>(jread_options_handle); |
||||||
|
return reinterpret_cast<jlong>(sst_file_reader->NewIterator(*read_options)); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReader |
||||||
|
* Method: disposeInternal |
||||||
|
* Signature: (J)V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_SstFileReader_disposeInternal(JNIEnv * /*env*/, |
||||||
|
jobject /*jobj*/, |
||||||
|
jlong jhandle) { |
||||||
|
delete reinterpret_cast<rocksdb::SstFileReader *>(jhandle); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReader |
||||||
|
* Method: verifyChecksum |
||||||
|
* Signature: (J)V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_SstFileReader_verifyChecksum(JNIEnv *env, |
||||||
|
jobject /*jobj*/, |
||||||
|
jlong jhandle) { |
||||||
|
auto* sst_file_reader = reinterpret_cast<rocksdb::SstFileReader*>(jhandle); |
||||||
|
auto s = sst_file_reader->VerifyChecksum(); |
||||||
|
if (!s.ok()) { |
||||||
|
rocksdb::RocksDBExceptionJni::ThrowNew(env, s); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_SstFileReader |
||||||
|
* Method: getTableProperties |
||||||
|
* Signature: (J)J |
||||||
|
*/ |
||||||
|
jobject Java_org_rocksdb_SstFileReader_getTableProperties(JNIEnv *env, |
||||||
|
jobject /*jobj*/, |
||||||
|
jlong jhandle) { |
||||||
|
auto* sst_file_reader = reinterpret_cast<rocksdb::SstFileReader*>(jhandle); |
||||||
|
std::shared_ptr<const rocksdb::TableProperties> tp = sst_file_reader->GetTableProperties(); |
||||||
|
jobject jtable_properties = rocksdb::TablePropertiesJni::fromCppTableProperties( |
||||||
|
env, *(tp.get())); |
||||||
|
return jtable_properties; |
||||||
|
} |
||||||
|
|
@ -0,0 +1,83 @@ |
|||||||
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
||||||
|
// 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).
|
||||||
|
|
||||||
|
package org.rocksdb; |
||||||
|
|
||||||
|
public class SstFileReader extends RocksObject { |
||||||
|
static { |
||||||
|
RocksDB.loadLibrary(); |
||||||
|
} |
||||||
|
|
||||||
|
public SstFileReader(final Options options) { |
||||||
|
super(newSstFileReader(options.nativeHandle_)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns an iterator that will iterate on all keys in the default |
||||||
|
* column family including both keys in the DB and uncommitted keys in this |
||||||
|
* transaction. |
||||||
|
* |
||||||
|
* Setting {@link ReadOptions#setSnapshot(Snapshot)} will affect what is read |
||||||
|
* from the DB but will NOT change which keys are read from this transaction |
||||||
|
* (the keys in this transaction do not yet belong to any snapshot and will be |
||||||
|
* fetched regardless). |
||||||
|
* |
||||||
|
* Caller is responsible for deleting the returned Iterator. |
||||||
|
* |
||||||
|
* @param readOptions Read options. |
||||||
|
* |
||||||
|
* @return instance of iterator object. |
||||||
|
*/ |
||||||
|
public SstFileReaderIterator newIterator(final ReadOptions readOptions) { |
||||||
|
assert(isOwningHandle()); |
||||||
|
long iter = newIterator(nativeHandle_, |
||||||
|
readOptions.nativeHandle_); |
||||||
|
return new SstFileReaderIterator(this, iter); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Prepare SstFileReader to read a file. |
||||||
|
* |
||||||
|
* @param filePath the location of file |
||||||
|
* |
||||||
|
* @throws RocksDBException thrown if error happens in underlying |
||||||
|
* native library. |
||||||
|
*/ |
||||||
|
public void open(final String filePath) throws RocksDBException { |
||||||
|
open(nativeHandle_, filePath); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Verify checksum |
||||||
|
* |
||||||
|
* @throws RocksDBException if the checksum is not valid |
||||||
|
*/ |
||||||
|
public void verifyChecksum() throws RocksDBException { |
||||||
|
verifyChecksum(nativeHandle_); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the properties of the table. |
||||||
|
* |
||||||
|
* |
||||||
|
* @return the properties |
||||||
|
*/ |
||||||
|
public TableProperties getTableProperties() throws RocksDBException { |
||||||
|
return getTableProperties(nativeHandle_); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override protected final native void disposeInternal(final long handle); |
||||||
|
private native long newIterator(final long handle, |
||||||
|
final long readOptionsHandle); |
||||||
|
|
||||||
|
private native void open(final long handle, final String filePath) |
||||||
|
throws RocksDBException; |
||||||
|
|
||||||
|
private native static long newSstFileReader(final long optionsHandle); |
||||||
|
private native void verifyChecksum(final long handle) throws RocksDBException; |
||||||
|
private native TableProperties getTableProperties(final long handle) throws RocksDBException; |
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
||||||
|
// 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).
|
||||||
|
|
||||||
|
package org.rocksdb; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p>An iterator that yields a sequence of key/value pairs from a source. |
||||||
|
* Multiple implementations are provided by this library. |
||||||
|
* In particular, iterators are provided |
||||||
|
* to access the contents of a Table or a DB.</p> |
||||||
|
* |
||||||
|
* <p>Multiple threads can invoke const methods on an RocksIterator without |
||||||
|
* external synchronization, but if any of the threads may call a |
||||||
|
* non-const method, all threads accessing the same RocksIterator must use |
||||||
|
* external synchronization.</p> |
||||||
|
* |
||||||
|
* @see RocksObject |
||||||
|
*/ |
||||||
|
public class SstFileReaderIterator extends AbstractRocksIterator<SstFileReader> { |
||||||
|
protected SstFileReaderIterator(SstFileReader reader, long nativeHandle) { |
||||||
|
super(reader, nativeHandle); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* <p>Return the key for the current entry. The underlying storage for |
||||||
|
* the returned slice is valid only until the next modification of |
||||||
|
* the iterator.</p> |
||||||
|
* |
||||||
|
* <p>REQUIRES: {@link #isValid()}</p> |
||||||
|
* |
||||||
|
* @return key for the current entry. |
||||||
|
*/ |
||||||
|
public byte[] key() { |
||||||
|
assert(isOwningHandle()); |
||||||
|
return key0(nativeHandle_); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* <p>Return the value for the current entry. The underlying storage for |
||||||
|
* the returned slice is valid only until the next modification of |
||||||
|
* the iterator.</p> |
||||||
|
* |
||||||
|
* <p>REQUIRES: !AtEnd() && !AtStart()</p> |
||||||
|
* @return value for the current entry. |
||||||
|
*/ |
||||||
|
public byte[] value() { |
||||||
|
assert(isOwningHandle()); |
||||||
|
return value0(nativeHandle_); |
||||||
|
} |
||||||
|
|
||||||
|
@Override protected final native void disposeInternal(final long handle); |
||||||
|
@Override final native boolean isValid0(long handle); |
||||||
|
@Override final native void seekToFirst0(long handle); |
||||||
|
@Override final native void seekToLast0(long handle); |
||||||
|
@Override final native void next0(long handle); |
||||||
|
@Override final native void prev0(long handle); |
||||||
|
@Override final native void seek0(long handle, byte[] target, int targetLen); |
||||||
|
@Override final native void seekForPrev0(long handle, byte[] target, int targetLen); |
||||||
|
@Override final native void status0(long handle) throws RocksDBException; |
||||||
|
|
||||||
|
private native byte[] key0(long handle); |
||||||
|
private native byte[] value0(long handle); |
||||||
|
} |
@ -0,0 +1,137 @@ |
|||||||
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
||||||
|
// 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).
|
||||||
|
|
||||||
|
package org.rocksdb; |
||||||
|
|
||||||
|
import org.junit.Rule; |
||||||
|
import org.junit.Test; |
||||||
|
import org.junit.rules.TemporaryFolder; |
||||||
|
import org.rocksdb.util.BytewiseComparator; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
import static org.junit.Assert.assertEquals; |
||||||
|
import static org.junit.Assert.fail; |
||||||
|
|
||||||
|
public class SstFileReaderTest { |
||||||
|
private static final String SST_FILE_NAME = "test.sst"; |
||||||
|
|
||||||
|
class KeyValueWithOp { |
||||||
|
KeyValueWithOp(String key, String value, OpType opType) { |
||||||
|
this.key = key; |
||||||
|
this.value = value; |
||||||
|
this.opType = opType; |
||||||
|
} |
||||||
|
|
||||||
|
String getKey() { |
||||||
|
return key; |
||||||
|
} |
||||||
|
|
||||||
|
String getValue() { |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
OpType getOpType() { |
||||||
|
return opType; |
||||||
|
} |
||||||
|
|
||||||
|
private String key; |
||||||
|
private String value; |
||||||
|
private OpType opType; |
||||||
|
} |
||||||
|
|
||||||
|
@Rule public TemporaryFolder parentFolder = new TemporaryFolder(); |
||||||
|
|
||||||
|
enum OpType { PUT, PUT_BYTES, MERGE, MERGE_BYTES, DELETE, DELETE_BYTES} |
||||||
|
|
||||||
|
private File newSstFile(final List<KeyValueWithOp> keyValues) throws IOException, RocksDBException { |
||||||
|
final EnvOptions envOptions = new EnvOptions(); |
||||||
|
final StringAppendOperator stringAppendOperator = new StringAppendOperator(); |
||||||
|
final Options options = new Options().setMergeOperator(stringAppendOperator); |
||||||
|
SstFileWriter sstFileWriter; |
||||||
|
sstFileWriter = new SstFileWriter(envOptions, options); |
||||||
|
|
||||||
|
final File sstFile = parentFolder.newFile(SST_FILE_NAME); |
||||||
|
try { |
||||||
|
sstFileWriter.open(sstFile.getAbsolutePath()); |
||||||
|
for (KeyValueWithOp keyValue : keyValues) { |
||||||
|
Slice keySlice = new Slice(keyValue.getKey()); |
||||||
|
Slice valueSlice = new Slice(keyValue.getValue()); |
||||||
|
byte[] keyBytes = keyValue.getKey().getBytes(); |
||||||
|
byte[] valueBytes = keyValue.getValue().getBytes(); |
||||||
|
switch (keyValue.getOpType()) { |
||||||
|
case PUT: |
||||||
|
sstFileWriter.put(keySlice, valueSlice); |
||||||
|
break; |
||||||
|
case PUT_BYTES: |
||||||
|
sstFileWriter.put(keyBytes, valueBytes); |
||||||
|
break; |
||||||
|
case MERGE: |
||||||
|
sstFileWriter.merge(keySlice, valueSlice); |
||||||
|
break; |
||||||
|
case MERGE_BYTES: |
||||||
|
sstFileWriter.merge(keyBytes, valueBytes); |
||||||
|
break; |
||||||
|
case DELETE: |
||||||
|
sstFileWriter.delete(keySlice); |
||||||
|
break; |
||||||
|
case DELETE_BYTES: |
||||||
|
sstFileWriter.delete(keyBytes); |
||||||
|
break; |
||||||
|
default: |
||||||
|
fail("Unsupported op type"); |
||||||
|
} |
||||||
|
keySlice.close(); |
||||||
|
valueSlice.close(); |
||||||
|
} |
||||||
|
sstFileWriter.finish(); |
||||||
|
} finally { |
||||||
|
assertThat(sstFileWriter).isNotNull(); |
||||||
|
sstFileWriter.close(); |
||||||
|
options.close(); |
||||||
|
envOptions.close(); |
||||||
|
} |
||||||
|
return sstFile; |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void readSstFile() throws RocksDBException, IOException { |
||||||
|
final List<KeyValueWithOp> keyValues = new ArrayList<>(); |
||||||
|
keyValues.add(new KeyValueWithOp("key1", "value1", OpType.PUT)); |
||||||
|
|
||||||
|
|
||||||
|
final File sstFile = newSstFile(keyValues); |
||||||
|
try(final StringAppendOperator stringAppendOperator = |
||||||
|
new StringAppendOperator(); |
||||||
|
final Options options = new Options() |
||||||
|
.setCreateIfMissing(true) |
||||||
|
.setMergeOperator(stringAppendOperator); |
||||||
|
final SstFileReader reader = new SstFileReader(options) |
||||||
|
) { |
||||||
|
// Open the sst file and iterator
|
||||||
|
reader.open(sstFile.getAbsolutePath()); |
||||||
|
final ReadOptions readOptions = new ReadOptions(); |
||||||
|
final SstFileReaderIterator iterator = reader.newIterator(readOptions); |
||||||
|
|
||||||
|
// Use the iterator to read sst file
|
||||||
|
iterator.seekToFirst(); |
||||||
|
|
||||||
|
// Verify Checksum
|
||||||
|
reader.verifyChecksum(); |
||||||
|
|
||||||
|
// Verify Table Properties
|
||||||
|
assertEquals(reader.getTableProperties().getNumEntries(), 1); |
||||||
|
|
||||||
|
// Check key and value
|
||||||
|
assertThat(iterator.key()).isEqualTo("key1".getBytes()); |
||||||
|
assertThat(iterator.value()).isEqualTo("value1".getBytes()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue