Expose DB::DeleteRange and WriteBath::DeleteRange in Java

Summary:
Added JNI wrapper from `DeleteRange` methods
Closes https://github.com/facebook/rocksdb/pull/1951

Differential Revision: D4657746

Pulled By: yiwu-arbug

fbshipit-source-id: 3fc7ab8
main
Matteo Merli 8 years ago committed by Facebook Github Bot
parent 58b12dfe37
commit 5f65dc8778
  1. 20
      java/rocksjni/portal.h
  2. 129
      java/rocksjni/rocksjni.cc
  3. 41
      java/rocksjni/write_batch.cc
  4. 38
      java/rocksjni/write_batch_with_index.cc
  5. 49
      java/rocksjni/writebatchhandlerjnicallback.cc
  6. 2
      java/rocksjni/writebatchhandlerjnicallback.h
  7. 17
      java/src/main/java/org/rocksdb/AbstractWriteBatch.java
  8. 110
      java/src/main/java/org/rocksdb/RocksDB.java
  9. 7
      java/src/main/java/org/rocksdb/WriteBatch.java
  10. 33
      java/src/main/java/org/rocksdb/WriteBatchInterface.java
  11. 6
      java/src/main/java/org/rocksdb/WriteBatchWithIndex.java
  12. 20
      java/src/test/java/org/rocksdb/RocksDBTest.java
  13. 12
      java/src/test/java/org/rocksdb/WriteBatchHandlerTest.java
  14. 29
      java/src/test/java/org/rocksdb/WriteBatchTest.java
  15. 24
      java/src/test/java/org/rocksdb/WriteBatchWithIndexTest.java

@ -795,6 +795,26 @@ class WriteBatchHandlerJni : public RocksDBNativeClass<
return mid; return mid;
} }
/**
* Get the Java Method: WriteBatch.Handler#deleteRange
*
* @param env A pointer to the Java environment
*
* @return The Java Method ID or nullptr if the class or method id could not
* be retieved
*/
static jmethodID getDeleteRangeMethodId(JNIEnv* env) {
jclass jclazz = getJClass(env);
if (jclazz == nullptr) {
// exception occurred accessing class
return nullptr;
}
static jmethodID mid = env->GetMethodID(jclazz, "deleteRange", "([B[B)V");
assert(mid != nullptr);
return mid;
}
/** /**
* Get the Java Method: WriteBatch.Handler#logData * Get the Java Method: WriteBatch.Handler#logData
* *

@ -1224,6 +1224,135 @@ void Java_org_rocksdb_RocksDB_singleDelete__JJ_3BIJ(
} }
} }
//////////////////////////////////////////////////////////////////////////////
// rocksdb::DB::DeleteRange()
/**
* @return true if the delete range succeeded, false if a Java Exception
* was thrown
*/
bool rocksdb_delete_range_helper(JNIEnv* env, rocksdb::DB* db,
const rocksdb::WriteOptions& write_options,
rocksdb::ColumnFamilyHandle* cf_handle,
jbyteArray jbegin_key, jint jbegin_key_off,
jint jbegin_key_len, jbyteArray jend_key,
jint jend_key_off, jint jend_key_len) {
jbyte* begin_key = new jbyte[jbegin_key_len];
env->GetByteArrayRegion(jbegin_key, jbegin_key_off, jbegin_key_len,
begin_key);
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
delete[] begin_key;
return false;
}
rocksdb::Slice begin_key_slice(reinterpret_cast<char*>(begin_key),
jbegin_key_len);
jbyte* end_key = new jbyte[jend_key_len];
env->GetByteArrayRegion(jend_key, jend_key_off, jend_key_len, end_key);
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
delete[] begin_key;
delete[] end_key;
return false;
}
rocksdb::Slice end_key_slice(reinterpret_cast<char*>(end_key), jend_key_len);
rocksdb::Status s =
db->DeleteRange(write_options, cf_handle, begin_key_slice, end_key_slice);
// cleanup
delete[] begin_key;
delete[] end_key;
if (s.ok()) {
return true;
}
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
return false;
}
/*
* Class: org_rocksdb_RocksDB
* Method: deleteRange
* Signature: (J[BII[BII)V
*/
void Java_org_rocksdb_RocksDB_deleteRange__J_3BII_3BII(
JNIEnv* env, jobject jdb, jlong jdb_handle, jbyteArray jbegin_key,
jint jbegin_key_off, jint jbegin_key_len, jbyteArray jend_key,
jint jend_key_off, jint jend_key_len) {
auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle);
static const rocksdb::WriteOptions default_write_options =
rocksdb::WriteOptions();
rocksdb_delete_range_helper(env, db, default_write_options, nullptr,
jbegin_key, jbegin_key_off, jbegin_key_len,
jend_key, jend_key_off, jend_key_len);
}
/*
* Class: org_rocksdb_RocksDB
* Method: deleteRange
* Signature: (J[BII[BIIJ)V
*/
void Java_org_rocksdb_RocksDB_deleteRange__J_3BII_3BIIJ(
JNIEnv* env, jobject jdb, jlong jdb_handle, jbyteArray jbegin_key,
jint jbegin_key_off, jint jbegin_key_len, jbyteArray jend_key,
jint jend_key_off, jint jend_key_len, jlong jcf_handle) {
auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle);
static const rocksdb::WriteOptions default_write_options =
rocksdb::WriteOptions();
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
if (cf_handle != nullptr) {
rocksdb_delete_range_helper(env, db, default_write_options, cf_handle,
jbegin_key, jbegin_key_off, jbegin_key_len,
jend_key, jend_key_off, jend_key_len);
} else {
rocksdb::RocksDBExceptionJni::ThrowNew(
env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle."));
}
}
/*
* Class: org_rocksdb_RocksDB
* Method: deleteRange
* Signature: (JJ[BII[BII)V
*/
void Java_org_rocksdb_RocksDB_deleteRange__JJ_3BII_3BII(
JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jwrite_options,
jbyteArray jbegin_key, jint jbegin_key_off, jint jbegin_key_len,
jbyteArray jend_key, jint jend_key_off, jint jend_key_len) {
auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle);
auto* write_options =
reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options);
rocksdb_delete_range_helper(env, db, *write_options, nullptr, jbegin_key,
jbegin_key_off, jbegin_key_len, jend_key,
jend_key_off, jend_key_len);
}
/*
* Class: org_rocksdb_RocksDB
* Method: deleteRange
* Signature: (JJ[BII[BIIJ)V
*/
void Java_org_rocksdb_RocksDB_deleteRange__JJ_3BII_3BIIJ(
JNIEnv* env, jobject jdb, jlong jdb_handle, jlong jwrite_options,
jbyteArray jbegin_key, jint jbegin_key_off, jint jbegin_key_len,
jbyteArray jend_key, jint jend_key_off, jint jend_key_len,
jlong jcf_handle) {
auto* db = reinterpret_cast<rocksdb::DB*>(jdb_handle);
auto* write_options =
reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options);
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
if (cf_handle != nullptr) {
rocksdb_delete_range_helper(env, db, *write_options, cf_handle, jbegin_key,
jbegin_key_off, jbegin_key_len, jend_key,
jend_key_off, jend_key_len);
} else {
rocksdb::RocksDBExceptionJni::ThrowNew(
env, rocksdb::Status::InvalidArgument("Invalid ColumnFamilyHandle."));
}
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// rocksdb::DB::Merge // rocksdb::DB::Merge

@ -201,6 +201,47 @@ void Java_org_rocksdb_WriteBatch_remove__J_3BIJ(
rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len); rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len);
} }
/*
* Class: org_rocksdb_WriteBatch
* Method: deleteRange
* Signature: (J[BI[BI)V
*/
JNIEXPORT void JNICALL Java_org_rocksdb_WriteBatch_deleteRange__J_3BI_3BI(
JNIEnv*, jobject, jlong, jbyteArray, jint, jbyteArray, jint);
void Java_org_rocksdb_WriteBatch_deleteRange__J_3BI_3BI(
JNIEnv* env, jobject jobj, jlong jwb_handle, jbyteArray jbegin_key,
jint jbegin_key_len, jbyteArray jend_key, jint jend_key_len) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
auto deleteRange = [&wb](rocksdb::Slice beginKey, rocksdb::Slice endKey) {
wb->DeleteRange(beginKey, endKey);
};
rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, jbegin_key_len,
jend_key, jend_key_len);
}
/*
* Class: org_rocksdb_WriteBatch
* Method: deleteRange
* Signature: (J[BI[BIJ)V
*/
void Java_org_rocksdb_WriteBatch_deleteRange__J_3BI_3BIJ(
JNIEnv* env, jobject jobj, jlong jwb_handle, jbyteArray jbegin_key,
jint jbegin_key_len, jbyteArray jend_key, jint jend_key_len,
jlong jcf_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
assert(cf_handle != nullptr);
auto deleteRange = [&wb, &cf_handle](rocksdb::Slice beginKey,
rocksdb::Slice endKey) {
wb->DeleteRange(cf_handle, beginKey, endKey);
};
rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, jbegin_key_len,
jend_key, jend_key_len);
}
/* /*
* Class: org_rocksdb_WriteBatch * Class: org_rocksdb_WriteBatch
* Method: putLogData * Method: putLogData

@ -172,6 +172,44 @@ void Java_org_rocksdb_WriteBatchWithIndex_remove__J_3BIJ(
rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len); rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len);
} }
/*
* Class: org_rocksdb_WriteBatchWithIndex
* Method: deleteRange
* Signature: (J[BI[BI)V
*/
void Java_org_rocksdb_WriteBatchWithIndex_deleteRange__J_3BI_3BI(
JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jbegin_key,
jint jbegin_key_len, jbyteArray jend_key, jint jend_key_len) {
auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
assert(wbwi != nullptr);
auto deleteRange = [&wbwi](rocksdb::Slice beginKey, rocksdb::Slice endKey) {
wbwi->DeleteRange(beginKey, endKey);
};
rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, jbegin_key_len,
jend_key, jend_key_len);
}
/*
* Class: org_rocksdb_WriteBatchWithIndex
* Method: deleteRange
* Signature: (J[BI[BIJ)V
*/
void Java_org_rocksdb_WriteBatchWithIndex_deleteRange__J_3BI_3BIJ(
JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jbegin_key,
jint jbegin_key_len, jbyteArray jend_key, jint jend_key_len,
jlong jcf_handle) {
auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
assert(wbwi != nullptr);
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
assert(cf_handle != nullptr);
auto deleteRange = [&wbwi, &cf_handle](rocksdb::Slice beginKey,
rocksdb::Slice endKey) {
wbwi->DeleteRange(cf_handle, beginKey, endKey);
};
rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, jbegin_key_len,
jend_key, jend_key_len);
}
/* /*
* Class: org_rocksdb_WriteBatchWithIndex * Class: org_rocksdb_WriteBatchWithIndex
* Method: putLogData * Method: putLogData

@ -41,6 +41,12 @@ WriteBatchHandlerJniCallback::WriteBatchHandlerJniCallback(
return; return;
} }
m_jDeleteRangeMethodId = WriteBatchHandlerJni::getDeleteRangeMethodId(env);
if (m_jDeleteRangeMethodId == nullptr) {
// exception thrown
return;
}
m_jLogDataMethodId = WriteBatchHandlerJni::getLogDataMethodId(env); m_jLogDataMethodId = WriteBatchHandlerJni::getLogDataMethodId(env);
if(m_jLogDataMethodId == nullptr) { if(m_jLogDataMethodId == nullptr) {
// exception thrown // exception thrown
@ -176,6 +182,49 @@ void WriteBatchHandlerJniCallback::Delete(const Slice& key) {
} }
} }
void WriteBatchHandlerJniCallback::DeleteRange(const Slice& beginKey,
const Slice& endKey) {
const jbyteArray j_beginKey = sliceToJArray(beginKey);
if (j_beginKey == nullptr) {
// exception thrown
if (m_env->ExceptionCheck()) {
m_env->ExceptionDescribe();
}
return;
}
const jbyteArray j_endKey = sliceToJArray(beginKey);
if (j_endKey == nullptr) {
// exception thrown
if (m_env->ExceptionCheck()) {
m_env->ExceptionDescribe();
}
return;
}
m_env->CallVoidMethod(m_jWriteBatchHandler, m_jDeleteRangeMethodId,
j_beginKey, j_endKey);
if (m_env->ExceptionCheck()) {
// exception thrown
m_env->ExceptionDescribe();
if (j_beginKey != nullptr) {
m_env->DeleteLocalRef(j_beginKey);
}
if (j_endKey != nullptr) {
m_env->DeleteLocalRef(j_endKey);
}
return;
}
if (j_beginKey != nullptr) {
m_env->DeleteLocalRef(j_beginKey);
}
if (j_endKey != nullptr) {
m_env->DeleteLocalRef(j_endKey);
}
}
void WriteBatchHandlerJniCallback::LogData(const Slice& blob) { void WriteBatchHandlerJniCallback::LogData(const Slice& blob) {
const jbyteArray j_blob = sliceToJArray(blob); const jbyteArray j_blob = sliceToJArray(blob);
if(j_blob == nullptr) { if(j_blob == nullptr) {

@ -28,6 +28,7 @@ class WriteBatchHandlerJniCallback : public WriteBatch::Handler {
void Put(const Slice& key, const Slice& value); void Put(const Slice& key, const Slice& value);
void Merge(const Slice& key, const Slice& value); void Merge(const Slice& key, const Slice& value);
void Delete(const Slice& key); void Delete(const Slice& key);
void DeleteRange(const Slice& beginKey, const Slice& endKey);
void LogData(const Slice& blob); void LogData(const Slice& blob);
bool Continue(); bool Continue();
@ -38,6 +39,7 @@ class WriteBatchHandlerJniCallback : public WriteBatch::Handler {
jmethodID m_jPutMethodId; jmethodID m_jPutMethodId;
jmethodID m_jMergeMethodId; jmethodID m_jMergeMethodId;
jmethodID m_jDeleteMethodId; jmethodID m_jDeleteMethodId;
jmethodID m_jDeleteRangeMethodId;
jmethodID m_jLogDataMethodId; jmethodID m_jLogDataMethodId;
jmethodID m_jContinueMethodId; jmethodID m_jContinueMethodId;
}; };

@ -51,6 +51,17 @@ public abstract class AbstractWriteBatch extends RocksObject
remove(nativeHandle_, key, key.length, columnFamilyHandle.nativeHandle_); remove(nativeHandle_, key, key.length, columnFamilyHandle.nativeHandle_);
} }
@Override
public void deleteRange(byte[] beginKey, byte[] endKey) {
deleteRange(nativeHandle_, beginKey, beginKey.length, endKey, endKey.length);
}
@Override
public void deleteRange(ColumnFamilyHandle columnFamilyHandle, byte[] beginKey, byte[] endKey) {
deleteRange(nativeHandle_, beginKey, beginKey.length, endKey, endKey.length,
columnFamilyHandle.nativeHandle_);
}
@Override @Override
public void putLogData(byte[] blob) { public void putLogData(byte[] blob) {
putLogData(nativeHandle_, blob, blob.length); putLogData(nativeHandle_, blob, blob.length);
@ -91,6 +102,12 @@ public abstract class AbstractWriteBatch extends RocksObject
abstract void remove(final long handle, final byte[] key, abstract void remove(final long handle, final byte[] key,
final int keyLen, final long cfHandle); final int keyLen, final long cfHandle);
abstract void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen,
final byte[] endKey, final int endKeyLen);
abstract void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen,
final byte[] endKey, final int endKeyLen, final long cfHandle);
abstract void putLogData(final long handle, final byte[] blob, abstract void putLogData(final long handle, final byte[] blob,
final int blobLen); final int blobLen);

@ -1337,6 +1337,104 @@ public class RocksDB extends RocksObject {
property, property.length()); property, property.length());
} }
/**
* Removes the database entries in the range ["beginKey", "endKey"), i.e.,
* including "beginKey" and excluding "endKey". a non-OK status on error. It
* is not an error if no keys exist in the range ["beginKey", "endKey").
*
* Delete the database entry (if any) for "key". Returns OK on success, and a
* non-OK status on error. It is not an error if "key" did not exist in the
* database.
*
* @param beginKey
* First key to delete within database (included)
* @param endKey
* Last key to delete within database (excluded)
*
* @throws RocksDBException
* thrown if error happens in underlying native library.
*/
public void deleteRange(final byte[] beginKey, final byte[] endKey) throws RocksDBException {
deleteRange(nativeHandle_, beginKey, 0, beginKey.length, endKey, 0, endKey.length);
}
/**
* Removes the database entries in the range ["beginKey", "endKey"), i.e.,
* including "beginKey" and excluding "endKey". a non-OK status on error. It
* is not an error if no keys exist in the range ["beginKey", "endKey").
*
* Delete the database entry (if any) for "key". Returns OK on success, and a
* non-OK status on error. It is not an error if "key" did not exist in the
* database.
*
* @param columnFamilyHandle
* {@link org.rocksdb.ColumnFamilyHandle} instance
* @param beginKey
* First key to delete within database (included)
* @param endKey
* Last key to delete within database (excluded)
*
* @throws RocksDBException
* thrown if error happens in underlying native library.
*/
public void deleteRange(final ColumnFamilyHandle columnFamilyHandle, final byte[] beginKey,
final byte[] endKey) throws RocksDBException {
deleteRange(nativeHandle_, beginKey, 0, beginKey.length, endKey, 0, endKey.length,
columnFamilyHandle.nativeHandle_);
}
/**
* Removes the database entries in the range ["beginKey", "endKey"), i.e.,
* including "beginKey" and excluding "endKey". a non-OK status on error. It
* is not an error if no keys exist in the range ["beginKey", "endKey").
*
* Delete the database entry (if any) for "key". Returns OK on success, and a
* non-OK status on error. It is not an error if "key" did not exist in the
* database.
*
* @param writeOpt
* WriteOptions to be used with delete operation
* @param beginKey
* First key to delete within database (included)
* @param endKey
* Last key to delete within database (excluded)
*
* @throws RocksDBException
* thrown if error happens in underlying native library.
*/
public void deleteRange(final WriteOptions writeOpt, final byte[] beginKey, final byte[] endKey)
throws RocksDBException {
deleteRange(nativeHandle_, writeOpt.nativeHandle_, beginKey, 0, beginKey.length, endKey, 0,
endKey.length);
}
/**
* Removes the database entries in the range ["beginKey", "endKey"), i.e.,
* including "beginKey" and excluding "endKey". a non-OK status on error. It
* is not an error if no keys exist in the range ["beginKey", "endKey").
*
* Delete the database entry (if any) for "key". Returns OK on success, and a
* non-OK status on error. It is not an error if "key" did not exist in the
* database.
*
* @param columnFamilyHandle {@link org.rocksdb.ColumnFamilyHandle}
* instance
* @param writeOpt
* WriteOptions to be used with delete operation
* @param beginKey
* First key to delete within database (included)
* @param endKey
* Last key to delete within database (excluded)
*
* @throws RocksDBException
* thrown if error happens in underlying native library.
*/
public void deleteRange(final ColumnFamilyHandle columnFamilyHandle, final WriteOptions writeOpt,
final byte[] beginKey, final byte[] endKey) throws RocksDBException {
deleteRange(nativeHandle_, writeOpt.nativeHandle_, beginKey, 0, beginKey.length, endKey, 0,
endKey.length, columnFamilyHandle.nativeHandle_);
}
/** /**
* DB implementations can export properties about their state * DB implementations can export properties about their state
* via this method. If "property" is a valid property understood by this * via this method. If "property" is a valid property understood by this
@ -2261,6 +2359,18 @@ public class RocksDB extends RocksObject {
protected native void singleDelete( protected native void singleDelete(
long handle, long writeOptHandle, long handle, long writeOptHandle,
byte[] key, int keyLen, long cfHandle) throws RocksDBException; byte[] key, int keyLen, long cfHandle) throws RocksDBException;
protected native void deleteRange(long handle, byte[] beginKey, int beginKeyOffset,
int beginKeyLength, byte[] endKey, int endKeyOffset, int endKeyLength)
throws RocksDBException;
protected native void deleteRange(long handle, byte[] beginKey, int beginKeyOffset,
int beginKeyLength, byte[] endKey, int endKeyOffset, int endKeyLength, long cfHandle)
throws RocksDBException;
protected native void deleteRange(long handle, long writeOptHandle, byte[] beginKey,
int beginKeyOffset, int beginKeyLength, byte[] endKey, int endKeyOffset, int endKeyLength)
throws RocksDBException;
protected native void deleteRange(long handle, long writeOptHandle, byte[] beginKey,
int beginKeyOffset, int beginKeyLength, byte[] endKey, int endKeyOffset, int endKeyLength,
long cfHandle) throws RocksDBException;
protected native String getProperty0(long nativeHandle, protected native String getProperty0(long nativeHandle,
String property, int propertyLength) throws RocksDBException; String property, int propertyLength) throws RocksDBException;
protected native String getProperty0(long nativeHandle, long cfHandle, protected native String getProperty0(long nativeHandle, long cfHandle,

@ -91,6 +91,12 @@ public class WriteBatch extends AbstractWriteBatch {
final int keyLen); final int keyLen);
@Override final native void remove(final long handle, final byte[] key, @Override final native void remove(final long handle, final byte[] key,
final int keyLen, final long cfHandle); final int keyLen, final long cfHandle);
@Override
final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen,
final byte[] endKey, final int endKeyLen);
@Override
final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen,
final byte[] endKey, final int endKeyLen, final long cfHandle);
@Override final native void putLogData(final long handle, @Override final native void putLogData(final long handle,
final byte[] blob, final int blobLen); final byte[] blob, final int blobLen);
@Override final native void clear0(final long handle); @Override final native void clear0(final long handle);
@ -116,6 +122,7 @@ public class WriteBatch extends AbstractWriteBatch {
public abstract void put(byte[] key, byte[] value); public abstract void put(byte[] key, byte[] value);
public abstract void merge(byte[] key, byte[] value); public abstract void merge(byte[] key, byte[] value);
public abstract void delete(byte[] key); public abstract void delete(byte[] key);
public abstract void deleteRange(byte[] beginKey, byte[] endKey);
public abstract void logData(byte[] blob); public abstract void logData(byte[] blob);
/** /**

@ -75,6 +75,39 @@ public interface WriteBatchInterface {
*/ */
void remove(ColumnFamilyHandle columnFamilyHandle, byte[] key); void remove(ColumnFamilyHandle columnFamilyHandle, byte[] key);
/**
* Removes the database entries in the range ["beginKey", "endKey"), i.e.,
* including "beginKey" and excluding "endKey". a non-OK status on error. It
* is not an error if no keys exist in the range ["beginKey", "endKey").
*
* Delete the database entry (if any) for "key". Returns OK on success, and a
* non-OK status on error. It is not an error if "key" did not exist in the
* database.
*
* @param beginKey
* First key to delete within database (included)
* @param endKey
* Last key to delete within database (excluded)
*/
void deleteRange(byte[] beginKey, byte[] endKey);
/**
* Removes the database entries in the range ["beginKey", "endKey"), i.e.,
* including "beginKey" and excluding "endKey". a non-OK status on error. It
* is not an error if no keys exist in the range ["beginKey", "endKey").
*
* Delete the database entry (if any) for "key". Returns OK on success, and a
* non-OK status on error. It is not an error if "key" did not exist in the
* database.
*
* @param columnFamilyHandle {@link ColumnFamilyHandle} instance
* @param beginKey
* First key to delete within database (included)
* @param endKey
* Last key to delete within database (excluded)
*/
void deleteRange(ColumnFamilyHandle columnFamilyHandle, byte[] beginKey, byte[] endKey);
/** /**
* Append a blob of arbitrary size to the records in this batch. The blob will * Append a blob of arbitrary size to the records in this batch. The blob will
* be stored in the transaction log but not in any other file. In particular, * be stored in the transaction log but not in any other file. In particular,

@ -248,6 +248,12 @@ public class WriteBatchWithIndex extends AbstractWriteBatch {
final int keyLen); final int keyLen);
@Override final native void remove(final long handle, final byte[] key, @Override final native void remove(final long handle, final byte[] key,
final int keyLen, final long cfHandle); final int keyLen, final long cfHandle);
@Override
final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen,
final byte[] endKey, final int endKeyLen);
@Override
final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen,
final byte[] endKey, final int endKeyLen, final long cfHandle);
@Override final native void putLogData(final long handle, final byte[] blob, @Override final native void putLogData(final long handle, final byte[] blob,
final int blobLen); final int blobLen);
@Override final native void clear0(final long handle); @Override final native void clear0(final long handle);

@ -255,6 +255,26 @@ public class RocksDBTest {
} }
} }
@Test
public void deleteRange() throws RocksDBException {
try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
final WriteOptions wOpt = new WriteOptions()) {
db.put("key1".getBytes(), "value".getBytes());
db.put("key2".getBytes(), "12345678".getBytes());
db.put("key3".getBytes(), "abcdefg".getBytes());
db.put("key4".getBytes(), "xyz".getBytes());
assertThat(db.get("key1".getBytes())).isEqualTo("value".getBytes());
assertThat(db.get("key2".getBytes())).isEqualTo("12345678".getBytes());
assertThat(db.get("key3".getBytes())).isEqualTo("abcdefg".getBytes());
assertThat(db.get("key4".getBytes())).isEqualTo("xyz".getBytes());
db.deleteRange("key2".getBytes(), "key4".getBytes());
assertThat(db.get("key1".getBytes())).isEqualTo("value".getBytes());
assertThat(db.get("key2".getBytes())).isNull();
assertThat(db.get("key3".getBytes())).isNull();
assertThat(db.get("key4".getBytes())).isEqualTo("xyz".getBytes());
}
}
@Test @Test
public void getIntProperty() throws RocksDBException { public void getIntProperty() throws RocksDBException {
try ( try (

@ -119,12 +119,7 @@ public class WriteBatchHandlerTest {
* Enumeration of Write Batch * Enumeration of Write Batch
* event actions * event actions
*/ */
private enum Action { private enum Action { PUT, MERGE, DELETE, DELETE_RANGE, LOG }
PUT,
MERGE,
DELETE,
LOG
}
/** /**
* A simple WriteBatch Handler which adds a record * A simple WriteBatch Handler which adds a record
@ -160,6 +155,11 @@ public class WriteBatchHandlerTest {
new Tuple<byte[], byte[]>(key, null))); new Tuple<byte[], byte[]>(key, null)));
} }
@Override
public void deleteRange(final byte[] beginKey, final byte[] endKey) {
events.add(new Tuple<>(Action.DELETE_RANGE, new Tuple<byte[], byte[]>(beginKey, endKey)));
}
@Override @Override
public void logData(final byte[] blob) { public void logData(final byte[] blob) {
events.add(new Tuple<>(Action.LOG, events.add(new Tuple<>(Action.LOG,

@ -163,6 +163,30 @@ public class WriteBatchTest {
} }
} }
@Test
public void deleteRange() throws RocksDBException {
try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
final WriteOptions wOpt = new WriteOptions()) {
db.put("key1".getBytes(), "value".getBytes());
db.put("key2".getBytes(), "12345678".getBytes());
db.put("key3".getBytes(), "abcdefg".getBytes());
db.put("key4".getBytes(), "xyz".getBytes());
assertThat(db.get("key1".getBytes())).isEqualTo("value".getBytes());
assertThat(db.get("key2".getBytes())).isEqualTo("12345678".getBytes());
assertThat(db.get("key3".getBytes())).isEqualTo("abcdefg".getBytes());
assertThat(db.get("key4".getBytes())).isEqualTo("xyz".getBytes());
WriteBatch batch = new WriteBatch();
batch.deleteRange("key2".getBytes(), "key4".getBytes());
db.write(new WriteOptions(), batch);
assertThat(db.get("key1".getBytes())).isEqualTo("value".getBytes());
assertThat(db.get("key2".getBytes())).isNull();
assertThat(db.get("key3".getBytes())).isNull();
assertThat(db.get("key4".getBytes())).isEqualTo("xyz".getBytes());
}
}
@Test(expected = RocksDBException.class) @Test(expected = RocksDBException.class)
public void restorePoints_withoutSavePoints() throws RocksDBException { public void restorePoints_withoutSavePoints() throws RocksDBException {
try (final WriteBatch batch = new WriteBatch()) { try (final WriteBatch batch = new WriteBatch()) {
@ -234,6 +258,11 @@ public class WriteBatchTest {
} }
} }
@Override
public void deleteRange(final byte[] beginKey, final byte[] endKey) {
throw new UnsupportedOperationException();
}
@Override @Override
public void logData(final byte[] blob) { public void logData(final byte[] blob) {
} }

@ -383,4 +383,28 @@ public class WriteBatchWithIndexTest {
buf.get(ary); buf.get(ary);
return ary; return ary;
} }
@Test
public void deleteRange() throws RocksDBException {
try (final RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
final WriteOptions wOpt = new WriteOptions()) {
db.put("key1".getBytes(), "value".getBytes());
db.put("key2".getBytes(), "12345678".getBytes());
db.put("key3".getBytes(), "abcdefg".getBytes());
db.put("key4".getBytes(), "xyz".getBytes());
assertThat(db.get("key1".getBytes())).isEqualTo("value".getBytes());
assertThat(db.get("key2".getBytes())).isEqualTo("12345678".getBytes());
assertThat(db.get("key3".getBytes())).isEqualTo("abcdefg".getBytes());
assertThat(db.get("key4".getBytes())).isEqualTo("xyz".getBytes());
WriteBatch batch = new WriteBatch();
batch.deleteRange("key2".getBytes(), "key4".getBytes());
db.write(new WriteOptions(), batch);
assertThat(db.get("key1".getBytes())).isEqualTo("value".getBytes());
assertThat(db.get("key2".getBytes())).isNull();
assertThat(db.get("key3".getBytes())).isNull();
assertThat(db.get("key4".getBytes())).isEqualTo("xyz".getBytes());
}
}
} }

Loading…
Cancel
Save