From 02224a21f6370b87d4f0700dc3dc47914ce1a9ef Mon Sep 17 00:00:00 2001 From: Swaminathan Balachandran Date: Mon, 22 Dec 2025 03:28:54 -0500 Subject: [PATCH] Support Delete Direct along the same lines as PutDirect in SstFileWriter --- java/rocksjni/sst_file_writerjni.cc | 19 +++++++++++++++++++ .../main/java/org/rocksdb/SstFileWriter.java | 17 +++++++++++++++++ .../java/org/rocksdb/SstFileWriterTest.java | 16 +++++++++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/java/rocksjni/sst_file_writerjni.cc b/java/rocksjni/sst_file_writerjni.cc index 481adbc85640..a4824d7d4082 100644 --- a/java/rocksjni/sst_file_writerjni.cc +++ b/java/rocksjni/sst_file_writerjni.cc @@ -283,6 +283,25 @@ void Java_org_rocksdb_SstFileWriter_delete__JJ(JNIEnv *env, jclass /*jcls*/, } } +/* + * Class: org_rocksdb_SstFileWriter + * Method: deleteDirect + * Signature: (JLjava/nio/ByteBuffer;IIL)V + */ +void Java_org_rocksdb_SstFileWriter_deleteDirect(JNIEnv *env, jclass /*jcls*/, + jlong jdb_handle, jobject jkey, + jint jkey_off, jint jkey_len) { + auto *writer = reinterpret_cast(jdb_handle); + auto Delete = [&env, &writer](ROCKSDB_NAMESPACE::Slice &key) { + ROCKSDB_NAMESPACE::Status s = writer->Delete(key); + if (s.ok()) { + return; + } + ROCKSDB_NAMESPACE::RocksDBExceptionJni::ThrowNew(env, s); + }; + ROCKSDB_NAMESPACE::JniUtil::k_op_direct(Delete, env, jkey, jkey_off, jkey_len); +} + /* * Class: org_rocksdb_SstFileWriter * Method: finish diff --git a/java/src/main/java/org/rocksdb/SstFileWriter.java b/java/src/main/java/org/rocksdb/SstFileWriter.java index ff8b574a9133..ad6dcd8cc9e6 100644 --- a/java/src/main/java/org/rocksdb/SstFileWriter.java +++ b/java/src/main/java/org/rocksdb/SstFileWriter.java @@ -150,6 +150,20 @@ public void delete(final Slice key) throws RocksDBException { delete(nativeHandle_, key.getNativeHandle()); } + /** + * Add a Delete key with value to currently opened file. + * + * @param key the specified key to be inserted. + * + * @throws RocksDBException thrown if error happens in underlying + * native library. + */ + public void delete(final ByteBuffer key) throws RocksDBException { + assert key.isDirect(); + deleteDirect(nativeHandle_, key, key.position(), key.remaining()); + key.position(key.limit()); + } + /** * Add a deletion key to currently opened file. * @@ -227,6 +241,9 @@ private static native void delete(final long handle, final long keyHandle) private static native void delete(final long handle, final byte[] key) throws RocksDBException; + private static native void deleteDirect(long handle, ByteBuffer key, int keyOffset, int keyLength) + throws RocksDBException; + private static native void finish(final long handle) throws RocksDBException; @Override diff --git a/java/src/test/java/org/rocksdb/SstFileWriterTest.java b/java/src/test/java/org/rocksdb/SstFileWriterTest.java index c0f4ed9f1a4a..2c8195998679 100644 --- a/java/src/test/java/org/rocksdb/SstFileWriterTest.java +++ b/java/src/test/java/org/rocksdb/SstFileWriterTest.java @@ -30,7 +30,7 @@ public class SstFileWriterTest { @Rule public TemporaryFolder parentFolder = new TemporaryFolder(); - enum OpType { PUT, PUT_BYTES, PUT_DIRECT, MERGE, MERGE_BYTES, DELETE, DELETE_BYTES } + enum OpType { PUT, PUT_BYTES, PUT_DIRECT, MERGE, MERGE_BYTES, DELETE, DELETE_BYTES, DELETE_DIRECT } static class KeyValueWithOp { KeyValueWithOp(final String key, final String value, final OpType opType) { @@ -114,6 +114,9 @@ private File newSstFile(final List keyValues, case DELETE_BYTES: sstFileWriter.delete(keyBytes); break; + case DELETE_DIRECT: + sstFileWriter.delete(keyDirect); + break; default: fail("Unsupported op type"); } @@ -146,6 +149,7 @@ public void generateSstFileWithJavaComparator() keyValues.add(new KeyValueWithOp("key3", "value3", OpType.MERGE)); keyValues.add(new KeyValueWithOp("key4", "value4", OpType.MERGE)); keyValues.add(new KeyValueWithOp("key5", "", OpType.DELETE)); + keyValues.add(new KeyValueWithOp("key6", "", OpType.DELETE_DIRECT)); newSstFile(keyValues, true); } @@ -159,6 +163,7 @@ public void generateSstFileWithNativeComparator() keyValues.add(new KeyValueWithOp("key3", "value3", OpType.MERGE)); keyValues.add(new KeyValueWithOp("key4", "value4", OpType.MERGE)); keyValues.add(new KeyValueWithOp("key5", "", OpType.DELETE)); + keyValues.add(new KeyValueWithOp("key6", "", OpType.DELETE_DIRECT)); newSstFile(keyValues, false); } @@ -173,6 +178,7 @@ public void ingestSstFile() throws RocksDBException, IOException { keyValues.add(new KeyValueWithOp("key5", "value5", OpType.MERGE_BYTES)); keyValues.add(new KeyValueWithOp("key6", "", OpType.DELETE)); keyValues.add(new KeyValueWithOp("key7", "", OpType.DELETE)); + keyValues.add(new KeyValueWithOp("key8", "", OpType.DELETE_DIRECT)); final File sstFile = newSstFile(keyValues, false); @@ -185,6 +191,8 @@ public void ingestSstFile() throws RocksDBException, IOException { final RocksDB db = RocksDB.open(options, dbFolder.getAbsolutePath()); final IngestExternalFileOptions ingestExternalFileOptions = new IngestExternalFileOptions()) { + db.put("key8".getBytes(), "value8".getBytes()); + assertThat(db.get("key8".getBytes())).isEqualTo("value8".getBytes()); db.ingestExternalFile( Collections.singletonList(sstFile.getAbsolutePath()), ingestExternalFileOptions); @@ -195,6 +203,7 @@ public void ingestSstFile() throws RocksDBException, IOException { assertThat(db.get("key5".getBytes())).isEqualTo("value5".getBytes()); assertThat(db.get("key6".getBytes())).isEqualTo(null); assertThat(db.get("key7".getBytes())).isEqualTo(null); + assertThat(db.get("key8".getBytes())).isEqualTo(null); } } @@ -205,6 +214,7 @@ public void ingestSstFile_cf() throws RocksDBException, IOException { keyValues.add(new KeyValueWithOp("key2", "value2", OpType.PUT)); keyValues.add(new KeyValueWithOp("key3", "value3", OpType.MERGE)); keyValues.add(new KeyValueWithOp("key4", "", OpType.DELETE)); + keyValues.add(new KeyValueWithOp("key5", "", OpType.DELETE_DIRECT)); final File sstFile = newSstFile(keyValues, false); final File dbFolder = parentFolder.newFolder(DB_DIRECTORY_NAME); @@ -222,6 +232,8 @@ public void ingestSstFile_cf() throws RocksDBException, IOException { .setMergeOperator(stringAppendOperator); final ColumnFamilyHandle cf_handle = db.createColumnFamily( new ColumnFamilyDescriptor("new_cf".getBytes(), cf_opts))) { + db.put(cf_handle, "key5".getBytes(), "value5".getBytes()); + assertThat(db.get(cf_handle, "key5".getBytes())).isEqualTo("value5".getBytes()); db.ingestExternalFile(cf_handle, Collections.singletonList(sstFile.getAbsolutePath()), ingestExternalFileOptions); @@ -233,6 +245,8 @@ public void ingestSstFile_cf() throws RocksDBException, IOException { "key3".getBytes())).isEqualTo("value3".getBytes()); assertThat(db.get(cf_handle, "key4".getBytes())).isEqualTo(null); + assertThat(db.get(cf_handle, + "key5".getBytes())).isEqualTo(null); } } }