--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2012 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.db.common;\r
+\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Map;\r
+import java.util.Set;\r
+import java.util.UUID;\r
+import java.util.concurrent.atomic.AtomicBoolean;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteOnlyGraph;\r
+import org.simantics.db.common.utils.Logger;\r
+\r
+/**\r
+ * A internal temporary store for database indexing-related low-level utilities\r
+ * and static data.\r
+ * \r
+ * This will be moved to more a more logical location at some point.\r
+ * \r
+ * @author Antti Villberg\r
+ * @author Tuukka Lehtonen\r
+ * @since 1.8\r
+ */\r
+public class Indexing {\r
+\r
+ private static final boolean PROFILE = false;\r
+\r
+ private static Set<UUID> indexPendings = new HashSet<UUID>();\r
+\r
+ private static AtomicBoolean dependenciesIndexingDisabled = new AtomicBoolean();\r
+\r
+ private static int indexPendingCounter = 0;\r
+\r
+ private static Map<Resource, Map<Class<?>, Object>> caches = new HashMap<Resource, Map<Class<?>, Object>>(); \r
+ \r
+ private static boolean useIndexing = true;\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public static <T> T getCache(Resource root, Class<T> clazz) {\r
+ Map<Class<?>,Object> cache = caches.get(root);\r
+ if(cache == null) return null;\r
+ return (T)cache.get(clazz);\r
+ }\r
+ \r
+ public static <T> T createCache(Resource root, T object) {\r
+ Map<Class<?>,Object> cache = caches.get(root);\r
+ if(cache == null) {\r
+ cache = new HashMap<Class<?>,Object>();\r
+ caches.put(root, cache);\r
+ }\r
+ cache.put(object.getClass(), object);\r
+ return object;\r
+ }\r
+ \r
+ public static void clearCaches(Resource root) {\r
+ caches.remove(root);\r
+ }\r
+ \r
+ public static UUID makeIndexPending() {\r
+ synchronized (indexPendings) {\r
+ UUID guid = UUID.randomUUID();\r
+ indexPendings.add(guid);\r
+ return guid;\r
+ }\r
+ }\r
+\r
+ public static void releaseIndexPending(UUID guid) {\r
+ synchronized (indexPendings) {\r
+ indexPendings.remove(guid);\r
+ if (indexPendings.isEmpty()) {\r
+ indexPendings.notifyAll();\r
+ indexPendingCounter++;\r
+ }\r
+ }\r
+ }\r
+\r
+ public static int getIndexPendingCounter() {\r
+ synchronized (indexPendings) {\r
+ return indexPendingCounter;\r
+ }\r
+ }\r
+ \r
+ public static boolean isIndexPending() {\r
+ synchronized (indexPendings) {\r
+ return !indexPendings.isEmpty();\r
+ }\r
+ }\r
+\r
+ private static long totalWaitTime = 0;\r
+\r
+ public static void waitIndexPending() {\r
+ long startTime = PROFILE ? System.nanoTime() : 0;\r
+ boolean waited = false;\r
+ int time = 1;\r
+ synchronized (indexPendings) {\r
+ while (isIndexPending()) {\r
+ try {\r
+ waited = true;\r
+ indexPendings.wait(time++);\r
+ if (time > 10) time = 10;\r
+ } catch (InterruptedException e) {\r
+ Logger.defaultLogError(e);\r
+ }\r
+ }\r
+ }\r
+ if (PROFILE) {\r
+ if (waited) {\r
+ long endTime = System.nanoTime();\r
+ long waitTime = endTime - startTime;\r
+ totalWaitTime += waitTime;\r
+ System.out.println("Indexing wait time " + (waitTime*1e-6) + " ms (total " + (totalWaitTime*1e-6) + " ms)");\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param graph an active database write handle to prove one is in a write\r
+ * transaction and wants to disable dependencies indexing for this\r
+ * transaction only.\r
+ * @return previous value\r
+ */\r
+ public static boolean setDependenciesIndexingDisabled(WriteOnlyGraph graph, boolean disabled) {\r
+ if (graph == null)\r
+ throw new NullPointerException("null write graph");\r
+ // TODO: check that graph is valid once made possible\r
+ return dependenciesIndexingDisabled.getAndSet(disabled);\r
+ }\r
+\r
+ public static boolean resetDependenciesIndexingDisabled() {\r
+ return dependenciesIndexingDisabled.compareAndSet(true, false);\r
+ }\r
+\r
+ public static boolean isDependenciesIndexingDisabled() {\r
+ if (!useIndexing)\r
+ return true;\r
+ return dependenciesIndexingDisabled.get();\r
+ }\r
+ \r
+ public static void setDefaultDependenciesIndexingEnabled(boolean b) {\r
+ useIndexing = b;\r
+ }\r
+\r
+}\r