/* * 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 net.grinder; import net.grinder.common.GrinderException; import net.grinder.common.GrinderProperties; import net.grinder.common.processidentity.AgentIdentity; import net.grinder.console.common.Resources; import net.grinder.console.common.ResourcesImplementation; import net.grinder.console.communication.*; import net.grinder.console.communication.AgentProcessControlImplementation.AgentStatus; import net.grinder.console.model.ConsoleCommunicationSetting; import net.grinder.console.model.ConsoleProperties; import net.grinder.engine.communication.AgentUpdateGrinderMessage; import net.grinder.message.console.AgentControllerState; import net.grinder.messages.agent.StartGrinderMessage; import net.grinder.messages.agent.StopGrinderMessage; import net.grinder.messages.console.AgentAddress; import net.grinder.util.ConsolePropertiesFactory; import net.grinder.util.thread.Condition; import org.ngrinder.monitor.controller.model.SystemDataModel; import org.python.google.common.base.Predicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Set; import static org.ngrinder.common.util.ExceptionUtils.processException; /** * Daemon for AgentControllerServer. * * @author JunHo Yoon */ public class AgentControllerServerDaemon { private final ConsoleProperties consoleProperties; private Thread thread; private AgentControllerServer agentControllerServer; public static final Resources RESOURCES = new ResourcesImplementation( "net.grinder.console.common.resources.Console"); private final Condition m_eventSyncCondition = new Condition(); public static final Logger LOGGER = LoggerFactory.getLogger(RESOURCES.getString("shortTitle")); private static final long AGENT_CONTROLLER_SERVER_SHUTDOWN_WAITING_TIMEOUT = 10000; private static final long AGENT_CONTROLLER_SERVER_EVENT_EXPIRATION_TIMEOUT = 10000; /** * Agent controller daemon constructor with default * {@link ConsoleProperties}. * * @param ip IP * @param port port */ public AgentControllerServerDaemon(String ip, int port, ConsoleCommunicationSetting consoleCommunicationSetting) { this(ip, port, ConsolePropertiesFactory.createEmptyConsoleProperties(), consoleCommunicationSetting); } /** * Agent controller daemon constructor. * * @param ip IP * @param port port * @param consoleProperties default property. */ public AgentControllerServerDaemon(String ip, int port, ConsoleProperties consoleProperties, ConsoleCommunicationSetting consoleCommunicationSetting) { this.consoleProperties = consoleProperties; try { this.consoleProperties.setConsoleHost(ip); this.consoleProperties.setConsolePort(port); this.agentControllerServer = new AgentControllerServer(RESOURCES, LOGGER, consoleProperties, m_eventSyncCondition, consoleCommunicationSetting); } catch (GrinderException e) { throw processException("Exception occurred while initiating the agent controller server daemon", e); } } /** * Get port. * * @return port */ public int getPort() { return this.consoleProperties.getConsolePort(); } /** * Constructor. * * @param port port used. */ public AgentControllerServerDaemon(int port) { this("", port, ConsoleCommunicationSetting.asDefault()); } /** * Start {@link AgentControllerServer} in the daemon thread. */ public void start() { thread = new Thread(new Runnable() { public void run() { startSync(); } }); thread.setName("Agent controller server thread"); thread.setDaemon(true); thread.start(); synchronized (m_eventSyncCondition) { m_eventSyncCondition.waitNoInterrruptException(AGENT_CONTROLLER_SERVER_EVENT_EXPIRATION_TIMEOUT); } } /** * For test. */ public void startSync() { agentControllerServer.run(); } /** * Shutdown {@link AgentControllerServer}. */ public void shutdown() { try { agentControllerServer.shutdown(); if (thread != null) { thread.join(AGENT_CONTROLLER_SERVER_SHUTDOWN_WAITING_TIMEOUT); thread.interrupt(); } } catch (Exception e) { throw processException("Exception occurred during shutting down the agent controller server daemon", e); } finally { thread = null; } } public int getAllAttachedAgentsCount() { return agentControllerServer.getComponent(AgentProcessControlImplementation.class) .getNumberOfLiveAgents(); } /** * Add Listener which will be used to save log in somewhere. * * @param logArrivedListener listener */ public void addLogArrivedListener(LogArrivedListener logArrivedListener) { getComponent(AgentProcessControlImplementation.class).addLogArrivedListener(logArrivedListener); } /** * Add Listener which will be used to send the agent download request. * * @param agentDownloadRequestListener listener */ public void setAgentDownloadRequestListener(AgentDownloadRequestListener agentDownloadRequestListener) { getComponent(AgentProcessControlImplementation.class).setAgentDownloadListener(agentDownloadRequestListener); } /** * Get the console port which the given controller's agent is using. * * @param agentIdentity agent identity * @return port */ public int getAgentConnectingPort(AgentIdentity agentIdentity) { return agentControllerServer.getComponent(AgentProcessControlImplementation.class).getAgentConnectingPort( agentIdentity); } /** * Get the agent version of the given agent. * * @param agentIdentity agent identity * @return version */ public String getAgentVersion(AgentIdentity agentIdentity) { return agentControllerServer.getComponent(AgentProcessControlImplementation.class).getAgentVersion(agentIdentity); } /** * Get agent status set matching the given predicate. * * @param predicate predicate * @return {@link AgentStatus} set * @since 3.1.2 */ public Set<AgentStatus> getAgentStatusSet(Predicate<AgentStatus> predicate) { return agentControllerServer.getComponent(AgentProcessControlImplementation.class).getAgentStatusSet(predicate); } /** * Get the agent status of the given agent controller. * * @param agentIdentity agent identity * @return agent controller status */ public AgentControllerState getAgentState(AgentIdentity agentIdentity) { return agentControllerServer.getComponent(AgentProcessControlImplementation.class).getAgentControllerState( agentIdentity); } /** * Get all free agents which is not used yet. * * @return free agent list */ public Set<AgentIdentity> getAllFreeAgents() { return agentControllerServer.getComponent(AgentProcessControlImplementation.class).getAgents( AgentControllerState.READY, 0); } /** * Get {@link SystemDataModel} of the given agent. * * @param agentIdentity agent identity * @return {@link SystemDataModel} instance. */ public SystemDataModel getSystemDataModel(AgentIdentity agentIdentity) { return agentControllerServer.getComponent(AgentProcessControlImplementation.class).getSystemDataModel( agentIdentity); } /** * Get all available agents. * * @return agent set */ public Set<AgentIdentity> getAllAvailableAgents() { return agentControllerServer.getComponent(AgentProcessControlImplementation.class).getAllAgents(); } /** * Get component used in {@link AgentControllerServer}. * * @param componentType component type class * @param <T> component type class * @return <T> the component in consoleFoundation */ public <T> T getComponent(Class<T> componentType) { return agentControllerServer.getComponent(componentType); } /** * Start agent using {@link GrinderProperties}. * * @param grinderProperties base grinder properties * @param agentIdentity agent controller identity */ public void startAgent(GrinderProperties grinderProperties, AgentIdentity agentIdentity) { LOGGER.info("{} agent is started.", agentIdentity); final ConsoleCommunicationImplementationEx component = getComponent(ConsoleCommunicationImplementationEx.class); final AgentAddress address = new AgentAddress(agentIdentity); final String localConnectingAddress = component.getLocalConnectingAddress(address); final GrinderProperties prop = (GrinderProperties) grinderProperties.clone(); prop.setProperty(GrinderProperties.CONSOLE_HOST, localConnectingAddress); component.sendToAddressedAgents(address, new StartGrinderMessage(prop, agentIdentity.getNumber())); } /** * Stop agent. * * @param agentIdentity agent controller identity */ public void stopAgent(AgentIdentity agentIdentity) { LOGGER.info("{} agent is stopped.", agentIdentity); getComponent(ConsoleCommunication.class).sendToAddressedAgents(new AgentAddress(agentIdentity), new StopGrinderMessage()); } /** * Send agent update message to agent * * @param agentIdentity agentIdentity * @param version version */ public void updateAgent(AgentIdentity agentIdentity, String version) { getComponent(ConsoleCommunication.class).sendToAddressedAgents(new AgentAddress(agentIdentity), AgentUpdateGrinderMessage.getStartAgentUpdateGrinderMessage(version)); } }