You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sa...@apache.org on 2022/06/10 15:47:09 UTC

[ignite-3] branch main updated: IGNITE-17036 KeyValueStorage get exact revision fixed (#875)

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

sanpwc pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new a1aa7fd4e IGNITE-17036 KeyValueStorage get exact revision fixed (#875)
a1aa7fd4e is described below

commit a1aa7fd4e2398c72827777ec5417d67915ff4da3
Author: Alexander Lapin <la...@gmail.com>
AuthorDate: Fri Jun 10 18:47:04 2022 +0300

    IGNITE-17036 KeyValueStorage get exact revision fixed (#875)
---
 .../metastorage/server/KeyValueStorage.java        |  6 +-
 .../server/persistence/RocksDbKeyValueStorage.java | 28 ++++---
 .../server/persistence/WatchCursor.java            |  2 +-
 .../server/AbstractKeyValueStorageTest.java        | 88 ++++++++++++++++++++++
 .../server/SimpleInMemoryKeyValueStorage.java      | 27 ++++---
 5 files changed, 118 insertions(+), 33 deletions(-)

diff --git a/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/KeyValueStorage.java b/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/KeyValueStorage.java
index dbc8c073e..56d6e33f4 100644
--- a/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/KeyValueStorage.java
+++ b/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/KeyValueStorage.java
@@ -57,13 +57,13 @@ public interface KeyValueStorage extends AutoCloseable {
     @NotNull Entry get(byte[] key);
 
     /**
-     * Returns an entry by the given key and revision.
+     * Returns an entry by the given key and bounded by the given revision.
      *
      * @param key The key.
-     * @param rev The revision.
+     * @param revUpperBound The upper bound of revision.
      * @return Value corresponding to the given key.
      */
-    @NotNull Entry get(byte[] key, long rev);
+    @NotNull Entry get(byte[] key, long revUpperBound);
 
     /**
      * Returns all entries corresponding to given keys.
diff --git a/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/persistence/RocksDbKeyValueStorage.java b/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/persistence/RocksDbKeyValueStorage.java
index 29f6638de..33ed663da 100644
--- a/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/persistence/RocksDbKeyValueStorage.java
+++ b/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/persistence/RocksDbKeyValueStorage.java
@@ -417,7 +417,7 @@ public class RocksDbKeyValueStorage implements KeyValueStorage {
         rwLock.readLock().lock();
 
         try {
-            return doGet(key, LATEST_REV, false);
+            return doGet(key, LATEST_REV);
         } finally {
             rwLock.readLock().unlock();
         }
@@ -426,11 +426,11 @@ public class RocksDbKeyValueStorage implements KeyValueStorage {
     /** {@inheritDoc} */
     @NotNull
     @Override
-    public Entry get(byte[] key, long rev) {
+    public Entry get(byte[] key, long revUpperBound) {
         rwLock.readLock().lock();
 
         try {
-            return doGet(key, rev, true);
+            return doGet(key, revUpperBound);
         } finally {
             rwLock.readLock().unlock();
         }
@@ -478,7 +478,7 @@ public class RocksDbKeyValueStorage implements KeyValueStorage {
         rwLock.writeLock().lock();
 
         try {
-            Entry e = doGet(key, LATEST_REV, false);
+            Entry e = doGet(key, LATEST_REV);
 
             if (e.empty() || e.tombstone()) {
                 return e;
@@ -538,7 +538,7 @@ public class RocksDbKeyValueStorage implements KeyValueStorage {
             List<byte[]> vals = new ArrayList<>(keys.size());
 
             for (byte[] key : keys) {
-                Entry e = doGet(key, LATEST_REV, false);
+                Entry e = doGet(key, LATEST_REV);
 
                 res.add(e);
 
@@ -759,7 +759,7 @@ public class RocksDbKeyValueStorage implements KeyValueStorage {
      * @throws RocksDBException If failed.
      */
     private boolean addToBatchForRemoval(WriteBatch batch, byte[] key, long curRev, long counter) throws RocksDBException {
-        Entry e = doGet(key, LATEST_REV, false);
+        Entry e = doGet(key, LATEST_REV);
 
         if (e.empty() || e.tombstone()) {
             return false;
@@ -817,7 +817,7 @@ public class RocksDbKeyValueStorage implements KeyValueStorage {
 
         try {
             for (byte[] key : keys) {
-                res.add(doGet(key, rev, false));
+                res.add(doGet(key, rev));
             }
         } finally {
             rwLock.readLock().unlock();
@@ -829,15 +829,13 @@ public class RocksDbKeyValueStorage implements KeyValueStorage {
     /**
      * Gets the value by key and revision.
      *
-     * @param key      Target key.
-     * @param rev      Target revision.
-     * @param exactRev {@code true} if searching for exact revision, {@code false} if rev is an upper bound (inclusive).
+     * @param key            Target key.
+     * @param revUpperBound  Target upper bound of revision.
      * @return Value.
      */
     @NotNull
-    Entry doGet(byte[] key, long rev, boolean exactRev) {
-        assert rev == LATEST_REV && !exactRev || rev > LATEST_REV :
-                "Invalid arguments: [rev=" + rev + ", exactRev=" + exactRev + ']';
+    Entry doGet(byte[] key, long revUpperBound) {
+        assert revUpperBound >= LATEST_REV : "Invalid arguments: [revUpperBound=" + revUpperBound + ']';
 
         long[] revs;
         try {
@@ -852,10 +850,10 @@ public class RocksDbKeyValueStorage implements KeyValueStorage {
 
         long lastRev;
 
-        if (rev == LATEST_REV) {
+        if (revUpperBound == LATEST_REV) {
             lastRev = lastRevision(revs);
         } else {
-            lastRev = exactRev ? rev : maxRevision(revs, rev);
+            lastRev = maxRevision(revs, revUpperBound);
         }
 
         // lastRev can be -1 if maxRevision return -1.
diff --git a/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/persistence/WatchCursor.java b/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/persistence/WatchCursor.java
index cbb675bb5..c3dabd4aa 100644
--- a/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/persistence/WatchCursor.java
+++ b/modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/persistence/WatchCursor.java
@@ -158,7 +158,7 @@ class WatchCursor implements Cursor<WatchEvent> {
                         newEntry = new Entry(key, val.bytes(), revision, val.updateCounter());
                     }
 
-                    Entry oldEntry = storage.doGet(key, revision - 1, false);
+                    Entry oldEntry = storage.doGet(key, revision - 1);
 
                     evts.add(new EntryEvent(oldEntry, newEntry));
                 }
diff --git a/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/AbstractKeyValueStorageTest.java b/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/AbstractKeyValueStorageTest.java
index 2af752ecd..77b983ce7 100644
--- a/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/AbstractKeyValueStorageTest.java
+++ b/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/AbstractKeyValueStorageTest.java
@@ -106,6 +106,94 @@ public abstract class AbstractKeyValueStorageTest {
         assertEquals(2, e.updateCounter());
     }
 
+    @Test
+    void getWithRevisionBound() {
+        byte[] key1 = key(1);
+        byte[] val1 = keyValue(1, 1);
+
+        final byte[] key2 = key(2);
+        final byte[] val2_1 = keyValue(2, 21);
+        final byte[] val2_2 = keyValue(2, 22);
+
+        final byte[] key3 = key(3);
+        final byte[] val3 = keyValue(3, 3);
+
+        final byte[] key4 = key(4);
+
+        assertEquals(0, storage.revision());
+        assertEquals(0, storage.updateCounter());
+
+        // Regular put.
+        storage.put(key1, val1);
+
+        // Rewrite.
+        storage.put(key2, val2_1);
+        storage.put(key2, val2_2);
+
+        // Remove.
+        storage.put(key3, val3);
+        storage.remove(key3);
+
+        assertEquals(5, storage.revision());
+        assertEquals(5, storage.updateCounter());
+
+        // Bounded by revision 2.
+        Entry key1EntryBounded2 = storage.get(key1, 2);
+
+        assertNotNull(key1EntryBounded2);
+        assertEquals(1, key1EntryBounded2.revision());
+        assertEquals(1, key1EntryBounded2.updateCounter());
+        assertArrayEquals(val1, key1EntryBounded2.value());
+        assertFalse(key1EntryBounded2.tombstone());
+        assertFalse(key1EntryBounded2.empty());
+
+        Entry key2EntryBounded2 = storage.get(key2, 2);
+
+        assertNotNull(key2EntryBounded2);
+        assertEquals(2, key2EntryBounded2.revision());
+        assertEquals(2, key2EntryBounded2.updateCounter());
+        assertArrayEquals(val2_1, key2EntryBounded2.value());
+        assertFalse(key2EntryBounded2.tombstone());
+        assertFalse(key2EntryBounded2.empty());
+
+        Entry key3EntryBounded2 = storage.get(key3, 2);
+
+        assertNotNull(key3EntryBounded2);
+        assertEquals(0, key3EntryBounded2.revision());
+        assertEquals(0, key3EntryBounded2.updateCounter());
+        assertNull(key3EntryBounded2.value());
+        assertFalse(key3EntryBounded2.tombstone());
+        assertTrue(key3EntryBounded2.empty());
+
+        // Bounded by revision 5.
+        Entry key1EntryBounded5 = storage.get(key1, 5);
+
+        assertNotNull(key1EntryBounded5);
+        assertEquals(1, key1EntryBounded5.revision());
+        assertEquals(1, key1EntryBounded5.updateCounter());
+        assertArrayEquals(val1, key1EntryBounded5.value());
+        assertFalse(key1EntryBounded5.tombstone());
+        assertFalse(key1EntryBounded5.empty());
+
+        Entry key2EntryBounded5 = storage.get(key2, 5);
+
+        assertNotNull(key2EntryBounded5);
+        assertEquals(3, key2EntryBounded5.revision());
+        assertEquals(3, key2EntryBounded5.updateCounter());
+        assertArrayEquals(val2_2, key2EntryBounded5.value());
+        assertFalse(key2EntryBounded5.tombstone());
+        assertFalse(key2EntryBounded5.empty());
+
+        Entry key3EntryBounded5 = storage.get(key3, 5);
+
+        assertNotNull(key3EntryBounded5);
+        assertEquals(5, key3EntryBounded5.revision());
+        assertEquals(5, key3EntryBounded5.updateCounter());
+        assertTrue(key3EntryBounded5.tombstone());
+        assertNull(key3EntryBounded5.value());
+        assertFalse(key3EntryBounded5.empty());
+    }
+
     @Test
     void getAll() {
         byte[] key1 = key(1);
diff --git a/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/SimpleInMemoryKeyValueStorage.java b/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/SimpleInMemoryKeyValueStorage.java
index fa550a775..ffea7e0e5 100644
--- a/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/SimpleInMemoryKeyValueStorage.java
+++ b/modules/metastorage-server/src/test/java/org/apache/ignite/internal/metastorage/server/SimpleInMemoryKeyValueStorage.java
@@ -146,16 +146,16 @@ public class SimpleInMemoryKeyValueStorage implements KeyValueStorage {
     @Override
     public Entry get(byte[] key) {
         synchronized (mux) {
-            return doGet(key, LATEST_REV, false);
+            return doGet(key, LATEST_REV);
         }
     }
 
     /** {@inheritDoc} */
     @NotNull
     @Override
-    public Entry get(byte[] key, long rev) {
+    public Entry get(byte[] key, long revUpperBound) {
         synchronized (mux) {
-            return doGet(key, rev, true);
+            return doGet(key, revUpperBound);
         }
     }
 
@@ -190,7 +190,7 @@ public class SimpleInMemoryKeyValueStorage implements KeyValueStorage {
     @Override
     public Entry getAndRemove(byte[] key) {
         synchronized (mux) {
-            Entry e = doGet(key, LATEST_REV, false);
+            Entry e = doGet(key, LATEST_REV);
 
             if (e.empty() || e.tombstone()) {
                 return e;
@@ -211,7 +211,7 @@ public class SimpleInMemoryKeyValueStorage implements KeyValueStorage {
             List<byte[]> vals = new ArrayList<>(keys.size());
 
             for (byte[] key : keys) {
-                Entry e = doGet(key, LATEST_REV, false);
+                Entry e = doGet(key, LATEST_REV);
 
                 if (e.empty() || e.tombstone()) {
                     continue;
@@ -240,7 +240,7 @@ public class SimpleInMemoryKeyValueStorage implements KeyValueStorage {
             List<byte[]> vals = new ArrayList<>(keys.size());
 
             for (byte[] key : keys) {
-                Entry e = doGet(key, LATEST_REV, false);
+                Entry e = doGet(key, LATEST_REV);
 
                 res.add(e);
 
@@ -434,7 +434,7 @@ public class SimpleInMemoryKeyValueStorage implements KeyValueStorage {
     }
 
     private boolean doRemove(byte[] key, long curRev) {
-        Entry e = doGet(key, LATEST_REV, false);
+        Entry e = doGet(key, LATEST_REV);
 
         if (e.empty() || e.tombstone()) {
             return false;
@@ -479,7 +479,7 @@ public class SimpleInMemoryKeyValueStorage implements KeyValueStorage {
 
         synchronized (mux) {
             for (byte[] key : keys) {
-                res.add(doGet(key, rev, false));
+                res.add(doGet(key, rev));
             }
         }
 
@@ -487,9 +487,8 @@ public class SimpleInMemoryKeyValueStorage implements KeyValueStorage {
     }
 
     @NotNull
-    private Entry doGet(byte[] key, long rev, boolean exactRev) {
-        assert rev == LATEST_REV && !exactRev || rev > LATEST_REV :
-                "Invalid arguments: [rev=" + rev + ", exactRev=" + exactRev + ']';
+    private Entry doGet(byte[] key, long revUpperBound) {
+        assert revUpperBound >= LATEST_REV : "Invalid arguments: [revUpperBound=" + revUpperBound + ']';
 
         List<Long> revs = keysIdx.get(key);
 
@@ -499,10 +498,10 @@ public class SimpleInMemoryKeyValueStorage implements KeyValueStorage {
 
         long lastRev;
 
-        if (rev == LATEST_REV) {
+        if (revUpperBound == LATEST_REV) {
             lastRev = lastRevision(revs);
         } else {
-            lastRev = exactRev ? rev : maxRevision(revs, rev);
+            lastRev = maxRevision(revs, revUpperBound);
         }
 
         // lastRev can be -1 if maxRevision return -1.
@@ -853,7 +852,7 @@ public class SimpleInMemoryKeyValueStorage implements KeyValueStorage {
                                             newEntry = new Entry(key, val.bytes(), nextRetRev, val.updateCounter());
                                         }
 
-                                        Entry oldEntry = doGet(key, nextRetRev - 1, false);
+                                        Entry oldEntry = doGet(key, nextRetRev - 1);
 
                                         evts.add(new EntryEvent(oldEntry, newEntry));
                                     }