Copilot commented on code in PR #11068:
URL: https://github.com/apache/ozone/pull/11068#discussion_r3899865788


##########
hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/TypedTable.java:
##########
@@ -306,6 +317,143 @@ private VALUE getFromTable(KEY key) throws 
RocksDatabaseException, CodecExceptio
     }
   }
 
+  List<VALUE> multiGetFromTable(List<KEY> keys)
+      throws RocksDatabaseException, CodecException {
+    if (supportCodecBuffer) {
+      return multiGetFromTableWithCodecBuffer(keys);
+    }
+    return multiGetFromTableWithByteArray(keys);
+  }
+
+  List<VALUE> multiGetFromTableWithByteArray(List<KEY> keys)
+      throws RocksDatabaseException, CodecException {
+    List<byte[]> keyBytesList = new ArrayList<>(keys.size());
+    for (KEY key : keys) {
+      keyBytesList.add(encodeKey(key));
+    }
+    List<byte[]> valueBytesList = rawTable.multiGetSkipCache(keyBytesList);
+    List<VALUE> values = new ArrayList<>(keys.size());
+    for (byte[] valueBytes : valueBytesList) {
+      values.add(decodeValue(valueBytes));
+    }
+    return values;
+  }
+
+  List<VALUE> multiGetFromTableWithCodecBuffer(List<KEY> keys)
+      throws RocksDatabaseException, CodecException {
+    final int n = keys.size();
+    final List<CodecBuffer> keyBuffers = new ArrayList<>(n);
+    final List<ByteBuffer> keyByteBuffers = new ArrayList<>(n);
+    final List<CodecBuffer> valueBuffers = new ArrayList<>(n);
+    final List<ByteBuffer> valueByteBuffers = new ArrayList<>(n);
+    final int initialCapacity = bufferCapacity.get();
+    for (KEY key : keys) {
+      final CodecBuffer keyBuffer = keyCodec.toDirectCodecBuffer(key);
+      keyBuffers.add(keyBuffer);
+      keyByteBuffers.add(keyBuffer.asReadOnlyByteBuffer());
+      final CodecBuffer valueBuffer = 
CodecBuffer.allocateDirect(initialCapacity);
+      valueBuffers.add(valueBuffer);
+      addWritableValueByteBuffer(valueBuffer, initialCapacity, 
valueByteBuffers);
+    }
+
+    try {
+      final List<VALUE> values = new ArrayList<>(Collections.nCopies(n, null));
+      final List<Integer> retryIndices = new ArrayList<>();
+      final List<Integer> retrySizes = new ArrayList<>();
+      try {
+        applyMultiGetStatuses(rawTable.multiGetSkipCache(keyByteBuffers, 
valueByteBuffers),
+            valueBuffers, initialCapacity, values, retryIndices, retrySizes);
+        if (!retryIndices.isEmpty()) {
+          retryOversizedMultiGet(keyByteBuffers, retryIndices, retrySizes, 
values);
+          bufferCapacity.increase(Collections.max(retrySizes));
+        }
+        return values;
+      } finally {
+        IOUtils.closeQuietly(valueBuffers);
+      }
+    } finally {
+      IOUtils.closeQuietly(keyBuffers);
+    }
+  }
+
+  void applyMultiGetStatuses(List<ByteBufferGetStatus> statuses, 
List<CodecBuffer> valueBuffers,
+      int valueBufferCapacity, List<VALUE> values, List<Integer> retryIndices, 
List<Integer> retrySizes)
+      throws CodecException {
+    for (int i = 0; i < statuses.size(); i++) {
+      final ByteBufferGetStatus status = statuses.get(i);
+      final CodecBuffer valueBuffer = valueBuffers.get(i);
+      if (status.value == null) {
+        continue;
+      }
+      validateMultiGetStatus(status, null);
+      if (status.requiredSize > valueBufferCapacity) {
+        retryIndices.add(i);
+        retrySizes.add(status.requiredSize);
+      } else {
+        values.set(i, decodeFromMultiGetStatus(status, valueBuffer));
+      }
+    }
+  }
+
+  void retryOversizedMultiGet(List<ByteBuffer> keyByteBuffers, List<Integer> 
retryIndices,
+      List<Integer> retrySizes, List<VALUE> values) throws 
RocksDatabaseException, CodecException {
+    final int retryCount = retryIndices.size();
+    final List<ByteBuffer> retryKeyByteBuffers = new ArrayList<>(retryCount);
+    final List<CodecBuffer> retryValueBuffers = new ArrayList<>(retryCount);
+    final List<ByteBuffer> retryValueByteBuffers = new ArrayList<>(retryCount);
+    for (int j = 0; j < retryCount; j++) {
+      final int requiredSize = retrySizes.get(j);
+      
retryKeyByteBuffers.add(keyByteBuffers.get(retryIndices.get(j)).duplicate());
+      final CodecBuffer valueBuffer = CodecBuffer.allocateDirect(requiredSize);
+      retryValueBuffers.add(valueBuffer);
+      addWritableValueByteBuffer(valueBuffer, requiredSize, 
retryValueByteBuffers);
+    }
+
+    try {
+      final List<ByteBufferGetStatus> retryStatuses =
+          rawTable.multiGetSkipCache(retryKeyByteBuffers, 
retryValueByteBuffers);
+      for (int j = 0; j < retryCount; j++) {
+        final int index = retryIndices.get(j);
+        final int expectedSize = retrySizes.get(j);
+        final ByteBufferGetStatus status = retryStatuses.get(j);
+        final CodecBuffer valueBuffer = retryValueBuffers.get(j);
+        if (status.value == null) {
+          continue;
+        }
+        validateMultiGetStatus(status, expectedSize);
+        values.set(index, decodeFromMultiGetStatus(status, valueBuffer));
+      }
+    } finally {
+      IOUtils.closeQuietly(retryValueBuffers);
+    }
+  }
+
+  static void addWritableValueByteBuffer(CodecBuffer valueBuffer, int capacity,
+      List<ByteBuffer> valueByteBuffers) {
+    valueBuffer.clear();
+    final ByteBuffer out = valueBuffer.asWritableByteBuffer();
+    out.position(0).limit(capacity);
+    valueByteBuffers.add(out);
+  }
+
+  static void validateMultiGetStatus(ByteBufferGetStatus status, Integer 
expectedSize) {
+    if (status.requiredSize < 0 || status.status.getCode() != 
org.rocksdb.Status.Code.Ok) {
+      throw new IllegalStateException("status = " + status.status.getCode()
+          + "; required = " + status.requiredSize + " < 0");

Review Comment:
   The IllegalStateException message in validateMultiGetStatus is misleading: 
it always says "< 0" even when the failure is due to a non-OK RocksDB status 
code. This makes debugging multiGet failures harder.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to