6111 |
29 Jan 21 |
nicklas |
1 |
package net.sf.basedb.varsearch.service; |
6111 |
29 Jan 21 |
nicklas |
2 |
|
6111 |
29 Jan 21 |
nicklas |
3 |
import java.io.File; |
6111 |
29 Jan 21 |
nicklas |
4 |
import java.io.IOException; |
6111 |
29 Jan 21 |
nicklas |
5 |
import java.util.Collection; |
6248 |
25 May 21 |
nicklas |
6 |
import java.util.LinkedHashMap; |
6112 |
02 Feb 21 |
nicklas |
7 |
import java.util.List; |
6111 |
29 Jan 21 |
nicklas |
8 |
import java.util.Map; |
6167 |
09 Mar 21 |
nicklas |
9 |
import java.util.Set; |
6111 |
29 Jan 21 |
nicklas |
10 |
import java.util.TimerTask; |
6141 |
19 Feb 21 |
nicklas |
11 |
import java.util.concurrent.Executors; |
6111 |
29 Jan 21 |
nicklas |
12 |
|
6111 |
29 Jan 21 |
nicklas |
13 |
import org.slf4j.LoggerFactory; |
6111 |
29 Jan 21 |
nicklas |
14 |
|
6111 |
29 Jan 21 |
nicklas |
15 |
import net.sf.basedb.clients.web.extensions.service.ServiceControllerAction; |
6111 |
29 Jan 21 |
nicklas |
16 |
import net.sf.basedb.clients.web.extensions.service.Services; |
6111 |
29 Jan 21 |
nicklas |
17 |
import net.sf.basedb.core.Application; |
6111 |
29 Jan 21 |
nicklas |
18 |
import net.sf.basedb.core.DbControl; |
6111 |
29 Jan 21 |
nicklas |
19 |
import net.sf.basedb.core.Include; |
6111 |
29 Jan 21 |
nicklas |
20 |
import net.sf.basedb.core.ItemList; |
6111 |
29 Jan 21 |
nicklas |
21 |
import net.sf.basedb.core.ItemQuery; |
6111 |
29 Jan 21 |
nicklas |
22 |
import net.sf.basedb.core.RawBioAssay; |
6111 |
29 Jan 21 |
nicklas |
23 |
import net.sf.basedb.core.SessionControl; |
6111 |
29 Jan 21 |
nicklas |
24 |
import net.sf.basedb.core.SystemItems; |
6111 |
29 Jan 21 |
nicklas |
25 |
import net.sf.basedb.core.User; |
6374 |
07 Sep 21 |
nicklas |
26 |
import net.sf.basedb.core.query.Expressions; |
6374 |
07 Sep 21 |
nicklas |
27 |
import net.sf.basedb.core.query.Hql; |
6374 |
07 Sep 21 |
nicklas |
28 |
import net.sf.basedb.core.query.Restrictions; |
6111 |
29 Jan 21 |
nicklas |
29 |
import net.sf.basedb.util.extensions.Extension; |
7074 |
24 Mar 23 |
nicklas |
30 |
import net.sf.basedb.util.extensions.logging.ExtensionsLog; |
7074 |
24 Mar 23 |
nicklas |
31 |
import net.sf.basedb.util.extensions.logging.ExtensionsLogger; |
6145 |
23 Feb 21 |
nicklas |
32 |
import net.sf.basedb.varsearch.dao.Annotationtype; |
6112 |
02 Feb 21 |
nicklas |
33 |
import net.sf.basedb.varsearch.dao.Datafiletype; |
6111 |
29 Jan 21 |
nicklas |
34 |
import net.sf.basedb.varsearch.dao.Itemlist; |
6374 |
07 Sep 21 |
nicklas |
35 |
import net.sf.basedb.varsearch.index.AnyToAnyVcfLocator; |
6374 |
07 Sep 21 |
nicklas |
36 |
import net.sf.basedb.varsearch.index.DatafileVcfLocator; |
6132 |
16 Feb 21 |
nicklas |
37 |
import net.sf.basedb.varsearch.index.LuceneIndex; |
6541 |
17 Jan 22 |
nicklas |
38 |
import net.sf.basedb.varsearch.index.VariantCallIndex; |
6167 |
09 Mar 21 |
nicklas |
39 |
import net.sf.basedb.varsearch.index.LuceneIndex.AutoUpdate; |
6168 |
12 Mar 21 |
nicklas |
40 |
import net.sf.basedb.varsearch.index.LuceneIndex.FullRebuildRunnable; |
6168 |
12 Mar 21 |
nicklas |
41 |
import net.sf.basedb.varsearch.index.LuceneIndex.QueryThreadFactory; |
6168 |
12 Mar 21 |
nicklas |
42 |
import net.sf.basedb.varsearch.index.LuceneIndex.Status; |
6541 |
17 Jan 22 |
nicklas |
43 |
import net.sf.basedb.varsearch.index.OncoArrayIndex; |
6111 |
29 Jan 21 |
nicklas |
44 |
|
6111 |
29 Jan 21 |
nicklas |
45 |
public class VarSearchService |
6111 |
29 Jan 21 |
nicklas |
46 |
{ |
7074 |
24 Mar 23 |
nicklas |
47 |
/** |
7074 |
24 Mar 23 |
nicklas |
The ID of the service extension. |
7074 |
24 Mar 23 |
nicklas |
@since 1.8 |
7074 |
24 Mar 23 |
nicklas |
50 |
*/ |
7074 |
24 Mar 23 |
nicklas |
51 |
public static final String ID = "net.sf.basedb.varsearch.service"; |
6111 |
29 Jan 21 |
nicklas |
52 |
|
7074 |
24 Mar 23 |
nicklas |
53 |
private static final ExtensionsLogger logger = |
7074 |
24 Mar 23 |
nicklas |
54 |
ExtensionsLog.getLogger(ID, true).wrap(LoggerFactory.getLogger(VarSearchService.class)); |
6111 |
29 Jan 21 |
nicklas |
55 |
|
6111 |
29 Jan 21 |
nicklas |
// At least 15 minutes between index updates (30 seconds when debugging) |
7074 |
24 Mar 23 |
nicklas |
57 |
private static final long MIN_WAIT_INTERVAL_NORMAL = 900 * 1000; |
7074 |
24 Mar 23 |
nicklas |
58 |
private static final long MIN_WAIT_INTERVAL_DEBUG = 30 * 1000; |
6111 |
29 Jan 21 |
nicklas |
59 |
|
6140 |
19 Feb 21 |
nicklas |
// If the number of raw bioassays is less than this, we wait a bit longer |
6140 |
19 Feb 21 |
nicklas |
// to see if the list is filled with more... |
6140 |
19 Feb 21 |
nicklas |
62 |
private static final int EXTENDED_WAIT_LIMIT = 24; |
6140 |
19 Feb 21 |
nicklas |
// Max time to wait for more until we index (4 hours; 95 seconds when debugging) |
7074 |
24 Mar 23 |
nicklas |
64 |
private static final long MAX_EXTENDED_WAIT_NORMAL = 4 * 3600 * 1000; |
7074 |
24 Mar 23 |
nicklas |
65 |
private static final long MAX_EXTENDED_WAIT_DEBUG = 95 * 1000; |
6111 |
29 Jan 21 |
nicklas |
66 |
|
6111 |
29 Jan 21 |
nicklas |
// The singleton instance of the service |
6111 |
29 Jan 21 |
nicklas |
68 |
private static VarSearchService instance = null; |
6111 |
29 Jan 21 |
nicklas |
69 |
|
6111 |
29 Jan 21 |
nicklas |
70 |
/** |
6111 |
29 Jan 21 |
nicklas |
Get the singleton instance of the service. If the service has |
6111 |
29 Jan 21 |
nicklas |
not been created yet it is created at this time. |
6111 |
29 Jan 21 |
nicklas |
73 |
*/ |
6111 |
29 Jan 21 |
nicklas |
74 |
public static final VarSearchService getInstance() |
6111 |
29 Jan 21 |
nicklas |
75 |
{ |
6111 |
29 Jan 21 |
nicklas |
76 |
if (instance == null) |
6111 |
29 Jan 21 |
nicklas |
77 |
{ |
6111 |
29 Jan 21 |
nicklas |
78 |
synchronized (VarSearchService.class) |
6111 |
29 Jan 21 |
nicklas |
79 |
{ |
6111 |
29 Jan 21 |
nicklas |
80 |
if (instance == null) |
6111 |
29 Jan 21 |
nicklas |
81 |
{ |
6111 |
29 Jan 21 |
nicklas |
82 |
VarSearchService tmp = new VarSearchService(); |
6111 |
29 Jan 21 |
nicklas |
83 |
instance = tmp; |
6111 |
29 Jan 21 |
nicklas |
84 |
} |
6111 |
29 Jan 21 |
nicklas |
85 |
} |
6111 |
29 Jan 21 |
nicklas |
86 |
} |
6111 |
29 Jan 21 |
nicklas |
87 |
|
6111 |
29 Jan 21 |
nicklas |
// Keep the session control alive |
6111 |
29 Jan 21 |
nicklas |
89 |
if (instance.rootSc != null) instance.rootSc.updateLastAccess(); |
6111 |
29 Jan 21 |
nicklas |
90 |
|
6111 |
29 Jan 21 |
nicklas |
91 |
return instance; |
6111 |
29 Jan 21 |
nicklas |
92 |
} |
6111 |
29 Jan 21 |
nicklas |
93 |
|
6111 |
29 Jan 21 |
nicklas |
94 |
|
6111 |
29 Jan 21 |
nicklas |
95 |
private volatile boolean isRunning; |
6111 |
29 Jan 21 |
nicklas |
96 |
private SessionControl systemSc; |
6111 |
29 Jan 21 |
nicklas |
97 |
private Extension<ServiceControllerAction> ext; |
6111 |
29 Jan 21 |
nicklas |
98 |
private SessionControl rootSc; |
6111 |
29 Jan 21 |
nicklas |
99 |
private TimerTask timer; |
6111 |
29 Jan 21 |
nicklas |
100 |
|
6111 |
29 Jan 21 |
nicklas |
// Time when last check for new data |
6111 |
29 Jan 21 |
nicklas |
102 |
private volatile long lastAutoUpdateCheck; |
6111 |
29 Jan 21 |
nicklas |
// If flag is set, we force check for new date |
6111 |
29 Jan 21 |
nicklas |
104 |
private volatile long forceUpdateCheck; |
6111 |
29 Jan 21 |
nicklas |
105 |
|
6111 |
29 Jan 21 |
nicklas |
// Map Index ID -> LuceneIndex |
6111 |
29 Jan 21 |
nicklas |
107 |
private final Map<String, LuceneIndex> indexes; |
6111 |
29 Jan 21 |
nicklas |
108 |
|
6111 |
29 Jan 21 |
nicklas |
109 |
|
6111 |
29 Jan 21 |
nicklas |
110 |
private VarSearchService() |
6111 |
29 Jan 21 |
nicklas |
111 |
{ |
6248 |
25 May 21 |
nicklas |
112 |
indexes = new LinkedHashMap<>(); |
6111 |
29 Jan 21 |
nicklas |
113 |
} |
6111 |
29 Jan 21 |
nicklas |
114 |
|
6111 |
29 Jan 21 |
nicklas |
115 |
|
6111 |
29 Jan 21 |
nicklas |
116 |
/** |
6111 |
29 Jan 21 |
nicklas |
Is the service running or not? |
6111 |
29 Jan 21 |
nicklas |
118 |
*/ |
6111 |
29 Jan 21 |
nicklas |
119 |
public boolean isRunning() |
6111 |
29 Jan 21 |
nicklas |
120 |
{ |
6111 |
29 Jan 21 |
nicklas |
121 |
return isRunning; |
6111 |
29 Jan 21 |
nicklas |
122 |
} |
6111 |
29 Jan 21 |
nicklas |
123 |
|
6165 |
08 Mar 21 |
nicklas |
124 |
/** |
6168 |
12 Mar 21 |
nicklas |
Get the session control used for this service. |
6168 |
12 Mar 21 |
nicklas |
126 |
*/ |
6168 |
12 Mar 21 |
nicklas |
127 |
public SessionControl getRootSessionControl() |
6168 |
12 Mar 21 |
nicklas |
128 |
{ |
6168 |
12 Mar 21 |
nicklas |
129 |
return rootSc; |
6168 |
12 Mar 21 |
nicklas |
130 |
} |
6168 |
12 Mar 21 |
nicklas |
131 |
|
6168 |
12 Mar 21 |
nicklas |
132 |
/** |
6165 |
08 Mar 21 |
nicklas |
Get an index database by id. |
6165 |
08 Mar 21 |
nicklas |
134 |
*/ |
6165 |
08 Mar 21 |
nicklas |
135 |
public LuceneIndex getIndexById(String id) |
6165 |
08 Mar 21 |
nicklas |
136 |
{ |
6165 |
08 Mar 21 |
nicklas |
137 |
return indexes.get(id); |
6165 |
08 Mar 21 |
nicklas |
138 |
} |
6165 |
08 Mar 21 |
nicklas |
139 |
|
6165 |
08 Mar 21 |
nicklas |
140 |
/** |
6165 |
08 Mar 21 |
nicklas |
Get all index databases. |
6165 |
08 Mar 21 |
nicklas |
142 |
*/ |
6111 |
29 Jan 21 |
nicklas |
143 |
public Collection<LuceneIndex> getIndexes() |
6111 |
29 Jan 21 |
nicklas |
144 |
{ |
6111 |
29 Jan 21 |
nicklas |
145 |
return indexes.values(); |
6111 |
29 Jan 21 |
nicklas |
146 |
} |
6111 |
29 Jan 21 |
nicklas |
147 |
|
6111 |
29 Jan 21 |
nicklas |
148 |
/** |
6111 |
29 Jan 21 |
nicklas |
Start the service if it is not running. |
6111 |
29 Jan 21 |
nicklas |
150 |
*/ |
6111 |
29 Jan 21 |
nicklas |
151 |
synchronized void start(SessionControl systemSc, Extension<ServiceControllerAction> ext) |
6111 |
29 Jan 21 |
nicklas |
152 |
{ |
6111 |
29 Jan 21 |
nicklas |
153 |
if (isRunning) return; |
6111 |
29 Jan 21 |
nicklas |
154 |
|
6111 |
29 Jan 21 |
nicklas |
155 |
logger.debug("Starting Variant Indexing Service"); |
6111 |
29 Jan 21 |
nicklas |
156 |
|
6111 |
29 Jan 21 |
nicklas |
157 |
try |
6111 |
29 Jan 21 |
nicklas |
158 |
{ |
6111 |
29 Jan 21 |
nicklas |
159 |
this.systemSc = systemSc; |
6111 |
29 Jan 21 |
nicklas |
160 |
this.ext = ext; |
6111 |
29 Jan 21 |
nicklas |
161 |
this.rootSc = systemSc.impersonateLogin(SystemItems.getId(User.ROOT), "Variant Indexing Service"); |
6111 |
29 Jan 21 |
nicklas |
162 |
|
6111 |
29 Jan 21 |
nicklas |
// Initialize LuceneIndexe:s |
6111 |
29 Jan 21 |
nicklas |
164 |
File dbDir = new File(Application.getUserFilesDirectory(), "lucene.db"); |
6111 |
29 Jan 21 |
nicklas |
165 |
try |
6111 |
29 Jan 21 |
nicklas |
166 |
{ |
6541 |
17 Jan 22 |
nicklas |
167 |
LuceneIndex filtered = new VariantCallIndex("filtered"); |
6111 |
29 Jan 21 |
nicklas |
168 |
filtered.setName("Variants (filtered)"); |
6140 |
19 Feb 21 |
nicklas |
169 |
filtered.setItemList(Itemlist.VARIANT_INDEX_FILTERED); |
6141 |
19 Feb 21 |
nicklas |
170 |
filtered.setMaxToIndex(2000); |
6374 |
07 Sep 21 |
nicklas |
171 |
filtered.setVcfFileLocator(new DatafileVcfLocator(Datafiletype.VCF, false)); |
6111 |
29 Jan 21 |
nicklas |
172 |
filtered.open(new File(dbDir, "filtered"), null); |
6111 |
29 Jan 21 |
nicklas |
173 |
indexes.put(filtered.getId(), filtered); |
6141 |
19 Feb 21 |
nicklas |
174 |
|
6541 |
17 Jan 22 |
nicklas |
175 |
LuceneIndex raw = new VariantCallIndex("raw"); |
6112 |
02 Feb 21 |
nicklas |
176 |
raw.setName("Variants (all)"); |
6141 |
19 Feb 21 |
nicklas |
177 |
raw.setItemList(Itemlist.VARIANT_INDEX_ALL); |
6374 |
07 Sep 21 |
nicklas |
178 |
raw.setVcfFileLocator(new AnyToAnyVcfLocator("variants-annotated.vcf.gz")); |
6525 |
20 Dec 21 |
nicklas |
179 |
raw.setViewAllVariantsEnabled(false); |
6168 |
12 Mar 21 |
nicklas |
180 |
int numQueryThreads = Math.min(8, Runtime.getRuntime().availableProcessors()); |
6168 |
12 Mar 21 |
nicklas |
181 |
raw.open(new File(dbDir, "raw"), numQueryThreads > 1 ? Executors.newFixedThreadPool(numQueryThreads, new QueryThreadFactory(raw.getId())) : null); |
6111 |
29 Jan 21 |
nicklas |
182 |
indexes.put(raw.getId(), raw); |
6372 |
07 Sep 21 |
nicklas |
183 |
|
6541 |
17 Jan 22 |
nicklas |
184 |
LuceneIndex targeted = new VariantCallIndex("targeted"); |
6407 |
17 Sep 21 |
nicklas |
185 |
targeted.setName("Variants (targeted)"); |
6372 |
07 Sep 21 |
nicklas |
186 |
targeted.setItemList(Itemlist.VARIANT_INDEX_TARGETED); |
6377 |
08 Sep 21 |
nicklas |
187 |
targeted.setIndexAllGenotypes(true); |
6372 |
07 Sep 21 |
nicklas |
188 |
targeted.setMaxToIndex(2000); |
6374 |
07 Sep 21 |
nicklas |
189 |
targeted.setVcfFileLocator(new AnyToAnyVcfLocator( |
6374 |
07 Sep 21 |
nicklas |
190 |
Restrictions.like(Hql.property("name"), Expressions.string("genotype_%.vcf")), |
6374 |
07 Sep 21 |
nicklas |
191 |
"genotype_*.vcf")); |
6372 |
07 Sep 21 |
nicklas |
192 |
targeted.open(new File(dbDir, "targeted"), null); |
6372 |
07 Sep 21 |
nicklas |
193 |
indexes.put(targeted.getId(), targeted); |
6541 |
17 Jan 22 |
nicklas |
194 |
|
6541 |
17 Jan 22 |
nicklas |
195 |
LuceneIndex oncoArray500K = new OncoArrayIndex("oncoarray-500K"); |
6541 |
17 Jan 22 |
nicklas |
196 |
oncoArray500K.setName("Genotyping (OncoArray500K)"); |
6541 |
17 Jan 22 |
nicklas |
197 |
oncoArray500K.setItemList(Itemlist.GENOTYPING_ONCOARRAY_500K); |
6541 |
17 Jan 22 |
nicklas |
198 |
oncoArray500K.setIndexAllGenotypes(true); |
6541 |
17 Jan 22 |
nicklas |
199 |
oncoArray500K.setViewAllVariantsEnabled(false); |
6541 |
17 Jan 22 |
nicklas |
200 |
oncoArray500K.setVcfFileLocator(new DatafileVcfLocator(Datafiletype.VCF, false)); |
6541 |
17 Jan 22 |
nicklas |
201 |
oncoArray500K.open(new File(dbDir, "oncoarray-500k"), null); |
6541 |
17 Jan 22 |
nicklas |
202 |
indexes.put(oncoArray500K.getId(), oncoArray500K); |
6111 |
29 Jan 21 |
nicklas |
203 |
} |
6111 |
29 Jan 21 |
nicklas |
204 |
catch (IOException ex) |
6111 |
29 Jan 21 |
nicklas |
205 |
{ |
6111 |
29 Jan 21 |
nicklas |
206 |
logger.error("Could not open Lucene index: " + dbDir, ex); |
6111 |
29 Jan 21 |
nicklas |
207 |
} |
6111 |
29 Jan 21 |
nicklas |
208 |
|
6111 |
29 Jan 21 |
nicklas |
// Start timer for processing async requests |
6111 |
29 Jan 21 |
nicklas |
210 |
timer = Application.getScheduler().scheduleAtFixedRate( |
6111 |
29 Jan 21 |
nicklas |
211 |
new IndexUpdateTimerTask(), 5000, 5000, false); |
6111 |
29 Jan 21 |
nicklas |
212 |
} |
6111 |
29 Jan 21 |
nicklas |
213 |
catch (RuntimeException ex) |
6111 |
29 Jan 21 |
nicklas |
214 |
{ |
6111 |
29 Jan 21 |
nicklas |
215 |
logger.debug("Could not start Variant Indexing Service", ex); |
6111 |
29 Jan 21 |
nicklas |
216 |
stopInternal(); |
6111 |
29 Jan 21 |
nicklas |
217 |
throw ex; |
6111 |
29 Jan 21 |
nicklas |
218 |
} |
6111 |
29 Jan 21 |
nicklas |
219 |
|
6111 |
29 Jan 21 |
nicklas |
220 |
isRunning = true; |
6111 |
29 Jan 21 |
nicklas |
221 |
logger.debug("Variant Indexing Service is now running"); |
6111 |
29 Jan 21 |
nicklas |
222 |
} |
6111 |
29 Jan 21 |
nicklas |
223 |
|
6111 |
29 Jan 21 |
nicklas |
224 |
/** |
6111 |
29 Jan 21 |
nicklas |
Stop the service if it is running. |
6111 |
29 Jan 21 |
nicklas |
226 |
*/ |
6111 |
29 Jan 21 |
nicklas |
227 |
synchronized void stop() |
6111 |
29 Jan 21 |
nicklas |
228 |
{ |
6111 |
29 Jan 21 |
nicklas |
229 |
if (!isRunning) return; |
6111 |
29 Jan 21 |
nicklas |
230 |
logger.debug("Stopping Variant Indexing Service"); |
6111 |
29 Jan 21 |
nicklas |
231 |
stopInternal(); |
6111 |
29 Jan 21 |
nicklas |
232 |
logger.debug("Variant Indexing Service has stopped"); |
6111 |
29 Jan 21 |
nicklas |
233 |
} |
6111 |
29 Jan 21 |
nicklas |
234 |
|
6111 |
29 Jan 21 |
nicklas |
235 |
/** |
6111 |
29 Jan 21 |
nicklas |
Restart the service. |
6111 |
29 Jan 21 |
nicklas |
237 |
*/ |
6111 |
29 Jan 21 |
nicklas |
238 |
public synchronized void restart() |
6111 |
29 Jan 21 |
nicklas |
239 |
{ |
6111 |
29 Jan 21 |
nicklas |
240 |
if (ext != null) Services.restart(ext); |
6111 |
29 Jan 21 |
nicklas |
241 |
} |
6111 |
29 Jan 21 |
nicklas |
242 |
|
6111 |
29 Jan 21 |
nicklas |
243 |
|
6111 |
29 Jan 21 |
nicklas |
244 |
private void stopInternal() |
6111 |
29 Jan 21 |
nicklas |
245 |
{ |
6111 |
29 Jan 21 |
nicklas |
246 |
if (timer != null) |
6111 |
29 Jan 21 |
nicklas |
247 |
{ |
6111 |
29 Jan 21 |
nicklas |
248 |
timer.cancel(); |
6111 |
29 Jan 21 |
nicklas |
249 |
timer = null; |
6111 |
29 Jan 21 |
nicklas |
250 |
} |
6241 |
21 May 21 |
nicklas |
251 |
for (LuceneIndex idx : indexes.values()) |
6241 |
21 May 21 |
nicklas |
252 |
{ |
6241 |
21 May 21 |
nicklas |
253 |
idx.close(); |
6241 |
21 May 21 |
nicklas |
254 |
} |
6241 |
21 May 21 |
nicklas |
255 |
indexes.clear(); |
6111 |
29 Jan 21 |
nicklas |
256 |
if (rootSc != null) |
6111 |
29 Jan 21 |
nicklas |
257 |
{ |
6111 |
29 Jan 21 |
nicklas |
258 |
rootSc.logout(); |
6111 |
29 Jan 21 |
nicklas |
259 |
rootSc = null; |
6111 |
29 Jan 21 |
nicklas |
260 |
} |
6111 |
29 Jan 21 |
nicklas |
261 |
ext = null; |
6111 |
29 Jan 21 |
nicklas |
262 |
systemSc = null; |
6111 |
29 Jan 21 |
nicklas |
263 |
isRunning = false; |
6111 |
29 Jan 21 |
nicklas |
264 |
} |
6111 |
29 Jan 21 |
nicklas |
265 |
|
6111 |
29 Jan 21 |
nicklas |
266 |
/** |
6111 |
29 Jan 21 |
nicklas |
Set a flag forcing the service to perform a check soon after the given number |
6111 |
29 Jan 21 |
nicklas |
of seconds. This method is intended to be called by external parties that know |
6111 |
29 Jan 21 |
nicklas |
that there is new or modified data to force an index update. |
6111 |
29 Jan 21 |
nicklas |
270 |
*/ |
6111 |
29 Jan 21 |
nicklas |
271 |
public void setForceUpdateCheck(int seconds) |
6111 |
29 Jan 21 |
nicklas |
272 |
{ |
6111 |
29 Jan 21 |
nicklas |
273 |
this.forceUpdateCheck = System.currentTimeMillis() + seconds * 1000; |
6111 |
29 Jan 21 |
nicklas |
274 |
} |
6111 |
29 Jan 21 |
nicklas |
275 |
|
6111 |
29 Jan 21 |
nicklas |
276 |
/** |
6111 |
29 Jan 21 |
nicklas |
Perform a check for new or removed data that should be added to or removed |
6111 |
29 Jan 21 |
nicklas |
from the index databases. |
6111 |
29 Jan 21 |
nicklas |
279 |
|
6111 |
29 Jan 21 |
nicklas |
Note that this method may return without doing |
6111 |
29 Jan 21 |
nicklas |
anything depending on how long time it was since the last check and if |
6111 |
29 Jan 21 |
nicklas |
the {@link #setForceCheck()} has been called or not. |
6111 |
29 Jan 21 |
nicklas |
283 |
*/ |
6111 |
29 Jan 21 |
nicklas |
284 |
void autoUpdateIndexes() |
6111 |
29 Jan 21 |
nicklas |
285 |
{ |
6111 |
29 Jan 21 |
nicklas |
286 |
long now = System.currentTimeMillis(); |
6111 |
29 Jan 21 |
nicklas |
287 |
long timeSinceLastCheck = now - lastAutoUpdateCheck; |
7074 |
24 Mar 23 |
nicklas |
288 |
long minWaitInterval = logger.isDebugEnabled() ? MIN_WAIT_INTERVAL_DEBUG : MIN_WAIT_INTERVAL_NORMAL; |
6111 |
29 Jan 21 |
nicklas |
289 |
|
6111 |
29 Jan 21 |
nicklas |
// If we have not waited long enough and there there is no recent request we don't have to check |
7074 |
24 Mar 23 |
nicklas |
291 |
if (timeSinceLastCheck < minWaitInterval && (forceUpdateCheck == 0 || forceUpdateCheck > now)) |
6111 |
29 Jan 21 |
nicklas |
292 |
{ |
6111 |
29 Jan 21 |
nicklas |
293 |
logger.trace("No auto-update check since no recent request and not long enough wait time [" + (timeSinceLastCheck / 1000) + "]"); |
6111 |
29 Jan 21 |
nicklas |
294 |
return; |
6111 |
29 Jan 21 |
nicklas |
295 |
} |
6111 |
29 Jan 21 |
nicklas |
296 |
|
6111 |
29 Jan 21 |
nicklas |
297 |
forceUpdateCheck = 0; |
6111 |
29 Jan 21 |
nicklas |
298 |
lastAutoUpdateCheck = now; |
6111 |
29 Jan 21 |
nicklas |
299 |
logger.debug("Time for auto-update check [" + (timeSinceLastCheck / 1000) + "]"); |
6111 |
29 Jan 21 |
nicklas |
300 |
|
6111 |
29 Jan 21 |
nicklas |
301 |
try |
6111 |
29 Jan 21 |
nicklas |
302 |
{ |
6167 |
09 Mar 21 |
nicklas |
303 |
int forceAnotherCheck = 0; |
6111 |
29 Jan 21 |
nicklas |
304 |
|
6140 |
19 Feb 21 |
nicklas |
305 |
for (LuceneIndex idx : indexes.values()) |
6111 |
29 Jan 21 |
nicklas |
306 |
{ |
6167 |
09 Mar 21 |
nicklas |
307 |
AutoUpdate autoUpdate = idx.getNextAutoUpdateAction(); |
6168 |
12 Mar 21 |
nicklas |
308 |
Status status = idx.getWorkingStatus(); |
6556 |
28 Jan 22 |
nicklas |
309 |
String customAction = idx.getCustomUpdateAction(); |
6168 |
12 Mar 21 |
nicklas |
310 |
logger.debug("Status ("+idx.getName()+"): " + status); |
6167 |
09 Mar 21 |
nicklas |
311 |
logger.debug("Auto-update action ("+idx.getName()+"): " + autoUpdate); |
6556 |
28 Jan 22 |
nicklas |
312 |
logger.debug("Custom action ("+idx.getName()+"): " + customAction); |
6168 |
12 Mar 21 |
nicklas |
313 |
if (autoUpdate == AutoUpdate.DISABLED || status != Status.IDLE) continue; |
6167 |
09 Mar 21 |
nicklas |
314 |
|
6140 |
19 Feb 21 |
nicklas |
315 |
DbControl dc = null; |
6140 |
19 Feb 21 |
nicklas |
316 |
try |
6140 |
19 Feb 21 |
nicklas |
317 |
{ |
6556 |
28 Jan 22 |
nicklas |
318 |
idx.setError(null); |
6604 |
23 Feb 22 |
nicklas |
319 |
dc = rootSc.newDbControl("Variant search: auto-update="+(customAction != null ? customAction : autoUpdate.name())); |
6140 |
19 Feb 21 |
nicklas |
320 |
|
6167 |
09 Mar 21 |
nicklas |
321 |
if (autoUpdate == AutoUpdate.REMOVE_NON_EXISTING) |
6140 |
19 Feb 21 |
nicklas |
322 |
{ |
6167 |
09 Mar 21 |
nicklas |
323 |
Set<Integer> nonExisting = idx.getNonExistingRawBioAssays(dc); |
6167 |
09 Mar 21 |
nicklas |
324 |
idx.removeFromIndex(dc, nonExisting, null); |
6544 |
19 Jan 22 |
nicklas |
325 |
idx.setNextAutoUpdateAction(AutoUpdate.DEFAULT, null); |
6241 |
21 May 21 |
nicklas |
326 |
idx.releaseCloseWait(); |
6140 |
19 Feb 21 |
nicklas |
327 |
} |
6167 |
09 Mar 21 |
nicklas |
328 |
else if (autoUpdate == AutoUpdate.FULL_REBUILD) |
6167 |
09 Mar 21 |
nicklas |
329 |
{ |
6168 |
12 Mar 21 |
nicklas |
330 |
Thread t = new Thread(new FullRebuildRunnable(idx), "VarSearch-Rebuild-"+idx.getId()); |
6168 |
12 Mar 21 |
nicklas |
331 |
t.start(); |
6167 |
09 Mar 21 |
nicklas |
332 |
} |
6169 |
15 Mar 21 |
nicklas |
333 |
else if (autoUpdate == AutoUpdate.DELETE) |
6169 |
15 Mar 21 |
nicklas |
334 |
{ |
6169 |
15 Mar 21 |
nicklas |
335 |
idx.deleteIndex(); |
6544 |
19 Jan 22 |
nicklas |
336 |
idx.setNextAutoUpdateAction(AutoUpdate.DEFAULT, null); |
6241 |
21 May 21 |
nicklas |
337 |
idx.releaseCloseWait(); |
6169 |
15 Mar 21 |
nicklas |
338 |
} |
6544 |
19 Jan 22 |
nicklas |
339 |
else if (autoUpdate == AutoUpdate.CUSTOM) |
6167 |
09 Mar 21 |
nicklas |
340 |
{ |
6556 |
28 Jan 22 |
nicklas |
341 |
idx.doCustomAction(customAction); |
6544 |
19 Jan 22 |
nicklas |
342 |
idx.setNextAutoUpdateAction(AutoUpdate.DEFAULT, null); |
6544 |
19 Jan 22 |
nicklas |
343 |
idx.releaseCloseWait(); |
6544 |
19 Jan 22 |
nicklas |
344 |
} |
6544 |
19 Jan 22 |
nicklas |
345 |
else // AutoUpdate.DEFAULT || AutoUpdate.ADD_TO_INDEX |
6544 |
19 Jan 22 |
nicklas |
346 |
{ |
6140 |
19 Feb 21 |
nicklas |
347 |
|
6167 |
09 Mar 21 |
nicklas |
348 |
ItemList rbaToIndex = idx.getItemList().get(dc); |
6167 |
09 Mar 21 |
nicklas |
349 |
if (rbaToIndex == null) |
6140 |
19 Feb 21 |
nicklas |
350 |
{ |
6167 |
09 Mar 21 |
nicklas |
351 |
logger.warn("Could not find the '" + idx.getItemList().getName() + "' item list"); |
6140 |
19 Feb 21 |
nicklas |
352 |
continue; |
6140 |
19 Feb 21 |
nicklas |
353 |
} |
6167 |
09 Mar 21 |
nicklas |
354 |
|
6167 |
09 Mar 21 |
nicklas |
355 |
int numItems = rbaToIndex.getSize(); |
6167 |
09 Mar 21 |
nicklas |
356 |
if (autoUpdate == AutoUpdate.DEFAULT) |
6167 |
09 Mar 21 |
nicklas |
357 |
{ |
6167 |
09 Mar 21 |
nicklas |
// Check "AutoProcessing" etc, |
6167 |
09 Mar 21 |
nicklas |
359 |
boolean disabled = "Disable".equals(Annotationtype.AUTO_PROCESSING.getAnnotationValue(dc, rbaToIndex)); |
6167 |
09 Mar 21 |
nicklas |
360 |
logger.debug("Number of items to index ("+idx.getName()+"): " + numItems); |
6167 |
09 Mar 21 |
nicklas |
361 |
logger.debug("AutoProcessing is "+ (disabled ? "disabled" : "enabled")+" for " + idx.getName()); |
6167 |
09 Mar 21 |
nicklas |
362 |
if (disabled || numItems == 0) continue; |
6167 |
09 Mar 21 |
nicklas |
363 |
|
6167 |
09 Mar 21 |
nicklas |
364 |
if (numItems < EXTENDED_WAIT_LIMIT) |
6167 |
09 Mar 21 |
nicklas |
365 |
{ |
6167 |
09 Mar 21 |
nicklas |
// Check if we should wait some more |
7074 |
24 Mar 23 |
nicklas |
367 |
long extendedWaitUntil = idx.getExtendedWaitUntil(logger.isDebugEnabled() ? MAX_EXTENDED_WAIT_DEBUG : MAX_EXTENDED_WAIT_NORMAL); |
6167 |
09 Mar 21 |
nicklas |
368 |
if (now < extendedWaitUntil) |
6167 |
09 Mar 21 |
nicklas |
369 |
{ |
6167 |
09 Mar 21 |
nicklas |
370 |
logger.debug("Waiting for more more rawbioassays: " + ((extendedWaitUntil-now)/1000) + " seconds"); |
6167 |
09 Mar 21 |
nicklas |
371 |
continue; |
6167 |
09 Mar 21 |
nicklas |
372 |
} |
6167 |
09 Mar 21 |
nicklas |
373 |
} |
6167 |
09 Mar 21 |
nicklas |
374 |
} |
6167 |
09 Mar 21 |
nicklas |
375 |
|
6167 |
09 Mar 21 |
nicklas |
376 |
int maxToIndex = idx.getMaxToIndex(); |
6167 |
09 Mar 21 |
nicklas |
377 |
if (maxToIndex < numItems) |
6167 |
09 Mar 21 |
nicklas |
378 |
{ |
6167 |
09 Mar 21 |
nicklas |
// Do not leave just a few items remaining |
6241 |
21 May 21 |
nicklas |
380 |
if (numItems-maxToIndex <= 2*EXTENDED_WAIT_LIMIT) maxToIndex = numItems; |
6167 |
09 Mar 21 |
nicklas |
381 |
} |
6167 |
09 Mar 21 |
nicklas |
382 |
|
6167 |
09 Mar 21 |
nicklas |
383 |
ItemQuery<RawBioAssay> rawQuery = rbaToIndex.getMembers(); |
6167 |
09 Mar 21 |
nicklas |
384 |
rawQuery.setIncludes(Include.ALL); |
6167 |
09 Mar 21 |
nicklas |
385 |
rawQuery.setMaxResults(maxToIndex); |
6167 |
09 Mar 21 |
nicklas |
386 |
List<RawBioAssay> rba = rawQuery.list(dc); |
6167 |
09 Mar 21 |
nicklas |
387 |
|
6167 |
09 Mar 21 |
nicklas |
388 |
logger.debug("Indexing " + idx.getName()); |
6241 |
21 May 21 |
nicklas |
389 |
List<RawBioAssay> indexed = idx.addToIndex(dc, rba, null); |
6241 |
21 May 21 |
nicklas |
390 |
if (indexed != null) |
6241 |
21 May 21 |
nicklas |
391 |
{ |
6241 |
21 May 21 |
nicklas |
392 |
rbaToIndex.removeItems(indexed.iterator()); |
6241 |
21 May 21 |
nicklas |
393 |
} |
6167 |
09 Mar 21 |
nicklas |
394 |
dc.commit(); |
6241 |
21 May 21 |
nicklas |
395 |
idx.releaseCloseWait(); |
6241 |
21 May 21 |
nicklas |
396 |
|
6167 |
09 Mar 21 |
nicklas |
397 |
if (rbaToIndex.getSize() == 0) |
6167 |
09 Mar 21 |
nicklas |
398 |
{ |
6167 |
09 Mar 21 |
nicklas |
// The list has been processed, revert to DEFAULT action |
6544 |
19 Jan 22 |
nicklas |
400 |
idx.setNextAutoUpdateAction(AutoUpdate.DEFAULT, null); |
6167 |
09 Mar 21 |
nicklas |
401 |
} |
6167 |
09 Mar 21 |
nicklas |
402 |
|
6167 |
09 Mar 21 |
nicklas |
403 |
if (rbaToIndex.getSize() > EXTENDED_WAIT_LIMIT) |
6167 |
09 Mar 21 |
nicklas |
404 |
{ |
6167 |
09 Mar 21 |
nicklas |
// Force an update if there are more items to index |
6167 |
09 Mar 21 |
nicklas |
406 |
logger.debug("Scheduling new check in 5 seconds since there are " + rbaToIndex.getSize() + " more items to index"); |
6167 |
09 Mar 21 |
nicklas |
407 |
forceAnotherCheck = 5; |
6167 |
09 Mar 21 |
nicklas |
408 |
} |
6140 |
19 Feb 21 |
nicklas |
409 |
} |
6140 |
19 Feb 21 |
nicklas |
410 |
} |
6140 |
19 Feb 21 |
nicklas |
411 |
catch (Exception ex) |
6140 |
19 Feb 21 |
nicklas |
412 |
{ |
6556 |
28 Jan 22 |
nicklas |
413 |
idx.setError(ex); |
6140 |
19 Feb 21 |
nicklas |
414 |
logger.error("Indexing failed ("+idx.getName()+")", ex); |
6140 |
19 Feb 21 |
nicklas |
415 |
} |
6140 |
19 Feb 21 |
nicklas |
416 |
finally |
6140 |
19 Feb 21 |
nicklas |
417 |
{ |
6605 |
23 Feb 22 |
nicklas |
418 |
idx.autoSetQueryStatus(); |
6140 |
19 Feb 21 |
nicklas |
419 |
if (dc != null) dc.close(); |
6140 |
19 Feb 21 |
nicklas |
420 |
} |
6111 |
29 Jan 21 |
nicklas |
421 |
} |
6111 |
29 Jan 21 |
nicklas |
422 |
|
6167 |
09 Mar 21 |
nicklas |
423 |
if (forceAnotherCheck > 0) setForceUpdateCheck(forceAnotherCheck); |
6111 |
29 Jan 21 |
nicklas |
424 |
} |
6112 |
02 Feb 21 |
nicklas |
425 |
catch (Exception ex) |
6112 |
02 Feb 21 |
nicklas |
426 |
{ |
6112 |
02 Feb 21 |
nicklas |
427 |
logger.error("Indexing failed", ex); |
6112 |
02 Feb 21 |
nicklas |
428 |
} |
6111 |
29 Jan 21 |
nicklas |
429 |
finally |
6111 |
29 Jan 21 |
nicklas |
430 |
{ |
6111 |
29 Jan 21 |
nicklas |
431 |
lastAutoUpdateCheck = System.currentTimeMillis(); |
6111 |
29 Jan 21 |
nicklas |
432 |
} |
6111 |
29 Jan 21 |
nicklas |
433 |
} |
6111 |
29 Jan 21 |
nicklas |
434 |
|
6111 |
29 Jan 21 |
nicklas |
435 |
|
6111 |
29 Jan 21 |
nicklas |
436 |
/** |
6111 |
29 Jan 21 |
nicklas |
Timer for updating indexes. |
6111 |
29 Jan 21 |
nicklas |
438 |
*/ |
6111 |
29 Jan 21 |
nicklas |
439 |
static class IndexUpdateTimerTask |
6111 |
29 Jan 21 |
nicklas |
440 |
extends TimerTask |
6111 |
29 Jan 21 |
nicklas |
441 |
{ |
6111 |
29 Jan 21 |
nicklas |
442 |
|
6111 |
29 Jan 21 |
nicklas |
443 |
public IndexUpdateTimerTask() |
6111 |
29 Jan 21 |
nicklas |
444 |
{} |
6111 |
29 Jan 21 |
nicklas |
445 |
|
6111 |
29 Jan 21 |
nicklas |
446 |
@Override |
6111 |
29 Jan 21 |
nicklas |
447 |
public void run() |
6111 |
29 Jan 21 |
nicklas |
448 |
{ |
6111 |
29 Jan 21 |
nicklas |
449 |
try |
6111 |
29 Jan 21 |
nicklas |
450 |
{ |
6111 |
29 Jan 21 |
nicklas |
451 |
getInstance().autoUpdateIndexes(); |
6111 |
29 Jan 21 |
nicklas |
452 |
} |
6111 |
29 Jan 21 |
nicklas |
453 |
catch (Exception ex) |
6111 |
29 Jan 21 |
nicklas |
454 |
{ |
6111 |
29 Jan 21 |
nicklas |
455 |
logger.error("Exception when performing auto-confirm check", ex); |
6111 |
29 Jan 21 |
nicklas |
456 |
} |
6111 |
29 Jan 21 |
nicklas |
457 |
} |
6111 |
29 Jan 21 |
nicklas |
458 |
|
6111 |
29 Jan 21 |
nicklas |
459 |
} |
6111 |
29 Jan 21 |
nicklas |
460 |
|
6111 |
29 Jan 21 |
nicklas |
461 |
} |