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