]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.common/src/org/simantics/db/common/Indexing.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.db.common / src / org / simantics / db / common / Indexing.java
1 /*******************************************************************************
2  * Copyright (c) 2012 Association for Decentralized Information Management in
3  * Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.common;
13
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.UUID;
19 import java.util.concurrent.atomic.AtomicBoolean;
20
21 import org.simantics.db.Resource;
22 import org.simantics.db.WriteOnlyGraph;
23 import org.simantics.db.common.utils.Logger;
24
25 /**
26  * A internal temporary store for database indexing-related low-level utilities
27  * and static data.
28  * 
29  * This will be moved to more a more logical location at some point.
30  * 
31  * @author Antti Villberg
32  * @author Tuukka Lehtonen
33  * @since 1.8
34  */
35 public class Indexing {
36
37     private static final boolean PROFILE                      = false;
38
39     private static Set<UUID>     indexPendings                = new HashSet<UUID>();
40
41     private static AtomicBoolean dependenciesIndexingDisabled = new AtomicBoolean();
42
43     private static int indexPendingCounter = 0;
44
45     private static Map<Resource, Map<Class<?>, Object>> caches = new HashMap<Resource, Map<Class<?>, Object>>(); 
46     
47     private static boolean useIndexing = true;
48     
49     @SuppressWarnings("unchecked")
50         public static <T> T getCache(Resource root, Class<T> clazz) {
51         Map<Class<?>,Object> cache = caches.get(root);
52         if(cache == null) return null;
53         return (T)cache.get(clazz);
54     }
55     
56     public static <T> T createCache(Resource root, T object) {
57         Map<Class<?>,Object> cache = caches.get(root);
58         if(cache == null) {
59                 cache = new HashMap<Class<?>,Object>();
60                 caches.put(root, cache);
61         }
62         cache.put(object.getClass(), object);
63         return object;
64     }
65     
66     public static void clearCaches(Resource root) {
67         caches.remove(root);
68     }
69     
70     public static UUID makeIndexPending() {
71         synchronized (indexPendings) {
72             UUID guid = UUID.randomUUID();
73             indexPendings.add(guid);
74             return guid;
75         }
76     }
77
78     public static void releaseIndexPending(UUID guid) {
79         synchronized (indexPendings) {
80             indexPendings.remove(guid);
81             if (indexPendings.isEmpty()) {
82                 indexPendings.notifyAll();
83                 indexPendingCounter++;
84             }
85         }
86     }
87
88     public static int getIndexPendingCounter() {
89         synchronized (indexPendings) {
90             return indexPendingCounter;
91         }
92     }
93     
94     public static boolean isIndexPending() {
95         synchronized (indexPendings) {
96             return !indexPendings.isEmpty();
97         }
98     }
99
100     private static long totalWaitTime = 0;
101
102     public static void waitIndexPending() {
103         long startTime = PROFILE ? System.nanoTime() : 0;
104         boolean waited = false;
105         int time = 1;
106         synchronized (indexPendings) {
107             while (isIndexPending()) {
108                 try {
109                     waited = true;
110                     indexPendings.wait(time++);
111                     if (time > 10) time = 10;
112                 } catch (InterruptedException e) {
113                     Logger.defaultLogError(e);
114                 }
115             }
116         }
117         if (PROFILE) {
118             if (waited) {
119                 long endTime = System.nanoTime();
120                 long waitTime = endTime - startTime;
121                 totalWaitTime += waitTime;
122                 System.out.println("Indexing wait time " + (waitTime*1e-6) + " ms (total " + (totalWaitTime*1e-6) + " ms)");
123             }
124         }
125     }
126
127     /**
128      * @param graph an active database write handle to prove one is in a write
129      *        transaction and wants to disable dependencies indexing for this
130      *        transaction only.
131      * @return previous value
132      */
133     public static boolean setDependenciesIndexingDisabled(WriteOnlyGraph graph, boolean disabled) {
134         if (graph == null)
135             throw new NullPointerException("null write graph");
136         // TODO: check that graph is valid once made possible
137         return dependenciesIndexingDisabled.getAndSet(disabled);
138     }
139
140     public static boolean resetDependenciesIndexingDisabled() {
141         return dependenciesIndexingDisabled.compareAndSet(true, false);
142     }
143
144     public static boolean isDependenciesIndexingDisabled() {
145         if (!useIndexing)
146                 return true;
147         return dependenciesIndexingDisabled.get();
148     }
149     
150     public static void setDefaultDependenciesIndexingEnabled(boolean b) {
151         useIndexing = b;
152     }
153
154 }