1 package org.simantics.db.service;
4 import java.io.IOException;
5 import java.util.HashMap;
7 import org.simantics.databoard.Bindings;
8 import org.simantics.databoard.Files;
9 import org.simantics.databoard.binding.Binding;
10 import org.simantics.databoard.parser.repository.DataValueRepository;
11 import org.simantics.db.exception.RuntimeDatabaseException;
13 public class ClusterSets {
15 // final private static boolean DEBUG = false;
17 private File writeDirectory;
18 final private String databaseId;
19 final private HashMap<Long, Long> clusterSets; // Maps cluster set resource id to last user cluster id in the cluster set.
20 final private HashMap<Long, Long> reverseMap;
21 private int refCount; // Reference counter for user of this class.
22 private boolean modified; // True if modified since last save.
24 public void setWriteDirectory(File writeDirectory) {
25 this.writeDirectory = writeDirectory;
28 private File getFile1(File directory) {
29 return new File(directory, "clusterSets." + this.databaseId + ".dat");
32 private File getFile2(File directory) {
33 return new File(directory, "clusterSets." + this.databaseId + ".dat.reverse");
36 public ClusterSets(File readDirectory, File writeDirectory, String databaseId) {
40 this.databaseId = databaseId;
41 this.writeDirectory = writeDirectory;
43 readDirectory.mkdirs();
45 File file1 = getFile1(readDirectory);
46 File file2 = getFile2(readDirectory);
49 PersistentData pd, pd2;
51 pd = (PersistentData)Files.readFile(file1, PersistentData.BINDING);
52 } catch (IOException e) {
54 pd = new PersistentData();
55 pd.values = new HashMap<Long, Long>();
56 Files.writeFile(file1, PersistentData.BINDING, pd);
59 pd2 = (PersistentData)Files.readFile(file2, PersistentData.BINDING);
60 } catch (IOException e) {
62 pd2 = new PersistentData();
63 pd2.values = new HashMap<Long, Long>();
64 Files.writeFile(file2, PersistentData.BINDING, pd2);
66 this.clusterSets = pd.values;
67 this.reverseMap = pd2.values;
68 this.modified = false;
69 } catch (Exception e) {
71 throw new RuntimeDatabaseException("Failed to create ClusterSets.");
74 public synchronized int inc() {
77 public synchronized int dec() {
80 // Save is thread safe.
81 public void dispose() {
83 // We still save changes even if transaction is not finished.
84 // This is because we have no cancel mechanism for cluster (sets).
86 } catch (IOException e) {
88 throw new RuntimeDatabaseException("Failed to save ClusterSets.");
91 // clusterSets is not thread safe.
92 public synchronized boolean containsKey(long resourceId) {
93 return clusterSets.containsKey(resourceId);
95 public synchronized Long get(Long resourceId) {
96 return clusterSets.get(resourceId);
98 public synchronized void put(long resourceId, long clusterId) {
99 clusterSets.put(resourceId, clusterId);
100 reverseMap.put(clusterId, resourceId);
103 public synchronized Long getClusterSet(Long clusterId) {
104 return reverseMap.get(clusterId);
106 public void clear() {
108 for(Long key : clusterSets.keySet())
109 clusterSets.put(key, -1L);
114 public synchronized void touch() {
117 public synchronized void save() throws IOException {
122 writeDirectory.mkdirs();
123 File file1 = getFile1(writeDirectory);
124 File file2 = getFile2(writeDirectory);
125 PersistentData pd = new PersistentData();
126 pd.values = clusterSets;
127 Files.writeFile(file1, PersistentData.BINDING, pd);
128 pd = new PersistentData();
129 pd.values = reverseMap;
130 Files.writeFile(file2, PersistentData.BINDING, pd);
134 static public class PersistentData {
135 final public static Binding BINDING = Bindings.getBindingUnchecked(PersistentData.class);
136 // public TreeMap<Long, Long> values;
137 public HashMap<Long, Long> values;
138 public static void main(String[] args) throws Exception {
139 System.err.println("" + BINDING.type().toSingleLineString());
140 PersistentData pd = new PersistentData();
141 // pd.values = new TreeMap<Long, Long>();
142 pd.values = new HashMap<Long, Long>();
143 for (long i=0; i<10; ++i)
145 BINDING.printValue(pd, System.err, new DataValueRepository(), true);