aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar OszkarSemerath <semerath@mit.bme.hu>2023-02-13 01:29:28 +0100
committerLibravatar OszkarSemerath <semerath@mit.bme.hu>2023-02-13 01:29:28 +0100
commit4f447bb7efd453eb6aa17fb29b8a0d7d65c03fcd (patch)
tree0bbfe721403b1ada3b323993e2f5322fd58abfbc
parentVersionedMapStoreBuilder returns builder state. (diff)
downloadrefinery-4f447bb7efd453eb6aa17fb29b8a0d7d65c03fcd.tar.gz
refinery-4f447bb7efd453eb6aa17fb29b8a0d7d65c03fcd.tar.zst
refinery-4f447bb7efd453eb6aa17fb29b8a0d7d65c03fcd.zip
Multiple small updates and fixes to support all upcoming tests.
- AnyVersionedMap.checkIntegrity added to the superclass - Default value of the map is gettable. - Errors fixed: - Delta store failed to update reference to the previous transaction in some cases. Fixed in VersionedMapStoreDeltaImpl.java import java.util.HashMap; - Null values caused issues in UncommittedDeltaMapStore.java as putIfAbsent does not work with null. - Small fixes in DeltaDiffCursor.java and IteratorAsCursor.java
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java5
-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/VersionedMapStoreDeltaImpl.java8
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/DeltaDiffCursor.java2
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/IteratorAsCursor.java3
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaMapStore.java11
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/UncommittedDeltaStore.java14
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapDeltaImpl.java85
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java2
9 files changed, 107 insertions, 25 deletions
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java b/subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java
index f82a8bb1..ead79878 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java
@@ -37,4 +37,9 @@ public sealed interface AnyVersionedMap extends Versioned permits VersionedMap {
37 @SuppressWarnings("squid:S1133") 37 @SuppressWarnings("squid:S1133")
38 @Deprecated(since = "0.0.0") 38 @Deprecated(since = "0.0.0")
39 boolean equals(Object obj); 39 boolean equals(Object obj);
40
41 /**
42 * Checks the integrity of the map, and throws an exception if an inconsistency is detected.
43 */
44 void checkIntegrity();
40} 45}
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 31985e94..08ce1dbd 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
@@ -1,6 +1,8 @@
1package tools.refinery.store.map; 1package tools.refinery.store.map;
2 2
3public non-sealed interface VersionedMap<K, V> extends AnyVersionedMap { 3public non-sealed interface VersionedMap<K, V> extends AnyVersionedMap {
4 V getDefaultValue();
5
4 V get(K key); 6 V get(K key);
5 7
6 Cursor<K, V> getAll(); 8 Cursor<K, V> getAll();
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreDeltaImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreDeltaImpl.java
index 98dec2bb..e556a8bb 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreDeltaImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreDeltaImpl.java
@@ -49,21 +49,22 @@ public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V>
49 return states.get(state); 49 return states.get(state);
50 } 50 }
51 51
52 public void getPath(long to, List<MapDelta<K, V>[]> forwardTransactions) { 52 public MapTransaction<K, V> getPath(long to, List<MapDelta<K, V>[]> forwardTransactions) {
53 MapTransaction<K, V> toTransaction = getState(to); 53 MapTransaction<K, V> toTransaction = getState(to);
54 while (toTransaction != null) { 54 while (toTransaction != null) {
55 forwardTransactions.add(toTransaction.deltas()); 55 forwardTransactions.add(toTransaction.deltas());
56 toTransaction = toTransaction.parent(); 56 toTransaction = toTransaction.parent();
57 } 57 }
58 return toTransaction;
58 } 59 }
59 60
60 public void getPath(long from, long to, 61 public MapTransaction<K, V> getPath(long from, long to,
61 List<MapDelta<K, V>[]> backwardTransactions, 62 List<MapDelta<K, V>[]> backwardTransactions,
62 List<MapDelta<K, V>[]> forwardTransactions) { 63 List<MapDelta<K, V>[]> forwardTransactions) {
63 MapTransaction<K, V> fromTransaction = getState(from); 64 MapTransaction<K, V> fromTransaction = getState(from);
64 MapTransaction<K, V> toTransaction = getState(to); 65 MapTransaction<K, V> toTransaction = getState(to);
65 while (fromTransaction != toTransaction) { 66 while (fromTransaction != toTransaction) {
66 if (fromTransaction == null || fromTransaction.version() < toTransaction.version()) { 67 if (fromTransaction == null || (toTransaction != null && fromTransaction.version() < toTransaction.version())) {
67 forwardTransactions.add(toTransaction.deltas()); 68 forwardTransactions.add(toTransaction.deltas());
68 toTransaction = toTransaction.parent(); 69 toTransaction = toTransaction.parent();
69 } else { 70 } else {
@@ -71,6 +72,7 @@ public class VersionedMapStoreDeltaImpl<K, V> implements VersionedMapStore<K, V>
71 fromTransaction = fromTransaction.parent(); 72 fromTransaction = fromTransaction.parent();
72 } 73 }
73 } 74 }
75 return toTransaction;
74 } 76 }
75 77
76 78
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/DeltaDiffCursor.java
index 75180bf9..49ea1f67 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/DeltaDiffCursor.java
@@ -62,6 +62,7 @@ public class DeltaDiffCursor<K, V> implements DiffCursor<K, V> {
62 return this.direction && listIndex == -1; 62 return this.direction && listIndex == -1;
63 } 63 }
64 64
65
65 @Override 66 @Override
66 public boolean move() { 67 public boolean move() {
67 if (isTerminated()) { 68 if (isTerminated()) {
@@ -74,6 +75,7 @@ public class DeltaDiffCursor<K, V> implements DiffCursor<K, V> {
74 } else { 75 } else {
75 if (listIndex-1 >= 0) { 76 if (listIndex-1 >= 0) {
76 listIndex--; 77 listIndex--;
78 arrayIndex = 0;
77 return true; 79 return true;
78 } else { 80 } else {
79 listIndex = -1; 81 listIndex = -1;
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/internal/IteratorAsCursor.java
index 4a8e9709..c1a0aec4 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/IteratorAsCursor.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/IteratorAsCursor.java
@@ -18,7 +18,6 @@ public class IteratorAsCursor<K, V> implements Cursor<K, V> {
18 public IteratorAsCursor(VersionedMap<K, V> source, Map<K, V> current) { 18 public IteratorAsCursor(VersionedMap<K, V> source, Map<K, V> current) {
19 this.iterator = current.entrySet().iterator(); 19 this.iterator = current.entrySet().iterator();
20 this.source = source; 20 this.source = source;
21 move();
22 } 21 }
23 22
24 @Override 23 @Override
@@ -38,7 +37,7 @@ public class IteratorAsCursor<K, V> implements Cursor<K, V> {
38 37
39 @Override 38 @Override
40 public boolean move() { 39 public boolean move() {
41 terminated = iterator.hasNext(); 40 terminated = !iterator.hasNext();
42 if (terminated) { 41 if (terminated) {
43 this.key = null; 42 this.key = null;
44 this.value = null; 43 this.value = null;
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/UncommittedDeltaMapStore.java
index 73df5080..31423b1c 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/UncommittedDeltaMapStore.java
@@ -1,7 +1,6 @@
1package tools.refinery.store.map.internal; 1package tools.refinery.store.map.internal;
2 2
3import java.util.HashMap; 3import java.util.*;
4import java.util.Map;
5import java.util.Map.Entry; 4import java.util.Map.Entry;
6 5
7import tools.refinery.store.map.VersionedMap; 6import tools.refinery.store.map.VersionedMap;
@@ -16,7 +15,9 @@ public class UncommittedDeltaMapStore<K, V> implements UncommittedDeltaStore<K,
16 15
17 @Override 16 @Override
18 public void processChange(K key, V oldValue, V newValue) { 17 public void processChange(K key, V oldValue, V newValue) {
19 this.uncommittedOldValues.putIfAbsent(key, oldValue); 18 if(!uncommittedOldValues.containsKey(key)) {
19 this.uncommittedOldValues.put(key,oldValue);
20 }
20 } 21 }
21 22
22 @Override 23 @Override
@@ -25,13 +26,13 @@ public class UncommittedDeltaMapStore<K, V> implements UncommittedDeltaStore<K,
25 return null; 26 return null;
26 } else { 27 } else {
27 @SuppressWarnings("unchecked") 28 @SuppressWarnings("unchecked")
28 MapDelta<K, V>[] deltas = new MapDelta[uncommittedOldValues.size()]; 29 MapDelta<K,V>[] deltas = new MapDelta[uncommittedOldValues.size()];
29 int i = 0; 30 int i = 0;
30 for (Entry<K, V> entry : uncommittedOldValues.entrySet()) { 31 for (Entry<K, V> entry : uncommittedOldValues.entrySet()) {
31 final K key = entry.getKey(); 32 final K key = entry.getKey();
32 final V oldValue = entry.getValue(); 33 final V oldValue = entry.getValue();
33 final V newValue = source.get(key); 34 final V newValue = source.get(key);
34 deltas[i] = new MapDelta<>(key, oldValue, newValue); 35 deltas[i++] = new MapDelta<>(key, oldValue, newValue);
35 } 36 }
36 37
37 return deltas; 38 return deltas;
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/UncommittedDeltaStore.java
index 37e5817c..7b017c8e 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/UncommittedDeltaStore.java
@@ -7,4 +7,18 @@ public interface UncommittedDeltaStore<K, V> {
7 7
8 MapDelta<K, V>[] extractAndDeleteDeltas(); 8 MapDelta<K, V>[] extractAndDeleteDeltas();
9 9
10 default void checkIntegrity() {
11 MapDelta<K, V>[] extractedDeltas = extractDeltas();
12 if(extractedDeltas != null) {
13 for(var uncommittedOldValue : extractedDeltas) {
14 if(uncommittedOldValue == null) {
15 throw new IllegalArgumentException("Null entry in deltas!");
16 }
17 if(uncommittedOldValue.getKey() == null) {
18 throw new IllegalStateException("Null key in deltas!");
19 }
20 }
21 }
22 }
23
10} 24}
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/VersionedMapDeltaImpl.java
index 6f2996e1..d09e54ba 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/VersionedMapDeltaImpl.java
@@ -19,7 +19,7 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
19 this.defaultValue = defaultValue; 19 this.defaultValue = defaultValue;
20 20
21 current = new HashMap<>(); 21 current = new HashMap<>();
22 if(summarizeChanges) { 22 if (summarizeChanges) {
23 this.uncommittedStore = new UncommittedDeltaMapStore<>(this); 23 this.uncommittedStore = new UncommittedDeltaMapStore<>(this);
24 } else { 24 } else {
25 this.uncommittedStore = new UncommittedDeltaArrayStore<>(); 25 this.uncommittedStore = new UncommittedDeltaArrayStore<>();
@@ -27,6 +27,11 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
27 } 27 }
28 28
29 @Override 29 @Override
30 public V getDefaultValue() {
31 return defaultValue;
32 }
33
34 @Override
30 public long commit() { 35 public long commit() {
31 MapDelta<K, V>[] deltas = uncommittedStore.extractAndDeleteDeltas(); 36 MapDelta<K, V>[] deltas = uncommittedStore.extractAndDeleteDeltas();
32 long[] versionContainer = new long[1]; 37 long[] versionContainer = new long[1];
@@ -43,16 +48,18 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
43 } 48 }
44 49
45 // 2. get common ancestor 50 // 2. get common ancestor
51 final MapTransaction<K,V> parent;
46 List<MapDelta<K, V>[]> forward = new ArrayList<>(); 52 List<MapDelta<K, V>[]> forward = new ArrayList<>();
47 if (this.previous == null) { 53 if (this.previous == null) {
48 this.store.getPath(state, forward); 54 parent = this.store.getPath(state, forward);
49 this.forward(forward); 55 this.forward(forward);
50 } else { 56 } else {
51 List<MapDelta<K, V>[]> backward = new ArrayList<>(); 57 List<MapDelta<K, V>[]> backward = new ArrayList<>();
52 this.store.getPath(this.previous.version(), state, backward, forward); 58 parent = this.store.getPath(this.previous.version(), state, backward, forward);
53 this.backward(backward); 59 this.backward(backward);
54 this.forward(forward); 60 this.forward(forward);
55 } 61 }
62 this.previous = parent;
56 } 63 }
57 64
58 protected void forward(List<MapDelta<K, V>[]> changes) { 65 protected void forward(List<MapDelta<K, V>[]> changes) {
@@ -70,14 +77,28 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
70 protected void forward(MapDelta<K, V>[] changes) { 77 protected void forward(MapDelta<K, V>[] changes) {
71 for (int i = 0; i < changes.length; i++) { 78 for (int i = 0; i < changes.length; i++) {
72 final MapDelta<K, V> change = changes[i]; 79 final MapDelta<K, V> change = changes[i];
73 current.put(change.getKey(), change.getNewValue()); 80 K key = change.getKey();
81 V newValue = change.getNewValue();
82
83 if(newValue == defaultValue) {
84 current.remove(key);
85 } else {
86 current.put(key,newValue);
87 }
74 } 88 }
75 } 89 }
76 90
77 protected void backward(MapDelta<K, V>[] changes) { 91 protected void backward(MapDelta<K, V>[] changes) {
78 for (int i = changes.length - 1; i >= 0; i--) { 92 for (int i = changes.length - 1; i >= 0; i--) {
79 final MapDelta<K, V> change = changes[i]; 93 final MapDelta<K, V> change = changes[i];
80 current.put(change.getKey(), change.getOldValue()); 94 K key = change.getKey();
95 V oldValue = change.oldValue();
96
97 if(oldValue == defaultValue) {
98 current.remove(key);
99 } else {
100 current.put(key,oldValue);
101 }
81 } 102 }
82 } 103 }
83 104
@@ -93,26 +114,46 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
93 114
94 @Override 115 @Override
95 public V put(K key, V value) { 116 public V put(K key, V value) {
96 if (value == defaultValue) { 117 final V oldValue;
97 V res = current.remove(key); 118 if (Objects.equals(value, defaultValue)) {
119 final V res = current.remove(key);
98 if (res == null) { 120 if (res == null) {
99 // no changes 121 // no changes: default > default
100 return defaultValue; 122 oldValue = defaultValue;
101 } else { 123 } else {
102 uncommittedStore.processChange(key, res, value); 124 oldValue = res;
103 return res;
104 } 125 }
105 } else { 126 } else {
106 V oldValue = current.put(key, value); 127 final var mapValue = current.put(key, value);
128 if (mapValue == null) {
129 oldValue = defaultValue;
130 } else {
131 oldValue = mapValue;
132 }
133 }
134 if(!Objects.equals(oldValue,value)) {
107 uncommittedStore.processChange(key, oldValue, value); 135 uncommittedStore.processChange(key, oldValue, value);
108 return oldValue;
109 } 136 }
137 return oldValue;
110 } 138 }
111 139
112 @Override 140 @Override
113 public void putAll(Cursor<K, V> cursor) { 141 public void putAll(Cursor<K, V> cursor) {
114 throw new UnsupportedOperationException(); 142 if (cursor.getDependingMaps().contains(this)) {
115 143 List<K> keys = new ArrayList<>();
144 List<V> values = new ArrayList<>();
145 while (cursor.move()) {
146 keys.add(cursor.getKey());
147 values.add(cursor.getValue());
148 }
149 for (int i = 0; i < keys.size(); i++) {
150 this.put(keys.get(i), values.get(i));
151 }
152 } else {
153 while (cursor.move()) {
154 this.put(cursor.getKey(), cursor.getValue());
155 }
156 }
116 } 157 }
117 158
118 @Override 159 @Override
@@ -156,4 +197,18 @@ public class VersionedMapDeltaImpl<K, V> implements VersionedMap<K, V> {
156 throw new UnsupportedOperationException("Comparing different map implementations is ineffective."); 197 throw new UnsupportedOperationException("Comparing different map implementations is ineffective.");
157 } 198 }
158 } 199 }
200
201 @Override
202 public void checkIntegrity() {
203 this.uncommittedStore.checkIntegrity();
204
205 for (var entry : this.current.entrySet()) {
206 var value = entry.getValue();
207 if (value == this.defaultValue) {
208 throw new IllegalStateException("Default value stored in map!");
209 } else if (value == null) {
210 throw new IllegalStateException("null value stored in map!");
211 }
212 }
213 }
159} 214}
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/VersionedMapImpl.java
index 674ffc47..fb359431 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/VersionedMapImpl.java
@@ -43,6 +43,7 @@ public class VersionedMapImpl<K, V> implements VersionedMap<K, V> {
43 this.root = data; 43 this.root = data;
44 } 44 }
45 45
46 @Override
46 public V getDefaultValue() { 47 public V getDefaultValue() {
47 return defaultValue; 48 return defaultValue;
48 } 49 }
@@ -141,6 +142,7 @@ public class VersionedMapImpl<K, V> implements VersionedMap<K, V> {
141 } 142 }
142 } 143 }
143 144
145 @Override
144 public void checkIntegrity() { 146 public void checkIntegrity() {
145 if (this.root != null) { 147 if (this.root != null) {
146 this.root.checkIntegrity(hashProvider, defaultValue, 0); 148 this.root.checkIntegrity(hashProvider, defaultValue, 0);