Skip to content

Package: CacheServerListBarrierListener

CacheServerListBarrierListener

nameinstructionbranchcomplexitylinemethod
CacheServerListBarrierListener(MemcachedCache, Set)
M: 27 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 8 C: 0
0%
M: 1 C: 0
0%
addCustomListener(BarrierListener)
M: 9 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
getAddressesFromStringList(String)
M: 97 C: 0
0%
M: 10 C: 0
0%
M: 6 C: 0
0%
M: 15 C: 0
0%
M: 1 C: 0
0%
getStringListFromAddressSet(Set)
M: 68 C: 0
0%
M: 10 C: 0
0%
M: 6 C: 0
0%
M: 14 C: 0
0%
M: 1 C: 0
0%
onCommit(String, String, byte[])
M: 173 C: 0
0%
M: 24 C: 0
0%
M: 13 C: 0
0%
M: 34 C: 0
0%
M: 1 C: 0
0%
onDestroy(String)
M: 39 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 8 C: 0
0%
M: 1 C: 0
0%
onInit(String, String, byte[])
M: 148 C: 0
0%
M: 24 C: 0
0%
M: 13 C: 0
0%
M: 28 C: 0
0%
M: 1 C: 0
0%
removeCustomListener(BarrierListener)
M: 9 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
toString()
M: 24 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 2012, 2017 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Public License v. 2.0, which is available at
6: * http://www.eclipse.org/legal/epl-2.0.
7: *
8: * This Source Code may also be made available under the following Secondary
9: * Licenses when the conditions for such availability set forth in the
10: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11: * version 2 with the GNU Classpath Exception, which is available at
12: * https://www.gnu.org/software/classpath/license.html.
13: *
14: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15: */
16:
17: package org.glassfish.grizzly.memcached.zookeeper;
18:
19: import org.glassfish.grizzly.Grizzly;
20: import org.glassfish.grizzly.memcached.MemcachedCache;
21:
22: import java.io.UnsupportedEncodingException;
23: import java.net.InetSocketAddress;
24: import java.net.SocketAddress;
25: import java.util.HashSet;
26: import java.util.List;
27: import java.util.Set;
28: import java.util.concurrent.CopyOnWriteArrayList;
29: import java.util.concurrent.CopyOnWriteArraySet;
30: import java.util.logging.Level;
31: import java.util.logging.Logger;
32:
33: /**
34: * The {@link BarrierListener} implementation for synchronizing the cache server list among all clients which have joined the same zookeeper server
35: *
36: * @author Bongjae Chang
37: */
38: public class CacheServerListBarrierListener implements BarrierListener {
39:
40: private static final Logger logger = Grizzly.logger(CacheServerListBarrierListener.class);
41: public static final String DEFAULT_SERVER_LIST_CHARSET = "UTF-8";
42:
43: protected final MemcachedCache cache;
44: protected final String cacheName;
45: protected final Set<SocketAddress> localCacheServerSet = new CopyOnWriteArraySet<SocketAddress>();
46: private final List<BarrierListener> customListenerList = new CopyOnWriteArrayList<BarrierListener>();
47:
48: public CacheServerListBarrierListener(final MemcachedCache cache, final Set<SocketAddress> cacheServerSet) {
49: this.cache = cache;
50: this.cacheName = cache.getName();
51:• if (cacheServerSet != null) {
52: this.localCacheServerSet.addAll(cacheServerSet);
53: }
54: }
55:
56: @Override
57: public void onInit(final String regionName, final String path, final byte[] remoteBytes) {
58:• if (remoteBytes == null || remoteBytes.length == 0) {
59: return;
60: }
61: // check the remote cache server list of the zookeeper server is equal to local if the server has pre-defined server list
62: try {
63: final String remoteCacheServerList = new String(remoteBytes, DEFAULT_SERVER_LIST_CHARSET);
64: final Set<SocketAddress> remoteCacheServers = getAddressesFromStringList(remoteCacheServerList);
65: boolean checked = true;
66:• for (final SocketAddress local : localCacheServerSet) {
67:• if (!remoteCacheServers.remove(local)) {
68: checked = false;
69: break;
70: }
71: }
72:• if (checked && !remoteCacheServers.isEmpty()) {
73: checked = false;
74: }
75:• if (!checked) {
76:• if (logger.isLoggable(Level.WARNING)) {
77: logger.log(Level.WARNING,
78: "failed to check the cache server list from the remote. cacheName={0}, local={1}, remote={2}",
79: new Object[]{cacheName, localCacheServerSet, remoteCacheServers});
80: }
81: } else {
82:• if (logger.isLoggable(Level.INFO)) {
83: logger.log(Level.INFO, "cache server list confirmed. cacheName={0}, list=[{1}]", new Object[]{cacheName, remoteCacheServerList});
84: }
85: }
86: } catch (UnsupportedEncodingException uee) {
87:• if (logger.isLoggable(Level.WARNING)) {
88: logger.log(Level.WARNING, "failed to check the cache server list from the remote. cacheName=" + cacheName, uee);
89: }
90: } finally {
91:• for (final BarrierListener listener : customListenerList) {
92: try {
93: listener.onInit(regionName, path, remoteBytes);
94: } catch (Exception e) {
95:• if (logger.isLoggable(Level.WARNING)) {
96: logger.log(Level.WARNING, "failed to call onInit(). cacheName=" + cacheName + ", listener=" + listener, e);
97: }
98: }
99: }
100: }
101: }
102:
103: @Override
104: public void onCommit(final String regionName, final String path, byte[] remoteBytes) {
105:• if (remoteBytes == null || remoteBytes.length == 0) {
106:• if (logger.isLoggable(Level.WARNING)) {
107: logger.log(Level.WARNING, "remote bytes is null or NO_DATA(byte[0]). regionName={0}, path={1}", new Object[]{regionName, path});
108: }
109: return;
110: }
111: try {
112: final String remoteDataString = new String(remoteBytes, DEFAULT_SERVER_LIST_CHARSET);
113: final Set<SocketAddress> remoteCacheServers = getAddressesFromStringList(remoteDataString);
114:• if (!remoteCacheServers.isEmpty()) {
115:• if (cache != null) {
116: final Set<SocketAddress> shouldBeAdded = new HashSet<SocketAddress>();
117: final Set<SocketAddress> shouldBeRemoved = new HashSet<SocketAddress>();
118:• for (final SocketAddress remoteServer : remoteCacheServers) {
119:• if (!localCacheServerSet.remove(remoteServer)) {
120: shouldBeAdded.add(remoteServer);
121: }
122: }
123: shouldBeRemoved.addAll(localCacheServerSet);
124:• for (final SocketAddress address : shouldBeAdded) {
125: cache.addServer(address);
126: }
127:• for (final SocketAddress address : shouldBeRemoved) {
128: cache.removeServer(address);
129: }
130: // refresh local
131: localCacheServerSet.clear();
132: localCacheServerSet.addAll(remoteCacheServers);
133: }
134: }
135: } catch (UnsupportedEncodingException uee) {
136:• if (logger.isLoggable(Level.WARNING)) {
137: logger.log(Level.WARNING,
138: "failed to apply the changed server list of the remote zookeeper server. regionName=" + regionName + ", path=" + path,
139: uee);
140: }
141: } finally {
142:• for (final BarrierListener listener : customListenerList) {
143: try {
144: listener.onCommit(regionName, path, remoteBytes);
145: } catch (Exception e) {
146:• if (logger.isLoggable(Level.WARNING)) {
147: logger.log(Level.WARNING, "failed to call onCommit(). cacheName=" + cacheName + ", listener=" + listener, e);
148: }
149: }
150: }
151: }
152: }
153:
154: @Override
155: public void onDestroy(final String regionName) {
156:• for (final BarrierListener listener : customListenerList) {
157: try {
158: listener.onDestroy(regionName);
159: } catch (Exception e) {
160:• if (logger.isLoggable(Level.WARNING)) {
161: logger.log(Level.WARNING, "failed to call onDestroy(). cacheName=" + cacheName + ", listener=" + listener, e);
162: }
163: }
164: }
165: }
166:
167: public void addCustomListener(final BarrierListener listener) {
168:• if (listener == null) {
169: return;
170: }
171: customListenerList.add(listener);
172: }
173:
174: public void removeCustomListener(final BarrierListener listener) {
175:• if (listener == null) {
176: return;
177: }
178: customListenerList.remove(listener);
179: }
180:
181: @Override
182: public String toString() {
183: return "CacheServerListBarrierListener{" +
184: "cacheName='" + cacheName + '\'' +
185: ", localCacheServerSet=" + localCacheServerSet +
186: ", customListenerList=" + customListenerList +
187: '}';
188: }
189:
190: /**
191: * Split a string in the form of "host:port, host2:port" into a Set of
192: * {@link java.net.SocketAddress} instances.
193: * <p>
194: * Note that colon-delimited IPv6 is also supported. For example: ::1:11211
195: *
196: * @param serverList server list in the form of "host:port,host2:port"
197: * @return server set
198: */
199: public static Set<SocketAddress> getAddressesFromStringList(final String serverList) {
200:• if (serverList == null) {
201: throw new IllegalArgumentException("null host list");
202: }
203:• if (serverList.trim().equals("")) {
204: throw new IllegalArgumentException("no hosts in list: ``" + serverList + "''");
205: }
206: final HashSet<SocketAddress> addrs = new HashSet<SocketAddress>();
207:• for (final String hoststuff : serverList.split("(,| )")) {
208:• if (hoststuff.length() == 0) {
209: continue;
210: }
211: int finalColon = hoststuff.lastIndexOf(':');
212:• if (finalColon < 1) {
213: throw new IllegalArgumentException("Invalid server ``" + hoststuff + "'' in list: " + serverList);
214: }
215: final String hostPart = hoststuff.substring(0, finalColon);
216: final String portNum = hoststuff.substring(finalColon + 1);
217: addrs.add(new InetSocketAddress(hostPart, Integer.parseInt(portNum)));
218: }
219: return addrs;
220: }
221:
222: /**
223: * Convert server set into server list like "host:port,host2:port"
224: *
225: * @param servers {@link InetSocketAddress} set
226: * @return server list in the form of "host:port,host2:port"
227: */
228: public static String getStringListFromAddressSet(final Set<SocketAddress> servers) {
229:• if (servers == null || servers.isEmpty()) {
230: throw new IllegalArgumentException("Null servers");
231: }
232: final StringBuilder builder = new StringBuilder(256);
233:• for (final SocketAddress server : servers) {
234:• if (server instanceof InetSocketAddress) {
235: final InetSocketAddress inetSocketAddress = (InetSocketAddress) server;
236: builder.append(inetSocketAddress.getHostName()).append(':').append(inetSocketAddress.getPort());
237: builder.append(',');
238: }
239: }
240: final String result = builder.toString();
241: final int resultLength = result.length();
242:• if (resultLength < 1) {
243: throw new IllegalArgumentException("there is no InetSocketAddress in the server set");
244: } else {
245: // remove the last comma
246: return result.substring(0, result.length() - 1);
247: }
248: }
249: }