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.query;
\r
14 import gnu.trove.procedure.TIntProcedure;
\r
15 import gnu.trove.set.hash.TIntHashSet;
\r
17 import java.util.concurrent.Semaphore;
\r
18 import java.util.concurrent.atomic.AtomicInteger;
\r
20 import org.simantics.db.impl.graph.ReadGraphImpl;
\r
21 import org.simantics.db.impl.procedure.InternalProcedure;
\r
22 import org.simantics.db.procedure.ListenerBase;
\r
24 final public class SuperRelations extends UnaryQuery<InternalProcedure<IntSet>> {
\r
26 // public ArrayList<InternalProcedure<IntSet>> procs = null;
\r
28 private SuperRelations(final int resource) {
\r
32 final static SuperRelations entry(final QueryProcessor provider, final int r) {
\r
34 return (SuperRelations)provider.superRelationsMap.get(r);
\r
38 final static IntSet runner(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<IntSet> procedure) {
\r
40 SuperRelations entry = (SuperRelations)provider.superRelationsMap.get(r);
\r
43 entry = new SuperRelations(r);
\r
45 entry.clearResult(provider.querySupport);
\r
46 entry.putEntry(provider);
\r
48 return (IntSet)provider.performForEach(graph, entry, parent, listener, procedure);
\r
52 if(!entry.isReady()) {
\r
53 throw new IllegalStateException();
\r
55 return (IntSet)provider.performForEach(graph, entry, parent, listener, procedure);
\r
61 final static IntSet runner2(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<IntSet> procedure) throws Throwable {
\r
63 SuperRelations entry = (SuperRelations)provider.superRelationsMap.get(r);
\r
66 entry = new SuperRelations(r);
\r
68 entry.clearResult(provider.querySupport);
\r
69 entry.putEntry(provider);
\r
71 return (IntSet)provider.performForEach2(graph, entry, parent, listener, procedure);
\r
75 if(!entry.isReady()) {
\r
76 throw new IllegalStateException();
\r
78 return (IntSet)provider.performForEach2(graph, entry, parent, listener, procedure);
\r
84 final public static void queryEach(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<IntSet> procedure) {
\r
86 if(parent == null && listener == null) {
\r
87 SuperRelations entry = (SuperRelations)provider.superRelationsMap.get(r);
\r
88 if(entry != null && entry.isReady()) {
\r
89 entry.performFromCache(graph, provider, procedure);
\r
94 runner(graph, r, provider, parent, listener, procedure);
\r
98 final public static IntSet queryEach2(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<IntSet> procedure) throws Throwable {
\r
100 if(parent == null && listener == null) {
\r
101 SuperRelations entry = (SuperRelations)provider.superRelationsMap.get(r);
\r
102 if(entry != null && entry.isReady()) {
\r
103 return (IntSet)entry.get(graph, provider, procedure);
\r
107 return runner2(graph, r, provider, parent, listener, procedure);
\r
112 public UnaryQuery<InternalProcedure<IntSet>> getEntry(QueryProcessor provider) {
\r
113 return provider.superRelationsMap.get(id);
\r
117 public void putEntry(QueryProcessor provider) {
\r
118 provider.superRelationsMap.put(id, this);
\r
122 final public void removeEntry(QueryProcessor provider) {
\r
123 provider.superRelationsMap.remove(id);
\r
126 static int histoCounter = 0;
\r
127 static IntSet EMPTY_SET = new IntSet();
\r
128 static int counter = 0;
\r
132 private TIntHashSet set = null;
\r
133 public int single = 0;
\r
135 public boolean add(int val) {
\r
136 if(single == val) return false;
\r
141 if(set == null) set = new TIntHashSet(4);
\r
142 return set.add(val);
\r
145 public int size() {
\r
147 if(single == 0) return 0;
\r
148 if(set == null) return 1;
\r
149 return set.size() + 1;
\r
153 public void forEach(TIntProcedure proc) {
\r
154 if(single > 0) proc.execute(single);
\r
155 if(set != null) set.forEach(proc);
\r
161 public Object computeForEach(final ReadGraphImpl graph, final QueryProcessor provider, final InternalProcedure<IntSet> procedure, final boolean store) {
\r
163 provider.querySupport.ensureLoaded(graph, id);
\r
165 final InternalProcedure<IntSet> proc = (InternalProcedure<IntSet>)procedure;
\r
167 final int subrelationOf = provider.getSubrelationOf();
\r
169 final IntSet result = new IntSet(provider.querySupport);
\r
171 final class DirectProcedure extends Koss implements IntProcedure, TIntProcedure, InternalProcedure<IntSet> {
\r
173 final public boolean execute(int r) {
\r
178 final public void execute(ReadGraphImpl graph, int r) {
\r
186 final public void execute(ReadGraphImpl graph, IntSet set) {
\r
188 addOrSet(graph, result, provider);
\r
189 proc.execute(graph, result);
\r
192 public void finished(ReadGraphImpl graph) {
\r
195 public void exception(ReadGraphImpl graph, Throwable t) {
\r
196 throw new Error("Errors are not supported.", t);
\r
201 final DirectProcedure directProc = new DirectProcedure();
\r
203 provider.querySupport.getObjects(graph, id, subrelationOf, directProc);
\r
205 int size = directProc.size();
\r
209 addOrSet(graph, EMPTY_SET, provider);
\r
210 proc.execute(graph, EMPTY_SET);
\r
212 } else if (size == 1) {
\r
214 result.add(directProc.single);
\r
215 SuperRelations.queryEach(graph, directProc.single, provider, SuperRelations.this, null, directProc);
\r
219 // if((counter++ % 500) == 0) System.out.println("SR " + counter);
\r
221 final TIntProcedure addToResult = new TIntProcedure() {
\r
223 public boolean execute(int r) {
\r
224 synchronized(result) {
\r
231 final AtomicInteger finishes = new AtomicInteger(0);
\r
233 directProc.forEach(new TIntProcedure() {
\r
236 public boolean execute(int arg0) {
\r
238 synchronized(result) {
\r
242 SuperRelations.queryEach(graph, arg0, provider, SuperRelations.this, null, new InternalProcedure<IntSet>() {
\r
245 public void execute(ReadGraphImpl graph, IntSet set) {
\r
246 set.forEach(addToResult);
\r
247 int current = finishes.addAndGet(1);
\r
248 if(current == directProc.size()) {
\r
249 addOrSet(graph, result, provider);
\r
250 proc.execute(graph, result);
\r
256 public void exception(ReadGraphImpl graph, Throwable t) {
\r
257 proc.exception(graph, t);
\r
275 public String toString() {
\r
276 return "SuperRelations[" + id + "]";
\r
279 private void addOrSet(ReadGraphImpl graph, final IntSet value, QueryProcessor provider) {
\r
281 assert(!isReady());
\r
283 // ArrayList<InternalProcedure<IntSet>> p = null;
\r
285 synchronized(this) {
\r
296 // IntSet v = (IntSet)getResult();
\r
298 // for(InternalProcedure<IntSet> proc : p) proc.execute(graph, v);
\r
305 public Object performFromCache(ReadGraphImpl graph, QueryProcessor provider, InternalProcedure<IntSet> procedure) {
\r
309 if(handleException(graph, procedure)) return null;
\r
311 IntSet result = getResult();
\r
313 procedure.execute(graph, result);
\r
320 public void recompute(ReadGraphImpl graph, QueryProcessor provider) {
\r
322 final Semaphore s = new Semaphore(0);
\r
324 computeForEach(graph, provider, new InternalProcedure<IntSet>() {
\r
327 public void execute(ReadGraphImpl graph, IntSet result) {
\r
332 public void exception(ReadGraphImpl graph, Throwable t) {
\r
334 new Error("Error in recompute.", t).printStackTrace();
\r
339 while(!s.tryAcquire()) {
\r
340 provider.resume(graph);
\r
347 boolean isImmutable(ReadGraphImpl graph) {
\r
348 return graph.processor.isImmutable(id);
\r