1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.db.impl;
\r
14 import java.io.Closeable;
\r
15 import java.io.File;
\r
16 import java.io.IOException;
\r
17 import java.util.ArrayList;
\r
18 import java.util.Arrays;
\r
19 import java.util.Collection;
\r
20 import java.util.HashSet;
\r
21 import java.util.LinkedList;
\r
23 import org.simantics.databoard.Bindings;
\r
24 import org.simantics.databoard.binding.Binding;
\r
25 import org.simantics.databoard.serialization.SerializationException;
\r
26 import org.simantics.databoard.serialization.Serializer;
\r
27 import org.simantics.databoard.serialization.SerializerConstructionException;
\r
28 import org.simantics.db.AsyncReadGraph;
\r
29 import org.simantics.db.AsyncRequestProcessor;
\r
30 import org.simantics.db.RequestProcessor;
\r
31 import org.simantics.db.Resource;
\r
32 import org.simantics.db.Statement;
\r
33 import org.simantics.db.VirtualGraphContext;
\r
34 import org.simantics.db.VirtualGraphSource;
\r
35 import org.simantics.db.WriteGraph;
\r
36 import org.simantics.db.WriteOnlyGraph;
\r
37 import org.simantics.db.common.ByteFileReader;
\r
38 import org.simantics.db.common.ByteFileWriter;
\r
39 import org.simantics.db.common.StandardStatement;
\r
40 import org.simantics.db.common.request.WriteOnlyRequest;
\r
41 import org.simantics.db.common.request.WriteRequest;
\r
42 import org.simantics.db.common.utils.Logger;
\r
43 import org.simantics.db.exception.DatabaseException;
\r
44 import org.simantics.db.impl.graph.ReadGraphImpl;
\r
45 import org.simantics.db.impl.support.ResourceSupport;
\r
46 import org.simantics.db.impl.support.VirtualGraphServerSupport;
\r
47 import org.simantics.db.procedure.AsyncProcedure;
\r
48 import org.simantics.db.request.Write;
\r
49 import org.simantics.db.request.WriteOnly;
\r
50 import org.simantics.db.service.SerialisationSupport;
\r
51 import org.simantics.utils.datastructures.Callback;
\r
53 import gnu.trove.list.array.TIntArrayList;
\r
54 import gnu.trove.map.hash.TIntObjectHashMap;
\r
55 import gnu.trove.procedure.TIntObjectProcedure;
\r
56 import gnu.trove.procedure.TIntProcedure;
\r
57 import gnu.trove.set.hash.TIntHashSet;
\r
59 class VirtualCluster {
\r
60 static final boolean DEBUG = false;
\r
61 final static int[] EMPTY = new int[0];
\r
63 private final ArrayList<TIntArrayList> statements = new ArrayList<TIntArrayList>();
\r
64 private final TIntHashSet lazy = new TIntHashSet();
\r
65 private final TIntObjectHashMap<byte[]> values = new TIntObjectHashMap<byte[]>();
\r
66 private final int clusterId;
\r
68 public VirtualCluster(int clusterId) {
\r
69 this.clusterId = clusterId;
\r
72 public int clusterId() {
\r
76 public void trim() {
\r
79 private TIntArrayList getPredicateMap(int subject) {
\r
81 int rId = ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(subject);
\r
82 if(rId >= statements.size()) return null;
\r
83 return statements.get(rId);
\r
87 public boolean isPending(int subject) {
\r
88 return lazy.contains(subject);
\r
91 boolean containsPredicate(TIntArrayList statements, int predicate) {
\r
92 for(int i=0;i<statements.size();i+=2) if(statements.getQuick(i) == predicate) return true;
\r
96 int containsStatement(TIntArrayList statements, int predicate, int object) {
\r
97 for(int i=0;i<statements.size();i+=2) if(statements.getQuick(i) == predicate && statements.getQuick(i+1) == object) return i;
\r
101 public boolean isPending(int subject, int predicate) {
\r
103 if(!lazy.contains(subject)) return false;
\r
104 TIntArrayList predicateMap = getPredicateMap(subject);
\r
105 if(predicateMap == null) return true;
\r
106 return !containsPredicate(predicateMap, predicate);
\r
107 // return !predicateMap.contains(predicate);
\r
111 public void resetLazy(int subject) {
\r
113 lazy.remove(subject);
\r
114 // Query all data from scratch
\r
115 int ri = ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(subject);
\r
116 statements.set(ri, new TIntArrayList());
\r
120 public void setLazy(int subject) {
\r
126 public void finish(int subject) {
\r
128 lazy.remove(subject);
\r
132 public void setValue(int subject, byte[] data, int length) {
\r
134 values.put(subject, Arrays.copyOf(data, length));
\r
138 public void denyValue(int subject) {
\r
140 values.remove(subject);
\r
144 public void addStatements(int subject, int[] data) {
\r
146 TIntArrayList result = getPredicateMap(subject);
\r
147 if(result == null) {
\r
148 result = new TIntArrayList();
\r
149 int rId = ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(subject);
\r
150 statements.ensureCapacity(rId+1);
\r
151 for(int i=statements.size();i<rId+1;i++) statements.add(null);
\r
152 statements.set(rId, result);
\r
155 for(int i=0;i<data.length;i+=2) {
\r
156 int predicate = data[i];
\r
157 int object = data[i+1];
\r
158 if(containsStatement(result, predicate, object) < 0) {
\r
159 result.add(predicate);
\r
160 result.add(object);
\r
166 public void claim(int subject, int predicate, int object) {
\r
168 TIntArrayList predicates = getPredicateMap(subject);
\r
169 if(predicates == null) {
\r
170 predicates = new TIntArrayList();
\r
171 int rId = ClusterTraitsBase.getResourceIndexFromResourceKeyNoThrow(subject);
\r
172 statements.ensureCapacity(rId+1);
\r
173 for(int i=statements.size();i<rId+1;i++) statements.add(null);
\r
174 statements.set(rId, predicates);
\r
177 if(containsStatement(predicates, predicate, object) < 0) {
\r
178 predicates.add(predicate);
\r
179 predicates.add(object);
\r
184 public void deny(int subject, int predicate, int object) {
\r
186 TIntArrayList predicates = getPredicateMap(subject);
\r
187 if(predicates == null) return;
\r
188 int index = containsStatement(predicates, predicate, object);
\r
189 if(index < 0) return;
\r
190 predicates.remove(index, 2);
\r
194 int[] getObjects(int subject, int predicate) {
\r
196 TIntArrayList predicates = getPredicateMap(subject);
\r
197 if(predicates == null) return EMPTY;
\r
198 TIntArrayList result = new TIntArrayList();
\r
199 for(int i=0;i<predicates.size();i+=2) {
\r
200 if(predicates.getQuick(i) == predicate) {
\r
201 result.add(predicates.getQuick(i+1));
\r
204 return result.toArray();
\r
208 int[] getPredicates(int subject) {
\r
210 TIntArrayList predicates = getPredicateMap(subject);
\r
211 if(predicates == null) return EMPTY;
\r
212 TIntHashSet result = new TIntHashSet();
\r
213 for(int i=0;i<predicates.size();i+=2) {
\r
214 result.add(predicates.getQuick(i));
\r
216 return result.toArray();
\r
220 byte[] getValue(int subject) {
\r
221 return values.get(subject);
\r
224 public int getTransientClusterKey() {
\r
225 int clusterBits = ClusterTraitsBase.getClusterBits(clusterId>>>1);
\r
226 if((clusterId & 1) == 0) // Virtual subjects
\r
227 return clusterBits | 0x80000000; // We are assuming that MSB means virtual resource.
\r
228 else // Database subjects
\r
229 return clusterBits;
\r
232 public int getTransientId(int subject) {
\r
233 if((clusterId & 1) == 0) // Virtual subjects
\r
234 return ClusterTraitsBase.createResourceKeyNoThrow(clusterId>>1, subject) | 0x80000000;
\r
235 else // Database subjects
\r
236 return ClusterTraitsBase.createResourceKeyNoThrow(clusterId>>1, subject);
\r
240 * Creates a persistent identifier for given transient graph cluster identifier.
\r
243 * For persistent clusters this obtains the random access id for (invalid)
\r
244 * resource at index 0 of given cluster. LSB in given id indicates persistence
\r
249 public static long getClusterIdentifier(SerialisationSupport ss, int clusterKey) {
\r
250 if((clusterKey & 1) == 0)// Virtual subjects
\r
252 else { // Database subjects
\r
253 int rk = ClusterTraitsBase.createResourceKeyNoThrow(clusterKey>>1, 1);
\r
255 // Assuming that cluster's first resource is created first and not deleted.
\r
256 // Assuming that resource index is in LSB bits.
\r
257 return ss.getRandomAccessId(rk);
\r
258 } catch (DatabaseException e) {
\r
259 Logger.defaultLogError("Could not get cluster id for virtual cluster key=" + clusterKey, e);
\r
265 public void saveImpl(final File file, SerialisationSupport ss) throws IOException {
\r
267 System.out.println("DEBUG: Saving virtual cluster " + clusterId + " to " + file.getAbsolutePath());
\r
269 final ByteFileWriter writer = new ByteFileWriter(file);
\r
274 for(TIntArrayList list : statements) {
\r
276 stms += list.size();
\r
279 writer.write((int)(1.5*stms));
\r
280 @SuppressWarnings("unused")
\r
282 for(int i=0;i<statements.size();i++) {
\r
283 TIntArrayList list = statements.get(i);
\r
285 for(int j=0;j<list.size();j+=2) {
\r
287 writer.write((short)i);
\r
288 int rk = list.getQuick(j);
\r
289 long rid = ss.getRandomAccessId(rk);
\r
291 rk = list.getQuick(j+1);
\r
292 rid = ss.getRandomAccessId(rk);
\r
295 } catch (DatabaseException e) {
\r
296 e.printStackTrace();
\r
302 writer.write(values.size());
\r
304 values.forEachEntry(new TIntObjectProcedure<byte[]>() {
\r
307 public boolean execute(int a, byte[] b) {
\r
309 writer.write(b.length);
\r
315 System.out.println("TransientGraph[" + file.getAbsolutePath() + "] wrote " + count + " statements and " + values.size() + " values to disk.");
\r
319 // FileUtils.uncheckedClose(_os);
\r
323 public void load(File file, SerialisationSupport serialization, VirtualGraphServerSupport vgss) throws DatabaseException {
\r
325 System.out.println("DEBUG: Loading virtual cluster " + clusterId + " from " + file.getAbsolutePath() + " " + file.length());
\r
327 ByteFileReader reader = null;
\r
330 if (!file.exists())
\r
333 reader = new ByteFileReader(file);
\r
334 int clusterInt = ClusterTraitsBase.getClusterBits(clusterId()>>1);
\r
335 int stms = reader.readInt();
\r
336 for (int i = 0; i < stms; i += 3) {
\r
337 // int rId = reader.readShort();
\r
338 // if(vgss != null) vgss.addVirtual(clusterInt + rId);
\r
340 // serialization.getTransientId(reader.readLong()),
\r
341 // serialization.getTransientId(reader.readLong()));
\r
342 int rId = reader.readShort();
\r
343 long sId = reader.readLong();
\r
344 long oId = reader.readLong();
\r
345 int sTransientId = serialization.getTransientId(sId);
\r
346 int oTransientId = serialization.getTransientId(oId);
\r
349 vgss.addVirtual(clusterInt + rId);
\r
351 claim(rId, sTransientId, oTransientId);
\r
354 int values = reader.readInt();
\r
355 for (int i = 0; i < values; i++) {
\r
356 int subject = reader.readInt();
\r
357 int length = reader.readInt();
\r
358 setValue(subject, reader.readBytes(length), length);
\r
361 System.out.println("DEBUG: TransientGraph[" + file.getAbsolutePath() + "] loaded " + stms / 3 + " statements and " + values + " values from disk.");
\r
363 } catch (IOException e) {
\r
364 throw new DatabaseException(e);
\r
366 if (reader != null)
\r
371 void listStatements(SerialisationSupport ss, ArrayList<Statement> result) {
\r
373 int clusterKey = getTransientClusterKey();
\r
376 for(int i=0;i<statements.size();i++) {
\r
377 TIntArrayList list = statements.get(i);
\r
379 Resource subject = ss.getResource(clusterKey | i);
\r
380 for(int j=0;j<list.size();j+=2) {
\r
381 Resource p = ss.getResource(list.getQuick(j));
\r
382 Resource o = ss.getResource(list.getQuick(j+1));
\r
383 result.add(new StandardStatement(subject, p, o));
\r
388 } catch (DatabaseException e) {
\r
389 e.printStackTrace();
\r
394 void listValues(final SerialisationSupport ss, final ArrayList<Resource> result) {
\r
396 values.forEachKey(new TIntProcedure() {
\r
399 public boolean execute(int value) {
\r
401 result.add(ss.getResource(getTransientId(value)));
\r
402 } catch (DatabaseException e) {
\r
403 e.printStackTrace();
\r
414 public class TransientGraph implements VirtualGraphImpl, VirtualGraphContext {
\r
415 private static final boolean DEBUG = VirtualCluster.DEBUG;
\r
416 final private static int SWAP_LIMIT = 30;
\r
418 // final private static byte[] NO_VALUE = new byte[0];
\r
419 final private static VirtualCluster NO_CLUSTER = new VirtualCluster(-1);
\r
421 final private Persistency persistency;
\r
423 final private SerialisationSupport serialization;
\r
424 final private ResourceSupport resourceSupport;
\r
425 final private VirtualGraphServerSupport virtualGraphServerSupport;
\r
426 final private RequestProcessor sessionRequestProcessor;
\r
429 * Cluster array by index.
\r
430 * -NO_CLUSTER value means that there is no such virtual cluster
\r
431 * -null value means that such virtual cluster could be on disk
\r
433 final private ArrayList<VirtualCluster> clusters = new ArrayList<VirtualCluster>();
\r
436 * A list of resident clusters
\r
438 final private LinkedList<VirtualCluster> memoryClusters = new LinkedList<VirtualCluster>();
\r
440 private final HashSet<VirtualGraphSource> sources = new HashSet<VirtualGraphSource>();
\r
442 final String identifier;
\r
443 final String databaseId;
\r
445 TIntObjectHashMap<TIntHashSet> NO_STATEMENTS = new TIntObjectHashMap<TIntHashSet>();
\r
447 int[] EMPTY = new int[0];
\r
449 public static TransientGraph workspacePersistent(SerialisationSupport ss, VirtualGraphServerSupport vgss, ResourceSupport rs, RequestProcessor srp, String databaseId, String identifier) throws DatabaseException {
\r
450 TransientGraph graph = new TransientGraph(ss, vgss, rs, srp, databaseId, identifier, Persistency.WORKSPACE);
\r
455 public static TransientGraph memoryPersistent(SerialisationSupport ss, VirtualGraphServerSupport vgss, ResourceSupport rs, RequestProcessor srp, String databaseId, String identifier) {
\r
456 return new TransientGraph(ss, vgss, rs, srp, databaseId, identifier, Persistency.MEMORY);
\r
459 private TransientGraph(SerialisationSupport ss, VirtualGraphServerSupport vgss, ResourceSupport rs, RequestProcessor srp, String databaseId, String identifier, Persistency persistency) {
\r
460 this.serialization = ss;
\r
461 this.virtualGraphServerSupport = vgss;
\r
462 this.sessionRequestProcessor = srp;
\r
463 this.resourceSupport = rs;
\r
464 this.identifier = identifier;
\r
465 this.databaseId = databaseId;
\r
467 this.persistency = persistency;
\r
470 public String getIdentifier() {
\r
474 private int transientClusterId(long id) throws DatabaseException {
\r
476 System.out.println("DEBUG: transientClusterId=" + id);
\r
477 if ((id & 1) == 0) // Cluster of virtual subjects
\r
479 // Corresponds to persistent cluster
\r
480 int rk = serialization.getTransientId(id);
\r
481 return ClusterTraitsBase.getClusterKeyFromResourceKey(rk) << 1 | 1;
\r
484 private String getPrefix() {
\r
485 return identifier + "." + persistency.identifier() + "." + databaseId;
\r
488 private void load() throws DatabaseException {
\r
490 String prefix = getPrefix();
\r
491 for(String file : virtualGraphServerSupport.storagePath().list()) {
\r
493 if(file.startsWith(prefix)) {
\r
494 long clusterLong = Long.parseLong(file.substring(prefix.length()+4));
\r
495 int clusterId = transientClusterId(clusterLong);
\r
496 VirtualCluster cluster = new VirtualCluster(clusterId);
\r
497 cluster.load(new File(virtualGraphServerSupport.storagePath(), file), serialization, (clusterId & 1) > 0 ? virtualGraphServerSupport : null);
\r
498 clusters.ensureCapacity(clusterId+1);
\r
499 for(int i=clusters.size(); i<clusterId+1; i++) clusters.add(null);
\r
500 clusters.set(clusterId, cluster);
\r
501 memoryClusters.addLast(cluster);
\r
503 } catch (DatabaseException t) {
\r
504 // file is assumably broken, delete it
\r
505 File filee = new File(virtualGraphServerSupport.storagePath(), file);
\r
506 if (!filee.delete()) {
\r
507 System.err.println("Could not delete file " + filee.getAbsolutePath());
\r
515 public void dispose() {
\r
517 saveImpl(serialization);
\r
518 } catch (IOException e) {
\r
519 e.printStackTrace();
\r
523 public void save() {
\r
526 saveImpl(serialization);
\r
527 } catch (IOException e) {
\r
528 e.printStackTrace();
\r
533 public void saveImpl(final SerialisationSupport ss) throws IOException {
\r
535 for(VirtualCluster cluster : memoryClusters) {
\r
536 String prefix = getPrefix();
\r
537 File file = new File(virtualGraphServerSupport.storagePath(), prefix + ".vg." + VirtualCluster.getClusterIdentifier(ss, cluster.clusterId()));
\r
538 cluster.saveImpl(file, ss);
\r
544 * Closes a stream and ignores any resulting exception. This is useful
\r
545 * when doing stream cleanup in a finally block where secondary exceptions
\r
546 * are not worth logging.
\r
548 static void uncheckedClose(Closeable closeable) {
\r
550 if (closeable != null)
\r
552 } catch (IOException e) {
\r
557 private void trimClusters() {
\r
558 for(VirtualCluster cluster : memoryClusters) {
\r
564 * Returns a transient cluster index
\r
565 * -Transient clusters for persistent resources have index with LSB=1
\r
566 * -Transient clusters for virtual resources have index with LSB=0
\r
568 * @param subject is a DB client transient id
\r
570 * For persistent resources cluster id is 2*clusterKey+1
\r
571 * For virtual resources transient ids are persistent and are directly chunked into 14-bit clusters.
\r
574 public static int getVirtualClusterKey(int subject) {
\r
576 int ck = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(subject);
\r
577 return (ck << 1) | 1;
\r
579 int ck = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(~subject);
\r
583 private VirtualCluster getOrLoad(int virtualClusterKey) {
\r
585 if(virtualClusterKey < clusters.size()) {
\r
586 VirtualCluster cluster = clusters.get(virtualClusterKey);
\r
587 if(NO_CLUSTER == cluster) return null;
\r
588 if(cluster != null) return cluster;
\r
591 System.out.println("Loading virtual cluster " + virtualClusterKey + " for " + identifier);
\r
593 clusters.ensureCapacity(virtualClusterKey+1);
\r
594 for(int i=clusters.size(); i<virtualClusterKey+1; i++) clusters.add(null);
\r
596 //if(!VirtualCluster.isValidVirtualClusterKey(serialization, virtualClusterKey)) return null;
\r
598 long clusterIdentifier = VirtualCluster.getClusterIdentifier(serialization, virtualClusterKey);
\r
599 File file = new File(virtualGraphServerSupport.storagePath(), getPrefix() + ".vg." + clusterIdentifier);
\r
600 if(file.exists()) {
\r
601 VirtualCluster cluster = new VirtualCluster(virtualClusterKey);
\r
602 // System.out.println("Loading virtual cluster2 " + virtualClusterKey + " for " + identifier);
\r
604 cluster.load(file, serialization, (virtualClusterKey & 1) > 0 ? virtualGraphServerSupport : null);
\r
605 clusters.set(virtualClusterKey, cluster);
\r
606 memoryClusters.addFirst(cluster);
\r
609 } catch (DatabaseException e) {
\r
610 e.printStackTrace();
\r
611 // File must be corrupt, lets delete it so we wont load it next time in future
\r
614 clusters.set(virtualClusterKey, NO_CLUSTER);
\r
619 clusters.set(virtualClusterKey, NO_CLUSTER);
\r
624 private void swap() {
\r
627 while(memoryClusters.size() > SWAP_LIMIT) {
\r
628 VirtualCluster remo = memoryClusters.removeLast();
\r
629 File file = new File(virtualGraphServerSupport.storagePath(), getPrefix() + ".vg." + VirtualCluster.getClusterIdentifier(serialization, remo.clusterId()));
\r
631 remo.saveImpl(file, serialization);
\r
632 } catch (IOException e) {
\r
633 e.printStackTrace();
\r
635 clusters.set(remo.clusterId(), null);
\r
640 private synchronized VirtualCluster getCluster(int subject, boolean create) {
\r
642 int clusterId = getVirtualClusterKey(subject);
\r
644 VirtualCluster cluster = getOrLoad(clusterId);
\r
645 if(cluster != null) return cluster;
\r
649 clusters.ensureCapacity(clusterId+1);
\r
650 for(int i=clusters.size(); i<clusterId+1; i++) clusters.add(null);
\r
651 cluster = new VirtualCluster(clusterId);
\r
652 clusters.set(clusterId, cluster);
\r
653 memoryClusters.addFirst(cluster);
\r
663 private synchronized void applyValue(int subject, Object value, Binding binding) {
\r
666 Serializer serializer = Bindings.getSerializer( binding );
\r
667 byte[] serialized = serializer.serialize(value);
\r
668 VirtualCluster cluster = getCluster(subject, true);
\r
669 cluster.setValue(subject, serialized, serialized.length);
\r
670 } catch (SerializationException e) {
\r
671 e.printStackTrace();
\r
672 } catch (SerializerConstructionException e) {
\r
673 e.printStackTrace();
\r
674 } catch (IOException e) {
\r
675 // TODO Auto-generated catch block
\r
676 e.printStackTrace();
\r
681 private synchronized void applyStatements(int subject, int[] statements) {
\r
683 VirtualCluster cluster = getCluster(subject, true);
\r
684 cluster.addStatements(subject, statements);
\r
687 if(subject > 0) virtualGraphServerSupport.addVirtual(subject);
\r
691 private synchronized void produceAllStatements(ReadGraphImpl graph, final int subject, final AsyncProcedure<Object> procedure) throws DatabaseException {
\r
693 VirtualCluster cluster = getCluster(subject, true);
\r
695 // This resource becomes a normal resource, all data is requeried
\r
696 cluster.resetLazy(subject);
\r
698 for(VirtualGraphSource source : sources) {
\r
699 source.getStatements(graph, this, subject);
\r
702 if(subject > 0) virtualGraphServerSupport.addVirtual(subject);
\r
706 private synchronized void producePartialStatements(ReadGraphImpl graph, final int subject, final int predicate, final AsyncProcedure<Object> procedure) throws DatabaseException {
\r
708 for(VirtualGraphSource source : sources) {
\r
709 source.getStatements(graph, this, subject, predicate);
\r
712 if(subject > 0) virtualGraphServerSupport.addVirtual(subject);
\r
717 public int getIndex(Resource resource) {
\r
719 return serialization.getTransientId(resource);
\r
720 } catch (DatabaseException e) {
\r
721 e.printStackTrace();
\r
727 public Resource getResource(int index) {
\r
728 return new ResourceImpl(resourceSupport, index);
\r
732 public void register(final VirtualGraphSource source) {
\r
733 if(sources.add(source)) {
\r
734 source.attach(TransientGraph.this);
\r
739 public void claim(int subject, int predicate, int object) {
\r
741 VirtualCluster cluster = getCluster(subject, true);
\r
742 cluster.claim(subject, predicate, object);
\r
743 if(subject > 0) virtualGraphServerSupport.addVirtual(subject);
\r
748 public synchronized int[] getObjects(int subject, int predicate) {
\r
749 VirtualCluster cluster = getCluster(subject, false);
\r
750 if(cluster == null) return EMPTY;
\r
751 return cluster.getObjects(subject, predicate);
\r
755 public synchronized int[] getPredicates(int subject) {
\r
756 VirtualCluster cluster = getCluster(subject, false);
\r
757 if(cluster == null) return EMPTY;
\r
758 return cluster.getPredicates(subject);
\r
762 public synchronized byte[] getValue(int subject) {
\r
763 VirtualCluster cluster = getCluster(subject, false);
\r
764 if(cluster == null) return null;
\r
765 return cluster.getValue(subject);
\r
769 public int newResource(boolean isLazy) {
\r
771 int id = virtualGraphServerSupport.createVirtual();
\r
772 VirtualCluster cluster = getCluster(id, true);
\r
773 if(isLazy) cluster.setLazy(id);
\r
779 public void finish(int subject) {
\r
780 VirtualCluster cluster = getCluster(subject, false);
\r
781 cluster.finish(subject);
\r
785 public void deny(int subject, int predicate, int object) {
\r
787 VirtualCluster cluster = getCluster(subject, true);
\r
788 cluster.deny(subject, predicate, object);
\r
793 public void claimValue(int subject, byte[] data, int length) {
\r
795 VirtualCluster cluster = getCluster(subject, true);
\r
796 cluster.setValue(subject, data, length);
\r
797 if(subject > 0) virtualGraphServerSupport.addVirtual(subject);
\r
802 public void denyValue(int subject) {
\r
803 // FIXME: this implementation is probably not proper, Antti needs to work on this.
\r
804 VirtualCluster cluster = getCluster(subject, true);
\r
805 cluster.denyValue(subject);
\r
806 if(subject > 0) virtualGraphServerSupport.removeVirtual(subject);
\r
810 public void initialise(final Write write) {
\r
812 sessionRequestProcessor.syncRequest(new WriteRequest(this) {
\r
815 public void perform(WriteGraph graph) throws DatabaseException {
\r
816 write.perform(graph);
\r
820 } catch (DatabaseException e) {
\r
821 e.printStackTrace();
\r
826 public void postModification(AsyncRequestProcessor processor, final WriteOnly request) {
\r
828 if(processor == null) processor = sessionRequestProcessor;
\r
830 processor.asyncRequest(new WriteOnlyRequest(this) {
\r
833 public void perform(WriteOnlyGraph graph) throws DatabaseException {
\r
834 request.perform(graph);
\r
842 public void updateStatements(int resource, int[] statements) {
\r
843 applyStatements(resource, statements);
\r
847 public void updateValue(int resource, Object value, Binding binding) {
\r
848 applyValue(resource, value, binding);
\r
852 public boolean isPending(int subject) {
\r
854 VirtualCluster cluster = getCluster(subject, false);
\r
855 if(cluster == null) return false;
\r
856 else return cluster.isPending(subject);
\r
861 public boolean isPending(int subject, int predicate) {
\r
863 VirtualCluster cluster = getCluster(subject, false);
\r
864 if(cluster == null) return false;
\r
865 else return cluster.isPending(subject, predicate);
\r
870 public void load(ReadGraphImpl graph, int resource, int predicate, final Callback<ReadGraphImpl> callback) throws DatabaseException {
\r
871 producePartialStatements(graph, resource, predicate, new AsyncProcedure<Object>() {
\r
874 public void execute(AsyncReadGraph graph, Object result) {
\r
875 callback.run((ReadGraphImpl)graph);
\r
879 public void exception(AsyncReadGraph graph, Throwable throwable) {
\r
880 callback.run((ReadGraphImpl)graph);
\r
887 public void load(ReadGraphImpl graph, int resource, final Callback<ReadGraphImpl> callback) throws DatabaseException {
\r
888 produceAllStatements(graph, resource, new AsyncProcedure<Object>() {
\r
891 public void execute(AsyncReadGraph graph, Object result) {
\r
892 callback.run((ReadGraphImpl)graph);
\r
896 public void exception(AsyncReadGraph graph, Throwable throwable) {
\r
897 callback.run((ReadGraphImpl)graph);
\r
903 public Collection<Statement> listStatements() {
\r
904 ArrayList<Statement> result = new ArrayList<Statement>();
\r
905 for(int i=0;i<clusters.size();i++) {
\r
906 VirtualCluster cluster = getOrLoad(i);
\r
907 if(cluster != null) {
\r
908 cluster.listStatements(serialization, result);
\r
914 public Collection<Resource> listValues() {
\r
915 ArrayList<Resource> result = new ArrayList<Resource>();
\r
916 for(int i=0;i<clusters.size();i++) {
\r
917 VirtualCluster cluster = getOrLoad(i);
\r
918 if(cluster != null) {
\r
919 cluster.listValues(serialization, result);
\r
926 public Persistency getPersistency() {
\r
927 return persistency;
\r
931 public String toString() {
\r
932 String result = "'" + identifier + "'";
\r
933 if(Persistency.WORKSPACE == persistency) result += " (W)";
\r
934 else if(Persistency.MEMORY == persistency) result += " (M)";
\r