package org.simantics.db.impl.query; import org.simantics.db.impl.query.QueryProcessor.QueryCollectorSupport; class QueryCollectorImpl implements QueryProcessor.QueryCollector { private static final boolean DEBUG = false; private static final boolean DEBUG_STATUS = false; private final QueryProcessor queryProcessor; final private QueryCollectorSupport support; /* * Set to true: at end of iteration if moreAll is false * Set to false: upon gc start and whenever a prospect is added. * */ boolean doneAll = false; /* * Set to true: upon gc start and whenever a prospect is added. * Set to false: at end of entry iteration * => if this is already false at end of entry iteration => no more work to be done */ int moreAll = 0; /* * Change propagation is in progress */ boolean propagate = true; private static final int COLLECT_N = 1000; private long spent = 0; QueryCollectorImpl(QueryProcessor queryProcessor, QueryCollectorSupport support) { this.queryProcessor = queryProcessor; this.support = support; } @Override public void collect(int youngTarget, int allowedTimeInMs) { // Flush listener registrations to prevent the collector from trashing // listeners that are still queued up waiting to be registered. queryProcessor.listening.sync(); long start = System.nanoTime(); // Refresh current size int size = support.calculateCurrentSize(); int bound = queryProcessor.boundQueries; int young = size - bound; int youngPct = size > 0 ? 100*young / size : 0; // Initialize support for new run // If support returns 0 we are starting from 0 if(support.start(youngTarget == 0)) { moreAll = 0; // We monitor all prospects here CacheEntryBase prospect = support.iterate(0); while(prospect != null) { if(prospect.isDiscarded()) { support.remove(); propagate = true; } else { CacheEntry parent = prospect.getFirstParent(queryProcessor); if(parent == null) { tryCollect(prospect); } else { support.setLevel(prospect, parent.getLevel() + 1); } } prospect = support.iterate(0); } // If no prospects were collected and most of the queries are old we can stop here if(!propagate && youngPct < youngTarget) { // System.err.println("collect2 skipped"); // System.err.println("-size=" + size); // System.err.println("-young=" + young); return; } } long test = (long)allowedTimeInMs*1000000; start(); while(true) { size = support.getCurrentSize(); bound = queryProcessor.boundQueries; long elapsed = System.nanoTime()-start; boolean timeCondition = elapsed > test; if(doneAll || timeCondition) { spent += elapsed; if(DEBUG_STATUS) System.err.println("Query collector used " + 1e-9*elapsed + "s total queries: " + size + " bound queries: " + bound + " spent: " + (double)spent*1e-9); return; } // Iterate all entries and update sets if(!doneAll) { // long start2 = System.nanoTime(); for(int i=0;i