/*
* Copyright (c) 2008-2012, Hazel Bilisim Ltd. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hazelcast.impl.management;
import com.hazelcast.config.GroupConfig;
import com.hazelcast.config.ManagementCenterConfig;
import com.hazelcast.core.*;
import com.hazelcast.core.Instance.InstanceType;
import com.hazelcast.impl.*;
import com.hazelcast.impl.management.DetectDeadlockRequest.Edge;
import com.hazelcast.impl.management.DetectDeadlockRequest.Vertex;
import com.hazelcast.impl.management.LockInformationCallable.MapLockState;
import com.hazelcast.impl.monitor.*;
import com.hazelcast.logging.ILogger;
import com.hazelcast.monitor.MemberState;
import com.hazelcast.monitor.TimedClusterState;
import com.hazelcast.monitor.TimedMemberState;
import com.hazelcast.nio.Address;
import com.hazelcast.nio.PipedZipBufferFactory;
import com.hazelcast.nio.PipedZipBufferFactory.DeflatingPipedBuffer;
import com.hazelcast.nio.PipedZipBufferFactory.InflatingPipedBuffer;
import com.hazelcast.partition.Partition;
import com.hazelcast.partition.PartitionService;
import java.io.*;
import java.lang.management.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.regex.Pattern;
import java.util.zip.Deflater;
public class ManagementCenterService implements MembershipListener, LifecycleListener {
private static final int DATAGRAM_BUFFER_SIZE = 64 * 1024;
private final Queue<ClientHandler> qClientHandlers = new LinkedBlockingQueue<ClientHandler>(100);
private final FactoryImpl factory;
private volatile boolean running = true;
private DatagramSocket datagramSocket;
private SocketReadyServerSocket serverSocket;
private UDPListener udpListener;
private UDPSender udpSender;
private TCPListener tcpListener;
private TaskPoller taskPoller;
private StateSender stateSender;
private final List<ClientHandler> lsClientHandlers = new CopyOnWriteArrayList<ClientHandler>();
private final ILogger logger;
private final ConcurrentMap<Address, MemberState> memberStates = new ConcurrentHashMap<Address, MemberState>(1000);
private final ConcurrentMap<Address, SocketAddress> socketAddresses = new ConcurrentHashMap<Address, SocketAddress>(1000);
private final Set<Address> addresses = new CopyOnWriteArraySet<Address>(); // should be ordered, thread-safe Set
private volatile MemberStateImpl latestThisMemberState = null;
private final Address thisAddress;
private final ConsoleCommandHandler commandHandler;
private final StatsInstanceFilter instanceFilterMap;
private final StatsInstanceFilter instanceFilterQueue;
private final StatsInstanceFilter instanceFilterTopic;
private final StatsInstanceFilter instanceFilterAtomicNumber;
private final StatsInstanceFilter instanceFilterCountDownLatch;
private final StatsInstanceFilter instanceFilterSemaphore;
private final int maxVisibleInstanceCount;
private final AtomicBoolean started = new AtomicBoolean(false);
private final String webServerUrl;
private final int updateIntervalMs;
@SuppressWarnings("CallToThreadStartDuringObjectConstruction")
public ManagementCenterService(FactoryImpl factoryImpl) throws Exception {
this.factory = factoryImpl;
final ManagementCenterConfig config = factory.node.config.getManagementCenterConfig();
this.instanceFilterMap = new StatsInstanceFilter(factoryImpl.node.getGroupProperties().MC_MAP_EXCLUDES.getString());
this.instanceFilterQueue = new StatsInstanceFilter(factoryImpl.node.getGroupProperties().MC_QUEUE_EXCLUDES.getString());
this.instanceFilterTopic = new StatsInstanceFilter(factoryImpl.node.getGroupProperties().MC_TOPIC_EXCLUDES.getString());
this.instanceFilterAtomicNumber = new StatsInstanceFilter(factoryImpl.node.getGroupProperties().MC_ATOMIC_NUMBER_EXCLUDES.getString());
this.instanceFilterCountDownLatch = new StatsInstanceFilter(factoryImpl.node.getGroupProperties().MC_COUNT_DOWN_LATCH_EXCLUDES.getString());
this.instanceFilterSemaphore = new StatsInstanceFilter(factoryImpl.node.getGroupProperties().MC_SEMAPHORE_EXCLUDES.getString());
updateMemberOrder();
logger = factory.node.getLogger(ManagementCenterService.class.getName());
maxVisibleInstanceCount = factory.node.groupProperties.MC_MAX_INSTANCE_COUNT.getInteger();
commandHandler = new ConsoleCommandHandler(factory);
String tmpWebServerUrl = config != null ? config.getUrl() : null;
webServerUrl = tmpWebServerUrl != null ?
(!tmpWebServerUrl.endsWith("/") ? tmpWebServerUrl + '/' : tmpWebServerUrl) : tmpWebServerUrl;
updateIntervalMs = (config != null && config.getUpdateInterval() > 0) ? config.getUpdateInterval() * 1000 : 3000;
factory.getCluster().addMembershipListener(this);
factory.getLifecycleService().addLifecycleListener(this);
final MemberImpl memberLocal = (MemberImpl) factory.getCluster().getLocalMember();
thisAddress = memberLocal.getAddress();
if (factory.node.groupProperties.MANCENTER_ENABLED.getBoolean()) {
int port = calculatePort(thisAddress);
datagramSocket = new DatagramSocket(port);
serverSocket = new SocketReadyServerSocket(port, 1000, factory.node.config.isReuseAddress());
udpListener = new UDPListener(datagramSocket, 1000, factory.node.config.isReuseAddress());
udpSender = new UDPSender(datagramSocket);
tcpListener = new TCPListener(serverSocket);
for (int i = 0; i < 100; i++) {
qClientHandlers.offer(new ClientHandler(i));
}
udpSender.start();
tcpListener.start();
udpListener.start();
logger.log(Level.INFO, "Hazelcast Management Center started at port " + port + ".");
}
if (config != null && config.isEnabled()) {
if (config.getUrl() != null) {
taskPoller = new TaskPoller();
stateSender = new StateSender();
taskPoller.start();
stateSender.start();
logger.log(Level.INFO, "Hazelcast Management Center is listening from " + config.getUrl());
} else {
logger.log(Level.WARNING, "Hazelcast Management Center Web server url is null!");
}
}
running = true; // volatile-write
}
public void shutdown() {
if (!running) return;
logger.log(Level.INFO, "Shutting down Hazelcast Management Center");
running = false;
try {
if (datagramSocket != null) {
datagramSocket.close();
}
} catch (Throwable ignored) {
}
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (Throwable ignored) {
}
try {
interruptThread(udpSender);
interruptThread(stateSender);
interruptThread(taskPoller);
for (ClientHandler clientHandler : lsClientHandlers) {
clientHandler.shutdown();
}
lsClientHandlers.clear();
} catch (Throwable ignored) {
}
}
private void interruptThread(Thread t) {
if (t != null) {
t.interrupt();
}
}
public void memberAdded(MembershipEvent membershipEvent) {
updateMemberOrder();
}
public void memberRemoved(MembershipEvent membershipEvent) {
Address address = ((MemberImpl) membershipEvent.getMember()).getAddress();
memberStates.remove(address);
socketAddresses.remove(address);
addresses.remove(address);
}
private void updateMemberOrder() {
try {
Set<Member> memberSet = factory.getCluster().getMembers();
for (Member member : memberSet) {
MemberImpl memberImpl = (MemberImpl) member;
Address address = memberImpl.getAddress();
try {
if (!socketAddresses.containsKey(address)) {
SocketAddress socketAddress = new InetSocketAddress(address.getInetAddress(), calculatePort(address));
socketAddresses.putIfAbsent(address, socketAddress);
}
addresses.add(address);
} catch (UnknownHostException e) {
logger.log(Level.WARNING, e.getMessage(), e);
}
}
} catch (Throwable e) {
if (running && factory.node.isActive()) {
logger.log(Level.WARNING, e.getMessage(), e);
}
}
}
private int calculatePort(final Address address) {
int port = (address.getPort() - factory.node.config.getPort())
+ factory.node.getGroupProperties().MC_PORT.getInteger();
return port;
}
boolean login(String groupName, String password) {
logger.log(Level.INFO, "Management Center Client is trying to login.");
GroupConfig groupConfig = factory.getConfig().getGroupConfig();
return groupConfig.getName().equals(groupName) && groupConfig.getPassword().equals(password);
}
List<Edge> detectDeadlock() {
Collection<Map<String, MapLockState>> collection =
(Collection<Map<String, MapLockState>>) callOnAllMembers(new LockInformationCallable());
List<Vertex> graph = new ArrayList<Vertex>();
for (Map<String, MapLockState> mapLockStateMap : collection) {
for (MapLockState map : mapLockStateMap.values()) {
for (Object key : map.getLockOwners().keySet()) {
Vertex owner = new Vertex(map.getLockOwners().get(key));
Vertex requester = new Vertex(map.getLockRequested().get(key));
int index = graph.indexOf(owner);
if (index >= 0) {
owner = graph.get(index);
} else {
graph.add(owner);
}
index = graph.indexOf(requester);
if (index >= 0) {
requester = graph.get(index);
} else {
graph.add(requester);
}
Edge edge = new Edge();
edge.from = requester;
edge.to = owner;
edge.key = key;
edge.mapName = map.getMapName();
edge.globalLock = map.isGlobalLock();
owner.addIncoming(edge);
requester.addOutgoing(edge);
}
}
}
List<Edge> list = new ArrayList<Edge>();
if (graph != null && graph.size() > 0) {
try {
graph.get(0).visit(list);
} catch (RuntimeException e) {
}
}
return list;
}
class TCPListener extends Thread {
final SocketReadyServerSocket serverSocket;
TCPListener(SocketReadyServerSocket serverSocket) {
super(factory.node.threadGroup, factory.node.getThreadNamePrefix("MC.TCP.Listener"));
this.serverSocket = serverSocket;
}
public void run() {
try {
while (running) {
final ClientHandler clientHandler = qClientHandlers.poll();
if (clientHandler == null) {
logger.log(Level.SEVERE, "ClientHandler pool exhausted! Try to connect another node...");
break;
}
try {
serverSocket.doAccept(clientHandler.getSocket());
} catch (SocketTimeoutException e) {
qClientHandlers.offer(clientHandler);
continue;
}
clientHandler.start();
}
} catch (Throwable throwable) {
if (running) {
logger.log(Level.FINEST, "ManagementCenter will be closed due to exception.", throwable);
}
shutdown();
}
}
}
class StateSender extends Thread {
final String host;
StateSender() {
super(factory.node.threadGroup, factory.node.getThreadNamePrefix("MC.State.Sender"));
this.host = webServerUrl;
}
public void run() {
if (host == null) {
logger.log(Level.WARNING, "Web server url is null!");
return;
}
try {
while (running) {
if (started.get()) {
try {
URL url = new URL(host + "collector.do");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setConnectTimeout(1000);
connection.setReadTimeout(1000);
final DataOutputStream out = new DataOutputStream(connection.getOutputStream());
TimedMemberState ts = getTimedMemberState();
ts.writeData(out);
out.flush();
connection.getInputStream();
} catch (Exception e) {
logger.log(Level.FINEST, e.getMessage(), e);
}
}
Thread.sleep(updateIntervalMs);
}
} catch (Throwable throwable) {
logger.log(Level.FINEST, "Web Management Center will be closed due to exception.", throwable);
shutdown();
}
}
}
class TaskPoller extends Thread {
final ConsoleRequest[] consoleRequests = new ConsoleRequest[10];
final String host;
TaskPoller() {
super(factory.node.threadGroup, factory.node.getThreadNamePrefix("MC.Task.Poller"));
this.host = webServerUrl;
register(new LoginRequest());
register(new GetClusterStateRequest());
register(new ThreadDumpRequest());
register(new ExecuteScriptRequest());
register(new EvictLocalMapRequest());
register(new ConsoleCommandRequest());
register(new MapConfigRequest());
}
public void register(ConsoleRequest consoleRequest) {
consoleRequests[consoleRequest.getType()] = consoleRequest;
}
public void sendResponse(int taskId, ConsoleRequest request) {
try {
URL url = new URL(host + "putResponse.do");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setConnectTimeout(1000);
connection.setReadTimeout(1000);
OutputStream outputStream = connection.getOutputStream();
DataOutputStream output = new DataOutputStream(outputStream);
output.writeInt(taskId);
output.writeInt(request.getType());
request.writeResponse(ManagementCenterService.this, output);
connection.getInputStream();
} catch (Exception e) {
logger.log(Level.FINEST, e.getMessage(), e);
}
}
public void run() {
if (host == null) {
logger.log(Level.WARNING, "Web server url is null!");
return;
}
try {
Random rand = new Random();
Address address = ((MemberImpl) factory.node.getClusterImpl().getLocalMember()).getAddress();
GroupConfig groupConfig = factory.getConfig().getGroupConfig();
while (running) {
try {
URL url = new URL(host + "getTask.do?member=" + address.getHost() + ":" + address.getPort() + "&cluster=" + groupConfig.getName());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Connection", "keep-alive");
InputStream inputStream = connection.getInputStream();
DataInputStream input = new DataInputStream(inputStream);
int taskId = input.readInt();
if (taskId > 0) {
int requestType = input.readInt();
ConsoleRequest request = consoleRequests[requestType];
request.readData(input);
sendResponse(taskId, request);
}
} catch (Exception e) {
logger.log(Level.FINEST, e.getMessage(), e);
}
Thread.sleep(700 + rand.nextInt(300));
}
} catch (Throwable throwable) {
logger.log(Level.FINEST, "Web Management Center will be closed due to exception.", throwable);
}
}
}
class UDPListener extends Thread {
final DatagramSocket socket;
final InflatingPipedBuffer buffer = PipedZipBufferFactory.createInflatingBuffer(DATAGRAM_BUFFER_SIZE);
final DatagramPacket packet = new DatagramPacket(buffer.getInputBuffer().array(), DATAGRAM_BUFFER_SIZE);
public UDPListener(DatagramSocket socket, int timeout, boolean reuseAddress) throws SocketException {
super(factory.node.threadGroup, factory.node.getThreadNamePrefix("MC.UDP.Listener"));
this.socket = socket;
this.socket.setSoTimeout(timeout);
this.socket.setReuseAddress(reuseAddress);
}
public void run() {
try {
while (running) {
try {
buffer.reset();
socket.receive(packet);
buffer.inflate(packet.getLength());
MemberStateImpl memberState = new MemberStateImpl();
memberState.readData(buffer.getDataInput());
memberStates.put(memberState.getAddress(), memberState);
} catch (SocketTimeoutException ignored) {
}
}
} catch (Throwable e) {
if (running && factory.node.isActive()) {
logger.log(Level.WARNING, e.getMessage(), e);
}
} finally {
buffer.destroy();
packet.setData(new byte[0]);
}
}
}
private class UDPSender extends Thread {
final DatagramSocket socket;
final DatagramPacket packet = new DatagramPacket(new byte[0], 0);
final DeflatingPipedBuffer buffer = PipedZipBufferFactory.createDeflatingBuffer(DATAGRAM_BUFFER_SIZE, Deflater.BEST_SPEED);
public UDPSender(DatagramSocket socket) throws SocketException {
super(factory.node.threadGroup, factory.node.getThreadNamePrefix("MC.UDP.Sender"));
this.socket = socket;
}
public void run() {
try {
while (running) {
if (started.get()) {
updateLocalState();
sendState();
}
//noinspection BusyWait
Thread.sleep(5000);
}
} catch (Throwable e) {
if (running && factory.node.isActive()) {
logger.log(Level.WARNING, e.getMessage(), e);
}
} finally {
buffer.destroy();
packet.setData(new byte[0]);
}
}
private void sendState() {
boolean preparedStateData = false;
int compressedCount = 0;
for (Address address : socketAddresses.keySet()) {
if (!thisAddress.equals(address)) {
final SocketAddress socketAddress = socketAddresses.get(address);
if (socketAddress != null) {
try {
if (!preparedStateData) {
compressedCount = prepareStateData();
preparedStateData = true;
}
packet.setData(buffer.getOutputBuffer().array(), 0, compressedCount);
packet.setSocketAddress(socketAddress);
socket.send(packet);
} catch (IOException e) {
if (running && factory.node.isActive()) {
logger.log(Level.WARNING, e.getMessage(), e);
}
}
}
}
}
}
private int prepareStateData() throws IOException {
final MemberState latestState = latestThisMemberState;
buffer.reset();
if (latestState != null) {
latestState.writeData(buffer.getDataOutput());
return buffer.deflate();
}
return 0;
}
}
private void updateLocalState() {
if (started.get()) {
latestThisMemberState = createMemberState();
memberStates.put(latestThisMemberState.getAddress(), latestThisMemberState);
}
}
class LazyDataInputStream extends DataInputStream {
LazyDataInputStream() {
super(null);
}
void setInputStream(InputStream in) {
super.in = in;
}
}
private MemberStateImpl createMemberState() {
if (started.get()) {
final MemberStateImpl memberState = new MemberStateImpl();
createMemberState(memberState);
return memberState;
}
return null;
}
private void createMemberState(MemberStateImpl memberState) {
final Node node = factory.node;
memberState.setAddress(thisAddress);
memberState.getMemberHealthStats().setOutOfMemory(node.isOutOfMemory());
memberState.getMemberHealthStats().setActive(node.isActive());
memberState.getMemberHealthStats().setServiceThreadStats(node.getCpuUtilization().serviceThread);
memberState.getMemberHealthStats().setOutThreadStats(node.getCpuUtilization().outThread);
memberState.getMemberHealthStats().setInThreadStats(node.getCpuUtilization().inThread);
PartitionService partitionService = factory.getPartitionService();
Set<Partition> partitions = partitionService.getPartitions();
memberState.clearPartitions();
for (Partition partition : partitions) {
if (partition.getOwner() != null && partition.getOwner().localMember()) {
memberState.addPartition(partition.getPartitionId());
}
}
Collection<HazelcastInstanceAwareInstance> proxyObjects = new ArrayList<HazelcastInstanceAwareInstance>(factory.getProxies());
createMemState(memberState, proxyObjects.iterator(), InstanceType.MAP);
createMemState(memberState, proxyObjects.iterator(), InstanceType.QUEUE);
createMemState(memberState, proxyObjects.iterator(), InstanceType.TOPIC);
createRuntimeProps(memberState);
// uncomment when client changes are made
//createMemState(memberState, proxyObjects.iterator(), InstanceType.ATOMIC_LONG);
//createMemState(memberState, proxyObjects.iterator(), InstanceType.COUNT_DOWN_LATCH);
//createMemState(memberState, proxyObjects.iterator(), InstanceType.SEMAPHORE);
}
private void createRuntimeProps(MemberStateImpl memberState) {
Runtime runtime = Runtime.getRuntime();
ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
ClassLoadingMXBean clMxBean = ManagementFactory.getClassLoadingMXBean();
MemoryMXBean memoryMxBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heapMemory = memoryMxBean.getHeapMemoryUsage();
MemoryUsage nonHeapMemory = memoryMxBean.getNonHeapMemoryUsage();
Map<String, Long> map = new HashMap<String, Long>();
map.put("runtime.availableProcessors", Integer.valueOf(runtime.availableProcessors()).longValue());
map.put("date.startTime", runtimeMxBean.getStartTime());
map.put("seconds.upTime", runtimeMxBean.getUptime());
map.put("memory.maxMemory", runtime.maxMemory());
map.put("memory.freeMemory", runtime.freeMemory());
map.put("memory.totalMemory", runtime.totalMemory());
map.put("memory.heapMemoryMax", heapMemory.getMax());
map.put("memory.heapMemoryUsed", heapMemory.getUsed());
map.put("memory.nonHeapMemoryMax", nonHeapMemory.getMax());
map.put("memory.nonHeapMemoryUsed", nonHeapMemory.getUsed());
map.put("runtime.totalLoadedClassCount", clMxBean.getTotalLoadedClassCount());
map.put("runtime.loadedClassCount", Integer.valueOf(clMxBean.getLoadedClassCount()).longValue());
map.put("runtime.unloadedClassCount", clMxBean.getUnloadedClassCount());
map.put("runtime.totalStartedThreadCount", threadMxBean.getTotalStartedThreadCount());
map.put("runtime.threadCount", Integer.valueOf(threadMxBean.getThreadCount()).longValue());
map.put("runtime.peakThreadCount", Integer.valueOf(threadMxBean.getPeakThreadCount()).longValue());
map.put("runtime.daemonThreadCount", Integer.valueOf(threadMxBean.getDaemonThreadCount()).longValue());
memberState.setRuntimeProps(map);
}
private void createMemState(MemberStateImpl memberState,
Iterator<HazelcastInstanceAwareInstance> it,
Instance.InstanceType type) {
int count = 0;
while (it.hasNext()) {
HazelcastInstanceAwareInstance proxyObject = it.next();
if (proxyObject.getInstanceType() == type) {
if (count < maxVisibleInstanceCount) {
if (type.isMap()) {
MProxy mapProxy = (MProxy) proxyObject;
if (instanceFilterMap.visible(mapProxy.getName())) {
memberState.putLocalMapStats(mapProxy.getName(), (LocalMapStatsImpl) mapProxy.getLocalMapStats());
count++;
}
} else if (type.isQueue()) {
QProxy qProxy = (QProxy) proxyObject;
if (instanceFilterQueue.visible(qProxy.getName())) {
memberState.putLocalQueueStats(qProxy.getName(), (LocalQueueStatsImpl) qProxy.getLocalQueueStats());
count++;
}
} else if (type.isTopic()) {
TopicProxy topicProxy = (TopicProxy) proxyObject;
if (instanceFilterTopic.visible(topicProxy.getName())) {
memberState.putLocalTopicStats(topicProxy.getName(), (LocalTopicStatsImpl) topicProxy.getLocalTopicStats());
count++;
}
} else if (type.isAtomicNumber()) {
AtomicNumberProxy atomicLongProxy = (AtomicNumberProxy) proxyObject;
if (instanceFilterAtomicNumber.visible(atomicLongProxy.getName())) {
memberState.putLocalAtomicNumberStats(atomicLongProxy.getName(), (LocalAtomicNumberStatsImpl) atomicLongProxy.getLocalAtomicNumberStats());
count++;
}
} else if (type.isCountDownLatch()) {
CountDownLatchProxy cdlProxy = (CountDownLatchProxy) proxyObject;
if (instanceFilterCountDownLatch.visible(cdlProxy.getName())) {
memberState.putLocalCountDownLatchStats(cdlProxy.getName(), (LocalCountDownLatchStatsImpl) cdlProxy.getLocalCountDownLatchStats());
count++;
}
} else if (type.isSemaphore()) {
SemaphoreProxy semaphoreProxy = (SemaphoreProxy) proxyObject;
if (instanceFilterSemaphore.visible(semaphoreProxy.getName())) {
memberState.putLocalSemaphoreStats(semaphoreProxy.getName(), (LocalSemaphoreStatsImpl) semaphoreProxy.getLocalSemaphoreStats());
count++;
}
}
}
it.remove();
}
}
}
private Set<String> getLongInstanceNames() {
Set<String> setLongInstanceNames = new HashSet<String>(maxVisibleInstanceCount);
Collection<HazelcastInstanceAwareInstance> proxyObjects = new ArrayList<HazelcastInstanceAwareInstance>(factory.getProxies());
collectInstanceNames(setLongInstanceNames, proxyObjects.iterator(), InstanceType.MAP);
collectInstanceNames(setLongInstanceNames, proxyObjects.iterator(), InstanceType.QUEUE);
collectInstanceNames(setLongInstanceNames, proxyObjects.iterator(), InstanceType.TOPIC);
// uncomment when client changes are made
// collectInstanceNames(setLongInstanceNames, proxyObjects.iterator(), InstanceType.ATOMIC_NUMBER);
// collectInstanceNames(setLongInstanceNames, proxyObjects.iterator(), InstanceType.COUNT_DOWN_LATCH);
// collectInstanceNames(setLongInstanceNames, proxyObjects.iterator(), InstanceType.SEMAPHORE);
return setLongInstanceNames;
}
private void collectInstanceNames(Set<String> setLongInstanceNames,
Iterator<HazelcastInstanceAwareInstance> it,
Instance.InstanceType type) {
int count = 0;
while (it.hasNext()) {
HazelcastInstanceAwareInstance proxyObject = it.next();
if (proxyObject.getInstanceType() == type) {
if (count < maxVisibleInstanceCount) {
if (type.isMap()) {
MProxy mapProxy = (MProxy) proxyObject;
if (instanceFilterMap.visible(mapProxy.getName())) {
setLongInstanceNames.add(mapProxy.getLongName());
count++;
}
} else if (type.isQueue()) {
QProxy qProxy = (QProxy) proxyObject;
if (instanceFilterQueue.visible(qProxy.getName())) {
setLongInstanceNames.add(qProxy.getLongName());
count++;
}
} else if (type.isTopic()) {
TopicProxy topicProxy = (TopicProxy) proxyObject;
if (instanceFilterTopic.visible(topicProxy.getName())) {
setLongInstanceNames.add(topicProxy.getLongName());
count++;
}
} else if (type.isAtomicNumber()) {
AtomicNumberProxy atomicLongProxy = (AtomicNumberProxy) proxyObject;
if (instanceFilterAtomicNumber.visible(atomicLongProxy.getName())) {
setLongInstanceNames.add(atomicLongProxy.getLongName());
count++;
}
} else if (type.isCountDownLatch()) {
CountDownLatchProxy cdlProxy = (CountDownLatchProxy) proxyObject;
if (instanceFilterCountDownLatch.visible(cdlProxy.getName())) {
setLongInstanceNames.add(cdlProxy.getLongName());
count++;
}
} else if (type.isSemaphore()) {
SemaphoreProxy semaphoreProxy = (SemaphoreProxy) proxyObject;
if (instanceFilterSemaphore.visible(semaphoreProxy.getName())) {
setLongInstanceNames.add(semaphoreProxy.getLongName());
count++;
}
}
}
it.remove();
}
}
}
class LazyDataOutputStream extends DataOutputStream {
LazyDataOutputStream() {
super(null);
}
void setOutputStream(OutputStream out) {
super.out = out;
}
}
class ClientHandler extends Thread {
final ConsoleRequest[] consoleRequests = new ConsoleRequest[10];
final Socket socket = new Socket();
final LazyDataInputStream socketIn = new LazyDataInputStream();
final LazyDataOutputStream socketOut = new LazyDataOutputStream();
public ClientHandler(int id) {
super(factory.node.threadGroup, factory.node.getThreadPoolNamePrefix("MC.Client.Handler") + id);
register(new LoginRequest());
register(new GetClusterStateRequest());
register(new ThreadDumpRequest());
register(new ExecuteScriptRequest());
register(new EvictLocalMapRequest());
register(new ConsoleCommandRequest());
register(new MapConfigRequest());
register(new DetectDeadlockRequest());
}
private void register(ConsoleRequest consoleRequest) {
consoleRequests[consoleRequest.getType()] = consoleRequest;
}
public Socket getSocket() {
return socket;
}
public void run() {
try {
socketIn.setInputStream(socket.getInputStream());
socketOut.setOutputStream(socket.getOutputStream());
while (running) {
int requestType = socketIn.read();
if (requestType == -1) {
logger.log(Level.WARNING, "Management Center Client connection ["
+ socket.getInetAddress() + "] is closed!");
return;
}
ConsoleRequest consoleRequest = consoleRequests[requestType];
consoleRequest.readData(socketIn);
boolean isOutOfMemory = factory.node.isOutOfMemory();
if (isOutOfMemory) {
socketOut.writeByte(ConsoleRequestConstants.STATE_OUT_OF_MEMORY);
} else {
socketOut.writeByte(ConsoleRequestConstants.STATE_ACTIVE);
consoleRequest.writeResponse(ManagementCenterService.this, socketOut);
}
}
} catch (Throwable e) {
if (running && factory.node.isActive()) {
logger.log(Level.WARNING, e.getMessage(), e);
}
} finally {
shutdown();
}
}
private void shutdown() {
try {
socket.close();
} catch (Throwable ignored) {
}
}
}
Object call(Address address, Callable callable) {
Set<Member> members = factory.getCluster().getMembers();
for (Member member : members) {
if (address.equals(((MemberImpl) member).getAddress())) {
DistributedTask task = new DistributedTask(callable, member);
return executeTaskAndGet(task);
}
}
return null;
}
Object call(Callable callable) {
DistributedTask task = new DistributedTask(callable);
return executeTaskAndGet(task);
}
Collection callOnMembers(Set<Address> addresses, Callable callable) {
Set<Member> allMembers = factory.getCluster().getMembers();
Set<Member> selectedMembers = new HashSet<Member>(addresses.size());
for (Member member : allMembers) {
if (addresses.contains(((MemberImpl) member).getAddress())) {
selectedMembers.add(member);
}
}
return callOnMembers0(selectedMembers, callable);
}
Collection callOnAllMembers(Callable callable) {
Set<Member> members = factory.getCluster().getMembers();
return callOnMembers0(members, callable);
}
private Collection callOnMembers0(Set<Member> members, Callable callable) {
MultiTask task = new MultiTask(callable, members);
return (Collection) executeTaskAndGet(task);
}
private Object executeTaskAndGet(final DistributedTask task) {
try {
factory.getExecutorService().execute(task);
try {
return task.get(3, TimeUnit.SECONDS);
} catch (Throwable e) {
logger.log(Level.FINEST, e.getMessage(), e);
return null;
}
} catch (Throwable e) {
if (running && factory.node.isActive()) {
logger.log(Level.WARNING, e.getMessage(), e);
}
return null;
}
}
public TimedMemberState getTimedMemberState() {
if (latestThisMemberState == null) {
updateLocalState();
}
GroupConfig groupConfig = factory.getConfig().getGroupConfig();
TimedMemberState timedMemberState = new TimedMemberState();
timedMemberState.setMaster(factory.node.isMaster());
if (timedMemberState.getMaster()) {
timedMemberState.setMemberList(new ArrayList<String>());
for (Address addr : addresses) {
timedMemberState.getMemberList().add(addr.getHost() + ":" + addr.getPort());
}
}
timedMemberState.setMemberState(latestThisMemberState);
timedMemberState.setClusterName(groupConfig.getName());
timedMemberState.setInstanceNames(getLongInstanceNames());
return timedMemberState;
}
TimedClusterState getState() {
if (latestThisMemberState == null) {
updateLocalState();
}
TimedClusterState timedClusterState = new TimedClusterState();
for (Address address : addresses) {
MemberState memberState = memberStates.get(address);
if (memberState != null) {
timedClusterState.addMemberState(memberState);
}
}
timedClusterState.setInstanceNames(getLongInstanceNames());
return timedClusterState;
}
HazelcastInstance getHazelcastInstance() {
return factory;
}
ConsoleCommandHandler getCommandHandler() {
return commandHandler;
}
public void stateChanged(final LifecycleEvent event) {
started.set(event.getState() == LifecycleEvent.LifecycleState.STARTED);
logger.log(Level.FINEST, "Hazelcast Management Center enabled: " + started.get());
}
public static class SocketReadyServerSocket extends ServerSocket {
public SocketReadyServerSocket(int port, int timeout, boolean reuseAddress) throws IOException {
super(port);
setSoTimeout(timeout);
setReuseAddress(reuseAddress);
}
public void doAccept(Socket socket) throws IOException {
super.implAccept(socket);
}
}
class StatsInstanceFilter {
final Set<Pattern> setExcludes;
final Set<String> setIncludeCache;
final Set<String> setExcludeCache;
StatsInstanceFilter(String excludes) {
if (excludes != null) {
setExcludes = new HashSet<Pattern>();
setIncludeCache = new HashSet<String>();
setExcludeCache = new HashSet<String>();
StringTokenizer st = new StringTokenizer(excludes, ",");
while (st.hasMoreTokens()) {
setExcludes.add(Pattern.compile(st.nextToken().trim()));
}
} else {
setExcludes = null;
setIncludeCache = null;
setExcludeCache = null;
}
}
boolean visible(String instanceName) {
if (setExcludes == null) {
return true;
}
if (setIncludeCache.contains(instanceName)) {
return true;
}
if (setExcludeCache.contains(instanceName)) {
return false;
}
for (Pattern pattern : setExcludes) {
if (pattern.matcher(instanceName).matches()) {
setExcludeCache.add(instanceName);
return false;
}
}
setIncludeCache.add(instanceName);
return true;
}
}
}