]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl2.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / QueryCollectorImpl2.java
diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl2.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl2.java
new file mode 100644 (file)
index 0000000..b964854
--- /dev/null
@@ -0,0 +1,184 @@
+package org.simantics.db.impl.query;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.IdentityHashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.simantics.databoard.util.IdentityHashSet;\r
+import org.simantics.db.common.exception.DebugException;\r
+import org.simantics.db.impl.DebugPolicy;\r
+import org.simantics.db.impl.query.QueryProcessor.QueryCollectorSupport;\r
+import org.simantics.utils.Development;\r
+\r
+class QueryCollectorImpl2 implements QueryProcessor.QueryCollector {\r
+\r
+       private final QueryProcessor queryProcessor;\r
+\r
+       final private QueryCollectorSupport support;\r
+\r
+       private int lastKnownFixedSize = 0;\r
+\r
+       QueryCollectorImpl2(QueryProcessor queryProcessor, QueryCollectorSupport support) {\r
+               this.queryProcessor = queryProcessor;\r
+               this.support = support;\r
+       }\r
+\r
+       private boolean findCollectables(CacheEntry entry, Map<CacheEntry, Boolean> collectables, ArrayList<CacheEntry> result) {\r
+\r
+               if (entry.isDiscarded()) {\r
+                       if(DebugPolicy.COLLECT && DebugPolicy.VERBOSE)\r
+                               System.out.println("GC: discarded entry " + entry);\r
+                       return true;\r
+               }\r
+\r
+               if (entry.isPending()) {\r
+                       if(DebugPolicy.COLLECT && DebugPolicy.VERBOSE)\r
+                               System.out.println("GC: pending entry " + entry + " was not collected.");\r
+                       collectables.remove(entry);\r
+                       return false;\r
+               }\r
+\r
+               if (this.queryProcessor.hasListenerAfterDisposing(entry)) {\r
+                       if (DebugPolicy.COLLECT && DebugPolicy.VERBOSE) {\r
+                               System.out.println("GC: listened entry " + entry + " was not collected. Entry=" + entry);\r
+                       }\r
+                       collectables.remove(entry);\r
+                       return false;\r
+               }\r
+\r
+               for (CacheEntry parent : entry.getParents(queryProcessor)) {\r
+\r
+                       boolean parentIsCollectable = false;\r
+\r
+                       if (!collectables.containsKey(parent)) {\r
+                               collectables.put(parent, true);\r
+                               parentIsCollectable = findCollectables(parent, collectables, result);\r
+                       } else {\r
+                               parentIsCollectable = collectables.get(parent);\r
+                       }\r
+\r
+                       if(!parentIsCollectable) {\r
+                               if(DebugPolicy.COLLECT && DebugPolicy.VERBOSE)\r
+                                       System.out.println("GC: due to bound parent " + parent + " the entry + " + entry + " was not collected.");\r
+                               collectables.remove(entry);\r
+                               return false;\r
+                       }\r
+\r
+               }\r
+\r
+               if(entry.shouldBeCollected()) {\r
+                       // This can be collected\r
+                       result.add(entry);\r
+                       return true;\r
+               } else {\r
+                       return false;\r
+               }\r
+\r
+       }\r
+\r
+       private List<CacheEntry> findCollectables() {\r
+\r
+               ArrayList<CacheEntry> result = new ArrayList<CacheEntry>();\r
+\r
+               IdentityHashMap<CacheEntry, Boolean> collectables = new IdentityHashMap<CacheEntry, Boolean>();\r
+               Collection<CacheEntry> rootList = support.getRootList();\r
+               for (CacheEntry entry : rootList) {\r
+                       if(!collectables.containsKey(entry)) {\r
+                               collectables.put(entry, true);\r
+                               findCollectables(entry, collectables, result);\r
+                       }\r
+               }\r
+\r
+               if(Development.DEVELOPMENT) {\r
+                       IdentityHashSet<CacheEntry> set = new IdentityHashSet<CacheEntry>();\r
+                       for(CacheEntry entry : result) {\r
+                               if(!set.add(entry)) throw new IllegalStateException();\r
+                       }\r
+               }\r
+\r
+               return result;\r
+\r
+       }\r
+\r
+       private void doCollect(int currentSize, int maxNumberOfCollectableQueries) {\r
+\r
+               List<CacheEntry> collectables = findCollectables();\r
+\r
+               // Compute amount of free queries\r
+               int freeCount = collectables.size();\r
+\r
+               if(DebugPolicy.COLLECT)\r
+                       System.out.println("collector found " + freeCount + " free queries.");\r
+\r
+               lastKnownFixedSize = currentSize - freeCount;\r
+\r
+               // No need to collect\r
+               if(freeCount < maxNumberOfCollectableQueries) return;\r
+\r
+               int target = freeCount - maxNumberOfCollectableQueries/2;\r
+\r
+               if(DebugPolicy.COLLECT)\r
+                       System.out.println("collector removes " + target + " free queries.");\r
+\r
+               for(CacheEntry entry : collectables) {\r
+                       if(queryProcessor.removeQuery(entry))\r
+                               if(--target < 0) break;\r
+               }\r
+\r
+               // Prune discarded parents\r
+               ArrayList<CacheEntry> removals = new ArrayList<CacheEntry>();\r
+               for (CacheEntry entry : support.allCaches().toCollection()) {\r
+                       for(CacheEntry p : entry.getParents(queryProcessor)) {\r
+                               if(p.isDiscarded()) removals.add(p);\r
+                       }\r
+                       for(CacheEntry r : removals) {\r
+                               entry.removeParent(r);\r
+                       }\r
+                       removals.clear();\r
+               }\r
+\r
+               if(DebugPolicy.COLLECT) {\r
+                       System.out.println("collect found " + freeCount + " collectable entries.");\r
+               }\r
+\r
+               return;\r
+\r
+       }\r
+\r
+       @Override\r
+       public void collect(int youngTarget, int maxAllowedTimeInMs) {\r
+\r
+               try {\r
+\r
+                       int current = support.calculateCurrentSize();\r
+\r
+                       if(DebugPolicy.COLLECT)\r
+                               new DebugException("checking the need for collecting queries (current=" + current + " , lastKnownFixedSize=" + lastKnownFixedSize + " max free=" + 0 + ")").printStackTrace();\r
+\r
+                       QueryProcessor.collecting = true;\r
+\r
+                       long start = System.nanoTime();\r
+\r
+                       doCollect(current, 0);\r
+\r
+                       if(DebugPolicy.COLLECT)\r
+                               System.out.println("collect finished with " + support.calculateCurrentSize() + " entries (lastKnownFixedSize=" + lastKnownFixedSize + ").");\r
+\r
+                       long duration = System.nanoTime() - start;\r
+\r
+                       if(DebugPolicy.COLLECT)\r
+                               System.err.println("Collect took " + 1e-9*duration + "s.");\r
+\r
+               } catch (Throwable t) {\r
+                       t.printStackTrace();\r
+               }\r
+\r
+               QueryProcessor.collecting = false;\r
+\r
+\r
+       }\r
+\r
+\r
+}
\ No newline at end of file