aboutsummaryrefslogtreecommitdiffstats
path: root/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/VersionedMapStoreImpl.java
blob: 09607d4a912e73be51a59c177dad9ddb37828a8a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package org.eclipse.viatra.solver.data.map;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.eclipse.viatra.solver.data.map.internal.ImmutableNode;
import org.eclipse.viatra.solver.data.map.internal.MapDiffCursor;
import org.eclipse.viatra.solver.data.map.internal.Node;
import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl;

public class VersionedMapStoreImpl<KEY,VALUE> implements VersionedMapStore<KEY, VALUE> {
	// Configuration
	final private boolean immutableWhenCommiting;
	
	// Static data
	protected final ContinousHashProvider<? super KEY> hashProvider;
	protected final VALUE defaultValue;
	
	// Dynamic data
	final protected Map<Long, ImmutableNode<KEY,VALUE>> states;
	final protected Map<Node<KEY,VALUE>, ImmutableNode<KEY,VALUE>> nodeCache;
	protected long nextID;
	
	public VersionedMapStoreImpl(ContinousHashProvider<? super KEY> hashProvider, VALUE defaultValue, VersionedMapStoreConfiguration config) {
		this.immutableWhenCommiting = config.immutableWhenCommiting;
		
		this.hashProvider = hashProvider;
		this.defaultValue = defaultValue;
		
		states = new HashMap<>();
		nextID = 0;
		if(config.sharedNodeCache) {
			nodeCache = new HashMap<>();
		} else {
			nodeCache = null;
		}
	}
	
	public VersionedMapStoreImpl(ContinousHashProvider<KEY> hashProvider, VALUE defaultValue) {
		this(hashProvider,defaultValue,new VersionedMapStoreConfiguration());
	}
	
	synchronized Set<Long> getStates() {
		return states.keySet();
	}
	
	@Override
	public VersionedMap<KEY,VALUE> createMap() {
		return new VersionedMapImpl<KEY,VALUE>(this,hashProvider,defaultValue);
	}
	@Override
	public VersionedMap<KEY,VALUE> createMap(long state) {
		ImmutableNode<KEY, VALUE> data = revert(state);
		return new VersionedMapImpl<KEY,VALUE>(this,hashProvider,defaultValue,data); 
	}
	
	synchronized public ImmutableNode<KEY,VALUE> revert(long state) {
		if(states.containsKey(state)) {
			return states.get(state);
		} else {
			ArrayList<Long> existingKeys = new ArrayList<Long>(states.keySet());
			Collections.sort(existingKeys);
			throw new IllegalArgumentException(
				"Store does not contain state "+state+"! Avaliable states: "+existingKeys.toArray().toString());
		}
	}
	synchronized public long commit(Node<KEY,VALUE> data, VersionedMapImpl<KEY, VALUE> mapToUpdateRoot) {
		ImmutableNode<KEY,VALUE> immutable;
		if(data != null) {
			if(this.nodeCache != null) {
				immutable = data.toImmutable(this.nodeCache);
			} else {
				immutable = data.toImmutable();
			}
		} else {
			immutable = null;
		}
		
		
		if(nextID == Long.MAX_VALUE) throw new IllegalStateException(
			"Map store run out of Id-s");
		long id = nextID++;
		this.states.put(id, immutable);
		if(this.immutableWhenCommiting) {
			mapToUpdateRoot.setRoot(immutable);
		}
		return id;
	}
	
//	public Map<Node<KEY,VALUE>, ImmutableNode<KEY,VALUE>> getStore() {
//		return this.nodeCache;
//	}
//	public long addState(ImmutableNode<KEY,VALUE> data) {
//		
//		states.put(id,data);
//		return id;
//	}

	@Override
	public DiffCursor<KEY, VALUE> getDiffCursor(long fromState, long toState) {
		VersionedMap<KEY, VALUE> map1 = createMap(fromState);
		VersionedMap<KEY, VALUE> map2 = createMap(toState);
		Cursor<KEY, VALUE> cursor1 = map1.getCursor();
		Cursor<KEY, VALUE> cursor2 = map2.getCursor();
		return new MapDiffCursor<KEY, VALUE>(this.hashProvider,this.defaultValue,cursor1,cursor2);
	}
}