Skip to content

Package: GrizzlyMemcachedCacheManager$Builder

GrizzlyMemcachedCacheManager$Builder

nameinstructionbranchcomplexitylinemethod
GrizzlyMemcachedCacheManager.Builder()
M: 15 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
blocking(boolean)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
build()
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
ioStrategy(IOStrategy)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
selectorRunnersCount(int)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
transport(TCPNIOTransport)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
workerThreadPool(ExecutorService)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
zooKeeperConfig(ZooKeeperConfig)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 2012, 2019 Oracle and/or its affiliates and others.
3: * All rights reserved.
4: *
5: * This program and the accompanying materials are made available under the
6: * terms of the Eclipse Public License v. 2.0, which is available at
7: * http://www.eclipse.org/legal/epl-2.0.
8: *
9: * This Source Code may also be made available under the following Secondary
10: * Licenses when the conditions for such availability set forth in the
11: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
12: * version 2 with the GNU Classpath Exception, which is available at
13: * https://www.gnu.org/software/classpath/license.html.
14: *
15: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
16: *
17: * Contributors:
18: * Payara Services - Remove Netty Internal ConcurrentHashMap.
19: */
20:
21: package org.glassfish.grizzly.memcached;
22:
23: import org.glassfish.grizzly.Grizzly;
24: import org.glassfish.grizzly.IOStrategy;
25: import org.glassfish.grizzly.filterchain.FilterChainBuilder;
26: import org.glassfish.grizzly.filterchain.TransportFilter;
27: import org.glassfish.grizzly.memcached.zookeeper.ZKClient;
28: import org.glassfish.grizzly.memcached.zookeeper.ZooKeeperConfig;
29: import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
30: import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder;
31: import org.glassfish.grizzly.strategies.SameThreadIOStrategy;
32:
33: import java.io.IOException;
34: import java.util.concurrent.ConcurrentMap;
35: import java.util.concurrent.ConcurrentHashMap;
36: import java.util.concurrent.ExecutorService;
37: import java.util.concurrent.atomic.AtomicBoolean;
38: import java.util.logging.Level;
39: import java.util.logging.Logger;
40:
41: /**
42: * The implementation of the {@link CacheManager} based on Grizzly
43: * <p>
44: * This cache manager has a key(String cache name)/value({@link GrizzlyMemcachedCache} map for retrieving caches.
45: * If the specific {@link TCPNIOTransport GrizzlyTransport} is not set at creation time, this will create a main GrizzlyTransport.
46: * The {@link TCPNIOTransport GrizzlyTransport} must contain {@link MemcachedClientFilter}.
47: *
48: * @author Bongjae Chang
49: */
50: public class GrizzlyMemcachedCacheManager implements CacheManager {
51:
52: private static final Logger logger = Grizzly.logger(GrizzlyMemcachedCacheManager.class);
53:
54: private final ConcurrentMap<String, GrizzlyMemcachedCache<?, ?>> caches = new ConcurrentHashMap<>();
55: private final TCPNIOTransport transport;
56: private final boolean isExternalTransport;
57: private final AtomicBoolean shutdown = new AtomicBoolean(false);
58:
59: private ZKClient zkClient;
60:
61: private GrizzlyMemcachedCacheManager(final Builder builder) {
62: TCPNIOTransport transportLocal = builder.transport;
63: if (transportLocal == null) {
64: isExternalTransport = false;
65: final FilterChainBuilder clientFilterChainBuilder = FilterChainBuilder.stateless();
66: clientFilterChainBuilder.add(new TransportFilter()).add(new MemcachedClientFilter(true, true));
67: final TCPNIOTransportBuilder clientTCPNIOTransportBuilder = TCPNIOTransportBuilder.newInstance();
68: transportLocal = clientTCPNIOTransportBuilder.build();
69: transportLocal.setProcessor(clientFilterChainBuilder.build());
70: transportLocal.setSelectorRunnersCount(builder.selectorRunnersCount);
71: transportLocal.setIOStrategy(builder.ioStrategy);
72: transportLocal.configureBlocking(builder.blocking);
73: if (builder.workerThreadPool != null) {
74: transportLocal.setWorkerThreadPool(builder.workerThreadPool);
75: }
76: try {
77: transportLocal.start();
78: } catch (IOException ie) {
79: if (logger.isLoggable(Level.SEVERE)) {
80: logger.log(Level.SEVERE, "failed to start the transport", ie);
81: }
82: }
83: } else {
84: isExternalTransport = true;
85: }
86: this.transport = transportLocal;
87: if (builder.zooKeeperConfig != null) {
88: final ZKClient.Builder zkBuilder = new ZKClient.Builder(builder.zooKeeperConfig.getName(),
89: builder.zooKeeperConfig.getZooKeeperServerList());
90: zkBuilder.rootPath(builder.zooKeeperConfig.getRootPath());
91: zkBuilder.connectTimeoutInMillis(builder.zooKeeperConfig.getConnectTimeoutInMillis());
92: zkBuilder.sessionTimeoutInMillis(builder.zooKeeperConfig.getSessionTimeoutInMillis());
93: zkBuilder.commitDelayTimeInSecs(builder.zooKeeperConfig.getCommitDelayTimeInSecs());
94: this.zkClient = zkBuilder.build();
95: boolean isZkConnected = false;
96: try {
97: isZkConnected = this.zkClient.connect();
98: } catch (IOException ie) {
99: if (logger.isLoggable(Level.SEVERE)) {
100: logger.log(Level.SEVERE, "failed to connect the zookeeper server. zkClient=" + this.zkClient, ie);
101: }
102: this.zkClient = null;
103: } catch (InterruptedException ie) {
104: if (logger.isLoggable(Level.SEVERE)) {
105: logger.log(Level.SEVERE, "failed to connect the zookeeper server. zkClient=" + this.zkClient, ie);
106: }
107: Thread.currentThread().interrupt();
108: this.zkClient = null;
109: }
110: if (!isZkConnected) {
111: if (logger.isLoggable(Level.SEVERE)) {
112: logger.log(Level.SEVERE, "failed to connect the zookeeper server. zkClient=" + this.zkClient);
113: }
114: this.zkClient = null;
115: }
116: } else {
117: this.zkClient = null;
118: }
119: }
120:
121: /**
122: * {@inheritDoc}
123: */
124: @Override
125: public <K, V> GrizzlyMemcachedCache.Builder<K, V> createCacheBuilder(final String cacheName) {
126: return new GrizzlyMemcachedCache.Builder<K, V>(cacheName, this, transport);
127: }
128:
129: /**
130: * {@inheritDoc}
131: */
132: @SuppressWarnings("unchecked")
133: @Override
134: public <K, V> GrizzlyMemcachedCache<K, V> getCache(final String cacheName) {
135: if (shutdown.get()) {
136: return null;
137: }
138: return cacheName != null ? (GrizzlyMemcachedCache<K, V>) caches.get(cacheName) : null;
139: }
140:
141: /**
142: * {@inheritDoc}
143: */
144: @Override
145: public boolean removeCache(final String cacheName) {
146: if (shutdown.get()) {
147: return false;
148: }
149: if (cacheName == null)
150: return false;
151: final GrizzlyMemcachedCache cache = caches.remove(cacheName);
152: if (cache == null) {
153: return false;
154: }
155: cache.stop();
156: return true;
157: }
158:
159: /**
160: * {@inheritDoc}
161: */
162: @Override
163: public void shutdown() {
164: if (!shutdown.compareAndSet(false, true)) {
165: return;
166: }
167: for (MemcachedCache cache : caches.values()) {
168: cache.stop();
169: }
170: caches.clear();
171: if (!isExternalTransport && transport != null) {
172: try {
173: transport.shutdownNow();
174: } catch (IOException ie) {
175: if (logger.isLoggable(Level.INFO)) {
176: logger.log(Level.INFO, "failed to stop the transport", ie);
177: }
178: }
179: }
180: if (zkClient != null) {
181: zkClient.shutdown();
182: }
183: }
184:
185: /**
186: * Add the given {@code cache} to this cache manager
187: * <p>
188: * If this returns false, the given {@code cache} should be stopped by caller.
189: * Currently, this method is called by only {@link org.glassfish.grizzly.memcached.GrizzlyMemcachedCache.Builder#build()}.
190: *
191: * @param cache a cache instance
192: * @return true if the cache was added
193: */
194: <K, V> boolean addCache(final GrizzlyMemcachedCache<K, V> cache) {
195: return !shutdown.get() &&
196: cache != null && caches.putIfAbsent(cache.getName(), cache) == null &&
197: !(shutdown.get() && caches.remove(cache.getName()) == cache);
198: }
199:
200: ZKClient getZkClient() {
201: return zkClient;
202: }
203:
204: public static class Builder {
205:
206: private TCPNIOTransport transport;
207:
208: // grizzly config
209: private int selectorRunnersCount = Runtime.getRuntime().availableProcessors() * 2;
210: private IOStrategy ioStrategy = SameThreadIOStrategy.getInstance();
211: private boolean blocking = false;
212: private ExecutorService workerThreadPool;
213:
214: // zookeeper config
215: private ZooKeeperConfig zooKeeperConfig;
216:
217: /**
218: * Set the specific {@link TCPNIOTransport GrizzlyTransport}
219: * <p>
220: * If this is not set or set to be null, {@link GrizzlyMemcachedCacheManager} will create a default transport.
221: * The given {@code transport} must be always started state if it is not null.
222: * Default is null.
223: *
224: * @param transport the specific Grizzly's {@link TCPNIOTransport}
225: * @return this builder
226: */
227: public Builder transport(final TCPNIOTransport transport) {
228: this.transport = transport;
229: return this;
230: }
231:
232: /**
233: * Set selector threads' count
234: * <p>
235: * If this cache manager will create a default transport, the given selector counts will be passed to {@link TCPNIOTransport}.
236: * Default is processors' count * 2.
237: *
238: * @param selectorRunnersCount selector threads' count
239: * @return this builder
240: */
241: public Builder selectorRunnersCount(final int selectorRunnersCount) {
242: this.selectorRunnersCount = selectorRunnersCount;
243: return this;
244: }
245:
246: /**
247: * Set the specific IO Strategy of Grizzly
248: * <p>
249: * If this cache manager will create a default transport, the given {@link IOStrategy} will be passed to {@link TCPNIOTransport}.
250: * Default is {@link SameThreadIOStrategy}.
251: *
252: * @param ioStrategy the specific IO Strategy
253: * @return this builder
254: */
255: public Builder ioStrategy(final IOStrategy ioStrategy) {
256: this.ioStrategy = ioStrategy;
257: return this;
258: }
259:
260: /**
261: * Enable or disable the blocking mode
262: * <p>
263: * If this cache manager will create a default transport, the given mode will be passed to {@link TCPNIOTransport}.
264: * Default is false.
265: *
266: * @param blocking true means the blocking mode
267: * @return this builder
268: */
269: public Builder blocking(final boolean blocking) {
270: this.blocking = blocking;
271: return this;
272: }
273:
274: /**
275: * Set the specific worker thread pool
276: * <p>
277: * If this cache manager will create a default transport, the given {@link ExecutorService} will be passed to {@link TCPNIOTransport}.
278: * This is only effective if {@link IOStrategy} is not {@link SameThreadIOStrategy}.
279: * Default is null.
280: *
281: * @param workerThreadPool worker thread pool
282: * @return this builder
283: */
284: public Builder workerThreadPool(final ExecutorService workerThreadPool) {
285: this.workerThreadPool = workerThreadPool;
286: return this;
287: }
288:
289: /**
290: * Set the {@link ZooKeeperConfig} for synchronizing cache server list among cache clients
291: *
292: * @param zooKeeperConfig zookeeper config. if {@code zooKeeperConfig} is null, the zookeeper is never used.
293: * @return this builder
294: */
295: public Builder zooKeeperConfig(final ZooKeeperConfig zooKeeperConfig) {
296: this.zooKeeperConfig = zooKeeperConfig;
297: return this;
298: }
299:
300: /**
301: * Create a {@link GrizzlyMemcachedCacheManager} instance with this builder's properties
302: *
303: * @return a cache manager
304: */
305: public GrizzlyMemcachedCacheManager build() {
306: return new GrizzlyMemcachedCacheManager(this);
307: }
308: }
309: }