]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/rocksdb/java/src/test/java/org/rocksdb/MultiGetTest.java
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / java / src / test / java / org / rocksdb / MultiGetTest.java
diff --git a/ceph/src/rocksdb/java/src/test/java/org/rocksdb/MultiGetTest.java b/ceph/src/rocksdb/java/src/test/java/org/rocksdb/MultiGetTest.java
new file mode 100644 (file)
index 0000000..323a6b1
--- /dev/null
@@ -0,0 +1,525 @@
+// 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 static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.rocksdb.util.TestUtil;
+
+public class MultiGetTest {
+  @Rule public TemporaryFolder dbFolder = new TemporaryFolder();
+
+  @Test
+  public void putNThenMultiGet() throws RocksDBException {
+    try (final Options opt = new Options().setCreateIfMissing(true);
+         final RocksDB db = RocksDB.open(opt, dbFolder.getRoot().getAbsolutePath())) {
+      db.put("key1".getBytes(), "value1ForKey1".getBytes());
+      db.put("key2".getBytes(), "value2ForKey2".getBytes());
+      db.put("key3".getBytes(), "value3ForKey3".getBytes());
+      final List<byte[]> keys =
+          Arrays.asList("key1".getBytes(), "key2".getBytes(), "key3".getBytes());
+      final List<byte[]> values = db.multiGetAsList(keys);
+      assertThat(values.size()).isEqualTo(keys.size());
+      assertThat(values.get(0)).isEqualTo("value1ForKey1".getBytes());
+      assertThat(values.get(1)).isEqualTo("value2ForKey2".getBytes());
+      assertThat(values.get(2)).isEqualTo("value3ForKey3".getBytes());
+    }
+  }
+
+  @Test
+  public void putNThenMultiGetDirect() throws RocksDBException {
+    try (final Options opt = new Options().setCreateIfMissing(true);
+         final RocksDB db = RocksDB.open(opt, dbFolder.getRoot().getAbsolutePath())) {
+      db.put("key1".getBytes(), "value1ForKey1".getBytes());
+      db.put("key2".getBytes(), "value2ForKey2".getBytes());
+      db.put("key3".getBytes(), "value3ForKey3".getBytes());
+
+      final List<ByteBuffer> keys = new ArrayList<>();
+      keys.add(ByteBuffer.allocateDirect(12).put("key1".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key2".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key3".getBytes()));
+      // Java8 and lower flip() returns Buffer not ByteBuffer, so can't chain above /\/\
+      for (final ByteBuffer key : keys) {
+        key.flip();
+      }
+      final List<ByteBuffer> values = new ArrayList<>();
+      for (int i = 0; i < keys.size(); i++) {
+        values.add(ByteBuffer.allocateDirect(24));
+      }
+
+      {
+        final List<ByteBufferGetStatus> results = db.multiGetByteBuffers(keys, values);
+
+        assertThat(results.get(0).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(1).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(2).status.getCode()).isEqualTo(Status.Code.Ok);
+
+        assertThat(results.get(0).requiredSize).isEqualTo("value1ForKey1".getBytes().length);
+        assertThat(results.get(1).requiredSize).isEqualTo("value2ForKey2".getBytes().length);
+        assertThat(results.get(2).requiredSize).isEqualTo("value3ForKey3".getBytes().length);
+
+        assertThat(TestUtil.bufferBytes(results.get(0).value))
+            .isEqualTo("value1ForKey1".getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(1).value))
+            .isEqualTo("value2ForKey2".getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(2).value))
+            .isEqualTo("value3ForKey3".getBytes());
+      }
+
+      {
+        final List<ByteBufferGetStatus> results =
+            db.multiGetByteBuffers(new ReadOptions(), keys, values);
+
+        assertThat(results.get(0).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(1).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(2).status.getCode()).isEqualTo(Status.Code.Ok);
+
+        assertThat(results.get(0).requiredSize).isEqualTo("value1ForKey1".getBytes().length);
+        assertThat(results.get(1).requiredSize).isEqualTo("value2ForKey2".getBytes().length);
+        assertThat(results.get(2).requiredSize).isEqualTo("value3ForKey3".getBytes().length);
+
+        assertThat(TestUtil.bufferBytes(results.get(0).value))
+            .isEqualTo("value1ForKey1".getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(1).value))
+            .isEqualTo("value2ForKey2".getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(2).value))
+            .isEqualTo("value3ForKey3".getBytes());
+      }
+    }
+  }
+
+  @Test
+  public void putNThenMultiGetDirectSliced() throws RocksDBException {
+    try (final Options opt = new Options().setCreateIfMissing(true);
+         final RocksDB db = RocksDB.open(opt, dbFolder.getRoot().getAbsolutePath())) {
+      db.put("key1".getBytes(), "value1ForKey1".getBytes());
+      db.put("key2".getBytes(), "value2ForKey2".getBytes());
+      db.put("key3".getBytes(), "value3ForKey3".getBytes());
+
+      final List<ByteBuffer> keys = new ArrayList<>();
+      keys.add(ByteBuffer.allocateDirect(12).put("key2".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key3".getBytes()));
+      keys.add(
+          ByteBuffer.allocateDirect(12).put("prefix1".getBytes()).slice().put("key1".getBytes()));
+      // Java8 and lower flip() returns Buffer not ByteBuffer, so can't chain above /\/\
+      for (final ByteBuffer key : keys) {
+        key.flip();
+      }
+      final List<ByteBuffer> values = new ArrayList<>();
+      for (int i = 0; i < keys.size(); i++) {
+        values.add(ByteBuffer.allocateDirect(24));
+      }
+
+      {
+        final List<ByteBufferGetStatus> results = db.multiGetByteBuffers(keys, values);
+
+        assertThat(results.get(0).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(1).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(2).status.getCode()).isEqualTo(Status.Code.Ok);
+
+        assertThat(results.get(1).requiredSize).isEqualTo("value2ForKey2".getBytes().length);
+        assertThat(results.get(2).requiredSize).isEqualTo("value3ForKey3".getBytes().length);
+        assertThat(results.get(0).requiredSize).isEqualTo("value1ForKey1".getBytes().length);
+
+        assertThat(TestUtil.bufferBytes(results.get(0).value))
+            .isEqualTo("value2ForKey2".getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(1).value))
+            .isEqualTo("value3ForKey3".getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(2).value))
+            .isEqualTo("value1ForKey1".getBytes());
+      }
+    }
+  }
+
+  @Test
+  public void putNThenMultiGetDirectBadValuesArray() throws RocksDBException {
+    try (final Options opt = new Options().setCreateIfMissing(true);
+         final RocksDB db = RocksDB.open(opt, dbFolder.getRoot().getAbsolutePath())) {
+      db.put("key1".getBytes(), "value1ForKey1".getBytes());
+      db.put("key2".getBytes(), "value2ForKey2".getBytes());
+      db.put("key3".getBytes(), "value3ForKey3".getBytes());
+
+      final List<ByteBuffer> keys = new ArrayList<>();
+      keys.add(ByteBuffer.allocateDirect(12).put("key1".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key2".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key3".getBytes()));
+      // Java8 and lower flip() returns Buffer not ByteBuffer, so can't chain above /\/\
+      for (final ByteBuffer key : keys) {
+        key.flip();
+      }
+
+      {
+        final List<ByteBuffer> values = new ArrayList<>();
+        for (int i = 0; i < keys.size(); i++) {
+          values.add(ByteBuffer.allocateDirect(24));
+        }
+
+        values.remove(0);
+
+        try {
+          db.multiGetByteBuffers(keys, values);
+          fail("Expected exception when not enough value ByteBuffers supplied");
+        } catch (final IllegalArgumentException e) {
+          assertThat(e.getMessage()).contains("For each key there must be a corresponding value");
+        }
+      }
+
+      {
+        final List<ByteBuffer> values = new ArrayList<>();
+        for (int i = 0; i < keys.size(); i++) {
+          values.add(ByteBuffer.allocateDirect(24));
+        }
+
+        values.add(ByteBuffer.allocateDirect(24));
+
+        try {
+          db.multiGetByteBuffers(keys, values);
+          fail("Expected exception when too many value ByteBuffers supplied");
+        } catch (final IllegalArgumentException e) {
+          assertThat(e.getMessage()).contains("For each key there must be a corresponding value");
+        }
+      }
+    }
+  }
+
+  @Test
+  public void putNThenMultiGetDirectShortValueBuffers() throws RocksDBException {
+    try (final Options opt = new Options().setCreateIfMissing(true);
+         final RocksDB db = RocksDB.open(opt, dbFolder.getRoot().getAbsolutePath())) {
+      db.put("key1".getBytes(), "value1ForKey1".getBytes());
+      db.put("key2".getBytes(), "value2ForKey2".getBytes());
+      db.put("key3".getBytes(), "value3ForKey3".getBytes());
+
+      final List<ByteBuffer> keys = new ArrayList<>();
+      keys.add(ByteBuffer.allocateDirect(12).put("key1".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key2".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key3".getBytes()));
+      // Java8 and lower flip() returns Buffer not ByteBuffer, so can't chain above /\/\
+      for (final ByteBuffer key : keys) {
+        key.flip();
+      }
+
+      {
+        final List<ByteBuffer> values = new ArrayList<>();
+        for (int i = 0; i < keys.size(); i++) {
+          values.add(ByteBuffer.allocateDirect(4));
+        }
+
+        final List<ByteBufferGetStatus> statii = db.multiGetByteBuffers(keys, values);
+        assertThat(statii.size()).isEqualTo(values.size());
+        for (final ByteBufferGetStatus status : statii) {
+          assertThat(status.status.getCode()).isEqualTo(Status.Code.Ok);
+          assertThat(status.requiredSize).isEqualTo("value3ForKey3".getBytes().length);
+          final ByteBuffer expected =
+              ByteBuffer.allocateDirect(24).put(Arrays.copyOf("valueX".getBytes(), 4));
+          expected.flip();
+          assertThat(status.value).isEqualTo(expected);
+        }
+      }
+    }
+  }
+
+  @Test
+  public void putNThenMultiGetDirectNondefaultCF() throws RocksDBException {
+    try (final Options opt = new Options().setCreateIfMissing(true);
+         final RocksDB db = RocksDB.open(opt, dbFolder.getRoot().getAbsolutePath())) {
+      final List<ColumnFamilyDescriptor> cfDescriptors = new ArrayList<>(0);
+      cfDescriptors.add(new ColumnFamilyDescriptor("cf0".getBytes()));
+      cfDescriptors.add(new ColumnFamilyDescriptor("cf1".getBytes()));
+      cfDescriptors.add(new ColumnFamilyDescriptor("cf2".getBytes()));
+
+      final List<ColumnFamilyHandle> cf = db.createColumnFamilies(cfDescriptors);
+
+      db.put(cf.get(0), "key1".getBytes(), "value1ForKey1".getBytes());
+      db.put(cf.get(0), "key2".getBytes(), "value2ForKey2".getBytes());
+      db.put(cf.get(0), "key3".getBytes(), "value3ForKey3".getBytes());
+
+      final List<ByteBuffer> keys = new ArrayList<>();
+      keys.add(ByteBuffer.allocateDirect(12).put("key1".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key2".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key3".getBytes()));
+      // Java8 and lower flip() returns Buffer not ByteBuffer, so can't chain above /\/\
+      for (final ByteBuffer key : keys) {
+        key.flip();
+      }
+      final List<ByteBuffer> values = new ArrayList<>();
+      for (int i = 0; i < keys.size(); i++) {
+        values.add(ByteBuffer.allocateDirect(24));
+      }
+
+      {
+        final List<ByteBufferGetStatus> results = db.multiGetByteBuffers(keys, values);
+
+        assertThat(results.get(0).status.getCode()).isEqualTo(Status.Code.NotFound);
+        assertThat(results.get(1).status.getCode()).isEqualTo(Status.Code.NotFound);
+        assertThat(results.get(2).status.getCode()).isEqualTo(Status.Code.NotFound);
+      }
+
+      {
+        final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
+        columnFamilyHandles.add(cf.get(0));
+        final List<ByteBufferGetStatus> results =
+            db.multiGetByteBuffers(columnFamilyHandles, keys, values);
+
+        assertThat(results.get(0).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(1).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(2).status.getCode()).isEqualTo(Status.Code.Ok);
+
+        assertThat(results.get(0).requiredSize).isEqualTo("value1ForKey1".getBytes().length);
+        assertThat(results.get(1).requiredSize).isEqualTo("value2ForKey2".getBytes().length);
+        assertThat(results.get(2).requiredSize).isEqualTo("value3ForKey3".getBytes().length);
+
+        assertThat(TestUtil.bufferBytes(results.get(0).value))
+            .isEqualTo("value1ForKey1".getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(1).value))
+            .isEqualTo("value2ForKey2".getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(2).value))
+            .isEqualTo("value3ForKey3".getBytes());
+      }
+
+      {
+        final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
+        columnFamilyHandles.add(cf.get(0));
+        columnFamilyHandles.add(cf.get(0));
+        columnFamilyHandles.add(cf.get(0));
+        final List<ByteBufferGetStatus> results =
+            db.multiGetByteBuffers(columnFamilyHandles, keys, values);
+
+        assertThat(results.get(0).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(1).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(2).status.getCode()).isEqualTo(Status.Code.Ok);
+
+        assertThat(results.get(0).requiredSize).isEqualTo("value1ForKey1".getBytes().length);
+        assertThat(results.get(1).requiredSize).isEqualTo("value2ForKey2".getBytes().length);
+        assertThat(results.get(2).requiredSize).isEqualTo("value3ForKey3".getBytes().length);
+
+        assertThat(TestUtil.bufferBytes(results.get(0).value))
+            .isEqualTo("value1ForKey1".getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(1).value))
+            .isEqualTo("value2ForKey2".getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(2).value))
+            .isEqualTo("value3ForKey3".getBytes());
+      }
+    }
+  }
+
+  @Test
+  public void putNThenMultiGetDirectCFParams() throws RocksDBException {
+    try (final Options opt = new Options().setCreateIfMissing(true);
+         final RocksDB db = RocksDB.open(opt, dbFolder.getRoot().getAbsolutePath())) {
+      db.put("key1".getBytes(), "value1ForKey1".getBytes());
+      db.put("key2".getBytes(), "value2ForKey2".getBytes());
+      db.put("key3".getBytes(), "value3ForKey3".getBytes());
+
+      final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
+      columnFamilyHandles.add(db.getDefaultColumnFamily());
+      columnFamilyHandles.add(db.getDefaultColumnFamily());
+
+      final List<ByteBuffer> keys = new ArrayList<>();
+      keys.add(ByteBuffer.allocateDirect(12).put("key1".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key2".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key3".getBytes()));
+      // Java8 and lower flip() returns Buffer not ByteBuffer, so can't chain above /\/\
+      for (final ByteBuffer key : keys) {
+        key.flip();
+      }
+      final List<ByteBuffer> values = new ArrayList<>();
+      for (int i = 0; i < keys.size(); i++) {
+        values.add(ByteBuffer.allocateDirect(24));
+      }
+      try {
+        db.multiGetByteBuffers(columnFamilyHandles, keys, values);
+        fail("Expected exception when 2 column families supplied");
+      } catch (final IllegalArgumentException e) {
+        assertThat(e.getMessage()).contains("Wrong number of ColumnFamilyHandle(s) supplied");
+      }
+
+      columnFamilyHandles.clear();
+      columnFamilyHandles.add(db.getDefaultColumnFamily());
+      final List<ByteBufferGetStatus> results =
+          db.multiGetByteBuffers(columnFamilyHandles, keys, values);
+
+      assertThat(results.get(0).status.getCode()).isEqualTo(Status.Code.Ok);
+      assertThat(results.get(1).status.getCode()).isEqualTo(Status.Code.Ok);
+      assertThat(results.get(2).status.getCode()).isEqualTo(Status.Code.Ok);
+
+      assertThat(results.get(0).requiredSize).isEqualTo("value1ForKey1".getBytes().length);
+      assertThat(results.get(1).requiredSize).isEqualTo("value2ForKey2".getBytes().length);
+      assertThat(results.get(2).requiredSize).isEqualTo("value3ForKey3".getBytes().length);
+
+      assertThat(TestUtil.bufferBytes(results.get(0).value)).isEqualTo("value1ForKey1".getBytes());
+      assertThat(TestUtil.bufferBytes(results.get(1).value)).isEqualTo("value2ForKey2".getBytes());
+      assertThat(TestUtil.bufferBytes(results.get(2).value)).isEqualTo("value3ForKey3".getBytes());
+    }
+  }
+
+  @Test
+  public void putNThenMultiGetDirectMixedCF() throws RocksDBException {
+    try (final Options opt = new Options().setCreateIfMissing(true);
+         final RocksDB db = RocksDB.open(opt, dbFolder.getRoot().getAbsolutePath())) {
+      final List<ColumnFamilyDescriptor> cfDescriptors = new ArrayList<>();
+      cfDescriptors.add(new ColumnFamilyDescriptor("cf0".getBytes()));
+      cfDescriptors.add(new ColumnFamilyDescriptor("cf1".getBytes()));
+      cfDescriptors.add(new ColumnFamilyDescriptor("cf2".getBytes()));
+      cfDescriptors.add(new ColumnFamilyDescriptor("cf3".getBytes()));
+
+      final List<ColumnFamilyHandle> cf = db.createColumnFamilies(cfDescriptors);
+
+      db.put(cf.get(1), "key1".getBytes(), "value1ForKey1".getBytes());
+      db.put("key2".getBytes(), "value2ForKey2".getBytes());
+      db.put(cf.get(3), "key3".getBytes(), "value3ForKey3".getBytes());
+
+      final List<ByteBuffer> keys = new ArrayList<>();
+      keys.add(ByteBuffer.allocateDirect(12).put("key1".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key2".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key3".getBytes()));
+      // Java8 and lower flip() returns Buffer not ByteBuffer, so can't chain above /\/\
+      for (final ByteBuffer key : keys) {
+        key.flip();
+      }
+      final List<ByteBuffer> values = new ArrayList<>();
+      for (int i = 0; i < keys.size(); i++) {
+        values.add(ByteBuffer.allocateDirect(24));
+      }
+
+      {
+        final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
+        columnFamilyHandles.add(db.getDefaultColumnFamily());
+
+        final List<ByteBufferGetStatus> results =
+            db.multiGetByteBuffers(columnFamilyHandles, keys, values);
+
+        assertThat(results.get(0).status.getCode()).isEqualTo(Status.Code.NotFound);
+        assertThat(results.get(1).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(2).status.getCode()).isEqualTo(Status.Code.NotFound);
+
+        assertThat(results.get(1).requiredSize).isEqualTo("value2ForKey2".getBytes().length);
+
+        assertThat(TestUtil.bufferBytes(results.get(1).value))
+            .isEqualTo("value2ForKey2".getBytes());
+      }
+
+      {
+        final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
+        columnFamilyHandles.add(cf.get(1));
+
+        final List<ByteBufferGetStatus> results =
+            db.multiGetByteBuffers(columnFamilyHandles, keys, values);
+
+        assertThat(results.get(0).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(1).status.getCode()).isEqualTo(Status.Code.NotFound);
+        assertThat(results.get(2).status.getCode()).isEqualTo(Status.Code.NotFound);
+
+        assertThat(results.get(0).requiredSize).isEqualTo("value2ForKey2".getBytes().length);
+
+        assertThat(TestUtil.bufferBytes(results.get(0).value))
+            .isEqualTo("value1ForKey1".getBytes());
+      }
+
+      {
+        final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
+        columnFamilyHandles.add(cf.get(1));
+        columnFamilyHandles.add(db.getDefaultColumnFamily());
+        columnFamilyHandles.add(cf.get(3));
+
+        final List<ByteBufferGetStatus> results =
+            db.multiGetByteBuffers(columnFamilyHandles, keys, values);
+
+        assertThat(results.get(0).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(1).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(2).status.getCode()).isEqualTo(Status.Code.Ok);
+
+        assertThat(results.get(0).requiredSize).isEqualTo("value1ForKey1".getBytes().length);
+        assertThat(results.get(1).requiredSize).isEqualTo("value2ForKey2".getBytes().length);
+        assertThat(results.get(2).requiredSize).isEqualTo("value3ForKey3".getBytes().length);
+
+        assertThat(TestUtil.bufferBytes(results.get(0).value))
+            .isEqualTo("value1ForKey1".getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(1).value))
+            .isEqualTo("value2ForKey2".getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(2).value))
+            .isEqualTo("value3ForKey3".getBytes());
+      }
+
+      {
+        final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
+        columnFamilyHandles.add(db.getDefaultColumnFamily());
+        columnFamilyHandles.add(cf.get(1));
+        columnFamilyHandles.add(cf.get(3));
+
+        final List<ByteBufferGetStatus> results =
+            db.multiGetByteBuffers(columnFamilyHandles, keys, values);
+
+        assertThat(results.get(0).status.getCode()).isEqualTo(Status.Code.NotFound);
+        assertThat(results.get(1).status.getCode()).isEqualTo(Status.Code.NotFound);
+        assertThat(results.get(2).status.getCode()).isEqualTo(Status.Code.Ok);
+
+        assertThat(results.get(2).requiredSize).isEqualTo("value3ForKey3".getBytes().length);
+
+        assertThat(TestUtil.bufferBytes(results.get(2).value))
+            .isEqualTo("value3ForKey3".getBytes());
+      }
+    }
+  }
+
+  @Test
+  public void putNThenMultiGetDirectTruncateCF() throws RocksDBException {
+    try (final Options opt = new Options().setCreateIfMissing(true);
+         final RocksDB db = RocksDB.open(opt, dbFolder.getRoot().getAbsolutePath())) {
+      final List<ColumnFamilyDescriptor> cfDescriptors = new ArrayList<>();
+      cfDescriptors.add(new ColumnFamilyDescriptor("cf0".getBytes()));
+
+      final List<ColumnFamilyHandle> cf = db.createColumnFamilies(cfDescriptors);
+
+      db.put(cf.get(0), "key1".getBytes(), "value1ForKey1".getBytes());
+      db.put(cf.get(0), "key2".getBytes(), "value2ForKey2WithLotsOfTrailingGarbage".getBytes());
+      db.put(cf.get(0), "key3".getBytes(), "value3ForKey3".getBytes());
+
+      final List<ByteBuffer> keys = new ArrayList<>();
+      keys.add(ByteBuffer.allocateDirect(12).put("key1".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key2".getBytes()));
+      keys.add(ByteBuffer.allocateDirect(12).put("key3".getBytes()));
+      // Java8 and lower flip() returns Buffer not ByteBuffer, so can't chain above /\/\
+      for (final ByteBuffer key : keys) {
+        key.flip();
+      }
+      final List<ByteBuffer> values = new ArrayList<>();
+      for (int i = 0; i < keys.size(); i++) {
+        values.add(ByteBuffer.allocateDirect(24));
+      }
+
+      {
+        final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
+        columnFamilyHandles.add(cf.get(0));
+        final List<ByteBufferGetStatus> results =
+            db.multiGetByteBuffers(columnFamilyHandles, keys, values);
+
+        assertThat(results.get(0).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(1).status.getCode()).isEqualTo(Status.Code.Ok);
+        assertThat(results.get(2).status.getCode()).isEqualTo(Status.Code.Ok);
+
+        assertThat(results.get(0).requiredSize).isEqualTo("value1ForKey1".getBytes().length);
+        assertThat(results.get(1).requiredSize)
+            .isEqualTo("value2ForKey2WithLotsOfTrailingGarbage".getBytes().length);
+        assertThat(results.get(2).requiredSize).isEqualTo("value3ForKey3".getBytes().length);
+
+        assertThat(TestUtil.bufferBytes(results.get(0).value))
+            .isEqualTo("value1ForKey1".getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(1).value))
+            .isEqualTo("valu e2Fo rKey 2Wit hLot sOfT".replace(" ", "").getBytes());
+        assertThat(TestUtil.bufferBytes(results.get(2).value))
+            .isEqualTo("value3ForKey3".getBytes());
+      }
+    }
+  }
+}