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.CountDownLatch;
19 import java.util.concurrent.Semaphore;
20 import java.util.concurrent.atomic.AtomicInteger;
22 import org.simantics.db.common.utils.Logger;
23 import org.simantics.db.exception.RuntimeDatabaseException;
24 import org.simantics.db.impl.query.QueryProcessor.AsyncBarrier;
25 import org.simantics.db.impl.query.QueryProcessor.SessionTask;
26 import org.simantics.utils.Development;
28 final public class AsyncBarrierImpl extends AtomicInteger implements AsyncBarrier {
30 private static final long serialVersionUID = 4724463372850048672L;
32 static final HashMap<AsyncBarrierImpl, Collection<AsyncBarrierImpl>> reverseLookup = new HashMap<AsyncBarrierImpl, Collection<AsyncBarrierImpl>>();
33 static final HashMap<AsyncBarrierImpl, Debugger> debuggerMap = new HashMap<AsyncBarrierImpl, Debugger>();
34 static final HashMap<AsyncBarrierImpl, Boolean> restartMap = new HashMap<AsyncBarrierImpl, Boolean>();
36 static final int WAIT_TIME = 600;
38 public static final boolean BOOKKEEPING = false;
39 public static final boolean PRINT = false;
40 static final boolean RESTART_GUARD = false;
42 final private AsyncBarrierImpl caller;
44 final private Semaphore sema = new Semaphore(0);
46 public AsyncBarrierImpl(AsyncBarrierImpl caller) {
49 synchronized (debuggerMap) {
50 debuggerMap.put(this, new Debugger());
52 synchronized (reverseLookup) {
53 Collection<AsyncBarrierImpl> barriers = reverseLookup
55 if (barriers == null) {
56 barriers = new ArrayList<AsyncBarrierImpl>();
57 reverseLookup.put(caller, barriers);
65 public class Debugger {
66 public HashMap<Object, ArrayList<String>> infos = new HashMap<Object, ArrayList<String>>();
68 public synchronized void inc(Object id, String info) {
71 ArrayList<String> exist = infos.get(id);
73 exist = new ArrayList<String>();
76 // System.err.println("Appending " + id + " += " + info);
79 // String exist = infos.put(id, info);
80 // if(exist != null) System.err.println("replacing " + exist +
81 // " => " + info + " for " + id);
84 public synchronized void dec(Object id) {
87 ArrayList<String> exist = infos.get(id);
89 System.err.println("No data for " + id);
98 public synchronized String toString() {
99 StringBuilder b = new StringBuilder();
100 for (ArrayList<String> ss : infos.values()) {
102 b.append("info " + s + "\r\n");
107 public synchronized void toErr(int indent) {
108 char[] spaces = new char[indent];
109 Arrays.fill(spaces, ' ');
110 for (ArrayList<String> ss : infos.values()) {
111 for (String s : ss) {
112 if (!s.startsWith("#"))
114 StringBuilder b = new StringBuilder();
117 System.err.println(b.toString());
126 inc(new Object(), new Exception().getStackTrace()[1].toString());
132 public void inc(String debug) {
135 inc(new Object(), new Exception().getStackTrace()[1].toString());
141 public void inc(Object id, String info) {
145 // new Exception("inc " + get() + " " + this).printStackTrace();
149 Debugger debugger = debuggerMap.get(this);
150 if (debugger != null)
151 debugger.inc(id, info);
152 // StackTraceElement[] tr = new Exception().getStackTrace();
153 // if(tr.length == 4)
154 // debugger.inc(new String[] { debug, tr[2].toString(),
155 // tr[3].toString() });
156 // else if(tr.length == 5)
157 // debugger.inc(new String[] { debug, tr[2].toString(),
158 // tr[3].toString(), tr[4].toString() });
159 // else if(tr.length == 6)
160 // debugger.inc(new String[] { debug, tr[2].toString(),
161 // tr[3].toString(), tr[4].toString(), tr[5].toString() });
163 // debugger.inc(new String[] { debug, tr[2].toString(),
164 // tr[3].toString(), tr[4].toString(), tr[5].toString(),
165 // tr[6].toString() });
168 // new Exception().printStackTrace();
172 System.err.println("inc barrier[" + get() + "] " + this);
173 StackTraceElement[] elems = new Exception().getStackTrace();
174 for(int i=0;i<4;i++) System.err.println(elems[i]);
178 if (incrementAndGet() == 1) {
179 if (caller != null) {
181 caller.inc(this, "Child");
183 caller.inc(null, null);
192 System.err.println("dec barrier[" + get() + "] " + this);
193 StackTraceElement[] elems = new Exception().getStackTrace();
194 for(int i=0;i<3;i++) System.err.println(elems[i]);
197 int count = decrementAndGet();
205 Logger.defaultLogError(
206 "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.",
214 public void dec(Object id) {
218 new Exception("dec" + get() + " " + this).printStackTrace();
222 Debugger debugger = debuggerMap.get(this);
223 if (debugger != null)
225 // StackTraceElement[] tr = new Exception().getStackTrace();
226 // if(tr.length == 3)
227 // debugger.dec(new String[] { debug, tr[2].toString() });
228 // else if(tr.length == 4)
229 // debugger.dec(new String[] { debug, tr[2].toString(),
230 // tr[3].toString() });
232 // debugger.dec(new String[] { debug, tr[2].toString(),
233 // tr[3].toString(), tr[4].toString() });
236 // System.err.println("barrier " + this);
237 // StackTraceElement[] elems = new Exception().getStackTrace();
238 // for(int i=0;i<3;i++) System.err.println(elems[i]);
239 // new Exception().printStackTrace();
241 int count = decrementAndGet();
247 restartMap.put(this, true);
250 // debuggerMap.remove(this);
252 // if(REVERSE_LOOKUP) {
253 // reverseLookup.remove(this);
257 Logger.defaultLogError(
258 "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.",
260 // String message = ;
261 // System.out.println(message);
263 // JOptionPane.showMessageDialog(null, message);
264 // System.out.println(debugger);
273 private static void printReverse(AsyncBarrierImpl barrier, int indent) {
275 if (barrier.get() == 0)
277 for (int i = 0; i < indent; i++)
278 System.err.print(" ");
279 System.err.println("[" + barrier.get() + " requests]: " + barrier);
281 Debugger debugger = debuggerMap.get(barrier);
282 debugger.toErr(indent + 2);
285 Collection<AsyncBarrierImpl> children = reverseLookup.get(barrier);
286 if (children != null) {
287 for (AsyncBarrierImpl child : children)
288 printReverse(child, indent + 2);
293 public void waitBarrier(Object request, ReadGraphImpl impl) {
301 boolean executed = impl.performPending();
302 if(executed) waitCount = 0;
305 if(waitCount > 100) Thread.yield();
306 if(waitCount > 1000) {
309 } catch (InterruptedException e) {
313 if(waitCount > WAIT_TIME*1000) {
315 System.err.println("AsyncBarrierImpl.waitBarrier("
317 + ") is taking long to execute, so far "
318 + (waitCount / 1000) + " s.");
322 synchronized (reverseLookup) {
323 printReverse(this, 0);
328 if(Development.DEVELOPMENT) {
330 // impl.processor.threadLocks[0].lock();
331 // System.err.println("-queues=" + impl.processor.queues[0].size());
332 // impl.processor.threadLocks[0].unlock();
333 // System.err.println("-own=" + impl.processor.ownTasks[0].size());
334 // System.err.println("-ownSync=" + impl.processor.ownSyncTasks[0].size());
335 // for(SessionTask task : impl.processor.ownSyncTasks[0]) {
336 // System.err.println("--" + task);
341 throw new RuntimeDatabaseException("Request timed out.");
352 public void restart() {
355 // sema.drainPermits();
357 restartMap.remove(this);
359 debuggerMap.put(this, new Debugger());
362 public void assertReady() {
365 throw new AssertionError("Barrier was not finished (pending="
369 public void report() {
370 // System.out.println("Barrier log:");
371 // for(Map.Entry<String, Integer> entry : sources.entrySet()) {
372 // System.out.println(entry.getKey() + " " + entry.getValue());
374 // System.out.println("SyncIntProcedure log:");
375 // for(Map.Entry<String, Integer> entry :
376 // SyncIntProcedure.counters.entrySet()) {
377 // System.out.println(entry.getKey() + " " + entry.getValue());
382 public String toString() {
383 return "AsyncBarrierImpl@" + System.identityHashCode(this)
384 + " - counter = " + get() + " - caller = " + caller;