From d30ff782c1c046a28939278b2e50d012d945f362 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Fri, 25 Sep 2026 09:44:49 +0000
Subject: [PATCH] [#1096] Copy a value into Persistit once rather than twice, and write the large values of PDBStorageTest through a small buffer pool (#1097)

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBStorage.java |   18 ++++++++++++++++--
 1 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBStorage.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBStorage.java
index d0ea8de..cdcccf8 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBStorage.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBStorage.java
@@ -139,6 +139,8 @@
   private static final String JOURNAL_NAME = VOLUME_NAME + "_journal";
   /** The buffer / page size used by the PersistIt storage. */
   private static final int BUFFER_SIZE = 16 * 1024;
+  /** Encoded by {@link #bytesToValue(Value, ByteSequence)} for the header Persistit puts before a byte array. */
+  private static final byte[] EMPTY_BYTES = new byte[0];
 
   /** PersistIt implementation of the {@link Cursor} interface. */
   private final class CursorImpl implements Cursor<ByteString, ByteString>
@@ -578,7 +580,7 @@
           }
           else
           {
-            ex.getValue().clear().putByteArray(newValue.toByteArray());
+            bytesToValue(ex.getValue(), newValue);
             ex.store();
           }
           return true;
@@ -1542,9 +1544,21 @@
     return key.clear().appendByteArray(tmp, 0, tmp.length);
   }
 
+  /**
+   * Encodes the bytes as a byte array value, copying them once, straight into the encoded bytes of the value.
+   * {@code putByteArray(bytes.toByteArray())} would copy them twice, and for a value of 63 MB the extra copy is
+   * one more humongous array live next to the source and the value buffer. Persistit encodes a byte array as a
+   * header followed by the bytes as they are, so the header is taken from Persistit itself - by encoding an empty
+   * array - and the bytes are appended behind it.
+   */
   private static Value bytesToValue(final Value value, final ByteSequence bytes)
   {
-    value.clear().putByteArray(bytes.toByteArray());
+    value.clear().putByteArray(EMPTY_BYTES);
+    final int headerSize = value.getEncodedSize();
+    value.ensureFit(bytes.length());
+    // ensureFit() may have replaced the encoded bytes, so they are read only after it
+    bytes.copyTo(value.getEncodedBytes(), headerSize);
+    value.setEncodedSize(headerSize + bytes.length());
     return value;
   }
 

--
Gitblit v1.10.0