/*******************************************************************************
* Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.com>
* This file is part of Gluster Management Gateway.
*
* Gluster Management Gateway is free software; you can redistribute
* it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* Gluster Management Gateway is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*******************************************************************************/
package org.gluster.storage.management.gateway.services;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.log4j.Logger;
import org.gluster.storage.management.core.exceptions.GlusterRuntimeException;
import org.gluster.storage.management.core.model.Server;
import org.gluster.storage.management.core.utils.ProcessUtil;
import org.gluster.storage.management.gateway.utils.ServerUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
*
*/
@Component
public class DiscoveredServerService {
@Autowired
protected ServerUtil serverUtil;
private List<String> discoveredServerNames = new ArrayList<String>();
private static final Logger logger = Logger.getLogger(DiscoveredServerService.class);
public List<Server> getDiscoveredServerDetails() {
try {
List<Server> discoveredServers = Collections.synchronizedList(new ArrayList<Server>());
List<Thread> threads = createThreads(discoveredServers);
ProcessUtil.waitForThreads(threads);
return discoveredServers;
} catch (Exception e) {
String errMsg = "Exception while fetching details of discovered servers! Error: [" + e.getMessage() + "]";
logger.error(errMsg, e);
throw new GlusterRuntimeException(errMsg, e);
}
}
/**
* Creates threads that will run in parallel and fetch details of all discovered servers
* @param discoveredServers The list to be populated with details of discovered servers
* @return
* @throws InterruptedException
*/
private List<Thread> createThreads(List<Server> discoveredServers) throws InterruptedException {
List<String> discoveredServerNames = getDiscoveredServerNames();
List<Thread> threads = new ArrayList<Thread>();
for (int i = discoveredServerNames.size() - 1; i >= 0; i--) {
Thread thread = new DiscoveredServerDetailsThread(discoveredServers, discoveredServerNames.get(i));
threads.add(thread);
thread.start();
if (i >= 5 && i % 5 == 0) {
// After every 5 servers, wait for 1 second so that we don't end up with too many running threads
Thread.sleep(1000);
}
}
return threads;
}
public List<String> getDiscoveredServerNames() {
return discoveredServerNames;
}
public void setDiscoveredServerNames(List<String> discoveredServerNames) {
synchronized (discoveredServerNames) {
this.discoveredServerNames = discoveredServerNames;
}
}
public void removeDiscoveredServer(String serverName) {
discoveredServerNames.remove(serverName);
}
public void addDiscoveredServer(String serverName) {
discoveredServerNames.add(serverName);
}
public Server getDiscoveredServer(String serverName) {
Server server = new Server(serverName);
serverUtil.fetchServerDetails(server);
return server;
}
public class DiscoveredServerDetailsThread extends Thread {
private List<Server> servers;
private String serverName;
private final Logger logger = Logger.getLogger(DiscoveredServerDetailsThread.class);
/**
* Private constructor called on each thread
* @param servers The list to be populated with fetched server details
* @param serverName Name of the server whose details should be fetched by this thread
*/
private DiscoveredServerDetailsThread(List<Server> servers, String serverName) {
this.servers = servers;
this.serverName = serverName;
}
@Override
public void run() {
try {
logger.info("fetching details of discovered server [" + serverName + "] - start");
servers.add(getDiscoveredServer(serverName));
logger.info("fetching details of discovered server [" + serverName + "] - end");
} catch(Exception e) {
logger.warn("fetching details of discovered server [" + serverName + "] - error", e);
// eat the exception as we can't consider this server as a discovered server any more
}
}
}
}