1 package fi.vtt.simantics.procore.internal;
3 import gnu.trove.set.hash.TIntHashSet;
6 import java.io.FileInputStream;
7 import java.io.FileOutputStream;
8 import java.io.FilenameFilter;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.ObjectInputStream;
12 import java.io.ObjectOutputStream;
13 import java.io.OutputStream;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashMap;
18 import java.util.concurrent.CopyOnWriteArrayList;
19 import java.util.concurrent.atomic.AtomicInteger;
21 import org.eclipse.core.runtime.IStatus;
22 import org.eclipse.core.runtime.Status;
23 import org.simantics.db.ReadGraph;
24 import org.simantics.db.Resource;
25 import org.simantics.db.Statement;
26 import org.simantics.db.VirtualGraph;
27 import org.simantics.db.VirtualGraph.Persistency;
28 import org.simantics.db.WriteOnlyGraph;
29 import org.simantics.db.common.utils.NameUtils;
30 import org.simantics.db.exception.DatabaseException;
31 import org.simantics.db.impl.ClusterI;
32 import org.simantics.db.impl.ResourceImpl;
33 import org.simantics.db.impl.TransientGraph;
34 import org.simantics.db.impl.graph.ReadGraphImpl;
35 import org.simantics.db.impl.support.VirtualGraphServerSupport;
36 import org.simantics.db.request.Read;
37 import org.simantics.db.service.SerialisationSupport;
38 import org.simantics.db.service.ServerInformation;
39 import org.simantics.db.service.TransferableGraphSupport;
40 import org.simantics.db.service.VirtualGraphSupport;
41 import org.simantics.db.service.XSupport;
42 import org.simantics.layer0.Layer0;
43 import org.simantics.utils.FileUtils;
45 public class VirtualGraphServerSupportImpl implements VirtualGraphSupport, VirtualGraphServerSupport {
47 final private static boolean DEBUG = false;
48 final private SessionImplSocket session;
50 final public File virtualGraphStoragePath;
51 public String dbString = null;
53 public TIntHashSet virtuals = new TIntHashSet();
55 final public CopyOnWriteArrayList<TransientGraph> providers = new CopyOnWriteArrayList<TransientGraph>();
56 final private CopyOnWriteArrayList<TransientGraph> workspaceProviders = new CopyOnWriteArrayList<TransientGraph>();
57 final private CopyOnWriteArrayList<TransientGraph> memoryProviders = new CopyOnWriteArrayList<TransientGraph>();
59 public AtomicInteger virtualId;
60 private boolean hasVirtuals = false;
62 public VirtualGraphServerSupportImpl(SessionImplSocket session, File path) {
63 this.session = session;
64 this.virtualGraphStoragePath = path;
67 void connect(String dbString) throws Exception {
68 virtualId = new AtomicInteger(-2);
69 this.dbString = dbString;
71 XSupport support = session.getService(XSupport.class);
72 if (support.rolledback()) {
73 for (File file : virtualGraphStoragePath.listFiles()) {
75 throw new IOException("Could not delete file " + file.getAbsolutePath());
80 File file = new File(virtualGraphStoragePath, "virtualGraphs." + dbString + ".dat");
82 // System.out.println("scanning " + file.getAbsolutePath());
86 InputStream stream = new FileInputStream(file);
87 final ObjectInputStream os = new ObjectInputStream(stream);
88 virtualId = new AtomicInteger(os.readInt());
89 // System.out.println("virtualId=" + virtualId.get());
95 String databaseId = session.getService(ServerInformation.class).getDatabaseId();
96 String matcher = ".W." + databaseId + ".vg.";
98 // Load existing workspace persistent graphs
99 for(File virtualGraph : virtualGraphStoragePath.listFiles(new FilenameFilter() {
101 public boolean accept(File dir, String name) {
102 boolean matches = name.contains(matcher);
106 String name = virtualGraph.getName();
107 String[] parts = name.split("\\x2E", 2);
108 getWorkspacePersistent(parts[0]);
111 } catch (IOException e) {
116 System.out.println("No stored virtual graphs.");
121 public void saveVirtualGraphState(SessionImplSocket session) {
123 if(!hasVirtuals) return;
127 String databaseId = session.getService(ServerInformation.class).getDatabaseId();
128 String serverId = session.getService(ServerInformation.class).getServerId();
129 File file = new File(virtualGraphStoragePath, "virtualGraphs." + databaseId + "." + serverId + ".dat");
131 OutputStream stream = new FileOutputStream(file);
132 final ObjectOutputStream os = new ObjectOutputStream(stream);
133 os.writeInt(virtualId.get());
137 } catch (IOException e) {
143 public void disposeVirtualGraphs() {
145 if(!hasVirtuals) return;
147 saveVirtualGraphState(session);
148 for(TransientGraph graph : workspaceProviders) graph.dispose();
152 public void saveVirtualGraphs() {
154 if(!hasVirtuals) return;
156 saveVirtualGraphState(session);
157 for(TransientGraph graph : workspaceProviders) graph.save();
162 public void saveAll() {
167 public VirtualGraph getMemoryPersistent(String identifier) {
169 if(identifier == null) throw new IllegalArgumentException("Argument cannot be null!");
171 for(TransientGraph graph : memoryProviders) {
172 if(identifier.equals(graph.getIdentifier())) return graph;
175 String databaseId = session.getService(ServerInformation.class).getDatabaseId();
176 VirtualGraphServerSupport vgss = session.getService(VirtualGraphServerSupport.class);
178 TransientGraph result = TransientGraph.memoryPersistent(new SerialisationSupportImpl(session), vgss, session.resourceSupport, session, databaseId, identifier);
179 memoryProviders.add(result);
180 providers.add(result);
184 private TransientGraph createWorkspacePersistentInternal(String identifier) {
186 String databaseId = session.getService(ServerInformation.class).getDatabaseId();
187 VirtualGraphServerSupport vgss = session.getService(VirtualGraphServerSupport.class);
190 return TransientGraph.workspacePersistent(new SerialisationSupportImpl(session), vgss, session.resourceSupport, session, databaseId, identifier);
191 } catch (Exception e) {
192 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));
193 return TransientGraph.memoryPersistent(new SerialisationSupportImpl(session), vgss, session.resourceSupport, session, databaseId, identifier);
199 public VirtualGraph getWorkspacePersistent(String identifier) {
201 if(identifier == null) throw new IllegalArgumentException("Argument cannot be null!");
203 for(TransientGraph graph : workspaceProviders) {
204 if(identifier.equals(graph.getIdentifier())) return graph;
207 TransientGraph result = createWorkspacePersistentInternal(identifier);
209 workspaceProviders.add(result);
210 providers.add(result);
217 public boolean discard(VirtualGraph provider) {
218 if (!(provider instanceof TransientGraph))
220 if (!providers.remove(provider))
223 TransientGraph tg = (TransientGraph) provider;
225 if (workspaceProviders.remove(provider)) {
226 // TODO: remove possibly existing data from disk
228 } else if (memoryProviders.remove(provider)) {
234 public Resource getPersistentResource(WriteOnlyGraph graph, Resource resource, Map<Resource, Resource> creation) throws DatabaseException {
235 if(resource.isPersistent()) return resource;
237 Resource result = creation.get(resource);
239 result = graph.newResource();
240 creation.put(resource, result);
247 public boolean integrate(WriteOnlyGraph graph, VirtualGraph provider) throws DatabaseException {
249 if (!(provider instanceof TransientGraph))
251 if (!providers.remove(provider))
254 workspaceProviders.remove(provider);
255 memoryProviders.remove(provider);
257 TransferableGraphSupport tgSupport = graph.getService(TransferableGraphSupport.class);
258 TransientGraph tg = (TransientGraph) provider;
260 Map<Resource, Resource> creation = new HashMap<Resource, Resource>();
261 for(Statement stm : tg.listStatements()) {
262 Resource subject = getPersistentResource(graph, stm.getSubject(), creation);
263 Resource predicate = getPersistentResource(graph, stm.getPredicate(), creation);
264 Resource object = getPersistentResource(graph, stm.getObject(), creation);
265 graph.claim(subject, predicate, null, object);
267 for(Resource r : tg.listValues()) {
268 byte[] value = tg.getValue(((ResourceImpl)r).id);
269 tgSupport.setValue(graph, getPersistentResource(graph, r, creation), null, value);
277 public Collection<TransientGraph> getVirtualGraphs(int subject) {
278 if(subject < 0 || virtuals.contains(subject)) return providers;
283 public void removeVirtual(int id) {
288 public void addVirtual(int id) {
290 // System.err.println("addVirtual " + id);
292 ClusterI cluster = session.clusterTable.getClusterByResourceKey(id);
293 cluster.markVirtual();
297 public int createVirtual() {
298 return virtualId.decrementAndGet();
302 public File storagePath() {
303 return virtualGraphStoragePath;
307 public Collection<Statement> listStatements(VirtualGraph graph_) {
308 TransientGraph graph = (TransientGraph)graph_;
309 return graph.listStatements();
313 public Collection<Resource> listValues(VirtualGraph graph_) {
314 TransientGraph graph = (TransientGraph)graph_;
315 return graph.listValues();
319 public Collection<VirtualGraph> listGraphs() {
320 ArrayList<VirtualGraph> result = new ArrayList<VirtualGraph>();
321 result.addAll(memoryProviders);
322 result.addAll(workspaceProviders);
326 public String report(final File file) {
328 session.asyncRequest(new Read<String>() {
331 public String perform(ReadGraph graph) throws DatabaseException {
333 SerialisationSupport ss = session.getService(SerialisationSupport.class);
334 StringBuilder b = new StringBuilder();
336 for(VirtualGraph vg : listGraphs()) {
337 TransientGraph tg = (TransientGraph)vg;
338 if(Persistency.MEMORY == tg.getPersistency()) b.append("Memory persistent virtual graph '" + tg.getIdentifier() + "'\n");
339 if(Persistency.WORKSPACE == tg.getPersistency()) b.append("Workspace persistent virtual graph '" + tg.getIdentifier() + "'\n");
340 for(Statement stm : listStatements(tg)) {
341 int s = ss.getTransientId(stm.getSubject());
342 int p = ss.getTransientId(stm.getPredicate());
343 int o = ss.getTransientId(stm.getObject());
344 String sName = NameUtils.getSafeName(graph, stm.getSubject());
345 String pName = NameUtils.getSafeName(graph, stm.getPredicate());
346 String oName = NameUtils.getSafeName(graph, stm.getObject());
347 b.append(" S '" + sName + "' '" + pName + "' '" + oName + "' " + s + " " + p + " " + o + "\n");
349 for(Resource r : listValues(tg)) {
350 String sName = NameUtils.getSafeName(graph, r);
351 Object value = graph.getPossibleValue(r);
352 b.append(" V '" + sName + "' '" + value + "'\n");
355 FileUtils.writeFile(file, b.toString().getBytes());
356 } catch (IOException e) {
359 } catch (DatabaseException e) {
373 public VirtualGraph getGraph(ReadGraph graph, Resource subject, Resource predicate, Resource object) throws DatabaseException {
374 ReadGraphImpl impl = (ReadGraphImpl)graph;
375 return impl.processor.getProvider(subject, predicate, object);
379 public VirtualGraph getGraph(ReadGraph graph, Resource subject, Resource predicate) throws DatabaseException {
380 ReadGraphImpl impl = (ReadGraphImpl)graph;
381 return impl.processor.getProvider(subject, predicate);
385 public VirtualGraph getGraph(ReadGraph graph, Resource subject) throws DatabaseException {
386 Layer0 L0 = Layer0.getInstance(graph);
387 if(graph.hasStatement(subject, L0.InstanceOf)) {
388 return getGraph(graph, subject, L0.InstanceOf);
389 } else if (graph.hasStatement(subject, L0.Inherits)) {
390 return getGraph(graph, subject, L0.Inherits);
391 } else if (graph.hasStatement(subject, L0.SubrelationOf)) {
392 return getGraph(graph, subject, L0.SubrelationOf);
394 throw new DatabaseException("Resource is invalid, should have a statement with either L0.InstanceOf, L0.Inherits or L0.SubrelationOf " + subject);