]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db/src/org/simantics/db/service/ClusterSets.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.db / src / org / simantics / db / service / ClusterSets.java
1 package org.simantics.db.service;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.HashMap;
6
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;
12
13 public class ClusterSets {
14
15         //    final private static boolean DEBUG = false;
16
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.
23
24         public void setWriteDirectory(File writeDirectory) {
25                 this.writeDirectory = writeDirectory;
26         }
27         
28         private File getFile1(File directory) {
29                 return new File(directory, "clusterSets." + this.databaseId + ".dat");
30         }
31
32         private File getFile2(File directory) {
33                 return new File(directory, "clusterSets." + this.databaseId + ".dat.reverse");
34         }
35
36         public ClusterSets(File readDirectory, File writeDirectory, String databaseId) {
37
38                 try {
39
40                         this.databaseId = databaseId;
41                         this.writeDirectory = writeDirectory;
42
43                         readDirectory.mkdirs();
44
45                         File file1 = getFile1(readDirectory);
46                         File file2 = getFile2(readDirectory);
47
48                         this.refCount = 1;
49                         PersistentData pd, pd2;
50                         try {
51                                 pd = (PersistentData)Files.readFile(file1, PersistentData.BINDING);
52                         } catch (IOException e) {
53                                 // New file
54                                 pd = new PersistentData();
55                                 pd.values = new HashMap<Long, Long>();
56                                 Files.writeFile(file1, PersistentData.BINDING, pd);
57                         }
58                         try {
59                                 pd2 = (PersistentData)Files.readFile(file2, PersistentData.BINDING);
60                         } catch (IOException e) {
61                                 // New file
62                                 pd2 = new PersistentData();
63                                 pd2.values = new HashMap<Long, Long>();
64                                 Files.writeFile(file2, PersistentData.BINDING, pd2);
65                         }
66                         this.clusterSets = pd.values;
67                         this.reverseMap = pd2.values;
68                         this.modified = false;
69                 } catch (Exception e) {
70                         e.printStackTrace();
71                         throw new RuntimeDatabaseException("Failed to create ClusterSets.");
72                 }
73         }
74         public synchronized int inc() {
75                 return ++refCount;
76         }
77         public synchronized int dec() {
78                 return --refCount;
79         }
80         // Save is thread safe.
81         public void dispose() {
82                 try {
83                         // We still save changes even if transaction is not finished.
84                         // This is because we have no cancel mechanism for cluster (sets).
85                         save();
86                 } catch (IOException e) {
87                         e.printStackTrace();
88                         throw new RuntimeDatabaseException("Failed to save ClusterSets.");
89                 } 
90         }
91         // clusterSets is not thread safe.
92         public synchronized boolean containsKey(long resourceId) {
93                 return clusterSets.containsKey(resourceId);
94         }
95         public synchronized Long get(Long resourceId) {
96                 return clusterSets.get(resourceId);
97         }
98         public synchronized void put(long resourceId, long clusterId) {
99                 clusterSets.put(resourceId, clusterId);
100                 reverseMap.put(clusterId, resourceId);
101                 modified = true;
102         }
103         public synchronized Long getClusterSet(Long clusterId) {
104                 return reverseMap.get(clusterId);
105         }
106         public void clear() {
107                 
108                 for(Long key : clusterSets.keySet())
109                         clusterSets.put(key, -1L);
110                 
111                 touch();
112                 
113         }
114         public synchronized void touch() {
115                 modified = true;
116         }
117         public synchronized void save() throws IOException {
118
119                 if (!modified)
120                         return;
121                 
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);
131                 modified = false;
132
133         }
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)
144                                 pd.values.put(i, i);
145                         BINDING.printValue(pd, System.err, new DataValueRepository(), true);
146                 }
147         }
148         
149 }