1 package org.apache.commons.jcs3.auxiliary.lateral;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.util.concurrent.ConcurrentHashMap;
23
24 import org.apache.commons.jcs3.auxiliary.AbstractAuxiliaryCacheMonitor;
25 import org.apache.commons.jcs3.auxiliary.lateral.socket.tcp.LateralTCPCacheFactory;
26 import org.apache.commons.jcs3.auxiliary.lateral.socket.tcp.behavior.ITCPLateralCacheAttributes;
27 import org.apache.commons.jcs3.engine.CacheStatus;
28 import org.apache.commons.jcs3.engine.ZombieCacheServiceNonLocal;
29 import org.apache.commons.jcs3.engine.behavior.ICacheServiceNonLocal;
30
31 /**
32 * Used to monitor and repair any failed connection for the lateral cache service. By default the
33 * monitor operates in a failure driven mode. That is, it goes into a wait state until there is an
34 * error. Upon the notification of a connection error, the monitor changes to operate in a time
35 * driven mode. That is, it attempts to recover the connections on a periodic basis. When all failed
36 * connections are restored, it changes back to the failure driven mode.
37 */
38 public class LateralCacheMonitor extends AbstractAuxiliaryCacheMonitor
39 {
40 /**
41 * Map of caches to monitor
42 */
43 private final ConcurrentHashMap<String, LateralCacheNoWait<Object, Object>> caches;
44
45 /**
46 * Reference to the factory
47 */
48 private final LateralTCPCacheFactory factory;
49
50 /**
51 * Allows close classes, ie testers to set the idle period to something testable.
52 * <p>
53 * @param idlePeriod
54 *
55 * @deprecated Use setIdlePeriod()
56 */
57 @Deprecated
58 protected static void forceShortIdlePeriod( final long idlePeriod )
59 {
60 LateralCacheMonitor.setIdlePeriod(idlePeriod);
61 }
62
63 /**
64 * Constructor for the LateralCacheMonitor object
65 * <p>
66 * It's the clients responsibility to decide how many of these there will be.
67 *
68 * @param factory a reference to the factory that manages the service instances
69 */
70 public LateralCacheMonitor(final LateralTCPCacheFactory factory)
71 {
72 super("JCS-LateralCacheMonitor");
73 this.factory = factory;
74 this.caches = new ConcurrentHashMap<>();
75 setIdlePeriod(20000L);
76 }
77
78 /**
79 * Add a cache to be monitored
80 *
81 * @param cache the cache
82 */
83 @SuppressWarnings("unchecked") // common map for all caches
84 public void addCache(final LateralCacheNoWait<?, ?> cache)
85 {
86 this.caches.put(cache.getCacheName(), (LateralCacheNoWait<Object, Object>)cache);
87
88 // if not yet started, go ahead
89 if (this.getState() == Thread.State.NEW)
90 {
91 this.start();
92 }
93 }
94
95 /**
96 * Clean up all resources before shutdown
97 */
98 @Override
99 public void dispose()
100 {
101 this.caches.clear();
102 }
103
104 /**
105 * Main processing method for the LateralCacheMonitor object
106 */
107 @Override
108 public void doWork()
109 {
110 // Monitor each cache instance one after the other.
111 log.info( "Number of caches to monitor = " + caches.size() );
112
113 caches.forEach((cacheName, cache) -> {
114
115 if (cache.getStatus() == CacheStatus.ERROR)
116 {
117 log.info( "Found LateralCacheNoWait in error, " + cacheName );
118
119 final ITCPLateralCacheAttributes lca =
120 (ITCPLateralCacheAttributes) cache.getAuxiliaryCacheAttributes();
121
122 // Get service instance
123 final ICacheServiceNonLocal<Object, Object> cacheService =
124 factory.getCSNLInstance(lca, cache.getElementSerializer());
125
126 // If we can't fix them, just skip and re-try in the
127 // next round.
128 if (!(cacheService instanceof ZombieCacheServiceNonLocal))
129 {
130 cache.fixCache(cacheService);
131 }
132 }
133 });
134 }
135 }