aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar OszkarSemerath <semerath@mit.bme.hu>2021-10-23 21:20:59 +0200
committerLibravatar OszkarSemerath <semerath@mit.bme.hu>2021-10-23 21:20:59 +0200
commit5e6b39d330d7c23fd8f5903ea36d129e62997af8 (patch)
tree620ea4761935aeff0a12d0b31d386e7fe390aecb
parentminor fixes (diff)
downloadrefinery-5e6b39d330d7c23fd8f5903ea36d129e62997af8.tar.gz
refinery-5e6b39d330d7c23fd8f5903ea36d129e62997af8.tar.zst
refinery-5e6b39d330d7c23fd8f5903ea36d129e62997af8.zip
exotic map bug fix
-rw-r--r--store/src/main/java/tools/refinery/store/map/internal/MutableNode.java22
-rw-r--r--store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java22
2 files changed, 32 insertions, 12 deletions
diff --git a/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java b/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java
index 7e94758c..54853010 100644
--- a/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java
+++ b/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java
@@ -79,7 +79,7 @@ public class MutableNode<K, V> extends Node<K, V> {
79 } 79 }
80 80
81 @Override 81 @Override
82 public Node<K, V> putValue(K key, V value, OldValueBox<V> oldValue, ContinousHashProvider<? super K> hashProvider, 82 public Node<K, V> putValue(K key, V value, OldValueBox<V> oldValueBox, ContinousHashProvider<? super K> hashProvider,
83 V defaultValue, int hash, int depth) { 83 V defaultValue, int hash, int depth) {
84 int selectedHashFragment = hashFragment(hash, shiftDepth(depth)); 84 int selectedHashFragment = hashFragment(hash, shiftDepth(depth));
85 @SuppressWarnings("unchecked") 85 @SuppressWarnings("unchecked")
@@ -89,20 +89,20 @@ public class MutableNode<K, V> extends Node<K, V> {
89 if (keyCandidate.equals(key)) { 89 if (keyCandidate.equals(key)) {
90 // The key is equals to an existing key -> update entry 90 // The key is equals to an existing key -> update entry
91 if (value == defaultValue) { 91 if (value == defaultValue) {
92 return removeEntry(selectedHashFragment, oldValue); 92 return removeEntry(selectedHashFragment, oldValueBox);
93 } else { 93 } else {
94 return updateValue(value, oldValue, selectedHashFragment); 94 return updateValue(value, oldValueBox, selectedHashFragment);
95 } 95 }
96 } else { 96 } else {
97 // The key is not equivalent to an existing key on the same hash bin 97 // The key is not equivalent to an existing key on the same hash bin
98 // -> split entry if it is necessary 98 // -> split entry if it is necessary
99 if (value == defaultValue) { 99 if (value == defaultValue) {
100 // Value is default -> do not need to add new node 100 // Value is default -> do not need to add new node
101 oldValue.setOldValue(defaultValue); 101 oldValueBox.setOldValue(defaultValue);
102 return this; 102 return this;
103 } else { 103 } else {
104 // Value is not default -> Split entry data to a new node 104 // Value is not default -> Split entry data to a new node
105 oldValue.setOldValue(defaultValue); 105 oldValueBox.setOldValue(defaultValue);
106 return moveDownAndSplit(hashProvider, key, value, keyCandidate, hash, depth, selectedHashFragment); 106 return moveDownAndSplit(hashProvider, key, value, keyCandidate, hash, depth, selectedHashFragment);
107 } 107 }
108 } 108 }
@@ -112,28 +112,26 @@ public class MutableNode<K, V> extends Node<K, V> {
112 var nodeCandidate = (Node<K, V>) content[2 * selectedHashFragment + 1]; 112 var nodeCandidate = (Node<K, V>) content[2 * selectedHashFragment + 1];
113 if (nodeCandidate != null) { 113 if (nodeCandidate != null) {
114 // If it has value, it is a subnode -> upate that 114 // If it has value, it is a subnode -> upate that
115 var newNode = nodeCandidate.putValue(key, value, oldValue, hashProvider, defaultValue, 115 var newNode = nodeCandidate.putValue(key, value, oldValueBox, hashProvider, defaultValue,
116 newHash(hashProvider, key, hash, depth + 1), depth + 1); 116 newHash(hashProvider, key, hash, depth + 1), depth + 1);
117 return updateWithSubNode(selectedHashFragment, newNode, value.equals(defaultValue)); 117 return updateWithSubNode(selectedHashFragment, newNode, value.equals(defaultValue));
118 } else { 118 } else {
119 // If it does not have value, put it in the empty place 119 // If it does not have value, put it in the empty place
120 if (value == defaultValue) { 120 if (value == defaultValue) {
121 // dont need to add new key-value pair 121 // dont need to add new key-value pair
122 oldValue.setOldValue(defaultValue); 122 oldValueBox.setOldValue(defaultValue);
123 return this; 123 return this;
124 } else { 124 } else {
125 return addEntry(key, value, oldValue, selectedHashFragment); 125 return addEntry(key, value, oldValueBox, selectedHashFragment, defaultValue);
126 } 126 }
127 127
128 } 128 }
129 } 129 }
130 } 130 }
131 131
132 private Node<K, V> addEntry(K key, V value, OldValueBox<V> oldValueBox, int selectedHashFragment) { 132 private Node<K, V> addEntry(K key, V value, OldValueBox<V> oldValueBox, int selectedHashFragment, V defaultValue) {
133 content[2 * selectedHashFragment] = key; 133 content[2 * selectedHashFragment] = key;
134 @SuppressWarnings("unchecked") 134 oldValueBox.setOldValue(defaultValue);
135 V oldValue = (V) content[2 * selectedHashFragment + 1];
136 oldValueBox.setOldValue(oldValue);
137 content[2 * selectedHashFragment + 1] = value; 135 content[2 * selectedHashFragment + 1] = value;
138 updateHash(); 136 updateHash();
139 return this; 137 return this;
diff --git a/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java b/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java
new file mode 100644
index 00000000..f0d5d927
--- /dev/null
+++ b/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java
@@ -0,0 +1,22 @@
1package tools.refinery.store.map.tests;
2
3import static org.junit.jupiter.api.Assertions.assertEquals;
4
5import org.junit.jupiter.api.Test;
6
7import tools.refinery.store.map.VersionedMapStore;
8import tools.refinery.store.map.VersionedMapStoreImpl;
9import tools.refinery.store.model.Tuple;
10import tools.refinery.store.model.TupleHashProvider;
11
12class MapUnitTests {
13 @Test
14 void defaultTest() {
15 VersionedMapStore<Tuple, Boolean> store = new VersionedMapStoreImpl<Tuple, Boolean>(TupleHashProvider.singleton(), false);
16 var map = store.createMap();
17 var out1 = map.put(Tuple.of(0), true);
18 assertEquals(false, out1);
19 var out2 = map.put(Tuple.of(1), true);
20 assertEquals(false, out2);
21 }
22}