]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / QueryCollectorImpl.java
diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl.java
new file mode 100644 (file)
index 0000000..3d5a5a5
--- /dev/null
@@ -0,0 +1,196 @@
+package org.simantics.db.impl.query;\r
+\r
+import org.simantics.db.impl.query.QueryProcessor.QueryCollectorSupport;\r
+\r
+class QueryCollectorImpl implements QueryProcessor.QueryCollector {\r
+       \r
+       private static final boolean DEBUG = false;\r
+       private static final boolean DEBUG_STATUS = false;\r
+\r
+       private final QueryProcessor queryProcessor;\r
+\r
+       final private QueryCollectorSupport support;\r
+\r
+       /*\r
+        * Set to true: at end of iteration if moreAll is false\r
+        * Set to false: upon gc start and whenever a prospect is added.\r
+        * \r
+        */\r
+       boolean doneAll = false;\r
+       /*\r
+        * Set to true: upon gc start and whenever a prospect is added.\r
+        * Set to false: at end of entry iteration\r
+        * => if this is already false at end of entry iteration => no more work to be done\r
+        */\r
+       int moreAll = 0;\r
+       \r
+       /*\r
+        * Change propagation is in progress\r
+        */\r
+       boolean propagate = true;\r
+       \r
+       \r
+       private static final int COLLECT_N = 1000;\r
+       \r
+       private long spent = 0;\r
+       \r
+       QueryCollectorImpl(QueryProcessor queryProcessor, QueryCollectorSupport support) {\r
+               this.queryProcessor = queryProcessor;\r
+               this.support = support;\r
+       }\r
+       \r
+       @Override\r
+       public void collect(int youngTarget, int allowedTimeInMs) {\r
+\r
+               long start = System.nanoTime();\r
+\r
+               // Refresh current size\r
+               int size = support.calculateCurrentSize();\r
+               int bound = queryProcessor.boundQueries;\r
+               int young = size - bound;\r
+               int youngPct = size > 0 ? 100*young / size : 0;\r
+               \r
+               // Initialize support for new run\r
+               // If support returns 0 we are starting from 0\r
+               if(support.start(youngTarget == 0)) {\r
+                       \r
+                       moreAll = 0;\r
+\r
+                       // We monitor all prospects here\r
+                       CacheEntryBase prospect = support.iterate(0);\r
+                       while(prospect != null) {\r
+                               if(prospect.isDiscarded()) {\r
+                                       support.remove();\r
+                                       propagate = true;\r
+                               } else {\r
+                                       CacheEntry parent = prospect.getFirstParent(queryProcessor);\r
+                                       if(parent == null) {\r
+                                               tryCollect(prospect);\r
+                                       } else {\r
+                                               support.setLevel(prospect, parent.getLevel() + 1);\r
+                                       }\r
+                               }\r
+                               prospect = support.iterate(0);\r
+                       }\r
+\r
+                       // If no prospects were collected and most of the queries are old we can stop here\r
+                       if(!propagate && youngPct < youngTarget) {\r
+//                             System.err.println("collect2 skipped");\r
+//                             System.err.println("-size=" + size);\r
+//                             System.err.println("-young=" + young);\r
+                               return; \r
+                       }\r
+                       \r
+               }\r
+               \r
+               long test = (long)allowedTimeInMs*1000000;\r
+\r
+               start();\r
+               \r
+               while(true) {\r
+                       \r
+                       size = support.getCurrentSize();\r
+                       bound = queryProcessor.boundQueries;\r
+                       \r
+                       long elapsed = System.nanoTime()-start;\r
+                       boolean timeCondition = elapsed > test; \r
+\r
+                       if(doneAll || timeCondition) {\r
+                               \r
+                               spent += elapsed;\r
+                               \r
+                               if(DEBUG_STATUS)\r
+                                       System.err.println("Query collector used " + 1e-9*elapsed + "s total queries: " + size + " bound queries: " + bound + " spent: " + (double)spent*1e-9);\r
+                               \r
+                               return;\r
+                               \r
+                       }\r
+\r
+                       // Iterate all entries and update sets\r
+                       if(!doneAll) {\r
+//                             long start2 = System.nanoTime();\r
+                               for(int i=0;i<COLLECT_N;i++) {\r
+                                       CacheEntryBase entry = support.iterate(Integer.MAX_VALUE);\r
+                                       if(entry == null) {\r
+                                               if(DEBUG) {\r
+                                                       System.err.println("finished iteration");\r
+                                                       System.err.println("-moreAll=" + moreAll);\r
+                                               }\r
+                                               if(moreAll < 1000) {\r
+                                                       doneAll = true;\r
+                                                       propagate = false;\r
+                                               }\r
+                                               moreAll = 0;\r
+                                               break;\r
+                                       }\r
+                                       \r
+                                       CacheEntry parent = entry.getFirstParent(queryProcessor);\r
+                                       if(parent == null) {\r
+                                               \r
+                                               boolean collected = tryCollect(entry);\r
+                                               if(!collected) {\r
+                                                       entry.setLevel((short)0);\r
+                                               }\r
+                                               \r
+                                       } else {\r
+\r
+                                               parent = entry.pruneFirstParents();\r
+                                               if(parent == null) {\r
+                                               \r
+                                                       boolean collected = tryCollect(entry);\r
+                                                       if(!collected) {\r
+                                                               entry.setLevel((short)0);\r
+                                                       }\r
+                                                       \r
+                                               } else {\r
+                                                       \r
+                                                       support.setLevel(entry, parent.getLevel() + 1);\r
+                                                       \r
+                                               }\r
+                                               \r
+                                       }\r
+                                       \r
+                                       int status = entry.getGCStatus(); \r
+                                       if((status & CacheEntry.HAS_BEEN_BOUND) == 0) {\r
+                                               \r
+                                               if(parent != null && !parent.isDiscarded()) {\r
+                                                       if((parent.getGCStatus() & CacheEntry.HAS_BEEN_BOUND) != 0) {\r
+                                                               queryProcessor.boundQueries++;\r
+                                                               entry.setGCStatusFlag(CacheEntry.HAS_BEEN_BOUND, true);\r
+                                                       }\r
+                                               }\r
+\r
+                                               if(queryProcessor.hasListenerAfterDisposing(entry)) {\r
+                                                       if((status & CacheEntry.HAS_BEEN_BOUND) == 0) {\r
+                                                               queryProcessor.boundQueries++;\r
+                                                               entry.setGCStatusFlag(CacheEntry.HAS_BEEN_BOUND, true);\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                                       \r
+                               }\r
+                       }\r
+\r
+               }\r
+\r
+       }\r
+\r
+       private boolean tryCollect(CacheEntry entry) {\r
+               if (!queryProcessor.hasListenerAfterDisposing(entry))\r
+                       if(entry.shouldBeCollected()) {\r
+                               queryProcessor.removeQuery(entry);\r
+                               support.remove();\r
+                               propagate = true;\r
+                               moreAll++;\r
+                               doneAll = false;\r
+                               return true;\r
+                       }\r
+               return false;\r
+       }\r
+\r
+       private void start() {\r
+               moreAll = 1;\r
+               doneAll = false;\r
+       }\r
+\r
+}
\ No newline at end of file