aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store/src/main/java/tools
diff options
context:
space:
mode:
authorLibravatar nagilooh <ficsorattila96@gmail.com>2023-08-02 13:08:10 +0200
committerLibravatar nagilooh <ficsorattila96@gmail.com>2023-08-02 13:08:10 +0200
commit2c303ec940651895ad76a92c0080c707058167ef (patch)
tree7ba94f9d94593ff3fa7d6a814dc5896d823719e7 /subprojects/store/src/main/java/tools
parentUpdate CRA test case (diff)
parentMerge pull request #31 from OszkarSemerath/datastructure (diff)
downloadrefinery-2c303ec940651895ad76a92c0080c707058167ef.tar.gz
refinery-2c303ec940651895ad76a92c0080c707058167ef.tar.zst
refinery-2c303ec940651895ad76a92c0080c707058167ef.zip
Merge remote-tracking branch 'origin/main' into design-space-exploration
Diffstat (limited to 'subprojects/store/src/main/java/tools')
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/ContinuousHashProvider.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java)14
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/IteratorAsCursor.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/IteratorAsCursor.java)12
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/Version.java26
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java18
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java2
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java8
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreFactoryBuilder.java3
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java129
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java23
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/StateBasedVersionedMapStoreFactory.java38
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapStoreFactoryBuilderImpl.java39
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/DeltaBasedVersionedMapStoreFactory.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/DeltaBasedVersionedMapStoreFactory.java)5
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/DeltaDiffCursor.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/DeltaDiffCursor.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/MapDelta.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDelta.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/MapTransaction.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/MapTransaction.java)14
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaArrayStore.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaArrayStore.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaMapStore.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaMapStore.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaStore.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaStore.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/VersionedMapDeltaImpl.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapDeltaImpl.java)39
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/VersionedMapStoreDeltaImpl.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreDeltaImpl.java)51
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/ImmutableNode.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java)19
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/InOrderMapCursor.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/InOrderMapCursor.java)6
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MapCursor.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MapDiffCursor.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MutableNode.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java)18
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/Node.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java)18
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/OldValueBox.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java)6
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/StateBasedVersionedMapStoreFactory.java43
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStateImpl.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java)34
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateConfiguration.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java)25
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateImpl.java119
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java3
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/Model.java10
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java8
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java34
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java66
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java18
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java37
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelVersion.java39
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java14
42 files changed, 510 insertions, 464 deletions
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java b/subprojects/store/src/main/java/tools/refinery/store/map/ContinuousHashProvider.java
index 8e451230..abc044d0 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/ContinuousHashProvider.java
@@ -5,17 +5,17 @@
5 */ 5 */
6package tools.refinery.store.map; 6package tools.refinery.store.map;
7 7
8import tools.refinery.store.map.internal.Node; 8import tools.refinery.store.map.internal.state.Node;
9 9
10/** 10/**
11 * A class representing an equivalence relation for a type {@code K} with a 11 * A class representing an equivalence relation for a type {@code K} with a
12 * continuous hash function. 12 * continuous hash function.
13 * 13 *
14 * @author Oszkar Semerath 14 * @author Oszkar Semerath
15 * 15 *
16 * @param <K> Target java type. 16 * @param <K> Target java type.
17 */ 17 */
18public interface ContinousHashProvider<K> { 18public interface ContinuousHashProvider<K> {
19 public static final int EFFECTIVE_BITS = Node.EFFECTIVE_BITS; 19 public static final int EFFECTIVE_BITS = Node.EFFECTIVE_BITS;
20 public static final int EFFECTIVE_BIT_MASK = (1 << (EFFECTIVE_BITS)) - 1; 20 public static final int EFFECTIVE_BIT_MASK = (1 << (EFFECTIVE_BITS)) - 1;
21 21
@@ -38,9 +38,9 @@ public interface ContinousHashProvider<K> {
38 * {@link #EFFECTIVE_BITS} 38 * {@link #EFFECTIVE_BITS}
39 * </ul> 39 * </ul>
40 * Check {@link #equals} for further details. 40 * Check {@link #equals} for further details.
41 * 41 *
42 * @param key The target data object. 42 * @param key The target data object.
43 * @param index The depth of the the hash code. Needs to be non-negative. 43 * @param index The depth of the hash code. Needs to be non-negative.
44 * @return A hash code. 44 * @return A hash code.
45 */ 45 */
46 public int getHash(K key, int index); 46 public int getHash(K key, int index);
@@ -53,7 +53,7 @@ public interface ContinousHashProvider<K> {
53 if (key1.equals(key2)) { 53 if (key1.equals(key2)) {
54 return 0; 54 return 0;
55 } else { 55 } else {
56 for (int i = 0; i < ContinousHashProvider.MAX_PRACTICAL_DEPTH; i++) { 56 for (int i = 0; i < ContinuousHashProvider.MAX_PRACTICAL_DEPTH; i++) {
57 int hash1 = getEffectiveHash(key1, i); 57 int hash1 = getEffectiveHash(key1, i);
58 int hash2 = getEffectiveHash(key2, i); 58 int hash2 = getEffectiveHash(key2, i);
59 for(int j = 0; j<Integer.SIZE/Node.BRANCHING_FACTOR_BITS; j++) { 59 for(int j = 0; j<Integer.SIZE/Node.BRANCHING_FACTOR_BITS; j++) {
@@ -68,7 +68,7 @@ public interface ContinousHashProvider<K> {
68 } 68 }
69 throw new IllegalArgumentException("Two different keys (" + key1 + " and " + key2 69 throw new IllegalArgumentException("Two different keys (" + key1 + " and " + key2
70 + ") have the same hashcode over the practical depth limitation (" 70 + ") have the same hashcode over the practical depth limitation ("
71 + ContinousHashProvider.MAX_PRACTICAL_DEPTH + ")!"); 71 + ContinuousHashProvider.MAX_PRACTICAL_DEPTH + ")!");
72 } 72 }
73 } 73 }
74} 74}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/IteratorAsCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/IteratorAsCursor.java
index d1ab8bb1..29b03edf 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/IteratorAsCursor.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/IteratorAsCursor.java
@@ -1,16 +1,14 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map;
7 7
8import java.util.*; 8import java.util.Iterator;
9import java.util.Map;
9import java.util.Map.Entry; 10import java.util.Map.Entry;
10 11import java.util.Set;
11import tools.refinery.store.map.AnyVersionedMap;
12import tools.refinery.store.map.Cursor;
13import tools.refinery.store.map.VersionedMap;
14 12
15public class IteratorAsCursor<K, V> implements Cursor<K, V> { 13public class IteratorAsCursor<K, V> implements Cursor<K, V> {
16 final Iterator<Entry<K, V>> iterator; 14 final Iterator<Entry<K, V>> iterator;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/Version.java b/subprojects/store/src/main/java/tools/refinery/store/map/Version.java
new file mode 100644
index 00000000..fa2734e4
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/Version.java
@@ -0,0 +1,26 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.map;
7
8/**
9 * Interface denoting versions of {@link Versioned}.
10 */
11public interface Version {
12 /**
13 * Hashcode should be updated in accordance with equals.
14 * @return a hashcode of the object.
15 */
16 int hashCode();
17
18 /**
19 * Equivalence of two {@link Version}. This equivalence must satisfy the following constraint (in addition to the
20 * constraints of {@link Object#equals(Object)}: if {@code v1} and {@code v2} are {@link Version}s, and {@code v1
21 * .equals(v2)}, then {@code versioned.restore(v1)} must be {@code equals} to {@code versioned.restore(v2)}.
22 * @param o the other object.
23 * @return weather the two versions are equals.
24 */
25 boolean equals(Object o);
26}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java b/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java
index 55720db3..da12b0a9 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java
@@ -5,8 +5,20 @@
5 */ 5 */
6package tools.refinery.store.map; 6package tools.refinery.store.map;
7 7
8/**
9 * Object that can save and restore its state.
10 */
8public interface Versioned { 11public interface Versioned {
9 public long commit(); 12 /**
10 //maybe revert()? 13 * Saves the state of the object.
11 public void restore(long state); 14 * @return an object that marks the version of the object at the time the function was called.
15 */
16 Version commit();
17
18 /**
19 * Restores the state of the object.
20 * @param state a {@link Version} object that marks the version. The state must be a {@link Version} object
21 * returned by a previous {@link #commit()}!
22 */
23 void restore(Version state);
12} 24}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java
index c8226c3e..28194b58 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java
@@ -16,5 +16,5 @@ public non-sealed interface VersionedMap<K, V> extends AnyVersionedMap {
16 16
17 void putAll(Cursor<K, V> cursor); 17 void putAll(Cursor<K, V> cursor);
18 18
19 DiffCursor<K, V> getDiffCursor(long state); 19 DiffCursor<K, V> getDiffCursor(Version state);
20} 20}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java
index b24c404c..55cf08a5 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java
@@ -7,17 +7,13 @@ package tools.refinery.store.map;
7 7
8import tools.refinery.store.map.internal.VersionedMapStoreFactoryBuilderImpl; 8import tools.refinery.store.map.internal.VersionedMapStoreFactoryBuilderImpl;
9 9
10import java.util.Set;
11
12public interface VersionedMapStore<K, V> { 10public interface VersionedMapStore<K, V> {
13 11
14 VersionedMap<K, V> createMap(); 12 VersionedMap<K, V> createMap();
15 13
16 VersionedMap<K, V> createMap(long state); 14 VersionedMap<K, V> createMap(Version state);
17
18 Set<Long> getStates();
19 15
20 DiffCursor<K,V> getDiffCursor(long fromState, long toState); 16 DiffCursor<K,V> getDiffCursor(Version fromState, Version toState);
21 17
22 static <K,V> VersionedMapStoreFactoryBuilder<K,V> builder() { 18 static <K,V> VersionedMapStoreFactoryBuilder<K,V> builder() {
23 return new VersionedMapStoreFactoryBuilderImpl<>(); 19 return new VersionedMapStoreFactoryBuilderImpl<>();
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreFactoryBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreFactoryBuilder.java
index 6329a2f6..0ac196f2 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreFactoryBuilder.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreFactoryBuilder.java
@@ -20,9 +20,10 @@ public interface VersionedMapStoreFactoryBuilder<K,V> {
20 20
21 VersionedMapStoreFactoryBuilder<K,V> defaultValue(V defaultValue); 21 VersionedMapStoreFactoryBuilder<K,V> defaultValue(V defaultValue);
22 VersionedMapStoreFactoryBuilder<K,V> strategy(StoreStrategy strategy); 22 VersionedMapStoreFactoryBuilder<K,V> strategy(StoreStrategy strategy);
23 VersionedMapStoreFactoryBuilder<K,V> versionFreeing(boolean enabled);
23 VersionedMapStoreFactoryBuilder<K,V> stateBasedImmutableWhenCommitting(boolean transformToImmutable); 24 VersionedMapStoreFactoryBuilder<K,V> stateBasedImmutableWhenCommitting(boolean transformToImmutable);
24 VersionedMapStoreFactoryBuilder<K,V> stateBasedSharingStrategy(SharingStrategy sharingStrategy); 25 VersionedMapStoreFactoryBuilder<K,V> stateBasedSharingStrategy(SharingStrategy sharingStrategy);
25 VersionedMapStoreFactoryBuilder<K,V> stateBasedHashProvider(ContinousHashProvider<K> hashProvider); 26 VersionedMapStoreFactoryBuilder<K,V> stateBasedHashProvider(ContinuousHashProvider<K> hashProvider);
26 VersionedMapStoreFactoryBuilder<K,V> deltaTransactionStrategy(DeltaTransactionStrategy deltaStrategy); 27 VersionedMapStoreFactoryBuilder<K,V> deltaTransactionStrategy(DeltaTransactionStrategy deltaStrategy);
27 28
28 VersionedMapStoreFactory<K,V> build(); 29 VersionedMapStoreFactory<K,V> build();
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java
deleted file mode 100644
index a934d59e..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java
+++ /dev/null
@@ -1,129 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.map;
7
8import tools.refinery.store.map.internal.*;
9
10import java.util.*;
11
12public class VersionedMapStoreImpl<K, V> implements VersionedMapStore<K, V> {
13 // Configuration
14 private final boolean immutableWhenCommitting;
15
16 // Static data
17 protected final ContinousHashProvider<K> hashProvider;
18 protected final V defaultValue;
19
20 // Dynamic data
21 protected final Map<Long, ImmutableNode<K, V>> states = new HashMap<>();
22 protected final Map<Node<K, V>, ImmutableNode<K, V>> nodeCache;
23 protected long nextID = 0;
24
25 public VersionedMapStoreImpl(ContinousHashProvider<K> hashProvider, V defaultValue,
26 VersionedMapStoreConfiguration config) {
27 this.immutableWhenCommitting = config.isImmutableWhenCommitting();
28 this.hashProvider = hashProvider;
29 this.defaultValue = defaultValue;
30 if (config.isSharedNodeCacheInStore()) {
31 nodeCache = new HashMap<>();
32 } else {
33 nodeCache = null;
34 }
35 }
36
37 private VersionedMapStoreImpl(ContinousHashProvider<K> hashProvider, V defaultValue,
38 Map<Node<K, V>, ImmutableNode<K, V>> nodeCache, VersionedMapStoreConfiguration config) {
39 this.immutableWhenCommitting = config.isImmutableWhenCommitting();
40 this.hashProvider = hashProvider;
41 this.defaultValue = defaultValue;
42 this.nodeCache = nodeCache;
43 }
44
45 public VersionedMapStoreImpl(ContinousHashProvider<K> hashProvider, V defaultValue) {
46 this(hashProvider, defaultValue, new VersionedMapStoreConfiguration());
47 }
48
49 public static <K, V> List<VersionedMapStore<K, V>> createSharedVersionedMapStores(int amount,
50 ContinousHashProvider<K> hashProvider, V defaultValue,
51 VersionedMapStoreConfiguration config) {
52 List<VersionedMapStore<K, V>> result = new ArrayList<>(amount);
53 if (config.isSharedNodeCacheInStoreGroups()) {
54 Map<Node<K, V>, ImmutableNode<K, V>> nodeCache;
55 if (config.isSharedNodeCacheInStore()) {
56 nodeCache = new HashMap<>();
57 } else {
58 nodeCache = null;
59 }
60 for (int i = 0; i < amount; i++) {
61 result.add(new VersionedMapStoreImpl<>(hashProvider, defaultValue, nodeCache, config));
62 }
63 } else {
64 for (int i = 0; i < amount; i++) {
65 result.add(new VersionedMapStoreImpl<>(hashProvider, defaultValue, config));
66 }
67 }
68 return result;
69 }
70
71 public static <K, V> List<VersionedMapStore<K, V>> createSharedVersionedMapStores(int amount,
72 ContinousHashProvider<K> hashProvider, V defaultValue) {
73 return createSharedVersionedMapStores(amount, hashProvider, defaultValue, new VersionedMapStoreConfiguration());
74 }
75
76 @Override
77 public synchronized Set<Long> getStates() {
78 return new HashSet<>(states.keySet());
79 }
80
81 @Override
82 public VersionedMap<K, V> createMap() {
83 return new VersionedMapImpl<>(this, hashProvider, defaultValue);
84 }
85
86 @Override
87 public VersionedMap<K, V> createMap(long state) {
88 ImmutableNode<K, V> data = revert(state);
89 return new VersionedMapImpl<>(this, hashProvider, defaultValue, data);
90 }
91
92 public synchronized ImmutableNode<K, V> revert(long state) {
93 if (states.containsKey(state)) {
94 return states.get(state);
95 } else {
96 ArrayList<Long> existingKeys = new ArrayList<>(states.keySet());
97 Collections.sort(existingKeys);
98 throw new IllegalArgumentException("Store does not contain state " + state + "! Available states: "
99 + Arrays.toString(existingKeys.toArray()));
100 }
101 }
102
103 public synchronized long commit(Node<K, V> data, VersionedMapImpl<K, V> mapToUpdateRoot) {
104 ImmutableNode<K, V> immutable;
105 if (data != null) {
106 immutable = data.toImmutable(this.nodeCache);
107 } else {
108 immutable = null;
109 }
110
111 if (nextID == Long.MAX_VALUE)
112 throw new IllegalStateException("Map store run out of Id-s");
113 long id = nextID++;
114 this.states.put(id, immutable);
115 if (this.immutableWhenCommitting) {
116 mapToUpdateRoot.setRoot(immutable);
117 }
118 return id;
119 }
120
121 @Override
122 public DiffCursor<K, V> getDiffCursor(long fromState, long toState) {
123 VersionedMapImpl<K, V> map1 = (VersionedMapImpl<K, V>) createMap(fromState);
124 VersionedMapImpl<K, V> map2 = (VersionedMapImpl<K, V>) createMap(toState);
125 InOrderMapCursor<K, V> cursor1 = new InOrderMapCursor<>(map1);
126 InOrderMapCursor<K, V> cursor2 = new InOrderMapCursor<>(map2);
127 return new MapDiffCursor<>(this.defaultValue, cursor1, cursor2);
128 }
129}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java
deleted file mode 100644
index a357fbce..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java
+++ /dev/null
@@ -1,23 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.map.internal;
7
8enum HashClash {
9 /**
10 * Not stuck.
11 */
12 NONE,
13
14 /**
15 * Clashed, next we should return the key of cursor 1.
16 */
17 STUCK_CURSOR_1,
18
19 /**
20 * Clashed, next we should return the key of cursor 2.
21 */
22 STUCK_CURSOR_2
23}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/StateBasedVersionedMapStoreFactory.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/StateBasedVersionedMapStoreFactory.java
deleted file mode 100644
index 1c3ab27b..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/StateBasedVersionedMapStoreFactory.java
+++ /dev/null
@@ -1,38 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.map.internal;
7
8import tools.refinery.store.map.*;
9
10import java.util.List;
11
12public class StateBasedVersionedMapStoreFactory<K, V> implements VersionedMapStoreFactory<K, V> {
13 private final V defaultValue;
14 private final ContinousHashProvider<K> continousHashProvider;
15 private final VersionedMapStoreConfiguration config;
16
17 public StateBasedVersionedMapStoreFactory(V defaultValue, Boolean transformToImmutable, VersionedMapStoreFactoryBuilder.SharingStrategy sharingStrategy, ContinousHashProvider<K> continousHashProvider) {
18 this.defaultValue = defaultValue;
19 this.continousHashProvider = continousHashProvider;
20
21 this.config = new VersionedMapStoreConfiguration(
22 transformToImmutable,
23 sharingStrategy == VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE || sharingStrategy == VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE_IN_GROUP,
24 sharingStrategy == VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE_IN_GROUP);
25 }
26
27 @Override
28 public VersionedMapStore<K, V> createOne() {
29 return new VersionedMapStoreImpl<>(continousHashProvider, defaultValue, config);
30
31 }
32
33 @Override
34 public List<VersionedMapStore<K, V>> createGroup(int amount) {
35 return VersionedMapStoreImpl.createSharedVersionedMapStores(amount, continousHashProvider, defaultValue,
36 config);
37 }
38}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapStoreFactoryBuilderImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapStoreFactoryBuilderImpl.java
index cf117d95..9f419ce1 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapStoreFactoryBuilderImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapStoreFactoryBuilderImpl.java
@@ -5,9 +5,11 @@
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal;
7 7
8import tools.refinery.store.map.ContinousHashProvider; 8import tools.refinery.store.map.ContinuousHashProvider;
9import tools.refinery.store.map.VersionedMapStoreFactory; 9import tools.refinery.store.map.VersionedMapStoreFactory;
10import tools.refinery.store.map.VersionedMapStoreFactoryBuilder; 10import tools.refinery.store.map.VersionedMapStoreFactoryBuilder;
11import tools.refinery.store.map.internal.delta.DeltaBasedVersionedMapStoreFactory;
12import tools.refinery.store.map.internal.state.StateBasedVersionedMapStoreFactory;
11 13
12public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapStoreFactoryBuilder<K, V> { 14public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapStoreFactoryBuilder<K, V> {
13 15
@@ -16,14 +18,15 @@ public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapSt
16 private StoreStrategy strategy = null; 18 private StoreStrategy strategy = null;
17 private Boolean transformToImmutable = null; 19 private Boolean transformToImmutable = null;
18 private SharingStrategy sharingStrategy = null; 20 private SharingStrategy sharingStrategy = null;
19 private ContinousHashProvider<K> continousHashProvider = null; 21 private Boolean enableVersionFreeing = null;
22 private ContinuousHashProvider<K> continuousHashProvider = null;
20 private DeltaTransactionStrategy deltaTransactionStrategy = null; 23 private DeltaTransactionStrategy deltaTransactionStrategy = null;
21 24
22 private StoreStrategy checkStrategy() { 25 private StoreStrategy checkStrategy() {
23 StoreStrategy currentStrategy = strategy; 26 StoreStrategy currentStrategy = strategy;
24 currentStrategy = mergeStrategies(currentStrategy, transformToImmutable, StoreStrategy.STATE); 27 currentStrategy = mergeStrategies(currentStrategy, transformToImmutable, StoreStrategy.STATE);
25 currentStrategy = mergeStrategies(currentStrategy, sharingStrategy, StoreStrategy.STATE); 28 currentStrategy = mergeStrategies(currentStrategy, sharingStrategy, StoreStrategy.STATE);
26 currentStrategy = mergeStrategies(currentStrategy, continousHashProvider, StoreStrategy.STATE); 29 currentStrategy = mergeStrategies(currentStrategy, continuousHashProvider, StoreStrategy.STATE);
27 currentStrategy = mergeStrategies(currentStrategy, deltaTransactionStrategy, StoreStrategy.DELTA); 30 currentStrategy = mergeStrategies(currentStrategy, deltaTransactionStrategy, StoreStrategy.DELTA);
28 return currentStrategy; 31 return currentStrategy;
29 } 32 }
@@ -63,6 +66,13 @@ public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapSt
63 } 66 }
64 67
65 @Override 68 @Override
69 public VersionedMapStoreFactoryBuilder<K, V> versionFreeing(boolean enabled) {
70 this.enableVersionFreeing = enabled;
71 checkStrategy();
72 return this;
73 }
74
75 @Override
66 public VersionedMapStoreFactoryBuilder<K, V> stateBasedImmutableWhenCommitting(boolean transformToImmutable) { 76 public VersionedMapStoreFactoryBuilder<K, V> stateBasedImmutableWhenCommitting(boolean transformToImmutable) {
67 this.transformToImmutable = transformToImmutable; 77 this.transformToImmutable = transformToImmutable;
68 checkStrategy(); 78 checkStrategy();
@@ -77,8 +87,8 @@ public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapSt
77 } 87 }
78 88
79 @Override 89 @Override
80 public VersionedMapStoreFactoryBuilder<K, V> stateBasedHashProvider(ContinousHashProvider<K> hashProvider) { 90 public VersionedMapStoreFactoryBuilder<K, V> stateBasedHashProvider(ContinuousHashProvider<K> hashProvider) {
81 this.continousHashProvider = hashProvider; 91 this.continuousHashProvider = hashProvider;
82 checkStrategy(); 92 checkStrategy();
83 return this; 93 return this;
84 } 94 }
@@ -110,13 +120,14 @@ public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapSt
110 } 120 }
111 return switch (strategyToUse) { 121 return switch (strategyToUse) {
112 case STATE -> { 122 case STATE -> {
113 if(continousHashProvider == null) { 123 if(continuousHashProvider == null) {
114 throw new IllegalArgumentException("Continuous hash provider is missing!"); 124 throw new IllegalArgumentException("Continuous hash provider is missing!");
115 } 125 }
116 yield new StateBasedVersionedMapStoreFactory<>(defaultValue, 126 yield new StateBasedVersionedMapStoreFactory<>(defaultValue,
117 getOrDefault(transformToImmutable,true), 127 getOrDefault(transformToImmutable,true),
118 getOrDefault(sharingStrategy, SharingStrategy.SHARED_NODE_CACHE_IN_GROUP), 128 getOrDefault(sharingStrategy, SharingStrategy.SHARED_NODE_CACHE_IN_GROUP),
119 continousHashProvider); 129 getOrDefault(enableVersionFreeing, true),
130 continuousHashProvider);
120 } 131 }
121 case DELTA -> new DeltaBasedVersionedMapStoreFactory<>(defaultValue, 132 case DELTA -> new DeltaBasedVersionedMapStoreFactory<>(defaultValue,
122 getOrDefault(deltaTransactionStrategy, DeltaTransactionStrategy.LIST)); 133 getOrDefault(deltaTransactionStrategy, DeltaTransactionStrategy.LIST));
@@ -125,13 +136,15 @@ public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapSt
125 136
126 @Override 137 @Override
127 public String toString() { 138 public String toString() {
128 return "VersionedMapStoreBuilder{" + 139 return "VersionedMapStoreFactoryBuilderImpl{" +
129 "defaultValue=" + defaultValue + 140 "defaultSet=" + defaultSet +
141 ", defaultValue=" + defaultValue +
130 ", strategy=" + strategy + 142 ", strategy=" + strategy +
131 ", stateBasedImmutableWhenCommitting=" + transformToImmutable + 143 ", transformToImmutable=" + transformToImmutable +
132 ", stateBasedNodeSharingStrategy=" + sharingStrategy + 144 ", sharingStrategy=" + sharingStrategy +
133 ", hashProvider=" + continousHashProvider + 145 ", enableVersionFreeing=" + enableVersionFreeing +
134 ", deltaStorageStrategy=" + deltaTransactionStrategy + 146 ", continuousHashProvider=" + continuousHashProvider +
147 ", deltaTransactionStrategy=" + deltaTransactionStrategy +
135 '}'; 148 '}';
136 } 149 }
137} 150}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/DeltaBasedVersionedMapStoreFactory.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/DeltaBasedVersionedMapStoreFactory.java
index fe490f46..cedcdc0b 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/DeltaBasedVersionedMapStoreFactory.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/DeltaBasedVersionedMapStoreFactory.java
@@ -1,12 +1,11 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8import tools.refinery.store.map.VersionedMapStore; 8import tools.refinery.store.map.VersionedMapStore;
9import tools.refinery.store.map.VersionedMapStoreDeltaImpl;
10import tools.refinery.store.map.VersionedMapStoreFactory; 9import tools.refinery.store.map.VersionedMapStoreFactory;
11import tools.refinery.store.map.VersionedMapStoreFactoryBuilder; 10import tools.refinery.store.map.VersionedMapStoreFactoryBuilder;
12 11
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/DeltaDiffCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/DeltaDiffCursor.java
index cc9003e3..ce10b246 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/DeltaDiffCursor.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/DeltaDiffCursor.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8import tools.refinery.store.map.AnyVersionedMap; 8import tools.refinery.store.map.AnyVersionedMap;
9import tools.refinery.store.map.DiffCursor; 9import tools.refinery.store.map.DiffCursor;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDelta.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/MapDelta.java
index 2674236c..0c0cc906 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDelta.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/MapDelta.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8public record MapDelta<K, V>(K key, V oldValue, V newValue) { 8public record MapDelta<K, V>(K key, V oldValue, V newValue) {
9 public K getKey() { 9 public K getKey() {
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapTransaction.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/MapTransaction.java
index d63522cd..6f3fa6d7 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapTransaction.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/MapTransaction.java
@@ -1,21 +1,23 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7
8import tools.refinery.store.map.Version;
7 9
8import java.util.Arrays; 10import java.util.Arrays;
9import java.util.Objects; 11import java.util.Objects;
10 12
11public record MapTransaction<K, V>(MapDelta<K, V>[] deltas, long version, MapTransaction<K, V> parent) { 13public record MapTransaction<K, V>(MapDelta<K, V>[] deltas, MapTransaction<K, V> parent, int depth) implements Version {
12 14
13 @Override 15 @Override
14 public int hashCode() { 16 public int hashCode() {
15 final int prime = 31; 17 final int prime = 31;
16 int result = 1; 18 int result = 1;
17 result = prime * result + Arrays.hashCode(deltas); 19 result = prime * result + Arrays.hashCode(deltas);
18 result = prime * result + Objects.hash(parent, version); 20 result = prime * result + Objects.hash(parent, depth);
19 return result; 21 return result;
20 } 22 }
21 23
@@ -29,11 +31,11 @@ public record MapTransaction<K, V>(MapDelta<K, V>[] deltas, long version, MapTra
29 return false; 31 return false;
30 @SuppressWarnings("unchecked") 32 @SuppressWarnings("unchecked")
31 MapTransaction<K, V> other = (MapTransaction<K, V>) obj; 33 MapTransaction<K, V> other = (MapTransaction<K, V>) obj;
32 return Arrays.equals(deltas, other.deltas) && Objects.equals(parent, other.parent) && version == other.version; 34 return depth == other.depth && Objects.equals(parent, other.parent) && Arrays.equals(deltas, other.deltas);
33 } 35 }
34 36
35 @Override 37 @Override
36 public String toString() { 38 public String toString() {
37 return "MapTransaction " + version + " " + Arrays.toString(deltas); 39 return "MapTransaction " + depth + " " + Arrays.toString(deltas);
38 } 40 }
39} 41}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaArrayStore.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaArrayStore.java
index ba59cfef..1f6a9000 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaArrayStore.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaArrayStore.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8import java.util.ArrayList; 8import java.util.ArrayList;
9import java.util.List; 9import java.util.List;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaMapStore.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaMapStore.java
index 61a34351..644884a6 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaMapStore.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaMapStore.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8import java.util.*; 8import java.util.*;
9import java.util.Map.Entry; 9import java.util.Map.Entry;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaStore.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaStore.java
index 438b5561..ecd33c5f 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaStore.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaStore.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8public interface UncommittedDeltaStore<K, V> { 8public interface UncommittedDeltaStore<K, V> {
9 void processChange(K key, V oldValue, V newValue); 9 void processChange(K key, V oldValue, V newValue);
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapDeltaImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/VersionedMapDeltaImpl.java
index ae47feda..c19cc817 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapDeltaImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/VersionedMapDeltaImpl.java
@@ -1,13 +1,14 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8import java.util.*; 8import java.util.*;
9 9
10import tools.refinery.store.map.*; 10import tools.refinery.store.map.*;
11import tools.refinery.store.map.IteratorAsCursor;
11 12
12public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> { 13public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
13 protected final VersionedMapStoreDeltaImpl<K, V> store; 14 protected final VersionedMapStoreDeltaImpl<K, V> store;
@@ -37,15 +38,15 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
37 } 38 }
38 39
39 @Override 40 @Override
40 public long commit() { 41 public Version commit() {
41 MapDelta<K, V>[] deltas = uncommittedStore.extractAndDeleteDeltas(); 42 MapDelta<K, V>[] deltas = uncommittedStore.extractAndDeleteDeltas();
42 long[] versionContainer = new long[1]; 43 final MapTransaction<K,V> committedTransaction = this.store.appendTransaction(deltas, previous);
43 this.previous = this.store.appendTransaction(deltas, previous, versionContainer); 44 this.previous = committedTransaction;
44 return versionContainer[0]; 45 return committedTransaction;
45 } 46 }
46 47
47 @Override 48 @Override
48 public void restore(long state) { 49 public void restore(Version state) {
49 // 1. restore uncommitted states 50 // 1. restore uncommitted states
50 MapDelta<K, V>[] uncommitted = this.uncommittedStore.extractAndDeleteDeltas(); 51 MapDelta<K, V>[] uncommitted = this.uncommittedStore.extractAndDeleteDeltas();
51 if (uncommitted != null) { 52 if (uncommitted != null) {
@@ -60,7 +61,7 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
60 this.forward(forward); 61 this.forward(forward);
61 } else { 62 } else {
62 List<MapDelta<K, V>[]> backward = new ArrayList<>(); 63 List<MapDelta<K, V>[]> backward = new ArrayList<>();
63 parent = this.store.getPath(this.previous.version(), state, backward, forward); 64 parent = this.store.getPath(this.previous, state, backward, forward);
64 this.backward(backward); 65 this.backward(backward);
65 this.forward(forward); 66 this.forward(forward);
66 } 67 }
@@ -74,12 +75,16 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
74 } 75 }
75 76
76 protected void backward(List<MapDelta<K, V>[]> changes) { 77 protected void backward(List<MapDelta<K, V>[]> changes) {
78 //Currently, this loop statement is faster.
79 //noinspection ForLoopReplaceableByForEach
77 for (int i = 0; i < changes.size(); i++) { 80 for (int i = 0; i < changes.size(); i++) {
78 backward(changes.get(i)); 81 backward(changes.get(i));
79 } 82 }
80 } 83 }
81 84
82 protected void forward(MapDelta<K, V>[] changes) { 85 protected void forward(MapDelta<K, V>[] changes) {
86 //Currently, this loop statement is faster.
87 //noinspection ForLoopReplaceableByForEach
83 for (int i = 0; i < changes.length; i++) { 88 for (int i = 0; i < changes.length; i++) {
84 final MapDelta<K, V> change = changes[i]; 89 final MapDelta<K, V> change = changes[i];
85 K key = change.getKey(); 90 K key = change.getKey();
@@ -167,7 +172,7 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
167 } 172 }
168 173
169 @Override 174 @Override
170 public DiffCursor<K, V> getDiffCursor(long state) { 175 public DiffCursor<K, V> getDiffCursor(Version state) {
171 MapDelta<K, V>[] backward = this.uncommittedStore.extractDeltas(); 176 MapDelta<K, V>[] backward = this.uncommittedStore.extractDeltas();
172 List<MapDelta<K, V>[]> backwardTransactions = new ArrayList<>(); 177 List<MapDelta<K, V>[]> backwardTransactions = new ArrayList<>();
173 List<MapDelta<K, V>[]> forwardTransactions = new ArrayList<>(); 178 List<MapDelta<K, V>[]> forwardTransactions = new ArrayList<>();
@@ -177,7 +182,7 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
177 } 182 }
178 183
179 if (this.previous != null) { 184 if (this.previous != null) {
180 store.getPath(this.previous.version(), state, backwardTransactions, forwardTransactions); 185 store.getPath(this.previous, state, backwardTransactions, forwardTransactions);
181 } else { 186 } else {
182 store.getPath(state, forwardTransactions); 187 store.getPath(state, forwardTransactions);
183 } 188 }
@@ -215,5 +220,19 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
215 throw new IllegalStateException("null value stored in map!"); 220 throw new IllegalStateException("null value stored in map!");
216 } 221 }
217 } 222 }
223 MapTransaction<K,V> transaction = this.previous;
224 while(transaction != null) {
225 MapTransaction<K,V> parent = transaction.parent();
226 if(parent != null) {
227 if(parent.depth() != transaction.depth()-1) {
228 throw new IllegalStateException("Parent depths are inconsistent!");
229 }
230 } else {
231 if(transaction.depth() != 0) {
232 throw new IllegalArgumentException("Root depth is not 0!");
233 }
234 }
235 transaction = transaction.parent();
236 }
218 } 237 }
219} 238}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreDeltaImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/VersionedMapStoreDeltaImpl.java
index 0c61bd09..ed169409 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreDeltaImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/VersionedMapStoreDeltaImpl.java
@@ -1,13 +1,16 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map; 6package tools.refinery.store.map.internal.delta;
7 7
8import java.util.*; 8import tools.refinery.store.map.DiffCursor;
9import tools.refinery.store.map.Version;
10import tools.refinery.store.map.VersionedMap;
11import tools.refinery.store.map.VersionedMapStore;
9 12
10import tools.refinery.store.map.internal.*; 13import java.util.*;
11 14
12public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V> { 15public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V> {
13 // Configuration 16 // Configuration
@@ -16,10 +19,6 @@ public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V>
16 // Static data 19 // Static data
17 protected final V defaultValue; 20 protected final V defaultValue;
18 21
19 // Dynamic data
20 protected final Map<Long, MapTransaction<K, V>> states = new HashMap<>();
21 protected long nextID = 0;
22
23 public VersionedMapStoreDeltaImpl(boolean summarizeChanges, V defaultValue) { 22 public VersionedMapStoreDeltaImpl(boolean summarizeChanges, V defaultValue) {
24 this.summarizeChanges = summarizeChanges; 23 this.summarizeChanges = summarizeChanges;
25 this.defaultValue = defaultValue; 24 this.defaultValue = defaultValue;
@@ -31,30 +30,32 @@ public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V>
31 } 30 }
32 31
33 @Override 32 @Override
34 public VersionedMap<K, V> createMap(long state) { 33 public VersionedMap<K, V> createMap(Version state) {
35 VersionedMapDeltaImpl<K, V> result = new VersionedMapDeltaImpl<>(this, this.summarizeChanges, this.defaultValue); 34 VersionedMapDeltaImpl<K, V> result = new VersionedMapDeltaImpl<>(this, this.summarizeChanges, this.defaultValue);
36 result.restore(state); 35 result.restore(state);
37 return result; 36 return result;
38 } 37 }
39 38
40 public synchronized MapTransaction<K, V> appendTransaction(MapDelta<K, V>[] deltas, MapTransaction<K, V> previous, long[] versionContainer) { 39 public MapTransaction<K, V> appendTransaction(MapDelta<K, V>[] deltas, MapTransaction<K, V> previous) {
41 long version = nextID++;
42 versionContainer[0] = version;
43 if (deltas == null) { 40 if (deltas == null) {
44 states.put(version, previous);
45 return previous; 41 return previous;
46 } else { 42 } else {
47 MapTransaction<K, V> transaction = new MapTransaction<>(deltas, version, previous); 43 final int depth;
48 states.put(version, transaction); 44 if(previous != null) {
49 return transaction; 45 depth = previous.depth()+1;
46 } else {
47 depth = 0;
48 }
49 return new MapTransaction<>(deltas, previous, depth);
50 } 50 }
51 } 51 }
52 52
53 private synchronized MapTransaction<K, V> getState(long state) { 53 @SuppressWarnings("unchecked")
54 return states.get(state); 54 private MapTransaction<K, V> getState(Version state) {
55 return (MapTransaction<K, V>) state;
55 } 56 }
56 57
57 public MapTransaction<K, V> getPath(long to, List<MapDelta<K, V>[]> forwardTransactions) { 58 public MapTransaction<K, V> getPath(Version to, List<MapDelta<K, V>[]> forwardTransactions) {
58 final MapTransaction<K, V> target = getState(to); 59 final MapTransaction<K, V> target = getState(to);
59 MapTransaction<K, V> toTransaction = target; 60 MapTransaction<K, V> toTransaction = target;
60 while (toTransaction != null) { 61 while (toTransaction != null) {
@@ -64,7 +65,7 @@ public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V>
64 return target; 65 return target;
65 } 66 }
66 67
67 public MapTransaction<K, V> getPath(long from, long to, 68 public MapTransaction<K, V> getPath(Version from, Version to,
68 List<MapDelta<K, V>[]> backwardTransactions, 69 List<MapDelta<K, V>[]> backwardTransactions,
69 List<MapDelta<K, V>[]> forwardTransactions) { 70 List<MapDelta<K, V>[]> forwardTransactions) {
70 MapTransaction<K, V> fromTransaction = getState(from); 71 MapTransaction<K, V> fromTransaction = getState(from);
@@ -72,7 +73,7 @@ public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V>
72 MapTransaction<K, V> toTransaction = target; 73 MapTransaction<K, V> toTransaction = target;
73 74
74 while (fromTransaction != toTransaction) { 75 while (fromTransaction != toTransaction) {
75 if (fromTransaction == null || (toTransaction != null && fromTransaction.version() < toTransaction.version())) { 76 if (fromTransaction == null || (toTransaction != null && fromTransaction.depth() < toTransaction.depth())) {
76 forwardTransactions.add(toTransaction.deltas()); 77 forwardTransactions.add(toTransaction.deltas());
77 toTransaction = toTransaction.parent(); 78 toTransaction = toTransaction.parent();
78 } else { 79 } else {
@@ -83,14 +84,8 @@ public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V>
83 return target; 84 return target;
84 } 85 }
85 86
86
87 @Override
88 public synchronized Set<Long> getStates() {
89 return new HashSet<>(states.keySet());
90 }
91
92 @Override 87 @Override
93 public DiffCursor<K, V> getDiffCursor(long fromState, long toState) { 88 public DiffCursor<K, V> getDiffCursor(Version fromState, Version toState) {
94 List<MapDelta<K, V>[]> backwardTransactions = new ArrayList<>(); 89 List<MapDelta<K, V>[]> backwardTransactions = new ArrayList<>();
95 List<MapDelta<K, V>[]> forwardTransactions = new ArrayList<>(); 90 List<MapDelta<K, V>[]> forwardTransactions = new ArrayList<>();
96 getPath(fromState, toState, backwardTransactions, forwardTransactions); 91 getPath(fromState, toState, backwardTransactions, forwardTransactions);
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/ImmutableNode.java
index d052318f..5b1d8b77 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/ImmutableNode.java
@@ -1,16 +1,17 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import java.util.Arrays; 8import java.util.Arrays;
9import java.util.Map; 9import java.util.Map;
10 10
11import tools.refinery.store.map.ContinousHashProvider; 11import tools.refinery.store.map.ContinuousHashProvider;
12import tools.refinery.store.map.Version;
12 13
13public class ImmutableNode<K, V> extends Node<K, V> { 14public class ImmutableNode<K, V> extends Node<K, V> implements Version {
14 /** 15 /**
15 * Bitmap defining the stored key and values. 16 * Bitmap defining the stored key and values.
16 */ 17 */
@@ -104,7 +105,7 @@ public class ImmutableNode<K, V> extends Node<K, V> {
104 } 105 }
105 106
106 @Override 107 @Override
107 public V getValue(K key, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) { 108 public V getValue(K key, ContinuousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) {
108 int selectedHashFragment = hashFragment(hash, shiftDepth(depth)); 109 int selectedHashFragment = hashFragment(hash, shiftDepth(depth));
109 int bitposition = 1 << selectedHashFragment; 110 int bitposition = 1 << selectedHashFragment;
110 // If the key is stored as a data 111 // If the key is stored as a data
@@ -133,7 +134,7 @@ public class ImmutableNode<K, V> extends Node<K, V> {
133 } 134 }
134 135
135 @Override 136 @Override
136 public Node<K, V> putValue(K key, V value, OldValueBox<V> oldValue, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) { 137 public Node<K, V> putValue(K key, V value, OldValueBox<V> oldValue, ContinuousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) {
137 int selectedHashFragment = hashFragment(hash, shiftDepth(depth)); 138 int selectedHashFragment = hashFragment(hash, shiftDepth(depth));
138 int bitPosition = 1 << selectedHashFragment; 139 int bitPosition = 1 << selectedHashFragment;
139 if ((dataMap & bitPosition) != 0) { 140 if ((dataMap & bitPosition) != 0) {
@@ -145,7 +146,7 @@ public class ImmutableNode<K, V> extends Node<K, V> {
145 MutableNode<K, V> mutable = this.toMutable(); 146 MutableNode<K, V> mutable = this.toMutable();
146 return mutable.removeEntry(selectedHashFragment, oldValue); 147 return mutable.removeEntry(selectedHashFragment, oldValue);
147 } else if (value == content[keyIndex + 1]) { 148 } else if (value == content[keyIndex + 1]) {
148 // dont change 149 // don't change
149 oldValue.setOldValue(value); 150 oldValue.setOldValue(value);
150 return this; 151 return this;
151 } else { 152 } else {
@@ -155,7 +156,7 @@ public class ImmutableNode<K, V> extends Node<K, V> {
155 } 156 }
156 } else { 157 } else {
157 if (value == defaultValue) { 158 if (value == defaultValue) {
158 // dont change 159 // don't change
159 oldValue.setOldValue(defaultValue); 160 oldValue.setOldValue(defaultValue);
160 return this; 161 return this;
161 } else { 162 } else {
@@ -339,7 +340,7 @@ public class ImmutableNode<K, V> extends Node<K, V> {
339 } 340 }
340 341
341 @Override 342 @Override
342 public void checkIntegrity(ContinousHashProvider<? super K> hashProvider, V defaultValue, int depth) { 343 public void checkIntegrity(ContinuousHashProvider<? super K> hashProvider, V defaultValue, int depth) {
343 if (depth > 0) { 344 if (depth > 0) {
344 boolean orphaned = Integer.bitCount(dataMap) == 1 && nodeMap == 0; 345 boolean orphaned = Integer.bitCount(dataMap) == 1 && nodeMap == 0;
345 if (orphaned) { 346 if (orphaned) {
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/InOrderMapCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/InOrderMapCursor.java
index cb3f366f..7cc91004 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/InOrderMapCursor.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/InOrderMapCursor.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import tools.refinery.store.map.AnyVersionedMap; 8import tools.refinery.store.map.AnyVersionedMap;
9import tools.refinery.store.map.ContentHashCode; 9import tools.refinery.store.map.ContentHashCode;
@@ -29,7 +29,7 @@ public class InOrderMapCursor<K, V> implements Cursor<K, V> {
29 final VersionedMap<K, V> map; 29 final VersionedMap<K, V> map;
30 final int creationHash; 30 final int creationHash;
31 31
32 public InOrderMapCursor(VersionedMapImpl<K, V> map) { 32 public InOrderMapCursor(VersionedMapStateImpl<K, V> map) {
33 // Initializing tree stack 33 // Initializing tree stack
34 super(); 34 super();
35 this.nodeStack = new ArrayDeque<>(); 35 this.nodeStack = new ArrayDeque<>();
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MapCursor.java
index d42519b2..0db50d04 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MapCursor.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import tools.refinery.store.map.AnyVersionedMap; 8import tools.refinery.store.map.AnyVersionedMap;
9import tools.refinery.store.map.ContentHashCode; 9import tools.refinery.store.map.ContentHashCode;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MapDiffCursor.java
index fb1d5d2b..083bf8cf 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MapDiffCursor.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import tools.refinery.store.map.AnyVersionedMap; 8import tools.refinery.store.map.AnyVersionedMap;
9import tools.refinery.store.map.Cursor; 9import tools.refinery.store.map.Cursor;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MutableNode.java
index bb85deb9..408ed62c 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MutableNode.java
@@ -1,11 +1,11 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import tools.refinery.store.map.ContinousHashProvider; 8import tools.refinery.store.map.ContinuousHashProvider;
9 9
10import java.util.Arrays; 10import java.util.Arrays;
11import java.util.Map; 11import java.util.Map;
@@ -20,7 +20,7 @@ public class MutableNode<K, V> extends Node<K, V> {
20 invalidateHash(); 20 invalidateHash();
21 } 21 }
22 22
23 public static <K, V> MutableNode<K, V> initialize(K key, V value, ContinousHashProvider<? super K> hashProvider, V defaultValue) { 23 public static <K, V> MutableNode<K, V> initialize(K key, V value, ContinuousHashProvider<? super K> hashProvider, V defaultValue) {
24 if (value == defaultValue) { 24 if (value == defaultValue) {
25 return null; 25 return null;
26 } else { 26 } else {
@@ -58,7 +58,7 @@ public class MutableNode<K, V> extends Node<K, V> {
58 } 58 }
59 59
60 @Override 60 @Override
61 public V getValue(K key, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) { 61 public V getValue(K key, ContinuousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) {
62 int selectedHashFragment = hashFragment(hash, shiftDepth(depth)); 62 int selectedHashFragment = hashFragment(hash, shiftDepth(depth));
63 @SuppressWarnings("unchecked") K keyCandidate = (K) this.content[2 * selectedHashFragment]; 63 @SuppressWarnings("unchecked") K keyCandidate = (K) this.content[2 * selectedHashFragment];
64 if (keyCandidate != null) { 64 if (keyCandidate != null) {
@@ -81,7 +81,7 @@ public class MutableNode<K, V> extends Node<K, V> {
81 } 81 }
82 82
83 @Override 83 @Override
84 public Node<K, V> putValue(K key, V value, OldValueBox<V> oldValueBox, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) { 84 public Node<K, V> putValue(K key, V value, OldValueBox<V> oldValueBox, ContinuousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) {
85 int selectedHashFragment = hashFragment(hash, shiftDepth(depth)); 85 int selectedHashFragment = hashFragment(hash, shiftDepth(depth));
86 @SuppressWarnings("unchecked") K keyCandidate = (K) content[2 * selectedHashFragment]; 86 @SuppressWarnings("unchecked") K keyCandidate = (K) content[2 * selectedHashFragment];
87 if (keyCandidate != null) { 87 if (keyCandidate != null) {
@@ -217,7 +217,7 @@ public class MutableNode<K, V> extends Node<K, V> {
217 } 217 }
218 218
219 @SuppressWarnings("unchecked") 219 @SuppressWarnings("unchecked")
220 private Node<K, V> moveDownAndSplit(ContinousHashProvider<? super K> hashProvider, K newKey, V newValue, K previousKey, int hashOfNewKey, int depth, int selectedHashFragmentOfCurrentDepth) { 220 private Node<K, V> moveDownAndSplit(ContinuousHashProvider<? super K> hashProvider, K newKey, V newValue, K previousKey, int hashOfNewKey, int depth, int selectedHashFragmentOfCurrentDepth) {
221 V previousValue = (V) content[2 * selectedHashFragmentOfCurrentDepth + 1]; 221 V previousValue = (V) content[2 * selectedHashFragmentOfCurrentDepth + 1];
222 222
223 MutableNode<K, V> newSubNode = newNodeWithTwoEntries(hashProvider, previousKey, previousValue, hashProvider.getHash(previousKey, hashDepth(depth)), newKey, newValue, hashOfNewKey, incrementDepth(depth)); 223 MutableNode<K, V> newSubNode = newNodeWithTwoEntries(hashProvider, previousKey, previousValue, hashProvider.getHash(previousKey, hashDepth(depth)), newKey, newValue, hashOfNewKey, incrementDepth(depth));
@@ -230,7 +230,7 @@ public class MutableNode<K, V> extends Node<K, V> {
230 230
231 // Pass everything as parameters for performance. 231 // Pass everything as parameters for performance.
232 @SuppressWarnings("squid:S107") 232 @SuppressWarnings("squid:S107")
233 private MutableNode<K, V> newNodeWithTwoEntries(ContinousHashProvider<? super K> hashProvider, K key1, V value1, int oldHash1, K key2, V value2, int oldHash2, int newDepth) { 233 private MutableNode<K, V> newNodeWithTwoEntries(ContinuousHashProvider<? super K> hashProvider, K key1, V value1, int oldHash1, K key2, V value2, int oldHash2, int newDepth) {
234 int newHash1 = newHash(hashProvider, key1, oldHash1, newDepth); 234 int newHash1 = newHash(hashProvider, key1, oldHash1, newDepth);
235 int newHash2 = newHash(hashProvider, key2, oldHash2, newDepth); 235 int newHash2 = newHash(hashProvider, key2, oldHash2, newDepth);
236 int newFragment1 = hashFragment(newHash1, shiftDepth(newDepth)); 236 int newFragment1 = hashFragment(newHash1, shiftDepth(newDepth));
@@ -418,7 +418,7 @@ public class MutableNode<K, V> extends Node<K, V> {
418 } 418 }
419 419
420 @Override 420 @Override
421 public void checkIntegrity(ContinousHashProvider<? super K> hashProvider, V defaultValue, int depth) { 421 public void checkIntegrity(ContinuousHashProvider<? super K> hashProvider, V defaultValue, int depth) {
422 // check for orphan nodes 422 // check for orphan nodes
423 if (depth > 0) { 423 if (depth > 0) {
424 int orphaned = isOrphaned(); 424 int orphaned = isOrphaned();
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/Node.java
index 4b44f760..0ecf2712 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/Node.java
@@ -1,13 +1,13 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import java.util.Map; 8import java.util.Map;
9 9
10import tools.refinery.store.map.ContinousHashProvider; 10import tools.refinery.store.map.ContinuousHashProvider;
11 11
12public abstract class Node<K, V> { 12public abstract class Node<K, V> {
13 public static final int BRANCHING_FACTOR_BITS = 5; 13 public static final int BRANCHING_FACTOR_BITS = 5;
@@ -77,14 +77,14 @@ public abstract class Node<K, V> {
77 * @param depth The depth. 77 * @param depth The depth.
78 * @return The new hash code. 78 * @return The new hash code.
79 */ 79 */
80 protected int newHash(final ContinousHashProvider<? super K> hashProvider, K key, int hash, int depth) { 80 protected int newHash(final ContinuousHashProvider<? super K> hashProvider, K key, int hash, int depth) {
81 final int shiftDepth = shiftDepth(depth); 81 final int shiftDepth = shiftDepth(depth);
82 if (shiftDepth == 0) { 82 if (shiftDepth == 0) {
83 final int hashDepth = hashDepth(depth); 83 final int hashDepth = hashDepth(depth);
84 if (hashDepth >= ContinousHashProvider.MAX_PRACTICAL_DEPTH) { 84 if (hashDepth >= ContinuousHashProvider.MAX_PRACTICAL_DEPTH) {
85 throw new IllegalArgumentException( 85 throw new IllegalArgumentException(
86 "Key " + key + " have the clashing hashcode over the practical depth limitation (" 86 "Key " + key + " have the clashing hashcode over the practical depth limitation ("
87 + ContinousHashProvider.MAX_PRACTICAL_DEPTH + ")!"); 87 + ContinuousHashProvider.MAX_PRACTICAL_DEPTH + ")!");
88 } 88 }
89 return hashProvider.getHash(key, hashDepth); 89 return hashProvider.getHash(key, hashDepth);
90 } else { 90 } else {
@@ -92,11 +92,11 @@ public abstract class Node<K, V> {
92 } 92 }
93 } 93 }
94 94
95 public abstract V getValue(K key, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, 95 public abstract V getValue(K key, ContinuousHashProvider<? super K> hashProvider, V defaultValue, int hash,
96 int depth); 96 int depth);
97 97
98 public abstract Node<K, V> putValue(K key, V value, OldValueBox<V> old, 98 public abstract Node<K, V> putValue(K key, V value, OldValueBox<V> old,
99 ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth); 99 ContinuousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth);
100 100
101 public abstract long getSize(); 101 public abstract long getSize();
102 102
@@ -126,6 +126,6 @@ public abstract class Node<K, V> {
126 return stringBuilder.toString(); 126 return stringBuilder.toString();
127 } 127 }
128 128
129 public void checkIntegrity(ContinousHashProvider<? super K> hashProvider, V defaultValue, int depth) { 129 public void checkIntegrity(ContinuousHashProvider<? super K> hashProvider, V defaultValue, int depth) {
130 } 130 }
131} 131}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/OldValueBox.java
index 354af51d..1b0a4b0c 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/OldValueBox.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8public class OldValueBox<V>{ 8public class OldValueBox<V>{
9 V oldValue; 9 V oldValue;
@@ -20,5 +20,5 @@ public class OldValueBox<V>{
20 this.oldValue = ouldValue; 20 this.oldValue = ouldValue;
21 isSet = true; 21 isSet = true;
22 } 22 }
23 23
24} 24}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/StateBasedVersionedMapStoreFactory.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/StateBasedVersionedMapStoreFactory.java
new file mode 100644
index 00000000..ccc791a8
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/StateBasedVersionedMapStoreFactory.java
@@ -0,0 +1,43 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.map.internal.state;
7
8import tools.refinery.store.map.*;
9
10import java.util.List;
11
12public class StateBasedVersionedMapStoreFactory<K, V> implements VersionedMapStoreFactory<K, V> {
13 private final V defaultValue;
14 private final ContinuousHashProvider<K> continuousHashProvider;
15 private final VersionedMapStoreStateConfiguration config;
16
17 public StateBasedVersionedMapStoreFactory(V defaultValue, Boolean transformToImmutable,
18 VersionedMapStoreFactoryBuilder.SharingStrategy sharingStrategy,
19 boolean versionFreeingEnabled,
20 ContinuousHashProvider<K> continuousHashProvider) {
21 this.defaultValue = defaultValue;
22 this.continuousHashProvider = continuousHashProvider;
23
24 this.config = new VersionedMapStoreStateConfiguration(
25 transformToImmutable,
26 sharingStrategy == VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE
27 || sharingStrategy == VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE_IN_GROUP,
28 sharingStrategy == VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE_IN_GROUP,
29 versionFreeingEnabled);
30 }
31
32 @Override
33 public VersionedMapStore<K, V> createOne() {
34 return new VersionedMapStoreStateImpl<>(continuousHashProvider, defaultValue, config);
35
36 }
37
38 @Override
39 public List<VersionedMapStore<K, V>> createGroup(int amount) {
40 return VersionedMapStoreStateImpl.createSharedVersionedMapStores(amount, continuousHashProvider, defaultValue,
41 config);
42 }
43}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStateImpl.java
index c107f7e0..57eeccf6 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStateImpl.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import tools.refinery.store.map.*; 8import tools.refinery.store.map.*;
9 9
@@ -19,18 +19,18 @@ import java.util.Objects;
19 * @param <V> 19 * @param <V>
20 * @author Oszkar Semerath 20 * @author Oszkar Semerath
21 */ 21 */
22public class VersionedMapImpl<K, V> implements VersionedMap<K, V> { 22public class VersionedMapStateImpl<K, V> implements VersionedMap<K, V> {
23 protected final VersionedMapStoreImpl<K, V> store; 23 protected final VersionedMapStoreStateImpl<K, V> store;
24 24
25 protected final ContinousHashProvider<K> hashProvider; 25 protected final ContinuousHashProvider<K> hashProvider;
26 protected final V defaultValue; 26 protected final V defaultValue;
27 protected Node<K, V> root; 27 protected Node<K, V> root;
28 28
29 private final OldValueBox<V> oldValueBox = new OldValueBox<>(); 29 private final OldValueBox<V> oldValueBox = new OldValueBox<>();
30 30
31 public VersionedMapImpl( 31 public VersionedMapStateImpl(
32 VersionedMapStoreImpl<K, V> store, 32 VersionedMapStoreStateImpl<K, V> store,
33 ContinousHashProvider<K> hashProvider, 33 ContinuousHashProvider<K> hashProvider,
34 V defaultValue) { 34 V defaultValue) {
35 this.store = store; 35 this.store = store;
36 this.hashProvider = hashProvider; 36 this.hashProvider = hashProvider;
@@ -38,9 +38,9 @@ public class VersionedMapImpl<K, V> implements VersionedMap<K, V> {
38 this.root = null; 38 this.root = null;
39 } 39 }
40 40
41 public VersionedMapImpl( 41 public VersionedMapStateImpl(
42 VersionedMapStoreImpl<K, V> store, 42 VersionedMapStoreStateImpl<K, V> store,
43 ContinousHashProvider<K> hashProvider, 43 ContinuousHashProvider<K> hashProvider,
44 V defaultValue, Node<K, V> data) { 44 V defaultValue, Node<K, V> data) {
45 this.store = store; 45 this.store = store;
46 this.hashProvider = hashProvider; 46 this.hashProvider = hashProvider;
@@ -53,7 +53,7 @@ public class VersionedMapImpl<K, V> implements VersionedMap<K, V> {
53 return defaultValue; 53 return defaultValue;
54 } 54 }
55 55
56 public ContinousHashProvider<K> getHashProvider() { 56 public ContinuousHashProvider<K> getHashProvider() {
57 return hashProvider; 57 return hashProvider;
58 } 58 }
59 59
@@ -115,16 +115,16 @@ public class VersionedMapImpl<K, V> implements VersionedMap<K, V> {
115 } 115 }
116 116
117 @Override 117 @Override
118 public DiffCursor<K, V> getDiffCursor(long toVersion) { 118 public DiffCursor<K, V> getDiffCursor(Version toVersion) {
119 InOrderMapCursor<K, V> fromCursor = new InOrderMapCursor<>(this); 119 InOrderMapCursor<K, V> fromCursor = new InOrderMapCursor<>(this);
120 VersionedMapImpl<K, V> toMap = (VersionedMapImpl<K, V>) this.store.createMap(toVersion); 120 VersionedMapStateImpl<K, V> toMap = (VersionedMapStateImpl<K, V>) this.store.createMap(toVersion);
121 InOrderMapCursor<K, V> toCursor = new InOrderMapCursor<>(toMap); 121 InOrderMapCursor<K, V> toCursor = new InOrderMapCursor<>(toMap);
122 return new MapDiffCursor<>(this.defaultValue, fromCursor, toCursor); 122 return new MapDiffCursor<>(this.defaultValue, fromCursor, toCursor);
123 } 123 }
124 124
125 125
126 @Override 126 @Override
127 public long commit() { 127 public Version commit() {
128 return this.store.commit(root, this); 128 return this.store.commit(root, this);
129 } 129 }
130 130
@@ -133,7 +133,7 @@ public class VersionedMapImpl<K, V> implements VersionedMap<K, V> {
133 } 133 }
134 134
135 @Override 135 @Override
136 public void restore(long state) { 136 public void restore(Version state) {
137 root = this.store.revert(state); 137 root = this.store.revert(state);
138 } 138 }
139 139
@@ -166,6 +166,6 @@ public class VersionedMapImpl<K, V> implements VersionedMap<K, V> {
166 166
167 @Override 167 @Override
168 public boolean contentEquals(AnyVersionedMap other) { 168 public boolean contentEquals(AnyVersionedMap other) {
169 return other instanceof VersionedMapImpl<?, ?> otherImpl && Objects.equals(root, otherImpl.root); 169 return other instanceof VersionedMapStateImpl<?, ?> otherImpl && Objects.equals(root, otherImpl.root);
170 } 170 }
171} 171}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateConfiguration.java
index b00cd961..6650f565 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateConfiguration.java
@@ -1,21 +1,25 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map; 6package tools.refinery.store.map.internal.state;
7 7
8public class VersionedMapStoreConfiguration { 8import tools.refinery.store.map.ContinuousHashProvider;
9import tools.refinery.store.map.VersionedMapStore;
9 10
10 public VersionedMapStoreConfiguration() { 11public class VersionedMapStoreStateConfiguration {
12
13 public VersionedMapStoreStateConfiguration() {
11 14
12 } 15 }
13 public VersionedMapStoreConfiguration(boolean immutableWhenCommitting, boolean sharedNodeCacheInStore, 16 public VersionedMapStoreStateConfiguration(boolean immutableWhenCommitting, boolean sharedNodeCacheInStore,
14 boolean sharedNodeCacheInStoreGroups) { 17 boolean sharedNodeCacheInStoreGroups, boolean versionFreeingEnabled) {
15 super(); 18 super();
16 this.immutableWhenCommitting = immutableWhenCommitting; 19 this.immutableWhenCommitting = immutableWhenCommitting;
17 this.sharedNodeCacheInStore = sharedNodeCacheInStore; 20 this.sharedNodeCacheInStore = sharedNodeCacheInStore;
18 this.sharedNodeCacheInStoreGroups = sharedNodeCacheInStoreGroups; 21 this.sharedNodeCacheInStoreGroups = sharedNodeCacheInStoreGroups;
22 this.versionFreeingEnabled = versionFreeingEnabled;
19 } 23 }
20 24
21 /** 25 /**
@@ -42,12 +46,17 @@ public class VersionedMapStoreConfiguration {
42 46
43 /** 47 /**
44 * If true, all sub-nodes are cached within a group of 48 * If true, all sub-nodes are cached within a group of
45 * {@link VersionedMapStoreImpl#createSharedVersionedMapStores(int, ContinousHashProvider, Object, VersionedMapStoreConfiguration)}. 49 * {@link VersionedMapStoreStateImpl#createSharedVersionedMapStores(int, ContinuousHashProvider, Object, VersionedMapStoreStateConfiguration)}.
46 * If {@link VersionedMapStoreConfiguration#sharedNodeCacheInStore} is 50 * If {@link VersionedMapStoreStateConfiguration#sharedNodeCacheInStore} is
47 * <code>false</code>, then it has currently no impact. 51 * <code>false</code>, then it has currently no impact.
48 */ 52 */
49 private boolean sharedNodeCacheInStoreGroups = true; 53 private boolean sharedNodeCacheInStoreGroups = true;
50 public boolean isSharedNodeCacheInStoreGroups() { 54 public boolean isSharedNodeCacheInStoreGroups() {
51 return sharedNodeCacheInStoreGroups; 55 return sharedNodeCacheInStoreGroups;
52 } 56 }
57
58 private boolean versionFreeingEnabled = true;
59 public boolean isVersionFreeingEnabled() {
60 return versionFreeingEnabled;
61 }
53} 62}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateImpl.java
new file mode 100644
index 00000000..8ff3f8e7
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateImpl.java
@@ -0,0 +1,119 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.map.internal.state;
7
8import tools.refinery.store.map.*;
9
10import java.util.*;
11
12public class VersionedMapStoreStateImpl<K, V> implements VersionedMapStore<K, V> {
13 // Configuration
14 private final boolean immutableWhenCommitting;
15
16 // Static data
17 protected final ContinuousHashProvider<K> hashProvider;
18 protected final V defaultValue;
19
20 protected final Map<Node<K, V>, ImmutableNode<K, V>> nodeCache;
21
22 public VersionedMapStoreStateImpl(ContinuousHashProvider<K> hashProvider, V defaultValue,
23 VersionedMapStoreStateConfiguration config) {
24 this.immutableWhenCommitting = config.isImmutableWhenCommitting();
25 this.hashProvider = hashProvider;
26 this.defaultValue = defaultValue;
27 if (config.isSharedNodeCacheInStore()) {
28 nodeCache = createNoteCache(config);
29 } else {
30 nodeCache = null;
31 }
32 }
33
34 private VersionedMapStoreStateImpl(ContinuousHashProvider<K> hashProvider, V defaultValue,
35 Map<Node<K, V>, ImmutableNode<K, V>> nodeCache, VersionedMapStoreStateConfiguration config) {
36 this.immutableWhenCommitting = config.isImmutableWhenCommitting();
37 this.hashProvider = hashProvider;
38 this.defaultValue = defaultValue;
39 this.nodeCache = nodeCache;
40 }
41
42 public VersionedMapStoreStateImpl(ContinuousHashProvider<K> hashProvider, V defaultValue) {
43 this(hashProvider, defaultValue, new VersionedMapStoreStateConfiguration());
44 }
45
46 public static <K, V> List<VersionedMapStore<K, V>> createSharedVersionedMapStores(int amount,
47 ContinuousHashProvider<K> hashProvider, V defaultValue,
48 VersionedMapStoreStateConfiguration config) {
49 List<VersionedMapStore<K, V>> result = new ArrayList<>(amount);
50 if (config.isSharedNodeCacheInStoreGroups()) {
51 Map<Node<K, V>, ImmutableNode<K, V>> nodeCache;
52 if (config.isSharedNodeCacheInStore()) {
53 nodeCache = createNoteCache(config);
54 } else {
55 nodeCache = null;
56 }
57 for (int i = 0; i < amount; i++) {
58 result.add(new VersionedMapStoreStateImpl<>(hashProvider, defaultValue, nodeCache, config));
59 }
60 } else {
61 for (int i = 0; i < amount; i++) {
62 result.add(new VersionedMapStoreStateImpl<>(hashProvider, defaultValue, config));
63 }
64 }
65 return result;
66 }
67
68 private static <K,V> Map<K,V> createNoteCache(VersionedMapStoreStateConfiguration config) {
69 if(config.isVersionFreeingEnabled()) {
70 return new WeakHashMap<>();
71 } else {
72 return new HashMap<>();
73 }
74 }
75
76 public static <K, V> List<VersionedMapStore<K, V>> createSharedVersionedMapStores(int amount,
77 ContinuousHashProvider<K> hashProvider, V defaultValue) {
78 return createSharedVersionedMapStores(amount, hashProvider, defaultValue, new VersionedMapStoreStateConfiguration());
79 }
80
81 @Override
82 public VersionedMap<K, V> createMap() {
83 return new VersionedMapStateImpl<>(this, hashProvider, defaultValue);
84 }
85
86 @Override
87 public VersionedMap<K, V> createMap(Version state) {
88 ImmutableNode<K, V> data = revert(state);
89 return new VersionedMapStateImpl<>(this, hashProvider, defaultValue, data);
90 }
91
92 @SuppressWarnings("unchecked")
93 public synchronized ImmutableNode<K, V> revert(Version state) {
94 return (ImmutableNode<K, V>) state;
95 }
96
97 public synchronized Version commit(Node<K, V> data, VersionedMapStateImpl<K, V> mapToUpdateRoot) {
98 ImmutableNode<K, V> immutable;
99 if (data != null) {
100 immutable = data.toImmutable(this.nodeCache);
101 } else {
102 immutable = null;
103 }
104
105 if (this.immutableWhenCommitting) {
106 mapToUpdateRoot.setRoot(immutable);
107 }
108 return immutable;
109 }
110
111 @Override
112 public DiffCursor<K, V> getDiffCursor(Version fromState, Version toState) {
113 VersionedMapStateImpl<K, V> map1 = (VersionedMapStateImpl<K, V>) createMap(fromState);
114 VersionedMapStateImpl<K, V> map2 = (VersionedMapStateImpl<K, V>) createMap(toState);
115 InOrderMapCursor<K, V> cursor1 = new InOrderMapCursor<>(map1);
116 InOrderMapCursor<K, V> cursor2 = new InOrderMapCursor<>(map2);
117 return new MapDiffCursor<>(this.defaultValue, cursor1, cursor2);
118 }
119}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java
index 26ad9a69..72f188d3 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java
@@ -7,6 +7,7 @@ package tools.refinery.store.model;
7 7
8import tools.refinery.store.map.Cursor; 8import tools.refinery.store.map.Cursor;
9import tools.refinery.store.map.DiffCursor; 9import tools.refinery.store.map.DiffCursor;
10import tools.refinery.store.map.Version;
10import tools.refinery.store.representation.Symbol; 11import tools.refinery.store.representation.Symbol;
11import tools.refinery.store.tuple.Tuple; 12import tools.refinery.store.tuple.Tuple;
12 13
@@ -22,7 +23,7 @@ public non-sealed interface Interpretation<T> extends AnyInterpretation {
22 23
23 void putAll(Cursor<Tuple, T> cursor); 24 void putAll(Cursor<Tuple, T> cursor);
24 25
25 DiffCursor<Tuple, T> getDiffCursor(long to); 26 DiffCursor<Tuple, T> getDiffCursor(Version to);
26 27
27 void addListener(InterpretationListener<T> listener, boolean alsoWhenRestoring); 28 void addListener(InterpretationListener<T> listener, boolean alsoWhenRestoring);
28 29
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/Model.java b/subprojects/store/src/main/java/tools/refinery/store/model/Model.java
index 703a0720..e2ab72e7 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/Model.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/Model.java
@@ -6,6 +6,7 @@
6package tools.refinery.store.model; 6package tools.refinery.store.model;
7 7
8import tools.refinery.store.adapter.ModelAdapter; 8import tools.refinery.store.adapter.ModelAdapter;
9import tools.refinery.store.map.Version;
9import tools.refinery.store.map.Versioned; 10import tools.refinery.store.map.Versioned;
10import tools.refinery.store.model.internal.VersionedInterpretation; 11import tools.refinery.store.model.internal.VersionedInterpretation;
11import tools.refinery.store.representation.AnySymbol; 12import tools.refinery.store.representation.AnySymbol;
@@ -15,11 +16,10 @@ import java.util.Map;
15import java.util.Optional; 16import java.util.Optional;
16 17
17public interface Model extends Versioned { 18public interface Model extends Versioned {
18 long NO_STATE_ID = -1; 19 Version NO_STATE_ID = null;
19
20 ModelStore getStore(); 20 ModelStore getStore();
21 21
22 long getState(); 22 Version getState();
23 23
24 boolean hasUncommittedChanges(); 24 boolean hasUncommittedChanges();
25 25
@@ -29,9 +29,7 @@ public interface Model extends Versioned {
29 29
30 <T> Interpretation<T> getInterpretation(Symbol<T> symbol); 30 <T> Interpretation<T> getInterpretation(Symbol<T> symbol);
31 31
32 public Map<? extends AnySymbol, ? extends Interpretation<?>> getInterpretations(); 32 ModelDiffCursor getDiffCursor(Version to);
33
34 ModelDiffCursor getDiffCursor(long to);
35 33
36 <T extends ModelAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType); 34 <T extends ModelAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType);
37 35
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java
index a9ad8cfd..703ee10a 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java
@@ -5,6 +5,8 @@
5 */ 5 */
6package tools.refinery.store.model; 6package tools.refinery.store.model;
7 7
8import tools.refinery.store.map.Version;
9
8public interface ModelListener { 10public interface ModelListener {
9 default void beforeCommit() { 11 default void beforeCommit() {
10 } 12 }
@@ -12,7 +14,7 @@ public interface ModelListener {
12 default void afterCommit() { 14 default void afterCommit() {
13 } 15 }
14 16
15 default void beforeRestore(long state) { 17 default void beforeRestore(Version state) {
16 } 18 }
17 19
18 default void afterRestore() { 20 default void afterRestore() {
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java
index b10eb8a4..89382b3a 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java
@@ -6,23 +6,21 @@
6package tools.refinery.store.model; 6package tools.refinery.store.model;
7 7
8import tools.refinery.store.adapter.ModelStoreAdapter; 8import tools.refinery.store.adapter.ModelStoreAdapter;
9import tools.refinery.store.map.Version;
9import tools.refinery.store.model.internal.ModelStoreBuilderImpl; 10import tools.refinery.store.model.internal.ModelStoreBuilderImpl;
10import tools.refinery.store.representation.AnySymbol; 11import tools.refinery.store.representation.AnySymbol;
11 12
12import java.util.Collection; 13import java.util.Collection;
13import java.util.Optional; 14import java.util.Optional;
14import java.util.Set;
15 15
16public interface ModelStore { 16public interface ModelStore {
17 Collection<AnySymbol> getSymbols(); 17 Collection<AnySymbol> getSymbols();
18 18
19 Model createEmptyModel(); 19 Model createEmptyModel();
20 20
21 Model createModelForState(long state); 21 Model createModelForState(Version state);
22 22
23 Set<Long> getStates(); 23 ModelDiffCursor getDiffCursor(Version from, Version to);
24
25 ModelDiffCursor getDiffCursor(long from, long to);
26 24
27 <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType); 25 <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType);
28 26
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java
index fdd4425e..3c94541f 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java
@@ -5,12 +5,12 @@
5 */ 5 */
6package tools.refinery.store.model; 6package tools.refinery.store.model;
7 7
8import tools.refinery.store.map.ContinousHashProvider; 8import tools.refinery.store.map.ContinuousHashProvider;
9import tools.refinery.store.tuple.Tuple; 9import tools.refinery.store.tuple.Tuple;
10import tools.refinery.store.tuple.Tuple1; 10import tools.refinery.store.tuple.Tuple1;
11import tools.refinery.store.tuple.Tuple2; 11import tools.refinery.store.tuple.Tuple2;
12 12
13public class TupleHashProvider implements ContinousHashProvider<Tuple> { 13public class TupleHashProvider implements ContinuousHashProvider<Tuple> {
14 protected static final int[] primes = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 14 protected static final int[] primes = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
15 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 15 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
16 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 16 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java
deleted file mode 100644
index 14116a90..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java
+++ /dev/null
@@ -1,34 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.model;
7
8import tools.refinery.store.map.ContinousHashProvider;
9import tools.refinery.store.tuple.Tuple;
10
11public class TupleHashProviderBitMagic implements ContinousHashProvider<Tuple> {
12
13 @Override
14 public int getHash(Tuple key, int index) {
15 if(key.getSize() == 1) {
16 return key.get(0);
17 }
18
19 int result = 0;
20 final int startBitIndex = index*30;
21 final int finalBitIndex = startBitIndex+30;
22 final int arity = key.getSize();
23
24 for(int i = startBitIndex; i<=finalBitIndex; i++) {
25 final int selectedKey = key.get(i%arity);
26 final int selectedPosition = 1<<(i/arity);
27 if((selectedKey&selectedPosition) != 0) {
28 result |= 1<<(i%30);
29 }
30 }
31
32 return result;
33 }
34}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java
index bf6987d6..92694af4 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java
@@ -8,6 +8,7 @@ package tools.refinery.store.model.internal;
8import tools.refinery.store.adapter.AdapterUtils; 8import tools.refinery.store.adapter.AdapterUtils;
9import tools.refinery.store.adapter.ModelAdapter; 9import tools.refinery.store.adapter.ModelAdapter;
10import tools.refinery.store.map.DiffCursor; 10import tools.refinery.store.map.DiffCursor;
11import tools.refinery.store.map.Version;
11import tools.refinery.store.model.*; 12import tools.refinery.store.model.*;
12import tools.refinery.store.representation.AnySymbol; 13import tools.refinery.store.representation.AnySymbol;
13import tools.refinery.store.representation.Symbol; 14import tools.refinery.store.representation.Symbol;
@@ -17,21 +18,21 @@ import java.util.*;
17 18
18public class ModelImpl implements Model { 19public class ModelImpl implements Model {
19 private final ModelStore store; 20 private final ModelStore store;
20 private long state; 21 private Version state;
21 private Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations; 22 private LinkedHashMap<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations;
22 private final List<ModelAdapter> adapters; 23 private final List<ModelAdapter> adapters;
23 private final List<ModelListener> listeners = new ArrayList<>(); 24 private final List<ModelListener> listeners = new ArrayList<>();
24 private boolean uncommittedChanges; 25 private boolean uncommittedChanges;
25 private ModelAction pendingAction = ModelAction.NONE; 26 private ModelAction pendingAction = ModelAction.NONE;
26 private long restoringToState = NO_STATE_ID; 27 private Version restoringToState = null;
27 28
28 ModelImpl(ModelStore store, long state, int adapterCount) { 29 ModelImpl(ModelStore store, Version state, int adapterCount) {
29 this.store = store; 30 this.store = store;
30 this.state = state; 31 this.state = state;
31 adapters = new ArrayList<>(adapterCount); 32 adapters = new ArrayList<>(adapterCount);
32 } 33 }
33 34
34 void setInterpretations(Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations) { 35 void setInterpretations(LinkedHashMap<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations) {
35 this.interpretations = interpretations; 36 this.interpretations = interpretations;
36 } 37 }
37 38
@@ -41,7 +42,7 @@ public class ModelImpl implements Model {
41 } 42 }
42 43
43 @Override 44 @Override
44 public long getState() { 45 public Version getState() {
45 return state; 46 return state;
46 } 47 }
47 48
@@ -57,7 +58,7 @@ public class ModelImpl implements Model {
57 } 58 }
58 59
59 @Override 60 @Override
60 public ModelDiffCursor getDiffCursor(long to) { 61 public ModelDiffCursor getDiffCursor(Version to) {
61 var diffCursors = new HashMap<AnySymbol, DiffCursor<Tuple, ?>>(interpretations.size()); 62 var diffCursors = new HashMap<AnySymbol, DiffCursor<Tuple, ?>>(interpretations.size());
62 for (var entry : interpretations.entrySet()) { 63 for (var entry : interpretations.entrySet()) {
63 diffCursors.put(entry.getKey(), entry.getValue().getDiffCursor(to)); 64 diffCursors.put(entry.getKey(), entry.getValue().getDiffCursor(to));
@@ -65,7 +66,7 @@ public class ModelImpl implements Model {
65 return new ModelDiffCursor(diffCursors); 66 return new ModelDiffCursor(diffCursors);
66 } 67 }
67 68
68 private void setState(long state) { 69 private void setState(Version state) {
69 this.state = state; 70 this.state = state;
70 uncommittedChanges = false; 71 uncommittedChanges = false;
71 } 72 }
@@ -82,11 +83,11 @@ public class ModelImpl implements Model {
82 } 83 }
83 84
84 private boolean hasPendingAction() { 85 private boolean hasPendingAction() {
85 return pendingAction != ModelAction.NONE || restoringToState != NO_STATE_ID; 86 return pendingAction != ModelAction.NONE || restoringToState != null;
86 } 87 }
87 88
88 @Override 89 @Override
89 public long commit() { 90 public Version commit() {
90 if (hasPendingAction()) { 91 if (hasPendingAction()) {
91 throw pendingActionError("commit"); 92 throw pendingActionError("commit");
92 } 93 }
@@ -94,43 +95,40 @@ public class ModelImpl implements Model {
94 try { 95 try {
95 int listenerCount = listeners.size(); 96 int listenerCount = listeners.size();
96 int i = listenerCount; 97 int i = listenerCount;
97 long version = 0; 98
99 // Before commit message to listeners
98 while (i > 0) { 100 while (i > 0) {
99 i--; 101 i--;
100 listeners.get(i).beforeCommit(); 102 listeners.get(i).beforeCommit();
101 } 103 }
102 boolean versionSet = false; 104
103 for (var interpretation : interpretations.values()) { 105 // Doing the commit on the interpretations
104 long newVersion = interpretation.commit(); 106 Version[] interpretationVersions = new Version[interpretations.size()];
105 if (versionSet) { 107 int j = 0;
106 if (version != newVersion) { 108 for(var interpretationEntry : interpretations.entrySet()) {
107 throw new IllegalStateException("Interpretations in model have different versions (%d and %d)" 109 interpretationVersions[j++] = interpretationEntry.getValue().commit();
108 .formatted(version, newVersion));
109 }
110 } else {
111 version = newVersion;
112 versionSet = true;
113 }
114 } 110 }
115 setState(version); 111 ModelVersion modelVersion = new ModelVersion(interpretationVersions);
112 setState(modelVersion);
113
114 // After commit message to listeners
116 while (i < listenerCount) { 115 while (i < listenerCount) {
117 listeners.get(i).afterCommit(); 116 listeners.get(i).afterCommit();
118 i++; 117 i++;
119 } 118 }
120 return version; 119
120 return modelVersion;
121 } finally { 121 } finally {
122 pendingAction = ModelAction.NONE; 122 pendingAction = ModelAction.NONE;
123 } 123 }
124 } 124 }
125 125
126 @Override 126 @Override
127 public void restore(long version) { 127 public void restore(Version version) {
128 if (hasPendingAction()) { 128 if (hasPendingAction()) {
129 throw pendingActionError("restore to %d".formatted(version)); 129 throw pendingActionError("restore to %s".formatted(version));
130 }
131 if (!store.getStates().contains(version)) {
132 throw new IllegalArgumentException("Store does not contain state %d".formatted(version));
133 } 130 }
131
134 pendingAction = ModelAction.RESTORE; 132 pendingAction = ModelAction.RESTORE;
135 restoringToState = version; 133 restoringToState = version;
136 try { 134 try {
@@ -140,9 +138,11 @@ public class ModelImpl implements Model {
140 i--; 138 i--;
141 listeners.get(i).beforeRestore(version); 139 listeners.get(i).beforeRestore(version);
142 } 140 }
141 int j = 0;
143 for (var interpretation : interpretations.values()) { 142 for (var interpretation : interpretations.values()) {
144 interpretation.restore(version); 143 interpretation.restore(ModelVersion.getInternalVersion(version,j++));
145 } 144 }
145
146 setState(version); 146 setState(version);
147 while (i < listenerCount) { 147 while (i < listenerCount) {
148 listeners.get(i).afterRestore(); 148 listeners.get(i).afterRestore();
@@ -150,7 +150,7 @@ public class ModelImpl implements Model {
150 } 150 }
151 } finally { 151 } finally {
152 pendingAction = ModelAction.NONE; 152 pendingAction = ModelAction.NONE;
153 restoringToState = NO_STATE_ID; 153 restoringToState = null;
154 } 154 }
155 } 155 }
156 156
@@ -159,7 +159,7 @@ public class ModelImpl implements Model {
159 case NONE -> throw new IllegalArgumentException("Trying to throw pending action error when there is no " + 159 case NONE -> throw new IllegalArgumentException("Trying to throw pending action error when there is no " +
160 "pending action"); 160 "pending action");
161 case COMMIT -> "commit"; 161 case COMMIT -> "commit";
162 case RESTORE -> "restore to %d".formatted(restoringToState); 162 case RESTORE -> "restore to %s".formatted(restoringToState);
163 }; 163 };
164 return new IllegalStateException("Cannot %s due to pending %s".formatted(currentActionName, pendingActionName)); 164 return new IllegalStateException("Cannot %s due to pending %s".formatted(currentActionName, pendingActionName));
165 } 165 }
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java
index 24d4088a..2bd187a8 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java
@@ -8,10 +8,10 @@ package tools.refinery.store.model.internal;
8import tools.refinery.store.adapter.AdapterUtils; 8import tools.refinery.store.adapter.AdapterUtils;
9import tools.refinery.store.adapter.ModelAdapterBuilder; 9import tools.refinery.store.adapter.ModelAdapterBuilder;
10import tools.refinery.store.map.VersionedMapStore; 10import tools.refinery.store.map.VersionedMapStore;
11import tools.refinery.store.map.VersionedMapStoreImpl; 11import tools.refinery.store.map.VersionedMapStoreFactory;
12import tools.refinery.store.map.VersionedMapStoreFactoryBuilder;
12import tools.refinery.store.model.ModelStore; 13import tools.refinery.store.model.ModelStore;
13import tools.refinery.store.model.ModelStoreBuilder; 14import tools.refinery.store.model.ModelStoreBuilder;
14import tools.refinery.store.model.TupleHashProvider;
15import tools.refinery.store.representation.AnySymbol; 15import tools.refinery.store.representation.AnySymbol;
16import tools.refinery.store.representation.Symbol; 16import tools.refinery.store.representation.Symbol;
17import tools.refinery.store.tuple.Tuple; 17import tools.refinery.store.tuple.Tuple;
@@ -19,8 +19,8 @@ import tools.refinery.store.tuple.Tuple;
19import java.util.*; 19import java.util.*;
20 20
21public class ModelStoreBuilderImpl implements ModelStoreBuilder { 21public class ModelStoreBuilderImpl implements ModelStoreBuilder {
22 private final Set<AnySymbol> allSymbols = new HashSet<>(); 22 private final LinkedHashSet<AnySymbol> allSymbols = new LinkedHashSet<>();
23 private final Map<SymbolEquivalenceClass<?>, List<AnySymbol>> equivalenceClasses = new HashMap<>(); 23 private final LinkedHashMap<SymbolEquivalenceClass<?>, List<AnySymbol>> equivalenceClasses = new LinkedHashMap<>();
24 private final List<ModelAdapterBuilder> adapters = new ArrayList<>(); 24 private final List<ModelAdapterBuilder> adapters = new ArrayList<>();
25 25
26 @Override 26 @Override
@@ -62,7 +62,7 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder {
62 for (int i = adapters.size() - 1; i >= 0; i--) { 62 for (int i = adapters.size() - 1; i >= 0; i--) {
63 adapters.get(i).configure(this); 63 adapters.get(i).configure(this);
64 } 64 }
65 var stores = new HashMap<AnySymbol, VersionedMapStore<Tuple, ?>>(allSymbols.size()); 65 var stores = new LinkedHashMap<AnySymbol, VersionedMapStore<Tuple, ?>>(allSymbols.size());
66 for (var entry : equivalenceClasses.entrySet()) { 66 for (var entry : equivalenceClasses.entrySet()) {
67 createStores(stores, entry.getKey(), entry.getValue()); 67 createStores(stores, entry.getKey(), entry.getValue());
68 } 68 }
@@ -77,8 +77,12 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder {
77 private <T> void createStores(Map<AnySymbol, VersionedMapStore<Tuple, ?>> stores, 77 private <T> void createStores(Map<AnySymbol, VersionedMapStore<Tuple, ?>> stores,
78 SymbolEquivalenceClass<T> equivalenceClass, List<AnySymbol> symbols) { 78 SymbolEquivalenceClass<T> equivalenceClass, List<AnySymbol> symbols) {
79 int size = symbols.size(); 79 int size = symbols.size();
80 var storeGroup = VersionedMapStoreImpl.createSharedVersionedMapStores(size, TupleHashProvider.INSTANCE, 80 VersionedMapStoreFactory<Tuple,T> mapFactory = VersionedMapStore
81 equivalenceClass.defaultValue()); 81 .<Tuple,T>builder()
82 .strategy(VersionedMapStoreFactoryBuilder.StoreStrategy.DELTA)
83 .defaultValue(equivalenceClass.defaultValue())
84 .build();
85 var storeGroup = mapFactory.createGroup(size);
82 for (int i = 0; i < size; i++) { 86 for (int i = 0; i < size; i++) {
83 stores.put(symbols.get(i), storeGroup.get(i)); 87 stores.put(symbols.get(i), storeGroup.get(i));
84 } 88 }
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java
index 60b735e6..a320a618 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java
@@ -8,8 +8,8 @@ package tools.refinery.store.model.internal;
8import tools.refinery.store.adapter.AdapterUtils; 8import tools.refinery.store.adapter.AdapterUtils;
9import tools.refinery.store.adapter.ModelStoreAdapter; 9import tools.refinery.store.adapter.ModelStoreAdapter;
10import tools.refinery.store.map.DiffCursor; 10import tools.refinery.store.map.DiffCursor;
11import tools.refinery.store.map.Version;
11import tools.refinery.store.map.VersionedMapStore; 12import tools.refinery.store.map.VersionedMapStore;
12import tools.refinery.store.model.Model;
13import tools.refinery.store.model.ModelDiffCursor; 13import tools.refinery.store.model.ModelDiffCursor;
14import tools.refinery.store.model.ModelStore; 14import tools.refinery.store.model.ModelStore;
15import tools.refinery.store.representation.AnySymbol; 15import tools.refinery.store.representation.AnySymbol;
@@ -18,10 +18,10 @@ import tools.refinery.store.tuple.Tuple;
18import java.util.*; 18import java.util.*;
19 19
20public class ModelStoreImpl implements ModelStore { 20public class ModelStoreImpl implements ModelStore {
21 private final Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores; 21 private final LinkedHashMap<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores;
22 private final List<ModelStoreAdapter> adapters; 22 private final List<ModelStoreAdapter> adapters;
23 23
24 ModelStoreImpl(Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores, int adapterCount) { 24 ModelStoreImpl(LinkedHashMap<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores, int adapterCount) {
25 this.stores = stores; 25 this.stores = stores;
26 adapters = new ArrayList<>(adapterCount); 26 adapters = new ArrayList<>(adapterCount);
27 } 27 }
@@ -31,14 +31,14 @@ public class ModelStoreImpl implements ModelStore {
31 return Collections.unmodifiableCollection(stores.keySet()); 31 return Collections.unmodifiableCollection(stores.keySet());
32 } 32 }
33 33
34 private ModelImpl createModelWithoutInterpretations(long state) { 34 private ModelImpl createModelWithoutInterpretations(Version state) {
35 return new ModelImpl(this, state, adapters.size()); 35 return new ModelImpl(this, state, adapters.size());
36 } 36 }
37 37
38 @Override 38 @Override
39 public ModelImpl createEmptyModel() { 39 public ModelImpl createEmptyModel() {
40 var model = createModelWithoutInterpretations(Model.NO_STATE_ID); 40 var model = createModelWithoutInterpretations(null);
41 var interpretations = new HashMap<AnySymbol, VersionedInterpretation<?>>(stores.size()); 41 var interpretations = new LinkedHashMap<AnySymbol, VersionedInterpretation<?>>(stores.size());
42 for (var entry : this.stores.entrySet()) { 42 for (var entry : this.stores.entrySet()) {
43 var symbol = entry.getKey(); 43 var symbol = entry.getKey();
44 interpretations.put(symbol, VersionedInterpretation.of(model, symbol, entry.getValue())); 44 interpretations.put(symbol, VersionedInterpretation.of(model, symbol, entry.getValue()));
@@ -49,13 +49,21 @@ public class ModelStoreImpl implements ModelStore {
49 } 49 }
50 50
51 @Override 51 @Override
52 public synchronized ModelImpl createModelForState(long state) { 52 public synchronized ModelImpl createModelForState(Version state) {
53 var model = createModelWithoutInterpretations(state); 53 var model = createModelWithoutInterpretations(state);
54 var interpretations = new HashMap<AnySymbol, VersionedInterpretation<?>>(stores.size()); 54 var interpretations = new LinkedHashMap<AnySymbol, VersionedInterpretation<?>>(stores.size());
55
56 int i=0;
55 for (var entry : this.stores.entrySet()) { 57 for (var entry : this.stores.entrySet()) {
56 var symbol = entry.getKey(); 58 var symbol = entry.getKey();
57 interpretations.put(symbol, VersionedInterpretation.of(model, symbol, entry.getValue(), state)); 59 interpretations.put(symbol,
60 VersionedInterpretation.of(
61 model,
62 symbol,
63 entry.getValue(),
64 ModelVersion.getInternalVersion(state,i++)));
58 } 65 }
66
59 model.setInterpretations(interpretations); 67 model.setInterpretations(interpretations);
60 adaptModel(model); 68 adaptModel(model);
61 return model; 69 return model;
@@ -69,16 +77,7 @@ public class ModelStoreImpl implements ModelStore {
69 } 77 }
70 78
71 @Override 79 @Override
72 public synchronized Set<Long> getStates() { 80 public synchronized ModelDiffCursor getDiffCursor(Version from, Version to) {
73 var iterator = stores.values().iterator();
74 if (iterator.hasNext()) {
75 return Set.copyOf(iterator.next().getStates());
76 }
77 return Set.of(0L);
78 }
79
80 @Override
81 public synchronized ModelDiffCursor getDiffCursor(long from, long to) {
82 var diffCursors = new HashMap<AnySymbol, DiffCursor<?, ?>>(); 81 var diffCursors = new HashMap<AnySymbol, DiffCursor<?, ?>>();
83 for (var entry : stores.entrySet()) { 82 for (var entry : stores.entrySet()) {
84 var representation = entry.getKey(); 83 var representation = entry.getKey();
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelVersion.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelVersion.java
new file mode 100644
index 00000000..cf3b7fc6
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelVersion.java
@@ -0,0 +1,39 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.model.internal;
7
8import tools.refinery.store.map.Version;
9
10import java.util.Arrays;
11
12public record ModelVersion(Version[] mapVersions) implements Version{
13
14 public static Version getInternalVersion(Version modelVersion, int interpretationIndex) {
15 return ((ModelVersion)modelVersion).mapVersions()[interpretationIndex];
16 }
17
18 @Override
19 public int hashCode() {
20 return Arrays.hashCode(mapVersions);
21 }
22
23 @Override
24 public boolean equals(Object o) {
25 if (this == o) return true;
26 if (o == null || getClass() != o.getClass()) return false;
27
28 ModelVersion that = (ModelVersion) o;
29
30 return Arrays.equals(mapVersions, that.mapVersions);
31 }
32
33 @Override
34 public String toString() {
35 return "ModelVersion{" +
36 "mapVersions=" + Arrays.toString(mapVersions) +
37 '}';
38 }
39}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java
index 404be65f..76e3baea 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java
@@ -5,10 +5,7 @@
5 */ 5 */
6package tools.refinery.store.model.internal; 6package tools.refinery.store.model.internal;
7 7
8import tools.refinery.store.map.Cursor; 8import tools.refinery.store.map.*;
9import tools.refinery.store.map.DiffCursor;
10import tools.refinery.store.map.VersionedMap;
11import tools.refinery.store.map.VersionedMapStore;
12import tools.refinery.store.model.Interpretation; 9import tools.refinery.store.model.Interpretation;
13import tools.refinery.store.model.InterpretationListener; 10import tools.refinery.store.model.InterpretationListener;
14import tools.refinery.store.model.Model; 11import tools.refinery.store.model.Model;
@@ -110,15 +107,14 @@ public class VersionedInterpretation<T> implements Interpretation<T> {
110 } 107 }
111 108
112 @Override 109 @Override
113 public DiffCursor<Tuple, T> getDiffCursor(long to) { 110 public DiffCursor<Tuple, T> getDiffCursor(Version to) {
114 return map.getDiffCursor(to); 111 return map.getDiffCursor(to);
115 } 112 }
116 113
117 public long commit() { 114 Version commit() {
118 return map.commit(); 115 return map.commit();
119 } 116 }
120 117 void restore(Version state) {
121 public void restore(long state) {
122 if (!restoreListeners.isEmpty()) { 118 if (!restoreListeners.isEmpty()) {
123 var diffCursor = getDiffCursor(state); 119 var diffCursor = getDiffCursor(state);
124 while (diffCursor.move()) { 120 while (diffCursor.move()) {
@@ -150,7 +146,7 @@ public class VersionedInterpretation<T> implements Interpretation<T> {
150 } 146 }
151 147
152 static <T> VersionedInterpretation<T> of(ModelImpl model, AnySymbol symbol, VersionedMapStore<Tuple, T> store, 148 static <T> VersionedInterpretation<T> of(ModelImpl model, AnySymbol symbol, VersionedMapStore<Tuple, T> store,
153 long state) { 149 Version state) {
154 @SuppressWarnings("unchecked") 150 @SuppressWarnings("unchecked")
155 var typedSymbol = (Symbol<T>) symbol; 151 var typedSymbol = (Symbol<T>) symbol;
156 var map = store.createMap(state); 152 var map = store.createMap(state);