]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/VirtualGraphServerSupportImpl.java
6c86c100a0fe0d2a6f78b86250f816bccb26ccb0
[simantics/platform.git] / bundles / org.simantics.db.procore / src / fi / vtt / simantics / procore / internal / VirtualGraphServerSupportImpl.java
1 package fi.vtt.simantics.procore.internal;\r
2 \r
3 import gnu.trove.set.hash.TIntHashSet;\r
4 \r
5 import java.io.File;\r
6 import java.io.FileInputStream;\r
7 import java.io.FileOutputStream;\r
8 import java.io.FilenameFilter;\r
9 import java.io.IOException;\r
10 import java.io.InputStream;\r
11 import java.io.ObjectInputStream;\r
12 import java.io.ObjectOutputStream;\r
13 import java.io.OutputStream;\r
14 import java.util.ArrayList;\r
15 import java.util.Collection;\r
16 import java.util.HashMap;\r
17 import java.util.Map;\r
18 import java.util.concurrent.CopyOnWriteArrayList;\r
19 import java.util.concurrent.atomic.AtomicInteger;\r
20 \r
21 import org.eclipse.core.runtime.IStatus;\r
22 import org.eclipse.core.runtime.Status;\r
23 import org.simantics.db.ReadGraph;\r
24 import org.simantics.db.Resource;\r
25 import org.simantics.db.Statement;\r
26 import org.simantics.db.VirtualGraph;\r
27 import org.simantics.db.VirtualGraph.Persistency;\r
28 import org.simantics.db.WriteOnlyGraph;\r
29 import org.simantics.db.common.utils.NameUtils;\r
30 import org.simantics.db.exception.DatabaseException;\r
31 import org.simantics.db.impl.ClusterI;\r
32 import org.simantics.db.impl.ResourceImpl;\r
33 import org.simantics.db.impl.TransientGraph;\r
34 import org.simantics.db.impl.graph.ReadGraphImpl;\r
35 import org.simantics.db.impl.support.VirtualGraphServerSupport;\r
36 import org.simantics.db.request.Read;\r
37 import org.simantics.db.service.SerialisationSupport;\r
38 import org.simantics.db.service.ServerInformation;\r
39 import org.simantics.db.service.TransferableGraphSupport;\r
40 import org.simantics.db.service.VirtualGraphSupport;\r
41 import org.simantics.layer0.Layer0;\r
42 import org.simantics.utils.FileUtils;\r
43 \r
44 public class VirtualGraphServerSupportImpl implements VirtualGraphSupport, VirtualGraphServerSupport {\r
45 \r
46         final private static boolean DEBUG = false;\r
47         final private SessionImplSocket session;\r
48 \r
49         final public File virtualGraphStoragePath;\r
50         public String dbString = null;\r
51 \r
52         public TIntHashSet virtuals = new TIntHashSet();\r
53 \r
54         final public CopyOnWriteArrayList<TransientGraph>  providers          = new CopyOnWriteArrayList<TransientGraph>();\r
55         final private CopyOnWriteArrayList<TransientGraph> workspaceProviders = new CopyOnWriteArrayList<TransientGraph>();\r
56         final private CopyOnWriteArrayList<TransientGraph> memoryProviders    = new CopyOnWriteArrayList<TransientGraph>();\r
57 \r
58         public AtomicInteger virtualId;\r
59         private boolean hasVirtuals = false;\r
60 \r
61         public VirtualGraphServerSupportImpl(SessionImplSocket session, File path) {\r
62                 this.session = session;\r
63                 this.virtualGraphStoragePath = path;\r
64         }\r
65 \r
66         void connect(String dbString) {\r
67 \r
68                 virtualId = new AtomicInteger(-2);\r
69 \r
70                 this.dbString = dbString;\r
71 \r
72                 File file = new File(virtualGraphStoragePath, "virtualGraphs." + dbString + ".dat");\r
73 \r
74                 //      System.out.println("scanning " + file.getAbsolutePath());\r
75 \r
76                 if(file.exists()) {\r
77                         try {\r
78                                 InputStream stream = new FileInputStream(file);\r
79                                 final ObjectInputStream os = new ObjectInputStream(stream);\r
80                                 virtualId = new AtomicInteger(os.readInt());\r
81                                 //                      System.out.println("virtualId=" + virtualId.get());\r
82                                 os.close();\r
83                                 stream.close();\r
84 \r
85                                 hasVirtuals = true;\r
86 \r
87                                 // Load existing workspace persistent graphs\r
88                                 for(File virtualGraph : virtualGraphStoragePath.listFiles(new FilenameFilter() {\r
89                                         @Override\r
90                                         public boolean accept(File dir, String name) {\r
91                                                 return name.endsWith(".vg");\r
92                                         }\r
93                                 })) {\r
94                                         String name = virtualGraph.getName();\r
95                                         String[] parts = name.split("\\x2E", 2);\r
96                                         getWorkspacePersistent(parts[0]);\r
97                                 }\r
98 \r
99                         } catch (IOException e) {\r
100                                 e.printStackTrace();\r
101                         }\r
102                 } else {\r
103                         if (DEBUG)\r
104                                 System.out.println("No stored virtual graphs.");\r
105                 }\r
106 \r
107         }\r
108 \r
109         public void saveVirtualGraphState(SessionImplSocket session) {\r
110 \r
111                 if(!hasVirtuals) return;\r
112 \r
113                 try {\r
114 \r
115                         String databaseId = session.getService(ServerInformation.class).getDatabaseId();\r
116                         String serverId = session.getService(ServerInformation.class).getServerId();\r
117                         File file = new File(virtualGraphStoragePath, "virtualGraphs." + databaseId + "." + serverId + ".dat");\r
118 \r
119                         OutputStream stream = new FileOutputStream(file);\r
120                         final ObjectOutputStream os = new ObjectOutputStream(stream);\r
121                         os.writeInt(virtualId.get());\r
122                         os.flush();\r
123                         stream.close();\r
124 \r
125                 } catch (IOException e) {\r
126                         e.printStackTrace();\r
127                 }\r
128 \r
129         }\r
130 \r
131         public void disposeVirtualGraphs() {\r
132 \r
133                 if(!hasVirtuals) return;\r
134 \r
135                 saveVirtualGraphState(session);\r
136                 for(TransientGraph graph : workspaceProviders) graph.dispose();\r
137 \r
138         }\r
139 \r
140         public void saveVirtualGraphs() {\r
141 \r
142                 if(!hasVirtuals) return;\r
143 \r
144                 saveVirtualGraphState(session);\r
145                 for(TransientGraph graph : workspaceProviders) graph.save();\r
146 \r
147         }\r
148 \r
149         @Override\r
150         public void saveAll() {\r
151                 saveVirtualGraphs();\r
152         }\r
153 \r
154         @Override\r
155         public VirtualGraph getMemoryPersistent(String identifier) {\r
156 \r
157                 if(identifier == null) throw new IllegalArgumentException("Argument cannot be null!");\r
158 \r
159                 for(TransientGraph graph : memoryProviders) {\r
160                         if(identifier.equals(graph.getIdentifier())) return graph;\r
161                 }\r
162 \r
163                 String databaseId =  session.getService(ServerInformation.class).getDatabaseId();\r
164                 VirtualGraphServerSupport vgss = session.getService(VirtualGraphServerSupport.class);\r
165 \r
166         TransientGraph result = TransientGraph.memoryPersistent(new SerialisationSupportImpl(session), vgss, session.resourceSupport, session, databaseId, identifier);\r
167         memoryProviders.add(result);\r
168         providers.add(result);\r
169         return result;\r
170         }\r
171 \r
172         private TransientGraph createWorkspacePersistentInternal(String identifier) {\r
173 \r
174             String databaseId = session.getService(ServerInformation.class).getDatabaseId();\r
175             VirtualGraphServerSupport vgss = session.getService(VirtualGraphServerSupport.class);\r
176 \r
177             try {\r
178                 return TransientGraph.workspacePersistent(new SerialisationSupportImpl(session), vgss, session.resourceSupport, session, databaseId, identifier);\r
179             } catch (Exception e) {\r
180                 Activator.log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Failed to restore contents of previous virtual graph with identifier '" + identifier + "'. Resetting its contents to empty. See exception for problem details.", e));\r
181             return TransientGraph.memoryPersistent(new SerialisationSupportImpl(session), vgss, session.resourceSupport, session, databaseId, identifier);\r
182             }\r
183 \r
184         }\r
185         \r
186         @Override\r
187         public VirtualGraph getWorkspacePersistent(String identifier) {\r
188 \r
189                 if(identifier == null) throw new IllegalArgumentException("Argument cannot be null!");\r
190 \r
191                 for(TransientGraph graph : workspaceProviders) {\r
192                         if(identifier.equals(graph.getIdentifier())) return graph;\r
193                 }\r
194 \r
195                 TransientGraph result = createWorkspacePersistentInternal(identifier);\r
196                 \r
197         workspaceProviders.add(result);\r
198         providers.add(result);\r
199         hasVirtuals = true;\r
200         return result;\r
201 \r
202         }\r
203 \r
204         @Override\r
205         public boolean discard(VirtualGraph provider) {\r
206                 if (!(provider instanceof TransientGraph))\r
207                         return false;\r
208                 if (!providers.remove(provider))\r
209                         return false;\r
210 \r
211                 TransientGraph tg = (TransientGraph) provider;\r
212 \r
213                 if (workspaceProviders.remove(provider)) {\r
214                         // TODO: remove possibly existing data from disk\r
215                         tg.dispose();\r
216                 } else if (memoryProviders.remove(provider)) {\r
217                         tg.dispose();\r
218                 }\r
219                 return true;\r
220         }\r
221 \r
222         public Resource getPersistentResource(WriteOnlyGraph graph, Resource resource, Map<Resource, Resource> creation) throws DatabaseException {\r
223                 if(resource.isPersistent()) return resource;\r
224                 else {\r
225                         Resource result = creation.get(resource);\r
226                         if(result == null) {\r
227                                 result = graph.newResource();\r
228                                 creation.put(resource, result);\r
229                         }\r
230                         return result;\r
231                 }\r
232         }\r
233         \r
234         @Override\r
235         public boolean integrate(WriteOnlyGraph graph, VirtualGraph provider) throws DatabaseException {\r
236 \r
237                 if (!(provider instanceof TransientGraph))\r
238                         return false;\r
239                 if (!providers.remove(provider))\r
240                         return false;\r
241 \r
242                 workspaceProviders.remove(provider);\r
243                 memoryProviders.remove(provider);\r
244                 \r
245                 TransferableGraphSupport tgSupport = graph.getService(TransferableGraphSupport.class);\r
246                 TransientGraph tg = (TransientGraph) provider;\r
247                 \r
248                 Map<Resource, Resource> creation = new HashMap<Resource, Resource>();\r
249                 for(Statement stm : tg.listStatements()) {\r
250                         Resource subject = getPersistentResource(graph, stm.getSubject(), creation);\r
251                         Resource predicate = getPersistentResource(graph, stm.getPredicate(), creation);\r
252                         Resource object = getPersistentResource(graph, stm.getObject(), creation);\r
253                         graph.claim(subject, predicate, null, object);\r
254                 }\r
255                 for(Resource r : tg.listValues()) {\r
256                         byte[] value = tg.getValue(((ResourceImpl)r).id);\r
257                         tgSupport.setValue(graph, getPersistentResource(graph, r, creation), null, value);\r
258                 }\r
259                 discard(provider);\r
260                 return true;\r
261                 \r
262         }\r
263 \r
264         @Override\r
265         public Collection<TransientGraph> getVirtualGraphs(int subject) {\r
266                 if(subject < 0 || virtuals.contains(subject)) return providers;\r
267                 else return null; \r
268         }\r
269 \r
270         @Override\r
271         public void removeVirtual(int id) {\r
272                 virtuals.remove(id);\r
273         }\r
274 \r
275         @Override\r
276         public void addVirtual(int id) {\r
277                 assert(id > 0);\r
278                 //              System.err.println("addVirtual " + id);\r
279                 virtuals.add(id);\r
280                 ClusterI cluster = session.clusterTable.getClusterByResourceKey(id);\r
281                 cluster.markVirtual();\r
282         }\r
283 \r
284         @Override\r
285         public int createVirtual() {\r
286                 return virtualId.decrementAndGet();\r
287         }\r
288 \r
289         @Override\r
290         public File storagePath() {\r
291                 return virtualGraphStoragePath;\r
292         }\r
293 \r
294         @Override\r
295         public Collection<Statement> listStatements(VirtualGraph graph_) {\r
296                 TransientGraph graph = (TransientGraph)graph_;\r
297                 return graph.listStatements();\r
298         }\r
299 \r
300         @Override\r
301         public Collection<Resource> listValues(VirtualGraph graph_) {\r
302                 TransientGraph graph = (TransientGraph)graph_;\r
303                 return graph.listValues();\r
304         }\r
305 \r
306         @Override\r
307         public Collection<VirtualGraph> listGraphs() {\r
308                 ArrayList<VirtualGraph> result = new ArrayList<VirtualGraph>();\r
309                 result.addAll(memoryProviders);\r
310                 result.addAll(workspaceProviders);\r
311                 return result;\r
312         }\r
313 \r
314         public String report(final File file) {\r
315 \r
316                 session.asyncRequest(new Read<String>() {\r
317 \r
318                         @Override\r
319                         public String perform(ReadGraph graph) throws DatabaseException {\r
320 \r
321                                 SerialisationSupport ss = session.getService(SerialisationSupport.class);\r
322                                 StringBuilder b = new StringBuilder();\r
323                                 try {\r
324                                         for(VirtualGraph vg : listGraphs()) {\r
325                                                 TransientGraph tg = (TransientGraph)vg;\r
326                                                 if(Persistency.MEMORY == tg.getPersistency()) b.append("Memory persistent virtual graph '" + tg.getIdentifier() + "'\n");\r
327                                                 if(Persistency.WORKSPACE == tg.getPersistency()) b.append("Workspace persistent virtual graph '" + tg.getIdentifier() + "'\n");\r
328                                                 for(Statement stm : listStatements(tg)) {\r
329                                                         int s = ss.getTransientId(stm.getSubject());\r
330                                                         int p = ss.getTransientId(stm.getPredicate());\r
331                                                         int o = ss.getTransientId(stm.getObject());\r
332                                                         String sName = NameUtils.getSafeName(graph, stm.getSubject());\r
333                                                         String pName = NameUtils.getSafeName(graph, stm.getPredicate());\r
334                                                         String oName = NameUtils.getSafeName(graph, stm.getObject());\r
335                                                         b.append(" S '" + sName + "' '" + pName + "' '" + oName + "' " + s + " " + p + " " + o + "\n");\r
336                                                 }\r
337                                                 for(Resource r : listValues(tg)) {\r
338                                                         String sName = NameUtils.getSafeName(graph, r);\r
339                                                         Object value = graph.getPossibleValue(r);\r
340                                                         b.append(" V '" + sName + "' '" + value + "'\n");\r
341                                                 }\r
342                                         }\r
343                                         FileUtils.writeFile(file, b.toString().getBytes());\r
344                                 } catch (IOException e) {\r
345                                         e.printStackTrace();\r
346                                         return "ERROR";\r
347                                 } catch (DatabaseException e) {\r
348                                         e.printStackTrace();\r
349                                         return "ERROR";\r
350                                 }\r
351                                 return "OK";\r
352 \r
353                         }\r
354 \r
355                 });\r
356                 return "OK";\r
357 \r
358         }\r
359 \r
360         @Override\r
361         public VirtualGraph getGraph(ReadGraph graph, Resource subject, Resource predicate, Resource object) throws DatabaseException {\r
362                 ReadGraphImpl impl = (ReadGraphImpl)graph;\r
363                 return impl.processor.getProvider(subject, predicate, object);\r
364         }\r
365 \r
366         @Override\r
367         public VirtualGraph getGraph(ReadGraph graph, Resource subject, Resource predicate) throws DatabaseException {\r
368                 ReadGraphImpl impl = (ReadGraphImpl)graph;\r
369                 return impl.processor.getProvider(subject, predicate);\r
370         }\r
371 \r
372         @Override\r
373         public VirtualGraph getGraph(ReadGraph graph, Resource subject) throws DatabaseException {\r
374                 Layer0 L0 = Layer0.getInstance(graph);\r
375                 if(graph.hasStatement(subject, L0.InstanceOf)) {\r
376                         return getGraph(graph, subject, L0.InstanceOf);\r
377                 } else if (graph.hasStatement(subject, L0.Inherits)) {\r
378                         return getGraph(graph, subject, L0.Inherits);\r
379                 } else if (graph.hasStatement(subject, L0.SubrelationOf)) {\r
380                         return getGraph(graph, subject, L0.SubrelationOf);\r
381                 } else {\r
382                         throw new DatabaseException("Resource is invalid, should have a statement with either L0.InstanceOf, L0.Inherits or L0.SubrelationOf " + subject);\r
383                 }\r
384         }\r
385         \r
386 }\r