1 package org.simantics.db.impl.query;
3 import org.simantics.db.impl.query.QueryProcessor.QueryCollectorSupport;
5 class QueryCollectorImpl implements QueryProcessor.QueryCollector {
7 private static final boolean DEBUG = false;
8 private static final boolean DEBUG_STATUS = false;
10 private final QueryProcessor queryProcessor;
12 final private QueryCollectorSupport support;
15 * Set to true: at end of iteration if moreAll is false
16 * Set to false: upon gc start and whenever a prospect is added.
19 boolean doneAll = false;
21 * Set to true: upon gc start and whenever a prospect is added.
22 * Set to false: at end of entry iteration
23 * => if this is already false at end of entry iteration => no more work to be done
28 * Change propagation is in progress
30 boolean propagate = true;
33 private static final int COLLECT_N = 1000;
35 private long spent = 0;
37 QueryCollectorImpl(QueryProcessor queryProcessor, QueryCollectorSupport support) {
38 this.queryProcessor = queryProcessor;
39 this.support = support;
43 public void collect(int youngTarget, int allowedTimeInMs) {
45 long start = System.nanoTime();
47 // Refresh current size
48 int size = support.calculateCurrentSize();
49 int bound = queryProcessor.boundQueries;
50 int young = size - bound;
51 int youngPct = size > 0 ? 100*young / size : 0;
53 // Initialize support for new run
54 // If support returns 0 we are starting from 0
55 if(support.start(youngTarget == 0)) {
59 // We monitor all prospects here
60 CacheEntryBase prospect = support.iterate(0);
61 while(prospect != null) {
62 if(prospect.isDiscarded()) {
66 CacheEntry parent = prospect.getFirstParent(queryProcessor);
70 support.setLevel(prospect, parent.getLevel() + 1);
73 prospect = support.iterate(0);
76 // If no prospects were collected and most of the queries are old we can stop here
77 if(!propagate && youngPct < youngTarget) {
78 // System.err.println("collect2 skipped");
79 // System.err.println("-size=" + size);
80 // System.err.println("-young=" + young);
86 long test = (long)allowedTimeInMs*1000000;
92 size = support.getCurrentSize();
93 bound = queryProcessor.boundQueries;
95 long elapsed = System.nanoTime()-start;
96 boolean timeCondition = elapsed > test;
98 if(doneAll || timeCondition) {
103 System.err.println("Query collector used " + 1e-9*elapsed + "s total queries: " + size + " bound queries: " + bound + " spent: " + (double)spent*1e-9);
109 // Iterate all entries and update sets
111 // long start2 = System.nanoTime();
112 for(int i=0;i<COLLECT_N;i++) {
113 CacheEntryBase entry = support.iterate(Integer.MAX_VALUE);
116 System.err.println("finished iteration");
117 System.err.println("-moreAll=" + moreAll);
127 CacheEntry parent = entry.getFirstParent(queryProcessor);
130 boolean collected = tryCollect(entry);
132 entry.setLevel((short)0);
137 parent = entry.pruneFirstParents();
140 boolean collected = tryCollect(entry);
142 entry.setLevel((short)0);
147 support.setLevel(entry, parent.getLevel() + 1);
153 int status = entry.getGCStatus();
154 if((status & CacheEntry.HAS_BEEN_BOUND) == 0) {
156 if(parent != null && !parent.isDiscarded()) {
157 if((parent.getGCStatus() & CacheEntry.HAS_BEEN_BOUND) != 0) {
158 queryProcessor.boundQueries++;
159 entry.setGCStatusFlag(CacheEntry.HAS_BEEN_BOUND, true);
163 if(queryProcessor.hasListenerAfterDisposing(entry)) {
164 if((status & CacheEntry.HAS_BEEN_BOUND) == 0) {
165 queryProcessor.boundQueries++;
166 entry.setGCStatusFlag(CacheEntry.HAS_BEEN_BOUND, true);
178 private boolean tryCollect(CacheEntry entry) {
179 if (!queryProcessor.hasListenerAfterDisposing(entry))
180 if(entry.shouldBeCollected()) {
181 queryProcessor.removeQuery(entry);
191 private void start() {