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.layer0.Layer0;
\r
42 import org.simantics.utils.FileUtils;
\r
44 public class VirtualGraphServerSupportImpl implements VirtualGraphSupport, VirtualGraphServerSupport {
\r
46 final private static boolean DEBUG = false;
\r
47 final private SessionImplSocket session;
\r
49 final public File virtualGraphStoragePath;
\r
50 public String dbString = null;
\r
52 public TIntHashSet virtuals = new TIntHashSet();
\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
58 public AtomicInteger virtualId;
\r
59 private boolean hasVirtuals = false;
\r
61 public VirtualGraphServerSupportImpl(SessionImplSocket session, File path) {
\r
62 this.session = session;
\r
63 this.virtualGraphStoragePath = path;
\r
66 void connect(String dbString) {
\r
68 virtualId = new AtomicInteger(-2);
\r
70 this.dbString = dbString;
\r
72 File file = new File(virtualGraphStoragePath, "virtualGraphs." + dbString + ".dat");
\r
74 // System.out.println("scanning " + file.getAbsolutePath());
\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
87 // Load existing workspace persistent graphs
\r
88 for(File virtualGraph : virtualGraphStoragePath.listFiles(new FilenameFilter() {
\r
90 public boolean accept(File dir, String name) {
\r
91 return name.endsWith(".vg");
\r
94 String name = virtualGraph.getName();
\r
95 String[] parts = name.split("\\x2E", 2);
\r
96 getWorkspacePersistent(parts[0]);
\r
99 } catch (IOException e) {
\r
100 e.printStackTrace();
\r
104 System.out.println("No stored virtual graphs.");
\r
109 public void saveVirtualGraphState(SessionImplSocket session) {
\r
111 if(!hasVirtuals) return;
\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
119 OutputStream stream = new FileOutputStream(file);
\r
120 final ObjectOutputStream os = new ObjectOutputStream(stream);
\r
121 os.writeInt(virtualId.get());
\r
125 } catch (IOException e) {
\r
126 e.printStackTrace();
\r
131 public void disposeVirtualGraphs() {
\r
133 if(!hasVirtuals) return;
\r
135 saveVirtualGraphState(session);
\r
136 for(TransientGraph graph : workspaceProviders) graph.dispose();
\r
140 public void saveVirtualGraphs() {
\r
142 if(!hasVirtuals) return;
\r
144 saveVirtualGraphState(session);
\r
145 for(TransientGraph graph : workspaceProviders) graph.save();
\r
150 public void saveAll() {
\r
151 saveVirtualGraphs();
\r
155 public VirtualGraph getMemoryPersistent(String identifier) {
\r
157 if(identifier == null) throw new IllegalArgumentException("Argument cannot be null!");
\r
159 for(TransientGraph graph : memoryProviders) {
\r
160 if(identifier.equals(graph.getIdentifier())) return graph;
\r
163 String databaseId = session.getService(ServerInformation.class).getDatabaseId();
\r
164 VirtualGraphServerSupport vgss = session.getService(VirtualGraphServerSupport.class);
\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
172 private TransientGraph createWorkspacePersistentInternal(String identifier) {
\r
174 String databaseId = session.getService(ServerInformation.class).getDatabaseId();
\r
175 VirtualGraphServerSupport vgss = session.getService(VirtualGraphServerSupport.class);
\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
187 public VirtualGraph getWorkspacePersistent(String identifier) {
\r
189 if(identifier == null) throw new IllegalArgumentException("Argument cannot be null!");
\r
191 for(TransientGraph graph : workspaceProviders) {
\r
192 if(identifier.equals(graph.getIdentifier())) return graph;
\r
195 TransientGraph result = createWorkspacePersistentInternal(identifier);
\r
197 workspaceProviders.add(result);
\r
198 providers.add(result);
\r
199 hasVirtuals = true;
\r
205 public boolean discard(VirtualGraph provider) {
\r
206 if (!(provider instanceof TransientGraph))
\r
208 if (!providers.remove(provider))
\r
211 TransientGraph tg = (TransientGraph) provider;
\r
213 if (workspaceProviders.remove(provider)) {
\r
214 // TODO: remove possibly existing data from disk
\r
216 } else if (memoryProviders.remove(provider)) {
\r
222 public Resource getPersistentResource(WriteOnlyGraph graph, Resource resource, Map<Resource, Resource> creation) throws DatabaseException {
\r
223 if(resource.isPersistent()) return resource;
\r
225 Resource result = creation.get(resource);
\r
226 if(result == null) {
\r
227 result = graph.newResource();
\r
228 creation.put(resource, result);
\r
235 public boolean integrate(WriteOnlyGraph graph, VirtualGraph provider) throws DatabaseException {
\r
237 if (!(provider instanceof TransientGraph))
\r
239 if (!providers.remove(provider))
\r
242 workspaceProviders.remove(provider);
\r
243 memoryProviders.remove(provider);
\r
245 TransferableGraphSupport tgSupport = graph.getService(TransferableGraphSupport.class);
\r
246 TransientGraph tg = (TransientGraph) provider;
\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
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
265 public Collection<TransientGraph> getVirtualGraphs(int subject) {
\r
266 if(subject < 0 || virtuals.contains(subject)) return providers;
\r
271 public void removeVirtual(int id) {
\r
272 virtuals.remove(id);
\r
276 public void addVirtual(int id) {
\r
278 // System.err.println("addVirtual " + id);
\r
280 ClusterI cluster = session.clusterTable.getClusterByResourceKey(id);
\r
281 cluster.markVirtual();
\r
285 public int createVirtual() {
\r
286 return virtualId.decrementAndGet();
\r
290 public File storagePath() {
\r
291 return virtualGraphStoragePath;
\r
295 public Collection<Statement> listStatements(VirtualGraph graph_) {
\r
296 TransientGraph graph = (TransientGraph)graph_;
\r
297 return graph.listStatements();
\r
301 public Collection<Resource> listValues(VirtualGraph graph_) {
\r
302 TransientGraph graph = (TransientGraph)graph_;
\r
303 return graph.listValues();
\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
314 public String report(final File file) {
\r
316 session.asyncRequest(new Read<String>() {
\r
319 public String perform(ReadGraph graph) throws DatabaseException {
\r
321 SerialisationSupport ss = session.getService(SerialisationSupport.class);
\r
322 StringBuilder b = new StringBuilder();
\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
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
343 FileUtils.writeFile(file, b.toString().getBytes());
\r
344 } catch (IOException e) {
\r
345 e.printStackTrace();
\r
347 } catch (DatabaseException e) {
\r
348 e.printStackTrace();
\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
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
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
382 throw new DatabaseException("Resource is invalid, should have a statement with either L0.InstanceOf, L0.Inherits or L0.SubrelationOf " + subject);
\r