]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DebugSupportImpl.java
Merge commit '55ca14c'
[simantics/platform.git] / bundles / org.simantics.db.procore / src / fi / vtt / simantics / procore / internal / DebugSupportImpl.java
1 package fi.vtt.simantics.procore.internal;\r
2 \r
3 import java.io.File;\r
4 import java.io.IOException;\r
5 import java.lang.management.ManagementFactory;\r
6 import java.lang.reflect.Method;\r
7 import java.util.HashMap;\r
8 import java.util.Map;\r
9 import java.util.TreeSet;\r
10 import java.util.UUID;\r
11 \r
12 import org.eclipse.core.runtime.Platform;\r
13 import org.osgi.framework.Bundle;\r
14 import org.simantics.databoard.binding.mutable.Variant;\r
15 import org.simantics.databoard.parser.repository.DataValueRepository;\r
16 import org.simantics.db.DirectStatements;\r
17 import org.simantics.db.Resource;\r
18 import org.simantics.db.Session;\r
19 import org.simantics.db.Statement;\r
20 import org.simantics.db.WriteGraph;\r
21 import org.simantics.db.common.request.WriteRequest;\r
22 import org.simantics.db.common.request.WriteResultRequest;\r
23 import org.simantics.db.common.utils.Logger;\r
24 import org.simantics.db.common.utils.NameUtils;\r
25 import org.simantics.db.exception.DatabaseException;\r
26 import org.simantics.db.exception.ServiceException;\r
27 import org.simantics.db.exception.ValidationException;\r
28 import org.simantics.db.impl.Activator;\r
29 import org.simantics.db.impl.ClusterI;\r
30 import org.simantics.db.impl.ResourceImpl;\r
31 import org.simantics.db.impl.graph.ReadGraphImpl;\r
32 import org.simantics.db.impl.graph.WriteLogger;\r
33 import org.simantics.db.impl.query.QueryProcessor;\r
34 import org.simantics.db.impl.query.QuerySupport;\r
35 import org.simantics.db.procore.cluster.ClusterBig;\r
36 import org.simantics.db.procore.cluster.ClusterImpl;\r
37 import org.simantics.db.procore.cluster.ClusterSmall;\r
38 import org.simantics.db.service.DebugSupport;\r
39 import org.simantics.db.service.QueryControl;\r
40 import org.simantics.db.service.XSupport;\r
41 import org.simantics.layer0.Layer0;\r
42 import org.simantics.scl.runtime.function.Function2;\r
43 import org.simantics.scl.runtime.function.Function3;\r
44 import org.simantics.scl.runtime.function.FunctionImpl2;\r
45 import org.simantics.scl.runtime.function.FunctionImpl3;\r
46 import org.simantics.utils.Development;\r
47 import org.simantics.utils.FileUtils;\r
48 \r
49 import gnu.trove.map.hash.TIntIntHashMap;\r
50 import gnu.trove.procedure.TIntIntProcedure;\r
51 import gnu.trove.procedure.TIntShortProcedure;\r
52 import gnu.trove.set.hash.TIntHashSet;\r
53 \r
54 public class DebugSupportImpl implements DebugSupport {\r
55 \r
56         final private Map<String, Function2<WriteGraph, String, Object>> getCommands = new HashMap<String, Function2<WriteGraph, String, Object>>();\r
57         final private Map<String, Function3<WriteGraph, File, String, String>> listCommands = new HashMap<String, Function3<WriteGraph, File, String, String>>();\r
58         final private Map<String, Function2<WriteGraph, String, String>> execCommands = new HashMap<String, Function2<WriteGraph, String, String>>();\r
59         final private Map<String, Function2<WriteGraph, String, String>> printCommands = new HashMap<String, Function2<WriteGraph, String, String>>();\r
60 \r
61         private static SessionImplSocket getSession(WriteGraph graph) {\r
62                 return (SessionImplSocket)graph.getSession();\r
63         }\r
64 \r
65         DebugSupportImpl() {\r
66 \r
67                 getCommands.put("listeners", new FunctionImpl2<WriteGraph, String, Object>() {\r
68 \r
69                         @Override\r
70                         public Object apply(WriteGraph graph, String args) {\r
71                                 try {\r
72                                         return getSession(graph).queryProvider2.getListenerReport();\r
73                                 } catch (IOException e) {\r
74                                         Logger.defaultLogError(e);\r
75                                         return e.getMessage();\r
76                                 }\r
77                         }\r
78 \r
79                 });\r
80 \r
81                 listCommands.put("counters", new FunctionImpl3<WriteGraph, File, String, String>() {\r
82 \r
83                         @Override\r
84                         public String apply(WriteGraph graph, File file, String args) {\r
85                                 try {\r
86                                         return ReadGraphImpl.listCounters(file);\r
87                                 } catch (IOException e) {\r
88                                         Logger.defaultLogError(e);\r
89                                         return e.getMessage();\r
90                                 }\r
91                         }\r
92 \r
93                 });\r
94 \r
95                 listCommands.put("queries", new FunctionImpl3<WriteGraph, File, String, String>() {\r
96 \r
97                         @Override\r
98                         public String apply(WriteGraph graph, File file, String args) {\r
99                                 try {\r
100                                         return getSession(graph).queryProvider2.reportQueries(file);\r
101                                 } catch (IOException e) {\r
102                                         Logger.defaultLogError(e);\r
103                                         return e.getMessage();\r
104                                 }\r
105                         }\r
106 \r
107                 });\r
108 \r
109                 listCommands.put("queryActivity", new FunctionImpl3<WriteGraph, File, String, String>() {\r
110 \r
111                         @Override\r
112                         public String apply(WriteGraph graph, File file, String args) {\r
113                                 try {\r
114                                         return getSession(graph).queryProvider2.reportQueryActivity(file);\r
115                                 } catch (IOException e) {\r
116                                         Logger.defaultLogError(e);\r
117                                         return e.getMessage();\r
118                                 }\r
119                         }\r
120 \r
121                 });\r
122 \r
123                 listCommands.put("listeners", new FunctionImpl3<WriteGraph, File, String, String>() {\r
124 \r
125                         @Override\r
126                         public String apply(WriteGraph graph, File file, String args) {\r
127                                 try {\r
128                                         return getSession(graph).queryProvider2.reportListeners(file);\r
129                                 } catch (IOException e) {\r
130                                         Logger.defaultLogError(e);\r
131                                         return e.getMessage();\r
132                                 }\r
133                         }\r
134 \r
135                 });\r
136 \r
137                 listCommands.put("clusters", new FunctionImpl3<WriteGraph, File, String, String>() {\r
138 \r
139                         @Override\r
140                         public String apply(WriteGraph graph, File file, String args) {\r
141                                 return reportClusters(getSession(graph), file);\r
142                         }\r
143 \r
144                 });\r
145 \r
146         listCommands.put("cluster", new FunctionImpl3<WriteGraph, File, String, String>() {\r
147 \r
148             @Override\r
149             public String apply(WriteGraph graph, File file, String args) {\r
150                 return reportCluster(graph, file, args);\r
151             }\r
152 \r
153         });\r
154 \r
155                 listCommands.put("virtuals", new FunctionImpl3<WriteGraph, File, String, String>() {\r
156 \r
157                         @Override\r
158                         public String apply(WriteGraph graph, File file, String args) {\r
159                                 return reportVirtuals(getSession(graph), file);\r
160                         }\r
161 \r
162                 });\r
163 \r
164                 listCommands.put("heap", new FunctionImpl3<WriteGraph, File, String, String>() {\r
165 \r
166                         @Override\r
167                         public String apply(WriteGraph graph, File file, String args) {\r
168 \r
169                                 try {\r
170 \r
171                                         file.delete();\r
172 \r
173                                         Object bean = getBean();\r
174                                         if (bean == null)\r
175                                                 return "Could not retrieve bean.";\r
176 \r
177                                         Method m = bean.getClass().getMethod("dumpHeap", String.class, boolean.class);\r
178                                         if (args.length() > 0) {\r
179                                                 m.invoke(bean, file.getParent() + "/" + args, true);\r
180                                         } else {\r
181                                                 m.invoke(bean, file.getAbsolutePath(), true);\r
182                                         }\r
183 \r
184                                 } catch (Throwable t) {\r
185                                         Logger.defaultLogError(t);\r
186                                         return "Unexpected exception " + t;\r
187                                 }\r
188 \r
189                                 return "Wrote " + file.getAbsolutePath();\r
190 \r
191                     }\r
192 \r
193                     private Object getBean() {\r
194                         Class<?> beanClass = getBeanClass();\r
195                         if (beanClass == null)\r
196                             return null;\r
197                         try {\r
198                             Object bean = ManagementFactory.newPlatformMXBeanProxy(\r
199                                     ManagementFactory.getPlatformMBeanServer(),\r
200                                     "com.sun.management:type=HotSpotDiagnostic",\r
201                                     beanClass);\r
202                             return bean;\r
203                         } catch (IOException e) {\r
204                             return null;\r
205                         }\r
206                     }\r
207 \r
208                     private Class<?> getBeanClass() {\r
209                         try {\r
210                             Class<?> clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean");\r
211                             return clazz;\r
212                         } catch (ClassNotFoundException e) {\r
213                             return null;\r
214                         }\r
215                     }\r
216 \r
217                 });\r
218 \r
219                 execCommands.put("WriteLogger.read", new FunctionImpl2<WriteGraph, String, String>() {\r
220 \r
221                         @Override\r
222                         public String apply(WriteGraph graph, String args) {\r
223                                 graph.getSession().async(new WriteRequest() {\r
224 \r
225                                         @Override\r
226                                         public void perform(WriteGraph graph) throws DatabaseException {\r
227                                                 try {\r
228                                                         WriteLogger.read(graph);\r
229                                                 } catch (Exception e) {\r
230                                                         e.printStackTrace();\r
231                                                 }\r
232                                         }\r
233 \r
234                                 });\r
235                                 return "Started to read the write log.";\r
236                         }\r
237 \r
238                 });\r
239 \r
240                 execCommands.put("ReadGraph.resetCounters", new FunctionImpl2<WriteGraph, String, String>() {\r
241 \r
242                         @Override\r
243                         public String apply(WriteGraph graph, String args) {\r
244                                 graph.getSession().async(new WriteRequest() {\r
245 \r
246                                         @Override\r
247                                         public void perform(WriteGraph graph) throws DatabaseException {\r
248                                                 try {\r
249                                                         ReadGraphImpl.resetCounters();\r
250                                                 } catch (Exception e) {\r
251                                                         e.printStackTrace();\r
252                                                 }\r
253                                         }\r
254 \r
255                                 });\r
256                                 return "Started to read the write log.";\r
257                         }\r
258 \r
259                 });\r
260 \r
261                 execCommands.put("QueryControl.flush", new FunctionImpl2<WriteGraph, String, String>() {\r
262 \r
263                         @Override\r
264                         public String apply(WriteGraph graph, String args) {\r
265                                 QueryControl qc = graph.getService(QueryControl.class);\r
266                                 qc.flush(graph);\r
267                                 return "Flushed queries.";\r
268                         }\r
269 \r
270                 });\r
271 \r
272         execCommands.put("DebugSupport.validateClusters", new FunctionImpl2<WriteGraph, String, String>() {\r
273 \r
274             @Override\r
275             public String apply(WriteGraph graph, String args) {\r
276                 return validateClusters(graph);\r
277             }\r
278 \r
279         });\r
280 \r
281         execCommands.put("DebugSupport.writeForMs", new FunctionImpl2<WriteGraph, String, String>() {\r
282 \r
283             @Override\r
284             public String apply(WriteGraph graph, String args) {\r
285                 Integer amount = Integer.parseInt(args);\r
286                 return writeForMs(graph, amount);\r
287             }\r
288 \r
289         });\r
290 \r
291                 printCommands.put("nextId", new FunctionImpl2<WriteGraph, String, String>() {\r
292 \r
293                         @Override\r
294                         public String apply(WriteGraph graph, String args) {\r
295                                 try {\r
296                                         SessionImplSocket session = getSession(graph);\r
297                                         ClusterImpl cluster = session.clusterTable.getNewResourceCluster(session.clusterTranslator, session.graphSession, false);\r
298                                         long cid = cluster.getClusterId();\r
299                                         int rid = cluster.getNumberOfResources(session.clusterTranslator);\r
300                                         return cid + "#" + rid;\r
301                                 } catch (Throwable t) {\r
302                                         return UUID.randomUUID().toString();\r
303                                 }\r
304                         }\r
305 \r
306                 });\r
307 \r
308                 printCommands.put("usedMemory", new FunctionImpl2<WriteGraph, String, String>() {\r
309 \r
310                         @Override\r
311                         public String apply(WriteGraph graph, String args) {\r
312                                 try {\r
313                                         Runtime runtime = Runtime.getRuntime();\r
314                                         return "" + (runtime.totalMemory() - runtime.freeMemory());\r
315                                 } catch (Throwable t) {\r
316                                         return UUID.randomUUID().toString();\r
317                                 }\r
318                         }\r
319 \r
320                 });\r
321 \r
322         }\r
323 \r
324         private String reportClusters(SessionImplSocket session, File file) {\r
325 \r
326                 try {\r
327                         StringBuilder b = new StringBuilder();\r
328                         long totalApproxSize = 0;\r
329                         int loaded = 0;\r
330                         for(ClusterI cluster : session.clusterTable.getClusters()) {\r
331                                 b.append("[" + cluster.getClusterKey() + "]: ");\r
332                                 if(cluster instanceof ClusterSmall) b.append("ClusterSmall[" + cluster.getClusterId() + "]");\r
333                                 if(cluster instanceof ClusterBig) b.append("ClusterBig[" + cluster.getClusterId() + "]");\r
334                                 if(cluster instanceof ClusterWriteOnly) b.append("ClusterWriteOnly[" + cluster.getClusterId() + "]");\r
335                                 if(cluster.isLoaded()) {\r
336                                         long approx = cluster.getUsedSpace();\r
337                                         b.append(" approx size = " + approx + " bytes.\n");\r
338                                         totalApproxSize += approx;\r
339                                         loaded++;\r
340                                 } else {\r
341                                         b.append(" is not loaded.\n");\r
342                                 }\r
343                         }\r
344                         b.append("#Total approx size is " + totalApproxSize + " bytes.\n");\r
345                         b.append("#Amount of loaded clusters is " + loaded + ".\n");\r
346                         FileUtils.writeFile(file, b.toString().getBytes());\r
347                 } catch (IOException e) {\r
348                         e.printStackTrace();\r
349                 } catch (DatabaseException e) {\r
350                         e.printStackTrace();\r
351                 }\r
352 \r
353                 return "OK";\r
354 \r
355         }\r
356 \r
357     private String reportCluster(final WriteGraph graph, File file, String args) {\r
358 \r
359         try {\r
360 \r
361             final StringBuilder b = new StringBuilder();\r
362             final SessionImplSocket session = (SessionImplSocket)graph.getSession();\r
363             long clusterId = Long.parseLong(args);\r
364             b.append("cluster id: " + clusterId);\r
365             b.append("\n");\r
366             b.append("internal resources: ");\r
367             b.append("\n");\r
368             ClusterI cluster = session.clusterTable.getClusterByClusterId(clusterId);\r
369             for(int i=1;i<=cluster.getNumberOfResources(session.clusterTranslator);i++) {\r
370                 Resource r = session.getResource(i, clusterId);\r
371                 String def = NameUtils.getSafeName(graph, r);\r
372                 b.append( i+": " + def);\r
373                 b.append("\n");\r
374             }\r
375             if(cluster instanceof ClusterSmall) {\r
376                 ClusterSmall clusterSmall = (ClusterSmall)cluster;\r
377                 b.append("foreign resources: ");\r
378                 b.append("\n");\r
379                 final TIntIntHashMap clusterHistogram = new TIntIntHashMap();\r
380                 clusterSmall.foreignTable.getResourceHashMap().forEachEntry(new TIntShortProcedure() {\r
381 \r
382                     @Override\r
383                     public boolean execute(int index, short pos) {\r
384                         try {\r
385                             Resource r = session.getResource(index);\r
386                             String def = NameUtils.getSafeName(graph, r, true);\r
387                             int cluster = index >>> 12;\r
388                             int key = index & 0xfff;\r
389                             int exist = clusterHistogram.get(cluster);\r
390                             clusterHistogram.put(cluster, exist+1);\r
391                             b.append( cluster + "$" + key +": " + def);\r
392                             b.append("\n");\r
393                         } catch (ValidationException e) {\r
394                             e.printStackTrace();\r
395                         } catch (ServiceException e) {\r
396                             e.printStackTrace();\r
397                         }\r
398                         return true;\r
399                     }\r
400                 });\r
401                 b.append("foreign histogram: ");\r
402                 b.append("\n");\r
403                 clusterHistogram.forEachEntry(new TIntIntProcedure() {\r
404 \r
405                     @Override\r
406                     public boolean execute(int cluster, int count) {\r
407                         b.append( cluster +": " + count);\r
408                         b.append("\n");\r
409                         return true;\r
410                     }\r
411                 });\r
412             }\r
413 \r
414             FileUtils.writeFile(file, b.toString().getBytes());\r
415         } catch (IOException e) {\r
416             e.printStackTrace();\r
417         } catch (DatabaseException e) {\r
418             e.printStackTrace();\r
419         }\r
420 \r
421         return "OK";\r
422 \r
423     }\r
424 \r
425         private String reportVirtuals(SessionImplSocket session, File file) {\r
426 \r
427                 session.virtualGraphServerSupport.report(file);\r
428 \r
429                 return "OK";\r
430 \r
431         }\r
432 \r
433         public Object query(Session session, final String command) {\r
434                 try {\r
435                         return session.sync(new WriteResultRequest<Object>() {\r
436 \r
437                                 @Override\r
438                                 public Object perform(WriteGraph graph) throws DatabaseException {\r
439                                         return query(graph, command);\r
440                                 }\r
441 \r
442                         });\r
443                 } catch (DatabaseException e) {\r
444                         Logger.defaultLogError(e);\r
445                         return null;\r
446                 }\r
447         }\r
448 \r
449         @Override\r
450         public Object query(WriteGraph graph, String command) {\r
451 \r
452                 Bundle bundle = Platform.getBundle(Activator.BUNDLE_ID);\r
453                 File base = Utils.getBaseFile(bundle);\r
454 \r
455                 command = command.trim();\r
456 \r
457                 try {\r
458 \r
459                         if("help".equals(command)) {\r
460 \r
461                                 return\r
462                                                 "Welcome to the Simantics session debugger.<br><br>" +\r
463                                                 "This shell allows you to make following queries into the running Simantics database session:<br>" +\r
464                                                 "<ul><li>Get commands, which return debug objects. Type 'help get' to obtain more information.</li>" +\r
465                                                 "<li>List commands, which create debug listings into files. Type 'help list' to obtain more information.</li>" +\r
466                                                 "<li>Print commands, which output information about session state. Type 'help print' to obtain more information.</li>" +\r
467                                                 "<li>Set commands, which modify session state variables. Type 'help set' to obtain more information.</li>" +\r
468                                                 "<li>Exec commands, which perform certain actions. Type 'help exec' to obtain more information.</li></ul>"\r
469                                                 ;\r
470 \r
471                         } else if ("help get".equals(command)) {\r
472 \r
473                                 StringBuilder b = new StringBuilder();\r
474                                 b.append("The following get commands are available.<br><ul>");\r
475                                 for(String key : getCommands.keySet())\r
476                                         b.append("<li>" + key + "</li>");\r
477 \r
478                                 b.append("</ul>");\r
479 \r
480                                 return b.toString();\r
481 \r
482                         } else if ("help list".equals(command)) {\r
483 \r
484                                 StringBuilder b = new StringBuilder();\r
485                                 b.append("The following list commands are available.<br><ul>");\r
486                                 for(String key : listCommands.keySet())\r
487                                         b.append("<li>" + key + "</li>");\r
488 \r
489                                 b.append("</ul>");\r
490 \r
491                                 return b.toString();\r
492 \r
493                         } else if ("help exec".equals(command)) {\r
494 \r
495                                 StringBuilder b = new StringBuilder();\r
496                                 b.append("The following exec commands are available.<br><ul>");\r
497                                 for(String key : execCommands.keySet())\r
498                                         b.append("<li>" + key + "</li>");\r
499 \r
500                                 b.append("</ul>");\r
501 \r
502                                 return b.toString();\r
503 \r
504                         } else if ("help print".equals(command)) {\r
505 \r
506                                 StringBuilder b = new StringBuilder();\r
507                                 b.append("The following print commands are available.<br><ul>");\r
508                                 for(String key : printCommands.keySet())\r
509                                         b.append("<li>" + key + "</li>");\r
510 \r
511                                 b.append("</ul>");\r
512 \r
513                                 return b.toString();\r
514 \r
515                         } else if ("help set".equals(command)) {\r
516 \r
517                                 StringBuilder b = new StringBuilder();\r
518                                 b.append("The following set commands are available.<br><ul>");\r
519 \r
520                                 for(Map.Entry<String, Variant> e : Development.getProperties().entrySet()) {\r
521                                         b.append("<li>" + e.getKey() + " - " + e.getValue().getBinding().type() + "</li>");\r
522                                 }\r
523 \r
524                                 b.append("</ul>");\r
525 \r
526                                 return b.toString();\r
527 \r
528                         } else if(command.startsWith("get")) {\r
529 \r
530                                 String remainder = command.substring(3).trim();\r
531 \r
532                                 for(Map.Entry<String, Function2<WriteGraph, String, Object>> e : getCommands.entrySet()) {\r
533                                         String key = e.getKey();\r
534                                         if(remainder.startsWith(key)) {\r
535                                                 String args = remainder.substring(key.length()).trim();\r
536                                                 return e.getValue().apply(graph, args);\r
537                                         }\r
538                                 }\r
539 \r
540                         } else if(command.startsWith("list")) {\r
541 \r
542                                 String remainder = command.substring(4).trim();\r
543 \r
544                                 for(Map.Entry<String, Function3<WriteGraph, File, String, String>> e : listCommands.entrySet()) {\r
545                                         String key = e.getKey();\r
546                                         if(remainder.startsWith(key)) {\r
547                                                 String args = remainder.substring(key.length()).trim();\r
548                                                 File file = new File(base, key + ".list");\r
549                                                 base.mkdirs();\r
550                                                 e.getValue().apply(graph, file, args);\r
551                                                 return "Wrote " + file.getAbsolutePath();\r
552                                         }\r
553                                 }\r
554 \r
555                         } else if(command.startsWith("set")) {\r
556 \r
557                                 String remainder = command.substring(3).trim();\r
558                                 String[] keyAndValue = remainder.split("=");\r
559                                 if(keyAndValue.length == 2) {\r
560 \r
561                                         Variant exist = Development.getProperties().get(keyAndValue[0]);\r
562                                         if(exist != null) {\r
563                                                 Development.setProperty(keyAndValue[0], exist.getBinding().parseValue(keyAndValue[1], new DataValueRepository()), exist.getBinding());\r
564                                                 return "Property " + keyAndValue[0] + " was set to '" + keyAndValue[1] + "'";\r
565                                         } else {\r
566                                                 return query(graph, "help set");\r
567                                         }\r
568                                 } else {\r
569                                         return query(graph, "help set");\r
570                                 }\r
571 \r
572                         } else if(command.startsWith("print")) {\r
573 \r
574                                 String remainder = command.substring(5).trim();\r
575 \r
576                                 for(Map.Entry<String, Function2<WriteGraph, String, String>> e : printCommands.entrySet()) {\r
577                                         String key = e.getKey();\r
578                                         if(remainder.startsWith(key)) {\r
579                                                 String args = remainder.substring(key.length()).trim();\r
580                                                 return e.getValue().apply(graph, args);\r
581                                         }\r
582                                 }\r
583 \r
584                         } else if(command.startsWith("exec")) {\r
585 \r
586                                 String remainder = command.substring(4).trim();\r
587 \r
588                                 for(Map.Entry<String, Function2<WriteGraph, String, String>> e : execCommands.entrySet()) {\r
589                                         String key = e.getKey();\r
590                                         if(remainder.startsWith(key)) {\r
591                                                 String args = remainder.substring(key.length()).trim();\r
592                                                 return e.getValue().apply(graph, args);\r
593                                         }\r
594                                 }\r
595 \r
596                         }\r
597 \r
598                         return "Unknown command '" + command + "'";\r
599 \r
600                 } catch (Throwable t) {\r
601 \r
602                         t.printStackTrace();\r
603 \r
604                         return t.getMessage();\r
605 \r
606                 }\r
607 \r
608         }\r
609         private void writeResouce(WriteGraph graph) throws DatabaseException {\r
610         Layer0 l0 = Layer0.getInstance(graph);\r
611         Resource r = graph.newResource();\r
612         graph.claim(r, l0.InstanceOf, l0.Entity);\r
613         XSupport xs = (XSupport)graph.getService(XSupport.class);\r
614         xs.flushCluster(r);\r
615         }\r
616         private void wait(int amount) {\r
617         long start = System.nanoTime();\r
618         long limit = amount * 1000000L;\r
619         while ((System.nanoTime() - start) < limit) {\r
620             try {\r
621                 Thread.sleep(100);\r
622             } catch (InterruptedException e) {\r
623                 e.printStackTrace();\r
624             }\r
625         }\r
626         }\r
627         String writeForMs(WriteGraph graph, int amount) {\r
628         try {\r
629             writeResouce(graph);\r
630             wait(amount);\r
631             writeResouce(graph);\r
632         } catch (DatabaseException e) {\r
633             e.printStackTrace();\r
634         }\r
635 \r
636                 return "Slept for " + amount + " ms in write transaction.";\r
637         }\r
638 \r
639         String validateClusters(WriteGraph graph) {\r
640 \r
641             ReadGraphImpl impl = (ReadGraphImpl)graph;\r
642             QueryProcessor processor = impl.processor;\r
643 \r
644             QuerySupport qs = graph.getService(QuerySupport.class);\r
645 \r
646             TIntHashSet done = new TIntHashSet();\r
647             TreeSet<Integer> fringe = new TreeSet<Integer>();\r
648 \r
649             ResourceImpl root = (ResourceImpl)graph.getRootLibrary();\r
650 \r
651             done.add(root.id);\r
652             fringe.add(root.id);\r
653 \r
654             while(!fringe.isEmpty()) {\r
655                 int r = fringe.first();\r
656                 fringe.remove(r);\r
657                 DirectStatements ds = qs.getStatements(impl, r, processor, true);\r
658             for(Statement stm : ds) {\r
659                 ResourceImpl p = (ResourceImpl)stm.getPredicate();\r
660                 ResourceImpl o = (ResourceImpl)stm.getObject();\r
661                 if(done.add(p.id)) fringe.add(p.id);\r
662                 if(done.add(o.id)) fringe.add(o.id);\r
663             }\r
664                 qs.getValue(impl, r);\r
665             }\r
666 \r
667             return "Validated " + done.size() + " resources.";\r
668 \r
669         }\r
670 \r
671 }\r