aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/DesignSpaceExplorationAdapter.java7
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/internal/DesignSpaceExplorationAdapterImpl.java22
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/strategy/BestFirstStrategy.java7
-rw-r--r--subprojects/store/src/jmh/java/tools/refinery/store/map/benchmarks/ImmutablePutExecutionPlan.java17
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/ContinuousHashProvider.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java)14
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/IteratorAsCursor.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/IteratorAsCursor.java)12
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/Version.java26
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java18
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java2
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java8
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreFactoryBuilder.java3
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java129
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java23
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/StateBasedVersionedMapStoreFactory.java38
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapStoreFactoryBuilderImpl.java39
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/DeltaBasedVersionedMapStoreFactory.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/DeltaBasedVersionedMapStoreFactory.java)5
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/DeltaDiffCursor.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/DeltaDiffCursor.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/MapDelta.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDelta.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/MapTransaction.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/MapTransaction.java)14
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaArrayStore.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaArrayStore.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaMapStore.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaMapStore.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaStore.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaStore.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/VersionedMapDeltaImpl.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapDeltaImpl.java)39
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/VersionedMapStoreDeltaImpl.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreDeltaImpl.java)51
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/ImmutableNode.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java)19
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/InOrderMapCursor.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/InOrderMapCursor.java)6
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MapCursor.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MapDiffCursor.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java)4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MutableNode.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java)18
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/Node.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java)18
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/OldValueBox.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java)6
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/StateBasedVersionedMapStoreFactory.java43
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStateImpl.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java)34
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateConfiguration.java (renamed from subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java)25
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateImpl.java119
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java3
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/Model.java10
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java8
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java34
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java66
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java18
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java37
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelVersion.java39
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java14
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/map/tests/InOrderCursorTest.java8
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java4
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/DiffCursorFuzzTest.java21
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MultiThreadTestRunnable.java16
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MutableImmutableCompareFuzzTest.java18
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/RestoreFuzzTest.java5
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/SharedStoreFuzzTest.java23
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/utils/FuzzTestCollections.java13
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java8
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/model/hashtests/HashEfficiencyTest.java13
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java5
-rw-r--r--subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerAdapter.java11
-rw-r--r--subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java40
59 files changed, 643 insertions, 569 deletions
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/DesignSpaceExplorationAdapter.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/DesignSpaceExplorationAdapter.java
index 4cfca210..ca780855 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/DesignSpaceExplorationAdapter.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/DesignSpaceExplorationAdapter.java
@@ -1,6 +1,7 @@
1package tools.refinery.store.query.dse; 1package tools.refinery.store.query.dse;
2 2
3import tools.refinery.store.adapter.ModelAdapter; 3import tools.refinery.store.adapter.ModelAdapter;
4import tools.refinery.store.map.Version;
4import tools.refinery.store.query.dse.internal.Activation; 5import tools.refinery.store.query.dse.internal.Activation;
5import tools.refinery.store.query.dse.internal.DesignSpaceExplorationBuilderImpl; 6import tools.refinery.store.query.dse.internal.DesignSpaceExplorationBuilderImpl;
6import tools.refinery.store.query.dse.objectives.Fitness; 7import tools.refinery.store.query.dse.objectives.Fitness;
@@ -20,7 +21,7 @@ public interface DesignSpaceExplorationAdapter extends ModelAdapter {
20 return new DesignSpaceExplorationBuilderImpl(); 21 return new DesignSpaceExplorationBuilderImpl();
21 } 22 }
22 23
23 Collection<Long> explore(); 24 Collection<Version> explore();
24 25
25 public int getModelSize(); 26 public int getModelSize();
26 27
@@ -46,13 +47,13 @@ public interface DesignSpaceExplorationAdapter extends ModelAdapter {
46 47
47 public boolean isCurrentInTrajectory(); 48 public boolean isCurrentInTrajectory();
48 49
49 public List<Long> getTrajectory(); 50 public List<Version> getTrajectory();
50 51
51 public boolean isCurrentStateAlreadyTraversed(); 52 public boolean isCurrentStateAlreadyTraversed();
52 53
53 public ObjectiveComparatorHelper getObjectiveComparatorHelper(); 54 public ObjectiveComparatorHelper getObjectiveComparatorHelper();
54 55
55 public void restoreTrajectory(List<Long> trajectory); 56 public void restoreTrajectory(List<Version> trajectory);
56 57
57 public void setRandom(Random random); 58 public void setRandom(Random random);
58 59
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/internal/DesignSpaceExplorationAdapterImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/internal/DesignSpaceExplorationAdapterImpl.java
index fbed0465..d2a8e6fa 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/internal/DesignSpaceExplorationAdapterImpl.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/internal/DesignSpaceExplorationAdapterImpl.java
@@ -1,5 +1,6 @@
1package tools.refinery.store.query.dse.internal; 1package tools.refinery.store.query.dse.internal;
2 2
3import tools.refinery.store.map.Version;
3import tools.refinery.store.model.Interpretation; 4import tools.refinery.store.model.Interpretation;
4import tools.refinery.store.model.Model; 5import tools.refinery.store.model.Model;
5import tools.refinery.store.query.ModelQueryAdapter; 6import tools.refinery.store.query.ModelQueryAdapter;
@@ -31,17 +32,17 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
31 private final Strategy strategy; 32 private final Strategy strategy;
32 33
33 private ObjectiveComparatorHelper objectiveComparatorHelper; 34 private ObjectiveComparatorHelper objectiveComparatorHelper;
34 private List<Long> trajectory = new LinkedList<>(); 35 private List<Version> trajectory = new LinkedList<>();
35 private Fitness lastFitness; 36 private Fitness lastFitness;
36 private final LinkedHashSet<Long> solutions = new LinkedHashSet<>(); 37 private final LinkedHashSet<Version> solutions = new LinkedHashSet<>();
37 private Map<Long, LinkedHashSet<Activation>> statesAndUntraversedActivations; 38 private Map<Version, LinkedHashSet<Activation>> statesAndUntraversedActivations;
38 private Map<Long, LinkedHashSet<Activation>> statesAndTraversedActivations; 39 private Map<Version, LinkedHashSet<Activation>> statesAndTraversedActivations;
39 private Random random = new Random(); 40 private Random random = new Random();
40 private boolean isNewState = false; 41 private boolean isNewState = false;
41 private final boolean isVisualizationEnabled; 42 private final boolean isVisualizationEnabled;
42 private final ModelVisualizerAdapter modelVisualizerAdapter; 43 private final ModelVisualizerAdapter modelVisualizerAdapter;
43 44
44 public List<Long> getTrajectory() { 45 public List<Version> getTrajectory() {
45 return new LinkedList<>(trajectory); 46 return new LinkedList<>(trajectory);
46 } 47 }
47 48
@@ -81,7 +82,7 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
81 } 82 }
82 83
83 @Override 84 @Override
84 public LinkedHashSet<Long> explore() { 85 public LinkedHashSet<Version> explore() {
85 var state = model.commit(); 86 var state = model.commit();
86 trajectory.add(state); 87 trajectory.add(state);
87 statesAndUntraversedActivations.put(state, getAllActivations()); 88 statesAndUntraversedActivations.put(state, getAllActivations());
@@ -140,7 +141,7 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
140 } 141 }
141 142
142 @Override 143 @Override
143 public void restoreTrajectory(List<Long> trajectory) { 144 public void restoreTrajectory(List<Version> trajectory) {
144 model.restore(trajectory.get(trajectory.size() - 1)); 145 model.restore(trajectory.get(trajectory.size() - 1));
145// if (isVisualizationEnabled) { 146// if (isVisualizationEnabled) {
146// modelVisualizerAdapter.addTransition(this.trajectory.get(trajectory.size() - 1), 147// modelVisualizerAdapter.addTransition(this.trajectory.get(trajectory.size() - 1),
@@ -209,7 +210,7 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
209 if (activation == null) { 210 if (activation == null) {
210 return false; 211 return false;
211 } 212 }
212 long previousState = model.getState(); 213 var previousState = model.getState();
213 if (!statesAndUntraversedActivations.get(previousState).contains(activation)) { 214 if (!statesAndUntraversedActivations.get(previousState).contains(activation)) {
214// TODO: throw exception? 215// TODO: throw exception?
215 return false; 216 return false;
@@ -219,12 +220,15 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
219 } 220 }
220 statesAndUntraversedActivations.get(previousState).remove(activation); 221 statesAndUntraversedActivations.get(previousState).remove(activation);
221 statesAndTraversedActivations.get(previousState).add(activation); 222 statesAndTraversedActivations.get(previousState).add(activation);
222 long newState = model.commit(); 223 var newState = model.commit();
223 trajectory.add(newState); 224 trajectory.add(newState);
224 isNewState = !statesAndUntraversedActivations.containsKey(newState); 225 isNewState = !statesAndUntraversedActivations.containsKey(newState);
225 statesAndUntraversedActivations.put(newState, getAllActivations()); 226 statesAndUntraversedActivations.put(newState, getAllActivations());
226 statesAndTraversedActivations.put(newState, new LinkedHashSet<>()); 227 statesAndTraversedActivations.put(newState, new LinkedHashSet<>());
227 if (isVisualizationEnabled) { 228 if (isVisualizationEnabled) {
229 if (isNewState) {
230 modelVisualizerAdapter.addState(newState);
231 }
228 modelVisualizerAdapter.addTransition(trajectory.get(trajectory.size() - 2), 232 modelVisualizerAdapter.addTransition(trajectory.get(trajectory.size() - 2),
229 trajectory.get(trajectory.size() - 1), activation.transformationRule().getName(), 233 trajectory.get(trajectory.size() - 1), activation.transformationRule().getName(),
230 activation.activation()); 234 activation.activation());
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/strategy/BestFirstStrategy.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/strategy/BestFirstStrategy.java
index 62adb72f..6264c502 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/strategy/BestFirstStrategy.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/dse/strategy/BestFirstStrategy.java
@@ -1,5 +1,6 @@
1package tools.refinery.store.query.dse.strategy; 1package tools.refinery.store.query.dse.strategy;
2 2
3import tools.refinery.store.map.Version;
3import tools.refinery.store.query.dse.DesignSpaceExplorationAdapter; 4import tools.refinery.store.query.dse.DesignSpaceExplorationAdapter;
4import tools.refinery.store.query.dse.Strategy; 5import tools.refinery.store.query.dse.Strategy;
5import tools.refinery.store.query.dse.internal.Activation; 6import tools.refinery.store.query.dse.internal.Activation;
@@ -23,10 +24,10 @@ public class BestFirstStrategy implements Strategy {
23 24
24 private static class TrajectoryWithFitness { 25 private static class TrajectoryWithFitness {
25 26
26 public List<Long> trajectory; 27 public List<Version> trajectory;
27 public Fitness fitness; 28 public Fitness fitness;
28 29
29 public TrajectoryWithFitness(List<Long> trajectory, Fitness fitness) { 30 public TrajectoryWithFitness(List<Version> trajectory, Fitness fitness) {
30 super(); 31 super();
31 this.trajectory = trajectory; 32 this.trajectory = trajectory;
32 this.fitness = fitness; 33 this.fitness = fitness;
@@ -93,7 +94,7 @@ public class BestFirstStrategy implements Strategy {
93 return; 94 return;
94 } 95 }
95 96
96 final List<Long> firstTrajectory = dseAdapter.getTrajectory(); 97 final List<Version> firstTrajectory = dseAdapter.getTrajectory();
97 TrajectoryWithFitness currentTrajectoryWithFitness = new TrajectoryWithFitness(firstTrajectory, firstFitness); 98 TrajectoryWithFitness currentTrajectoryWithFitness = new TrajectoryWithFitness(firstTrajectory, firstFitness);
98 trajectoriesToExplore.add(currentTrajectoryWithFitness); 99 trajectoriesToExplore.add(currentTrajectoryWithFitness);
99 100
diff --git a/subprojects/store/src/jmh/java/tools/refinery/store/map/benchmarks/ImmutablePutExecutionPlan.java b/subprojects/store/src/jmh/java/tools/refinery/store/map/benchmarks/ImmutablePutExecutionPlan.java
index 7e89cd06..4708e6d3 100644
--- a/subprojects/store/src/jmh/java/tools/refinery/store/map/benchmarks/ImmutablePutExecutionPlan.java
+++ b/subprojects/store/src/jmh/java/tools/refinery/store/map/benchmarks/ImmutablePutExecutionPlan.java
@@ -5,12 +5,13 @@
5 */ 5 */
6package tools.refinery.store.map.benchmarks; 6package tools.refinery.store.map.benchmarks;
7 7
8import java.util.Objects;
8import java.util.Random; 9import java.util.Random;
9 10
10import tools.refinery.store.map.ContinousHashProvider; 11import tools.refinery.store.map.ContinuousHashProvider;
11import tools.refinery.store.map.VersionedMapStore; 12import tools.refinery.store.map.VersionedMapStore;
12import tools.refinery.store.map.VersionedMapStoreImpl; 13import tools.refinery.store.map.internal.state.VersionedMapStoreStateImpl;
13import tools.refinery.store.map.internal.VersionedMapImpl; 14import tools.refinery.store.map.internal.state.VersionedMapStateImpl;
14import tools.refinery.store.map.tests.utils.MapTestEnvironment; 15import tools.refinery.store.map.tests.utils.MapTestEnvironment;
15 16
16import org.openjdk.jmh.annotations.Level; 17import org.openjdk.jmh.annotations.Level;
@@ -35,7 +36,7 @@ public class ImmutablePutExecutionPlan {
35 36
36 private String[] values; 37 private String[] values;
37 38
38 private ContinousHashProvider<Integer> hashProvider = MapTestEnvironment.prepareHashProvider(false); 39 private ContinuousHashProvider<Integer> hashProvider = MapTestEnvironment.prepareHashProvider(false);
39 40
40 @Setup(Level.Trial) 41 @Setup(Level.Trial)
41 public void setUpTrial() { 42 public void setUpTrial() {
@@ -43,9 +44,9 @@ public class ImmutablePutExecutionPlan {
43 values = MapTestEnvironment.prepareValues(nValues, true); 44 values = MapTestEnvironment.prepareValues(nValues, true);
44 } 45 }
45 46
46 public VersionedMapImpl<Integer, String> createSut() { 47 public VersionedMapStateImpl<Integer, String> createSut() {
47 VersionedMapStore<Integer, String> store = new VersionedMapStoreImpl<Integer, String>(hashProvider, values[0]); 48 VersionedMapStore<Integer, String> store = new VersionedMapStoreStateImpl<>(hashProvider, values[0]);
48 return (VersionedMapImpl<Integer, String>) store.createMap(); 49 return (VersionedMapStateImpl<Integer, String>) store.createMap();
49 } 50 }
50 51
51 public Integer nextKey() { 52 public Integer nextKey() {
@@ -53,7 +54,7 @@ public class ImmutablePutExecutionPlan {
53 } 54 }
54 55
55 public boolean isDefault(String value) { 56 public boolean isDefault(String value) {
56 return value == values[0]; 57 return Objects.equals(value,values[0]);
57 } 58 }
58 59
59 public String nextValue() { 60 public String nextValue() {
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java b/subprojects/store/src/main/java/tools/refinery/store/map/ContinuousHashProvider.java
index 8e451230..abc044d0 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/ContinuousHashProvider.java
@@ -5,17 +5,17 @@
5 */ 5 */
6package tools.refinery.store.map; 6package tools.refinery.store.map;
7 7
8import tools.refinery.store.map.internal.Node; 8import tools.refinery.store.map.internal.state.Node;
9 9
10/** 10/**
11 * A class representing an equivalence relation for a type {@code K} with a 11 * A class representing an equivalence relation for a type {@code K} with a
12 * continuous hash function. 12 * continuous hash function.
13 * 13 *
14 * @author Oszkar Semerath 14 * @author Oszkar Semerath
15 * 15 *
16 * @param <K> Target java type. 16 * @param <K> Target java type.
17 */ 17 */
18public interface ContinousHashProvider<K> { 18public interface ContinuousHashProvider<K> {
19 public static final int EFFECTIVE_BITS = Node.EFFECTIVE_BITS; 19 public static final int EFFECTIVE_BITS = Node.EFFECTIVE_BITS;
20 public static final int EFFECTIVE_BIT_MASK = (1 << (EFFECTIVE_BITS)) - 1; 20 public static final int EFFECTIVE_BIT_MASK = (1 << (EFFECTIVE_BITS)) - 1;
21 21
@@ -38,9 +38,9 @@ public interface ContinousHashProvider<K> {
38 * {@link #EFFECTIVE_BITS} 38 * {@link #EFFECTIVE_BITS}
39 * </ul> 39 * </ul>
40 * Check {@link #equals} for further details. 40 * Check {@link #equals} for further details.
41 * 41 *
42 * @param key The target data object. 42 * @param key The target data object.
43 * @param index The depth of the the hash code. Needs to be non-negative. 43 * @param index The depth of the hash code. Needs to be non-negative.
44 * @return A hash code. 44 * @return A hash code.
45 */ 45 */
46 public int getHash(K key, int index); 46 public int getHash(K key, int index);
@@ -53,7 +53,7 @@ public interface ContinousHashProvider<K> {
53 if (key1.equals(key2)) { 53 if (key1.equals(key2)) {
54 return 0; 54 return 0;
55 } else { 55 } else {
56 for (int i = 0; i < ContinousHashProvider.MAX_PRACTICAL_DEPTH; i++) { 56 for (int i = 0; i < ContinuousHashProvider.MAX_PRACTICAL_DEPTH; i++) {
57 int hash1 = getEffectiveHash(key1, i); 57 int hash1 = getEffectiveHash(key1, i);
58 int hash2 = getEffectiveHash(key2, i); 58 int hash2 = getEffectiveHash(key2, i);
59 for(int j = 0; j<Integer.SIZE/Node.BRANCHING_FACTOR_BITS; j++) { 59 for(int j = 0; j<Integer.SIZE/Node.BRANCHING_FACTOR_BITS; j++) {
@@ -68,7 +68,7 @@ public interface ContinousHashProvider<K> {
68 } 68 }
69 throw new IllegalArgumentException("Two different keys (" + key1 + " and " + key2 69 throw new IllegalArgumentException("Two different keys (" + key1 + " and " + key2
70 + ") have the same hashcode over the practical depth limitation (" 70 + ") have the same hashcode over the practical depth limitation ("
71 + ContinousHashProvider.MAX_PRACTICAL_DEPTH + ")!"); 71 + ContinuousHashProvider.MAX_PRACTICAL_DEPTH + ")!");
72 } 72 }
73 } 73 }
74} 74}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/IteratorAsCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/IteratorAsCursor.java
index d1ab8bb1..29b03edf 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/IteratorAsCursor.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/IteratorAsCursor.java
@@ -1,16 +1,14 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map;
7 7
8import java.util.*; 8import java.util.Iterator;
9import java.util.Map;
9import java.util.Map.Entry; 10import java.util.Map.Entry;
10 11import java.util.Set;
11import tools.refinery.store.map.AnyVersionedMap;
12import tools.refinery.store.map.Cursor;
13import tools.refinery.store.map.VersionedMap;
14 12
15public class IteratorAsCursor<K, V> implements Cursor<K, V> { 13public class IteratorAsCursor<K, V> implements Cursor<K, V> {
16 final Iterator<Entry<K, V>> iterator; 14 final Iterator<Entry<K, V>> iterator;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/Version.java b/subprojects/store/src/main/java/tools/refinery/store/map/Version.java
new file mode 100644
index 00000000..fa2734e4
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/Version.java
@@ -0,0 +1,26 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.map;
7
8/**
9 * Interface denoting versions of {@link Versioned}.
10 */
11public interface Version {
12 /**
13 * Hashcode should be updated in accordance with equals.
14 * @return a hashcode of the object.
15 */
16 int hashCode();
17
18 /**
19 * Equivalence of two {@link Version}. This equivalence must satisfy the following constraint (in addition to the
20 * constraints of {@link Object#equals(Object)}: if {@code v1} and {@code v2} are {@link Version}s, and {@code v1
21 * .equals(v2)}, then {@code versioned.restore(v1)} must be {@code equals} to {@code versioned.restore(v2)}.
22 * @param o the other object.
23 * @return weather the two versions are equals.
24 */
25 boolean equals(Object o);
26}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java b/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java
index 55720db3..da12b0a9 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java
@@ -5,8 +5,20 @@
5 */ 5 */
6package tools.refinery.store.map; 6package tools.refinery.store.map;
7 7
8/**
9 * Object that can save and restore its state.
10 */
8public interface Versioned { 11public interface Versioned {
9 public long commit(); 12 /**
10 //maybe revert()? 13 * Saves the state of the object.
11 public void restore(long state); 14 * @return an object that marks the version of the object at the time the function was called.
15 */
16 Version commit();
17
18 /**
19 * Restores the state of the object.
20 * @param state a {@link Version} object that marks the version. The state must be a {@link Version} object
21 * returned by a previous {@link #commit()}!
22 */
23 void restore(Version state);
12} 24}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java
index c8226c3e..28194b58 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java
@@ -16,5 +16,5 @@ public non-sealed interface VersionedMap<K, V> extends AnyVersionedMap {
16 16
17 void putAll(Cursor<K, V> cursor); 17 void putAll(Cursor<K, V> cursor);
18 18
19 DiffCursor<K, V> getDiffCursor(long state); 19 DiffCursor<K, V> getDiffCursor(Version state);
20} 20}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java
index b24c404c..55cf08a5 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java
@@ -7,17 +7,13 @@ package tools.refinery.store.map;
7 7
8import tools.refinery.store.map.internal.VersionedMapStoreFactoryBuilderImpl; 8import tools.refinery.store.map.internal.VersionedMapStoreFactoryBuilderImpl;
9 9
10import java.util.Set;
11
12public interface VersionedMapStore<K, V> { 10public interface VersionedMapStore<K, V> {
13 11
14 VersionedMap<K, V> createMap(); 12 VersionedMap<K, V> createMap();
15 13
16 VersionedMap<K, V> createMap(long state); 14 VersionedMap<K, V> createMap(Version state);
17
18 Set<Long> getStates();
19 15
20 DiffCursor<K,V> getDiffCursor(long fromState, long toState); 16 DiffCursor<K,V> getDiffCursor(Version fromState, Version toState);
21 17
22 static <K,V> VersionedMapStoreFactoryBuilder<K,V> builder() { 18 static <K,V> VersionedMapStoreFactoryBuilder<K,V> builder() {
23 return new VersionedMapStoreFactoryBuilderImpl<>(); 19 return new VersionedMapStoreFactoryBuilderImpl<>();
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreFactoryBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreFactoryBuilder.java
index 6329a2f6..0ac196f2 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreFactoryBuilder.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreFactoryBuilder.java
@@ -20,9 +20,10 @@ public interface VersionedMapStoreFactoryBuilder<K,V> {
20 20
21 VersionedMapStoreFactoryBuilder<K,V> defaultValue(V defaultValue); 21 VersionedMapStoreFactoryBuilder<K,V> defaultValue(V defaultValue);
22 VersionedMapStoreFactoryBuilder<K,V> strategy(StoreStrategy strategy); 22 VersionedMapStoreFactoryBuilder<K,V> strategy(StoreStrategy strategy);
23 VersionedMapStoreFactoryBuilder<K,V> versionFreeing(boolean enabled);
23 VersionedMapStoreFactoryBuilder<K,V> stateBasedImmutableWhenCommitting(boolean transformToImmutable); 24 VersionedMapStoreFactoryBuilder<K,V> stateBasedImmutableWhenCommitting(boolean transformToImmutable);
24 VersionedMapStoreFactoryBuilder<K,V> stateBasedSharingStrategy(SharingStrategy sharingStrategy); 25 VersionedMapStoreFactoryBuilder<K,V> stateBasedSharingStrategy(SharingStrategy sharingStrategy);
25 VersionedMapStoreFactoryBuilder<K,V> stateBasedHashProvider(ContinousHashProvider<K> hashProvider); 26 VersionedMapStoreFactoryBuilder<K,V> stateBasedHashProvider(ContinuousHashProvider<K> hashProvider);
26 VersionedMapStoreFactoryBuilder<K,V> deltaTransactionStrategy(DeltaTransactionStrategy deltaStrategy); 27 VersionedMapStoreFactoryBuilder<K,V> deltaTransactionStrategy(DeltaTransactionStrategy deltaStrategy);
27 28
28 VersionedMapStoreFactory<K,V> build(); 29 VersionedMapStoreFactory<K,V> build();
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java
deleted file mode 100644
index a934d59e..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java
+++ /dev/null
@@ -1,129 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.map;
7
8import tools.refinery.store.map.internal.*;
9
10import java.util.*;
11
12public class VersionedMapStoreImpl<K, V> implements VersionedMapStore<K, V> {
13 // Configuration
14 private final boolean immutableWhenCommitting;
15
16 // Static data
17 protected final ContinousHashProvider<K> hashProvider;
18 protected final V defaultValue;
19
20 // Dynamic data
21 protected final Map<Long, ImmutableNode<K, V>> states = new HashMap<>();
22 protected final Map<Node<K, V>, ImmutableNode<K, V>> nodeCache;
23 protected long nextID = 0;
24
25 public VersionedMapStoreImpl(ContinousHashProvider<K> hashProvider, V defaultValue,
26 VersionedMapStoreConfiguration config) {
27 this.immutableWhenCommitting = config.isImmutableWhenCommitting();
28 this.hashProvider = hashProvider;
29 this.defaultValue = defaultValue;
30 if (config.isSharedNodeCacheInStore()) {
31 nodeCache = new HashMap<>();
32 } else {
33 nodeCache = null;
34 }
35 }
36
37 private VersionedMapStoreImpl(ContinousHashProvider<K> hashProvider, V defaultValue,
38 Map<Node<K, V>, ImmutableNode<K, V>> nodeCache, VersionedMapStoreConfiguration config) {
39 this.immutableWhenCommitting = config.isImmutableWhenCommitting();
40 this.hashProvider = hashProvider;
41 this.defaultValue = defaultValue;
42 this.nodeCache = nodeCache;
43 }
44
45 public VersionedMapStoreImpl(ContinousHashProvider<K> hashProvider, V defaultValue) {
46 this(hashProvider, defaultValue, new VersionedMapStoreConfiguration());
47 }
48
49 public static <K, V> List<VersionedMapStore<K, V>> createSharedVersionedMapStores(int amount,
50 ContinousHashProvider<K> hashProvider, V defaultValue,
51 VersionedMapStoreConfiguration config) {
52 List<VersionedMapStore<K, V>> result = new ArrayList<>(amount);
53 if (config.isSharedNodeCacheInStoreGroups()) {
54 Map<Node<K, V>, ImmutableNode<K, V>> nodeCache;
55 if (config.isSharedNodeCacheInStore()) {
56 nodeCache = new HashMap<>();
57 } else {
58 nodeCache = null;
59 }
60 for (int i = 0; i < amount; i++) {
61 result.add(new VersionedMapStoreImpl<>(hashProvider, defaultValue, nodeCache, config));
62 }
63 } else {
64 for (int i = 0; i < amount; i++) {
65 result.add(new VersionedMapStoreImpl<>(hashProvider, defaultValue, config));
66 }
67 }
68 return result;
69 }
70
71 public static <K, V> List<VersionedMapStore<K, V>> createSharedVersionedMapStores(int amount,
72 ContinousHashProvider<K> hashProvider, V defaultValue) {
73 return createSharedVersionedMapStores(amount, hashProvider, defaultValue, new VersionedMapStoreConfiguration());
74 }
75
76 @Override
77 public synchronized Set<Long> getStates() {
78 return new HashSet<>(states.keySet());
79 }
80
81 @Override
82 public VersionedMap<K, V> createMap() {
83 return new VersionedMapImpl<>(this, hashProvider, defaultValue);
84 }
85
86 @Override
87 public VersionedMap<K, V> createMap(long state) {
88 ImmutableNode<K, V> data = revert(state);
89 return new VersionedMapImpl<>(this, hashProvider, defaultValue, data);
90 }
91
92 public synchronized ImmutableNode<K, V> revert(long state) {
93 if (states.containsKey(state)) {
94 return states.get(state);
95 } else {
96 ArrayList<Long> existingKeys = new ArrayList<>(states.keySet());
97 Collections.sort(existingKeys);
98 throw new IllegalArgumentException("Store does not contain state " + state + "! Available states: "
99 + Arrays.toString(existingKeys.toArray()));
100 }
101 }
102
103 public synchronized long commit(Node<K, V> data, VersionedMapImpl<K, V> mapToUpdateRoot) {
104 ImmutableNode<K, V> immutable;
105 if (data != null) {
106 immutable = data.toImmutable(this.nodeCache);
107 } else {
108 immutable = null;
109 }
110
111 if (nextID == Long.MAX_VALUE)
112 throw new IllegalStateException("Map store run out of Id-s");
113 long id = nextID++;
114 this.states.put(id, immutable);
115 if (this.immutableWhenCommitting) {
116 mapToUpdateRoot.setRoot(immutable);
117 }
118 return id;
119 }
120
121 @Override
122 public DiffCursor<K, V> getDiffCursor(long fromState, long toState) {
123 VersionedMapImpl<K, V> map1 = (VersionedMapImpl<K, V>) createMap(fromState);
124 VersionedMapImpl<K, V> map2 = (VersionedMapImpl<K, V>) createMap(toState);
125 InOrderMapCursor<K, V> cursor1 = new InOrderMapCursor<>(map1);
126 InOrderMapCursor<K, V> cursor2 = new InOrderMapCursor<>(map2);
127 return new MapDiffCursor<>(this.defaultValue, cursor1, cursor2);
128 }
129}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java
deleted file mode 100644
index a357fbce..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java
+++ /dev/null
@@ -1,23 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.map.internal;
7
8enum HashClash {
9 /**
10 * Not stuck.
11 */
12 NONE,
13
14 /**
15 * Clashed, next we should return the key of cursor 1.
16 */
17 STUCK_CURSOR_1,
18
19 /**
20 * Clashed, next we should return the key of cursor 2.
21 */
22 STUCK_CURSOR_2
23}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/StateBasedVersionedMapStoreFactory.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/StateBasedVersionedMapStoreFactory.java
deleted file mode 100644
index 1c3ab27b..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/StateBasedVersionedMapStoreFactory.java
+++ /dev/null
@@ -1,38 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.map.internal;
7
8import tools.refinery.store.map.*;
9
10import java.util.List;
11
12public class StateBasedVersionedMapStoreFactory<K, V> implements VersionedMapStoreFactory<K, V> {
13 private final V defaultValue;
14 private final ContinousHashProvider<K> continousHashProvider;
15 private final VersionedMapStoreConfiguration config;
16
17 public StateBasedVersionedMapStoreFactory(V defaultValue, Boolean transformToImmutable, VersionedMapStoreFactoryBuilder.SharingStrategy sharingStrategy, ContinousHashProvider<K> continousHashProvider) {
18 this.defaultValue = defaultValue;
19 this.continousHashProvider = continousHashProvider;
20
21 this.config = new VersionedMapStoreConfiguration(
22 transformToImmutable,
23 sharingStrategy == VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE || sharingStrategy == VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE_IN_GROUP,
24 sharingStrategy == VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE_IN_GROUP);
25 }
26
27 @Override
28 public VersionedMapStore<K, V> createOne() {
29 return new VersionedMapStoreImpl<>(continousHashProvider, defaultValue, config);
30
31 }
32
33 @Override
34 public List<VersionedMapStore<K, V>> createGroup(int amount) {
35 return VersionedMapStoreImpl.createSharedVersionedMapStores(amount, continousHashProvider, defaultValue,
36 config);
37 }
38}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapStoreFactoryBuilderImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapStoreFactoryBuilderImpl.java
index cf117d95..9f419ce1 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapStoreFactoryBuilderImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapStoreFactoryBuilderImpl.java
@@ -5,9 +5,11 @@
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal;
7 7
8import tools.refinery.store.map.ContinousHashProvider; 8import tools.refinery.store.map.ContinuousHashProvider;
9import tools.refinery.store.map.VersionedMapStoreFactory; 9import tools.refinery.store.map.VersionedMapStoreFactory;
10import tools.refinery.store.map.VersionedMapStoreFactoryBuilder; 10import tools.refinery.store.map.VersionedMapStoreFactoryBuilder;
11import tools.refinery.store.map.internal.delta.DeltaBasedVersionedMapStoreFactory;
12import tools.refinery.store.map.internal.state.StateBasedVersionedMapStoreFactory;
11 13
12public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapStoreFactoryBuilder<K, V> { 14public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapStoreFactoryBuilder<K, V> {
13 15
@@ -16,14 +18,15 @@ public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapSt
16 private StoreStrategy strategy = null; 18 private StoreStrategy strategy = null;
17 private Boolean transformToImmutable = null; 19 private Boolean transformToImmutable = null;
18 private SharingStrategy sharingStrategy = null; 20 private SharingStrategy sharingStrategy = null;
19 private ContinousHashProvider<K> continousHashProvider = null; 21 private Boolean enableVersionFreeing = null;
22 private ContinuousHashProvider<K> continuousHashProvider = null;
20 private DeltaTransactionStrategy deltaTransactionStrategy = null; 23 private DeltaTransactionStrategy deltaTransactionStrategy = null;
21 24
22 private StoreStrategy checkStrategy() { 25 private StoreStrategy checkStrategy() {
23 StoreStrategy currentStrategy = strategy; 26 StoreStrategy currentStrategy = strategy;
24 currentStrategy = mergeStrategies(currentStrategy, transformToImmutable, StoreStrategy.STATE); 27 currentStrategy = mergeStrategies(currentStrategy, transformToImmutable, StoreStrategy.STATE);
25 currentStrategy = mergeStrategies(currentStrategy, sharingStrategy, StoreStrategy.STATE); 28 currentStrategy = mergeStrategies(currentStrategy, sharingStrategy, StoreStrategy.STATE);
26 currentStrategy = mergeStrategies(currentStrategy, continousHashProvider, StoreStrategy.STATE); 29 currentStrategy = mergeStrategies(currentStrategy, continuousHashProvider, StoreStrategy.STATE);
27 currentStrategy = mergeStrategies(currentStrategy, deltaTransactionStrategy, StoreStrategy.DELTA); 30 currentStrategy = mergeStrategies(currentStrategy, deltaTransactionStrategy, StoreStrategy.DELTA);
28 return currentStrategy; 31 return currentStrategy;
29 } 32 }
@@ -63,6 +66,13 @@ public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapSt
63 } 66 }
64 67
65 @Override 68 @Override
69 public VersionedMapStoreFactoryBuilder<K, V> versionFreeing(boolean enabled) {
70 this.enableVersionFreeing = enabled;
71 checkStrategy();
72 return this;
73 }
74
75 @Override
66 public VersionedMapStoreFactoryBuilder<K, V> stateBasedImmutableWhenCommitting(boolean transformToImmutable) { 76 public VersionedMapStoreFactoryBuilder<K, V> stateBasedImmutableWhenCommitting(boolean transformToImmutable) {
67 this.transformToImmutable = transformToImmutable; 77 this.transformToImmutable = transformToImmutable;
68 checkStrategy(); 78 checkStrategy();
@@ -77,8 +87,8 @@ public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapSt
77 } 87 }
78 88
79 @Override 89 @Override
80 public VersionedMapStoreFactoryBuilder<K, V> stateBasedHashProvider(ContinousHashProvider<K> hashProvider) { 90 public VersionedMapStoreFactoryBuilder<K, V> stateBasedHashProvider(ContinuousHashProvider<K> hashProvider) {
81 this.continousHashProvider = hashProvider; 91 this.continuousHashProvider = hashProvider;
82 checkStrategy(); 92 checkStrategy();
83 return this; 93 return this;
84 } 94 }
@@ -110,13 +120,14 @@ public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapSt
110 } 120 }
111 return switch (strategyToUse) { 121 return switch (strategyToUse) {
112 case STATE -> { 122 case STATE -> {
113 if(continousHashProvider == null) { 123 if(continuousHashProvider == null) {
114 throw new IllegalArgumentException("Continuous hash provider is missing!"); 124 throw new IllegalArgumentException("Continuous hash provider is missing!");
115 } 125 }
116 yield new StateBasedVersionedMapStoreFactory<>(defaultValue, 126 yield new StateBasedVersionedMapStoreFactory<>(defaultValue,
117 getOrDefault(transformToImmutable,true), 127 getOrDefault(transformToImmutable,true),
118 getOrDefault(sharingStrategy, SharingStrategy.SHARED_NODE_CACHE_IN_GROUP), 128 getOrDefault(sharingStrategy, SharingStrategy.SHARED_NODE_CACHE_IN_GROUP),
119 continousHashProvider); 129 getOrDefault(enableVersionFreeing, true),
130 continuousHashProvider);
120 } 131 }
121 case DELTA -> new DeltaBasedVersionedMapStoreFactory<>(defaultValue, 132 case DELTA -> new DeltaBasedVersionedMapStoreFactory<>(defaultValue,
122 getOrDefault(deltaTransactionStrategy, DeltaTransactionStrategy.LIST)); 133 getOrDefault(deltaTransactionStrategy, DeltaTransactionStrategy.LIST));
@@ -125,13 +136,15 @@ public class VersionedMapStoreFactoryBuilderImpl<K, V> implements VersionedMapSt
125 136
126 @Override 137 @Override
127 public String toString() { 138 public String toString() {
128 return "VersionedMapStoreBuilder{" + 139 return "VersionedMapStoreFactoryBuilderImpl{" +
129 "defaultValue=" + defaultValue + 140 "defaultSet=" + defaultSet +
141 ", defaultValue=" + defaultValue +
130 ", strategy=" + strategy + 142 ", strategy=" + strategy +
131 ", stateBasedImmutableWhenCommitting=" + transformToImmutable + 143 ", transformToImmutable=" + transformToImmutable +
132 ", stateBasedNodeSharingStrategy=" + sharingStrategy + 144 ", sharingStrategy=" + sharingStrategy +
133 ", hashProvider=" + continousHashProvider + 145 ", enableVersionFreeing=" + enableVersionFreeing +
134 ", deltaStorageStrategy=" + deltaTransactionStrategy + 146 ", continuousHashProvider=" + continuousHashProvider +
147 ", deltaTransactionStrategy=" + deltaTransactionStrategy +
135 '}'; 148 '}';
136 } 149 }
137} 150}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/DeltaBasedVersionedMapStoreFactory.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/DeltaBasedVersionedMapStoreFactory.java
index fe490f46..cedcdc0b 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/DeltaBasedVersionedMapStoreFactory.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/DeltaBasedVersionedMapStoreFactory.java
@@ -1,12 +1,11 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8import tools.refinery.store.map.VersionedMapStore; 8import tools.refinery.store.map.VersionedMapStore;
9import tools.refinery.store.map.VersionedMapStoreDeltaImpl;
10import tools.refinery.store.map.VersionedMapStoreFactory; 9import tools.refinery.store.map.VersionedMapStoreFactory;
11import tools.refinery.store.map.VersionedMapStoreFactoryBuilder; 10import tools.refinery.store.map.VersionedMapStoreFactoryBuilder;
12 11
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/DeltaDiffCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/DeltaDiffCursor.java
index cc9003e3..ce10b246 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/DeltaDiffCursor.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/DeltaDiffCursor.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8import tools.refinery.store.map.AnyVersionedMap; 8import tools.refinery.store.map.AnyVersionedMap;
9import tools.refinery.store.map.DiffCursor; 9import tools.refinery.store.map.DiffCursor;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDelta.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/MapDelta.java
index 2674236c..0c0cc906 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDelta.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/MapDelta.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8public record MapDelta<K, V>(K key, V oldValue, V newValue) { 8public record MapDelta<K, V>(K key, V oldValue, V newValue) {
9 public K getKey() { 9 public K getKey() {
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapTransaction.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/MapTransaction.java
index d63522cd..6f3fa6d7 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapTransaction.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/MapTransaction.java
@@ -1,21 +1,23 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7
8import tools.refinery.store.map.Version;
7 9
8import java.util.Arrays; 10import java.util.Arrays;
9import java.util.Objects; 11import java.util.Objects;
10 12
11public record MapTransaction<K, V>(MapDelta<K, V>[] deltas, long version, MapTransaction<K, V> parent) { 13public record MapTransaction<K, V>(MapDelta<K, V>[] deltas, MapTransaction<K, V> parent, int depth) implements Version {
12 14
13 @Override 15 @Override
14 public int hashCode() { 16 public int hashCode() {
15 final int prime = 31; 17 final int prime = 31;
16 int result = 1; 18 int result = 1;
17 result = prime * result + Arrays.hashCode(deltas); 19 result = prime * result + Arrays.hashCode(deltas);
18 result = prime * result + Objects.hash(parent, version); 20 result = prime * result + Objects.hash(parent, depth);
19 return result; 21 return result;
20 } 22 }
21 23
@@ -29,11 +31,11 @@ public record MapTransaction<K, V>(MapDelta<K, V>[] deltas, long version, MapTra
29 return false; 31 return false;
30 @SuppressWarnings("unchecked") 32 @SuppressWarnings("unchecked")
31 MapTransaction<K, V> other = (MapTransaction<K, V>) obj; 33 MapTransaction<K, V> other = (MapTransaction<K, V>) obj;
32 return Arrays.equals(deltas, other.deltas) && Objects.equals(parent, other.parent) && version == other.version; 34 return depth == other.depth && Objects.equals(parent, other.parent) && Arrays.equals(deltas, other.deltas);
33 } 35 }
34 36
35 @Override 37 @Override
36 public String toString() { 38 public String toString() {
37 return "MapTransaction " + version + " " + Arrays.toString(deltas); 39 return "MapTransaction " + depth + " " + Arrays.toString(deltas);
38 } 40 }
39} 41}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaArrayStore.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaArrayStore.java
index ba59cfef..1f6a9000 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaArrayStore.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaArrayStore.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8import java.util.ArrayList; 8import java.util.ArrayList;
9import java.util.List; 9import java.util.List;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaMapStore.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaMapStore.java
index 61a34351..644884a6 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaMapStore.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaMapStore.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8import java.util.*; 8import java.util.*;
9import java.util.Map.Entry; 9import java.util.Map.Entry;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaStore.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaStore.java
index 438b5561..ecd33c5f 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaStore.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/UncommittedDeltaStore.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8public interface UncommittedDeltaStore<K, V> { 8public interface UncommittedDeltaStore<K, V> {
9 void processChange(K key, V oldValue, V newValue); 9 void processChange(K key, V oldValue, V newValue);
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapDeltaImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/VersionedMapDeltaImpl.java
index ae47feda..c19cc817 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapDeltaImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/VersionedMapDeltaImpl.java
@@ -1,13 +1,14 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.delta;
7 7
8import java.util.*; 8import java.util.*;
9 9
10import tools.refinery.store.map.*; 10import tools.refinery.store.map.*;
11import tools.refinery.store.map.IteratorAsCursor;
11 12
12public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> { 13public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
13 protected final VersionedMapStoreDeltaImpl<K, V> store; 14 protected final VersionedMapStoreDeltaImpl<K, V> store;
@@ -37,15 +38,15 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
37 } 38 }
38 39
39 @Override 40 @Override
40 public long commit() { 41 public Version commit() {
41 MapDelta<K, V>[] deltas = uncommittedStore.extractAndDeleteDeltas(); 42 MapDelta<K, V>[] deltas = uncommittedStore.extractAndDeleteDeltas();
42 long[] versionContainer = new long[1]; 43 final MapTransaction<K,V> committedTransaction = this.store.appendTransaction(deltas, previous);
43 this.previous = this.store.appendTransaction(deltas, previous, versionContainer); 44 this.previous = committedTransaction;
44 return versionContainer[0]; 45 return committedTransaction;
45 } 46 }
46 47
47 @Override 48 @Override
48 public void restore(long state) { 49 public void restore(Version state) {
49 // 1. restore uncommitted states 50 // 1. restore uncommitted states
50 MapDelta<K, V>[] uncommitted = this.uncommittedStore.extractAndDeleteDeltas(); 51 MapDelta<K, V>[] uncommitted = this.uncommittedStore.extractAndDeleteDeltas();
51 if (uncommitted != null) { 52 if (uncommitted != null) {
@@ -60,7 +61,7 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
60 this.forward(forward); 61 this.forward(forward);
61 } else { 62 } else {
62 List<MapDelta<K, V>[]> backward = new ArrayList<>(); 63 List<MapDelta<K, V>[]> backward = new ArrayList<>();
63 parent = this.store.getPath(this.previous.version(), state, backward, forward); 64 parent = this.store.getPath(this.previous, state, backward, forward);
64 this.backward(backward); 65 this.backward(backward);
65 this.forward(forward); 66 this.forward(forward);
66 } 67 }
@@ -74,12 +75,16 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
74 } 75 }
75 76
76 protected void backward(List<MapDelta<K, V>[]> changes) { 77 protected void backward(List<MapDelta<K, V>[]> changes) {
78 //Currently, this loop statement is faster.
79 //noinspection ForLoopReplaceableByForEach
77 for (int i = 0; i < changes.size(); i++) { 80 for (int i = 0; i < changes.size(); i++) {
78 backward(changes.get(i)); 81 backward(changes.get(i));
79 } 82 }
80 } 83 }
81 84
82 protected void forward(MapDelta<K, V>[] changes) { 85 protected void forward(MapDelta<K, V>[] changes) {
86 //Currently, this loop statement is faster.
87 //noinspection ForLoopReplaceableByForEach
83 for (int i = 0; i < changes.length; i++) { 88 for (int i = 0; i < changes.length; i++) {
84 final MapDelta<K, V> change = changes[i]; 89 final MapDelta<K, V> change = changes[i];
85 K key = change.getKey(); 90 K key = change.getKey();
@@ -167,7 +172,7 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
167 } 172 }
168 173
169 @Override 174 @Override
170 public DiffCursor<K, V> getDiffCursor(long state) { 175 public DiffCursor<K, V> getDiffCursor(Version state) {
171 MapDelta<K, V>[] backward = this.uncommittedStore.extractDeltas(); 176 MapDelta<K, V>[] backward = this.uncommittedStore.extractDeltas();
172 List<MapDelta<K, V>[]> backwardTransactions = new ArrayList<>(); 177 List<MapDelta<K, V>[]> backwardTransactions = new ArrayList<>();
173 List<MapDelta<K, V>[]> forwardTransactions = new ArrayList<>(); 178 List<MapDelta<K, V>[]> forwardTransactions = new ArrayList<>();
@@ -177,7 +182,7 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
177 } 182 }
178 183
179 if (this.previous != null) { 184 if (this.previous != null) {
180 store.getPath(this.previous.version(), state, backwardTransactions, forwardTransactions); 185 store.getPath(this.previous, state, backwardTransactions, forwardTransactions);
181 } else { 186 } else {
182 store.getPath(state, forwardTransactions); 187 store.getPath(state, forwardTransactions);
183 } 188 }
@@ -215,5 +220,19 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
215 throw new IllegalStateException("null value stored in map!"); 220 throw new IllegalStateException("null value stored in map!");
216 } 221 }
217 } 222 }
223 MapTransaction<K,V> transaction = this.previous;
224 while(transaction != null) {
225 MapTransaction<K,V> parent = transaction.parent();
226 if(parent != null) {
227 if(parent.depth() != transaction.depth()-1) {
228 throw new IllegalStateException("Parent depths are inconsistent!");
229 }
230 } else {
231 if(transaction.depth() != 0) {
232 throw new IllegalArgumentException("Root depth is not 0!");
233 }
234 }
235 transaction = transaction.parent();
236 }
218 } 237 }
219} 238}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreDeltaImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/VersionedMapStoreDeltaImpl.java
index 0c61bd09..ed169409 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreDeltaImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/delta/VersionedMapStoreDeltaImpl.java
@@ -1,13 +1,16 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map; 6package tools.refinery.store.map.internal.delta;
7 7
8import java.util.*; 8import tools.refinery.store.map.DiffCursor;
9import tools.refinery.store.map.Version;
10import tools.refinery.store.map.VersionedMap;
11import tools.refinery.store.map.VersionedMapStore;
9 12
10import tools.refinery.store.map.internal.*; 13import java.util.*;
11 14
12public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V> { 15public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V> {
13 // Configuration 16 // Configuration
@@ -16,10 +19,6 @@ public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V>
16 // Static data 19 // Static data
17 protected final V defaultValue; 20 protected final V defaultValue;
18 21
19 // Dynamic data
20 protected final Map<Long, MapTransaction<K, V>> states = new HashMap<>();
21 protected long nextID = 0;
22
23 public VersionedMapStoreDeltaImpl(boolean summarizeChanges, V defaultValue) { 22 public VersionedMapStoreDeltaImpl(boolean summarizeChanges, V defaultValue) {
24 this.summarizeChanges = summarizeChanges; 23 this.summarizeChanges = summarizeChanges;
25 this.defaultValue = defaultValue; 24 this.defaultValue = defaultValue;
@@ -31,30 +30,32 @@ public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V>
31 } 30 }
32 31
33 @Override 32 @Override
34 public VersionedMap<K, V> createMap(long state) { 33 public VersionedMap<K, V> createMap(Version state) {
35 VersionedMapDeltaImpl<K, V> result = new VersionedMapDeltaImpl<>(this, this.summarizeChanges, this.defaultValue); 34 VersionedMapDeltaImpl<K, V> result = new VersionedMapDeltaImpl<>(this, this.summarizeChanges, this.defaultValue);
36 result.restore(state); 35 result.restore(state);
37 return result; 36 return result;
38 } 37 }
39 38
40 public synchronized MapTransaction<K, V> appendTransaction(MapDelta<K, V>[] deltas, MapTransaction<K, V> previous, long[] versionContainer) { 39 public MapTransaction<K, V> appendTransaction(MapDelta<K, V>[] deltas, MapTransaction<K, V> previous) {
41 long version = nextID++;
42 versionContainer[0] = version;
43 if (deltas == null) { 40 if (deltas == null) {
44 states.put(version, previous);
45 return previous; 41 return previous;
46 } else { 42 } else {
47 MapTransaction<K, V> transaction = new MapTransaction<>(deltas, version, previous); 43 final int depth;
48 states.put(version, transaction); 44 if(previous != null) {
49 return transaction; 45 depth = previous.depth()+1;
46 } else {
47 depth = 0;
48 }
49 return new MapTransaction<>(deltas, previous, depth);
50 } 50 }
51 } 51 }
52 52
53 private synchronized MapTransaction<K, V> getState(long state) { 53 @SuppressWarnings("unchecked")
54 return states.get(state); 54 private MapTransaction<K, V> getState(Version state) {
55 return (MapTransaction<K, V>) state;
55 } 56 }
56 57
57 public MapTransaction<K, V> getPath(long to, List<MapDelta<K, V>[]> forwardTransactions) { 58 public MapTransaction<K, V> getPath(Version to, List<MapDelta<K, V>[]> forwardTransactions) {
58 final MapTransaction<K, V> target = getState(to); 59 final MapTransaction<K, V> target = getState(to);
59 MapTransaction<K, V> toTransaction = target; 60 MapTransaction<K, V> toTransaction = target;
60 while (toTransaction != null) { 61 while (toTransaction != null) {
@@ -64,7 +65,7 @@ public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V>
64 return target; 65 return target;
65 } 66 }
66 67
67 public MapTransaction<K, V> getPath(long from, long to, 68 public MapTransaction<K, V> getPath(Version from, Version to,
68 List<MapDelta<K, V>[]> backwardTransactions, 69 List<MapDelta<K, V>[]> backwardTransactions,
69 List<MapDelta<K, V>[]> forwardTransactions) { 70 List<MapDelta<K, V>[]> forwardTransactions) {
70 MapTransaction<K, V> fromTransaction = getState(from); 71 MapTransaction<K, V> fromTransaction = getState(from);
@@ -72,7 +73,7 @@ public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V>
72 MapTransaction<K, V> toTransaction = target; 73 MapTransaction<K, V> toTransaction = target;
73 74
74 while (fromTransaction != toTransaction) { 75 while (fromTransaction != toTransaction) {
75 if (fromTransaction == null || (toTransaction != null && fromTransaction.version() < toTransaction.version())) { 76 if (fromTransaction == null || (toTransaction != null && fromTransaction.depth() < toTransaction.depth())) {
76 forwardTransactions.add(toTransaction.deltas()); 77 forwardTransactions.add(toTransaction.deltas());
77 toTransaction = toTransaction.parent(); 78 toTransaction = toTransaction.parent();
78 } else { 79 } else {
@@ -83,14 +84,8 @@ public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V>
83 return target; 84 return target;
84 } 85 }
85 86
86
87 @Override
88 public synchronized Set<Long> getStates() {
89 return new HashSet<>(states.keySet());
90 }
91
92 @Override 87 @Override
93 public DiffCursor<K, V> getDiffCursor(long fromState, long toState) { 88 public DiffCursor<K, V> getDiffCursor(Version fromState, Version toState) {
94 List<MapDelta<K, V>[]> backwardTransactions = new ArrayList<>(); 89 List<MapDelta<K, V>[]> backwardTransactions = new ArrayList<>();
95 List<MapDelta<K, V>[]> forwardTransactions = new ArrayList<>(); 90 List<MapDelta<K, V>[]> forwardTransactions = new ArrayList<>();
96 getPath(fromState, toState, backwardTransactions, forwardTransactions); 91 getPath(fromState, toState, backwardTransactions, forwardTransactions);
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/ImmutableNode.java
index d052318f..5b1d8b77 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/ImmutableNode.java
@@ -1,16 +1,17 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import java.util.Arrays; 8import java.util.Arrays;
9import java.util.Map; 9import java.util.Map;
10 10
11import tools.refinery.store.map.ContinousHashProvider; 11import tools.refinery.store.map.ContinuousHashProvider;
12import tools.refinery.store.map.Version;
12 13
13public class ImmutableNode<K, V> extends Node<K, V> { 14public class ImmutableNode<K, V> extends Node<K, V> implements Version {
14 /** 15 /**
15 * Bitmap defining the stored key and values. 16 * Bitmap defining the stored key and values.
16 */ 17 */
@@ -104,7 +105,7 @@ public class ImmutableNode<K, V> extends Node<K, V> {
104 } 105 }
105 106
106 @Override 107 @Override
107 public V getValue(K key, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) { 108 public V getValue(K key, ContinuousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) {
108 int selectedHashFragment = hashFragment(hash, shiftDepth(depth)); 109 int selectedHashFragment = hashFragment(hash, shiftDepth(depth));
109 int bitposition = 1 << selectedHashFragment; 110 int bitposition = 1 << selectedHashFragment;
110 // If the key is stored as a data 111 // If the key is stored as a data
@@ -133,7 +134,7 @@ public class ImmutableNode<K, V> extends Node<K, V> {
133 } 134 }
134 135
135 @Override 136 @Override
136 public Node<K, V> putValue(K key, V value, OldValueBox<V> oldValue, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) { 137 public Node<K, V> putValue(K key, V value, OldValueBox<V> oldValue, ContinuousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) {
137 int selectedHashFragment = hashFragment(hash, shiftDepth(depth)); 138 int selectedHashFragment = hashFragment(hash, shiftDepth(depth));
138 int bitPosition = 1 << selectedHashFragment; 139 int bitPosition = 1 << selectedHashFragment;
139 if ((dataMap & bitPosition) != 0) { 140 if ((dataMap & bitPosition) != 0) {
@@ -145,7 +146,7 @@ public class ImmutableNode<K, V> extends Node<K, V> {
145 MutableNode<K, V> mutable = this.toMutable(); 146 MutableNode<K, V> mutable = this.toMutable();
146 return mutable.removeEntry(selectedHashFragment, oldValue); 147 return mutable.removeEntry(selectedHashFragment, oldValue);
147 } else if (value == content[keyIndex + 1]) { 148 } else if (value == content[keyIndex + 1]) {
148 // dont change 149 // don't change
149 oldValue.setOldValue(value); 150 oldValue.setOldValue(value);
150 return this; 151 return this;
151 } else { 152 } else {
@@ -155,7 +156,7 @@ public class ImmutableNode<K, V> extends Node<K, V> {
155 } 156 }
156 } else { 157 } else {
157 if (value == defaultValue) { 158 if (value == defaultValue) {
158 // dont change 159 // don't change
159 oldValue.setOldValue(defaultValue); 160 oldValue.setOldValue(defaultValue);
160 return this; 161 return this;
161 } else { 162 } else {
@@ -339,7 +340,7 @@ public class ImmutableNode<K, V> extends Node<K, V> {
339 } 340 }
340 341
341 @Override 342 @Override
342 public void checkIntegrity(ContinousHashProvider<? super K> hashProvider, V defaultValue, int depth) { 343 public void checkIntegrity(ContinuousHashProvider<? super K> hashProvider, V defaultValue, int depth) {
343 if (depth > 0) { 344 if (depth > 0) {
344 boolean orphaned = Integer.bitCount(dataMap) == 1 && nodeMap == 0; 345 boolean orphaned = Integer.bitCount(dataMap) == 1 && nodeMap == 0;
345 if (orphaned) { 346 if (orphaned) {
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/InOrderMapCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/InOrderMapCursor.java
index cb3f366f..7cc91004 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/InOrderMapCursor.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/InOrderMapCursor.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import tools.refinery.store.map.AnyVersionedMap; 8import tools.refinery.store.map.AnyVersionedMap;
9import tools.refinery.store.map.ContentHashCode; 9import tools.refinery.store.map.ContentHashCode;
@@ -29,7 +29,7 @@ public class InOrderMapCursor<K, V> implements Cursor<K, V> {
29 final VersionedMap<K, V> map; 29 final VersionedMap<K, V> map;
30 final int creationHash; 30 final int creationHash;
31 31
32 public InOrderMapCursor(VersionedMapImpl<K, V> map) { 32 public InOrderMapCursor(VersionedMapStateImpl<K, V> map) {
33 // Initializing tree stack 33 // Initializing tree stack
34 super(); 34 super();
35 this.nodeStack = new ArrayDeque<>(); 35 this.nodeStack = new ArrayDeque<>();
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MapCursor.java
index d42519b2..0db50d04 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MapCursor.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import tools.refinery.store.map.AnyVersionedMap; 8import tools.refinery.store.map.AnyVersionedMap;
9import tools.refinery.store.map.ContentHashCode; 9import tools.refinery.store.map.ContentHashCode;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MapDiffCursor.java
index fb1d5d2b..083bf8cf 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MapDiffCursor.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import tools.refinery.store.map.AnyVersionedMap; 8import tools.refinery.store.map.AnyVersionedMap;
9import tools.refinery.store.map.Cursor; 9import tools.refinery.store.map.Cursor;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MutableNode.java
index bb85deb9..408ed62c 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/MutableNode.java
@@ -1,11 +1,11 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import tools.refinery.store.map.ContinousHashProvider; 8import tools.refinery.store.map.ContinuousHashProvider;
9 9
10import java.util.Arrays; 10import java.util.Arrays;
11import java.util.Map; 11import java.util.Map;
@@ -20,7 +20,7 @@ public class MutableNode<K, V> extends Node<K, V> {
20 invalidateHash(); 20 invalidateHash();
21 } 21 }
22 22
23 public static <K, V> MutableNode<K, V> initialize(K key, V value, ContinousHashProvider<? super K> hashProvider, V defaultValue) { 23 public static <K, V> MutableNode<K, V> initialize(K key, V value, ContinuousHashProvider<? super K> hashProvider, V defaultValue) {
24 if (value == defaultValue) { 24 if (value == defaultValue) {
25 return null; 25 return null;
26 } else { 26 } else {
@@ -58,7 +58,7 @@ public class MutableNode<K, V> extends Node<K, V> {
58 } 58 }
59 59
60 @Override 60 @Override
61 public V getValue(K key, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) { 61 public V getValue(K key, ContinuousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) {
62 int selectedHashFragment = hashFragment(hash, shiftDepth(depth)); 62 int selectedHashFragment = hashFragment(hash, shiftDepth(depth));
63 @SuppressWarnings("unchecked") K keyCandidate = (K) this.content[2 * selectedHashFragment]; 63 @SuppressWarnings("unchecked") K keyCandidate = (K) this.content[2 * selectedHashFragment];
64 if (keyCandidate != null) { 64 if (keyCandidate != null) {
@@ -81,7 +81,7 @@ public class MutableNode<K, V> extends Node<K, V> {
81 } 81 }
82 82
83 @Override 83 @Override
84 public Node<K, V> putValue(K key, V value, OldValueBox<V> oldValueBox, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) { 84 public Node<K, V> putValue(K key, V value, OldValueBox<V> oldValueBox, ContinuousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth) {
85 int selectedHashFragment = hashFragment(hash, shiftDepth(depth)); 85 int selectedHashFragment = hashFragment(hash, shiftDepth(depth));
86 @SuppressWarnings("unchecked") K keyCandidate = (K) content[2 * selectedHashFragment]; 86 @SuppressWarnings("unchecked") K keyCandidate = (K) content[2 * selectedHashFragment];
87 if (keyCandidate != null) { 87 if (keyCandidate != null) {
@@ -217,7 +217,7 @@ public class MutableNode<K, V> extends Node<K, V> {
217 } 217 }
218 218
219 @SuppressWarnings("unchecked") 219 @SuppressWarnings("unchecked")
220 private Node<K, V> moveDownAndSplit(ContinousHashProvider<? super K> hashProvider, K newKey, V newValue, K previousKey, int hashOfNewKey, int depth, int selectedHashFragmentOfCurrentDepth) { 220 private Node<K, V> moveDownAndSplit(ContinuousHashProvider<? super K> hashProvider, K newKey, V newValue, K previousKey, int hashOfNewKey, int depth, int selectedHashFragmentOfCurrentDepth) {
221 V previousValue = (V) content[2 * selectedHashFragmentOfCurrentDepth + 1]; 221 V previousValue = (V) content[2 * selectedHashFragmentOfCurrentDepth + 1];
222 222
223 MutableNode<K, V> newSubNode = newNodeWithTwoEntries(hashProvider, previousKey, previousValue, hashProvider.getHash(previousKey, hashDepth(depth)), newKey, newValue, hashOfNewKey, incrementDepth(depth)); 223 MutableNode<K, V> newSubNode = newNodeWithTwoEntries(hashProvider, previousKey, previousValue, hashProvider.getHash(previousKey, hashDepth(depth)), newKey, newValue, hashOfNewKey, incrementDepth(depth));
@@ -230,7 +230,7 @@ public class MutableNode<K, V> extends Node<K, V> {
230 230
231 // Pass everything as parameters for performance. 231 // Pass everything as parameters for performance.
232 @SuppressWarnings("squid:S107") 232 @SuppressWarnings("squid:S107")
233 private MutableNode<K, V> newNodeWithTwoEntries(ContinousHashProvider<? super K> hashProvider, K key1, V value1, int oldHash1, K key2, V value2, int oldHash2, int newDepth) { 233 private MutableNode<K, V> newNodeWithTwoEntries(ContinuousHashProvider<? super K> hashProvider, K key1, V value1, int oldHash1, K key2, V value2, int oldHash2, int newDepth) {
234 int newHash1 = newHash(hashProvider, key1, oldHash1, newDepth); 234 int newHash1 = newHash(hashProvider, key1, oldHash1, newDepth);
235 int newHash2 = newHash(hashProvider, key2, oldHash2, newDepth); 235 int newHash2 = newHash(hashProvider, key2, oldHash2, newDepth);
236 int newFragment1 = hashFragment(newHash1, shiftDepth(newDepth)); 236 int newFragment1 = hashFragment(newHash1, shiftDepth(newDepth));
@@ -418,7 +418,7 @@ public class MutableNode<K, V> extends Node<K, V> {
418 } 418 }
419 419
420 @Override 420 @Override
421 public void checkIntegrity(ContinousHashProvider<? super K> hashProvider, V defaultValue, int depth) { 421 public void checkIntegrity(ContinuousHashProvider<? super K> hashProvider, V defaultValue, int depth) {
422 // check for orphan nodes 422 // check for orphan nodes
423 if (depth > 0) { 423 if (depth > 0) {
424 int orphaned = isOrphaned(); 424 int orphaned = isOrphaned();
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/Node.java
index 4b44f760..0ecf2712 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/Node.java
@@ -1,13 +1,13 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import java.util.Map; 8import java.util.Map;
9 9
10import tools.refinery.store.map.ContinousHashProvider; 10import tools.refinery.store.map.ContinuousHashProvider;
11 11
12public abstract class Node<K, V> { 12public abstract class Node<K, V> {
13 public static final int BRANCHING_FACTOR_BITS = 5; 13 public static final int BRANCHING_FACTOR_BITS = 5;
@@ -77,14 +77,14 @@ public abstract class Node<K, V> {
77 * @param depth The depth. 77 * @param depth The depth.
78 * @return The new hash code. 78 * @return The new hash code.
79 */ 79 */
80 protected int newHash(final ContinousHashProvider<? super K> hashProvider, K key, int hash, int depth) { 80 protected int newHash(final ContinuousHashProvider<? super K> hashProvider, K key, int hash, int depth) {
81 final int shiftDepth = shiftDepth(depth); 81 final int shiftDepth = shiftDepth(depth);
82 if (shiftDepth == 0) { 82 if (shiftDepth == 0) {
83 final int hashDepth = hashDepth(depth); 83 final int hashDepth = hashDepth(depth);
84 if (hashDepth >= ContinousHashProvider.MAX_PRACTICAL_DEPTH) { 84 if (hashDepth >= ContinuousHashProvider.MAX_PRACTICAL_DEPTH) {
85 throw new IllegalArgumentException( 85 throw new IllegalArgumentException(
86 "Key " + key + " have the clashing hashcode over the practical depth limitation (" 86 "Key " + key + " have the clashing hashcode over the practical depth limitation ("
87 + ContinousHashProvider.MAX_PRACTICAL_DEPTH + ")!"); 87 + ContinuousHashProvider.MAX_PRACTICAL_DEPTH + ")!");
88 } 88 }
89 return hashProvider.getHash(key, hashDepth); 89 return hashProvider.getHash(key, hashDepth);
90 } else { 90 } else {
@@ -92,11 +92,11 @@ public abstract class Node<K, V> {
92 } 92 }
93 } 93 }
94 94
95 public abstract V getValue(K key, ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, 95 public abstract V getValue(K key, ContinuousHashProvider<? super K> hashProvider, V defaultValue, int hash,
96 int depth); 96 int depth);
97 97
98 public abstract Node<K, V> putValue(K key, V value, OldValueBox<V> old, 98 public abstract Node<K, V> putValue(K key, V value, OldValueBox<V> old,
99 ContinousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth); 99 ContinuousHashProvider<? super K> hashProvider, V defaultValue, int hash, int depth);
100 100
101 public abstract long getSize(); 101 public abstract long getSize();
102 102
@@ -126,6 +126,6 @@ public abstract class Node<K, V> {
126 return stringBuilder.toString(); 126 return stringBuilder.toString();
127 } 127 }
128 128
129 public void checkIntegrity(ContinousHashProvider<? super K> hashProvider, V defaultValue, int depth) { 129 public void checkIntegrity(ContinuousHashProvider<? super K> hashProvider, V defaultValue, int depth) {
130 } 130 }
131} 131}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/OldValueBox.java
index 354af51d..1b0a4b0c 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/OldValueBox.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8public class OldValueBox<V>{ 8public class OldValueBox<V>{
9 V oldValue; 9 V oldValue;
@@ -20,5 +20,5 @@ public class OldValueBox<V>{
20 this.oldValue = ouldValue; 20 this.oldValue = ouldValue;
21 isSet = true; 21 isSet = true;
22 } 22 }
23 23
24} 24}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/StateBasedVersionedMapStoreFactory.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/StateBasedVersionedMapStoreFactory.java
new file mode 100644
index 00000000..ccc791a8
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/StateBasedVersionedMapStoreFactory.java
@@ -0,0 +1,43 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.map.internal.state;
7
8import tools.refinery.store.map.*;
9
10import java.util.List;
11
12public class StateBasedVersionedMapStoreFactory<K, V> implements VersionedMapStoreFactory<K, V> {
13 private final V defaultValue;
14 private final ContinuousHashProvider<K> continuousHashProvider;
15 private final VersionedMapStoreStateConfiguration config;
16
17 public StateBasedVersionedMapStoreFactory(V defaultValue, Boolean transformToImmutable,
18 VersionedMapStoreFactoryBuilder.SharingStrategy sharingStrategy,
19 boolean versionFreeingEnabled,
20 ContinuousHashProvider<K> continuousHashProvider) {
21 this.defaultValue = defaultValue;
22 this.continuousHashProvider = continuousHashProvider;
23
24 this.config = new VersionedMapStoreStateConfiguration(
25 transformToImmutable,
26 sharingStrategy == VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE
27 || sharingStrategy == VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE_IN_GROUP,
28 sharingStrategy == VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE_IN_GROUP,
29 versionFreeingEnabled);
30 }
31
32 @Override
33 public VersionedMapStore<K, V> createOne() {
34 return new VersionedMapStoreStateImpl<>(continuousHashProvider, defaultValue, config);
35
36 }
37
38 @Override
39 public List<VersionedMapStore<K, V>> createGroup(int amount) {
40 return VersionedMapStoreStateImpl.createSharedVersionedMapStores(amount, continuousHashProvider, defaultValue,
41 config);
42 }
43}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStateImpl.java
index c107f7e0..57eeccf6 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStateImpl.java
@@ -1,9 +1,9 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map.internal; 6package tools.refinery.store.map.internal.state;
7 7
8import tools.refinery.store.map.*; 8import tools.refinery.store.map.*;
9 9
@@ -19,18 +19,18 @@ import java.util.Objects;
19 * @param <V> 19 * @param <V>
20 * @author Oszkar Semerath 20 * @author Oszkar Semerath
21 */ 21 */
22public class VersionedMapImpl<K, V> implements VersionedMap<K, V> { 22public class VersionedMapStateImpl<K, V> implements VersionedMap<K, V> {
23 protected final VersionedMapStoreImpl<K, V> store; 23 protected final VersionedMapStoreStateImpl<K, V> store;
24 24
25 protected final ContinousHashProvider<K> hashProvider; 25 protected final ContinuousHashProvider<K> hashProvider;
26 protected final V defaultValue; 26 protected final V defaultValue;
27 protected Node<K, V> root; 27 protected Node<K, V> root;
28 28
29 private final OldValueBox<V> oldValueBox = new OldValueBox<>(); 29 private final OldValueBox<V> oldValueBox = new OldValueBox<>();
30 30
31 public VersionedMapImpl( 31 public VersionedMapStateImpl(
32 VersionedMapStoreImpl<K, V> store, 32 VersionedMapStoreStateImpl<K, V> store,
33 ContinousHashProvider<K> hashProvider, 33 ContinuousHashProvider<K> hashProvider,
34 V defaultValue) { 34 V defaultValue) {
35 this.store = store; 35 this.store = store;
36 this.hashProvider = hashProvider; 36 this.hashProvider = hashProvider;
@@ -38,9 +38,9 @@ public class VersionedMapImpl<K, V> implements VersionedMap<K, V> {
38 this.root = null; 38 this.root = null;
39 } 39 }
40 40
41 public VersionedMapImpl( 41 public VersionedMapStateImpl(
42 VersionedMapStoreImpl<K, V> store, 42 VersionedMapStoreStateImpl<K, V> store,
43 ContinousHashProvider<K> hashProvider, 43 ContinuousHashProvider<K> hashProvider,
44 V defaultValue, Node<K, V> data) { 44 V defaultValue, Node<K, V> data) {
45 this.store = store; 45 this.store = store;
46 this.hashProvider = hashProvider; 46 this.hashProvider = hashProvider;
@@ -53,7 +53,7 @@ public class VersionedMapImpl<K, V> implements VersionedMap<K, V> {
53 return defaultValue; 53 return defaultValue;
54 } 54 }
55 55
56 public ContinousHashProvider<K> getHashProvider() { 56 public ContinuousHashProvider<K> getHashProvider() {
57 return hashProvider; 57 return hashProvider;
58 } 58 }
59 59
@@ -115,16 +115,16 @@ public class VersionedMapImpl<K, V> implements VersionedMap<K, V> {
115 } 115 }
116 116
117 @Override 117 @Override
118 public DiffCursor<K, V> getDiffCursor(long toVersion) { 118 public DiffCursor<K, V> getDiffCursor(Version toVersion) {
119 InOrderMapCursor<K, V> fromCursor = new InOrderMapCursor<>(this); 119 InOrderMapCursor<K, V> fromCursor = new InOrderMapCursor<>(this);
120 VersionedMapImpl<K, V> toMap = (VersionedMapImpl<K, V>) this.store.createMap(toVersion); 120 VersionedMapStateImpl<K, V> toMap = (VersionedMapStateImpl<K, V>) this.store.createMap(toVersion);
121 InOrderMapCursor<K, V> toCursor = new InOrderMapCursor<>(toMap); 121 InOrderMapCursor<K, V> toCursor = new InOrderMapCursor<>(toMap);
122 return new MapDiffCursor<>(this.defaultValue, fromCursor, toCursor); 122 return new MapDiffCursor<>(this.defaultValue, fromCursor, toCursor);
123 } 123 }
124 124
125 125
126 @Override 126 @Override
127 public long commit() { 127 public Version commit() {
128 return this.store.commit(root, this); 128 return this.store.commit(root, this);
129 } 129 }
130 130
@@ -133,7 +133,7 @@ public class VersionedMapImpl<K, V> implements VersionedMap<K, V> {
133 } 133 }
134 134
135 @Override 135 @Override
136 public void restore(long state) { 136 public void restore(Version state) {
137 root = this.store.revert(state); 137 root = this.store.revert(state);
138 } 138 }
139 139
@@ -166,6 +166,6 @@ public class VersionedMapImpl<K, V> implements VersionedMap<K, V> {
166 166
167 @Override 167 @Override
168 public boolean contentEquals(AnyVersionedMap other) { 168 public boolean contentEquals(AnyVersionedMap other) {
169 return other instanceof VersionedMapImpl<?, ?> otherImpl && Objects.equals(root, otherImpl.root); 169 return other instanceof VersionedMapStateImpl<?, ?> otherImpl && Objects.equals(root, otherImpl.root);
170 } 170 }
171} 171}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateConfiguration.java
index b00cd961..6650f565 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateConfiguration.java
@@ -1,21 +1,25 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.map; 6package tools.refinery.store.map.internal.state;
7 7
8public class VersionedMapStoreConfiguration { 8import tools.refinery.store.map.ContinuousHashProvider;
9import tools.refinery.store.map.VersionedMapStore;
9 10
10 public VersionedMapStoreConfiguration() { 11public class VersionedMapStoreStateConfiguration {
12
13 public VersionedMapStoreStateConfiguration() {
11 14
12 } 15 }
13 public VersionedMapStoreConfiguration(boolean immutableWhenCommitting, boolean sharedNodeCacheInStore, 16 public VersionedMapStoreStateConfiguration(boolean immutableWhenCommitting, boolean sharedNodeCacheInStore,
14 boolean sharedNodeCacheInStoreGroups) { 17 boolean sharedNodeCacheInStoreGroups, boolean versionFreeingEnabled) {
15 super(); 18 super();
16 this.immutableWhenCommitting = immutableWhenCommitting; 19 this.immutableWhenCommitting = immutableWhenCommitting;
17 this.sharedNodeCacheInStore = sharedNodeCacheInStore; 20 this.sharedNodeCacheInStore = sharedNodeCacheInStore;
18 this.sharedNodeCacheInStoreGroups = sharedNodeCacheInStoreGroups; 21 this.sharedNodeCacheInStoreGroups = sharedNodeCacheInStoreGroups;
22 this.versionFreeingEnabled = versionFreeingEnabled;
19 } 23 }
20 24
21 /** 25 /**
@@ -42,12 +46,17 @@ public class VersionedMapStoreConfiguration {
42 46
43 /** 47 /**
44 * If true, all sub-nodes are cached within a group of 48 * If true, all sub-nodes are cached within a group of
45 * {@link VersionedMapStoreImpl#createSharedVersionedMapStores(int, ContinousHashProvider, Object, VersionedMapStoreConfiguration)}. 49 * {@link VersionedMapStoreStateImpl#createSharedVersionedMapStores(int, ContinuousHashProvider, Object, VersionedMapStoreStateConfiguration)}.
46 * If {@link VersionedMapStoreConfiguration#sharedNodeCacheInStore} is 50 * If {@link VersionedMapStoreStateConfiguration#sharedNodeCacheInStore} is
47 * <code>false</code>, then it has currently no impact. 51 * <code>false</code>, then it has currently no impact.
48 */ 52 */
49 private boolean sharedNodeCacheInStoreGroups = true; 53 private boolean sharedNodeCacheInStoreGroups = true;
50 public boolean isSharedNodeCacheInStoreGroups() { 54 public boolean isSharedNodeCacheInStoreGroups() {
51 return sharedNodeCacheInStoreGroups; 55 return sharedNodeCacheInStoreGroups;
52 } 56 }
57
58 private boolean versionFreeingEnabled = true;
59 public boolean isVersionFreeingEnabled() {
60 return versionFreeingEnabled;
61 }
53} 62}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateImpl.java
new file mode 100644
index 00000000..8ff3f8e7
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/state/VersionedMapStoreStateImpl.java
@@ -0,0 +1,119 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.map.internal.state;
7
8import tools.refinery.store.map.*;
9
10import java.util.*;
11
12public class VersionedMapStoreStateImpl<K, V> implements VersionedMapStore<K, V> {
13 // Configuration
14 private final boolean immutableWhenCommitting;
15
16 // Static data
17 protected final ContinuousHashProvider<K> hashProvider;
18 protected final V defaultValue;
19
20 protected final Map<Node<K, V>, ImmutableNode<K, V>> nodeCache;
21
22 public VersionedMapStoreStateImpl(ContinuousHashProvider<K> hashProvider, V defaultValue,
23 VersionedMapStoreStateConfiguration config) {
24 this.immutableWhenCommitting = config.isImmutableWhenCommitting();
25 this.hashProvider = hashProvider;
26 this.defaultValue = defaultValue;
27 if (config.isSharedNodeCacheInStore()) {
28 nodeCache = createNoteCache(config);
29 } else {
30 nodeCache = null;
31 }
32 }
33
34 private VersionedMapStoreStateImpl(ContinuousHashProvider<K> hashProvider, V defaultValue,
35 Map<Node<K, V>, ImmutableNode<K, V>> nodeCache, VersionedMapStoreStateConfiguration config) {
36 this.immutableWhenCommitting = config.isImmutableWhenCommitting();
37 this.hashProvider = hashProvider;
38 this.defaultValue = defaultValue;
39 this.nodeCache = nodeCache;
40 }
41
42 public VersionedMapStoreStateImpl(ContinuousHashProvider<K> hashProvider, V defaultValue) {
43 this(hashProvider, defaultValue, new VersionedMapStoreStateConfiguration());
44 }
45
46 public static <K, V> List<VersionedMapStore<K, V>> createSharedVersionedMapStores(int amount,
47 ContinuousHashProvider<K> hashProvider, V defaultValue,
48 VersionedMapStoreStateConfiguration config) {
49 List<VersionedMapStore<K, V>> result = new ArrayList<>(amount);
50 if (config.isSharedNodeCacheInStoreGroups()) {
51 Map<Node<K, V>, ImmutableNode<K, V>> nodeCache;
52 if (config.isSharedNodeCacheInStore()) {
53 nodeCache = createNoteCache(config);
54 } else {
55 nodeCache = null;
56 }
57 for (int i = 0; i < amount; i++) {
58 result.add(new VersionedMapStoreStateImpl<>(hashProvider, defaultValue, nodeCache, config));
59 }
60 } else {
61 for (int i = 0; i < amount; i++) {
62 result.add(new VersionedMapStoreStateImpl<>(hashProvider, defaultValue, config));
63 }
64 }
65 return result;
66 }
67
68 private static <K,V> Map<K,V> createNoteCache(VersionedMapStoreStateConfiguration config) {
69 if(config.isVersionFreeingEnabled()) {
70 return new WeakHashMap<>();
71 } else {
72 return new HashMap<>();
73 }
74 }
75
76 public static <K, V> List<VersionedMapStore<K, V>> createSharedVersionedMapStores(int amount,
77 ContinuousHashProvider<K> hashProvider, V defaultValue) {
78 return createSharedVersionedMapStores(amount, hashProvider, defaultValue, new VersionedMapStoreStateConfiguration());
79 }
80
81 @Override
82 public VersionedMap<K, V> createMap() {
83 return new VersionedMapStateImpl<>(this, hashProvider, defaultValue);
84 }
85
86 @Override
87 public VersionedMap<K, V> createMap(Version state) {
88 ImmutableNode<K, V> data = revert(state);
89 return new VersionedMapStateImpl<>(this, hashProvider, defaultValue, data);
90 }
91
92 @SuppressWarnings("unchecked")
93 public synchronized ImmutableNode<K, V> revert(Version state) {
94 return (ImmutableNode<K, V>) state;
95 }
96
97 public synchronized Version commit(Node<K, V> data, VersionedMapStateImpl<K, V> mapToUpdateRoot) {
98 ImmutableNode<K, V> immutable;
99 if (data != null) {
100 immutable = data.toImmutable(this.nodeCache);
101 } else {
102 immutable = null;
103 }
104
105 if (this.immutableWhenCommitting) {
106 mapToUpdateRoot.setRoot(immutable);
107 }
108 return immutable;
109 }
110
111 @Override
112 public DiffCursor<K, V> getDiffCursor(Version fromState, Version toState) {
113 VersionedMapStateImpl<K, V> map1 = (VersionedMapStateImpl<K, V>) createMap(fromState);
114 VersionedMapStateImpl<K, V> map2 = (VersionedMapStateImpl<K, V>) createMap(toState);
115 InOrderMapCursor<K, V> cursor1 = new InOrderMapCursor<>(map1);
116 InOrderMapCursor<K, V> cursor2 = new InOrderMapCursor<>(map2);
117 return new MapDiffCursor<>(this.defaultValue, cursor1, cursor2);
118 }
119}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java
index 26ad9a69..72f188d3 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java
@@ -7,6 +7,7 @@ package tools.refinery.store.model;
7 7
8import tools.refinery.store.map.Cursor; 8import tools.refinery.store.map.Cursor;
9import tools.refinery.store.map.DiffCursor; 9import tools.refinery.store.map.DiffCursor;
10import tools.refinery.store.map.Version;
10import tools.refinery.store.representation.Symbol; 11import tools.refinery.store.representation.Symbol;
11import tools.refinery.store.tuple.Tuple; 12import tools.refinery.store.tuple.Tuple;
12 13
@@ -22,7 +23,7 @@ public non-sealed interface Interpretation<T> extends AnyInterpretation {
22 23
23 void putAll(Cursor<Tuple, T> cursor); 24 void putAll(Cursor<Tuple, T> cursor);
24 25
25 DiffCursor<Tuple, T> getDiffCursor(long to); 26 DiffCursor<Tuple, T> getDiffCursor(Version to);
26 27
27 void addListener(InterpretationListener<T> listener, boolean alsoWhenRestoring); 28 void addListener(InterpretationListener<T> listener, boolean alsoWhenRestoring);
28 29
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/Model.java b/subprojects/store/src/main/java/tools/refinery/store/model/Model.java
index 703a0720..e2ab72e7 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/Model.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/Model.java
@@ -6,6 +6,7 @@
6package tools.refinery.store.model; 6package tools.refinery.store.model;
7 7
8import tools.refinery.store.adapter.ModelAdapter; 8import tools.refinery.store.adapter.ModelAdapter;
9import tools.refinery.store.map.Version;
9import tools.refinery.store.map.Versioned; 10import tools.refinery.store.map.Versioned;
10import tools.refinery.store.model.internal.VersionedInterpretation; 11import tools.refinery.store.model.internal.VersionedInterpretation;
11import tools.refinery.store.representation.AnySymbol; 12import tools.refinery.store.representation.AnySymbol;
@@ -15,11 +16,10 @@ import java.util.Map;
15import java.util.Optional; 16import java.util.Optional;
16 17
17public interface Model extends Versioned { 18public interface Model extends Versioned {
18 long NO_STATE_ID = -1; 19 Version NO_STATE_ID = null;
19
20 ModelStore getStore(); 20 ModelStore getStore();
21 21
22 long getState(); 22 Version getState();
23 23
24 boolean hasUncommittedChanges(); 24 boolean hasUncommittedChanges();
25 25
@@ -29,9 +29,7 @@ public interface Model extends Versioned {
29 29
30 <T> Interpretation<T> getInterpretation(Symbol<T> symbol); 30 <T> Interpretation<T> getInterpretation(Symbol<T> symbol);
31 31
32 public Map<? extends AnySymbol, ? extends Interpretation<?>> getInterpretations(); 32 ModelDiffCursor getDiffCursor(Version to);
33
34 ModelDiffCursor getDiffCursor(long to);
35 33
36 <T extends ModelAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType); 34 <T extends ModelAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType);
37 35
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java
index a9ad8cfd..703ee10a 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java
@@ -5,6 +5,8 @@
5 */ 5 */
6package tools.refinery.store.model; 6package tools.refinery.store.model;
7 7
8import tools.refinery.store.map.Version;
9
8public interface ModelListener { 10public interface ModelListener {
9 default void beforeCommit() { 11 default void beforeCommit() {
10 } 12 }
@@ -12,7 +14,7 @@ public interface ModelListener {
12 default void afterCommit() { 14 default void afterCommit() {
13 } 15 }
14 16
15 default void beforeRestore(long state) { 17 default void beforeRestore(Version state) {
16 } 18 }
17 19
18 default void afterRestore() { 20 default void afterRestore() {
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java
index b10eb8a4..89382b3a 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java
@@ -6,23 +6,21 @@
6package tools.refinery.store.model; 6package tools.refinery.store.model;
7 7
8import tools.refinery.store.adapter.ModelStoreAdapter; 8import tools.refinery.store.adapter.ModelStoreAdapter;
9import tools.refinery.store.map.Version;
9import tools.refinery.store.model.internal.ModelStoreBuilderImpl; 10import tools.refinery.store.model.internal.ModelStoreBuilderImpl;
10import tools.refinery.store.representation.AnySymbol; 11import tools.refinery.store.representation.AnySymbol;
11 12
12import java.util.Collection; 13import java.util.Collection;
13import java.util.Optional; 14import java.util.Optional;
14import java.util.Set;
15 15
16public interface ModelStore { 16public interface ModelStore {
17 Collection<AnySymbol> getSymbols(); 17 Collection<AnySymbol> getSymbols();
18 18
19 Model createEmptyModel(); 19 Model createEmptyModel();
20 20
21 Model createModelForState(long state); 21 Model createModelForState(Version state);
22 22
23 Set<Long> getStates(); 23 ModelDiffCursor getDiffCursor(Version from, Version to);
24
25 ModelDiffCursor getDiffCursor(long from, long to);
26 24
27 <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType); 25 <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType);
28 26
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java
index fdd4425e..3c94541f 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java
@@ -5,12 +5,12 @@
5 */ 5 */
6package tools.refinery.store.model; 6package tools.refinery.store.model;
7 7
8import tools.refinery.store.map.ContinousHashProvider; 8import tools.refinery.store.map.ContinuousHashProvider;
9import tools.refinery.store.tuple.Tuple; 9import tools.refinery.store.tuple.Tuple;
10import tools.refinery.store.tuple.Tuple1; 10import tools.refinery.store.tuple.Tuple1;
11import tools.refinery.store.tuple.Tuple2; 11import tools.refinery.store.tuple.Tuple2;
12 12
13public class TupleHashProvider implements ContinousHashProvider<Tuple> { 13public class TupleHashProvider implements ContinuousHashProvider<Tuple> {
14 protected static final int[] primes = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 14 protected static final int[] primes = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
15 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 15 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
16 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 16 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java
deleted file mode 100644
index 14116a90..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java
+++ /dev/null
@@ -1,34 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.model;
7
8import tools.refinery.store.map.ContinousHashProvider;
9import tools.refinery.store.tuple.Tuple;
10
11public class TupleHashProviderBitMagic implements ContinousHashProvider<Tuple> {
12
13 @Override
14 public int getHash(Tuple key, int index) {
15 if(key.getSize() == 1) {
16 return key.get(0);
17 }
18
19 int result = 0;
20 final int startBitIndex = index*30;
21 final int finalBitIndex = startBitIndex+30;
22 final int arity = key.getSize();
23
24 for(int i = startBitIndex; i<=finalBitIndex; i++) {
25 final int selectedKey = key.get(i%arity);
26 final int selectedPosition = 1<<(i/arity);
27 if((selectedKey&selectedPosition) != 0) {
28 result |= 1<<(i%30);
29 }
30 }
31
32 return result;
33 }
34}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java
index bf6987d6..92694af4 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java
@@ -8,6 +8,7 @@ package tools.refinery.store.model.internal;
8import tools.refinery.store.adapter.AdapterUtils; 8import tools.refinery.store.adapter.AdapterUtils;
9import tools.refinery.store.adapter.ModelAdapter; 9import tools.refinery.store.adapter.ModelAdapter;
10import tools.refinery.store.map.DiffCursor; 10import tools.refinery.store.map.DiffCursor;
11import tools.refinery.store.map.Version;
11import tools.refinery.store.model.*; 12import tools.refinery.store.model.*;
12import tools.refinery.store.representation.AnySymbol; 13import tools.refinery.store.representation.AnySymbol;
13import tools.refinery.store.representation.Symbol; 14import tools.refinery.store.representation.Symbol;
@@ -17,21 +18,21 @@ import java.util.*;
17 18
18public class ModelImpl implements Model { 19public class ModelImpl implements Model {
19 private final ModelStore store; 20 private final ModelStore store;
20 private long state; 21 private Version state;
21 private Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations; 22 private LinkedHashMap<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations;
22 private final List<ModelAdapter> adapters; 23 private final List<ModelAdapter> adapters;
23 private final List<ModelListener> listeners = new ArrayList<>(); 24 private final List<ModelListener> listeners = new ArrayList<>();
24 private boolean uncommittedChanges; 25 private boolean uncommittedChanges;
25 private ModelAction pendingAction = ModelAction.NONE; 26 private ModelAction pendingAction = ModelAction.NONE;
26 private long restoringToState = NO_STATE_ID; 27 private Version restoringToState = null;
27 28
28 ModelImpl(ModelStore store, long state, int adapterCount) { 29 ModelImpl(ModelStore store, Version state, int adapterCount) {
29 this.store = store; 30 this.store = store;
30 this.state = state; 31 this.state = state;
31 adapters = new ArrayList<>(adapterCount); 32 adapters = new ArrayList<>(adapterCount);
32 } 33 }
33 34
34 void setInterpretations(Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations) { 35 void setInterpretations(LinkedHashMap<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations) {
35 this.interpretations = interpretations; 36 this.interpretations = interpretations;
36 } 37 }
37 38
@@ -41,7 +42,7 @@ public class ModelImpl implements Model {
41 } 42 }
42 43
43 @Override 44 @Override
44 public long getState() { 45 public Version getState() {
45 return state; 46 return state;
46 } 47 }
47 48
@@ -57,7 +58,7 @@ public class ModelImpl implements Model {
57 } 58 }
58 59
59 @Override 60 @Override
60 public ModelDiffCursor getDiffCursor(long to) { 61 public ModelDiffCursor getDiffCursor(Version to) {
61 var diffCursors = new HashMap<AnySymbol, DiffCursor<Tuple, ?>>(interpretations.size()); 62 var diffCursors = new HashMap<AnySymbol, DiffCursor<Tuple, ?>>(interpretations.size());
62 for (var entry : interpretations.entrySet()) { 63 for (var entry : interpretations.entrySet()) {
63 diffCursors.put(entry.getKey(), entry.getValue().getDiffCursor(to)); 64 diffCursors.put(entry.getKey(), entry.getValue().getDiffCursor(to));
@@ -65,7 +66,7 @@ public class ModelImpl implements Model {
65 return new ModelDiffCursor(diffCursors); 66 return new ModelDiffCursor(diffCursors);
66 } 67 }
67 68
68 private void setState(long state) { 69 private void setState(Version state) {
69 this.state = state; 70 this.state = state;
70 uncommittedChanges = false; 71 uncommittedChanges = false;
71 } 72 }
@@ -82,11 +83,11 @@ public class ModelImpl implements Model {
82 } 83 }
83 84
84 private boolean hasPendingAction() { 85 private boolean hasPendingAction() {
85 return pendingAction != ModelAction.NONE || restoringToState != NO_STATE_ID; 86 return pendingAction != ModelAction.NONE || restoringToState != null;
86 } 87 }
87 88
88 @Override 89 @Override
89 public long commit() { 90 public Version commit() {
90 if (hasPendingAction()) { 91 if (hasPendingAction()) {
91 throw pendingActionError("commit"); 92 throw pendingActionError("commit");
92 } 93 }
@@ -94,43 +95,40 @@ public class ModelImpl implements Model {
94 try { 95 try {
95 int listenerCount = listeners.size(); 96 int listenerCount = listeners.size();
96 int i = listenerCount; 97 int i = listenerCount;
97 long version = 0; 98
99 // Before commit message to listeners
98 while (i > 0) { 100 while (i > 0) {
99 i--; 101 i--;
100 listeners.get(i).beforeCommit(); 102 listeners.get(i).beforeCommit();
101 } 103 }
102 boolean versionSet = false; 104
103 for (var interpretation : interpretations.values()) { 105 // Doing the commit on the interpretations
104 long newVersion = interpretation.commit(); 106 Version[] interpretationVersions = new Version[interpretations.size()];
105 if (versionSet) { 107 int j = 0;
106 if (version != newVersion) { 108 for(var interpretationEntry : interpretations.entrySet()) {
107 throw new IllegalStateException("Interpretations in model have different versions (%d and %d)" 109 interpretationVersions[j++] = interpretationEntry.getValue().commit();
108 .formatted(version, newVersion));
109 }
110 } else {
111 version = newVersion;
112 versionSet = true;
113 }
114 } 110 }
115 setState(version); 111 ModelVersion modelVersion = new ModelVersion(interpretationVersions);
112 setState(modelVersion);
113
114 // After commit message to listeners
116 while (i < listenerCount) { 115 while (i < listenerCount) {
117 listeners.get(i).afterCommit(); 116 listeners.get(i).afterCommit();
118 i++; 117 i++;
119 } 118 }
120 return version; 119
120 return modelVersion;
121 } finally { 121 } finally {
122 pendingAction = ModelAction.NONE; 122 pendingAction = ModelAction.NONE;
123 } 123 }
124 } 124 }
125 125
126 @Override 126 @Override
127 public void restore(long version) { 127 public void restore(Version version) {
128 if (hasPendingAction()) { 128 if (hasPendingAction()) {
129 throw pendingActionError("restore to %d".formatted(version)); 129 throw pendingActionError("restore to %s".formatted(version));
130 }
131 if (!store.getStates().contains(version)) {
132 throw new IllegalArgumentException("Store does not contain state %d".formatted(version));
133 } 130 }
131
134 pendingAction = ModelAction.RESTORE; 132 pendingAction = ModelAction.RESTORE;
135 restoringToState = version; 133 restoringToState = version;
136 try { 134 try {
@@ -140,9 +138,11 @@ public class ModelImpl implements Model {
140 i--; 138 i--;
141 listeners.get(i).beforeRestore(version); 139 listeners.get(i).beforeRestore(version);
142 } 140 }
141 int j = 0;
143 for (var interpretation : interpretations.values()) { 142 for (var interpretation : interpretations.values()) {
144 interpretation.restore(version); 143 interpretation.restore(ModelVersion.getInternalVersion(version,j++));
145 } 144 }
145
146 setState(version); 146 setState(version);
147 while (i < listenerCount) { 147 while (i < listenerCount) {
148 listeners.get(i).afterRestore(); 148 listeners.get(i).afterRestore();
@@ -150,7 +150,7 @@ public class ModelImpl implements Model {
150 } 150 }
151 } finally { 151 } finally {
152 pendingAction = ModelAction.NONE; 152 pendingAction = ModelAction.NONE;
153 restoringToState = NO_STATE_ID; 153 restoringToState = null;
154 } 154 }
155 } 155 }
156 156
@@ -159,7 +159,7 @@ public class ModelImpl implements Model {
159 case NONE -> throw new IllegalArgumentException("Trying to throw pending action error when there is no " + 159 case NONE -> throw new IllegalArgumentException("Trying to throw pending action error when there is no " +
160 "pending action"); 160 "pending action");
161 case COMMIT -> "commit"; 161 case COMMIT -> "commit";
162 case RESTORE -> "restore to %d".formatted(restoringToState); 162 case RESTORE -> "restore to %s".formatted(restoringToState);
163 }; 163 };
164 return new IllegalStateException("Cannot %s due to pending %s".formatted(currentActionName, pendingActionName)); 164 return new IllegalStateException("Cannot %s due to pending %s".formatted(currentActionName, pendingActionName));
165 } 165 }
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java
index 24d4088a..2bd187a8 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java
@@ -8,10 +8,10 @@ package tools.refinery.store.model.internal;
8import tools.refinery.store.adapter.AdapterUtils; 8import tools.refinery.store.adapter.AdapterUtils;
9import tools.refinery.store.adapter.ModelAdapterBuilder; 9import tools.refinery.store.adapter.ModelAdapterBuilder;
10import tools.refinery.store.map.VersionedMapStore; 10import tools.refinery.store.map.VersionedMapStore;
11import tools.refinery.store.map.VersionedMapStoreImpl; 11import tools.refinery.store.map.VersionedMapStoreFactory;
12import tools.refinery.store.map.VersionedMapStoreFactoryBuilder;
12import tools.refinery.store.model.ModelStore; 13import tools.refinery.store.model.ModelStore;
13import tools.refinery.store.model.ModelStoreBuilder; 14import tools.refinery.store.model.ModelStoreBuilder;
14import tools.refinery.store.model.TupleHashProvider;
15import tools.refinery.store.representation.AnySymbol; 15import tools.refinery.store.representation.AnySymbol;
16import tools.refinery.store.representation.Symbol; 16import tools.refinery.store.representation.Symbol;
17import tools.refinery.store.tuple.Tuple; 17import tools.refinery.store.tuple.Tuple;
@@ -19,8 +19,8 @@ import tools.refinery.store.tuple.Tuple;
19import java.util.*; 19import java.util.*;
20 20
21public class ModelStoreBuilderImpl implements ModelStoreBuilder { 21public class ModelStoreBuilderImpl implements ModelStoreBuilder {
22 private final Set<AnySymbol> allSymbols = new HashSet<>(); 22 private final LinkedHashSet<AnySymbol> allSymbols = new LinkedHashSet<>();
23 private final Map<SymbolEquivalenceClass<?>, List<AnySymbol>> equivalenceClasses = new HashMap<>(); 23 private final LinkedHashMap<SymbolEquivalenceClass<?>, List<AnySymbol>> equivalenceClasses = new LinkedHashMap<>();
24 private final List<ModelAdapterBuilder> adapters = new ArrayList<>(); 24 private final List<ModelAdapterBuilder> adapters = new ArrayList<>();
25 25
26 @Override 26 @Override
@@ -62,7 +62,7 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder {
62 for (int i = adapters.size() - 1; i >= 0; i--) { 62 for (int i = adapters.size() - 1; i >= 0; i--) {
63 adapters.get(i).configure(this); 63 adapters.get(i).configure(this);
64 } 64 }
65 var stores = new HashMap<AnySymbol, VersionedMapStore<Tuple, ?>>(allSymbols.size()); 65 var stores = new LinkedHashMap<AnySymbol, VersionedMapStore<Tuple, ?>>(allSymbols.size());
66 for (var entry : equivalenceClasses.entrySet()) { 66 for (var entry : equivalenceClasses.entrySet()) {
67 createStores(stores, entry.getKey(), entry.getValue()); 67 createStores(stores, entry.getKey(), entry.getValue());
68 } 68 }
@@ -77,8 +77,12 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder {
77 private <T> void createStores(Map<AnySymbol, VersionedMapStore<Tuple, ?>> stores, 77 private <T> void createStores(Map<AnySymbol, VersionedMapStore<Tuple, ?>> stores,
78 SymbolEquivalenceClass<T> equivalenceClass, List<AnySymbol> symbols) { 78 SymbolEquivalenceClass<T> equivalenceClass, List<AnySymbol> symbols) {
79 int size = symbols.size(); 79 int size = symbols.size();
80 var storeGroup = VersionedMapStoreImpl.createSharedVersionedMapStores(size, TupleHashProvider.INSTANCE, 80 VersionedMapStoreFactory<Tuple,T> mapFactory = VersionedMapStore
81 equivalenceClass.defaultValue()); 81 .<Tuple,T>builder()
82 .strategy(VersionedMapStoreFactoryBuilder.StoreStrategy.DELTA)
83 .defaultValue(equivalenceClass.defaultValue())
84 .build();
85 var storeGroup = mapFactory.createGroup(size);
82 for (int i = 0; i < size; i++) { 86 for (int i = 0; i < size; i++) {
83 stores.put(symbols.get(i), storeGroup.get(i)); 87 stores.put(symbols.get(i), storeGroup.get(i));
84 } 88 }
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java
index 60b735e6..a320a618 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java
@@ -8,8 +8,8 @@ package tools.refinery.store.model.internal;
8import tools.refinery.store.adapter.AdapterUtils; 8import tools.refinery.store.adapter.AdapterUtils;
9import tools.refinery.store.adapter.ModelStoreAdapter; 9import tools.refinery.store.adapter.ModelStoreAdapter;
10import tools.refinery.store.map.DiffCursor; 10import tools.refinery.store.map.DiffCursor;
11import tools.refinery.store.map.Version;
11import tools.refinery.store.map.VersionedMapStore; 12import tools.refinery.store.map.VersionedMapStore;
12import tools.refinery.store.model.Model;
13import tools.refinery.store.model.ModelDiffCursor; 13import tools.refinery.store.model.ModelDiffCursor;
14import tools.refinery.store.model.ModelStore; 14import tools.refinery.store.model.ModelStore;
15import tools.refinery.store.representation.AnySymbol; 15import tools.refinery.store.representation.AnySymbol;
@@ -18,10 +18,10 @@ import tools.refinery.store.tuple.Tuple;
18import java.util.*; 18import java.util.*;
19 19
20public class ModelStoreImpl implements ModelStore { 20public class ModelStoreImpl implements ModelStore {
21 private final Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores; 21 private final LinkedHashMap<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores;
22 private final List<ModelStoreAdapter> adapters; 22 private final List<ModelStoreAdapter> adapters;
23 23
24 ModelStoreImpl(Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores, int adapterCount) { 24 ModelStoreImpl(LinkedHashMap<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores, int adapterCount) {
25 this.stores = stores; 25 this.stores = stores;
26 adapters = new ArrayList<>(adapterCount); 26 adapters = new ArrayList<>(adapterCount);
27 } 27 }
@@ -31,14 +31,14 @@ public class ModelStoreImpl implements ModelStore {
31 return Collections.unmodifiableCollection(stores.keySet()); 31 return Collections.unmodifiableCollection(stores.keySet());
32 } 32 }
33 33
34 private ModelImpl createModelWithoutInterpretations(long state) { 34 private ModelImpl createModelWithoutInterpretations(Version state) {
35 return new ModelImpl(this, state, adapters.size()); 35 return new ModelImpl(this, state, adapters.size());
36 } 36 }
37 37
38 @Override 38 @Override
39 public ModelImpl createEmptyModel() { 39 public ModelImpl createEmptyModel() {
40 var model = createModelWithoutInterpretations(Model.NO_STATE_ID); 40 var model = createModelWithoutInterpretations(null);
41 var interpretations = new HashMap<AnySymbol, VersionedInterpretation<?>>(stores.size()); 41 var interpretations = new LinkedHashMap<AnySymbol, VersionedInterpretation<?>>(stores.size());
42 for (var entry : this.stores.entrySet()) { 42 for (var entry : this.stores.entrySet()) {
43 var symbol = entry.getKey(); 43 var symbol = entry.getKey();
44 interpretations.put(symbol, VersionedInterpretation.of(model, symbol, entry.getValue())); 44 interpretations.put(symbol, VersionedInterpretation.of(model, symbol, entry.getValue()));
@@ -49,13 +49,21 @@ public class ModelStoreImpl implements ModelStore {
49 } 49 }
50 50
51 @Override 51 @Override
52 public synchronized ModelImpl createModelForState(long state) { 52 public synchronized ModelImpl createModelForState(Version state) {
53 var model = createModelWithoutInterpretations(state); 53 var model = createModelWithoutInterpretations(state);
54 var interpretations = new HashMap<AnySymbol, VersionedInterpretation<?>>(stores.size()); 54 var interpretations = new LinkedHashMap<AnySymbol, VersionedInterpretation<?>>(stores.size());
55
56 int i=0;
55 for (var entry : this.stores.entrySet()) { 57 for (var entry : this.stores.entrySet()) {
56 var symbol = entry.getKey(); 58 var symbol = entry.getKey();
57 interpretations.put(symbol, VersionedInterpretation.of(model, symbol, entry.getValue(), state)); 59 interpretations.put(symbol,
60 VersionedInterpretation.of(
61 model,
62 symbol,
63 entry.getValue(),
64 ModelVersion.getInternalVersion(state,i++)));
58 } 65 }
66
59 model.setInterpretations(interpretations); 67 model.setInterpretations(interpretations);
60 adaptModel(model); 68 adaptModel(model);
61 return model; 69 return model;
@@ -69,16 +77,7 @@ public class ModelStoreImpl implements ModelStore {
69 } 77 }
70 78
71 @Override 79 @Override
72 public synchronized Set<Long> getStates() { 80 public synchronized ModelDiffCursor getDiffCursor(Version from, Version to) {
73 var iterator = stores.values().iterator();
74 if (iterator.hasNext()) {
75 return Set.copyOf(iterator.next().getStates());
76 }
77 return Set.of(0L);
78 }
79
80 @Override
81 public synchronized ModelDiffCursor getDiffCursor(long from, long to) {
82 var diffCursors = new HashMap<AnySymbol, DiffCursor<?, ?>>(); 81 var diffCursors = new HashMap<AnySymbol, DiffCursor<?, ?>>();
83 for (var entry : stores.entrySet()) { 82 for (var entry : stores.entrySet()) {
84 var representation = entry.getKey(); 83 var representation = entry.getKey();
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelVersion.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelVersion.java
new file mode 100644
index 00000000..cf3b7fc6
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelVersion.java
@@ -0,0 +1,39 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.model.internal;
7
8import tools.refinery.store.map.Version;
9
10import java.util.Arrays;
11
12public record ModelVersion(Version[] mapVersions) implements Version{
13
14 public static Version getInternalVersion(Version modelVersion, int interpretationIndex) {
15 return ((ModelVersion)modelVersion).mapVersions()[interpretationIndex];
16 }
17
18 @Override
19 public int hashCode() {
20 return Arrays.hashCode(mapVersions);
21 }
22
23 @Override
24 public boolean equals(Object o) {
25 if (this == o) return true;
26 if (o == null || getClass() != o.getClass()) return false;
27
28 ModelVersion that = (ModelVersion) o;
29
30 return Arrays.equals(mapVersions, that.mapVersions);
31 }
32
33 @Override
34 public String toString() {
35 return "ModelVersion{" +
36 "mapVersions=" + Arrays.toString(mapVersions) +
37 '}';
38 }
39}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java
index 404be65f..76e3baea 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java
@@ -5,10 +5,7 @@
5 */ 5 */
6package tools.refinery.store.model.internal; 6package tools.refinery.store.model.internal;
7 7
8import tools.refinery.store.map.Cursor; 8import tools.refinery.store.map.*;
9import tools.refinery.store.map.DiffCursor;
10import tools.refinery.store.map.VersionedMap;
11import tools.refinery.store.map.VersionedMapStore;
12import tools.refinery.store.model.Interpretation; 9import tools.refinery.store.model.Interpretation;
13import tools.refinery.store.model.InterpretationListener; 10import tools.refinery.store.model.InterpretationListener;
14import tools.refinery.store.model.Model; 11import tools.refinery.store.model.Model;
@@ -110,15 +107,14 @@ public class VersionedInterpretation<T> implements Interpretation<T> {
110 } 107 }
111 108
112 @Override 109 @Override
113 public DiffCursor<Tuple, T> getDiffCursor(long to) { 110 public DiffCursor<Tuple, T> getDiffCursor(Version to) {
114 return map.getDiffCursor(to); 111 return map.getDiffCursor(to);
115 } 112 }
116 113
117 public long commit() { 114 Version commit() {
118 return map.commit(); 115 return map.commit();
119 } 116 }
120 117 void restore(Version state) {
121 public void restore(long state) {
122 if (!restoreListeners.isEmpty()) { 118 if (!restoreListeners.isEmpty()) {
123 var diffCursor = getDiffCursor(state); 119 var diffCursor = getDiffCursor(state);
124 while (diffCursor.move()) { 120 while (diffCursor.move()) {
@@ -150,7 +146,7 @@ public class VersionedInterpretation<T> implements Interpretation<T> {
150 } 146 }
151 147
152 static <T> VersionedInterpretation<T> of(ModelImpl model, AnySymbol symbol, VersionedMapStore<Tuple, T> store, 148 static <T> VersionedInterpretation<T> of(ModelImpl model, AnySymbol symbol, VersionedMapStore<Tuple, T> store,
153 long state) { 149 Version state) {
154 @SuppressWarnings("unchecked") 150 @SuppressWarnings("unchecked")
155 var typedSymbol = (Symbol<T>) symbol; 151 var typedSymbol = (Symbol<T>) symbol;
156 var map = store.createMap(state); 152 var map = store.createMap(state);
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/InOrderCursorTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/InOrderCursorTest.java
index 4ada4ea4..98756460 100644
--- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/InOrderCursorTest.java
+++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/InOrderCursorTest.java
@@ -8,8 +8,8 @@ package tools.refinery.store.map.tests;
8import org.junit.jupiter.api.Test; 8import org.junit.jupiter.api.Test;
9import tools.refinery.store.map.VersionedMapStore; 9import tools.refinery.store.map.VersionedMapStore;
10import tools.refinery.store.map.VersionedMapStoreFactoryBuilder; 10import tools.refinery.store.map.VersionedMapStoreFactoryBuilder;
11import tools.refinery.store.map.internal.InOrderMapCursor; 11import tools.refinery.store.map.internal.state.InOrderMapCursor;
12import tools.refinery.store.map.internal.VersionedMapImpl; 12import tools.refinery.store.map.internal.state.VersionedMapStateImpl;
13import tools.refinery.store.map.tests.utils.MapTestEnvironment; 13import tools.refinery.store.map.tests.utils.MapTestEnvironment;
14 14
15import static org.junit.jupiter.api.Assertions.*; 15import static org.junit.jupiter.api.Assertions.*;
@@ -26,7 +26,7 @@ class InOrderCursorTest {
26 .build() 26 .build()
27 .createOne(); 27 .createOne();
28 28
29 VersionedMapImpl<Integer,String> map = (VersionedMapImpl<Integer,String>) store.createMap(); 29 VersionedMapStateImpl<Integer,String> map = (VersionedMapStateImpl<Integer,String>) store.createMap();
30 checkMove(map,0); 30 checkMove(map,0);
31 31
32 map.put(1,"A"); 32 map.put(1,"A");
@@ -44,7 +44,7 @@ class InOrderCursorTest {
44 44
45 } 45 }
46 46
47 private void checkMove(VersionedMapImpl<Integer,String> map, int num) { 47 private void checkMove(VersionedMapStateImpl<Integer,String> map, int num) {
48 InOrderMapCursor<Integer,String> cursor = new InOrderMapCursor<>(map); 48 InOrderMapCursor<Integer,String> cursor = new InOrderMapCursor<>(map);
49 for(int i=0; i<num; i++) { 49 for(int i=0; i<num; i++) {
50 assertTrue(cursor.move()); 50 assertTrue(cursor.move());
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java
index 2be49bd9..cc2e425c 100644
--- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java
+++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java
@@ -7,7 +7,7 @@ package tools.refinery.store.map.tests;
7 7
8import org.junit.jupiter.api.Test; 8import org.junit.jupiter.api.Test;
9import tools.refinery.store.map.VersionedMapStore; 9import tools.refinery.store.map.VersionedMapStore;
10import tools.refinery.store.map.VersionedMapStoreImpl; 10import tools.refinery.store.map.internal.state.VersionedMapStoreStateImpl;
11import tools.refinery.store.model.TupleHashProvider; 11import tools.refinery.store.model.TupleHashProvider;
12import tools.refinery.store.tuple.Tuple; 12import tools.refinery.store.tuple.Tuple;
13 13
@@ -16,7 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
16class MapUnitTests { 16class MapUnitTests {
17 @Test 17 @Test
18 void defaultTest() { 18 void defaultTest() {
19 VersionedMapStore<Tuple, Boolean> store = new VersionedMapStoreImpl<>(TupleHashProvider.INSTANCE, false); 19 VersionedMapStore<Tuple, Boolean> store = new VersionedMapStoreStateImpl<>(TupleHashProvider.INSTANCE, false);
20 var map = store.createMap(); 20 var map = store.createMap();
21 var out1 = map.put(Tuple.of(0), true); 21 var out1 = map.put(Tuple.of(0), true);
22 assertEquals(false, out1); 22 assertEquals(false, out1);
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/DiffCursorFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/DiffCursorFuzzTest.java
index 5a4f8038..94259edc 100644
--- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/DiffCursorFuzzTest.java
+++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/DiffCursorFuzzTest.java
@@ -10,13 +10,12 @@ import org.junit.jupiter.api.Timeout;
10import org.junit.jupiter.params.ParameterizedTest; 10import org.junit.jupiter.params.ParameterizedTest;
11import org.junit.jupiter.params.provider.Arguments; 11import org.junit.jupiter.params.provider.Arguments;
12import org.junit.jupiter.params.provider.MethodSource; 12import org.junit.jupiter.params.provider.MethodSource;
13import tools.refinery.store.map.DiffCursor; 13import tools.refinery.store.map.*;
14import tools.refinery.store.map.VersionedMap;
15import tools.refinery.store.map.VersionedMapStore;
16import tools.refinery.store.map.VersionedMapStoreFactoryBuilder;
17import tools.refinery.store.map.tests.fuzz.utils.FuzzTestUtils; 14import tools.refinery.store.map.tests.fuzz.utils.FuzzTestUtils;
18import tools.refinery.store.map.tests.utils.MapTestEnvironment; 15import tools.refinery.store.map.tests.utils.MapTestEnvironment;
19 16
17import java.util.HashMap;
18import java.util.Map;
20import java.util.Random; 19import java.util.Random;
21import java.util.stream.Stream; 20import java.util.stream.Stream;
22 21
@@ -39,6 +38,7 @@ class DiffCursorFuzzTest {
39 int commitFrequency, boolean commitBeforeDiffCursor) { 38 int commitFrequency, boolean commitBeforeDiffCursor) {
40 39
41 int largestCommit = -1; 40 int largestCommit = -1;
41 Map<Integer,Version> index2Version = new HashMap<>();
42 42
43 { 43 {
44 // 1. build a map with versions 44 // 1. build a map with versions
@@ -55,8 +55,9 @@ class DiffCursorFuzzTest {
55 fail(scenario + ":" + index + ": exception happened: " + exception); 55 fail(scenario + ":" + index + ": exception happened: " + exception);
56 } 56 }
57 if (index % commitFrequency == 0) { 57 if (index % commitFrequency == 0) {
58 long version = versioned.commit(); 58 Version version = versioned.commit();
59 largestCommit = (int) version; 59 index2Version.put(index,version);
60 largestCommit = index;
60 } 61 }
61 if (index % 10000 == 0) 62 if (index % 10000 == 0)
62 System.out.println(scenario + ":" + index + "/" + steps + " building finished"); 63 System.out.println(scenario + ":" + index + "/" + steps + " building finished");
@@ -73,20 +74,20 @@ class DiffCursorFuzzTest {
73 int index = i + 1; 74 int index = i + 1;
74 if (index % diffTravelFrequency == 0) { 75 if (index % diffTravelFrequency == 0) {
75 // diff-travel 76 // diff-travel
76 long travelToVersion = r2.nextInt(largestCommit + 1); 77 int travelToVersion = r2.nextInt(largestCommit + 1);
77 78
78 VersionedMap<Integer, String> oracle = store.createMap(travelToVersion); 79 VersionedMap<Integer, String> oracle = store.createMap(index2Version.get(travelToVersion));
79 80
80 if(commitBeforeDiffCursor) { 81 if(commitBeforeDiffCursor) {
81 moving.commit(); 82 moving.commit();
82 } 83 }
83 DiffCursor<Integer, String> diffCursor = moving.getDiffCursor(travelToVersion); 84 DiffCursor<Integer, String> diffCursor = moving.getDiffCursor(index2Version.get(travelToVersion));
84 moving.putAll(diffCursor); 85 moving.putAll(diffCursor);
85 moving.commit(); 86 moving.commit();
86 87
87 MapTestEnvironment.compareTwoMaps(scenario + ":c" + index, oracle, moving); 88 MapTestEnvironment.compareTwoMaps(scenario + ":c" + index, oracle, moving);
88 89
89 moving.restore(travelToVersion); 90 moving.restore(index2Version.get(travelToVersion));
90 91
91 } else { 92 } else {
92 // random puts 93 // random puts
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MultiThreadTestRunnable.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MultiThreadTestRunnable.java
index 9b2e591a..dfe46bae 100644
--- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MultiThreadTestRunnable.java
+++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MultiThreadTestRunnable.java
@@ -13,6 +13,7 @@ import java.util.List;
13import java.util.Map; 13import java.util.Map;
14import java.util.Random; 14import java.util.Random;
15 15
16import tools.refinery.store.map.Version;
16import tools.refinery.store.map.VersionedMap; 17import tools.refinery.store.map.VersionedMap;
17import tools.refinery.store.map.VersionedMapStore; 18import tools.refinery.store.map.VersionedMapStore;
18import tools.refinery.store.map.tests.utils.MapTestEnvironment; 19import tools.refinery.store.map.tests.utils.MapTestEnvironment;
@@ -61,7 +62,7 @@ public class MultiThreadTestRunnable implements Runnable {
61 // 1. build a map with versions 62 // 1. build a map with versions
62 Random r = new Random(seed); 63 Random r = new Random(seed);
63 VersionedMap<Integer, String> versioned = store.createMap(); 64 VersionedMap<Integer, String> versioned = store.createMap();
64 Map<Integer, Long> index2Version = new HashMap<>(); 65 Map<Integer, Version> index2Version = new HashMap<>();
65 66
66 for (int i = 0; i < steps; i++) { 67 for (int i = 0; i < steps; i++) {
67 int index = i + 1; 68 int index = i + 1;
@@ -74,7 +75,7 @@ public class MultiThreadTestRunnable implements Runnable {
74 logAndThrowError(scenario + ":" + index + ": exception happened: " + exception); 75 logAndThrowError(scenario + ":" + index + ": exception happened: " + exception);
75 } 76 }
76 if (index % commitFrequency == 0) { 77 if (index % commitFrequency == 0) {
77 long version = versioned.commit(); 78 Version version = versioned.commit();
78 index2Version.put(i, version); 79 index2Version.put(i, version);
79 } 80 }
80 MapTestEnvironment.printStatus(scenario, index, steps, "building"); 81 MapTestEnvironment.printStatus(scenario, index, steps, "building");
@@ -100,13 +101,12 @@ public class MultiThreadTestRunnable implements Runnable {
100 MapTestEnvironment.compareTwoMaps(scenario + ":" + index, reference, versioned, null); 101 MapTestEnvironment.compareTwoMaps(scenario + ":" + index, reference, versioned, null);
101 102
102 // go back to a random state (probably created by another thread) 103 // go back to a random state (probably created by another thread)
103 List<Long> states = new ArrayList<>(store.getStates()); 104 List<Version> states = new ArrayList<>(index2Version.values());
104 states.sort(Long::compare); 105 //states.sort(Long::compare);
105 Collections.shuffle(states, r2); 106 Collections.shuffle(states, r2);
106 for (Long state : states.subList(0, Math.min(states.size(), 100))) { 107 for (Version state : states.subList(0, Math.min(states.size(), 100))) {
107 long x = state; 108 versioned.restore(state);
108 versioned.restore(x); 109 var clean = store.createMap(state);
109 var clean = store.createMap(x);
110 MapTestEnvironment.compareTwoMaps(scenario + ":" + index, clean, versioned, null); 110 MapTestEnvironment.compareTwoMaps(scenario + ":" + index, clean, versioned, null);
111 } 111 }
112 versioned.restore(index2Version.get(i)); 112 versioned.restore(index2Version.get(i));
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MutableImmutableCompareFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MutableImmutableCompareFuzzTest.java
index 420dade6..abfb4791 100644
--- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MutableImmutableCompareFuzzTest.java
+++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MutableImmutableCompareFuzzTest.java
@@ -17,10 +17,10 @@ import org.junit.jupiter.params.ParameterizedTest;
17import org.junit.jupiter.params.provider.Arguments; 17import org.junit.jupiter.params.provider.Arguments;
18import org.junit.jupiter.params.provider.MethodSource; 18import org.junit.jupiter.params.provider.MethodSource;
19 19
20import tools.refinery.store.map.ContinousHashProvider; 20import tools.refinery.store.map.ContinuousHashProvider;
21import tools.refinery.store.map.VersionedMapStore; 21import tools.refinery.store.map.VersionedMapStore;
22import tools.refinery.store.map.VersionedMapStoreImpl; 22import tools.refinery.store.map.internal.state.VersionedMapStoreStateImpl;
23import tools.refinery.store.map.internal.VersionedMapImpl; 23import tools.refinery.store.map.internal.state.VersionedMapStateImpl;
24import tools.refinery.store.map.tests.fuzz.utils.FuzzTestUtils; 24import tools.refinery.store.map.tests.fuzz.utils.FuzzTestUtils;
25import tools.refinery.store.map.tests.utils.MapTestEnvironment; 25import tools.refinery.store.map.tests.utils.MapTestEnvironment;
26 26
@@ -28,11 +28,11 @@ class MutableImmutableCompareFuzzTest {
28 private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, 28 private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue,
29 boolean nullDefault, int commitFrequency, boolean evilHash) { 29 boolean nullDefault, int commitFrequency, boolean evilHash) {
30 String[] values = MapTestEnvironment.prepareValues(maxValue, nullDefault); 30 String[] values = MapTestEnvironment.prepareValues(maxValue, nullDefault);
31 ContinousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash); 31 ContinuousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash);
32 32
33 VersionedMapStore<Integer, String> store = new VersionedMapStoreImpl<>(chp, values[0]); 33 VersionedMapStore<Integer, String> store = new VersionedMapStoreStateImpl<>(chp, values[0]);
34 VersionedMapImpl<Integer, String> immutable = (VersionedMapImpl<Integer, String>) store.createMap(); 34 VersionedMapStateImpl<Integer, String> immutable = (VersionedMapStateImpl<Integer, String>) store.createMap();
35 VersionedMapImpl<Integer, String> mutable = (VersionedMapImpl<Integer, String>) store.createMap(); 35 VersionedMapStateImpl<Integer, String> mutable = (VersionedMapStateImpl<Integer, String>) store.createMap();
36 36
37 Random r = new Random(seed); 37 Random r = new Random(seed);
38 38
@@ -40,8 +40,8 @@ class MutableImmutableCompareFuzzTest {
40 commitFrequency); 40 commitFrequency);
41 } 41 }
42 42
43 private void iterativeRandomPutsAndCommitsAndCompare(String scenario, VersionedMapImpl<Integer, String> immutable, 43 private void iterativeRandomPutsAndCommitsAndCompare(String scenario, VersionedMapStateImpl<Integer, String> immutable,
44 VersionedMapImpl<Integer, String> mutable, int steps, int maxKey, String[] values, Random r, 44 VersionedMapStateImpl<Integer, String> mutable, int steps, int maxKey, String[] values, Random r,
45 int commitFrequency) { 45 int commitFrequency) {
46 for (int i = 0; i < steps; i++) { 46 for (int i = 0; i < steps; i++) {
47 int index = i + 1; 47 int index = i + 1;
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/RestoreFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/RestoreFuzzTest.java
index 0b399c3a..5c768788 100644
--- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/RestoreFuzzTest.java
+++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/RestoreFuzzTest.java
@@ -10,6 +10,7 @@ import org.junit.jupiter.api.Timeout;
10import org.junit.jupiter.params.ParameterizedTest; 10import org.junit.jupiter.params.ParameterizedTest;
11import org.junit.jupiter.params.provider.Arguments; 11import org.junit.jupiter.params.provider.Arguments;
12import org.junit.jupiter.params.provider.MethodSource; 12import org.junit.jupiter.params.provider.MethodSource;
13import tools.refinery.store.map.Version;
13import tools.refinery.store.map.VersionedMap; 14import tools.refinery.store.map.VersionedMap;
14import tools.refinery.store.map.VersionedMapStore; 15import tools.refinery.store.map.VersionedMapStore;
15import tools.refinery.store.map.VersionedMapStoreFactoryBuilder; 16import tools.refinery.store.map.VersionedMapStoreFactoryBuilder;
@@ -40,7 +41,7 @@ class RestoreFuzzTest {
40 // 1. build a map with versions 41 // 1. build a map with versions
41 Random r = new Random(seed); 42 Random r = new Random(seed);
42 VersionedMap<Integer, String> versioned = store.createMap(); 43 VersionedMap<Integer, String> versioned = store.createMap();
43 Map<Integer, Long> index2Version = new HashMap<>(); 44 Map<Integer, Version> index2Version = new HashMap<>();
44 45
45 for (int i = 0; i < steps; i++) { 46 for (int i = 0; i < steps; i++) {
46 int index = i + 1; 47 int index = i + 1;
@@ -53,7 +54,7 @@ class RestoreFuzzTest {
53 fail(scenario + ":" + index + ": exception happened: " + exception); 54 fail(scenario + ":" + index + ": exception happened: " + exception);
54 } 55 }
55 if (index % commitFrequency == 0) { 56 if (index % commitFrequency == 0) {
56 long version = versioned.commit(); 57 Version version = versioned.commit();
57 index2Version.put(i, version); 58 index2Version.put(i, version);
58 } 59 }
59 MapTestEnvironment.printStatus(scenario, index, steps, "building"); 60 MapTestEnvironment.printStatus(scenario, index, steps, "building");
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/SharedStoreFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/SharedStoreFuzzTest.java
index 680d962d..299c94b1 100644
--- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/SharedStoreFuzzTest.java
+++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/SharedStoreFuzzTest.java
@@ -18,10 +18,11 @@ import org.junit.jupiter.params.ParameterizedTest;
18import org.junit.jupiter.params.provider.Arguments; 18import org.junit.jupiter.params.provider.Arguments;
19import org.junit.jupiter.params.provider.MethodSource; 19import org.junit.jupiter.params.provider.MethodSource;
20 20
21import tools.refinery.store.map.ContinousHashProvider; 21import tools.refinery.store.map.ContinuousHashProvider;
22import tools.refinery.store.map.Version;
22import tools.refinery.store.map.VersionedMapStore; 23import tools.refinery.store.map.VersionedMapStore;
23import tools.refinery.store.map.VersionedMapStoreImpl; 24import tools.refinery.store.map.internal.state.VersionedMapStoreStateImpl;
24import tools.refinery.store.map.internal.VersionedMapImpl; 25import tools.refinery.store.map.internal.state.VersionedMapStateImpl;
25import tools.refinery.store.map.tests.fuzz.utils.FuzzTestUtils; 26import tools.refinery.store.map.tests.fuzz.utils.FuzzTestUtils;
26import tools.refinery.store.map.tests.utils.MapTestEnvironment; 27import tools.refinery.store.map.tests.utils.MapTestEnvironment;
27 28
@@ -31,9 +32,9 @@ class SharedStoreFuzzTest {
31 private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue, 32 private void runFuzzTest(String scenario, int seed, int steps, int maxKey, int maxValue,
32 boolean nullDefault, int commitFrequency, boolean evilHash) { 33 boolean nullDefault, int commitFrequency, boolean evilHash) {
33 String[] values = MapTestEnvironment.prepareValues(maxValue, nullDefault); 34 String[] values = MapTestEnvironment.prepareValues(maxValue, nullDefault);
34 ContinousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash); 35 ContinuousHashProvider<Integer> chp = MapTestEnvironment.prepareHashProvider(evilHash);
35 36
36 List<VersionedMapStore<Integer, String>> stores = VersionedMapStoreImpl.createSharedVersionedMapStores(5, chp, values[0]); 37 List<VersionedMapStore<Integer, String>> stores = VersionedMapStoreStateImpl.createSharedVersionedMapStores(5, chp, values[0]);
37 38
38 iterativeRandomPutsAndCommitsThenRestore(scenario, stores, steps, maxKey, values, seed, commitFrequency); 39 iterativeRandomPutsAndCommitsThenRestore(scenario, stores, steps, maxKey, values, seed, commitFrequency);
39 } 40 }
@@ -42,12 +43,12 @@ class SharedStoreFuzzTest {
42 int steps, int maxKey, String[] values, int seed, int commitFrequency) { 43 int steps, int maxKey, String[] values, int seed, int commitFrequency) {
43 // 1. maps with versions 44 // 1. maps with versions
44 Random r = new Random(seed); 45 Random r = new Random(seed);
45 List<VersionedMapImpl<Integer, String>> versioneds = new LinkedList<>(); 46 List<VersionedMapStateImpl<Integer, String>> versioneds = new LinkedList<>();
46 for (VersionedMapStore<Integer, String> store : stores) { 47 for (VersionedMapStore<Integer, String> store : stores) {
47 versioneds.add((VersionedMapImpl<Integer, String>) store.createMap()); 48 versioneds.add((VersionedMapStateImpl<Integer, String>) store.createMap());
48 } 49 }
49 50
50 List<Map<Integer, Long>> index2Version = new LinkedList<>(); 51 List<Map<Integer, Version>> index2Version = new LinkedList<>();
51 for (int i = 0; i < stores.size(); i++) { 52 for (int i = 0; i < stores.size(); i++) {
52 index2Version.add(new HashMap<>()); 53 index2Version.add(new HashMap<>());
53 } 54 }
@@ -59,16 +60,16 @@ class SharedStoreFuzzTest {
59 String nextValue = values[r.nextInt(values.length)]; 60 String nextValue = values[r.nextInt(values.length)];
60 versioneds.get(storeIndex).put(nextKey, nextValue); 61 versioneds.get(storeIndex).put(nextKey, nextValue);
61 if (stepIndex % commitFrequency == 0) { 62 if (stepIndex % commitFrequency == 0) {
62 long version = versioneds.get(storeIndex).commit(); 63 Version version = versioneds.get(storeIndex).commit();
63 index2Version.get(storeIndex).put(i, version); 64 index2Version.get(storeIndex).put(i, version);
64 } 65 }
65 MapTestEnvironment.printStatus(scenario, stepIndex, steps, "building"); 66 MapTestEnvironment.printStatus(scenario, stepIndex, steps, "building");
66 } 67 }
67 } 68 }
68 // 2. create a non-versioned and 69 // 2. create a non-versioned and
69 List<VersionedMapImpl<Integer, String>> reference = new LinkedList<>(); 70 List<VersionedMapStateImpl<Integer, String>> reference = new LinkedList<>();
70 for (VersionedMapStore<Integer, String> store : stores) { 71 for (VersionedMapStore<Integer, String> store : stores) {
71 reference.add((VersionedMapImpl<Integer, String>) store.createMap()); 72 reference.add((VersionedMapStateImpl<Integer, String>) store.createMap());
72 } 73 }
73 r = new Random(seed); 74 r = new Random(seed);
74 75
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/utils/FuzzTestCollections.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/utils/FuzzTestCollections.java
index 4c3ecb09..ec04904e 100644
--- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/utils/FuzzTestCollections.java
+++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/utils/FuzzTestCollections.java
@@ -18,26 +18,35 @@ public final class FuzzTestCollections {
18 public static final Object[] randomSeedOptions = {1}; 18 public static final Object[] randomSeedOptions = {1};
19 public static final Object[] storeConfigs = { 19 public static final Object[] storeConfigs = {
20 // State based 20 // State based
21 // Default
21 VersionedMapStore.<Integer,String>builder() 22 VersionedMapStore.<Integer,String>builder()
22 .stateBasedImmutableWhenCommitting(true)
23 .stateBasedHashProvider(MapTestEnvironment.prepareHashProvider(false)) 23 .stateBasedHashProvider(MapTestEnvironment.prepareHashProvider(false))
24 .stateBasedSharingStrategy(VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE), 24 .stateBasedSharingStrategy(VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE),
25 // Evil hash code test
25 VersionedMapStore.<Integer,String>builder() 26 VersionedMapStore.<Integer,String>builder()
26 .stateBasedImmutableWhenCommitting(true)
27 .stateBasedHashProvider(MapTestEnvironment.prepareHashProvider(true)) 27 .stateBasedHashProvider(MapTestEnvironment.prepareHashProvider(true))
28 .stateBasedSharingStrategy(VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE), 28 .stateBasedSharingStrategy(VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE),
29 // No weak hashmap test
30 VersionedMapStore.<Integer,String>builder()
31 .versionFreeing(false)
32 .stateBasedHashProvider(MapTestEnvironment.prepareHashProvider(false))
33 .stateBasedSharingStrategy(VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE),
34 // Copy when committing, do not hurt the work copy, share between saves.
29 VersionedMapStore.<Integer,String>builder() 35 VersionedMapStore.<Integer,String>builder()
30 .stateBasedImmutableWhenCommitting(false) 36 .stateBasedImmutableWhenCommitting(false)
31 .stateBasedHashProvider(MapTestEnvironment.prepareHashProvider(false)) 37 .stateBasedHashProvider(MapTestEnvironment.prepareHashProvider(false))
32 .stateBasedSharingStrategy(VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE), 38 .stateBasedSharingStrategy(VersionedMapStoreFactoryBuilder.SharingStrategy.SHARED_NODE_CACHE),
39 // Copy when committing, do not hurt the work copy, do not share between states.
33 VersionedMapStore.<Integer,String>builder() 40 VersionedMapStore.<Integer,String>builder()
34 .stateBasedImmutableWhenCommitting(false) 41 .stateBasedImmutableWhenCommitting(false)
35 .stateBasedHashProvider(MapTestEnvironment.prepareHashProvider(false)) 42 .stateBasedHashProvider(MapTestEnvironment.prepareHashProvider(false))
36 .stateBasedSharingStrategy(VersionedMapStoreFactoryBuilder.SharingStrategy.NO_NODE_CACHE), 43 .stateBasedSharingStrategy(VersionedMapStoreFactoryBuilder.SharingStrategy.NO_NODE_CACHE),
37 44
38 // Delta based 45 // Delta based
46 // Set based transactions
39 VersionedMapStore.<Integer,String>builder() 47 VersionedMapStore.<Integer,String>builder()
40 .deltaTransactionStrategy(VersionedMapStoreFactoryBuilder.DeltaTransactionStrategy.SET), 48 .deltaTransactionStrategy(VersionedMapStoreFactoryBuilder.DeltaTransactionStrategy.SET),
49 // List based transactions
41 VersionedMapStore.<Integer,String>builder() 50 VersionedMapStore.<Integer,String>builder()
42 .deltaTransactionStrategy(VersionedMapStoreFactoryBuilder.DeltaTransactionStrategy.LIST) 51 .deltaTransactionStrategy(VersionedMapStoreFactoryBuilder.DeltaTransactionStrategy.LIST)
43 }; 52 };
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java
index e7348370..b84df280 100644
--- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java
+++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java
@@ -6,7 +6,7 @@
6package tools.refinery.store.map.tests.utils; 6package tools.refinery.store.map.tests.utils;
7 7
8import tools.refinery.store.map.*; 8import tools.refinery.store.map.*;
9import tools.refinery.store.map.internal.VersionedMapImpl; 9import tools.refinery.store.map.internal.state.VersionedMapStateImpl;
10 10
11import java.util.*; 11import java.util.*;
12import java.util.Map.Entry; 12import java.util.Map.Entry;
@@ -28,7 +28,7 @@ public class MapTestEnvironment<K, V> {
28 return values; 28 return values;
29 } 29 }
30 30
31 public static ContinousHashProvider<Integer> prepareHashProvider(final boolean evil) { 31 public static ContinuousHashProvider<Integer> prepareHashProvider(final boolean evil) {
32 // Use maxPrime = 2147483629 32 // Use maxPrime = 2147483629
33 33
34 return (key, index) -> { 34 return (key, index) -> {
@@ -125,7 +125,7 @@ public class MapTestEnvironment<K, V> {
125 } 125 }
126 } 126 }
127 127
128 public long commit(){ 128 public Version commit(){
129 return sut.commit(); 129 return sut.commit();
130 } 130 }
131 131
@@ -187,7 +187,7 @@ public class MapTestEnvironment<K, V> {
187 //System.out.println(cursor.getKey() + " " + ((VersionedMapImpl<K, V>) versionedMap).getHashProvider() 187 //System.out.println(cursor.getKey() + " " + ((VersionedMapImpl<K, V>) versionedMap).getHashProvider()
188 // .getHash(cursor.getKey(), 0)); 188 // .getHash(cursor.getKey(), 0));
189 if (previous != null) { 189 if (previous != null) {
190 int comparisonResult = ((VersionedMapImpl<K, V>) versionedMap).getHashProvider().compare(previous, 190 int comparisonResult = ((VersionedMapStateImpl<K, V>) versionedMap).getHashProvider().compare(previous,
191 cursor.getKey()); 191 cursor.getKey());
192 assertTrue(comparisonResult < 0, scenario + " Cursor order is not incremental!"); 192 assertTrue(comparisonResult < 0, scenario + " Cursor order is not incremental!");
193 } 193 }
diff --git a/subprojects/store/src/test/java/tools/refinery/store/model/hashtests/HashEfficiencyTest.java b/subprojects/store/src/test/java/tools/refinery/store/model/hashtests/HashEfficiencyTest.java
index 4d4f5e26..5b595da7 100644
--- a/subprojects/store/src/test/java/tools/refinery/store/model/hashtests/HashEfficiencyTest.java
+++ b/subprojects/store/src/test/java/tools/refinery/store/model/hashtests/HashEfficiencyTest.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.store.model.hashtests; 6package tools.refinery.store.model.hashTests;
7 7
8import static org.junit.jupiter.api.Assertions.assertEquals; 8import static org.junit.jupiter.api.Assertions.assertEquals;
9 9
@@ -14,10 +14,9 @@ import java.util.Random;
14 14
15import org.junit.jupiter.api.Test; 15import org.junit.jupiter.api.Test;
16 16
17import tools.refinery.store.map.ContinousHashProvider; 17import tools.refinery.store.map.ContinuousHashProvider;
18import tools.refinery.store.tuple.Tuple; 18import tools.refinery.store.tuple.Tuple;
19import tools.refinery.store.model.TupleHashProvider; 19import tools.refinery.store.model.TupleHashProvider;
20import tools.refinery.store.model.TupleHashProviderBitMagic;
21 20
22class HashEfficiencyTest { 21class HashEfficiencyTest {
23 22
@@ -95,7 +94,7 @@ class HashEfficiencyTest {
95 List<Tuple> p = nRandoms(2, amount, 1);; 94 List<Tuple> p = nRandoms(2, amount, 1);;
96 assertEquals(amount,p.size()); 95 assertEquals(amount,p.size());
97 } 96 }
98 private static double calculateHashClashes(List<Tuple> tuples, ContinousHashProvider<Tuple> chp) { 97 private static double calculateHashClashes(List<Tuple> tuples, ContinuousHashProvider<Tuple> chp) {
99 int sumClashes = 0; 98 int sumClashes = 0;
100 99
101 for(int i = 0; i<tuples.size(); i++) { 100 for(int i = 0; i<tuples.size(); i++) {
@@ -108,7 +107,7 @@ class HashEfficiencyTest {
108 } 107 }
109 return (sumClashes+0.0) / tuples.size(); 108 return (sumClashes+0.0) / tuples.size();
110 } 109 }
111 private static int calculateHashClash(ContinousHashProvider<Tuple> chp, Tuple a, Tuple b) { 110 private static int calculateHashClash(ContinuousHashProvider<Tuple> chp, Tuple a, Tuple b) {
112 if(a.equals(b)) return 0; 111 if(a.equals(b)) return 0;
113 final int bits = 5; 112 final int bits = 5;
114 final int segments = Integer.SIZE/bits; 113 final int segments = Integer.SIZE/bits;
@@ -131,11 +130,9 @@ class HashEfficiencyTest {
131 } 130 }
132 public static void main(String[] args) { 131 public static void main(String[] args) {
133 List<String> hashNames = new LinkedList<>(); 132 List<String> hashNames = new LinkedList<>();
134 List<ContinousHashProvider<Tuple>> hashes = new LinkedList<>(); 133 List<ContinuousHashProvider<Tuple>> hashes = new LinkedList<>();
135 hashNames.add("PrimeGroup"); 134 hashNames.add("PrimeGroup");
136 hashes.add(new TupleHashProvider()); 135 hashes.add(new TupleHashProvider());
137 hashNames.add("BitMagic");
138 hashes.add(new TupleHashProviderBitMagic());
139 136
140 int[] arities = new int[] {2,3,4,5}; 137 int[] arities = new int[] {2,3,4,5};
141 int[] sizes = new int[] {32*32,32*32*8}; 138 int[] sizes = new int[] {32*32,32*32*8};
diff --git a/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java b/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java
index 56b75804..dc7b776e 100644
--- a/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java
+++ b/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java
@@ -6,6 +6,7 @@
6package tools.refinery.store.model.tests; 6package tools.refinery.store.model.tests;
7 7
8import org.junit.jupiter.api.Test; 8import org.junit.jupiter.api.Test;
9import tools.refinery.store.map.Version;
9import tools.refinery.store.model.Model; 10import tools.refinery.store.model.Model;
10import tools.refinery.store.model.ModelStore; 11import tools.refinery.store.model.ModelStore;
11import tools.refinery.store.representation.Symbol; 12import tools.refinery.store.representation.Symbol;
@@ -120,7 +121,7 @@ class ModelTest {
120 assertTrue(model.hasUncommittedChanges()); 121 assertTrue(model.hasUncommittedChanges());
121 assertEquals(Model.NO_STATE_ID, model.getState()); 122 assertEquals(Model.NO_STATE_ID, model.getState());
122 123
123 long state1 = model.commit(); 124 Version state1 = model.commit();
124 125
125 assertFalse(model.hasUncommittedChanges()); 126 assertFalse(model.hasUncommittedChanges());
126 assertEquals(state1, model.getState()); 127 assertEquals(state1, model.getState());
@@ -134,7 +135,7 @@ class ModelTest {
134 assertTrue(model.hasUncommittedChanges()); 135 assertTrue(model.hasUncommittedChanges());
135 assertEquals(state1, model.getState()); 136 assertEquals(state1, model.getState());
136 137
137 long state2 = model.commit(); 138 Version state2 = model.commit();
138 139
139 assertFalse(model.hasUncommittedChanges()); 140 assertFalse(model.hasUncommittedChanges());
140 assertEquals(state2, model.getState()); 141 assertEquals(state2, model.getState());
diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerAdapter.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerAdapter.java
index 2f71d4f3..b3f833ef 100644
--- a/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerAdapter.java
+++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/ModelVisualizerAdapter.java
@@ -1,6 +1,7 @@
1package tools.refinery.visualization; 1package tools.refinery.visualization;
2 2
3import tools.refinery.store.adapter.ModelAdapter; 3import tools.refinery.store.adapter.ModelAdapter;
4import tools.refinery.store.map.Version;
4import tools.refinery.store.tuple.Tuple; 5import tools.refinery.store.tuple.Tuple;
5import tools.refinery.visualization.internal.FileFormat; 6import tools.refinery.visualization.internal.FileFormat;
6import tools.refinery.visualization.internal.ModelVisualizerBuilderImpl; 7import tools.refinery.visualization.internal.ModelVisualizerBuilderImpl;
@@ -14,7 +15,7 @@ public interface ModelVisualizerAdapter extends ModelAdapter {
14 15
15 public String createDotForCurrentModelState(); 16 public String createDotForCurrentModelState();
16 17
17 public String createDotForModelState(Long version); 18 public String createDotForModelState(Version version);
18 19
19 public boolean saveDot(String dot, String filePath); 20 public boolean saveDot(String dot, String filePath);
20 21
@@ -22,15 +23,17 @@ public interface ModelVisualizerAdapter extends ModelAdapter {
22 23
23 public boolean renderDot(String dot, FileFormat format, String filePath); 24 public boolean renderDot(String dot, FileFormat format, String filePath);
24 25
25 public void addTransition(Long from, Long to, String action); 26 public void addTransition(Version from, Version to, String action);
26 27
27 28
28 public void addTransition(Long from, Long to, String action, Tuple activation); 29 public void addTransition(Version from, Version to, String action, Tuple activation);
29 public void addSolution(Long state); 30 public void addState(Version state);
31 public void addSolution(Version state);
30 32
31 public boolean saveDesignSpace(String path); 33 public boolean saveDesignSpace(String path);
32 34
33 public boolean renderDesignSpace(String path); 35 public boolean renderDesignSpace(String path);
34 36
35 public boolean renderDesignSpace(String path, FileFormat format); 37 public boolean renderDesignSpace(String path, FileFormat format);
38
36} 39}
diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java
index 9a284e24..33c5a43b 100644
--- a/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java
+++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java
@@ -1,5 +1,6 @@
1package tools.refinery.visualization.internal; 1package tools.refinery.visualization.internal;
2 2
3import tools.refinery.store.map.Version;
3import tools.refinery.store.model.Interpretation; 4import tools.refinery.store.model.Interpretation;
4import tools.refinery.store.model.Model; 5import tools.refinery.store.model.Model;
5import tools.refinery.store.representation.AnySymbol; 6import tools.refinery.store.representation.AnySymbol;
@@ -16,7 +17,9 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter {
16 private final ModelVisualizerStoreAdapter storeAdapter; 17 private final ModelVisualizerStoreAdapter storeAdapter;
17 private final Map<AnySymbol, Interpretation<?>> interpretations; 18 private final Map<AnySymbol, Interpretation<?>> interpretations;
18 private final StringBuilder designSpaceBuilder = new StringBuilder(); 19 private final StringBuilder designSpaceBuilder = new StringBuilder();
20 private final Map<Version, Integer> states = new HashMap<>();
19 private int transitionCounter = 0; 21 private int transitionCounter = 0;
22 private Integer numberOfStates = 0;
20 23
21 public ModelVisualizerAdapterImpl(Model model, ModelVisualizerStoreAdapter storeAdapter) { 24 public ModelVisualizerAdapterImpl(Model model, ModelVisualizerStoreAdapter storeAdapter) {
22 this.model = model; 25 this.model = model;
@@ -81,7 +84,7 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter {
81 } 84 }
82 85
83 @Override 86 @Override
84 public String createDotForModelState(Long version) { 87 public String createDotForModelState(Version version) {
85 var currentVersion = model.getState(); 88 var currentVersion = model.getState();
86 model.restore(version); 89 model.restore(version);
87 var graph = createDotForCurrentModelState(); 90 var graph = createDotForCurrentModelState();
@@ -125,15 +128,15 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter {
125 } 128 }
126 129
127 @Override 130 @Override
128 public void addTransition(Long from, Long to, String action) { 131 public void addTransition(Version from, Version to, String action) {
129 designSpaceBuilder.append(from).append(" -> ").append(to).append(" [label=\"").append(transitionCounter++) 132 designSpaceBuilder.append(states.get(from)).append(" -> ").append(states.get(to)).append(" [label=\"")
130 .append(": ").append(action).append("\"]\n"); 133 .append(transitionCounter++).append(": ").append(action).append("\"]\n");
131 134
132 } 135 }
133 136
134 @Override 137 @Override
135 public void addTransition(Long from, Long to, String action, Tuple activation) { 138 public void addTransition(Version from, Version to, String action, Tuple activation) {
136 designSpaceBuilder.append(from).append(" -> ").append(to).append(" [label=\"").append(transitionCounter++) 139 designSpaceBuilder.append(states.get(from)).append(" -> ").append(states.get(to)).append(" [label=\"").append(transitionCounter++)
137 .append(": ").append(action).append(" / "); 140 .append(": ").append(action).append(" / ");
138 141
139 142
@@ -147,14 +150,17 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter {
147 } 150 }
148 151
149 @Override 152 @Override
150 public void addSolution(Long state) { 153 public void addState(Version state) {
151 designSpaceBuilder.append(state).append(" [shape = doublecircle]\n"); 154 states.put(state, numberOfStates++);
155 designSpaceBuilder.append(states.get(state)).append(" [URL=\"./").append(states.get(state)).append(".svg\"]\n");
156 }
157
158 @Override
159 public void addSolution(Version state) {
160 designSpaceBuilder.append(states.get(state)).append(" [shape = doublecircle]\n");
152 } 161 }
153 162
154 private String buildDesignSpaceDot() { 163 private String buildDesignSpaceDot() {
155 for (var state : storeAdapter.getStore().getStates()) {
156 designSpaceBuilder.append(state).append(" [URL=\"./").append(state).append(".svg\"]\n");
157 }
158 designSpaceBuilder.append("}"); 164 designSpaceBuilder.append("}");
159 return designSpaceBuilder.toString(); 165 return designSpaceBuilder.toString();
160 } 166 }
@@ -162,8 +168,8 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter {
162 @Override 168 @Override
163 public boolean saveDesignSpace(String path) { 169 public boolean saveDesignSpace(String path) {
164 saveDot(buildDesignSpaceDot(), path + "/designSpace.dot"); 170 saveDot(buildDesignSpaceDot(), path + "/designSpace.dot");
165 for (var state : storeAdapter.getStore().getStates()) { 171 for (var state : states.keySet()) {
166 saveDot(createDotForModelState(state), path + "/" + state + ".dot"); 172 saveDot(createDotForModelState(state), path + "/" + states.get(state) + ".dot");
167 } 173 }
168 return true; 174 return true;
169 } 175 }
@@ -175,10 +181,12 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter {
175 181
176 @Override 182 @Override
177 public boolean renderDesignSpace(String path, FileFormat format) { 183 public boolean renderDesignSpace(String path, FileFormat format) {
178 for (var state : storeAdapter.getStore().getStates()) { 184 for (var entry : states.entrySet()) {
185 var state = entry.getKey();
186 var stateId = entry.getValue();
179 var stateDot = createDotForModelState(state); 187 var stateDot = createDotForModelState(state);
180 saveDot(stateDot, path + "/" + state + ".dot"); 188 saveDot(stateDot, path + "/" + stateId + ".dot");
181 renderDot(stateDot, path + "/" + state + "." + format.getFormat()); 189 renderDot(stateDot, path + "/" + stateId + "." + format.getFormat());
182 } 190 }
183 var designSpaceDot = buildDesignSpaceDot(); 191 var designSpaceDot = buildDesignSpaceDot();
184 saveDot(designSpaceDot, path + "/designSpace.dot"); 192 saveDot(designSpaceDot, path + "/designSpace.dot");