1 package org.apache.commons.jcs3.auxiliary.lateral;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Map.Entry;
30 import java.util.Objects;
31 import java.util.Set;
32 import java.util.concurrent.ConcurrentHashMap;
33 import java.util.concurrent.atomic.AtomicBoolean;
34 import java.util.stream.Collectors;
35
36 import org.apache.commons.jcs3.auxiliary.AbstractAuxiliaryCache;
37 import org.apache.commons.jcs3.auxiliary.lateral.behavior.ILateralCacheAttributes;
38 import org.apache.commons.jcs3.auxiliary.lateral.behavior.ILateralCacheListener;
39 import org.apache.commons.jcs3.engine.CacheStatus;
40 import org.apache.commons.jcs3.engine.behavior.ICacheElement;
41 import org.apache.commons.jcs3.engine.stats.StatElement;
42 import org.apache.commons.jcs3.engine.stats.Stats;
43 import org.apache.commons.jcs3.engine.stats.behavior.IStatElement;
44 import org.apache.commons.jcs3.engine.stats.behavior.IStats;
45 import org.apache.commons.jcs3.log.Log;
46 import org.apache.commons.jcs3.log.LogManager;
47
48
49
50
51
52
53
54 public class LateralCacheNoWaitFacade<K, V>
55 extends AbstractAuxiliaryCache<K, V>
56 {
57
58 private static final Log log = LogManager.getLog( LateralCacheNoWaitFacade.class );
59
60
61
62
63
64 @Deprecated
65 public LateralCacheNoWait<K, V>[] noWaits;
66
67
68
69
70 private final ConcurrentHashMap<String, LateralCacheNoWait<K, V>> noWaitMap;
71
72
73 private final String cacheName;
74
75
76 private ILateralCacheListener<K, V> listener;
77
78
79 private final ILateralCacheAttributes lateralCacheAttributes;
80
81
82 private final AtomicBoolean disposed = new AtomicBoolean(false);
83
84
85
86
87
88
89
90
91
92
93 @Deprecated
94 public LateralCacheNoWaitFacade(final ILateralCacheListener<K, V> listener, final LateralCacheNoWait<K, V>[] noWaits, final ILateralCacheAttributes cattr )
95 {
96 this(listener, Arrays.asList(noWaits), cattr);
97 }
98
99
100
101
102
103
104
105
106
107 @SuppressWarnings("unchecked")
108 public LateralCacheNoWaitFacade(final ILateralCacheListener<K, V> listener,
109 final List<LateralCacheNoWait<K, V>> noWaits, final ILateralCacheAttributes cattr )
110 {
111 log.debug( "CONSTRUCTING NO WAIT FACADE" );
112 this.listener = listener;
113 this.noWaits = noWaits.toArray(new LateralCacheNoWait[0]);
114 this.noWaitMap = new ConcurrentHashMap<>();
115 noWaits.forEach(noWait -> noWaitMap.put(noWait.getIdentityKey(), noWait));
116 this.cacheName = cattr.getCacheName();
117 this.lateralCacheAttributes = cattr;
118 }
119
120
121
122
123
124
125
126 protected int getNoWaitSize()
127 {
128 return noWaitMap.size();
129 }
130
131
132
133
134
135
136
137 public boolean containsNoWait( final LateralCacheNoWait<K, V> noWait )
138 {
139 return containsNoWait(noWait.getIdentityKey());
140 }
141
142
143
144
145
146
147
148
149
150 public boolean containsNoWait(final String tcpServer)
151 {
152 return noWaitMap.containsKey(tcpServer);
153 }
154
155
156
157
158
159
160
161 @SuppressWarnings("unchecked")
162 public synchronized boolean addNoWait( final LateralCacheNoWait<K, V> noWait )
163 {
164 if ( noWait == null )
165 {
166 return false;
167 }
168
169 final LateralCacheNoWait<K,V> added =
170 noWaitMap.putIfAbsent(noWait.getIdentityKey(), noWait);
171
172 if (added != null)
173 {
174 log.debug( "No Wait already contained, [{0}]", noWait );
175 return false;
176 }
177
178 noWaits = noWaitMap.values().toArray(new LateralCacheNoWait[0]);
179
180 return true;
181 }
182
183
184
185
186
187
188
189 public synchronized boolean removeNoWait( final LateralCacheNoWait<K, V> noWait )
190 {
191 if (noWait == null)
192 {
193 return false;
194 }
195
196 return removeNoWait(noWait.getIdentityKey());
197 }
198
199
200
201
202
203
204
205
206
207 @SuppressWarnings("unchecked")
208 public synchronized boolean removeNoWait(final String tcpServer)
209 {
210 if (tcpServer == null)
211 {
212 return false;
213 }
214
215 final LateralCacheNoWait<K,V> contained = noWaitMap.remove(tcpServer);
216 noWaits = noWaitMap.values().toArray(new LateralCacheNoWait[0]);
217
218 if (contained != null)
219 {
220 contained.dispose();
221 }
222
223 return contained != null;
224 }
225
226
227
228
229
230
231 @Override
232 public void update( final ICacheElement<K, V> ce )
233 throws IOException
234 {
235 log.debug("updating through lateral cache facade, noWaits.length = {0}",
236 noWaitMap::size);
237
238 for (final LateralCacheNoWait<K, V> nw : noWaitMap.values())
239 {
240 nw.update( ce );
241 }
242 }
243
244
245
246
247
248
249
250 @Override
251 public ICacheElement<K, V> get( final K key )
252 {
253 return noWaitMap.values().stream()
254 .map(nw -> nw.get(key))
255 .filter(Objects::nonNull)
256 .findFirst()
257 .orElse(null);
258 }
259
260
261
262
263
264
265
266
267 @Override
268 public Map<K, ICacheElement<K, V>> getMultiple(final Set<K> keys)
269 {
270 if (keys != null && !keys.isEmpty())
271 {
272 return keys.stream()
273 .collect(Collectors.toMap(
274 key -> key,
275 this::get)).entrySet().stream()
276 .filter(entry -> entry.getValue() != null)
277 .collect(Collectors.toMap(
278 Entry::getKey,
279 Entry::getValue));
280 }
281
282 return new HashMap<>();
283 }
284
285
286
287
288
289
290
291
292 @Override
293 public Map<K, ICacheElement<K, V>> getMatching(final String pattern)
294 {
295 return noWaitMap.values().stream()
296 .flatMap(nw -> nw.getMatching(pattern).entrySet().stream())
297 .collect(Collectors.toMap(
298 Entry::getKey,
299 Entry::getValue));
300 }
301
302
303
304
305
306
307 @Override
308 public Set<K> getKeySet() throws IOException
309 {
310 final HashSet<K> allKeys = new HashSet<>();
311 for (final LateralCacheNoWait<K, V> nw : noWaitMap.values())
312 {
313 final Set<K> keys = nw.getKeySet();
314 if (keys != null)
315 {
316 allKeys.addAll(keys);
317 }
318 }
319 return allKeys;
320 }
321
322
323
324
325
326
327
328 @Override
329 public boolean remove( final K key )
330 {
331 noWaitMap.values().forEach(nw -> nw.remove( key ));
332 return false;
333 }
334
335
336
337
338 @Override
339 public void removeAll()
340 {
341 noWaitMap.values().forEach(LateralCacheNoWait::removeAll);
342 }
343
344
345 @Override
346 public void dispose()
347 {
348 if (disposed.compareAndSet(false, true))
349 {
350 if ( listener != null )
351 {
352 listener.dispose();
353 listener = null;
354 }
355
356 noWaitMap.values().forEach(LateralCacheNoWait::dispose);
357 noWaitMap.clear();
358 }
359 }
360
361
362
363
364
365 @Override
366 public int getSize()
367 {
368 return 0;
369
370 }
371
372
373
374
375
376
377 @Override
378 public CacheType getCacheType()
379 {
380 return CacheType.LATERAL_CACHE;
381 }
382
383
384
385
386
387
388 @Override
389 public String getCacheName()
390 {
391 return cacheName;
392 }
393
394
395
396
397
398 @Override
399 public CacheStatus getStatus()
400 {
401 if (disposed.get())
402 {
403 return CacheStatus.DISPOSED;
404 }
405
406 if (noWaitMap.isEmpty() || listener != null)
407 {
408 return CacheStatus.ALIVE;
409 }
410
411 final List<CacheStatus> statii = noWaitMap.values().stream()
412 .map(LateralCacheNoWait::getStatus)
413 .collect(Collectors.toList());
414
415
416 if (statii.contains(CacheStatus.ALIVE))
417 {
418 return CacheStatus.ALIVE;
419 }
420
421
422 if (statii.contains(CacheStatus.ERROR))
423 {
424 return CacheStatus.ERROR;
425 }
426
427
428 return CacheStatus.DISPOSED;
429 }
430
431
432
433
434 @Override
435 public ILateralCacheAttributes getAuxiliaryCacheAttributes()
436 {
437 return this.lateralCacheAttributes;
438 }
439
440
441
442
443 @Override
444 public String toString()
445 {
446 return "LateralCacheNoWaitFacade: " + cacheName;
447 }
448
449
450
451
452
453
454 @Override
455 public String getEventLoggingExtraInfo()
456 {
457 return "Lateral Cache No Wait";
458 }
459
460
461
462
463
464 @Override
465 public String getStats()
466 {
467 return getStatistics().toString();
468 }
469
470
471
472
473 @Override
474 public IStats getStatistics()
475 {
476 final IStats stats = new Stats();
477 stats.setTypeName( "Lateral Cache No Wait Facade" );
478
479 final ArrayList<IStatElement<?>> elems = new ArrayList<>();
480
481 if (noWaitMap != null)
482 {
483 elems.add(new StatElement<>("Number of No Waits", Integer.valueOf(noWaitMap.size())));
484
485 elems.addAll(noWaitMap.values().stream()
486 .flatMap(lcnw -> lcnw.getStatistics().getStatElements().stream())
487 .collect(Collectors.toList()));
488 }
489
490 stats.setStatElements( elems );
491
492 return stats;
493 }
494 }