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 java.util.ArrayList;
\r
15 import java.util.concurrent.Semaphore;
\r
16 import java.util.concurrent.atomic.AtomicBoolean;
\r
18 import org.simantics.db.RelationInfo;
\r
19 import org.simantics.db.exception.DatabaseException;
\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
23 import org.simantics.db.request.RequestFlags;
\r
25 final public class RelationInfoQuery extends UnaryQuery<InternalProcedure<RelationInfo>> {
\r
27 // public ArrayList<InternalProcedure<RelationInfo>> procs = null;
\r
29 private RelationInfoQuery(final int resource) {
\r
33 final static RelationInfo runner(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<RelationInfo> procedure) {
\r
35 RelationInfoQuery entry = (RelationInfoQuery)provider.relationInfoMap.get(r);
\r
38 entry = new RelationInfoQuery(r);
\r
40 entry.clearResult(provider.querySupport);
\r
41 entry.putEntry(provider);
\r
43 provider.performForEach(graph, entry, parent, listener, procedure);
\r
45 return entry.getResult();
\r
49 if(!entry.isReady()) {
\r
50 synchronized(entry) {
\r
51 if(!entry.isReady()) {
\r
52 throw new IllegalStateException();
\r
53 // if(entry.procs == null) entry.procs = new ArrayList<InternalProcedure<RelationInfo>>();
\r
54 // entry.procs.add(procedure);
\r
55 // provider.registerDependencies(graph, entry, parent, listener, procedure, false);
\r
56 // return entry.getResult();
\r
60 provider.performForEach(graph, entry, parent, listener, procedure);
\r
62 return entry.getResult();
\r
68 final public static RelationInfo queryEach(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final InternalProcedure<RelationInfo> procedure) {
\r
70 RelationInfoQuery entry = (RelationInfoQuery)provider.relationInfoMap.get(r);
\r
71 if(entry != null && entry.isReady()) {
\r
72 entry.performFromCache(graph, provider, procedure);
\r
73 return entry.getResult();
\r
76 return runner(graph, r, provider, parent, listener, procedure);
\r
80 final public static RelationInfoQuery probe(ReadGraphImpl graph, int resource) {
\r
82 final int thread = graph.thread(resource);
\r
83 RelationInfoQuery entry = (RelationInfoQuery)graph.processor.relationInfoMap.get(resource);
\r
84 if(entry != null && entry.isReady()) {
\r
93 public UnaryQuery<InternalProcedure<RelationInfo>> getEntry(QueryProcessor provider) {
\r
94 return provider.relationInfoMap.get(id);
\r
98 public void putEntry(QueryProcessor provider) {
\r
99 provider.relationInfoMap.put(id, this);
\r
103 final public void removeEntry(QueryProcessor provider) {
\r
104 provider.relationInfoMap.remove(id);
\r
107 private void computeAssertions(ReadGraphImpl graph, final boolean isFinal, final boolean isFunctional, final QueryProcessor queryProvider, final InternalProcedure<RelationInfo> proc) {
\r
109 final int isUsedInAssertion = queryProvider.getHasPredicateInverse();
\r
110 assert(isUsedInAssertion != 0);
\r
112 DirectObjects.queryEach(graph, id, isUsedInAssertion, queryProvider, this, null, new IntProcedure() {
\r
114 AtomicBoolean done = new AtomicBoolean(false);
\r
117 public void execute(ReadGraphImpl graph, int i) {
\r
118 if(done.compareAndSet(false, true)) {
\r
119 // System.err.println("Assertions for relation " + id);
\r
120 RelationInfo result = new RelationInfo(id, isFunctional, isFinal, true);
\r
121 addOrSet(graph, result, queryProvider);
\r
122 proc.execute(graph, result);
\r
127 public void finished(ReadGraphImpl graph) {
\r
128 if(done.compareAndSet(false, true)) {
\r
129 // System.err.println("No assertions for relation " + id);
\r
130 RelationInfo result = new RelationInfo(id, isFunctional, isFinal, false);
\r
131 addOrSet(graph, result, queryProvider);
\r
132 proc.execute(graph, result);
\r
137 public void exception(ReadGraphImpl graph, Throwable throwable) {
\r
138 if(done.compareAndSet(false, true)) {
\r
139 DatabaseException e = new DatabaseException("Internal error in RelationInfoQuery");
\r
141 proc.exception(graph, e);
\r
147 // Types.queryEach(callerThread, id, queryProvider, this, null, new InternalProcedure<IntSet>() {
\r
150 // public void execute(int callerThread, IntSet types) {
\r
151 // computeAssertions(callerThread, isFinal, isFunctional, queryProvider, proc);
\r
154 ////// System.out.println("RelationInfoQuery: computeTypes execute " + types);
\r
156 //// RelationInfo result = new RelationInfo(id, types.contains(queryProvider.getFunctionalRelation()), isFinal);
\r
158 //// addOrSet(callerThread, result, queryProvider);
\r
160 //// proc.execute(callerThread, result);
\r
165 // public void exception(int callerThread, Throwable t) {
\r
166 // proc.exception(callerThread, t);
\r
173 private void computeTypes(ReadGraphImpl graph, final boolean isFinal, final QueryProcessor queryProvider, final InternalProcedure<RelationInfo> proc) {
\r
175 // System.out.println("RelationInfoQuery: computeTypes " + id);
\r
177 Types.queryEach(graph, id, queryProvider, this, null, new InternalProcedure<IntSet>() {
\r
180 public void execute(ReadGraphImpl graph, IntSet types) {
\r
181 computeAssertions(graph, isFinal, types.contains(queryProvider.getFunctionalRelation()), queryProvider, proc);
\r
183 //// System.out.println("RelationInfoQuery: computeTypes execute " + types);
\r
185 // RelationInfo result = new RelationInfo(id, types.contains(queryProvider.getFunctionalRelation()), isFinal);
\r
187 // addOrSet(callerThread, result, queryProvider);
\r
189 // proc.execute(callerThread, result);
\r
194 public void exception(ReadGraphImpl graph, Throwable t) {
\r
195 proc.exception(graph, t);
\r
203 public Object computeForEach(ReadGraphImpl graph, final QueryProcessor provider, final InternalProcedure<RelationInfo> procedure, boolean store) {
\r
205 // System.out.println("RelationInfoQuery computeForEach begin " + id + " " + getResult() + " " + statusOrException);
\r
207 final int superRelationOf = provider.getSuperrelationOf();
\r
208 assert(superRelationOf != 0);
\r
210 DirectPredicates.queryEach(graph, id, provider, this, null, new IntProcedure() {
\r
212 boolean found = false;
\r
215 public void execute(ReadGraphImpl graph, int i) {
\r
216 // System.out.println("RelationInfoQuery: execute " + i + " super = " + superRelationOf);
\r
217 if(i == superRelationOf) {
\r
218 computeTypes(graph, false, provider, procedure);
\r
224 public void finished(ReadGraphImpl graph) {
\r
225 // System.out.println("RelationInfoQuery: finished");
\r
227 computeTypes(graph, true, provider, procedure);
\r
232 public void exception(ReadGraphImpl graph, Throwable t) {
\r
233 // System.out.println("RelationInfoQuery: exception");
\r
234 procedure.exception(graph, t);
\r
239 return getResult();
\r
244 public String toString() {
\r
245 return "RelationInfoQuery[" + id + "]";
\r
248 public void addOrSet(ReadGraphImpl graph, final RelationInfo result, final QueryProcessor provider) {
\r
250 assert(isPending());
\r
252 // ArrayList<InternalProcedure<RelationInfo>> p = null;
\r
254 synchronized(this) {
\r
265 // for(InternalProcedure<RelationInfo> proc : p)
\r
266 // proc.execute(graph, (RelationInfo)result);
\r
272 public Object performFromCache(ReadGraphImpl graph, QueryProcessor provider, InternalProcedure<RelationInfo> procedure) {
\r
276 if(handleException(graph, procedure)) return EXCEPTED;
\r
278 RelationInfo result = getResult();
\r
280 procedure.execute(graph, result);
\r
287 public void recompute(ReadGraphImpl graph, QueryProcessor provider) {
\r
289 final Semaphore s = new Semaphore(0);
\r
291 computeForEach(graph, provider, new InternalProcedure<RelationInfo>() {
\r
294 public void execute(ReadGraphImpl graph, RelationInfo result) {
\r
299 public void exception(ReadGraphImpl graph, Throwable t) {
\r
300 throw new Error("Error in recompute.", t);
\r
305 while(!s.tryAcquire()) {
\r
306 provider.resume(graph);
\r
310 // } catch (InterruptedException e) {
\r
311 // throw new Error(e);
\r
317 public int type() {
\r
318 return RequestFlags.IMMEDIATE_UPDATE;
\r