diff options
author | 2023-08-02 13:08:10 +0200 | |
---|---|---|
committer | 2023-08-02 13:08:10 +0200 | |
commit | 2c303ec940651895ad76a92c0080c707058167ef (patch) | |
tree | 7ba94f9d94593ff3fa7d6a814dc5896d823719e7 /subprojects/store/src/main/java/tools | |
parent | Update CRA test case (diff) | |
parent | Merge pull request #31 from OszkarSemerath/datastructure (diff) | |
download | refinery-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')
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 | */ |
6 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
7 | 7 | ||
8 | import tools.refinery.store.map.internal.Node; | 8 | import 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 | */ |
18 | public interface ContinousHashProvider<K> { | 18 | public 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map; |
7 | 7 | ||
8 | import java.util.*; | 8 | import java.util.Iterator; |
9 | import java.util.Map; | ||
9 | import java.util.Map.Entry; | 10 | import java.util.Map.Entry; |
10 | 11 | import java.util.Set; | |
11 | import tools.refinery.store.map.AnyVersionedMap; | ||
12 | import tools.refinery.store.map.Cursor; | ||
13 | import tools.refinery.store.map.VersionedMap; | ||
14 | 12 | ||
15 | public class IteratorAsCursor<K, V> implements Cursor<K, V> { | 13 | public 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 | */ | ||
6 | package tools.refinery.store.map; | ||
7 | |||
8 | /** | ||
9 | * Interface denoting versions of {@link Versioned}. | ||
10 | */ | ||
11 | public 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 | */ |
6 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
7 | 7 | ||
8 | /** | ||
9 | * Object that can save and restore its state. | ||
10 | */ | ||
8 | public interface Versioned { | 11 | public 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 | ||
8 | import tools.refinery.store.map.internal.VersionedMapStoreFactoryBuilderImpl; | 8 | import tools.refinery.store.map.internal.VersionedMapStoreFactoryBuilderImpl; |
9 | 9 | ||
10 | import java.util.Set; | ||
11 | |||
12 | public interface VersionedMapStore<K, V> { | 10 | public 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 | */ | ||
6 | package tools.refinery.store.map; | ||
7 | |||
8 | import tools.refinery.store.map.internal.*; | ||
9 | |||
10 | import java.util.*; | ||
11 | |||
12 | public 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 | */ | ||
6 | package tools.refinery.store.map.internal; | ||
7 | |||
8 | enum 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 | */ | ||
6 | package tools.refinery.store.map.internal; | ||
7 | |||
8 | import tools.refinery.store.map.*; | ||
9 | |||
10 | import java.util.List; | ||
11 | |||
12 | public 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
7 | 7 | ||
8 | import tools.refinery.store.map.ContinousHashProvider; | 8 | import tools.refinery.store.map.ContinuousHashProvider; |
9 | import tools.refinery.store.map.VersionedMapStoreFactory; | 9 | import tools.refinery.store.map.VersionedMapStoreFactory; |
10 | import tools.refinery.store.map.VersionedMapStoreFactoryBuilder; | 10 | import tools.refinery.store.map.VersionedMapStoreFactoryBuilder; |
11 | import tools.refinery.store.map.internal.delta.DeltaBasedVersionedMapStoreFactory; | ||
12 | import tools.refinery.store.map.internal.state.StateBasedVersionedMapStoreFactory; | ||
11 | 13 | ||
12 | public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapStoreFactoryBuilder<K, V> { | 14 | public 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.delta; |
7 | 7 | ||
8 | import tools.refinery.store.map.VersionedMapStore; | 8 | import tools.refinery.store.map.VersionedMapStore; |
9 | import tools.refinery.store.map.VersionedMapStoreDeltaImpl; | ||
10 | import tools.refinery.store.map.VersionedMapStoreFactory; | 9 | import tools.refinery.store.map.VersionedMapStoreFactory; |
11 | import tools.refinery.store.map.VersionedMapStoreFactoryBuilder; | 10 | import 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.delta; |
7 | 7 | ||
8 | import tools.refinery.store.map.AnyVersionedMap; | 8 | import tools.refinery.store.map.AnyVersionedMap; |
9 | import tools.refinery.store.map.DiffCursor; | 9 | import 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.delta; |
7 | 7 | ||
8 | public record MapDelta<K, V>(K key, V oldValue, V newValue) { | 8 | public 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.delta; |
7 | |||
8 | import tools.refinery.store.map.Version; | ||
7 | 9 | ||
8 | import java.util.Arrays; | 10 | import java.util.Arrays; |
9 | import java.util.Objects; | 11 | import java.util.Objects; |
10 | 12 | ||
11 | public record MapTransaction<K, V>(MapDelta<K, V>[] deltas, long version, MapTransaction<K, V> parent) { | 13 | public 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.delta; |
7 | 7 | ||
8 | import java.util.ArrayList; | 8 | import java.util.ArrayList; |
9 | import java.util.List; | 9 | import 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.delta; |
7 | 7 | ||
8 | import java.util.*; | 8 | import java.util.*; |
9 | import java.util.Map.Entry; | 9 | import 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.delta; |
7 | 7 | ||
8 | public interface UncommittedDeltaStore<K, V> { | 8 | public 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.delta; |
7 | 7 | ||
8 | import java.util.*; | 8 | import java.util.*; |
9 | 9 | ||
10 | import tools.refinery.store.map.*; | 10 | import tools.refinery.store.map.*; |
11 | import tools.refinery.store.map.IteratorAsCursor; | ||
11 | 12 | ||
12 | public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> { | 13 | public 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 | */ |
6 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map.internal.delta; |
7 | 7 | ||
8 | import java.util.*; | 8 | import tools.refinery.store.map.DiffCursor; |
9 | import tools.refinery.store.map.Version; | ||
10 | import tools.refinery.store.map.VersionedMap; | ||
11 | import tools.refinery.store.map.VersionedMapStore; | ||
9 | 12 | ||
10 | import tools.refinery.store.map.internal.*; | 13 | import java.util.*; |
11 | 14 | ||
12 | public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V> { | 15 | public 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.state; |
7 | 7 | ||
8 | import java.util.Arrays; | 8 | import java.util.Arrays; |
9 | import java.util.Map; | 9 | import java.util.Map; |
10 | 10 | ||
11 | import tools.refinery.store.map.ContinousHashProvider; | 11 | import tools.refinery.store.map.ContinuousHashProvider; |
12 | import tools.refinery.store.map.Version; | ||
12 | 13 | ||
13 | public class ImmutableNode<K, V> extends Node<K, V> { | 14 | public 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.state; |
7 | 7 | ||
8 | import tools.refinery.store.map.AnyVersionedMap; | 8 | import tools.refinery.store.map.AnyVersionedMap; |
9 | import tools.refinery.store.map.ContentHashCode; | 9 | import 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.state; |
7 | 7 | ||
8 | import tools.refinery.store.map.AnyVersionedMap; | 8 | import tools.refinery.store.map.AnyVersionedMap; |
9 | import tools.refinery.store.map.ContentHashCode; | 9 | import 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.state; |
7 | 7 | ||
8 | import tools.refinery.store.map.AnyVersionedMap; | 8 | import tools.refinery.store.map.AnyVersionedMap; |
9 | import tools.refinery.store.map.Cursor; | 9 | import 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.state; |
7 | 7 | ||
8 | import tools.refinery.store.map.ContinousHashProvider; | 8 | import tools.refinery.store.map.ContinuousHashProvider; |
9 | 9 | ||
10 | import java.util.Arrays; | 10 | import java.util.Arrays; |
11 | import java.util.Map; | 11 | import 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.state; |
7 | 7 | ||
8 | import java.util.Map; | 8 | import java.util.Map; |
9 | 9 | ||
10 | import tools.refinery.store.map.ContinousHashProvider; | 10 | import tools.refinery.store.map.ContinuousHashProvider; |
11 | 11 | ||
12 | public abstract class Node<K, V> { | 12 | public 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.state; |
7 | 7 | ||
8 | public class OldValueBox<V>{ | 8 | public 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 | */ | ||
6 | package tools.refinery.store.map.internal.state; | ||
7 | |||
8 | import tools.refinery.store.map.*; | ||
9 | |||
10 | import java.util.List; | ||
11 | |||
12 | public 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 | */ |
6 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal.state; |
7 | 7 | ||
8 | import tools.refinery.store.map.*; | 8 | import 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 | */ |
22 | public class VersionedMapImpl<K, V> implements VersionedMap<K, V> { | 22 | public 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 | */ |
6 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map.internal.state; |
7 | 7 | ||
8 | public class VersionedMapStoreConfiguration { | 8 | import tools.refinery.store.map.ContinuousHashProvider; |
9 | import tools.refinery.store.map.VersionedMapStore; | ||
9 | 10 | ||
10 | public VersionedMapStoreConfiguration() { | 11 | public 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 | */ | ||
6 | package tools.refinery.store.map.internal.state; | ||
7 | |||
8 | import tools.refinery.store.map.*; | ||
9 | |||
10 | import java.util.*; | ||
11 | |||
12 | public 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 | ||
8 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
9 | import tools.refinery.store.map.DiffCursor; | 9 | import tools.refinery.store.map.DiffCursor; |
10 | import tools.refinery.store.map.Version; | ||
10 | import tools.refinery.store.representation.Symbol; | 11 | import tools.refinery.store.representation.Symbol; |
11 | import tools.refinery.store.tuple.Tuple; | 12 | import 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 @@ | |||
6 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
7 | 7 | ||
8 | import tools.refinery.store.adapter.ModelAdapter; | 8 | import tools.refinery.store.adapter.ModelAdapter; |
9 | import tools.refinery.store.map.Version; | ||
9 | import tools.refinery.store.map.Versioned; | 10 | import tools.refinery.store.map.Versioned; |
10 | import tools.refinery.store.model.internal.VersionedInterpretation; | 11 | import tools.refinery.store.model.internal.VersionedInterpretation; |
11 | import tools.refinery.store.representation.AnySymbol; | 12 | import tools.refinery.store.representation.AnySymbol; |
@@ -15,11 +16,10 @@ import java.util.Map; | |||
15 | import java.util.Optional; | 16 | import java.util.Optional; |
16 | 17 | ||
17 | public interface Model extends Versioned { | 18 | public 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 | */ |
6 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
7 | 7 | ||
8 | import tools.refinery.store.map.Version; | ||
9 | |||
8 | public interface ModelListener { | 10 | public 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 @@ | |||
6 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
7 | 7 | ||
8 | import tools.refinery.store.adapter.ModelStoreAdapter; | 8 | import tools.refinery.store.adapter.ModelStoreAdapter; |
9 | import tools.refinery.store.map.Version; | ||
9 | import tools.refinery.store.model.internal.ModelStoreBuilderImpl; | 10 | import tools.refinery.store.model.internal.ModelStoreBuilderImpl; |
10 | import tools.refinery.store.representation.AnySymbol; | 11 | import tools.refinery.store.representation.AnySymbol; |
11 | 12 | ||
12 | import java.util.Collection; | 13 | import java.util.Collection; |
13 | import java.util.Optional; | 14 | import java.util.Optional; |
14 | import java.util.Set; | ||
15 | 15 | ||
16 | public interface ModelStore { | 16 | public 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 | */ |
6 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
7 | 7 | ||
8 | import tools.refinery.store.map.ContinousHashProvider; | 8 | import tools.refinery.store.map.ContinuousHashProvider; |
9 | import tools.refinery.store.tuple.Tuple; | 9 | import tools.refinery.store.tuple.Tuple; |
10 | import tools.refinery.store.tuple.Tuple1; | 10 | import tools.refinery.store.tuple.Tuple1; |
11 | import tools.refinery.store.tuple.Tuple2; | 11 | import tools.refinery.store.tuple.Tuple2; |
12 | 12 | ||
13 | public class TupleHashProvider implements ContinousHashProvider<Tuple> { | 13 | public 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 | */ | ||
6 | package tools.refinery.store.model; | ||
7 | |||
8 | import tools.refinery.store.map.ContinousHashProvider; | ||
9 | import tools.refinery.store.tuple.Tuple; | ||
10 | |||
11 | public 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; | |||
8 | import tools.refinery.store.adapter.AdapterUtils; | 8 | import tools.refinery.store.adapter.AdapterUtils; |
9 | import tools.refinery.store.adapter.ModelAdapter; | 9 | import tools.refinery.store.adapter.ModelAdapter; |
10 | import tools.refinery.store.map.DiffCursor; | 10 | import tools.refinery.store.map.DiffCursor; |
11 | import tools.refinery.store.map.Version; | ||
11 | import tools.refinery.store.model.*; | 12 | import tools.refinery.store.model.*; |
12 | import tools.refinery.store.representation.AnySymbol; | 13 | import tools.refinery.store.representation.AnySymbol; |
13 | import tools.refinery.store.representation.Symbol; | 14 | import tools.refinery.store.representation.Symbol; |
@@ -17,21 +18,21 @@ import java.util.*; | |||
17 | 18 | ||
18 | public class ModelImpl implements Model { | 19 | public 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; | |||
8 | import tools.refinery.store.adapter.AdapterUtils; | 8 | import tools.refinery.store.adapter.AdapterUtils; |
9 | import tools.refinery.store.adapter.ModelAdapterBuilder; | 9 | import tools.refinery.store.adapter.ModelAdapterBuilder; |
10 | import tools.refinery.store.map.VersionedMapStore; | 10 | import tools.refinery.store.map.VersionedMapStore; |
11 | import tools.refinery.store.map.VersionedMapStoreImpl; | 11 | import tools.refinery.store.map.VersionedMapStoreFactory; |
12 | import tools.refinery.store.map.VersionedMapStoreFactoryBuilder; | ||
12 | import tools.refinery.store.model.ModelStore; | 13 | import tools.refinery.store.model.ModelStore; |
13 | import tools.refinery.store.model.ModelStoreBuilder; | 14 | import tools.refinery.store.model.ModelStoreBuilder; |
14 | import tools.refinery.store.model.TupleHashProvider; | ||
15 | import tools.refinery.store.representation.AnySymbol; | 15 | import tools.refinery.store.representation.AnySymbol; |
16 | import tools.refinery.store.representation.Symbol; | 16 | import tools.refinery.store.representation.Symbol; |
17 | import tools.refinery.store.tuple.Tuple; | 17 | import tools.refinery.store.tuple.Tuple; |
@@ -19,8 +19,8 @@ import tools.refinery.store.tuple.Tuple; | |||
19 | import java.util.*; | 19 | import java.util.*; |
20 | 20 | ||
21 | public class ModelStoreBuilderImpl implements ModelStoreBuilder { | 21 | public 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; | |||
8 | import tools.refinery.store.adapter.AdapterUtils; | 8 | import tools.refinery.store.adapter.AdapterUtils; |
9 | import tools.refinery.store.adapter.ModelStoreAdapter; | 9 | import tools.refinery.store.adapter.ModelStoreAdapter; |
10 | import tools.refinery.store.map.DiffCursor; | 10 | import tools.refinery.store.map.DiffCursor; |
11 | import tools.refinery.store.map.Version; | ||
11 | import tools.refinery.store.map.VersionedMapStore; | 12 | import tools.refinery.store.map.VersionedMapStore; |
12 | import tools.refinery.store.model.Model; | ||
13 | import tools.refinery.store.model.ModelDiffCursor; | 13 | import tools.refinery.store.model.ModelDiffCursor; |
14 | import tools.refinery.store.model.ModelStore; | 14 | import tools.refinery.store.model.ModelStore; |
15 | import tools.refinery.store.representation.AnySymbol; | 15 | import tools.refinery.store.representation.AnySymbol; |
@@ -18,10 +18,10 @@ import tools.refinery.store.tuple.Tuple; | |||
18 | import java.util.*; | 18 | import java.util.*; |
19 | 19 | ||
20 | public class ModelStoreImpl implements ModelStore { | 20 | public 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 | */ | ||
6 | package tools.refinery.store.model.internal; | ||
7 | |||
8 | import tools.refinery.store.map.Version; | ||
9 | |||
10 | import java.util.Arrays; | ||
11 | |||
12 | public 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 | */ |
6 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
7 | 7 | ||
8 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.*; |
9 | import tools.refinery.store.map.DiffCursor; | ||
10 | import tools.refinery.store.map.VersionedMap; | ||
11 | import tools.refinery.store.map.VersionedMapStore; | ||
12 | import tools.refinery.store.model.Interpretation; | 9 | import tools.refinery.store.model.Interpretation; |
13 | import tools.refinery.store.model.InterpretationListener; | 10 | import tools.refinery.store.model.InterpretationListener; |
14 | import tools.refinery.store.model.Model; | 11 | import 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); |