]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 package org.simantics.db.impl.query;\r
2 \r
3 import org.simantics.db.impl.query.QueryProcessor.QueryCollectorSupport;\r
4 \r
5 class QueryCollectorImpl implements QueryProcessor.QueryCollector {\r
6         \r
7         private static final boolean DEBUG = false;\r
8         private static final boolean DEBUG_STATUS = false;\r
9 \r
10         private final QueryProcessor queryProcessor;\r
11 \r
12         final private QueryCollectorSupport support;\r
13 \r
14         /*\r
15          * Set to true: at end of iteration if moreAll is false\r
16          * Set to false: upon gc start and whenever a prospect is added.\r
17          * \r
18          */\r
19         boolean doneAll = false;\r
20         /*\r
21          * Set to true: upon gc start and whenever a prospect is added.\r
22          * Set to false: at end of entry iteration\r
23          * => if this is already false at end of entry iteration => no more work to be done\r
24          */\r
25         int moreAll = 0;\r
26         \r
27         /*\r
28          * Change propagation is in progress\r
29          */\r
30         boolean propagate = true;\r
31         \r
32         \r
33         private static final int COLLECT_N = 1000;\r
34         \r
35         private long spent = 0;\r
36         \r
37         QueryCollectorImpl(QueryProcessor queryProcessor, QueryCollectorSupport support) {\r
38                 this.queryProcessor = queryProcessor;\r
39                 this.support = support;\r
40         }\r
41         \r
42         @Override\r
43         public void collect(int youngTarget, int allowedTimeInMs) {\r
44 \r
45                 long start = System.nanoTime();\r
46 \r
47                 // Refresh current size\r
48                 int size = support.calculateCurrentSize();\r
49                 int bound = queryProcessor.boundQueries;\r
50                 int young = size - bound;\r
51                 int youngPct = size > 0 ? 100*young / size : 0;\r
52                 \r
53                 // Initialize support for new run\r
54                 // If support returns 0 we are starting from 0\r
55                 if(support.start(youngTarget == 0)) {\r
56                         \r
57                         moreAll = 0;\r
58 \r
59                         // We monitor all prospects here\r
60                         CacheEntryBase prospect = support.iterate(0);\r
61                         while(prospect != null) {\r
62                                 if(prospect.isDiscarded()) {\r
63                                         support.remove();\r
64                                         propagate = true;\r
65                                 } else {\r
66                                         CacheEntry parent = prospect.getFirstParent(queryProcessor);\r
67                                         if(parent == null) {\r
68                                                 tryCollect(prospect);\r
69                                         } else {\r
70                                                 support.setLevel(prospect, parent.getLevel() + 1);\r
71                                         }\r
72                                 }\r
73                                 prospect = support.iterate(0);\r
74                         }\r
75 \r
76                         // If no prospects were collected and most of the queries are old we can stop here\r
77                         if(!propagate && youngPct < youngTarget) {\r
78 //                              System.err.println("collect2 skipped");\r
79 //                              System.err.println("-size=" + size);\r
80 //                              System.err.println("-young=" + young);\r
81                                 return; \r
82                         }\r
83                         \r
84                 }\r
85                 \r
86                 long test = (long)allowedTimeInMs*1000000;\r
87 \r
88                 start();\r
89                 \r
90                 while(true) {\r
91                         \r
92                         size = support.getCurrentSize();\r
93                         bound = queryProcessor.boundQueries;\r
94                         \r
95                         long elapsed = System.nanoTime()-start;\r
96                         boolean timeCondition = elapsed > test; \r
97 \r
98                         if(doneAll || timeCondition) {\r
99                                 \r
100                                 spent += elapsed;\r
101                                 \r
102                                 if(DEBUG_STATUS)\r
103                                         System.err.println("Query collector used " + 1e-9*elapsed + "s total queries: " + size + " bound queries: " + bound + " spent: " + (double)spent*1e-9);\r
104                                 \r
105                                 return;\r
106                                 \r
107                         }\r
108 \r
109                         // Iterate all entries and update sets\r
110                         if(!doneAll) {\r
111 //                              long start2 = System.nanoTime();\r
112                                 for(int i=0;i<COLLECT_N;i++) {\r
113                                         CacheEntryBase entry = support.iterate(Integer.MAX_VALUE);\r
114                                         if(entry == null) {\r
115                                                 if(DEBUG) {\r
116                                                         System.err.println("finished iteration");\r
117                                                         System.err.println("-moreAll=" + moreAll);\r
118                                                 }\r
119                                                 if(moreAll < 1000) {\r
120                                                         doneAll = true;\r
121                                                         propagate = false;\r
122                                                 }\r
123                                                 moreAll = 0;\r
124                                                 break;\r
125                                         }\r
126                                         \r
127                                         CacheEntry parent = entry.getFirstParent(queryProcessor);\r
128                                         if(parent == null) {\r
129                                                 \r
130                                                 boolean collected = tryCollect(entry);\r
131                                                 if(!collected) {\r
132                                                         entry.setLevel((short)0);\r
133                                                 }\r
134                                                 \r
135                                         } else {\r
136 \r
137                                                 parent = entry.pruneFirstParents();\r
138                                                 if(parent == null) {\r
139                                                 \r
140                                                         boolean collected = tryCollect(entry);\r
141                                                         if(!collected) {\r
142                                                                 entry.setLevel((short)0);\r
143                                                         }\r
144                                                         \r
145                                                 } else {\r
146                                                         \r
147                                                         support.setLevel(entry, parent.getLevel() + 1);\r
148                                                         \r
149                                                 }\r
150                                                 \r
151                                         }\r
152                                         \r
153                                         int status = entry.getGCStatus(); \r
154                                         if((status & CacheEntry.HAS_BEEN_BOUND) == 0) {\r
155                                                 \r
156                                                 if(parent != null && !parent.isDiscarded()) {\r
157                                                         if((parent.getGCStatus() & CacheEntry.HAS_BEEN_BOUND) != 0) {\r
158                                                                 queryProcessor.boundQueries++;\r
159                                                                 entry.setGCStatusFlag(CacheEntry.HAS_BEEN_BOUND, true);\r
160                                                         }\r
161                                                 }\r
162 \r
163                                                 if(queryProcessor.hasListenerAfterDisposing(entry)) {\r
164                                                         if((status & CacheEntry.HAS_BEEN_BOUND) == 0) {\r
165                                                                 queryProcessor.boundQueries++;\r
166                                                                 entry.setGCStatusFlag(CacheEntry.HAS_BEEN_BOUND, true);\r
167                                                         }\r
168                                                 }\r
169                                         }\r
170                                         \r
171                                 }\r
172                         }\r
173 \r
174                 }\r
175 \r
176         }\r
177 \r
178         private boolean tryCollect(CacheEntry entry) {\r
179                 if (!queryProcessor.hasListenerAfterDisposing(entry))\r
180                         if(entry.shouldBeCollected()) {\r
181                                 queryProcessor.removeQuery(entry);\r
182                                 support.remove();\r
183                                 propagate = true;\r
184                                 moreAll++;\r
185                                 doneAll = false;\r
186                                 return true;\r
187                         }\r
188                 return false;\r
189         }\r
190 \r
191         private void start() {\r
192                 moreAll = 1;\r
193                 doneAll = false;\r
194         }\r
195 \r
196 }