This is an automated email from the ASF dual-hosted git repository.

szetszwo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 1bfd93b12d HDDS-8725. Support keyMayExist with ByteBuffer. (#4793)
1bfd93b12d is described below

commit 1bfd93b12d768ed115b8f9aa25a91f0e4d5c1277
Author: Tsz-Wo Nicholas Sze <[email protected]>
AuthorDate: Thu Jun 1 03:16:11 2023 +0800

    HDDS-8725. Support keyMayExist with ByteBuffer. (#4793)
---
 .../apache/hadoop/hdds/utils/db/CodecBuffer.java   |  2 +-
 .../org/apache/hadoop/hdds/utils/db/RDBTable.java  | 21 +++++++++++
 .../apache/hadoop/hdds/utils/db/RocksDatabase.java | 21 +++++++++++
 .../apache/hadoop/hdds/utils/db/TypedTable.java    | 44 ++++++++++++++++++++--
 pom.xml                                            |  1 +
 5 files changed, 85 insertions(+), 4 deletions(-)

diff --git 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/utils/db/CodecBuffer.java
 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/utils/db/CodecBuffer.java
index 38d2db8af7..f73cd389fd 100644
--- 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/utils/db/CodecBuffer.java
+++ 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/utils/db/CodecBuffer.java
@@ -251,7 +251,7 @@ public final class CodecBuffer implements AutoCloseable {
     final Integer size = source.apply(buffer);
     if (size != null) {
       Preconditions.assertTrue(size >= 0, () -> "size = " + size + " < 0");
-      if (size <= writable) {
+      if (size > 0 && size <= writable) {
         buf.setIndex(buf.readerIndex(), i + size);
       }
     }
diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/RDBTable.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/RDBTable.java
index 63d0e431c9..c597ad73e6 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/RDBTable.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/RDBTable.java
@@ -167,6 +167,27 @@ class RDBTable implements Table<byte[], byte[]> {
     return val;
   }
 
+  Integer getIfExist(ByteBuffer key, ByteBuffer outValue) throws IOException {
+    rdbMetrics.incNumDBKeyGetIfExistChecks();
+    final Supplier<Integer> value = db.keyMayExist(
+        family, key, outValue.duplicate());
+    if (value == null) {
+      return null; // definitely not exists
+    }
+    if (value.get() != null) {
+      // definitely exists, return value size.
+      return value.get();
+    }
+
+    // inconclusive: the key may or may not exist
+    rdbMetrics.incNumDBKeyGetIfExistGets();
+    final Integer val = get(key, outValue);
+    if (val == null) {
+      rdbMetrics.incNumDBKeyGetIfExistMisses();
+    }
+    return val;
+  }
+
   @Override
   public void delete(byte[] key) throws IOException {
     db.delete(family, key);
diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/RocksDatabase.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/RocksDatabase.java
index c800cce171..2e59d7f16c 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/RocksDatabase.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/RocksDatabase.java
@@ -37,6 +37,7 @@ import 
org.apache.hadoop.hdds.utils.db.managed.ManagedWriteOptions;
 import org.rocksdb.ColumnFamilyDescriptor;
 import org.rocksdb.ColumnFamilyHandle;
 import org.rocksdb.Holder;
+import org.rocksdb.KeyMayExist;
 import org.rocksdb.LiveFileMetaData;
 import org.rocksdb.RocksDBException;
 import org.slf4j.Logger;
@@ -671,6 +672,26 @@ public final class RocksDatabase implements Closeable {
     }
   }
 
+  Supplier<Integer> keyMayExist(ColumnFamily family,
+      ByteBuffer key, ByteBuffer out) throws IOException {
+    assertClose();
+    try {
+      counter.incrementAndGet();
+      final KeyMayExist result = db.get().keyMayExist(
+          family.getHandle(), key, out);
+      switch (result.exists) {
+      case kNotExist: return null;
+      case kExistsWithValue: return () -> result.valueLength;
+      case kExistsWithoutValue: return () -> null;
+      default:
+        throw new IllegalStateException(
+            "Unexpected KeyMayExistEnum case " + result.exists);
+      }
+    } finally {
+      counter.decrementAndGet();
+    }
+  }
+
   public ColumnFamily getColumnFamily(String key) {
     return columnFamilies.get(key);
   }
diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/TypedTable.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/TypedTable.java
index 26e1f5c58c..068722b8ad 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/TypedTable.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/TypedTable.java
@@ -187,6 +187,14 @@ public class TypedTable<KEY, VALUE> implements Table<KEY, 
VALUE> {
       return true;
     } else if (cacheResult.getCacheStatus() == NOT_EXIST) {
       return false;
+    } else if (keyCodec.supportCodecBuffer()) {
+      // keyCodec.supportCodecBuffer() is enough since value is not needed.
+      try (CodecBuffer inKey = keyCodec.toDirectCodecBuffer(key)) {
+        // Use zero capacity buffer since value is not needed.
+        try (CodecBuffer outValue = CodecBuffer.allocateDirect(0)) {
+          return getFromTableIfExist(inKey, outValue) != null;
+        }
+      }
     } else {
       return rawTable.isExist(encodeKey(key));
     }
@@ -334,10 +342,40 @@ public class TypedTable<KEY, VALUE> implements Table<KEY, 
VALUE> {
     }
   }
 
+  private Integer getFromTableIfExist(CodecBuffer key,
+      CodecBuffer outValue) throws IOException {
+    return outValue.putFromSource(
+        buffer -> rawTable.getIfExist(key.asReadOnlyByteBuffer(), buffer));
+  }
+
+  private VALUE getFromTableIfExistCodecBuffer(KEY key) throws IOException {
+    try (CodecBuffer inKey = keyCodec.toDirectCodecBuffer(key)) {
+      for (; ;) {
+        final int allocated = bufferSize.get();
+        try (CodecBuffer outValue = CodecBuffer.allocateDirect(allocated)) {
+          final Integer required = getFromTableIfExist(inKey, outValue);
+          if (required == null) {
+            // key not found
+            return null;
+          } else if (required >= 0 && required <= allocated) {
+            // buffer size is big enough
+            return valueCodec.fromCodecBuffer(outValue);
+          }
+          // buffer size too small, retry
+          increaseBufferSize(required);
+        }
+      }
+    }
+  }
+
   private VALUE getFromTableIfExist(KEY key) throws IOException {
-    final byte[] keyBytes = encodeKey(key);
-    byte[] valueBytes = rawTable.getIfExist(keyBytes);
-    return decodeValue(valueBytes);
+    if (supportCodecBuffer) {
+      return getFromTableIfExistCodecBuffer(key);
+    } else {
+      final byte[] keyBytes = encodeKey(key);
+      final byte[] valueBytes = rawTable.getIfExist(keyBytes);
+      return decodeValue(valueBytes);
+    }
   }
 
   @Override
diff --git a/pom.xml b/pom.xml
index f7e1a4f59b..2b83f05a46 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1765,6 +1765,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xs
                       <!-- Allow non-RocksObject classes. -->
                       
<allowedImport>org.rocksdb.ColumnFamilyDescriptor</allowedImport>
                       
<allowedImport>org.rocksdb.CompactionStyle</allowedImport>
+                      <allowedImport>org.rocksdb.KeyMayExist</allowedImport>
                       <allowedImport>org.rocksdb.HistogramData</allowedImport>
                       <allowedImport>org.rocksdb.HistogramType</allowedImport>
                       <allowedImport>org.rocksdb.Holder</allowedImport>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to