]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DebugSupportImpl.java
Ignore NoSingleResultException in DependenciesRelation
[simantics/platform.git] / bundles / org.simantics.db.procore / src / fi / vtt / simantics / procore / internal / DebugSupportImpl.java
index 7c9f0953c7bd04be3bf253c942168046fc55de5d..f788a12448bfd9b26254bcf489ebbec42c437f31 100644 (file)
-package fi.vtt.simantics.procore.internal;\r
-\r
-import java.io.File;\r
-import java.io.IOException;\r
-import java.lang.management.ManagementFactory;\r
-import java.lang.reflect.Method;\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-import java.util.TreeSet;\r
-import java.util.UUID;\r
-\r
-import org.eclipse.core.runtime.Platform;\r
-import org.osgi.framework.Bundle;\r
-import org.simantics.databoard.binding.mutable.Variant;\r
-import org.simantics.databoard.parser.repository.DataValueRepository;\r
-import org.simantics.db.DirectStatements;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.Statement;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.request.WriteRequest;\r
-import org.simantics.db.common.request.WriteResultRequest;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.common.utils.NameUtils;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.exception.ServiceException;\r
-import org.simantics.db.exception.ValidationException;\r
-import org.simantics.db.impl.Activator;\r
-import org.simantics.db.impl.ClusterI;\r
-import org.simantics.db.impl.ResourceImpl;\r
-import org.simantics.db.impl.graph.ReadGraphImpl;\r
-import org.simantics.db.impl.graph.WriteLogger;\r
-import org.simantics.db.impl.query.QueryProcessor;\r
-import org.simantics.db.impl.query.QuerySupport;\r
-import org.simantics.db.procore.cluster.ClusterBig;\r
-import org.simantics.db.procore.cluster.ClusterImpl;\r
-import org.simantics.db.procore.cluster.ClusterSmall;\r
-import org.simantics.db.service.DebugSupport;\r
-import org.simantics.db.service.QueryControl;\r
-import org.simantics.db.service.XSupport;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.scl.runtime.function.Function2;\r
-import org.simantics.scl.runtime.function.Function3;\r
-import org.simantics.scl.runtime.function.FunctionImpl2;\r
-import org.simantics.scl.runtime.function.FunctionImpl3;\r
-import org.simantics.utils.Development;\r
-import org.simantics.utils.FileUtils;\r
-\r
-import gnu.trove.map.hash.TIntIntHashMap;\r
-import gnu.trove.procedure.TIntIntProcedure;\r
-import gnu.trove.procedure.TIntShortProcedure;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public class DebugSupportImpl implements DebugSupport {\r
-\r
-       final private Map<String, Function2<WriteGraph, String, Object>> getCommands = new HashMap<String, Function2<WriteGraph, String, Object>>();\r
-       final private Map<String, Function3<WriteGraph, File, String, String>> listCommands = new HashMap<String, Function3<WriteGraph, File, String, String>>();\r
-       final private Map<String, Function2<WriteGraph, String, String>> execCommands = new HashMap<String, Function2<WriteGraph, String, String>>();\r
-       final private Map<String, Function2<WriteGraph, String, String>> printCommands = new HashMap<String, Function2<WriteGraph, String, String>>();\r
-\r
-       private static SessionImplSocket getSession(WriteGraph graph) {\r
-               return (SessionImplSocket)graph.getSession();\r
-       }\r
-\r
-       DebugSupportImpl() {\r
-\r
-               getCommands.put("listeners", new FunctionImpl2<WriteGraph, String, Object>() {\r
-\r
-                       @Override\r
-                       public Object apply(WriteGraph graph, String args) {\r
-                               try {\r
-                                       return getSession(graph).queryProvider2.getListenerReport();\r
-                               } catch (IOException e) {\r
-                                       Logger.defaultLogError(e);\r
-                                       return e.getMessage();\r
-                               }\r
-                       }\r
-\r
-               });\r
-\r
-               listCommands.put("counters", new FunctionImpl3<WriteGraph, File, String, String>() {\r
-\r
-                       @Override\r
-                       public String apply(WriteGraph graph, File file, String args) {\r
-                               try {\r
-                                       return ReadGraphImpl.listCounters(file);\r
-                               } catch (IOException e) {\r
-                                       Logger.defaultLogError(e);\r
-                                       return e.getMessage();\r
-                               }\r
-                       }\r
-\r
-               });\r
-\r
-               listCommands.put("queries", new FunctionImpl3<WriteGraph, File, String, String>() {\r
-\r
-                       @Override\r
-                       public String apply(WriteGraph graph, File file, String args) {\r
-                               try {\r
-                                       return getSession(graph).queryProvider2.reportQueries(file);\r
-                               } catch (IOException e) {\r
-                                       Logger.defaultLogError(e);\r
-                                       return e.getMessage();\r
-                               }\r
-                       }\r
-\r
-               });\r
-\r
-               listCommands.put("queryActivity", new FunctionImpl3<WriteGraph, File, String, String>() {\r
-\r
-                       @Override\r
-                       public String apply(WriteGraph graph, File file, String args) {\r
-                               try {\r
-                                       return getSession(graph).queryProvider2.reportQueryActivity(file);\r
-                               } catch (IOException e) {\r
-                                       Logger.defaultLogError(e);\r
-                                       return e.getMessage();\r
-                               }\r
-                       }\r
-\r
-               });\r
-\r
-               listCommands.put("listeners", new FunctionImpl3<WriteGraph, File, String, String>() {\r
-\r
-                       @Override\r
-                       public String apply(WriteGraph graph, File file, String args) {\r
-                               try {\r
-                                       return getSession(graph).queryProvider2.reportListeners(file);\r
-                               } catch (IOException e) {\r
-                                       Logger.defaultLogError(e);\r
-                                       return e.getMessage();\r
-                               }\r
-                       }\r
-\r
-               });\r
-\r
-               listCommands.put("clusters", new FunctionImpl3<WriteGraph, File, String, String>() {\r
-\r
-                       @Override\r
-                       public String apply(WriteGraph graph, File file, String args) {\r
-                               return reportClusters(getSession(graph), file);\r
-                       }\r
-\r
-               });\r
-\r
-        listCommands.put("cluster", new FunctionImpl3<WriteGraph, File, String, String>() {\r
-\r
-            @Override\r
-            public String apply(WriteGraph graph, File file, String args) {\r
-                return reportCluster(graph, file, args);\r
-            }\r
-\r
-        });\r
-\r
-               listCommands.put("virtuals", new FunctionImpl3<WriteGraph, File, String, String>() {\r
-\r
-                       @Override\r
-                       public String apply(WriteGraph graph, File file, String args) {\r
-                               return reportVirtuals(getSession(graph), file);\r
-                       }\r
-\r
-               });\r
-\r
-               listCommands.put("heap", new FunctionImpl3<WriteGraph, File, String, String>() {\r
-\r
-                       @Override\r
-                       public String apply(WriteGraph graph, File file, String args) {\r
-\r
-                               try {\r
-\r
-                                       file.delete();\r
-\r
-                                       Object bean = getBean();\r
-                                       if (bean == null)\r
-                                               return "Could not retrieve bean.";\r
-\r
-                                       Method m = bean.getClass().getMethod("dumpHeap", String.class, boolean.class);\r
-                                       if (args.length() > 0) {\r
-                                               m.invoke(bean, file.getParent() + "/" + args, true);\r
-                                       } else {\r
-                                               m.invoke(bean, file.getAbsolutePath(), true);\r
-                                       }\r
-\r
-                               } catch (Throwable t) {\r
-                                       Logger.defaultLogError(t);\r
-                                       return "Unexpected exception " + t;\r
-                               }\r
-\r
-                               return "Wrote " + file.getAbsolutePath();\r
-\r
-                   }\r
-\r
-                   private Object getBean() {\r
-                       Class<?> beanClass = getBeanClass();\r
-                       if (beanClass == null)\r
-                           return null;\r
-                       try {\r
-                           Object bean = ManagementFactory.newPlatformMXBeanProxy(\r
-                                   ManagementFactory.getPlatformMBeanServer(),\r
-                                   "com.sun.management:type=HotSpotDiagnostic",\r
-                                   beanClass);\r
-                           return bean;\r
-                       } catch (IOException e) {\r
-                           return null;\r
-                       }\r
-                   }\r
-\r
-                   private Class<?> getBeanClass() {\r
-                       try {\r
-                           Class<?> clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean");\r
-                           return clazz;\r
-                       } catch (ClassNotFoundException e) {\r
-                           return null;\r
-                       }\r
-                   }\r
-\r
-               });\r
-\r
-               execCommands.put("WriteLogger.read", new FunctionImpl2<WriteGraph, String, String>() {\r
-\r
-                       @Override\r
-                       public String apply(WriteGraph graph, String args) {\r
-                               graph.getSession().async(new WriteRequest() {\r
-\r
-                                       @Override\r
-                                       public void perform(WriteGraph graph) throws DatabaseException {\r
-                                               try {\r
-                                                       WriteLogger.read(graph);\r
-                                               } catch (Exception e) {\r
-                                                       e.printStackTrace();\r
-                                               }\r
-                                       }\r
-\r
-                               });\r
-                               return "Started to read the write log.";\r
-                       }\r
-\r
-               });\r
-\r
-               execCommands.put("ReadGraph.resetCounters", new FunctionImpl2<WriteGraph, String, String>() {\r
-\r
-                       @Override\r
-                       public String apply(WriteGraph graph, String args) {\r
-                               graph.getSession().async(new WriteRequest() {\r
-\r
-                                       @Override\r
-                                       public void perform(WriteGraph graph) throws DatabaseException {\r
-                                               try {\r
-                                                       ReadGraphImpl.resetCounters();\r
-                                               } catch (Exception e) {\r
-                                                       e.printStackTrace();\r
-                                               }\r
-                                       }\r
-\r
-                               });\r
-                               return "Started to read the write log.";\r
-                       }\r
-\r
-               });\r
-\r
-               execCommands.put("QueryControl.flush", new FunctionImpl2<WriteGraph, String, String>() {\r
-\r
-                       @Override\r
-                       public String apply(WriteGraph graph, String args) {\r
-                               QueryControl qc = graph.getService(QueryControl.class);\r
-                               qc.flush(graph);\r
-                               return "Flushed queries.";\r
-                       }\r
-\r
-               });\r
-\r
-        execCommands.put("DebugSupport.validateClusters", new FunctionImpl2<WriteGraph, String, String>() {\r
-\r
-            @Override\r
-            public String apply(WriteGraph graph, String args) {\r
-                return validateClusters(graph);\r
-            }\r
-\r
-        });\r
-\r
-        execCommands.put("DebugSupport.writeForMs", new FunctionImpl2<WriteGraph, String, String>() {\r
-\r
-            @Override\r
-            public String apply(WriteGraph graph, String args) {\r
-                Integer amount = Integer.parseInt(args);\r
-                return writeForMs(graph, amount);\r
-            }\r
-\r
-        });\r
-\r
-               printCommands.put("nextId", new FunctionImpl2<WriteGraph, String, String>() {\r
-\r
-                       @Override\r
-                       public String apply(WriteGraph graph, String args) {\r
-                               try {\r
-                                       SessionImplSocket session = getSession(graph);\r
-                                       ClusterImpl cluster = session.clusterTable.getNewResourceCluster(session.clusterTranslator, session.graphSession, false);\r
-                                       long cid = cluster.getClusterId();\r
-                                       int rid = cluster.getNumberOfResources(session.clusterTranslator);\r
-                                       return cid + "#" + rid;\r
-                               } catch (Throwable t) {\r
-                                       return UUID.randomUUID().toString();\r
-                               }\r
-                       }\r
-\r
-               });\r
-\r
-               printCommands.put("usedMemory", new FunctionImpl2<WriteGraph, String, String>() {\r
-\r
-                       @Override\r
-                       public String apply(WriteGraph graph, String args) {\r
-                               try {\r
-                                       Runtime runtime = Runtime.getRuntime();\r
-                                       return "" + (runtime.totalMemory() - runtime.freeMemory());\r
-                               } catch (Throwable t) {\r
-                                       return UUID.randomUUID().toString();\r
-                               }\r
-                       }\r
-\r
-               });\r
-\r
-       }\r
-\r
-       private String reportClusters(SessionImplSocket session, File file) {\r
-\r
-               try {\r
-                       StringBuilder b = new StringBuilder();\r
-                       long totalApproxSize = 0;\r
-                       int loaded = 0;\r
-                       for(ClusterI cluster : session.clusterTable.getClusters()) {\r
-                               b.append("[" + cluster.getClusterKey() + "]: ");\r
-                               if(cluster instanceof ClusterSmall) b.append("ClusterSmall[" + cluster.getClusterId() + "]");\r
-                               if(cluster instanceof ClusterBig) b.append("ClusterBig[" + cluster.getClusterId() + "]");\r
-                               if(cluster instanceof ClusterWriteOnly) b.append("ClusterWriteOnly[" + cluster.getClusterId() + "]");\r
-                               if(cluster.isLoaded()) {\r
-                                       long approx = cluster.getUsedSpace();\r
-                                       b.append(" approx size = " + approx + " bytes.\n");\r
-                                       totalApproxSize += approx;\r
-                                       loaded++;\r
-                               } else {\r
-                                       b.append(" is not loaded.\n");\r
-                               }\r
-                       }\r
-                       b.append("#Total approx size is " + totalApproxSize + " bytes.\n");\r
-                       b.append("#Amount of loaded clusters is " + loaded + ".\n");\r
-                       FileUtils.writeFile(file, b.toString().getBytes());\r
-               } catch (IOException e) {\r
-                       e.printStackTrace();\r
-               } catch (DatabaseException e) {\r
-                       e.printStackTrace();\r
-               }\r
-\r
-               return "OK";\r
-\r
-       }\r
-\r
-    private String reportCluster(final WriteGraph graph, File file, String args) {\r
-\r
-        try {\r
-\r
-            final StringBuilder b = new StringBuilder();\r
-            final SessionImplSocket session = (SessionImplSocket)graph.getSession();\r
-            long clusterId = Long.parseLong(args);\r
-            b.append("cluster id: " + clusterId);\r
-            b.append("\n");\r
-            b.append("internal resources: ");\r
-            b.append("\n");\r
-            ClusterI cluster = session.clusterTable.getClusterByClusterId(clusterId);\r
-            for(int i=1;i<=cluster.getNumberOfResources(session.clusterTranslator);i++) {\r
-                Resource r = session.getResource(i, clusterId);\r
-                String def = NameUtils.getSafeName(graph, r);\r
-                b.append( i+": " + def);\r
-                b.append("\n");\r
-            }\r
-            if(cluster instanceof ClusterSmall) {\r
-                ClusterSmall clusterSmall = (ClusterSmall)cluster;\r
-                b.append("foreign resources: ");\r
-                b.append("\n");\r
-                final TIntIntHashMap clusterHistogram = new TIntIntHashMap();\r
-                clusterSmall.foreignTable.getResourceHashMap().forEachEntry(new TIntShortProcedure() {\r
-\r
-                    @Override\r
-                    public boolean execute(int index, short pos) {\r
-                        try {\r
-                            Resource r = session.getResource(index);\r
-                            String def = NameUtils.getSafeName(graph, r, true);\r
-                            int cluster = index >>> 12;\r
-                            int key = index & 0xfff;\r
-                            int exist = clusterHistogram.get(cluster);\r
-                            clusterHistogram.put(cluster, exist+1);\r
-                            b.append( cluster + "$" + key +": " + def);\r
-                            b.append("\n");\r
-                        } catch (ValidationException e) {\r
-                            e.printStackTrace();\r
-                        } catch (ServiceException e) {\r
-                            e.printStackTrace();\r
-                        }\r
-                        return true;\r
-                    }\r
-                });\r
-                b.append("foreign histogram: ");\r
-                b.append("\n");\r
-                clusterHistogram.forEachEntry(new TIntIntProcedure() {\r
-\r
-                    @Override\r
-                    public boolean execute(int cluster, int count) {\r
-                        b.append( cluster +": " + count);\r
-                        b.append("\n");\r
-                        return true;\r
-                    }\r
-                });\r
-            }\r
-\r
-            FileUtils.writeFile(file, b.toString().getBytes());\r
-        } catch (IOException e) {\r
-            e.printStackTrace();\r
-        } catch (DatabaseException e) {\r
-            e.printStackTrace();\r
-        }\r
-\r
-        return "OK";\r
-\r
-    }\r
-\r
-       private String reportVirtuals(SessionImplSocket session, File file) {\r
-\r
-               session.virtualGraphServerSupport.report(file);\r
-\r
-               return "OK";\r
-\r
-       }\r
-\r
-       public Object query(Session session, final String command) {\r
-               try {\r
-                       return session.sync(new WriteResultRequest<Object>() {\r
-\r
-                               @Override\r
-                               public Object perform(WriteGraph graph) throws DatabaseException {\r
-                                       return query(graph, command);\r
-                               }\r
-\r
-                       });\r
-               } catch (DatabaseException e) {\r
-                       Logger.defaultLogError(e);\r
-                       return null;\r
-               }\r
-       }\r
-\r
-       @Override\r
-       public Object query(WriteGraph graph, String command) {\r
-\r
-               Bundle bundle = Platform.getBundle(Activator.BUNDLE_ID);\r
-               File base = Utils.getBaseFile(bundle);\r
-\r
-               command = command.trim();\r
-\r
-               try {\r
-\r
-                       if("help".equals(command)) {\r
-\r
-                               return\r
-                                               "Welcome to the Simantics session debugger.<br><br>" +\r
-                                               "This shell allows you to make following queries into the running Simantics database session:<br>" +\r
-                                               "<ul><li>Get commands, which return debug objects. Type 'help get' to obtain more information.</li>" +\r
-                                               "<li>List commands, which create debug listings into files. Type 'help list' to obtain more information.</li>" +\r
-                                               "<li>Print commands, which output information about session state. Type 'help print' to obtain more information.</li>" +\r
-                                               "<li>Set commands, which modify session state variables. Type 'help set' to obtain more information.</li>" +\r
-                                               "<li>Exec commands, which perform certain actions. Type 'help exec' to obtain more information.</li></ul>"\r
-                                               ;\r
-\r
-                       } else if ("help get".equals(command)) {\r
-\r
-                               StringBuilder b = new StringBuilder();\r
-                               b.append("The following get commands are available.<br><ul>");\r
-                               for(String key : getCommands.keySet())\r
-                                       b.append("<li>" + key + "</li>");\r
-\r
-                               b.append("</ul>");\r
-\r
-                               return b.toString();\r
-\r
-                       } else if ("help list".equals(command)) {\r
-\r
-                               StringBuilder b = new StringBuilder();\r
-                               b.append("The following list commands are available.<br><ul>");\r
-                               for(String key : listCommands.keySet())\r
-                                       b.append("<li>" + key + "</li>");\r
-\r
-                               b.append("</ul>");\r
-\r
-                               return b.toString();\r
-\r
-                       } else if ("help exec".equals(command)) {\r
-\r
-                               StringBuilder b = new StringBuilder();\r
-                               b.append("The following exec commands are available.<br><ul>");\r
-                               for(String key : execCommands.keySet())\r
-                                       b.append("<li>" + key + "</li>");\r
-\r
-                               b.append("</ul>");\r
-\r
-                               return b.toString();\r
-\r
-                       } else if ("help print".equals(command)) {\r
-\r
-                               StringBuilder b = new StringBuilder();\r
-                               b.append("The following print commands are available.<br><ul>");\r
-                               for(String key : printCommands.keySet())\r
-                                       b.append("<li>" + key + "</li>");\r
-\r
-                               b.append("</ul>");\r
-\r
-                               return b.toString();\r
-\r
-                       } else if ("help set".equals(command)) {\r
-\r
-                               StringBuilder b = new StringBuilder();\r
-                               b.append("The following set commands are available.<br><ul>");\r
-\r
-                               for(Map.Entry<String, Variant> e : Development.getProperties().entrySet()) {\r
-                                       b.append("<li>" + e.getKey() + " - " + e.getValue().getBinding().type() + "</li>");\r
-                               }\r
-\r
-                               b.append("</ul>");\r
-\r
-                               return b.toString();\r
-\r
-                       } else if(command.startsWith("get")) {\r
-\r
-                               String remainder = command.substring(3).trim();\r
-\r
-                               for(Map.Entry<String, Function2<WriteGraph, String, Object>> e : getCommands.entrySet()) {\r
-                                       String key = e.getKey();\r
-                                       if(remainder.startsWith(key)) {\r
-                                               String args = remainder.substring(key.length()).trim();\r
-                                               return e.getValue().apply(graph, args);\r
-                                       }\r
-                               }\r
-\r
-                       } else if(command.startsWith("list")) {\r
-\r
-                               String remainder = command.substring(4).trim();\r
-\r
-                               for(Map.Entry<String, Function3<WriteGraph, File, String, String>> e : listCommands.entrySet()) {\r
-                                       String key = e.getKey();\r
-                                       if(remainder.startsWith(key)) {\r
-                                               String args = remainder.substring(key.length()).trim();\r
-                                               File file = new File(base, key + ".list");\r
-                                               base.mkdirs();\r
-                                               e.getValue().apply(graph, file, args);\r
-                                               return "Wrote " + file.getAbsolutePath();\r
-                                       }\r
-                               }\r
-\r
-                       } else if(command.startsWith("set")) {\r
-\r
-                               String remainder = command.substring(3).trim();\r
-                               String[] keyAndValue = remainder.split("=");\r
-                               if(keyAndValue.length == 2) {\r
-\r
-                                       Variant exist = Development.getProperties().get(keyAndValue[0]);\r
-                                       if(exist != null) {\r
-                                               Development.setProperty(keyAndValue[0], exist.getBinding().parseValue(keyAndValue[1], new DataValueRepository()), exist.getBinding());\r
-                                               return "Property " + keyAndValue[0] + " was set to '" + keyAndValue[1] + "'";\r
-                                       } else {\r
-                                               return query(graph, "help set");\r
-                                       }\r
-                               } else {\r
-                                       return query(graph, "help set");\r
-                               }\r
-\r
-                       } else if(command.startsWith("print")) {\r
-\r
-                               String remainder = command.substring(5).trim();\r
-\r
-                               for(Map.Entry<String, Function2<WriteGraph, String, String>> e : printCommands.entrySet()) {\r
-                                       String key = e.getKey();\r
-                                       if(remainder.startsWith(key)) {\r
-                                               String args = remainder.substring(key.length()).trim();\r
-                                               return e.getValue().apply(graph, args);\r
-                                       }\r
-                               }\r
-\r
-                       } else if(command.startsWith("exec")) {\r
-\r
-                               String remainder = command.substring(4).trim();\r
-\r
-                               for(Map.Entry<String, Function2<WriteGraph, String, String>> e : execCommands.entrySet()) {\r
-                                       String key = e.getKey();\r
-                                       if(remainder.startsWith(key)) {\r
-                                               String args = remainder.substring(key.length()).trim();\r
-                                               return e.getValue().apply(graph, args);\r
-                                       }\r
-                               }\r
-\r
-                       }\r
-\r
-                       return "Unknown command '" + command + "'";\r
-\r
-               } catch (Throwable t) {\r
-\r
-                       t.printStackTrace();\r
-\r
-                       return t.getMessage();\r
-\r
-               }\r
-\r
-       }\r
-       private void writeResouce(WriteGraph graph) throws DatabaseException {\r
-        Layer0 l0 = Layer0.getInstance(graph);\r
-        Resource r = graph.newResource();\r
-        graph.claim(r, l0.InstanceOf, l0.Entity);\r
-        XSupport xs = (XSupport)graph.getService(XSupport.class);\r
-        xs.flushCluster(r);\r
-       }\r
-       private void wait(int amount) {\r
-        long start = System.nanoTime();\r
-        long limit = amount * 1000000L;\r
-        while ((System.nanoTime() - start) < limit) {\r
-            try {\r
-                Thread.sleep(100);\r
-            } catch (InterruptedException e) {\r
-                e.printStackTrace();\r
-            }\r
-        }\r
-       }\r
-       String writeForMs(WriteGraph graph, int amount) {\r
-        try {\r
-            writeResouce(graph);\r
-            wait(amount);\r
-            writeResouce(graph);\r
-        } catch (DatabaseException e) {\r
-            e.printStackTrace();\r
-        }\r
-\r
-               return "Slept for " + amount + " ms in write transaction.";\r
-       }\r
-\r
-       String validateClusters(WriteGraph graph) {\r
-\r
-           ReadGraphImpl impl = (ReadGraphImpl)graph;\r
-           QueryProcessor processor = impl.processor;\r
-\r
-           QuerySupport qs = graph.getService(QuerySupport.class);\r
-\r
-           TIntHashSet done = new TIntHashSet();\r
-           TreeSet<Integer> fringe = new TreeSet<Integer>();\r
-\r
-           ResourceImpl root = (ResourceImpl)graph.getRootLibrary();\r
-\r
-           done.add(root.id);\r
-           fringe.add(root.id);\r
-\r
-           while(!fringe.isEmpty()) {\r
-               int r = fringe.first();\r
-               fringe.remove(r);\r
-               DirectStatements ds = qs.getStatements(impl, r, processor, true);\r
-           for(Statement stm : ds) {\r
-               ResourceImpl p = (ResourceImpl)stm.getPredicate();\r
-               ResourceImpl o = (ResourceImpl)stm.getObject();\r
-               if(done.add(p.id)) fringe.add(p.id);\r
-               if(done.add(o.id)) fringe.add(o.id);\r
-           }\r
-               qs.getValue(impl, r);\r
-           }\r
-\r
-           return "Validated " + done.size() + " resources.";\r
-\r
-       }\r
-\r
-}\r
+package fi.vtt.simantics.procore.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.eclipse.core.runtime.Platform;
+import org.osgi.framework.Bundle;
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.databoard.parser.repository.DataValueRepository;
+import org.simantics.db.DirectStatements;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.Statement;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.common.request.WriteResultRequest;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.ServiceException;
+import org.simantics.db.exception.ValidationException;
+import org.simantics.db.impl.Activator;
+import org.simantics.db.impl.ClusterI;
+import org.simantics.db.impl.ResourceImpl;
+import org.simantics.db.impl.graph.ReadGraphImpl;
+import org.simantics.db.impl.graph.WriteLogger;
+import org.simantics.db.impl.query.QueryProcessor;
+import org.simantics.db.impl.query.QuerySupport;
+import org.simantics.db.procore.cluster.ClusterBig;
+import org.simantics.db.procore.cluster.ClusterImpl;
+import org.simantics.db.procore.cluster.ClusterSmall;
+import org.simantics.db.service.DebugSupport;
+import org.simantics.db.service.QueryControl;
+import org.simantics.db.service.XSupport;
+import org.simantics.layer0.Layer0;
+import org.simantics.scl.runtime.function.Function2;
+import org.simantics.scl.runtime.function.Function3;
+import org.simantics.scl.runtime.function.FunctionImpl2;
+import org.simantics.scl.runtime.function.FunctionImpl3;
+import org.simantics.utils.Development;
+import org.simantics.utils.FileUtils;
+
+import gnu.trove.map.hash.TIntIntHashMap;
+import gnu.trove.procedure.TIntIntProcedure;
+import gnu.trove.procedure.TIntShortProcedure;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class DebugSupportImpl implements DebugSupport {
+
+       final private Map<String, Function2<WriteGraph, String, Object>> getCommands = new HashMap<String, Function2<WriteGraph, String, Object>>();
+       final private Map<String, Function3<WriteGraph, File, String, String>> listCommands = new HashMap<String, Function3<WriteGraph, File, String, String>>();
+       final private Map<String, Function2<WriteGraph, String, String>> execCommands = new HashMap<String, Function2<WriteGraph, String, String>>();
+       final private Map<String, Function2<WriteGraph, String, String>> printCommands = new HashMap<String, Function2<WriteGraph, String, String>>();
+
+       private static SessionImplSocket getSession(WriteGraph graph) {
+               return (SessionImplSocket)graph.getSession();
+       }
+
+       DebugSupportImpl() {
+
+               getCommands.put("listeners", new FunctionImpl2<WriteGraph, String, Object>() {
+
+                       @Override
+                       public Object apply(WriteGraph graph, String args) {
+                               try {
+                                       return getSession(graph).queryProvider2.getListenerReport();
+                               } catch (IOException e) {
+                                       Logger.defaultLogError(e);
+                                       return e.getMessage();
+                               }
+                       }
+
+               });
+
+               listCommands.put("counters", new FunctionImpl3<WriteGraph, File, String, String>() {
+
+                       @Override
+                       public String apply(WriteGraph graph, File file, String args) {
+                               try {
+                                       return ReadGraphImpl.listCounters(file);
+                               } catch (IOException e) {
+                                       Logger.defaultLogError(e);
+                                       return e.getMessage();
+                               }
+                       }
+
+               });
+
+               listCommands.put("queries", new FunctionImpl3<WriteGraph, File, String, String>() {
+
+                       @Override
+                       public String apply(WriteGraph graph, File file, String args) {
+                               try {
+                                       return getSession(graph).queryProvider2.reportQueries(file);
+                               } catch (IOException e) {
+                                       Logger.defaultLogError(e);
+                                       return e.getMessage();
+                               }
+                       }
+
+               });
+
+               listCommands.put("queryActivity", new FunctionImpl3<WriteGraph, File, String, String>() {
+
+                       @Override
+                       public String apply(WriteGraph graph, File file, String args) {
+                               try {
+                                       return getSession(graph).queryProvider2.reportQueryActivity(file);
+                               } catch (IOException e) {
+                                       Logger.defaultLogError(e);
+                                       return e.getMessage();
+                               }
+                       }
+
+               });
+
+               listCommands.put("listeners", new FunctionImpl3<WriteGraph, File, String, String>() {
+
+                       @Override
+                       public String apply(WriteGraph graph, File file, String args) {
+                               try {
+                                       return getSession(graph).queryProvider2.reportListeners(file);
+                               } catch (IOException e) {
+                                       Logger.defaultLogError(e);
+                                       return e.getMessage();
+                               }
+                       }
+
+               });
+
+               listCommands.put("clusters", new FunctionImpl3<WriteGraph, File, String, String>() {
+
+                       @Override
+                       public String apply(WriteGraph graph, File file, String args) {
+                               return reportClusters(getSession(graph), file);
+                       }
+
+               });
+
+        listCommands.put("cluster", new FunctionImpl3<WriteGraph, File, String, String>() {
+
+            @Override
+            public String apply(WriteGraph graph, File file, String args) {
+                return reportCluster(graph, file, args);
+            }
+
+        });
+
+               listCommands.put("virtuals", new FunctionImpl3<WriteGraph, File, String, String>() {
+
+                       @Override
+                       public String apply(WriteGraph graph, File file, String args) {
+                               return reportVirtuals(getSession(graph), file);
+                       }
+
+               });
+
+               listCommands.put("heap", new FunctionImpl3<WriteGraph, File, String, String>() {
+
+                       @Override
+                       public String apply(WriteGraph graph, File file, String args) {
+
+                               try {
+
+                                       file.delete();
+
+                                       Object bean = getBean();
+                                       if (bean == null)
+                                               return "Could not retrieve bean.";
+
+                                       Method m = bean.getClass().getMethod("dumpHeap", String.class, boolean.class);
+                                       if (args.length() > 0) {
+                                               m.invoke(bean, file.getParent() + "/" + args, true);
+                                       } else {
+                                               m.invoke(bean, file.getAbsolutePath(), true);
+                                       }
+
+                               } catch (Throwable t) {
+                                       Logger.defaultLogError(t);
+                                       return "Unexpected exception " + t;
+                               }
+
+                               return "Wrote " + file.getAbsolutePath();
+
+                   }
+
+                   private Object getBean() {
+                       Class<?> beanClass = getBeanClass();
+                       if (beanClass == null)
+                           return null;
+                       try {
+                           Object bean = ManagementFactory.newPlatformMXBeanProxy(
+                                   ManagementFactory.getPlatformMBeanServer(),
+                                   "com.sun.management:type=HotSpotDiagnostic",
+                                   beanClass);
+                           return bean;
+                       } catch (IOException e) {
+                           return null;
+                       }
+                   }
+
+                   private Class<?> getBeanClass() {
+                       try {
+                           Class<?> clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean");
+                           return clazz;
+                       } catch (ClassNotFoundException e) {
+                           return null;
+                       }
+                   }
+
+               });
+
+               execCommands.put("WriteLogger.read", new FunctionImpl2<WriteGraph, String, String>() {
+
+                       @Override
+                       public String apply(WriteGraph graph, String args) {
+                               graph.getSession().async(new WriteRequest() {
+
+                                       @Override
+                                       public void perform(WriteGraph graph) throws DatabaseException {
+                                               try {
+                                                       WriteLogger.read(graph);
+                                               } catch (Exception e) {
+                                                       e.printStackTrace();
+                                               }
+                                       }
+
+                               });
+                               return "Started to read the write log.";
+                       }
+
+               });
+
+               execCommands.put("ReadGraph.resetCounters", new FunctionImpl2<WriteGraph, String, String>() {
+
+                       @Override
+                       public String apply(WriteGraph graph, String args) {
+                               graph.getSession().async(new WriteRequest() {
+
+                                       @Override
+                                       public void perform(WriteGraph graph) throws DatabaseException {
+                                               try {
+                                                       ReadGraphImpl.resetCounters();
+                                               } catch (Exception e) {
+                                                       e.printStackTrace();
+                                               }
+                                       }
+
+                               });
+                               return "Started to read the write log.";
+                       }
+
+               });
+
+               execCommands.put("QueryControl.flush", new FunctionImpl2<WriteGraph, String, String>() {
+
+                       @Override
+                       public String apply(WriteGraph graph, String args) {
+                               QueryControl qc = graph.getService(QueryControl.class);
+                               qc.flush(graph);
+                               return "Flushed queries.";
+                       }
+
+               });
+
+        execCommands.put("DebugSupport.validateClusters", new FunctionImpl2<WriteGraph, String, String>() {
+
+            @Override
+            public String apply(WriteGraph graph, String args) {
+                return validateClusters(graph);
+            }
+
+        });
+
+        execCommands.put("DebugSupport.writeForMs", new FunctionImpl2<WriteGraph, String, String>() {
+
+            @Override
+            public String apply(WriteGraph graph, String args) {
+                Integer amount = Integer.parseInt(args);
+                return writeForMs(graph, amount);
+            }
+
+        });
+
+               printCommands.put("nextId", new FunctionImpl2<WriteGraph, String, String>() {
+
+                       @Override
+                       public String apply(WriteGraph graph, String args) {
+                               try {
+                                       SessionImplSocket session = getSession(graph);
+                                       ClusterImpl cluster = session.clusterTable.getNewResourceCluster(session.clusterTranslator, session.graphSession, false);
+                                       long cid = cluster.getClusterId();
+                                       int rid = cluster.getNumberOfResources(session.clusterTranslator);
+                                       return cid + "#" + rid;
+                               } catch (Throwable t) {
+                                       return UUID.randomUUID().toString();
+                               }
+                       }
+
+               });
+
+               printCommands.put("usedMemory", new FunctionImpl2<WriteGraph, String, String>() {
+
+                       @Override
+                       public String apply(WriteGraph graph, String args) {
+                               try {
+                                       Runtime runtime = Runtime.getRuntime();
+                                       return "" + (runtime.totalMemory() - runtime.freeMemory());
+                               } catch (Throwable t) {
+                                       return UUID.randomUUID().toString();
+                               }
+                       }
+
+               });
+
+       }
+
+       private String reportClusters(SessionImplSocket session, File file) {
+
+               try {
+                       StringBuilder b = new StringBuilder();
+                       long totalApproxSize = 0;
+                       int loaded = 0;
+                       for(ClusterI cluster : session.clusterTable.getClusters()) {
+                               b.append("[" + cluster.getClusterKey() + "]: ");
+                               if(cluster instanceof ClusterSmall) b.append("ClusterSmall[" + cluster.getClusterId() + "]");
+                               if(cluster instanceof ClusterBig) b.append("ClusterBig[" + cluster.getClusterId() + "]");
+                               if(cluster instanceof ClusterWriteOnly) b.append("ClusterWriteOnly[" + cluster.getClusterId() + "]");
+                               if(cluster.isLoaded()) {
+                                       long approx = cluster.getUsedSpace();
+                                       b.append(" approx size = " + approx + " bytes.\n");
+                                       totalApproxSize += approx;
+                                       loaded++;
+                               } else {
+                                       b.append(" is not loaded.\n");
+                               }
+                       }
+                       b.append("#Total approx size is " + totalApproxSize + " bytes.\n");
+                       b.append("#Amount of loaded clusters is " + loaded + ".\n");
+                       FileUtils.writeFile(file, b.toString().getBytes());
+               } catch (IOException e) {
+                       e.printStackTrace();
+               } catch (DatabaseException e) {
+                       e.printStackTrace();
+               }
+
+               return "OK";
+
+       }
+
+    private String reportCluster(final WriteGraph graph, File file, String args) {
+
+        try {
+
+            final StringBuilder b = new StringBuilder();
+            final SessionImplSocket session = (SessionImplSocket)graph.getSession();
+            long clusterId = Long.parseLong(args);
+            b.append("cluster id: " + clusterId);
+            b.append("\n");
+            b.append("internal resources: ");
+            b.append("\n");
+            ClusterI cluster = session.clusterTable.getClusterByClusterId(clusterId);
+            for(int i=1;i<=cluster.getNumberOfResources(session.clusterTranslator);i++) {
+                Resource r = session.getResource(i, clusterId);
+                String def = NameUtils.getSafeName(graph, r);
+                b.append( i+": " + def);
+                b.append("\n");
+            }
+            if(cluster instanceof ClusterSmall) {
+                ClusterSmall clusterSmall = (ClusterSmall)cluster;
+                b.append("foreign resources: ");
+                b.append("\n");
+                final TIntIntHashMap clusterHistogram = new TIntIntHashMap();
+                clusterSmall.foreignTable.getResourceHashMap().forEachEntry(new TIntShortProcedure() {
+
+                    @Override
+                    public boolean execute(int index, short pos) {
+                        try {
+                            Resource r = session.getResource(index);
+                            String def = NameUtils.getSafeName(graph, r, true);
+                            int cluster = index >>> 12;
+                            int key = index & 0xfff;
+                            int exist = clusterHistogram.get(cluster);
+                            clusterHistogram.put(cluster, exist+1);
+                            b.append( cluster + "$" + key +": " + def);
+                            b.append("\n");
+                        } catch (ValidationException e) {
+                            e.printStackTrace();
+                        } catch (ServiceException e) {
+                            e.printStackTrace();
+                        }
+                        return true;
+                    }
+                });
+                b.append("foreign histogram: ");
+                b.append("\n");
+                clusterHistogram.forEachEntry(new TIntIntProcedure() {
+
+                    @Override
+                    public boolean execute(int cluster, int count) {
+                        b.append( cluster +": " + count);
+                        b.append("\n");
+                        return true;
+                    }
+                });
+            }
+
+            FileUtils.writeFile(file, b.toString().getBytes());
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (DatabaseException e) {
+            e.printStackTrace();
+        }
+
+        return "OK";
+
+    }
+
+       private String reportVirtuals(SessionImplSocket session, File file) {
+
+               session.virtualGraphServerSupport.report(file);
+
+               return "OK";
+
+       }
+
+       public Object query(Session session, final String command) {
+               try {
+                       return session.sync(new WriteResultRequest<Object>() {
+
+                               @Override
+                               public Object perform(WriteGraph graph) throws DatabaseException {
+                                       return query(graph, command);
+                               }
+
+                       });
+               } catch (DatabaseException e) {
+                       Logger.defaultLogError(e);
+                       return null;
+               }
+       }
+
+       @Override
+       public Object query(WriteGraph graph, String command) {
+
+               Bundle bundle = Platform.getBundle(Activator.BUNDLE_ID);
+               File base = Utils.getBaseFile(bundle);
+
+               command = command.trim();
+
+               try {
+
+                       if("help".equals(command)) {
+
+                               return
+                                               "Welcome to the Simantics session debugger.<br><br>" +
+                                               "This shell allows you to make following queries into the running Simantics database session:<br>" +
+                                               "<ul><li>Get commands, which return debug objects. Type 'help get' to obtain more information.</li>" +
+                                               "<li>List commands, which create debug listings into files. Type 'help list' to obtain more information.</li>" +
+                                               "<li>Print commands, which output information about session state. Type 'help print' to obtain more information.</li>" +
+                                               "<li>Set commands, which modify session state variables. Type 'help set' to obtain more information.</li>" +
+                                               "<li>Exec commands, which perform certain actions. Type 'help exec' to obtain more information.</li></ul>"
+                                               ;
+
+                       } else if ("help get".equals(command)) {
+
+                               StringBuilder b = new StringBuilder();
+                               b.append("The following get commands are available.<br><ul>");
+                               for(String key : getCommands.keySet())
+                                       b.append("<li>" + key + "</li>");
+
+                               b.append("</ul>");
+
+                               return b.toString();
+
+                       } else if ("help list".equals(command)) {
+
+                               StringBuilder b = new StringBuilder();
+                               b.append("The following list commands are available.<br><ul>");
+                               for(String key : listCommands.keySet())
+                                       b.append("<li>" + key + "</li>");
+
+                               b.append("</ul>");
+
+                               return b.toString();
+
+                       } else if ("help exec".equals(command)) {
+
+                               StringBuilder b = new StringBuilder();
+                               b.append("The following exec commands are available.<br><ul>");
+                               for(String key : execCommands.keySet())
+                                       b.append("<li>" + key + "</li>");
+
+                               b.append("</ul>");
+
+                               return b.toString();
+
+                       } else if ("help print".equals(command)) {
+
+                               StringBuilder b = new StringBuilder();
+                               b.append("The following print commands are available.<br><ul>");
+                               for(String key : printCommands.keySet())
+                                       b.append("<li>" + key + "</li>");
+
+                               b.append("</ul>");
+
+                               return b.toString();
+
+                       } else if ("help set".equals(command)) {
+
+                               StringBuilder b = new StringBuilder();
+                               b.append("The following set commands are available.<br><ul>");
+
+                               for(Map.Entry<String, Variant> e : Development.getProperties().entrySet()) {
+                                       b.append("<li>" + e.getKey() + " - " + e.getValue().getBinding().type() + "</li>");
+                               }
+
+                               b.append("</ul>");
+
+                               return b.toString();
+
+                       } else if(command.startsWith("get")) {
+
+                               String remainder = command.substring(3).trim();
+
+                               for(Map.Entry<String, Function2<WriteGraph, String, Object>> e : getCommands.entrySet()) {
+                                       String key = e.getKey();
+                                       if(remainder.startsWith(key)) {
+                                               String args = remainder.substring(key.length()).trim();
+                                               return e.getValue().apply(graph, args);
+                                       }
+                               }
+
+                       } else if(command.startsWith("list")) {
+
+                               String remainder = command.substring(4).trim();
+
+                               for(Map.Entry<String, Function3<WriteGraph, File, String, String>> e : listCommands.entrySet()) {
+                                       String key = e.getKey();
+                                       if(remainder.startsWith(key)) {
+                                               String args = remainder.substring(key.length()).trim();
+                                               File file = new File(base, key + ".list");
+                                               base.mkdirs();
+                                               e.getValue().apply(graph, file, args);
+                                               return "Wrote " + file.getAbsolutePath();
+                                       }
+                               }
+
+                       } else if(command.startsWith("set")) {
+
+                               String remainder = command.substring(3).trim();
+                               String[] keyAndValue = remainder.split("=");
+                               if(keyAndValue.length == 2) {
+
+                                       Variant exist = Development.getProperties().get(keyAndValue[0]);
+                                       if(exist != null) {
+                                               Development.setProperty(keyAndValue[0], exist.getBinding().parseValue(keyAndValue[1], new DataValueRepository()), exist.getBinding());
+                                               return "Property " + keyAndValue[0] + " was set to '" + keyAndValue[1] + "'";
+                                       } else {
+                                               return query(graph, "help set");
+                                       }
+                               } else {
+                                       return query(graph, "help set");
+                               }
+
+                       } else if(command.startsWith("print")) {
+
+                               String remainder = command.substring(5).trim();
+
+                               for(Map.Entry<String, Function2<WriteGraph, String, String>> e : printCommands.entrySet()) {
+                                       String key = e.getKey();
+                                       if(remainder.startsWith(key)) {
+                                               String args = remainder.substring(key.length()).trim();
+                                               return e.getValue().apply(graph, args);
+                                       }
+                               }
+
+                       } else if(command.startsWith("exec")) {
+
+                               String remainder = command.substring(4).trim();
+
+                               for(Map.Entry<String, Function2<WriteGraph, String, String>> e : execCommands.entrySet()) {
+                                       String key = e.getKey();
+                                       if(remainder.startsWith(key)) {
+                                               String args = remainder.substring(key.length()).trim();
+                                               return e.getValue().apply(graph, args);
+                                       }
+                               }
+
+                       }
+
+                       return "Unknown command '" + command + "'";
+
+               } catch (Throwable t) {
+
+                       t.printStackTrace();
+
+                       return t.getMessage();
+
+               }
+
+       }
+       private void writeResouce(WriteGraph graph) throws DatabaseException {
+        Layer0 l0 = Layer0.getInstance(graph);
+        Resource r = graph.newResource();
+        graph.claim(r, l0.InstanceOf, l0.Entity);
+        XSupport xs = (XSupport)graph.getService(XSupport.class);
+        xs.flushCluster(r);
+       }
+       private void wait(int amount) {
+        long start = System.nanoTime();
+        long limit = amount * 1000000L;
+        while ((System.nanoTime() - start) < limit) {
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+       }
+       String writeForMs(WriteGraph graph, int amount) {
+        try {
+            writeResouce(graph);
+            wait(amount);
+            writeResouce(graph);
+        } catch (DatabaseException e) {
+            e.printStackTrace();
+        }
+
+               return "Slept for " + amount + " ms in write transaction.";
+       }
+
+       String validateClusters(WriteGraph graph) {
+
+           ReadGraphImpl impl = (ReadGraphImpl)graph;
+           QueryProcessor processor = impl.processor;
+
+           QuerySupport qs = graph.getService(QuerySupport.class);
+
+           TIntHashSet done = new TIntHashSet();
+           TreeSet<Integer> fringe = new TreeSet<Integer>();
+
+           ResourceImpl root = (ResourceImpl)graph.getRootLibrary();
+
+           done.add(root.id);
+           fringe.add(root.id);
+
+           while(!fringe.isEmpty()) {
+               int r = fringe.first();
+               fringe.remove(r);
+               DirectStatements ds = qs.getStatements(impl, r, processor, true);
+           for(Statement stm : ds) {
+               ResourceImpl p = (ResourceImpl)stm.getPredicate();
+               ResourceImpl o = (ResourceImpl)stm.getObject();
+               if(done.add(p.id)) fringe.add(p.id);
+               if(done.add(o.id)) fringe.add(o.id);
+           }
+               qs.getValue(impl, r);
+           }
+
+           return "Validated " + done.size() + " resources.";
+
+       }
+
+}