1 package org.simantics.db.impl.query;
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.IdentityHashMap;
9 import org.simantics.databoard.util.IdentityHashSet;
10 import org.simantics.db.common.exception.DebugException;
11 import org.simantics.db.impl.DebugPolicy;
12 import org.simantics.db.impl.query.QueryProcessor.QueryCollectorSupport;
13 import org.simantics.utils.Development;
15 class QueryCollectorImpl2 implements QueryProcessor.QueryCollector {
17 private final QueryProcessor queryProcessor;
19 final private QueryCollectorSupport support;
21 private int lastKnownFixedSize = 0;
23 QueryCollectorImpl2(QueryProcessor queryProcessor, QueryCollectorSupport support) {
24 this.queryProcessor = queryProcessor;
25 this.support = support;
28 private boolean findCollectables(CacheEntry entry, Map<CacheEntry, Boolean> collectables, ArrayList<CacheEntry> result) {
30 if (entry.isDiscarded()) {
31 if(DebugPolicy.COLLECT && DebugPolicy.VERBOSE)
32 System.out.println("GC: discarded entry " + entry);
36 if (entry.isPending()) {
37 if(DebugPolicy.COLLECT && DebugPolicy.VERBOSE)
38 System.out.println("GC: pending entry " + entry + " was not collected.");
39 collectables.remove(entry);
43 if (this.queryProcessor.hasListenerAfterDisposing(entry)) {
44 if (DebugPolicy.COLLECT && DebugPolicy.VERBOSE) {
45 System.out.println("GC: listened entry " + entry + " was not collected. Entry=" + entry);
47 collectables.remove(entry);
51 for (CacheEntry parent : entry.getParents(queryProcessor)) {
53 boolean parentIsCollectable = false;
55 if (!collectables.containsKey(parent)) {
56 collectables.put(parent, true);
57 parentIsCollectable = findCollectables(parent, collectables, result);
59 parentIsCollectable = collectables.get(parent);
62 if(!parentIsCollectable) {
63 if(DebugPolicy.COLLECT && DebugPolicy.VERBOSE)
64 System.out.println("GC: due to bound parent " + parent + " the entry + " + entry + " was not collected.");
65 collectables.remove(entry);
71 if(entry.shouldBeCollected()) {
72 // This can be collected
81 private List<CacheEntry> findCollectables() {
83 ArrayList<CacheEntry> result = new ArrayList<CacheEntry>();
85 IdentityHashMap<CacheEntry, Boolean> collectables = new IdentityHashMap<CacheEntry, Boolean>();
86 Collection<CacheEntry> rootList = support.getRootList();
87 for (CacheEntry entry : rootList) {
88 if(!collectables.containsKey(entry)) {
89 collectables.put(entry, true);
90 findCollectables(entry, collectables, result);
94 if(Development.DEVELOPMENT) {
95 IdentityHashSet<CacheEntry> set = new IdentityHashSet<CacheEntry>();
96 for(CacheEntry entry : result) {
97 if(!set.add(entry)) throw new IllegalStateException();
105 private void doCollect(int currentSize, int maxNumberOfCollectableQueries) {
107 List<CacheEntry> collectables = findCollectables();
109 // Compute amount of free queries
110 int freeCount = collectables.size();
112 if(DebugPolicy.COLLECT)
113 System.out.println("collector found " + freeCount + " free queries.");
115 lastKnownFixedSize = currentSize - freeCount;
117 // No need to collect
118 if(freeCount < maxNumberOfCollectableQueries) return;
120 int target = freeCount - maxNumberOfCollectableQueries/2;
122 if(DebugPolicy.COLLECT)
123 System.out.println("collector removes " + target + " free queries.");
125 for(CacheEntry entry : collectables) {
126 if(queryProcessor.removeQuery(entry))
127 if(--target < 0) break;
130 // Prune discarded parents
131 ArrayList<CacheEntry> removals = new ArrayList<CacheEntry>();
132 for (CacheEntry entry : support.allCaches().toCollection()) {
133 for(CacheEntry p : entry.getParents(queryProcessor)) {
134 if(p.isDiscarded()) removals.add(p);
136 for(CacheEntry r : removals) {
137 entry.removeParent(r);
142 if(DebugPolicy.COLLECT) {
143 System.out.println("collect found " + freeCount + " collectable entries.");
151 public void collect(int youngTarget, int maxAllowedTimeInMs) {
155 int current = support.calculateCurrentSize();
157 if(DebugPolicy.COLLECT)
158 new DebugException("checking the need for collecting queries (current=" + current + " , lastKnownFixedSize=" + lastKnownFixedSize + " max free=" + 0 + ")").printStackTrace();
160 QueryProcessor.collecting = true;
162 long start = System.nanoTime();
164 doCollect(current, 0);
166 if(DebugPolicy.COLLECT)
167 System.out.println("collect finished with " + support.calculateCurrentSize() + " entries (lastKnownFixedSize=" + lastKnownFixedSize + ").");
169 long duration = System.nanoTime() - start;
171 if(DebugPolicy.COLLECT)
172 System.err.println("Collect took " + 1e-9*duration + "s.");
174 } catch (Throwable t) {
178 QueryProcessor.collecting = false;