MtasSolrJoinCache.java.html
17.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>MtasSolrJoinCache.java</title><link rel="stylesheet" href="../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">MTAS</a> > <a href="index.source.html" class="el_package">mtas.solr.search</a> > <span class="el_source">MtasSolrJoinCache.java</span></div><h1>MtasSolrJoinCache.java</h1><pre class="source lang-java linenums">package mtas.solr.search;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.solr.common.util.Base64;
/**
* The Class MtasSolrJoinCache.
*/
public class MtasSolrJoinCache {
/** The Constant log. */
<span class="fc" id="L37"> private static final Log log = LogFactory.getLog(MtasSolrJoinCache.class);</span>
/** The Constant DEFAULT_LIFETIME. */
private static final long DEFAULT_LIFETIME = 86400;
/** The Constant DEFAULT_MAXIMUM_NUMBER. */
private static final int DEFAULT_MAXIMUM_NUMBER = 1000;
/** The Constant DEFAULT_MAXIMUM_OVERFLOW. */
private static final int DEFAULT_MAXIMUM_OVERFLOW = 10;
/** The administration. */
private HashMap<MtasSolrJoinCacheItem, String> administration;
/** The index. */
private HashMap<String, MtasSolrJoinCacheItem> index;
/** The expiration. */
private HashMap<String, Long> expiration;
/** The join cache path. */
private Path joinCachePath;
/** The life time. */
private long lifeTime;
/** The maximum number. */
private int maximumNumber;
/** The maximum overflow. */
private int maximumOverflow;
/**
* Instantiates a new mtas solr join cache.
*
* @param cacheDirectory the cache directory
* @param lifeTime the life time
* @param maximumNumber the maximum number
* @param maximumOverflow the maximum overflow
*/
public MtasSolrJoinCache(String cacheDirectory, Long lifeTime,
<span class="fc" id="L78"> Integer maximumNumber, Integer maximumOverflow) {</span>
<span class="fc" id="L79"> joinCachePath = null;</span>
<span class="pc bpc" id="L80" title="3 of 4 branches missed."> this.lifeTime = (lifeTime != null && lifeTime > 0) ? lifeTime</span>
: DEFAULT_LIFETIME;
<span class="pc bpc" id="L82" title="3 of 4 branches missed."> this.maximumNumber = (maximumNumber != null && maximumNumber > 0)</span>
<span class="pc" id="L83"> ? maximumNumber : DEFAULT_MAXIMUM_NUMBER;</span>
<span class="pc bpc" id="L84" title="3 of 4 branches missed."> this.maximumOverflow = (maximumOverflow != null && maximumOverflow > 0)</span>
<span class="pc" id="L85"> ? maximumOverflow : DEFAULT_MAXIMUM_OVERFLOW;</span>
<span class="pc bpc" id="L86" title="1 of 2 branches missed."> if (cacheDirectory != null) {</span>
try {
<span class="nc" id="L88"> joinCachePath = Files.createDirectories(Paths.get(cacheDirectory));</span>
<span class="nc" id="L89"> File[] fileList = joinCachePath.toFile().listFiles();</span>
<span class="nc bnc" id="L90" title="All 2 branches missed."> if (fileList != null) {</span>
<span class="nc bnc" id="L91" title="All 2 branches missed."> for (File file : fileList) {</span>
<span class="nc bnc" id="L92" title="All 4 branches missed."> if (file.isFile() && !file.delete()) {</span>
<span class="nc" id="L93"> log.error("couldn't delete " + file);</span>
<span class="nc bnc" id="L94" title="All 2 branches missed."> } else if (file.isDirectory()) {</span>
<span class="nc" id="L95"> log.info("unexpected directory " + file.getName());</span>
}
}
}
<span class="nc" id="L99"> } catch (IOException e) {</span>
<span class="nc" id="L100"> joinCachePath = null;</span>
<span class="nc" id="L101"> log.info("couldn't create cache directory " + cacheDirectory, e);</span>
<span class="nc" id="L102"> }</span>
}
<span class="fc" id="L104"> administration = new HashMap<>();</span>
<span class="fc" id="L105"> expiration = new HashMap<>();</span>
<span class="fc" id="L106"> }</span>
/**
* Creates the.
*
* @param url the url
* @param request the request
* @param data the data
* @return the string
* @throws IOException Signals that an I/O exception has occurred.
*/
public String create(String url, String request, Serializable data)
throws IOException {
<span class="nc" id="L119"> MtasSolrJoinCacheItem item = new MtasSolrJoinCacheItem(url, request, null);</span>
<span class="nc" id="L120"> return create(item, data);</span>
}
/**
* Creates the.
*
* @param item the item
* @param data the data
* @return the string
* @throws IOException Signals that an I/O exception has occurred.
*/
private String create(MtasSolrJoinCacheItem item, Serializable data)
throws IOException {
// initialisation
<span class="nc" id="L134"> Date date = clear();</span>
<span class="nc" id="L135"> delete(item);</span>
// create always new key
String key;
do {
<span class="nc" id="L139"> key = UUID.randomUUID().toString();</span>
<span class="nc bnc" id="L140" title="All 2 branches missed."> } while (index.containsKey(key));</span>
// register
<span class="nc" id="L142"> administration.put(item, key);</span>
<span class="nc" id="L143"> expiration.put(key, date.getTime() + lifeTime);</span>
<span class="nc" id="L144"> index.put(key, item);</span>
// store data
<span class="nc bnc" id="L146" title="All 2 branches missed."> if (joinCachePath != null) {</span>
<span class="nc" id="L147"> File file = joinCachePath.resolve(key).toFile();</span>
<span class="nc" id="L148"> try (OutputStream outputStream = new FileOutputStream(file);</span>
<span class="nc" id="L149"> Writer outputStreamWriter = new OutputStreamWriter(outputStream,</span>
StandardCharsets.UTF_8);) {
<span class="nc" id="L151"> outputStreamWriter.write(encode(data));</span>
<span class="nc" id="L152"> return key;</span>
<span class="nc bnc" id="L153" title="All 16 branches missed."> } catch (IOException e) {</span>
<span class="nc" id="L154"> administration.remove(item);</span>
<span class="nc" id="L155"> expiration.remove(key);</span>
<span class="nc" id="L156"> log.error("couldn't create " + key, e);</span>
<span class="nc" id="L157"> return null;</span>
}
} else {
<span class="nc" id="L160"> item.data = encode(data);</span>
<span class="nc" id="L161"> return key;</span>
}
}
/**
* Gets the.
*
* @param url the url
* @param request the request
* @return the object
* @throws IOException Signals that an I/O exception has occurred.
*/
public Object get(String url, String request) throws IOException {
<span class="nc" id="L174"> MtasSolrJoinCacheItem item = new MtasSolrJoinCacheItem(url, request, null);</span>
<span class="nc bnc" id="L175" title="All 2 branches missed."> if (administration.containsKey(item)) {</span>
<span class="nc" id="L176"> return get(item);</span>
} else {
<span class="nc" id="L178"> return null;</span>
}
}
/**
* Gets the.
*
* @param key the key
* @return the object
* @throws IOException Signals that an I/O exception has occurred.
*/
public Object get(String key) throws IOException {
<span class="nc bnc" id="L190" title="All 2 branches missed."> if (index.containsKey(key)) {</span>
<span class="nc" id="L191"> return get(index.get(key));</span>
} else {
<span class="nc" id="L193"> return null;</span>
}
}
/**
* Gets the.
*
* @param item the item
* @return the object
* @throws IOException Signals that an I/O exception has occurred.
*/
private Object get(MtasSolrJoinCacheItem item) throws IOException {
<span class="nc" id="L205"> Date date = clear();</span>
<span class="nc bnc" id="L206" title="All 2 branches missed."> if (administration.containsKey(item)) {</span>
<span class="nc" id="L207"> String key = administration.get(item);</span>
<span class="nc" id="L208"> expiration.put(key, date.getTime() + lifeTime);</span>
<span class="nc bnc" id="L209" title="All 2 branches missed."> if (joinCachePath != null) {</span>
try {
<span class="nc" id="L211"> Path path = joinCachePath.resolve(key);</span>
<span class="nc" id="L212"> String data = new String(Files.readAllBytes(path),</span>
StandardCharsets.UTF_8);
<span class="nc" id="L214"> return decode(data);</span>
<span class="nc" id="L215"> } catch (IOException e) {</span>
<span class="nc bnc" id="L216" title="All 2 branches missed."> if (!joinCachePath.resolve(key).toFile().delete()) {</span>
<span class="nc" id="L217"> log.debug("couldn't delete " + key);</span>
}
<span class="nc" id="L219"> administration.remove(item);</span>
<span class="nc" id="L220"> expiration.remove(key);</span>
<span class="nc" id="L221"> log.error("couldn't get " + key, e);</span>
<span class="nc" id="L222"> }</span>
} else {
<span class="nc bnc" id="L224" title="All 2 branches missed."> if (item.data != null) {</span>
<span class="nc" id="L225"> return decode(item.data);</span>
} else {
<span class="nc" id="L227"> return null;</span>
}
}
<span class="nc" id="L230"> } else {</span>
<span class="nc" id="L231"> log.error("doesn't exist anymore");</span>
}
<span class="nc" id="L233"> return null;</span>
}
/**
* Delete.
*
* @param item the item
*/
private void delete(MtasSolrJoinCacheItem item) {
<span class="nc bnc" id="L242" title="All 2 branches missed."> if (administration.containsKey(item)) {</span>
<span class="nc" id="L243"> String key = administration.remove(item);</span>
<span class="nc" id="L244"> expiration.remove(key);</span>
<span class="nc" id="L245"> index.remove(key);</span>
<span class="nc bnc" id="L246" title="All 2 branches missed."> if (joinCachePath != null</span>
<span class="nc bnc" id="L247" title="All 2 branches missed."> && !joinCachePath.resolve(key).toFile().delete()) {</span>
<span class="nc" id="L248"> log.debug("couldn't delete " + key);</span>
}
}
<span class="nc" id="L251"> }</span>
/**
* Clear.
*
* @return the date
*/
private Date clear() {
<span class="nc" id="L259"> Date date = new Date();</span>
<span class="nc" id="L260"> Long timestamp = date.getTime();</span>
<span class="nc" id="L261"> HashSet<MtasSolrJoinCacheItem> toBeRemoved = new HashSet<>();</span>
// check expiration
<span class="nc bnc" id="L263" title="All 2 branches missed."> for (Entry<String, Long> entry : expiration.entrySet()) {</span>
<span class="nc bnc" id="L264" title="All 2 branches missed."> if (entry.getValue() < timestamp) {</span>
<span class="nc bnc" id="L265" title="All 2 branches missed."> for (Entry<MtasSolrJoinCacheItem, String> subEntry : administration</span>
<span class="nc" id="L266"> .entrySet()) {</span>
<span class="nc bnc" id="L267" title="All 2 branches missed."> if (subEntry.getValue().equals(entry.getKey())) {</span>
<span class="nc" id="L268"> toBeRemoved.add(subEntry.getKey());</span>
}
<span class="nc" id="L270"> }</span>
}
<span class="nc" id="L272"> }</span>
<span class="nc bnc" id="L273" title="All 2 branches missed."> for (MtasSolrJoinCacheItem item : toBeRemoved) {</span>
<span class="nc" id="L274"> delete(item);</span>
<span class="nc" id="L275"> }</span>
// check size
<span class="nc bnc" id="L277" title="All 2 branches missed."> if (expiration.size() > maximumNumber + maximumOverflow) {</span>
<span class="nc" id="L278"> Set<Entry<String, Long>> mapEntries = expiration.entrySet();</span>
<span class="nc" id="L279"> List<Entry<String, Long>> aList = new LinkedList<>(mapEntries);</span>
<span class="nc" id="L280"> Collections.sort(aList,</span>
(Entry<String, Long> ele1, Entry<String, Long> ele2) -> ele2
<span class="nc" id="L282"> .getValue().compareTo(ele1.getValue()));</span>
<span class="nc" id="L283"> aList.subList(maximumNumber, aList.size()).clear();</span>
<span class="nc bnc" id="L284" title="All 2 branches missed."> for (Entry<String, MtasSolrJoinCacheItem> entry : index.entrySet()) {</span>
<span class="nc bnc" id="L285" title="All 2 branches missed."> if (!expiration.containsKey(entry.getKey())) {</span>
<span class="nc" id="L286"> toBeRemoved.add(entry.getValue());</span>
}
<span class="nc" id="L288"> }</span>
<span class="nc bnc" id="L289" title="All 2 branches missed."> for (MtasSolrJoinCacheItem item : toBeRemoved) {</span>
<span class="nc" id="L290"> delete(item);</span>
<span class="nc" id="L291"> }</span>
}
<span class="nc" id="L293"> return date;</span>
}
/**
* Encode.
*
* @param o the o
* @return the string
* @throws IOException Signals that an I/O exception has occurred.
*/
private String encode(Serializable o) throws IOException {
<span class="nc" id="L304"> ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();</span>
ObjectOutputStream objectOutputStream;
<span class="nc" id="L306"> objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);</span>
<span class="nc" id="L307"> objectOutputStream.writeObject(o);</span>
<span class="nc" id="L308"> objectOutputStream.close();</span>
<span class="nc" id="L309"> byte[] byteArray = byteArrayOutputStream.toByteArray();</span>
<span class="nc" id="L310"> return Base64.byteArrayToBase64(byteArray);</span>
}
/**
* Decode.
*
* @param s the s
* @return the object
* @throws IOException Signals that an I/O exception has occurred.
*/
private Object decode(String s) throws IOException {
<span class="nc" id="L321"> byte[] bytes = Base64.base64ToByteArray(s);</span>
ObjectInputStream objectInputStream;
<span class="nc" id="L323"> objectInputStream = new ObjectInputStream(new ByteArrayInputStream(bytes));</span>
try {
<span class="nc" id="L325"> return objectInputStream.readObject();</span>
<span class="nc" id="L326"> } catch (ClassNotFoundException e) {</span>
<span class="nc" id="L327"> throw new IOException(e);</span>
}
}
}
class MtasSolrJoinCacheItem {
public String url;
public String request;
public String data;
<span class="nc" id="L339"> public MtasSolrJoinCacheItem(String url, String request, String data) {</span>
<span class="nc bnc" id="L340" title="All 2 branches missed."> this.url = url == null ? "" : url;</span>
<span class="nc bnc" id="L341" title="All 2 branches missed."> this.request = request == null ? "" : request;</span>
<span class="nc bnc" id="L342" title="All 2 branches missed."> this.data = data == null ? "" : data;</span>
<span class="nc" id="L343"> }</span>
@Override
public int hashCode() {
<span class="nc" id="L347"> int h = this.getClass().getSimpleName().hashCode();</span>
<span class="nc" id="L348"> h = (h * 3) ^ url.hashCode();</span>
<span class="nc" id="L349"> h = (h * 5) ^ request.hashCode();</span>
<span class="nc" id="L350"> return h;</span>
}
@Override
public boolean equals(Object obj) {
<span class="nc bnc" id="L355" title="All 2 branches missed."> if (this == obj)</span>
<span class="nc" id="L356"> return true;</span>
<span class="nc bnc" id="L357" title="All 2 branches missed."> if (obj == null)</span>
<span class="nc" id="L358"> return false;</span>
<span class="nc bnc" id="L359" title="All 2 branches missed."> if (getClass() != obj.getClass())</span>
<span class="nc" id="L360"> return false;</span>
<span class="nc" id="L361"> final MtasSolrJoinCacheItem that = (MtasSolrJoinCacheItem) obj;</span>
<span class="nc bnc" id="L362" title="All 4 branches missed."> return (url.equals(that.url)) && (request.equals(that.request));</span>
}
}
</pre><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.7.9.201702052155</span></div></body></html>