1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.db.impl.graph;
14 import java.util.ArrayList;
15 import java.util.Arrays;
16 import java.util.Collection;
17 import java.util.HashMap;
18 import java.util.concurrent.atomic.AtomicInteger;
20 import org.simantics.db.common.utils.Logger;
21 import org.simantics.db.exception.RuntimeDatabaseException;
22 import org.simantics.db.impl.query.QueryProcessor.AsyncBarrier;
23 import org.simantics.db.impl.query.QueryProcessor.SessionTask;
24 import org.simantics.utils.Development;
26 final public class AsyncBarrierImpl extends AtomicInteger implements AsyncBarrier {
28 private static final long serialVersionUID = 4724463372850048672L;
30 static final HashMap<AsyncBarrierImpl, Collection<AsyncBarrierImpl>> reverseLookup = new HashMap<AsyncBarrierImpl, Collection<AsyncBarrierImpl>>();
31 static final HashMap<AsyncBarrierImpl, Debugger> debuggerMap = new HashMap<AsyncBarrierImpl, Debugger>();
32 static final HashMap<AsyncBarrierImpl, Boolean> restartMap = new HashMap<AsyncBarrierImpl, Boolean>();
34 static final int WAIT_TIME = 600;
36 public static final boolean BOOKKEEPING = false;
37 public static final boolean PRINT = false;
38 static final boolean RESTART_GUARD = false;
40 final private AsyncBarrierImpl caller;
42 public AsyncBarrierImpl(AsyncBarrierImpl caller) {
45 synchronized (debuggerMap) {
46 debuggerMap.put(this, new Debugger());
48 synchronized (reverseLookup) {
49 Collection<AsyncBarrierImpl> barriers = reverseLookup
51 if (barriers == null) {
52 barriers = new ArrayList<AsyncBarrierImpl>();
53 reverseLookup.put(caller, barriers);
61 public class Debugger {
62 public HashMap<Object, ArrayList<String>> infos = new HashMap<Object, ArrayList<String>>();
64 public synchronized void inc(Object id, String info) {
67 ArrayList<String> exist = infos.get(id);
69 exist = new ArrayList<String>();
72 // System.err.println("Appending " + id + " += " + info);
75 // String exist = infos.put(id, info);
76 // if(exist != null) System.err.println("replacing " + exist +
77 // " => " + info + " for " + id);
80 public synchronized void dec(Object id) {
83 ArrayList<String> exist = infos.get(id);
85 System.err.println("No data for " + id);
94 public synchronized String toString() {
95 StringBuilder b = new StringBuilder();
96 for (ArrayList<String> ss : infos.values()) {
98 b.append("info " + s + "\r\n");
103 public synchronized void toErr(int indent) {
104 char[] spaces = new char[indent];
105 Arrays.fill(spaces, ' ');
106 for (ArrayList<String> ss : infos.values()) {
107 for (String s : ss) {
108 if (!s.startsWith("#"))
110 StringBuilder b = new StringBuilder();
113 System.err.println(b.toString());
122 inc(new Object(), new Exception().getStackTrace()[1].toString());
128 public void inc(String debug) {
131 inc(new Object(), new Exception().getStackTrace()[1].toString());
137 public void inc(Object id, String info) {
141 // new Exception("inc " + get() + " " + this).printStackTrace();
145 Debugger debugger = debuggerMap.get(this);
146 if (debugger != null)
147 debugger.inc(id, info);
148 // StackTraceElement[] tr = new Exception().getStackTrace();
149 // if(tr.length == 4)
150 // debugger.inc(new String[] { debug, tr[2].toString(),
151 // tr[3].toString() });
152 // else if(tr.length == 5)
153 // debugger.inc(new String[] { debug, tr[2].toString(),
154 // tr[3].toString(), tr[4].toString() });
155 // else if(tr.length == 6)
156 // debugger.inc(new String[] { debug, tr[2].toString(),
157 // tr[3].toString(), tr[4].toString(), tr[5].toString() });
159 // debugger.inc(new String[] { debug, tr[2].toString(),
160 // tr[3].toString(), tr[4].toString(), tr[5].toString(),
161 // tr[6].toString() });
164 // new Exception().printStackTrace();
168 System.err.println("inc barrier[" + get() + "] " + this);
169 StackTraceElement[] elems = new Exception().getStackTrace();
170 for(int i=0;i<4;i++) System.err.println(elems[i]);
174 if (incrementAndGet() == 1) {
175 if (caller != null) {
177 caller.inc(this, "Child");
179 caller.inc(null, null);
188 System.err.println("dec barrier[" + get() + "] " + this);
189 StackTraceElement[] elems = new Exception().getStackTrace();
190 for(int i=0;i<3;i++) System.err.println(elems[i]);
193 int count = decrementAndGet();
201 Logger.defaultLogError(
202 "Database request processing error. The application code has performed illegal actions (probably called multiple times the execute or exception method of a single result request.",
210 public void dec(Object id) {
214 new Exception("dec" + get() + " " + this).printStackTrace();
218 Debugger debugger = debuggerMap.get(this);
219 if (debugger != null)
221 // StackTraceElement[] tr = new Exception().getStackTrace();
222 // if(tr.length == 3)
223 // debugger.dec(new String[] { debug, tr[2].toString() });
224 // else if(tr.length == 4)
225 // debugger.dec(new String[] { debug, tr[2].toString(),
226 // tr[3].toString() });
228 // debugger.dec(new String[] { debug, tr[2].toString(),
229 // tr[3].toString(), tr[4].toString() });
232 // System.err.println("barrier " + this);
233 // StackTraceElement[] elems = new Exception().getStackTrace();
234 // for(int i=0;i<3;i++) System.err.println(elems[i]);
235 // new Exception().printStackTrace();
237 int count = decrementAndGet();
243 restartMap.put(this, true);
246 // debuggerMap.remove(this);
248 // if(REVERSE_LOOKUP) {
249 // reverseLookup.remove(this);
253 Logger.defaultLogError(
254 "Database request processing error. The application code has performed illegal actions (probably called multiple times the execute or exception method of a single result request.",
256 // String message = ;
257 // System.out.println(message);
259 // JOptionPane.showMessageDialog(null, message);
260 // System.out.println(debugger);
269 private static void printReverse(AsyncBarrierImpl barrier, int indent) {
271 if (barrier.get() == 0)
273 for (int i = 0; i < indent; i++)
274 System.err.print(" ");
275 System.err.println("[" + barrier.get() + " requests]: " + barrier);
277 Debugger debugger = debuggerMap.get(barrier);
278 debugger.toErr(indent + 2);
281 Collection<AsyncBarrierImpl> children = reverseLookup.get(barrier);
282 if (children != null) {
283 for (AsyncBarrierImpl child : children)
284 printReverse(child, indent + 2);
289 public void waitBarrier(Object request, ReadGraphImpl impl) {
297 boolean executed = impl.processor.resume(impl);
298 if(executed) waitCount = 0;
301 if(waitCount > 100) Thread.yield();
302 if(waitCount > 1000) {
305 } catch (InterruptedException e) {
309 if(waitCount > WAIT_TIME*1000) {
311 System.err.println("AsyncBarrierImpl.waitBarrier("
313 + ") is taking long to execute, so far "
314 + (waitCount / 1000) + " s.");
318 synchronized (reverseLookup) {
319 printReverse(this, 0);
324 if(Development.DEVELOPMENT) {
326 impl.processor.threadLocks[0].lock();
327 System.err.println("-queues=" + impl.processor.queues[0].size());
328 impl.processor.threadLocks[0].unlock();
329 System.err.println("-own=" + impl.processor.ownTasks[0].size());
330 System.err.println("-ownSync=" + impl.processor.ownSyncTasks[0].size());
331 for(SessionTask task : impl.processor.ownSyncTasks[0]) {
332 System.err.println("--" + task);
337 throw new RuntimeDatabaseException("Request timed out.");
348 public void restart() {
351 // sema.drainPermits();
353 restartMap.remove(this);
355 debuggerMap.put(this, new Debugger());
358 public void assertReady() {
361 throw new AssertionError("Barrier was not finished (pending="
365 public void report() {
366 // System.out.println("Barrier log:");
367 // for(Map.Entry<String, Integer> entry : sources.entrySet()) {
368 // System.out.println(entry.getKey() + " " + entry.getValue());
370 // System.out.println("SyncIntProcedure log:");
371 // for(Map.Entry<String, Integer> entry :
372 // SyncIntProcedure.counters.entrySet()) {
373 // System.out.println(entry.getKey() + " " + entry.getValue());
378 public String toString() {
379 return "AsyncBarrierImpl@" + System.identityHashCode(this)
380 + " - counter = " + get() + " - caller = " + caller;