From 0b5da0d6205cd8096eaeae5f62cf85900f170730 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Fri, 19 Dec 2014 14:36:57 +0000
Subject: [PATCH] OPENDJ-1602 (CR-5566) New pluggable storage based backend

---
 opendj3-server-dev/src/server/org/opends/server/backends/persistit/PersistItStorage.java |  104 ++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 72 insertions(+), 32 deletions(-)

diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/persistit/PersistItStorage.java b/opendj3-server-dev/src/server/org/opends/server/backends/persistit/PersistItStorage.java
index e11010b..d99a600 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/persistit/PersistItStorage.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/persistit/PersistItStorage.java
@@ -58,6 +58,36 @@
 
 @SuppressWarnings("javadoc")
 public final class PersistItStorage implements Storage {
+  /*
+   * TODO: it would be nice to use the low-level key/value APIs. They seem quite
+   * inefficient at the moment for simple byte arrays.
+   */
+  private Key bytesToKey(Key key, ByteSequence bytes)
+  {
+    final byte[] tmp = bytes.toByteArray();
+    return key.clear().appendByteArray(tmp, 0, tmp.length);
+  }
+
+  private Value bytesToValue(Value value, ByteSequence bytes)
+  {
+    value.clear().putByteArray(bytes.toByteArray());
+    return value;
+  }
+
+  private ByteString valueToBytes(Value value)
+  {
+    if (value.isDefined())
+    {
+      return ByteString.wrap(value.getByteArray());
+    }
+    return null;
+  }
+
+  private ByteString keyToBytes(Key key)
+  {
+    return ByteString.wrap(key.reset().decodeByteArray());
+  }
+
     private final class ImporterImpl implements Importer {
         private final Map<TreeName, Tree> trees = new HashMap<TreeName, Tree>();
         private final TreeBuilder importer = new TreeBuilder(db);
@@ -76,15 +106,13 @@
 
         @Override
         public void put(TreeName treeName, ByteSequence key, ByteSequence value) {
-            try {
-                final Tree tree = trees.get(treeName);
-                byte[] keyBytes = key.toByteArray();
-                importKey.clear().appendByteArray(keyBytes, 0, keyBytes.length);
-                importValue.clear().putByteArray(value.toByteArray());
-                importer.store(tree, importKey, importValue);
-            } catch (Exception e) {
-                throw new StorageRuntimeException(e);
-            }
+          try {
+            final Tree tree = trees.get(treeName);
+            importer.store(tree, bytesToKey(importKey, key),
+                bytesToValue(importValue, value));
+          } catch (Exception e) {
+            throw new StorageRuntimeException(e);
+          }
         }
 
         @Override
@@ -121,13 +149,9 @@
         public ByteString read(TreeName treeName, ByteSequence key) {
             try {
                 final Exchange ex = getExchange(treeName);
-                ex.getKey().clear().append(key.toByteArray());
+                bytesToKey(ex.getKey(), key);
                 ex.fetch();
-                final Value value = ex.getValue();
-                if (value.isDefined()) {
-                    return ByteString.wrap(value.getByteArray());
-                }
-                return null;
+                return valueToBytes(ex.getValue());
             } catch (PersistitException e) {
                 throw new StorageRuntimeException(e);
             }
@@ -142,8 +166,8 @@
         public void create(TreeName treeName, ByteSequence key, ByteSequence value) {
             try {
                 final Exchange ex = getExchange(treeName);
-                ex.getKey().clear().append(key.toByteArray());
-                ex.getValue().clear().putByteArray(value.toByteArray());
+                bytesToKey(ex.getKey(), key);
+                bytesToValue(ex.getValue(), value);
                 ex.store();
             } catch (Exception e) {
                 throw new StorageRuntimeException(e);
@@ -154,14 +178,15 @@
         public boolean putIfAbsent(TreeName treeName, ByteSequence key, ByteSequence value) {
             try {
                 final Exchange ex = getExchange(treeName);
-                ex.getKey().clear().append(key.toByteArray());
+                bytesToKey(ex.getKey(), key);
                 ex.fetch();
                 // FIXME poor man's CAS: this will not work under high volume,
                 // but PersistIt does not provide APIs for this use case.
-                if (ex.isValueDefined()) {
+                final Value exValue = ex.getValue();
+                if (exValue.isDefined()) {
                     return false;
                 }
-                ex.getValue().clear().putByteArray(value.toByteArray());
+                bytesToValue(exValue, value);
                 ex.store();
                 return true;
             } catch (Exception e) {
@@ -175,11 +200,9 @@
           try
           {
             final Exchange ex = getExchange(treeName);
-            ex.getKey().clear().append(key.toByteArray());
+            bytesToKey(ex.getKey(), key);
             ex.fetch();
-            final Value value = ex.getValue();
-            final ByteSequence oldValue = value.isDefined() ? ByteString.wrap(value
-                .getByteArray()) : null;
+            final ByteSequence oldValue = valueToBytes(ex.getValue());
             final ByteSequence newValue = f.computeNewValue(oldValue);
             ex.getValue().clear().putByteArray(newValue.toByteArray());
             ex.store();
@@ -194,7 +217,7 @@
         public boolean remove(TreeName treeName, ByteSequence key) {
             try {
                 final Exchange ex = getExchange(treeName);
-                ex.getKey().clear().append(key.toByteArray());
+                bytesToKey(ex.getKey(), key);
                 return ex.remove();
             } catch (PersistitException e) {
                 throw new StorageRuntimeException(e);
@@ -205,7 +228,7 @@
         public void delete(TreeName treeName, ByteSequence key) {
             try {
                 final Exchange ex = getExchange(treeName);
-                ex.getKey().clear().append(key.toByteArray());
+                bytesToKey(ex.getKey(), key);
                 ex.remove();
             } catch (PersistitException e) {
                 throw new StorageRuntimeException(e);
@@ -262,17 +285,24 @@
     }
 
     private final class CursorImpl implements Cursor {
-
         private final Exchange ex;
         private boolean useCurrentKeyForNext = false;
+        private ByteString currentKey;
+        private ByteString currentValue;
 
         public CursorImpl(Exchange exchange) {
             this.ex = exchange;
         }
 
+        private void clearCurrentKeyAndValue() {
+          currentKey = null;
+          currentValue = null;
+        }
+
         @Override
         public boolean positionToKey(ByteSequence key) {
-            ex.getKey().clear().append(key.toByteArray());
+            clearCurrentKeyAndValue();
+            bytesToKey(ex.getKey(), key);
             try {
                 ex.fetch();
                 useCurrentKeyForNext = ex.getValue().isDefined();
@@ -285,7 +315,8 @@
 
         @Override
         public boolean positionToKeyOrNext(ByteSequence key) {
-            ex.getKey().clear().append(key.toByteArray());
+            clearCurrentKeyAndValue();
+            bytesToKey(ex.getKey(), key);
             try {
                 ex.fetch();
                 if (ex.getValue().isDefined()) {
@@ -304,6 +335,7 @@
         @Override
         public boolean positionToLastKey() {
             try {
+                clearCurrentKeyAndValue();
                 ex.getKey().to(Key.AFTER);
                 useCurrentKeyForNext = ex.previous() && ex.getValue().isDefined();
                 return useCurrentKeyForNext;
@@ -315,6 +347,7 @@
 
         @Override
         public boolean next() {
+            clearCurrentKeyAndValue();
             if (useCurrentKeyForNext) {
                 useCurrentKeyForNext = false;
                 return true;
@@ -328,6 +361,7 @@
 
         @Override
         public boolean previous() {
+            clearCurrentKeyAndValue();
             try {
                 return ex.previous();
             } catch (PersistitException e) {
@@ -337,12 +371,18 @@
 
         @Override
         public ByteString getKey() {
-            return ByteString.wrap(ex.getKey().decodeByteArray());
+          if (currentKey == null) {
+            currentKey = keyToBytes(ex.getKey());
+          }
+          return currentKey;
         }
 
         @Override
         public ByteString getValue() {
-            return ByteString.wrap(ex.getValue().getByteArray());
+            if (currentValue == null) {
+              currentValue = valueToBytes(ex.getValue());
+            }
+            return currentValue;
         }
 
         @Override
@@ -373,7 +413,7 @@
         properties.setProperty("journalpath", "${datapath}/dj_journal");
 
         properties.setProperty("volume.1",
-            "${datapath}/dj" 
+            "${datapath}/dj"
                 + ",create,pageSize:16K"
                 + ",initialSize:50M"
                 + ",extensionSize:1M"

--
Gitblit v1.10.0