Mercurial > hg > release > thermostat-0.7
changeset 708:da7f134762f6
Make backends OSGi services (and port system backend to its own sub module)
review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-October/003762.html
reviewed-by: omajid
line wrap: on
line diff
--- a/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/AgentApplication.java Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/AgentApplication.java Fri Oct 19 21:58:18 2012 +0200 @@ -40,15 +40,18 @@ import java.util.logging.Level; import java.util.logging.Logger; -import org.apache.commons.cli.Options; +import org.osgi.framework.BundleContext; + +import sun.misc.Signal; +import sun.misc.SignalHandler; import com.redhat.thermostat.agent.Agent; import com.redhat.thermostat.agent.command.ConfigurationServer; import com.redhat.thermostat.agent.config.AgentConfigsUtils; import com.redhat.thermostat.agent.config.AgentOptionParser; import com.redhat.thermostat.agent.config.AgentStartupConfiguration; -import com.redhat.thermostat.backend.BackendLoadException; import com.redhat.thermostat.backend.BackendRegistry; +import com.redhat.thermostat.backend.BackendService; import com.redhat.thermostat.common.Constants; import com.redhat.thermostat.common.LaunchException; import com.redhat.thermostat.common.ThreadPoolTimerFactory; @@ -69,9 +72,6 @@ import com.redhat.thermostat.common.utils.LoggingUtils; import com.redhat.thermostat.common.utils.OSGIUtils; -import sun.misc.Signal; -import sun.misc.SignalHandler; - @SuppressWarnings("restriction") public final class AgentApplication extends BasicCommand { @@ -80,6 +80,12 @@ private AgentStartupConfiguration configuration; private AgentOptionParser parser; + private BundleContext bundleContext; + + public AgentApplication(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + private void parseArguments(Arguments args) throws InvalidConfigurationException { configuration = AgentConfigsUtils.createAgentConfigs(); parser = new AgentOptionParser(configuration, args); @@ -135,19 +141,23 @@ final ConfigurationServer configServer = OSGIUtils.getInstance().getService(ConfigurationServer.class); configServer.startListening(configuration.getConfigListenAddress()); - + BackendRegistry backendRegistry = null; try { - backendRegistry = new BackendRegistry(configuration, daoFactory); - } catch (BackendLoadException ble) { - logger.log(Level.SEVERE, "Could not get BackendRegistry instance.", ble); + backendRegistry = new BackendRegistry(bundleContext); + + } catch (Exception e) { + logger.log(Level.SEVERE, "Could not get BackendRegistry instance.", e); System.exit(Constants.EXIT_BACKEND_LOAD_ERROR); } - final Agent agent = new Agent(backendRegistry, configuration, daoFactory.getStorage(), daoFactory.getAgentInfoDAO(), daoFactory.getBackendInfoDAO()); + final Agent agent = new Agent(backendRegistry, configuration, daoFactory); try { logger.fine("Starting agent."); agent.start(); + + bundleContext.registerService(BackendService.class, new BackendService(), null); + } catch (LaunchException le) { logger.log(Level.SEVERE, "Agent could not start, probably because a configured backend could not be activated.",
--- a/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/impl/Activator.java Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/impl/Activator.java Fri Oct 19 21:58:18 2012 +0200 @@ -54,7 +54,7 @@ @Override public void start(BundleContext context) throws Exception { reg = new CommandRegistryImpl(context); - reg.registerCommands(Arrays.asList(new ServiceCommand(), new StorageCommand(), new AgentApplication())); + reg.registerCommands(Arrays.asList(new ServiceCommand(), new StorageCommand(), new AgentApplication(context))); } @Override
--- a/agent/cli/src/test/java/com/redhat/thermostat/agent/cli/AgentApplicationTest.java Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/cli/src/test/java/com/redhat/thermostat/agent/cli/AgentApplicationTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -37,18 +37,13 @@ package com.redhat.thermostat.agent.cli; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; - -import com.redhat.thermostat.agent.cli.AgentApplication; +import org.osgi.framework.BundleContext; public class AgentApplicationTest { @@ -56,9 +51,14 @@ private AgentApplication agent; + private BundleContext context; + @Before public void setUp() { - agent = new AgentApplication(); + + context = mock(BundleContext.class); + + agent = new AgentApplication(context); } @After @@ -77,47 +77,4 @@ assertNotNull(agent.getDescription()); assertNotNull(agent.getUsage()); } - - // TODO These options are provided by CommandInfo, we should check that an injected CommandInfo does - // result in correct results, but we should also have some test that the properties file that - // CommandInfo uses contains the correct set of options. - @Ignore - @Test - public void testOptions() { - Options options = agent.getOptions(); - assertNotNull(options); - assertEquals(5, options.getOptions().size()); - - assertTrue(options.hasOption("saveOnExit")); - Option save = options.getOption("saveOnExit"); - assertEquals("s", save.getOpt()); - assertEquals("save the data on exit", save.getDescription()); - assertFalse(save.isRequired()); - assertFalse(save.hasArg()); - - assertTrue(options.hasOption("debug")); - Option debug = options.getOption("debug"); - assertEquals("launch with debug console enabled", debug.getDescription()); - assertFalse(debug.isRequired()); - assertFalse(debug.hasArg()); - - assertTrue(options.hasOption("dbUrl")); - Option db = options.getOption("dbUrl"); - assertEquals("d", db.getOpt()); - assertEquals("connect to the given url", db.getDescription()); - assertTrue(db.isRequired()); - assertTrue(db.hasArg()); - - assertTrue(options.hasOption("username")); - Option user = options.getOption("username"); - assertEquals("the username to use for authentication", user.getDescription()); - assertFalse(user.isRequired()); - assertTrue(user.hasArg()); - - assertTrue(options.hasOption("password")); - Option pass = options.getOption("password"); - assertEquals("the password to use for authentication", pass.getDescription()); - assertFalse(pass.isRequired()); - assertTrue(pass.hasArg()); - } }
--- a/agent/core/pom.xml Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/core/pom.xml Fri Oct 19 21:58:18 2012 +0200 @@ -102,11 +102,11 @@ com.redhat.thermostat.agent, com.redhat.thermostat.agent.config, com.redhat.thermostat.backend, + com.redhat.thermostat.utils.hostname, + com.redhat.thermostat.utils, </Export-Package> <Private-Package> - com.redhat.thermostat.utils.hostname, com.redhat.thermostat.backend.sample, - com.redhat.thermostat.backend.system, </Private-Package> <!-- Do not autogenerate uses clauses in Manifests --> <_nouses>true</_nouses>
--- a/agent/core/src/main/java/com/redhat/thermostat/agent/Agent.java Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/core/src/main/java/com/redhat/thermostat/agent/Agent.java Fri Oct 19 21:58:18 2012 +0200 @@ -37,16 +37,22 @@ package com.redhat.thermostat.agent; import java.util.ArrayList; -import java.util.List; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; import java.util.logging.Logger; import com.redhat.thermostat.agent.config.AgentStartupConfiguration; import com.redhat.thermostat.backend.Backend; import com.redhat.thermostat.backend.BackendRegistry; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.LaunchException; +import com.redhat.thermostat.common.ThermostatExtensionRegistry; import com.redhat.thermostat.common.dao.AgentInfoDAO; import com.redhat.thermostat.common.dao.BackendInfoDAO; +import com.redhat.thermostat.common.dao.DAOFactory; import com.redhat.thermostat.common.model.AgentInformation; import com.redhat.thermostat.common.model.BackendInformation; import com.redhat.thermostat.common.storage.Storage; @@ -63,67 +69,101 @@ private final BackendRegistry backendRegistry; private final AgentStartupConfiguration config; + private final DAOFactory daoFactory; + private AgentInformation agentInfo; - private List<BackendInformation> backendInfos; + private Map<Backend, BackendInformation> backendInfos; private Storage storage; private AgentInfoDAO agentDao; private BackendInfoDAO backendDao; private boolean started = false; - public Agent(BackendRegistry backendRegistry, AgentStartupConfiguration config, Storage storage, AgentInfoDAO agentDao, BackendInfoDAO backendDao) { - this(backendRegistry, UUID.randomUUID(), config, storage, agentDao, backendDao); + private ActionListener<ThermostatExtensionRegistry.Action> backendRegistryListener = + new ActionListener<ThermostatExtensionRegistry.Action>() + { + @Override + public void actionPerformed(ActionEvent<ThermostatExtensionRegistry.Action> actionEvent) { + Backend backend = (Backend) actionEvent.getPayload(); + + switch (actionEvent.getActionId()) { + case SERVICE_ADDED: { + // TODO: this backed has been already added, we should + // probably signal the user this + if (!backendInfos.containsKey(backend)) { + + logger.info("Adding backend: " + backend); + + backend.setDAOFactory(daoFactory); + backend.activate(); + + BackendInformation info = createBackendInformation(backend); + backendDao.addBackendInformation(info); + backendInfos.put(backend, info); + } + } + break; + + case SERVICE_REMOVED: { + BackendInformation info = backendInfos.get(backend); + if (info != null) { + logger.info("removing backend: " + backend); + + backend.deactivate(); + + backendDao.removeBackendInformation(info); + backendInfos.remove(backend); + } + } + break; + + default: + logger.log(Level.WARNING, "received unknown event from BackendRegistry: " + actionEvent.getActionId()); + break; + } + } + }; + + public Agent(BackendRegistry backendRegistry, AgentStartupConfiguration config, DAOFactory daoFactory) + { + this(backendRegistry, UUID.randomUUID(), config, daoFactory); } - public Agent(BackendRegistry registry, UUID agentId, AgentStartupConfiguration config, Storage storage, AgentInfoDAO agentDao, BackendInfoDAO backendDao) { + public Agent(BackendRegistry registry, UUID agentId, AgentStartupConfiguration config, DAOFactory daoFactory) + { this.id = agentId; this.backendRegistry = registry; this.config = config; - this.storage = storage; + this.storage = daoFactory.getStorage(); this.storage.setAgentId(agentId); - this.agentDao = agentDao; - this.backendDao = backendDao; - } - - private void startBackends() throws LaunchException { - for (Backend be : backendRegistry.getAll()) { - logger.fine("Attempting to start backend: " + be.getName()); - if (!be.activate()) { - logger.warning("Issue while starting backend: " + be.getName()); - // When encountering issues during startup, we should not attempt to continue activating. - stopBackends(); - throw new LaunchException("Could not activate backend: " + be.getName()); - } - } - } - - private void stopBackends() { - for (Backend be : backendRegistry.getAll()) { - logger.fine("Attempting to stop backend: " +be.getName()); - if (!be.deactivate()) { - // When encountering issues during shutdown, we should attempt to shut down remaining backends. - logger.warning("Issue while deactivating backend: " + be.getName()); - } - } + this.agentDao = daoFactory.getAgentInfoDAO(); + this.backendDao = daoFactory.getBackendInfoDAO(); + + this.daoFactory = daoFactory; + + backendInfos = new ConcurrentHashMap<>(); + + backendRegistry.addActionListener(backendRegistryListener); } public synchronized void start() throws LaunchException { if (!started) { - startBackends(); agentInfo = createAgentInformation(); agentDao.addAgentInformation(agentInfo); - - backendInfos = createBackendInformation(); - for (BackendInformation backendInfo : backendInfos) { - backendDao.addBackendInformation(backendInfo); - } + + backendRegistry.start(); + started = true; } else { logger.warning("Attempt to start agent when already started."); } } + Map<Backend, BackendInformation> getBackendInfos() { + return backendInfos; + } + private AgentInformation createAgentInformation() { AgentInformation agentInfo = new AgentInformation(); agentInfo.setStartTime(config.getStartTime()); @@ -132,46 +172,34 @@ return agentInfo; } - private List<BackendInformation> createBackendInformation() { - List<BackendInformation> results = new ArrayList<>(); + private BackendInformation createBackendInformation(Backend backend) { - for (Backend backend : backendRegistry.getAll()) { - BackendInformation backendInfo = new BackendInformation(); - backendInfo.setName(backend.getName()); - backendInfo.setDescription(backend.getDescription()); - backendInfo.setObserveNewJvm(backend.getObserveNewJvm()); - backendInfo.setActive(true); - backendInfo.setPids(new ArrayList<Integer>()); - - results.add(backendInfo); - - } - return results; + BackendInformation backendInfo = new BackendInformation(); + backendInfo.setName(backend.getName()); + backendInfo.setDescription(backend.getDescription()); + backendInfo.setObserveNewJvm(backend.getObserveNewJvm()); + backendInfo.setActive(true); + backendInfo.setPids(new ArrayList<Integer>()); + + return backendInfo; } public synchronized void stop() { if (started) { - - stopBackends(); - removeBackendInformation(); + + backendRegistry.stop(); + if (config.purge()) { removeAllAgentRelatedInformation(); } else { updateAgentStatusToStopped(); } - started = false; } else { logger.warning("Attempt to stop agent which is not active"); } } - private void removeBackendInformation() { - for (BackendInformation info : backendInfos) { - backendDao.removeBackendInformation(info); - } - } - private void removeAllAgentRelatedInformation() { System.out.println("purging database"); logger.info("purging database");
--- a/agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentConfigsUtils.java Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentConfigsUtils.java Fri Oct 19 21:58:18 2012 +0200 @@ -67,15 +67,6 @@ throw new InvalidConfigurationException(e); } - if (properties.containsKey(AgentProperties.BACKENDS.name())) { - // this is a command separated list of backends - String backends = properties.getProperty(AgentProperties.BACKENDS.name()); - configuration.parseBackends(backends.split(",")); - - } else { - throw new InvalidConfigurationException(AgentProperties.BACKENDS + " property missing"); - } - if (properties.containsKey(AgentProperties.DB_URL.name())) { String db = properties.getProperty(AgentProperties.DB_URL.name()); configuration.setDatabaseURL(db);
--- a/agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentProperties.java Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentProperties.java Fri Oct 19 21:58:18 2012 +0200 @@ -38,8 +38,6 @@ public enum AgentProperties { - // backend list, comma separated - BACKENDS, DEBUG_CONSOLE, DB_URL, SAVE_ON_EXIT,
--- a/agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentStartupConfiguration.java Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentStartupConfiguration.java Fri Oct 19 21:58:18 2012 +0200 @@ -51,8 +51,6 @@ import com.redhat.thermostat.common.config.StartupConfiguration; public class AgentStartupConfiguration implements StartupConfiguration, AuthenticationConfiguration { - - private List<BackendID> backends; private boolean debugConsole; private boolean purge; @@ -65,49 +63,13 @@ private String address; AgentStartupConfiguration() { - this.backends = new ArrayList<>(); } @Override public String getDBConnectionString() { return url; } - - void parseBackends(String[] backendsList) throws InvalidConfigurationException { - backends.clear(); - - for (String simpleName : backendsList) { - String backendName = simpleName.trim(); - - // a file must exist, at least with the class name - File backendSettings = ConfigUtils.getBackendPropertyFile(backendName); - if (!backendSettings.exists()) - throw new InvalidConfigurationException("backends configuration " + - "directory doesn't exist: " + - backendSettings); - Properties backendProps = new Properties(); - try { - backendProps.load(new FileInputStream(backendSettings)); - - } catch (IOException e) { - throw new InvalidConfigurationException(e); - } - - String backendClass = backendProps.getProperty(BackendsProperties.BACKEND_CLASS.name()); - if (backendClass == null) { - throw new InvalidConfigurationException("Class name not found for backend: " + - backendName); - } - - BackendID backend = new BackendID(backendName, backendClass); - backends.add(backend); - } - } - public List<BackendID> getBackends() { - return backends; - } - void setDebugConsole(boolean debugConsole) { this.debugConsole = debugConsole; }
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/Backend.java Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/core/src/main/java/com/redhat/thermostat/backend/Backend.java Fri Oct 19 21:58:18 2012 +0200 @@ -40,13 +40,13 @@ import java.util.Map; import java.util.Map.Entry; +import com.redhat.thermostat.backend.BackendRegistry; import com.redhat.thermostat.common.LaunchException; import com.redhat.thermostat.common.dao.DAOFactory; import com.redhat.thermostat.common.storage.Storage; /** - * Represents a monitoring back-end. All the {@link Backend}s should be - * registered with the {@link BackendRegistry}. + * Represents a monitoring back-end. */ public abstract class Backend { @@ -61,6 +61,10 @@ private BackendID id; + public Backend(BackendID id) { + this.id = id; + } + /** * * @param configMap a map containing the settings that this backend has been configured with. @@ -177,8 +181,14 @@ /** * Activate the {@link Backend}. Based on the current configuration, - * begin pushing data to the {@link Storage} layer. If the {@link Backend} is - * already active, this method should have no effect + * begin pushing data to the {@link Storage} layer. + * If the {@link Backend} is already active, this method should have no + * effect. + * + * <br /><br /> + * + * This method is called by the framework when the {@link Backend} is + * registered. * * @return true on success, false if there was an error */ @@ -190,6 +200,11 @@ * {@link #activate()}. If the {@link Backend} is not active, this * method should have no effect * + * <br /><br /> + * + * This method is called by the framework when the {@link Backend} is + * deregistered. + * * @return true on success */ public abstract boolean deactivate(); @@ -225,12 +240,51 @@ public void setObserveNewJvm(boolean newValue) { observeNewJvm = newValue; } - - void setID(BackendID backendID) { - this.id = backendID; - } public BackendID getID() { return id; } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((vendor == null) ? 0 : vendor.hashCode()); + result = prime * result + ((version == null) ? 0 : version.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Backend other = (Backend) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (vendor == null) { + if (other.vendor != null) + return false; + } else if (!vendor.equals(other.vendor)) + return false; + if (version == null) { + if (other.version != null) + return false; + } else if (!version.equals(other.version)) + return false; + return true; + } + + @Override + public String toString() { + return "Backend [version=" + version + ", vendor=" + vendor + + ", description=" + description + ", id=" + id + "]"; + } }
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/BackendConfigurationLoader.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; - -import com.redhat.thermostat.common.config.ConfigUtils; -import com.redhat.thermostat.common.config.InvalidConfigurationException; - -class BackendConfigurationLoader { - - public Map<String, String> retrieveBackendConfigs(String name) throws InvalidConfigurationException { - - // reads the backend - File backend = new File(ConfigUtils.getBackendsBaseDirectory(), name); - backend = new File(backend, BackendsProperties.PROPERTY_FILE); - if (!backend.isFile() || !backend.canRead()) { - throw new InvalidConfigurationException("invalid backend configuration file: " + backend); - } - - Properties props = new Properties(); - try { - props.load(new FileInputStream(backend)); - } catch (IOException e) { - throw new InvalidConfigurationException("invalid backend configuration file", e); - } - - return toMap(props); - } - - private static Map<String, String> toMap(Properties props) { - - Map<String, String> configMap = new HashMap<>(); - for (Entry<Object, Object> e : props.entrySet()) { - String key = (String) e.getKey(); - String value = (String) e.getValue(); - - configMap.put(key, value); - } - return configMap; - } -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/BackendID.java Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/core/src/main/java/com/redhat/thermostat/backend/BackendID.java Fri Oct 19 21:58:18 2012 +0200 @@ -58,4 +58,37 @@ public String toString() { return simpleName + " = " + className; } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((className == null) ? 0 : className.hashCode()); + result = prime * result + + ((simpleName == null) ? 0 : simpleName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BackendID other = (BackendID) obj; + if (className == null) { + if (other.className != null) + return false; + } else if (!className.equals(other.className)) + return false; + if (simpleName == null) { + if (other.simpleName != null) + return false; + } else if (!simpleName.equals(other.simpleName)) + return false; + return true; + } }
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/BackendRegistry.java Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/core/src/main/java/com/redhat/thermostat/backend/BackendRegistry.java Fri Oct 19 21:58:18 2012 +0200 @@ -36,82 +36,27 @@ package com.redhat.thermostat.backend; -import java.lang.reflect.Constructor; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; import java.util.logging.Logger; -import com.redhat.thermostat.agent.config.AgentStartupConfiguration; -import com.redhat.thermostat.common.dao.DAOFactory; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.InvalidSyntaxException; + +import com.redhat.thermostat.backend.Backend; +import com.redhat.thermostat.common.ThermostatExtensionRegistry; import com.redhat.thermostat.common.utils.LoggingUtils; /** - * A registry for {@link Backend}s. Each {@link Backend} should call - * {@link #register(Backend)} to register itself. + * A registry for {@link Backend}s. {@link Backend}s are responsible to be + * registered as OSGi services into the framework. */ -public class BackendRegistry { +public class BackendRegistry extends ThermostatExtensionRegistry<Backend> { private static final Logger logger = LoggingUtils.getLogger(BackendRegistry.class); - private final Map<String, Backend> registeredBackends; - - public BackendRegistry(AgentStartupConfiguration config, DAOFactory daoFactory) throws BackendLoadException { - this(config, new BackendConfigurationLoader(), daoFactory); - } - - public BackendRegistry(AgentStartupConfiguration config, BackendConfigurationLoader backendConfigLoader, DAOFactory daoFactory) throws BackendLoadException { - - registeredBackends = new HashMap<String, Backend>(); - - List<BackendID> backends = config.getBackends(); - - /* - * Configure the dynamic/custom backends - */ - for (BackendID backendID : backends) { - logger.log(Level.FINE, "Initializing backend: \"" + backendID.getClassName() + "\""); - Backend backend = null; - try { - Class<? > c = Class.forName(backendID.getClassName()); - Class<? extends Backend> narrowed = c.asSubclass(Backend.class); - Constructor<? extends Backend> backendConstructor = narrowed.getConstructor(); - backend = backendConstructor.newInstance(); + private static final String FILTER = "(" + Constants.OBJECTCLASS + "=" + Backend.class.getName() + ")"; - backend.setDAOFactory(daoFactory); - backend.setID(backendID); - - backend.setInitialConfiguration(backendConfigLoader.retrieveBackendConfigs(backend.getName())); - } catch (Exception e) { - throw new BackendLoadException("Could not instantiate configured backend class: " + backendID.getClassName(), e); - } - register(backend); - } - } - - private synchronized void register(Backend backend) throws BackendLoadException { - if (registeredBackends.containsKey(backend.getName())) { - throw new BackendLoadException("Attempt to register two backends with the same name: " + backend.getName()); - } - registeredBackends.put(backend.getName(), backend); - } - - private synchronized void unregister(Backend backend) { - registeredBackends.remove(backend.getName()); - } - - public synchronized Collection<Backend> getAll() { - return registeredBackends.values(); - } - - public synchronized Backend getByName(String name) { - for (Backend backend : registeredBackends.values()) { - if (backend.getName().equals((name))) { - return backend; - } - } - return null; + public BackendRegistry(BundleContext context) throws InvalidSyntaxException { + super(context, FILTER, Backend.class); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/main/java/com/redhat/thermostat/backend/BackendService.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend; + +/** + * Class used to signal that {@link Backend}s can start registering themselves + * into the Framework. It is registered by the Agent as soon as it is ready to + * accept new {@link Backend}s. + */ +public class BackendService { +}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/sample/SampleBackend.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.sample; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.redhat.thermostat.backend.Backend; -import com.redhat.thermostat.common.utils.LoggingUtils; - -/** - * Just an example backend implementation. This is really just to test the loading and configuration mechanisms - */ -public class SampleBackend extends Backend { - private final String NAME = "sample-backend"; - private final String DESCRIPTION = "A backend which does nothing at all."; - private final String VENDOR = "Nobody"; - private final String VERSION = "0.1"; - private boolean currentlyActive = false; - - private Logger logger = LoggingUtils.getLogger(SampleBackend.class); - - private final Map<String, String> config = new HashMap<>(); - - public SampleBackend() { - super(); - } - - @Override - protected void setConfigurationValue(String name, String value) { - logger.log(Level.FINE, "Setting configuration value for backend: " + this.NAME); - logger.log(Level.FINE, "key: " + name + " value: " + value); - config.put(name, value); - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getDescription() { - return DESCRIPTION; - } - - @Override - public String getVendor() { - return VENDOR; - } - - @Override - public String getVersion() { - return VERSION; - } - - @Override - public Map<String, String> getConfigurationMap() { - return Collections.unmodifiableMap(config); - } - - @Override - public String getConfigurationValue(String key) { - return config.get(key); - } - - @Override - public boolean activate() { - currentlyActive = true; - return true; - } - - @Override - public boolean deactivate() { - currentlyActive = false; - return true; - } - - @Override - public boolean isActive() { - return currentlyActive; - } - - @Override - public boolean attachToNewProcessByDefault() { - return false; - } - - @Override - protected void setDAOFactoryAction() { - /* NO-OP */ - } - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/CpuStatBuilder.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,136 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.io.BufferedReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.redhat.thermostat.common.Clock; -import com.redhat.thermostat.common.model.CpuStat; -import com.redhat.thermostat.common.utils.LoggingUtils; - -public class CpuStatBuilder { - - private static final Logger logger = LoggingUtils.getLogger(CpuStatBuilder.class); - - private final ProcDataSource dataSource; - private final Clock clock; - private final long ticksPerSecond; - - private boolean initialized = false; - - private long[] previousCpuTicks; - private long previousTime; - - public CpuStatBuilder(Clock clock, ProcDataSource dataSource, long ticksPerSecond) { - this.dataSource = dataSource; - this.clock = clock; - this.ticksPerSecond = ticksPerSecond; - } - - public void initialize() { - if (initialized) { - throw new IllegalStateException("already initialized"); - } - - previousTime = clock.getMonotonicTimeNanos(); - previousCpuTicks = getCurrentCpuTicks(); - initialized = true; - } - - public CpuStat build() { - if (!initialized) { - throw new IllegalStateException("not initialized yet"); - } - - long currentRealTime = clock.getRealTimeMillis(); - long currentTime = clock.getMonotonicTimeNanos(); - long[] currentValues = getCurrentCpuTicks(); - - List<Double> cpuUsage = new ArrayList<Double>(currentValues.length); - - double timeDelta = (currentTime - previousTime) * 1E-9; - for (int i = 0; i < currentValues.length; i++) { - long cpuTicksDelta = currentValues[i] - previousCpuTicks[i]; - // 100 as in 100 percent. - cpuUsage.add(cpuTicksDelta * (100.0 / timeDelta / ticksPerSecond)); - } - previousTime = currentTime; - previousCpuTicks = currentValues; - - return new CpuStat(currentRealTime, cpuUsage); - } - - private long[] getCurrentCpuTicks() { - int maxIndex = 0; - long[] values = new long[1]; - try (BufferedReader reader = new BufferedReader(dataSource.getStatReader())) { - String line; - while ((line = reader.readLine()) != null) { - if (!line.startsWith("cpu")) { - continue; - } - String[] parts = line.split("\\s"); - if (!parts[0].matches("cpu\\d+")) { - continue; - } - - int cpuIndex = Integer.valueOf(parts[0].substring("cpu".length())); - if (cpuIndex > maxIndex) { - long[] newValues = new long[cpuIndex+1]; - System.arraycopy(values, 0, newValues, 0, cpuIndex); - values = newValues; - maxIndex = cpuIndex; - } - values[cpuIndex] = Long.valueOf(parts[1]) + Long.valueOf(parts[2]) + Long.valueOf(parts[3]); - } - } catch (IOException e) { - logger.log(Level.WARNING, "error reading stat file", e); - } - - return values; - } - - public boolean isInitialized() { - return initialized; - } - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/DistributionInformation.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.redhat.thermostat.common.utils.LoggingUtils; - -public class DistributionInformation { - - public static final String UNKNOWN_NAME = "Unknown Distribution"; - public static final String UNKNOWN_VERSION = "Unknown Version"; - - private static final Logger logger = LoggingUtils.getLogger(DistributionInformation.class); - - private final String name; - private final String version; - - public DistributionInformation(String name, String version) { - this.name = name; - this.version = version; - } - - public static DistributionInformation get() { - try { - return new EtcOsRelease().getDistributionInformation(); - } catch (IOException e) { - logger.log(Level.WARNING, "unable to use os-release", e); - } - try { - return new LsbRelease().getDistributionInformation(); - } catch (IOException e) { - logger.log(Level.WARNING, "unable to use lsb_release", e); - } - return new DistributionInformation(UNKNOWN_NAME, UNKNOWN_VERSION); - } - - /** - * @return the name of the distribution, or {@link #UNKNOWN_NAME} if it can not be - * identified - */ - public String getName() { - return name; - } - - /** - * @return the release of the distribution or {@link #UNKNOWN_VERSION} if it can not be - * identified - */ - public String getVersion() { - return version; - } - -} \ No newline at end of file
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/DistributionInformationSource.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.io.IOException; - -public interface DistributionInformationSource { - - public DistributionInformation getDistributionInformation() throws IOException; - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/EtcOsRelease.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.redhat.thermostat.common.utils.LoggingUtils; - -public class EtcOsRelease implements DistributionInformationSource { - - private static final Logger logger = LoggingUtils.getLogger(EtcOsRelease.class); - - private static final String OS_RELEASE = "/etc/os-release"; - - @Override - public DistributionInformation getDistributionInformation() throws IOException { - return getFromOsRelease(); - } - - public DistributionInformation getFromOsRelease() throws IOException { - return getFromOsRelease(OS_RELEASE); - } - - public DistributionInformation getFromOsRelease(String releaseFile) throws IOException { - BufferedReader reader = null; - try { - reader = new BufferedReader(new FileReader(releaseFile)); - return getFromOsRelease(reader); - } finally { - try { - if (reader != null) { - reader.close(); - } - } catch (IOException e) { - logger.log(Level.WARNING, "unable to close input stream", e); - } - } - } - - public DistributionInformation getFromOsRelease(BufferedReader reader) throws IOException { - String name = "Linux"; - String version = DistributionInformation.UNKNOWN_VERSION; - String line = null; - while ((line = reader.readLine()) != null) { - if (line.matches("^NAME *=.*")) { - name = readShellVariable(line); - } - if (line.matches("^VERSION *=.*")) { - version = readShellVariable(line); - } - } - return new DistributionInformation(name, version); - } - - /** Reads and parses a shell variable declaration: {@code FOO="bar"} - * - * @return the value of the shell variable - */ - private String readShellVariable(String line) { - // TODO we should try to handle shell quotes better - String result = line.substring(line.indexOf("=")+1); - result = result.trim(); - if (result.startsWith("\"") && result.endsWith("\"")) { - result = result.substring(1, result.length()-1); - result = result.trim(); - } - return result; - } - - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/HostInfoBuilder.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,183 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.io.BufferedReader; -import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.redhat.thermostat.common.Constants; -import com.redhat.thermostat.common.model.HostInfo; -import com.redhat.thermostat.common.utils.LoggingUtils; -import com.redhat.thermostat.utils.hostname.HostName; - -public class HostInfoBuilder { - - private static final Logger logger = LoggingUtils.getLogger(HostInfoBuilder.class); - - static class HostCpuInfo { - public final String model; - public final int count; - - public HostCpuInfo(String model, int count) { - this.count = count; - this.model = model; - } - } - - static class HostOsInfo { - public final String kernel; - public final String distribution; - - public HostOsInfo(String kernel, String distribution) { - this.kernel = kernel; - this.distribution = distribution; - } - } - - static class HostMemoryInfo { - public final long totalMemory; - - public HostMemoryInfo(long totalMemory) { - this.totalMemory = totalMemory; - } - } - - private final ProcDataSource dataSource; - - public HostInfoBuilder(ProcDataSource dataSource) { - this.dataSource = dataSource; - } - - public HostInfo build() { - String hostname = getHostName(); - HostCpuInfo cpuInfo = getCpuInfo(); - HostMemoryInfo memoryInfo = getMemoryInfo(); - HostOsInfo osInfo = getOsInfo(); - - return new HostInfo(hostname, osInfo.distribution, osInfo.kernel, cpuInfo.model, cpuInfo.count, memoryInfo.totalMemory); - } - - HostCpuInfo getCpuInfo() { - final String KEY_PROCESSOR_ID = "processor"; - final String KEY_CPU_MODEL = "model name"; - int cpuCount = 0; - String cpuModel = null; - try (BufferedReader bufferedReader = new BufferedReader(dataSource.getCpuInfoReader())) { - String line = null; - while ((line = bufferedReader.readLine()) != null) { - if (line.startsWith(KEY_PROCESSOR_ID)) { - cpuCount++; - } else if (line.startsWith(KEY_CPU_MODEL)) { - cpuModel = line.substring(line.indexOf(":") + 1).trim(); - } - } - } catch (IOException ioe) { - logger.log(Level.WARNING, "unable to read cpu info"); - } - - logger.log(Level.FINEST, "cpuModel: " + cpuModel); - logger.log(Level.FINEST, "cpuCount: " + cpuCount); - - return new HostCpuInfo(cpuModel, cpuCount); - } - - HostMemoryInfo getMemoryInfo() { - long totalMemory = -1; - try (BufferedReader bufferedReader = new BufferedReader(dataSource.getMemInfoReader())) { - String[] memTotalParts = bufferedReader.readLine().split(" +"); - long data = Long.valueOf(memTotalParts[1]); - String units = memTotalParts[2]; - if (units.equals("kB")) { - totalMemory = data * Constants.KILOBYTES_TO_BYTES; - } - } catch (IOException ioe) { - logger.log(Level.WARNING, "unable to read memory info"); - } - - logger.log(Level.FINEST, "totalMemory: " + totalMemory + " bytes"); - return new HostMemoryInfo(totalMemory); - } - - HostOsInfo getOsInfo() { - return getOsInfo(DistributionInformation.get()); - } - - HostOsInfo getOsInfo(DistributionInformation distroInfo) { - String osName = distroInfo.getName() + " " + distroInfo.getVersion(); - logger.log(Level.FINEST, "osName: " + osName); - - String osKernel = System.getProperty("os.name") + " " + System.getProperty("os.version"); - logger.log(Level.FINEST, "osKernel: " + osKernel); - - return new HostOsInfo(osKernel, osName); - } - - String getHostName() { - String hostname = null; - - try { - InetAddress localAddress = null; - localAddress = InetAddress.getLocalHost(); - hostname = getHostName(localAddress); - } catch (UnknownHostException uhe) { - logger.log(Level.WARNING, "unable to get hostname", uhe); - } - - // if fails, try to get hostname without dns lookup - if (hostname == null) { - hostname = HostName.getLocalHostName(); - } - - // still null, use localhost - if (hostname == null) { - hostname = Constants.AGENT_LOCAL_HOSTNAME; - } - - return hostname; - } - - String getHostName(InetAddress localAddress) { - String hostname = localAddress.getCanonicalHostName(); - logger.log(Level.FINEST, "hostname: " + hostname); - return hostname; - } - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/JvmStatDataExtractor.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,170 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import com.redhat.thermostat.common.model.VmMemoryStat.Generation; - -import sun.jvmstat.monitor.Monitor; -import sun.jvmstat.monitor.MonitorException; -import sun.jvmstat.monitor.MonitoredVm; -import sun.jvmstat.monitor.MonitoredVmUtil; - -/** - * A helper class to provide type-safe access to commonly used jvmstat monitors - * <p> - * Implementation details: For local vms, jvmstat uses a ByteBuffer - * corresponding to mmap()ed hsperfdata file. The hsperfdata file is updated - * asynchronously by the vm that created the file. The polling that jvmstat api - * provides is merely an abstraction over this (possibly always up-to-date) - * ByteBuffer. So the data this class extracts is as current as possible, and - * does not correspond to when the jvmstat update events fired. - */ -public class JvmStatDataExtractor { - - /* - * Note, there may be a performance issue to consider here. We have a lot of - * string constants. When we start adding some of the more heavyweight - * features, and running into CPU issues this may need to be reconsidered in - * order to avoid the String pool overhead. See also: - * http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#intern() - */ - - private final MonitoredVm vm; - - public JvmStatDataExtractor(MonitoredVm vm) { - this.vm = vm; - } - - public String getCommandLine() throws MonitorException { - return MonitoredVmUtil.commandLine(vm); - } - - public String getMainClass() throws MonitorException { - return MonitoredVmUtil.mainClass(vm, true); - } - - public String getJavaVersion() throws MonitorException { - return (String) vm.findByName("java.property.java.version").getValue(); - } - - public String getJavaHome() throws MonitorException { - return (String) vm.findByName("java.property.java.home").getValue(); - } - - public String getVmName() throws MonitorException { - return (String) vm.findByName("java.property.java.vm.name").getValue(); - } - - public String getVmInfo() throws MonitorException { - return (String) vm.findByName("java.property.java.vm.info").getValue(); - } - - public String getVmVersion() throws MonitorException { - return (String) vm.findByName("java.property.java.vm.version").getValue(); - } - - public String getVmArguments() throws MonitorException { - return MonitoredVmUtil.jvmArgs(vm); - } - - public long getTotalCollectors() throws MonitorException { - return (Long) vm.findByName("sun.gc.policy.collectors").getValue(); - } - - public String getCollectorName(long collector) throws MonitorException { - return (String) vm.findByName("sun.gc.collector." + collector + ".name").getValue(); - } - - public long getCollectorTime(long collector) throws MonitorException { - return (Long) vm.findByName("sun.gc.collector." + collector + ".time").getValue(); - } - - public long getCollectorInvocations(long collector) throws MonitorException { - return (Long) vm.findByName("sun.gc.collector." + collector + ".invocations").getValue(); - } - - public long getTotalGcGenerations() throws MonitorException { - return (Long) vm.findByName("sun.gc.policy.generations").getValue(); - } - - public String getGenerationName(long generation) throws MonitorException { - return (String) vm.findByName("sun.gc.generation." + generation + ".name").getValue(); - } - - public long getGenerationCapacity(long generation) throws MonitorException { - return (Long) vm.findByName("sun.gc.generation." + generation + ".capacity").getValue(); - } - - public long getGenerationMaxCapacity(long generation) throws MonitorException { - return (Long) vm.findByName("sun.gc.generation." + generation + ".maxCapacity").getValue(); - } - - public String getGenerationCollector(long generation) throws MonitorException { - // this is just re-implementing getCollectorName() - // TODO check generation number and collector number are always associated - Monitor m = vm.findByName("sun.gc.collector." + generation + ".name"); - if (m == null) { - return Generation.COLLECTOR_NONE; - } - return (String) m.getValue(); - } - - public long getTotalSpaces(long generation) throws MonitorException { - return (Long) vm.findByName("sun.gc.generation." + generation + ".spaces").getValue(); - } - - public String getSpaceName(long generation, long space) throws MonitorException { - return (String) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".name").getValue(); - } - - public long getSpaceCapacity(long generation, long space) throws MonitorException { - return (Long) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".capacity").getValue(); - } - - public long getSpaceMaxCapacity(long generation, long space) throws MonitorException { - return (Long) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".maxCapacity").getValue(); - } - - public long getSpaceUsed(long generation, long space) throws MonitorException { - return (Long) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".used").getValue(); - } - - public long getLoadedClasses() throws MonitorException { - return (Long) vm.findByName("java.cls.loadedClasses").getValue(); - } - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,226 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.logging.Level; -import java.util.logging.Logger; - -import sun.jvmstat.monitor.MonitorException; -import sun.jvmstat.monitor.MonitoredHost; -import sun.jvmstat.monitor.MonitoredVm; -import sun.jvmstat.monitor.VmIdentifier; -import sun.jvmstat.monitor.event.HostEvent; -import sun.jvmstat.monitor.event.HostListener; -import sun.jvmstat.monitor.event.VmListener; -import sun.jvmstat.monitor.event.VmStatusChangeEvent; - -import com.redhat.thermostat.agent.JvmStatusListener; -import com.redhat.thermostat.agent.JvmStatusNotifier; -import com.redhat.thermostat.common.dao.VmClassStatDAO; -import com.redhat.thermostat.common.dao.VmGcStatDAO; -import com.redhat.thermostat.common.dao.VmInfoDAO; -import com.redhat.thermostat.common.dao.VmMemoryStatDAO; -import com.redhat.thermostat.common.model.VmInfo; -import com.redhat.thermostat.common.utils.LoggingUtils; - -public class JvmStatHostListener implements HostListener, JvmStatusNotifier { - - private static final Logger logger = LoggingUtils.getLogger(JvmStatHostListener.class); - - private boolean attachNew; - - private final VmInfoDAO vmInfoDAO; - private final VmMemoryStatDAO vmMemoryStatDAO; - private final VmClassStatDAO vmClassStatDAO; - private final VmGcStatDAO vmGcStatDAO; - - private Map<Integer, MonitoredVm> monitoredVms = new HashMap<>(); - private Map<MonitoredVm, List<VmListener>> registeredListeners = new ConcurrentHashMap<>(); - - private Set<JvmStatusListener> statusListeners = new CopyOnWriteArraySet<JvmStatusListener>(); - - JvmStatHostListener(VmInfoDAO vmInfoDAO, VmMemoryStatDAO vmMemoryStatDAO, VmGcStatDAO vmGcStatDAO, - VmClassStatDAO vmClassStatDAO, boolean attachNew) { - this.vmInfoDAO = vmInfoDAO; - this.vmMemoryStatDAO = vmMemoryStatDAO; - this.vmGcStatDAO = vmGcStatDAO; - this.vmClassStatDAO = vmClassStatDAO; - this.attachNew = attachNew; - } - - void removeAllListeners() { - for (MonitoredVm vm : monitoredVms.values()) { - for (VmListener listener : registeredListeners.get(vm)) { - try { - if (listener != null) vm.removeVmListener(listener); - - } catch (MonitorException e) { - logger.log(Level.WARNING, "can't remove vm listener", e); - } - } - } - } - - @Override - public void disconnected(HostEvent event) { - logger.warning("Disconnected from host"); - } - - @SuppressWarnings("unchecked") // Unchecked casts to (Set<Integer>). - @Override - public void vmStatusChanged(VmStatusChangeEvent event) { - MonitoredHost host = event.getMonitoredHost(); - - for (Integer newVm : (Set<Integer>) event.getStarted()) { - try { - logger.fine("New vm: " + newVm); - sendNewVM(newVm, host); - } catch (MonitorException e) { - logger.log(Level.WARNING, "error getting info for new vm" + newVm, e); - } catch (URISyntaxException e) { - logger.log(Level.WARNING, "error getting info for new vm" + newVm, e); - } - } - - for (Integer stoppedVm : (Set<Integer>) event.getTerminated()) { - try { - logger.fine("stopped vm: " + stoppedVm); - sendStoppedVM(stoppedVm, host); - } catch (URISyntaxException e) { - logger.log(Level.WARNING, "error getting info for stopped vm" + stoppedVm, e); - } catch (MonitorException e) { - logger.log(Level.WARNING, "error getting info for stopped vm" + stoppedVm, e); - } - } - } - - private void sendNewVM(Integer vmId, MonitoredHost host) - throws MonitorException, URISyntaxException { - MonitoredVm vm = host.getMonitoredVm(host.getHostIdentifier().resolve( - new VmIdentifier(vmId.toString()))); - if (vm != null) { - VmInfo info = null; - try { - long startTime = System.currentTimeMillis(); - long stopTime = Long.MIN_VALUE; - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Map<String, String> properties = new HashMap<String, String>(); - ProcDataSource dataSource = new ProcDataSource(); - Map<String, String> environment = new ProcessEnvironmentBuilder(dataSource).build(vmId); - // TODO actually figure out the loaded libraries. - List<String> loadedNativeLibraries = new ArrayList<String>(); - info = new VmInfo(vmId, startTime, stopTime, - extractor.getJavaVersion(), extractor.getJavaHome(), - extractor.getMainClass(), extractor.getCommandLine(), - extractor.getVmName(), extractor.getVmInfo(), extractor.getVmVersion(), extractor.getVmArguments(), - properties, environment, loadedNativeLibraries); - vmInfoDAO.putVmInfo(info); - logger.finer("Sent VM_STARTED messsage"); - } catch (MonitorException me) { - logger.log(Level.WARNING, "error getting vm info for " + vmId, me); - } - - if (attachNew) { - List<VmListener> listeners = registeredListeners.get(vm); - if (listeners == null) { - listeners = new CopyOnWriteArrayList<>(); - } - - VmListener listener = new JvmStatVmListener(vmMemoryStatDAO, vmGcStatDAO, vmId); - vm.addVmListener(listener); - listeners.add(listener); - - listener = new JvmStatVmClassListener(vmClassStatDAO, vmId); - vm.addVmListener(listener); - listeners.add(listener); - - registeredListeners.put(vm, listeners); - - } else { - logger.log(Level.FINE, "skipping new vm " + vmId); - } - for (JvmStatusListener statusListener : statusListeners) { - statusListener.jvmStarted(vmId); - } - - monitoredVms.put(vmId, vm); - } - } - - private void sendStoppedVM(Integer vmId, MonitoredHost host) - throws URISyntaxException, MonitorException { - VmIdentifier resolvedVmID = host.getHostIdentifier().resolve( - new VmIdentifier(vmId.toString())); - if (resolvedVmID != null) { - long stopTime = System.currentTimeMillis(); - for (JvmStatusListener statusListener : statusListeners) { - statusListener.jvmStopped(vmId); - } - vmInfoDAO.putVmStoppedTime(vmId, stopTime); - - MonitoredVm vm = monitoredVms.remove(vmId); - List<VmListener> listeners = registeredListeners.remove(vm); - for (VmListener listener : listeners) { - try { - if (listener != null) vm.removeVmListener(listener); - } catch (MonitorException e) { - logger.log(Level.WARNING, "can't remove vm listener", e); - } - } - vm.detach(); - } - } - - @Override - public void addJvmStatusListener(JvmStatusListener listener) { - statusListeners.add(listener); - } - - @Override - public void removeJvmStatusListener(JvmStatusListener listener) { - statusListeners.remove(listener); - } -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmClassListener.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import sun.jvmstat.monitor.MonitorException; -import sun.jvmstat.monitor.MonitoredVm; -import sun.jvmstat.monitor.event.MonitorStatusChangeEvent; -import sun.jvmstat.monitor.event.VmEvent; -import sun.jvmstat.monitor.event.VmListener; - -import com.redhat.thermostat.common.dao.VmClassStatDAO; -import com.redhat.thermostat.common.model.VmClassStat; -import com.redhat.thermostat.common.utils.LoggingUtils; - -class JvmStatVmClassListener implements VmListener { - - private static final Logger logger = LoggingUtils.getLogger(JvmStatVmClassListener.class); - - private VmClassStatDAO dao; - private int vmId; - - JvmStatVmClassListener(VmClassStatDAO dao, int vmId) { - this.dao = dao; - this.vmId = vmId; - } - - @Override - public void disconnected(VmEvent vmEvent) { - /* nothing to do here */ - } - - @Override - public void monitorStatusChanged(MonitorStatusChangeEvent vmEvent) { - /* nothing to do here */ - } - - @Override - public void monitorsUpdated(VmEvent vmEvent) { - MonitoredVm vm = vmEvent.getMonitoredVm(); - try { - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - long loadedClasses = extractor.getLoadedClasses(); - long timestamp = System.currentTimeMillis(); - VmClassStat stat = new VmClassStat(vmId, timestamp, loadedClasses); - dao.putVmClassStat(stat); - } catch (MonitorException e) { - logger.log(Level.WARNING, "error gathering class info for vm " + vmId, e); - } - - - } - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -import sun.jvmstat.monitor.MonitorException; -import sun.jvmstat.monitor.MonitoredVm; -import sun.jvmstat.monitor.event.MonitorStatusChangeEvent; -import sun.jvmstat.monitor.event.VmEvent; -import sun.jvmstat.monitor.event.VmListener; - -import com.redhat.thermostat.common.dao.VmGcStatDAO; -import com.redhat.thermostat.common.dao.VmMemoryStatDAO; -import com.redhat.thermostat.common.model.VmGcStat; -import com.redhat.thermostat.common.model.VmMemoryStat; -import com.redhat.thermostat.common.model.VmMemoryStat.Generation; -import com.redhat.thermostat.common.model.VmMemoryStat.Space; -import com.redhat.thermostat.common.utils.LoggingUtils; - -public class JvmStatVmListener implements VmListener { - - private static final Logger logger = LoggingUtils.getLogger(JvmStatVmListener.class); - - private final int vmId; - private final VmGcStatDAO gcDAO; - private final VmMemoryStatDAO memDAO; - - public JvmStatVmListener(VmMemoryStatDAO vmMemoryStatDao, VmGcStatDAO vmGcStatDao, int vmId) { - gcDAO = vmGcStatDao; - memDAO = vmMemoryStatDao; - this.vmId = vmId; - } - - @Override - public void disconnected(VmEvent event) { - /* nothing to do here */ - } - - @Override - public void monitorStatusChanged(MonitorStatusChangeEvent event) { - /* nothing to do here */ - } - - @Override - public void monitorsUpdated(VmEvent event) { - MonitoredVm vm = event.getMonitoredVm(); - if (vm == null) { - throw new NullPointerException(); - } - recordMemoryStat(vm); - recordGcStat(vm); - } - - private void recordGcStat(MonitoredVm vm) { - try { - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - long collectors = extractor.getTotalCollectors(); - for (int i = 0; i < collectors; i++) { - long timestamp = System.currentTimeMillis(); - VmGcStat stat = new VmGcStat(vmId, timestamp, - extractor.getCollectorName(i), - extractor.getCollectorInvocations(i), - extractor.getCollectorTime(i)); - gcDAO.putVmGcStat(stat); - } - } catch (MonitorException e) { - logger.log(Level.WARNING, "error gathering gc info for vm " + vmId, e); - } - - } - - private void recordMemoryStat(MonitoredVm vm) { - try { - long timestamp = System.currentTimeMillis(); - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - long maxGenerations = extractor.getTotalGcGenerations(); - List<Generation> generations = new ArrayList<Generation>(); - VmMemoryStat stat = new VmMemoryStat(timestamp, vmId, generations); - for (long generation = 0; generation < maxGenerations; generation++) { - Generation g = new Generation(); - generations.add(g); - g.name = extractor.getGenerationName(generation); - g.capacity = extractor.getGenerationCapacity(generation); - g.maxCapacity = extractor.getGenerationMaxCapacity(generation); - g.collector = extractor.getGenerationCollector(generation); - long maxSpaces = extractor.getTotalSpaces(generation); - List<Space> spaces = new ArrayList<Space>(); - g.spaces = spaces; - for (long space = 0; space < maxSpaces; space++) { - Space s = new Space(); - spaces.add(s); - s.index = (int) space; - s.name = extractor.getSpaceName(generation, space); - s.capacity = extractor.getSpaceCapacity(generation, space); - s.maxCapacity = extractor.getSpaceMaxCapacity(generation, space); - s.used = extractor.getSpaceUsed(generation, space); - } - } - memDAO.putVmMemoryStat(stat); - } catch (MonitorException e) { - logger.log(Level.WARNING, "error gathering memory info for vm " + vmId, e); - } - } - - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/LsbRelease.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.redhat.thermostat.common.utils.LoggingUtils; - -public class LsbRelease implements DistributionInformationSource { - - private static final Logger logger = LoggingUtils.getLogger(LsbRelease.class); - - private static final String DISTRIBUTION_NAME = "distributor id"; - private static final String DISTRIBUTION_VERSION = "release"; - - @Override - public DistributionInformation getDistributionInformation() - throws IOException { - return getFromLsbRelease(); - } - - public DistributionInformation getFromLsbRelease() throws IOException { - - BufferedReader reader = null; - try { - Process lsbProc = Runtime.getRuntime().exec(new String[] { "lsb_release", "-a" }); - InputStream progOutput = lsbProc.getInputStream(); - reader = new BufferedReader(new InputStreamReader(progOutput)); - DistributionInformation result = getFromLsbRelease(reader); - int exitValue = lsbProc.waitFor(); - if (exitValue != 0) { - logger.log(Level.WARNING, "unable to identify distribution, problems running 'lsb_release'"); - } - return result; - } catch (InterruptedException e) { - throw new IOException(e); - } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - logger.log(Level.WARNING, "unable to close a child's output stream"); - } - } - } - - } - - public DistributionInformation getFromLsbRelease(BufferedReader reader) throws IOException { - String name = DistributionInformation.UNKNOWN_NAME; - String version = DistributionInformation.UNKNOWN_VERSION; - - String line; - while ((line = reader.readLine()) != null) { - int sepLocation = line.indexOf(":"); - if (sepLocation != -1) { - String key = line.substring(0, sepLocation).toLowerCase(); - if (key.equals(DISTRIBUTION_NAME)) { - name = line.substring(sepLocation + 1).trim(); - } else if (key.equals(DISTRIBUTION_VERSION)) { - version = line.substring(sepLocation + 1).trim(); - } - } - } - - logger.log(Level.FINE, "distro-name: " + name); - logger.log(Level.FINE, "distro-version: " + version); - - return new DistributionInformation(name, version); - } - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/MemoryStatBuilder.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.io.BufferedReader; -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.redhat.thermostat.common.Constants; -import com.redhat.thermostat.common.NotImplementedException; -import com.redhat.thermostat.common.model.MemoryStat; -import com.redhat.thermostat.common.utils.LoggingUtils; - -/** - * Implementation note: uses information from /proc/ - */ -public class MemoryStatBuilder { - - private static final long UNAVAILABLE = -1; - - private static final String KEY_MEMORY_TOTAL = "MemTotal"; - private static final String KEY_MEMORY_FREE = "MemFree"; - private static final String KEY_BUFFERS = "Buffers"; - private static final String KEY_CACHED = "Cached"; - private static final String KEY_SWAP_TOTAL = "SwapTotal"; - private static final String KEY_SWAP_FREE = "SwapFree"; - private static final String KEY_COMMIT_LIMIT = "CommitLimit"; - - private static final Logger logger = LoggingUtils.getLogger(MemoryStatBuilder.class); - - private final ProcDataSource dataSource; - - public MemoryStatBuilder(ProcDataSource dataSource) { - this.dataSource = dataSource; - } - - protected MemoryStat build() { - long timestamp = System.currentTimeMillis(); - - long total = UNAVAILABLE; - long free = UNAVAILABLE; - long swapTotal = UNAVAILABLE; - long swapFree = UNAVAILABLE; - long buffers = UNAVAILABLE; - long cached = UNAVAILABLE; - long commitLimit = UNAVAILABLE; - - try (BufferedReader reader = new BufferedReader(dataSource.getMemInfoReader())) { - String line = null; - while ((line = reader.readLine()) != null) { - String[] parts = line.split(":"); - if (parts.length == 2) { - String key = parts[0].trim(); - long value = getValue(parts[1].trim()); - if (key.equals(KEY_MEMORY_TOTAL)) { - total = value; - } else if (key.equals(KEY_MEMORY_FREE)) { - free = value; - } else if (key.equals(KEY_SWAP_TOTAL)) { - swapTotal = value; - } else if (key.equals(KEY_SWAP_FREE)) { - swapFree = value; - } else if (key.equals(KEY_BUFFERS)) { - buffers = value; - } else if (key.equals(KEY_CACHED)) { - cached = value; - } else if (key.equals(KEY_COMMIT_LIMIT)) { - commitLimit = value; - } - } - } - } catch (IOException ioe) { - logger.log(Level.WARNING, "unable to read memory info"); - } - - return new MemoryStat(timestamp, total, free, buffers, cached, swapTotal, swapFree, commitLimit); - } - - private long getValue(String rawValue) { - String[] parts = rawValue.split(" +"); - String value = rawValue; - String units = null; - if (parts.length > 1) { - value = parts[0]; - units = parts[1]; - } - - long result = UNAVAILABLE; - try { - result = Long.parseLong(value); - if (units != null) { - if (units.equals("kB") || units.equals("KB")) { - result = result * Constants.KILOBYTES_TO_BYTES; - } else { - throw new NotImplementedException("unit conversion from " + units + " not implemented"); - } - } - } catch (NumberFormatException nfe) { - logger.log(Level.WARNING, "error extracting memory info"); - } - - return result; - } -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/NetworkInfoBuilder.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.redhat.thermostat.common.model.NetworkInterfaceInfo; -import com.redhat.thermostat.common.utils.LoggingUtils; - -public class NetworkInfoBuilder { - - private static final Logger logger = LoggingUtils.getLogger(NetworkInfoBuilder.class); - - public static List<NetworkInterfaceInfo> build() { - List<NetworkInterfaceInfo> infos = new ArrayList<NetworkInterfaceInfo>(); - try { - Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); - for (NetworkInterface iface : Collections.list(ifaces)) { - NetworkInterfaceInfo info = new NetworkInterfaceInfo(iface.getName()); - for (InetAddress addr : Collections.list(iface.getInetAddresses())) { - if (addr instanceof Inet4Address) { - info.setIp4Addr(addr.getHostAddress()); - } else if (addr instanceof Inet6Address) { - info.setIp6Addr(addr.getHostAddress()); - } - } - infos.add(info); - } - } catch (SocketException e) { - logger.log(Level.WARNING, "error enumerating network interfaces"); - } - return infos; - } - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/ProcDataSource.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.io.FileReader; -import java.io.IOException; -import java.io.Reader; - -/** - * Wrapper for files under /proc. See proc(5) for details about this. - */ -public class ProcDataSource { - - private static final String LOAD_FILE = "/proc/loadavg"; - private static final String STAT_FILE = "/proc/stat"; - private static final String MEMINFO_FILE = "/proc/meminfo"; - private static final String CPUINFO_FILE = "/proc/cpuinfo"; - - private static final String PID_STAT_FILE = "/proc/${pid}/stat"; - private static final String PID_ENVIRON_FILE = "/proc/${pid}/environ"; - - /** - * Returns a reader for /proc/cpuinfo - */ - public Reader getCpuInfoReader() throws IOException { - return new FileReader(CPUINFO_FILE); - } - - /** - * Returns a reader for /proc/loadavg - */ - public Reader getCpuLoadReader() throws IOException { - return new FileReader(LOAD_FILE); - } - - /** - * Returns a reader for /proc/stat. Kernel/System statistics. - */ - public Reader getStatReader() throws IOException { - return new FileReader(STAT_FILE); - } - - /** - * Returns a reader for /proc/meminfo - */ - public Reader getMemInfoReader() throws IOException { - return new FileReader(MEMINFO_FILE); - } - - /** - * Returns a reader for /proc/$PID/stat - */ - public Reader getStatReader(int pid) throws IOException { - return new FileReader(getPidFile(PID_STAT_FILE, pid)); - } - - /** - * Returns a reader for /proc/$PID/environ - */ - public Reader getEnvironReader(int pid) throws IOException { - return new FileReader(getPidFile(PID_ENVIRON_FILE, pid)); - } - - private String getPidFile(String fileName, int pid) { - return fileName.replace("${pid}", Integer.toString(pid)); - } - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilder.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.io.IOException; -import java.io.Reader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.redhat.thermostat.common.utils.LoggingUtils; - -public class ProcessEnvironmentBuilder { - - private static final Logger logger = LoggingUtils.getLogger(ProcessEnvironmentBuilder.class); - - private final ProcDataSource dataSource; - - public ProcessEnvironmentBuilder(ProcDataSource dataSource) { - this.dataSource = dataSource; - } - - public Map<String, String> build(int pid) { - try (Reader reader = dataSource.getEnvironReader(pid)) { - return build(reader); - } catch (IOException ioe) { - logger.log(Level.WARNING, "error reading env", ioe); - } - - return Collections.emptyMap(); - } - - private Map<String,String> build(Reader reader) throws IOException { - - Map<String, String> env = new HashMap<String, String>(); - - char[] fileBuffer = new char[1024]; - int fileBufferIndex = 0; - char[] buffer = new char[1024]; - int read = 0; - while (true) { - read = reader.read(buffer); - if (read == -1) { - break; - } - - if (read + fileBufferIndex > fileBuffer.length) { - char[] newFileBuffer = new char[fileBuffer.length * 2]; - System.arraycopy(fileBuffer, 0, newFileBuffer, 0, fileBufferIndex); - fileBuffer = newFileBuffer; - } - System.arraycopy(buffer, 0, fileBuffer, fileBufferIndex, read); - fileBufferIndex = fileBufferIndex + read; - - } - List<String> parts = getParts(fileBuffer, fileBufferIndex); - for (String part : parts) { - int splitterPos = part.indexOf("="); - String key = part.substring(0, splitterPos); - String value = part.substring(splitterPos + 1); - env.put(key, value); - } - - return env; - } - - /** - * Split a char array, where items are separated by a null into into a list - * of strings - */ - private List<String> getParts(char[] nullSeparatedBuffer, int bufferLength) { - int maxLength = Math.min(nullSeparatedBuffer.length, bufferLength); - List<String> parts = new ArrayList<String>(); - - int lastStart = 0; - for (int i = 0; i < maxLength; i++) { - if (nullSeparatedBuffer[i] == '\0') { - String string = new String(nullSeparatedBuffer, lastStart, (i - lastStart)); - parts.add(string); - lastStart = i + 1; - } - } - return parts; - } - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfo.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -public class ProcessStatusInfo { - - /* All times are measured in clock ticks */ - - private final int pid; - private final long userTime; - private final long kernelTime; - - public ProcessStatusInfo(int pid, long userTime, long kernelTime) { - this.pid = pid; - this.userTime = userTime; - this.kernelTime = kernelTime; - } - - public int getPid() { - return pid; - } - - /** - * @return the time this process has spent in user-mode as a number of - * kernel ticks - */ - public long getUserTime() { - return userTime; - } - - /** - * @return the time this process spent in kernel-mode as a number of kernel - * ticks - */ - public long getKernelTime() { - return kernelTime; - } - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilder.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.Reader; -import java.util.Scanner; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.redhat.thermostat.common.utils.LoggingUtils; - -/** - * Extract status information about the process from /proc/. This is what tools - * like {@code ps} and {@code top} use. - * - * @see {@code proc(5)} - */ -public class ProcessStatusInfoBuilder { - - private static final Logger logger = LoggingUtils.getLogger(ProcessStatusInfoBuilder.class); - - private final ProcDataSource dataSource; - - public ProcessStatusInfoBuilder(ProcDataSource dataSource) { - this.dataSource = dataSource; - } - - public ProcessStatusInfo build(int pid) { - try (BufferedReader reader = new BufferedReader(dataSource.getStatReader(pid))) { - return build(reader); - } catch (IOException e) { - logger.log(Level.WARNING, "unable to read stat info for " + pid); - } - - return null; - } - - private ProcessStatusInfo build(Reader r) throws IOException { - - int pid = -1; - long utime = -1; - long stime = -1; - - Scanner scanner = null; - - /* TODO map these (effectively c) data types to java types more sanely */ - - try (BufferedReader reader = new BufferedReader(r)) { - String statusLine = reader.readLine(); - - /* be prepared for process names like '1 ) 2 3 4 foo 5' */ - - scanner = new Scanner(statusLine); - pid = scanner.nextInt(); - scanner.close(); - - int execEndNamePos = statusLine.lastIndexOf(')'); - - String cleanStatusLine = statusLine.substring(execEndNamePos + 1); - - scanner = new Scanner(cleanStatusLine); - /* state = */scanner.next(); - /* ppid = */scanner.nextInt(); - /* pgrp = */scanner.nextInt(); - /* session = */scanner.nextInt(); - /* tty_nr = */scanner.nextInt(); - /* tpgid = */scanner.nextInt(); - /* flags = */scanner.nextInt(); - /* minflt = */scanner.nextLong(); - /* cminflt = */scanner.nextLong(); - /* majflt = */scanner.nextLong(); - /* cmajflt = */scanner.nextLong(); - utime = scanner.nextLong(); - stime = scanner.nextLong(); - scanner.close(); - } - - return new ProcessStatusInfo(pid, utime, stime); - - } - -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/SysConf.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -/** - * A wrapper over POSIX's sysconf. - * <p> - * Implementation notes: uses {@code getconf(1)} - */ -public class SysConf { - - private SysConf() { - /* do not initialize */ - } - - public static long getClockTicksPerSecond() { - String ticks = sysConf("CLK_TCK"); - try { - return Long.valueOf(ticks); - } catch (NumberFormatException nfe) { - return 0; - } - } - - private static String sysConf(String arg) { - BufferedReader reader = null; - try { - Process process = Runtime.getRuntime().exec(new String[] { "getconf", arg }); - int result = process.waitFor(); - if (result != 0) { - return null; - } - reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - return reader.readLine(); - } catch (IOException e) { - return null; - } catch (InterruptedException e) { - return null; - } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - // TODO - } - } - } - } -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,243 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.logging.Level; -import java.util.logging.Logger; - -import sun.jvmstat.monitor.HostIdentifier; -import sun.jvmstat.monitor.MonitorException; -import sun.jvmstat.monitor.MonitoredHost; - -import com.redhat.thermostat.agent.JvmStatusListener; -import com.redhat.thermostat.agent.JvmStatusNotifier; -import com.redhat.thermostat.backend.Backend; -import com.redhat.thermostat.common.Clock; -import com.redhat.thermostat.common.SystemClock; -import com.redhat.thermostat.common.dao.CpuStatDAO; -import com.redhat.thermostat.common.dao.HostInfoDAO; -import com.redhat.thermostat.common.dao.MemoryStatDAO; -import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO; -import com.redhat.thermostat.common.dao.VmClassStatDAO; -import com.redhat.thermostat.common.dao.VmCpuStatDAO; -import com.redhat.thermostat.common.dao.VmGcStatDAO; -import com.redhat.thermostat.common.dao.VmInfoDAO; -import com.redhat.thermostat.common.dao.VmMemoryStatDAO; -import com.redhat.thermostat.common.model.NetworkInterfaceInfo; -import com.redhat.thermostat.common.model.VmCpuStat; -import com.redhat.thermostat.common.storage.Category; -import com.redhat.thermostat.common.utils.LoggingUtils; - -public class SystemBackend extends Backend implements JvmStatusNotifier, JvmStatusListener { - - private static final Logger logger = LoggingUtils.getLogger(SystemBackend.class); - - private CpuStatDAO cpuStats; - private HostInfoDAO hostInfos; - private MemoryStatDAO memoryStats; - private VmCpuStatDAO vmCpuStats; - private NetworkInterfaceInfoDAO networkInterfaces; - - private final Set<Integer> pidsToMonitor = new CopyOnWriteArraySet<Integer>(); - - private long procCheckInterval = 1000; // TODO make this configurable. - - private Timer timer = null; - - private HostIdentifier hostId = null; - private MonitoredHost host = null; - private JvmStatHostListener hostListener; - - private final VmCpuStatBuilder vmCpuBuilder; - private final HostInfoBuilder hostInfoBuilder; - private final CpuStatBuilder cpuStatBuilder; - private final MemoryStatBuilder memoryStatBuilder; - - public SystemBackend() { - super(); - - Clock clock = new SystemClock(); - ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(new ProcDataSource()); - long ticksPerSecond = SysConf.getClockTicksPerSecond(); - ProcDataSource source = new ProcDataSource(); - hostInfoBuilder = new HostInfoBuilder(source); - cpuStatBuilder = new CpuStatBuilder(clock, source, ticksPerSecond); - memoryStatBuilder = new MemoryStatBuilder(source); - - int cpuCount = hostInfoBuilder.getCpuInfo().count; - vmCpuBuilder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, builder); - } - - @Override - protected void setDAOFactoryAction() { - cpuStats = df.getCpuStatDAO(); - hostInfos = df.getHostInfoDAO(); - memoryStats = df.getMemoryStatDAO(); - vmCpuStats = df.getVmCpuStatDAO(); - networkInterfaces = df.getNetworkInterfaceInfoDAO(); - hostListener = new JvmStatHostListener(df.getVmInfoDAO(), df.getVmMemoryStatDAO(), df.getVmGcStatDAO(), df.getVmClassStatsDAO(), getObserveNewJvm()); - } - - @Override - public synchronized boolean activate() { - if (timer != null) { - return true; - } - if (df == null) { - throw new IllegalStateException("Cannot activate backend without DAOFactory."); - } - - addJvmStatusListener(this); - - if (!getObserveNewJvm()) { - logger.fine("not monitoring new vms"); - } - hostInfos.putHostInfo(hostInfoBuilder.build()); - - timer = new Timer(); - timer.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - if (!cpuStatBuilder.isInitialized()) { - cpuStatBuilder.initialize(); - } else { - cpuStats.putCpuStat(cpuStatBuilder.build()); - } - for (NetworkInterfaceInfo info: NetworkInfoBuilder.build()) { - networkInterfaces.putNetworkInterfaceInfo(info); - } - memoryStats.putMemoryStat(memoryStatBuilder.build()); - - for (Integer pid : pidsToMonitor) { - if (vmCpuBuilder.knowsAbout(pid)) { - VmCpuStat dataBuilt = vmCpuBuilder.build(pid); - if (dataBuilt != null) { - vmCpuStats.putVmCpuStat(dataBuilt); - } - } else { - vmCpuBuilder.learnAbout(pid); - } - } - } - }, 0, procCheckInterval); - - try { - hostId = new HostIdentifier((String) null); - host = MonitoredHost.getMonitoredHost(hostId); - host.addHostListener(hostListener); - } catch (MonitorException me) { - logger.log(Level.WARNING, "problems with connecting jvmstat to local machine", me); - } catch (URISyntaxException use) { - logger.log(Level.WARNING, "problems with connecting jvmstat to local machine", use); - } - - return true; - } - - @Override - public synchronized boolean deactivate() { - if (timer == null) { - return true; - } - - timer.cancel(); - timer = null; - - removeJvmStatusListener(this); - - try { - - // remove all listener from the host listener - hostListener.removeAllListeners(); - - host.removeHostListener(hostListener); - } catch (MonitorException me) { - logger.log(Level.INFO, "something went wrong in jvmstat's listening to this host"); - } - host = null; - hostId = null; - - return true; - } - - @Override - public synchronized boolean isActive() { - return (timer != null); - } - - @Override - public String getConfigurationValue(String key) { - return null; - } - - @Override - public boolean attachToNewProcessByDefault() { - return true; - } - - @Override - public void addJvmStatusListener(JvmStatusListener listener) { - hostListener.addJvmStatusListener(listener); - } - - @Override - public void removeJvmStatusListener(JvmStatusListener listener) { - hostListener.removeJvmStatusListener(listener); - } - - @Override - public void jvmStarted(int vmId) { - if (getObserveNewJvm()) { - pidsToMonitor.add(vmId); - } - } - - @Override - public void jvmStopped(int vmId) { - pidsToMonitor.remove(vmId); - vmCpuBuilder.forgetAbout(vmId); - } -}
--- a/agent/core/src/main/java/com/redhat/thermostat/backend/system/VmCpuStatBuilder.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.redhat.thermostat.common.Clock; -import com.redhat.thermostat.common.model.VmCpuStat; -import com.redhat.thermostat.common.utils.LoggingUtils; - -public class VmCpuStatBuilder { - - private static final Logger logger = LoggingUtils.getLogger(VmCpuStatBuilder.class); - - // pid -> ticks - private final Map<Integer, Long> lastProcessTicks = new HashMap<Integer, Long>(); - // pid -> last time the ticks were updated - private final Map<Integer, Long> lastProcessTickTime = new HashMap<Integer, Long>(); - - private final Clock clock; - private final int cpuCount; - private final long ticksPerSecond; - private final ProcessStatusInfoBuilder statusBuilder; - - public VmCpuStatBuilder(Clock clock, int cpuCount, long ticksPerSecond, ProcessStatusInfoBuilder statusBuilder) { - this.clock = clock; - this.cpuCount = cpuCount; - this.ticksPerSecond = ticksPerSecond; - this.statusBuilder = statusBuilder; - } - - /** - * @param pid the process id - * @return an object representing the cpu usage of the process, or null if - * the information can not be found. - */ - public synchronized VmCpuStat build(Integer pid) { - if (!lastProcessTicks.containsKey(pid) || !lastProcessTickTime.containsKey(pid)) { - throw new IllegalArgumentException("unknown pid"); - } - - ProcessStatusInfo info = statusBuilder.build(pid); - if (info == null) { - return null; - } - long miliTime = clock.getRealTimeMillis(); - long time = clock.getMonotonicTimeNanos(); - long programTicks = (info.getKernelTime() + info.getUserTime()); - double cpuLoad = 0.0; - - double timeDelta = (time - lastProcessTickTime.get(pid)) * 1E-9; - long programTicksDelta = programTicks - lastProcessTicks.get(pid); - // 100 as in 100 percent. - cpuLoad = programTicksDelta * (100.0 / timeDelta / ticksPerSecond / cpuCount); - - if (cpuLoad < 0.0 || cpuLoad > 100.0) { - logger.log(Level.WARNING, "cpu load for " + pid + " is outside [0,100]: " + cpuLoad); - logger.log(Level.WARNING, " (" + pid + ") programTicks: " + programTicks); - logger.log(Level.WARNING, " (" + pid + ") programTicksDelta: " + programTicksDelta); - logger.log(Level.WARNING, " (" + pid + ") time: " + time); - logger.log(Level.WARNING, " (" + pid + ") timeDelta: " + timeDelta); - logger.log(Level.WARNING, " (" + pid + ") ticksPerSecond: " + ticksPerSecond); - logger.log(Level.WARNING, " (" + pid + ") cpuCount: " + cpuCount); - } - - lastProcessTicks.put(pid, programTicks); - lastProcessTickTime.put(pid, time); - - return new VmCpuStat(miliTime, pid, cpuLoad); - } - - public synchronized boolean knowsAbout(int pid) { - return (lastProcessTickTime.containsKey(pid) && lastProcessTicks.containsKey(pid)); - } - - public synchronized void learnAbout(int pid) { - long time = clock.getMonotonicTimeNanos(); - ProcessStatusInfo info = statusBuilder.build(pid); - if (info == null) { - logger.log(Level.WARNING, "can not learn about pid " + pid + " : statusBuilder returned null"); - return; - } - - lastProcessTickTime.put(pid, time); - lastProcessTicks.put(pid, info.getUserTime()+ info.getKernelTime()); - } - - public synchronized void forgetAbout(int pid) { - lastProcessTicks.remove(pid); - lastProcessTickTime.remove(pid); - } - -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/main/java/com/redhat/thermostat/utils/ProcDataSource.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,102 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.utils; + +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; + +/** + * Wrapper for files under /proc. See proc(5) for details about this. + */ +public class ProcDataSource { + + private static final String LOAD_FILE = "/proc/loadavg"; + private static final String STAT_FILE = "/proc/stat"; + private static final String MEMINFO_FILE = "/proc/meminfo"; + private static final String CPUINFO_FILE = "/proc/cpuinfo"; + + private static final String PID_STAT_FILE = "/proc/${pid}/stat"; + private static final String PID_ENVIRON_FILE = "/proc/${pid}/environ"; + + /** + * Returns a reader for /proc/cpuinfo + */ + public Reader getCpuInfoReader() throws IOException { + return new FileReader(CPUINFO_FILE); + } + + /** + * Returns a reader for /proc/loadavg + */ + public Reader getCpuLoadReader() throws IOException { + return new FileReader(LOAD_FILE); + } + + /** + * Returns a reader for /proc/stat. Kernel/System statistics. + */ + public Reader getStatReader() throws IOException { + return new FileReader(STAT_FILE); + } + + /** + * Returns a reader for /proc/meminfo + */ + public Reader getMemInfoReader() throws IOException { + return new FileReader(MEMINFO_FILE); + } + + /** + * Returns a reader for /proc/$PID/stat + */ + public Reader getStatReader(int pid) throws IOException { + return new FileReader(getPidFile(PID_STAT_FILE, pid)); + } + + /** + * Returns a reader for /proc/$PID/environ + */ + public Reader getEnvironReader(int pid) throws IOException { + return new FileReader(getPidFile(PID_ENVIRON_FILE, pid)); + } + + private String getPidFile(String fileName, int pid) { + return fileName.replace("${pid}", Integer.toString(pid)); + } + +}
--- a/agent/core/src/test/java/com/redhat/thermostat/agent/AgentTest.java Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/core/src/test/java/com/redhat/thermostat/agent/AgentTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -37,17 +37,20 @@ package com.redhat.thermostat.agent; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.isA; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.isA; +import static org.mockito.Mockito.atLeast; import java.util.ArrayList; import java.util.Collection; -import java.util.List; import org.junit.Before; import org.junit.Test; @@ -55,19 +58,27 @@ import com.redhat.thermostat.agent.config.AgentStartupConfiguration; import com.redhat.thermostat.backend.Backend; +import com.redhat.thermostat.backend.BackendID; import com.redhat.thermostat.backend.BackendRegistry; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.ThermostatExtensionRegistry; import com.redhat.thermostat.common.dao.AgentInfoDAO; import com.redhat.thermostat.common.dao.BackendInfoDAO; +import com.redhat.thermostat.common.dao.DAOFactory; import com.redhat.thermostat.common.model.AgentInformation; import com.redhat.thermostat.common.model.BackendInformation; import com.redhat.thermostat.common.storage.Storage; +@SuppressWarnings({ "rawtypes", "unchecked" }) public class AgentTest { private AgentStartupConfiguration config; private BackendRegistry backendRegistry; private Backend backend; + private DAOFactory daoFactory; + private Storage storage; private AgentInfoDAO agentInfoDao; private BackendInfoDAO backendInfoDao; @@ -82,6 +93,11 @@ agentInfoDao = mock(AgentInfoDAO.class); backendInfoDao = mock(BackendInfoDAO.class); + daoFactory = mock(DAOFactory.class); + when(daoFactory.getStorage()).thenReturn(storage); + when(daoFactory.getAgentInfoDAO()).thenReturn(agentInfoDao); + when(daoFactory.getBackendInfoDAO()).thenReturn(backendInfoDao); + backend = mock(Backend.class); when(backend.getName()).thenReturn("testname"); when(backend.getDescription()).thenReturn("testdesc"); @@ -91,52 +107,100 @@ backends.add(backend); backendRegistry = mock(BackendRegistry.class); - when(backendRegistry.getAll()).thenReturn(backends); + } + + @SuppressWarnings("unused") + @Test + public void testAgentInit() throws Exception { + Agent agent = new Agent(backendRegistry, config, daoFactory); + + verify(daoFactory).getStorage(); + verify(daoFactory).getAgentInfoDAO(); + verify(daoFactory).getBackendInfoDAO(); + + verify(backendRegistry).addActionListener(any(ActionListener.class)); } @Test public void testStartAgent() throws Exception { // Start agent. - Agent agent = new Agent(backendRegistry, config, storage, agentInfoDao, backendInfoDao); + Agent agent = new Agent(backendRegistry, config, daoFactory); + agent.start(); - // Verify that backend has been activated and storage received the agent information. - verify(backend).activate(); + // Verify that backend registry is started + verify(backendRegistry).start(); + ArgumentCaptor<AgentInformation> argument = ArgumentCaptor.forClass(AgentInformation.class); + + verify(agentInfoDao).addAgentInformation(argument.capture()); + assertEquals(123, argument.getValue().getStartTime()); + } + + @Test + public void testServiceAddedRemovedFromOSGi() throws Exception { + ArgumentCaptor<ActionListener> backendListener = ArgumentCaptor.forClass(ActionListener.class); + + // Start agent. + Agent agent = new Agent(backendRegistry, config, daoFactory); + verify(backendRegistry).addActionListener(backendListener.capture()); + + agent.start(); + + // Verify that backend registry is started + verify(backendRegistry).start(); ArgumentCaptor<AgentInformation> argument = ArgumentCaptor.forClass(AgentInformation.class); verify(agentInfoDao).addAgentInformation(argument.capture()); assertEquals(123, argument.getValue().getStartTime()); - ArgumentCaptor<BackendInformation> backendsArg = ArgumentCaptor.forClass(BackendInformation.class); - verify(backendInfoDao).addBackendInformation(backendsArg.capture()); + ActionListener listener = backendListener.getValue(); + + // add a fake backend to see if it's registered corectly + ActionEvent<ThermostatExtensionRegistry.Action> actionEvent = + new ActionEvent<>(this, ThermostatExtensionRegistry.Action.SERVICE_ADDED); + actionEvent.setPayload(backend); + + listener.actionPerformed(actionEvent); + + verify(backend).setDAOFactory(daoFactory); + verify(backend).activate(); + + assertTrue(agent.getBackendInfos().containsKey(backend)); + BackendInformation info = agent.getBackendInfos().get(backend); + assertEquals("testname", info.getName()); + assertEquals("testdesc", info.getDescription()); + assertEquals(true, info.isObserveNewJvm()); + assertEquals(true, info.isActive()); + + verify(backendInfoDao).addBackendInformation(info); - List<BackendInformation> backendInfos = backendsArg.getAllValues(); - assertEquals(1, backendInfos.size()); - BackendInformation backend0 = backendInfos.get(0); - assertEquals("testname", backend0.getName()); - assertEquals("testdesc", backend0.getDescription()); - assertEquals(true, backend0.isObserveNewJvm()); - assertEquals(true, backend0.isActive()); - // TODO: We should probably also test getPIDs() and getConfiguration(), but it's not clear to me at this point - // what those should really do (and it looks like they're not implemented yet). + actionEvent = new ActionEvent<>(this, ThermostatExtensionRegistry.Action.SERVICE_REMOVED); + actionEvent.setPayload(backend); + listener.actionPerformed(actionEvent); + + verify(backend).deactivate(); + + assertFalse(agent.getBackendInfos().containsKey(backend)); + verify(backendInfoDao).removeBackendInformation(info); } @Test public void testStopAgentWithPurging() throws Exception { - Agent agent = new Agent(backendRegistry, config, storage, agentInfoDao, backendInfoDao); + + Agent agent = new Agent(backendRegistry, config, daoFactory); agent.start(); // stop agent agent.stop(); - verify(backend).deactivate(); + verify(backendRegistry).stop(); ArgumentCaptor<AgentInformation> argument = ArgumentCaptor.forClass(AgentInformation.class); verify(agentInfoDao, never()).updateAgentInformation(argument.capture()); verify(storage, times(1)).purge(); } - + @Test public void testStopAgentWithoutPurging() throws Exception { @@ -144,16 +208,15 @@ when(config.getStartTime()).thenReturn(123L); when(config.purge()).thenReturn(false); - Agent agent = new Agent(backendRegistry, config, storage, agentInfoDao, backendInfoDao); + Agent agent = new Agent(backendRegistry, config, daoFactory); agent.start(); // stop agent agent.stop(); - verify(backend).deactivate(); + verify(backendRegistry).stop(); verify(agentInfoDao).updateAgentInformation(isA(AgentInformation.class)); - verify(backendInfoDao, atLeast(1)).removeBackendInformation(isA(BackendInformation.class)); verify(storage, times(0)).purge(); } }
--- a/agent/core/src/test/java/com/redhat/thermostat/agent/TestUtils.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.agent; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.util.Properties; -import java.util.Random; - -import com.redhat.thermostat.agent.config.AgentProperties; -import com.redhat.thermostat.backend.BackendsProperties; - -public class TestUtils { - - public static int getProcessId() { - String name = ManagementFactory.getRuntimeMXBean().getName(); - String pidPart = name.split("@")[0]; - return Integer.parseInt(pidPart); - } - - public static boolean isLinux() { - return (System.getProperty("os.name").toLowerCase().contains("linux")); - } - - public static String setupAgentConfigs() throws IOException { - // need to create dummy config files for the tests - Random random = new Random(); - - String tmpDir = System.getProperty("java.io.tmpdir") + File.separatorChar + - Math.abs(random.nextInt()) + File.separatorChar; - - System.setProperty("THERMOSTAT_HOME", tmpDir); - File agent = new File(tmpDir, "agent"); - agent.mkdirs(); - - File tmpConfigs = new File(agent, "agent.properties"); - - new File(agent, "run").mkdirs(); - new File(agent, "logs").mkdirs(); - - File backends = new File(tmpDir, "backends"); - File system = new File(backends, "system"); - system.mkdirs(); - - Properties props = new Properties(); - - props.setProperty(AgentProperties.BACKENDS.name(), "system"); - props.setProperty(AgentProperties.SAVE_ON_EXIT.name(), "false"); - - props.store(new FileOutputStream(tmpConfigs), "thermostat agent test properties"); - - // now write the configs for the backends - tmpConfigs = new File(system, "backend.properties"); - props = new Properties(); - props.setProperty(BackendsProperties.BACKEND_CLASS.name(), - "com.redhat.thermostat.backend.system.SystemBackend"); - props.setProperty(BackendsProperties.DESCRIPTION.name(), - "fluff backend for tests"); - props.setProperty(BackendsProperties.VENDOR.name(), - "Red Hat, Inc."); - props.setProperty(BackendsProperties.VERSION.name(), - "1.0"); - props.store(new FileOutputStream(tmpConfigs), "thermostat system backend properties"); - - return tmpDir; - } -}
--- a/agent/core/src/test/java/com/redhat/thermostat/agent/config/AgentConfigsUtilsTest.java Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/core/src/test/java/com/redhat/thermostat/agent/config/AgentConfigsUtilsTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -37,14 +37,12 @@ package com.redhat.thermostat.agent.config; import java.io.IOException; -import java.util.List; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import com.redhat.thermostat.agent.TestUtils; -import com.redhat.thermostat.backend.BackendID; +import com.redhat.thermostat.common.TestUtils; import com.redhat.thermostat.common.config.InvalidConfigurationException; public class AgentConfigsUtilsTest { @@ -57,10 +55,8 @@ @Test public void test() throws InvalidConfigurationException { AgentStartupConfiguration config = AgentConfigsUtils.createAgentConfigs(); - List<BackendID> backends = config.getBackends(); - - // the test property only define the system backend so far - Assert.assertEquals(1, backends.size()); - Assert.assertEquals("system", backends.get(0).getSimpleName()); + + Assert.assertFalse(config.purge()); + Assert.assertEquals("42.42.42.42:42", config.getConfigListenAddress()); } }
--- a/agent/core/src/test/java/com/redhat/thermostat/agent/config/AgentOptionParserTest.java Fri Oct 19 15:33:45 2012 -0400 +++ b/agent/core/src/test/java/com/redhat/thermostat/agent/config/AgentOptionParserTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -45,7 +45,7 @@ import org.junit.BeforeClass; import org.junit.Test; -import com.redhat.thermostat.agent.TestUtils; +import com.redhat.thermostat.common.TestUtils; import com.redhat.thermostat.common.cli.SimpleArguments; import com.redhat.thermostat.common.config.InvalidConfigurationException; @@ -76,7 +76,7 @@ Assert.assertEquals("testURL", configs.getDBConnectionString()); Assert.assertTrue(configs.isDebugConsole()); - Assert.assertTrue(configs.purge()); + Assert.assertFalse(configs.purge()); } @Test
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/BackendConfigurationLoaderTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend; - -import java.io.IOException; -import java.util.Map; - -import junit.framework.Assert; - -import org.junit.Before; -import org.junit.Test; - -import com.redhat.thermostat.agent.TestUtils; -import com.redhat.thermostat.backend.system.SystemBackend; -import com.redhat.thermostat.common.config.InvalidConfigurationException; - -public class BackendConfigurationLoaderTest { - - @Before - public void setUp() throws IOException { - TestUtils.setupAgentConfigs(); - } - - @Test - public void test() throws InvalidConfigurationException { - Map<String, String> backendProps = new BackendConfigurationLoader().retrieveBackendConfigs("system"); - Assert.assertTrue(backendProps.containsKey(BackendsProperties.BACKEND_CLASS.name())); - - String className = backendProps.get(BackendsProperties.BACKEND_CLASS.name()); - Assert.assertEquals(SystemBackend.class.getCanonicalName(), className); - } -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/BackendRegistryTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import com.redhat.thermostat.agent.config.AgentStartupConfiguration; -import com.redhat.thermostat.common.config.InvalidConfigurationException; -import com.redhat.thermostat.common.dao.DAOFactory; -import com.redhat.thermostat.common.storage.Storage; - -public class BackendRegistryTest { - - public static class MockBackend extends Backend { - public MockBackend() { - super(); - } - - @Override - public String getConfigurationValue(String key) { - return null; - } - @Override - public boolean activate() { - return true; - } - @Override - public boolean deactivate() { - return false; - } - @Override - public boolean isActive() { - return false; - } - @Override - public boolean attachToNewProcessByDefault() { - return false; - } - - @Override - protected void setDAOFactoryAction() { - /* NO-OP */ - } - } - - private DAOFactory daoFactory; - private List<BackendID> backends; - private AgentStartupConfiguration config; - private BackendConfigurationLoader configLoader; - - @Before - public void setUp() throws InvalidConfigurationException { - backends = new ArrayList<>(); - - config = mock(AgentStartupConfiguration.class); - when(config.getBackends()).thenReturn(backends); - - configLoader = mock(BackendConfigurationLoader.class); - when(configLoader.retrieveBackendConfigs(any(String.class))).thenReturn(new HashMap<String,String>()); - - Storage storage = mock(Storage.class); - daoFactory = mock(DAOFactory.class); - when(daoFactory.getStorage()).thenReturn(storage); - } - - @After - public void tearDown() { - backends = null; - config = null; - configLoader = null; - } - - @Test - public void testRegisterBackend() throws BackendLoadException, InvalidConfigurationException { - /* setup fake backend */ - backends.add(new BackendID("mock", MockBackend.class.getName())); - - BackendRegistry registry = new BackendRegistry(config, configLoader, daoFactory); - assertEquals(1, registry.getAll().size()); - assertNotNull(registry.getByName("mock")); - } - - @Test - public void testNoBackendsRegistered() throws InvalidConfigurationException, BackendLoadException { - BackendRegistry registry = new BackendRegistry(config, configLoader, daoFactory); - assertEquals(0, registry.getAll().size()); - assertEquals(null, registry.getByName("system")); - assertEquals(null, registry.getByName("mock")); - } - - @Test (expected=BackendLoadException.class) - public void testRegisterBackendTwice() throws BackendLoadException, InvalidConfigurationException { - /* setup fake backends */ - - backends.add(new BackendID("mock", MockBackend.class.getClass().getName())); - backends.add(new BackendID("mock", MockBackend.class.getClass().getName())); - - /* load the backends */ - new BackendRegistry(config, configLoader, daoFactory); - } - -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/sample/SampleBackendTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.sample; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import org.junit.Before; -import org.junit.Test; - -public class SampleBackendTest { - - private SampleBackend b; - - @Before - public void setUp() { - b = new SampleBackend(); - } - - @Test - public void testBackendInfo() { - assertNotNull(b.getName()); - assertNotNull(b.getVersion()); - assertNotNull(b.getVendor()); - assertNotNull(b.getDescription()); - } - - @Test - public void testBasicBackend() { - assertFalse(b.isActive()); - b.activate(); - assertTrue(b.isActive()); - b.deactivate(); - assertFalse(b.isActive()); - } - - @Test - public void testActivateTwice() { - b.activate(); - b.activate(); - assert (b.isActive()); - } - - @Test - public void testDeactiateWhenNotActive() { - b.deactivate(); - b.deactivate(); - assertFalse(b.isActive()); - } - - @Test - public void testDefaultConfiguration() { - assertTrue(b.getConfigurationMap().isEmpty()); - assertTrue(b.getConfigurationValue("foo") == null); - - } - - @Test - public void testModifyConfiguration() { - b.setConfigurationValue("speed", "fast"); - assertEquals("fast", b.getConfigurationValue("speed")); - } - -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/CpuStatBuilderTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; - -import org.junit.Test; - -import com.redhat.thermostat.common.Clock; -import com.redhat.thermostat.common.SystemClock; -import com.redhat.thermostat.common.model.CpuStat; -import com.redhat.thermostat.common.utils.ArrayUtils; - -public class CpuStatBuilderTest { - - @Test - public void testSimpleBuild() { - ProcDataSource dataSource = new ProcDataSource(); - CpuStatBuilder builder= new CpuStatBuilder(new SystemClock(), dataSource, 100l); - builder.initialize(); - CpuStat stat = builder.build(); - assertNotNull(stat); - } - - @Test (expected=IllegalStateException.class) - public void buildWithoutInitializeThrowsException() { - Clock clock = mock(Clock.class); - ProcDataSource dataSource = mock(ProcDataSource.class); - long ticksPerSecond = 1; - CpuStatBuilder builder = new CpuStatBuilder(clock, dataSource, ticksPerSecond); - builder.build(); - } - - @Test - public void testBuildCpuStatFromFile() throws IOException { - long CLOCK1 = 1000; - long CLOCK2 = 2000; - - String firstReadContents = - "cpu 100 0 0 1000 1000\n" + - "cpu0 100 0 0 1000 1000\n" + - "cpu1 10 80 10 1000 1000\n"; - BufferedReader reader1 = new BufferedReader(new StringReader(firstReadContents)); - - String secondReadContents = - "cpu 400 0 0 1000 1000\n" + - "cpu0 200 0 0 1000 1000\n" + - "cpu1 30 50 120 1000 1000\n"; - BufferedReader reader2 = new BufferedReader(new StringReader(secondReadContents)); - - long ticksPerSecond = 100; - Clock clock = mock(Clock.class); - when(clock.getRealTimeMillis()).thenReturn(CLOCK2); - when(clock.getMonotonicTimeNanos()).thenReturn((long)(CLOCK1 * 1E6)).thenReturn((long)(CLOCK2 * 1E6)); - - ProcDataSource dataSource = mock(ProcDataSource.class); - when(dataSource.getStatReader()).thenReturn(reader1).thenReturn(reader2); - CpuStatBuilder builder = new CpuStatBuilder(clock, dataSource, ticksPerSecond); - - builder.initialize(); - - CpuStat stat = builder.build(); - - verify(dataSource, times(2)).getStatReader(); - assertArrayEquals(new double[] {100, 100}, ArrayUtils.toPrimitiveDoubleArray(stat.getPerProcessorUsage()), 0.01); - } - -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/DistributionInformationTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import com.redhat.thermostat.agent.TestUtils; - -public class DistributionInformationTest { - - @Test - public void testName() { - if (TestUtils.isLinux()) { - DistributionInformation info = DistributionInformation.get(); - String name = info.getName(); - assertNotNull(name); - assertTrue(name.length() > 0); - assertFalse(name.startsWith(":")); - assertFalse(name.equals(DistributionInformation.UNKNOWN_NAME)); - } - } - - @Test - public void testVersion() { - if (TestUtils.isLinux()) { - DistributionInformation info = DistributionInformation.get(); - String version = info.getVersion(); - assertNotNull(version); - assertTrue(version.length()> 0); - assertFalse(version.startsWith(":")); - assertFalse(version.equals(DistributionInformation.UNKNOWN_VERSION)); - } - } - -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/EtcOsReleaseTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertEquals; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; - -import org.junit.Test; - -import com.redhat.thermostat.test.Bug; - -public class EtcOsReleaseTest { - - @Test - public void testName() throws IOException, InterruptedException { - BufferedReader reader = new BufferedReader(new StringReader("NAME=\"Name\"\n")); - DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader); - assertEquals("Name", info.getName()); - } - - - @Test - public void testVersion() throws IOException { - BufferedReader reader = new BufferedReader(new StringReader("VERSION=\"Version\"\n")); - DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader); - assertEquals("Version", info.getVersion()); - } - - @Bug(id="981", - summary="DistributionInformationTest fails on OpenSUSE Linux 12.1", - url="http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=981") - @Test - public void testFormattedOutput() throws IOException { - String output = - "NAME=openSUSE\n" + - "VERSION = 12.1 (Asparagus)\n" + - "VERSION_ID=\"12.1\"\n" + - "PRETTY_NAME=\"openSUSE 12.1 (Asparagus) (x86_64)\"\n" + - "ID=opensuse"; - BufferedReader reader = new BufferedReader(new StringReader(output)); - DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader); - - assertEquals("openSUSE", info.getName()); - assertEquals("12.1 (Asparagus)", info.getVersion()); - } - -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/HostInfoBuilderTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.IOException; -import java.io.StringReader; -import java.net.InetAddress; - -import org.junit.Test; - -import com.redhat.thermostat.backend.system.HostInfoBuilder.HostCpuInfo; -import com.redhat.thermostat.backend.system.HostInfoBuilder.HostMemoryInfo; -import com.redhat.thermostat.backend.system.HostInfoBuilder.HostOsInfo; -import com.redhat.thermostat.common.Constants; -import com.redhat.thermostat.common.model.HostInfo; - -public class HostInfoBuilderTest { - - @Test - public void testSimpleBuild() { - HostInfo info = new HostInfoBuilder(new ProcDataSource()).build(); - assertNotNull(info); - } - - @Test - public void testCpuInfo() throws IOException { - String cpuInfoString = - "processor: 1\n" + - "model name: Test Model\n" + - "processor: 0\n" + - "model name: Test Model\n"; - - StringReader cpuInfoReader = new StringReader(cpuInfoString); - - ProcDataSource dataSource = mock(ProcDataSource.class); - when(dataSource.getCpuInfoReader()).thenReturn(cpuInfoReader); - - HostCpuInfo cpuInfo = new HostInfoBuilder(dataSource).getCpuInfo(); - assertEquals(2, cpuInfo.count); - assertEquals("Test Model", cpuInfo.model); - verify(dataSource).getCpuInfoReader(); - } - - @Test - public void testMemoryInfo() throws IOException { - String memoryInfoString = - "MemTotal: 12345 kB"; - - StringReader memoryInfoReader = new StringReader(memoryInfoString); - ProcDataSource dataSource = mock(ProcDataSource.class); - when(dataSource.getMemInfoReader()).thenReturn(memoryInfoReader); - - HostMemoryInfo memoryInfo = new HostInfoBuilder(dataSource).getMemoryInfo(); - assertNotNull(memoryInfo); - assertEquals(12345 * Constants.KILOBYTES_TO_BYTES, memoryInfo.totalMemory); - verify(dataSource).getMemInfoReader(); - - } - - @Test - public void testOsInfo() { - DistributionInformation distroInfo = new DistributionInformation("distro-name", "distro-version"); - ProcDataSource dataSource = mock(ProcDataSource.class); - HostOsInfo osInfo = new HostInfoBuilder(dataSource).getOsInfo(distroInfo); - assertEquals("distro-name distro-version", osInfo.distribution); - assertEquals(System.getProperty("os.name") + " " + System.getProperty("os.version"), osInfo.kernel); - } - - @Test - public void testHostname() { - - InetAddress address = mock(InetAddress.class); - when(address.getCanonicalHostName()).thenReturn("test-hostname"); - - ProcDataSource dataSource = mock(ProcDataSource.class); - - String name = new HostInfoBuilder(dataSource).getHostName(address); - assertEquals("test-hostname", name); - } - -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/JvmStatDataExtractorTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,375 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.junit.Test; - -import sun.jvmstat.monitor.LongMonitor; -import sun.jvmstat.monitor.MonitorException; -import sun.jvmstat.monitor.MonitoredVm; -import sun.jvmstat.monitor.StringMonitor; - -public class JvmStatDataExtractorTest { - - private MonitoredVm buildStringMonitoredVm(String monitorName, String monitorReturn) throws MonitorException { - final StringMonitor monitor = mock(StringMonitor.class); - when(monitor.stringValue()).thenReturn(monitorReturn); - when(monitor.getValue()).thenReturn(monitorReturn); - MonitoredVm vm = mock(MonitoredVm.class); - when(vm.findByName(monitorName)).thenReturn(monitor); - return vm; - } - - private MonitoredVm buildLongMonitoredVm(String monitorName, Long monitorReturn) throws MonitorException { - final LongMonitor monitor = mock(LongMonitor.class); - when(monitor.longValue()).thenReturn(monitorReturn); - when(monitor.getValue()).thenReturn(monitorReturn); - MonitoredVm vm = mock(MonitoredVm.class); - when(vm.findByName(monitorName)).thenReturn(monitor); - return vm; - } - - @Test - public void testCommandLine() throws MonitorException { - final String MONITOR_NAME = "sun.rt.javaCommand"; - final String MONITOR_VALUE = "command line java"; - MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - String returned = extractor.getCommandLine(); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(MONITOR_VALUE, returned); - } - - @Test - public void testMainClass() throws MonitorException { - final String MONITOR_NAME = "sun.rt.javaCommand"; - final String MONITOR_VALUE = "some.package.Main"; - MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - String returned = extractor.getMainClass(); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(MONITOR_VALUE, returned); - } - - @Test - public void testJavaVersion() throws MonitorException { - final String MONITOR_NAME = "java.property.java.version"; - final String MONITOR_VALUE = "some java version"; - MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - String returned = extractor.getJavaVersion(); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(MONITOR_VALUE, returned); - } - - @Test - public void testJavaHome() throws MonitorException { - final String MONITOR_NAME = "java.property.java.home"; - final String MONITOR_VALUE = "${java.home}"; - MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - String returned = extractor.getJavaHome(); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(MONITOR_VALUE, returned); - } - - @Test - public void testVmName() throws MonitorException { - final String MONITOR_NAME = "java.property.java.vm.name"; - final String MONITOR_VALUE = "${vm.name}"; - MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - String returned = extractor.getVmName(); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(MONITOR_VALUE, returned); - } - - @Test - public void testVmInfo() throws MonitorException { - final String MONITOR_NAME = "java.property.java.vm.info"; - final String MONITOR_VALUE = "${vm.info}"; - MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - String returned = extractor.getVmInfo(); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(MONITOR_VALUE, returned); - } - - @Test - public void testVmVersion() throws MonitorException { - final String MONITOR_NAME = "java.property.java.vm.version"; - final String MONITOR_VALUE = "${vm.version}"; - MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - String returned = extractor.getVmVersion(); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(MONITOR_VALUE, returned); - } - - @Test - public void testVmArguments() throws MonitorException { - final String MONITOR_NAME = "java.rt.vmArgs"; - final String MONITOR_VALUE = "${vm.arguments}"; - MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - String returned = extractor.getVmArguments(); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(MONITOR_VALUE, returned); - } - - @Test - public void testTotalCollectors() throws MonitorException { - final String MONITOR_NAME = "sun.gc.policy.collectors"; - final Long MONITOR_VALUE = 9l; - MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, MONITOR_VALUE); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getTotalCollectors(); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(MONITOR_VALUE, returned); - } - - @Test - public void testCollectorName() throws MonitorException { - final String MONITOR_NAME = "sun.gc.collector.0.name"; - final String COLLECTOR_NAME = "SomeMemoryCollector"; - MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, COLLECTOR_NAME); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - String returned = extractor.getCollectorName(0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(COLLECTOR_NAME, returned); - } - - @Test - public void testCollectorTime() throws MonitorException { - final String MONITOR_NAME = "sun.gc.collector.0.time"; - final Long COLLECTOR_TIME = 99l; - MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, COLLECTOR_TIME); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getCollectorTime(0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(COLLECTOR_TIME, returned); - } - - @Test - public void testCollectorInvocations() throws MonitorException { - final String MONITOR_NAME = "sun.gc.collector.0.invocations"; - final Long COLLECTOR_INVOCATIONS = 99l; - MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, COLLECTOR_INVOCATIONS); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getCollectorInvocations(0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(COLLECTOR_INVOCATIONS, returned); - } - - @Test - public void testTotalGcGenerations() throws MonitorException { - final String MONITOR_NAME = "sun.gc.policy.generations"; - final Long GC_GENERATIONS = 99l; - MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, GC_GENERATIONS); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getTotalGcGenerations(); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(GC_GENERATIONS, returned); - } - - @Test - public void testGenerationName() throws MonitorException { - final String MONITOR_NAME = "sun.gc.generation.0.name"; - final String GENERATION_NAME = "Youth"; - MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, GENERATION_NAME); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - String returned = extractor.getGenerationName(0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(GENERATION_NAME, returned); - } - - @Test - public void testGenerationCapacity() throws MonitorException { - final String MONITOR_NAME = "sun.gc.generation.0.capacity"; - final Long GENERATION_CAPACITY = 99l; - MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, GENERATION_CAPACITY); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getGenerationCapacity(0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(GENERATION_CAPACITY, returned); - } - - @Test - public void testGenerationMaxCapacity() throws MonitorException { - final String MONITOR_NAME = "sun.gc.generation.0.maxCapacity"; - final Long GENERATION_MAX_CAPACITY = 99l; - MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, GENERATION_MAX_CAPACITY); - - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getGenerationMaxCapacity(0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(GENERATION_MAX_CAPACITY, returned); - } - - @Test - public void testGenerationCollector() throws MonitorException { - final String MONITOR_NAME = "sun.gc.collector.0.name"; - final String GENERATION_COLLECTOR = "generation collector"; - MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, GENERATION_COLLECTOR); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - String returned = extractor.getGenerationCollector(0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(GENERATION_COLLECTOR, returned); - } - - @Test - public void testTotalSpaces() throws MonitorException { - final Long TOTAL_SPACES = 99l; - final LongMonitor monitor = mock(LongMonitor.class); - when(monitor.getValue()).thenReturn(TOTAL_SPACES); - MonitoredVm vm = mock(MonitoredVm.class); - when(vm.findByName("sun.gc.generation.0.spaces")).thenReturn(monitor); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getTotalSpaces(0); - - verify(vm).findByName(eq("sun.gc.generation.0.spaces")); - assertEquals(TOTAL_SPACES, returned); - } - - - @Test - public void testSpaceName() throws MonitorException { - final String MONITOR_NAME = "sun.gc.generation.0.space.0.name"; - final String SPACE_NAME = "Hilbert"; - MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, SPACE_NAME); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - String returned = extractor.getSpaceName(0,0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(SPACE_NAME, returned); - } - - @Test - public void testSpaceCapacity() throws MonitorException { - final String MONITOR_NAME = "sun.gc.generation.0.space.0.capacity"; - final Long SPACE_CAPACITY = 99l; - MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, SPACE_CAPACITY); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getSpaceCapacity(0,0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(SPACE_CAPACITY, returned); - } - - @Test - public void testSpaceMaxCapacity() throws MonitorException { - final String MONITOR_NAME = "sun.gc.generation.0.space.0.maxCapacity"; - final Long SPACE_MAX_CAPACITY = 99l; - MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, SPACE_MAX_CAPACITY); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getSpaceMaxCapacity(0,0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(SPACE_MAX_CAPACITY, returned); - } - - @Test - public void testSpaceUsed() throws MonitorException { - final String MONITOR_NAME = "sun.gc.generation.0.space.0.used"; - final Long SPACE_USED = 99l; - MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, SPACE_USED); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getSpaceUsed(0,0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(SPACE_USED, returned); - } - - @Test - public void testLoadedClasses() throws MonitorException { - final String MONITOR_NAME = "java.cls.loadedClasses"; - final Long LOADED_CLASSES = 99l; - MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, LOADED_CLASSES); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getLoadedClasses(); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(LOADED_CLASSES, returned); - } - -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/JvmStatHostListenerTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.HashSet; -import java.util.Set; - -import org.junit.Test; -import org.mockito.Matchers; - -import sun.jvmstat.monitor.HostIdentifier; -import sun.jvmstat.monitor.MonitoredHost; -import sun.jvmstat.monitor.MonitoredVm; -import sun.jvmstat.monitor.StringMonitor; -import sun.jvmstat.monitor.VmIdentifier; -import sun.jvmstat.monitor.event.VmStatusChangeEvent; - -import com.redhat.thermostat.common.dao.VmClassStatDAO; -import com.redhat.thermostat.common.dao.VmInfoDAO; - -public class JvmStatHostListenerTest { - - @Test - public void testVmStatusChangedAddsVmClassListener() throws Exception { - VmStatusChangeEvent vmEvent = mock(VmStatusChangeEvent.class); - Set<Integer> startedVms = new HashSet<Integer>(); - startedVms.add(123); - when(vmEvent.getStarted()).thenReturn(startedVms); - - MonitoredVm vm = mock(MonitoredVm.class); - StringMonitor monitor = mock(StringMonitor.class); - when(monitor.stringValue()).thenReturn("test"); - when(monitor.getValue()).thenReturn("test"); - when(vm.findByName(anyString())).thenReturn(monitor); - MonitoredHost host = mock(MonitoredHost.class); - HostIdentifier hostId = mock(HostIdentifier.class); - when(host.getHostIdentifier()).thenReturn(hostId); - when(host.getMonitoredVm(any(VmIdentifier.class))).thenReturn(vm); - when(vmEvent.getMonitoredHost()).thenReturn(host); - - VmClassStatDAO vmClassDAO = mock(VmClassStatDAO.class); - VmInfoDAO vmInfoDAO = mock(VmInfoDAO.class); - - JvmStatHostListener l = new JvmStatHostListener(vmInfoDAO, null, null, vmClassDAO ,true); - SystemBackend backend = mock(SystemBackend.class); - when(backend.getObserveNewJvm()).thenReturn(true); - - l.vmStatusChanged(vmEvent); - - verify(vm).addVmListener(Matchers.isA(JvmStatVmClassListener.class)); - } - -} \ No newline at end of file
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/JvmStatVmClassListenerTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -import sun.jvmstat.monitor.Monitor; -import sun.jvmstat.monitor.MonitoredVm; -import sun.jvmstat.monitor.event.VmEvent; - -import com.redhat.thermostat.common.dao.VmClassStatDAO; -import com.redhat.thermostat.common.model.VmClassStat; - -public class JvmStatVmClassListenerTest { - - private static final Integer VM_ID = 123; - private static final Long LOADED_CLASSES = 1234L; - - @Test - public void testMonitorUpdatedClassStat() throws Exception { - - VmClassStatDAO dao = mock(VmClassStatDAO.class); - - JvmStatVmClassListener l = new JvmStatVmClassListener(dao, VM_ID); - VmEvent vmEvent = mock(VmEvent.class); - MonitoredVm monitoredVm = mock(MonitoredVm.class); - Monitor m = mock(Monitor.class); - when(m.getValue()).thenReturn(LOADED_CLASSES); - when(monitoredVm.findByName("java.cls.loadedClasses")).thenReturn(m); - when(vmEvent.getMonitoredVm()).thenReturn(monitoredVm); - - l.monitorsUpdated(vmEvent); - - ArgumentCaptor<VmClassStat> arg = ArgumentCaptor.forClass(VmClassStat.class); - verify(dao).putVmClassStat(arg.capture()); - VmClassStat stat = arg.getValue(); - assertEquals(LOADED_CLASSES, (Long) stat.getLoadedClasses()); - assertEquals(VM_ID, (Integer) stat.getVmId()); - } - - @Test - public void testMonitorUpdatedClassStatTwice() throws Exception { - - VmClassStatDAO dao = mock(VmClassStatDAO.class); - - JvmStatVmClassListener l = new JvmStatVmClassListener(dao, VM_ID); - VmEvent vmEvent = mock(VmEvent.class); - MonitoredVm monitoredVm = mock(MonitoredVm.class); - Monitor m = mock(Monitor.class); - when(m.getValue()).thenReturn(LOADED_CLASSES); - when(monitoredVm.findByName("java.cls.loadedClasses")).thenReturn(m); - when(vmEvent.getMonitoredVm()).thenReturn(monitoredVm); - - l.monitorsUpdated(vmEvent); - l.monitorsUpdated(vmEvent); - - // This checks a bug where the Category threw an IllegalStateException because the DAO - // created a new one on each call, thus violating the unique guarantee of Category. - } -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/LsbReleaseTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertEquals; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; - -import org.junit.Test; - -public class LsbReleaseTest { - - @Test - public void testName() throws IOException, InterruptedException { - BufferedReader reader = new BufferedReader(new StringReader("Distributor ID: Name")); - DistributionInformation info = new LsbRelease().getFromLsbRelease(reader); - assertEquals("Name", info.getName()); - } - - @Test - public void testVersion() throws IOException { - BufferedReader reader = new BufferedReader(new StringReader("Release: Version")); - DistributionInformation info = new LsbRelease().getFromLsbRelease(reader); - assertEquals("Version", info.getVersion()); - } - -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/MemoryStatBuilderTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.IOException; -import java.io.StringReader; - -import org.junit.Test; - -import com.redhat.thermostat.common.Constants; -import com.redhat.thermostat.common.model.MemoryStat; - -public class MemoryStatBuilderTest { - - @Test - public void testSimpleBuild() { - MemoryStat stat = new MemoryStatBuilder(new ProcDataSource()).build(); - assertNotNull(stat); - } - - @Test - public void testEmptyBuild() throws IOException { - String memory = ""; - StringReader memoryReader = new StringReader(memory); - ProcDataSource dataSource = mock(ProcDataSource.class); - when(dataSource.getMemInfoReader()).thenReturn(memoryReader); - - MemoryStat stat = new MemoryStatBuilder(dataSource).build(); - assertNotNull(stat); - verify(dataSource).getMemInfoReader(); - } - - @Test - public void testBuild() throws IOException { - int i = 1; - final long TOTAL = i++; - final long FREE = i++; - final long BUFFERS = i++; - final long CACHED = i++; - final long COMMIT_LIMIT = i++; - final long SWAP_TOTAL = i++; - final long SWAP_FREE = i++; - - String memory = "" + - "MemTotal: " + TOTAL + " kB\n" + - "MemFree: " + FREE + " kB\n" + - "Buffers:" + BUFFERS + " kB\n" + - "Cached: " + CACHED + " kB\n" + - "CommitLimit: " + COMMIT_LIMIT + " kB\n" + - "SwapTotal: " + SWAP_TOTAL + " kB\n" + - "SwapFree: " + SWAP_FREE + " kB\n"; - - StringReader memoryReader = new StringReader(memory); - ProcDataSource dataSource = mock(ProcDataSource.class); - when(dataSource.getMemInfoReader()).thenReturn(memoryReader); - - MemoryStat stat = new MemoryStatBuilder(dataSource).build(); - - assertEquals(BUFFERS * Constants.KILOBYTES_TO_BYTES, stat.getBuffers()); - assertEquals(CACHED * Constants.KILOBYTES_TO_BYTES, stat.getCached()); - assertEquals(COMMIT_LIMIT * Constants.KILOBYTES_TO_BYTES, stat.getCommitLimit()); - assertEquals(FREE * Constants.KILOBYTES_TO_BYTES, stat.getFree()); - assertEquals(SWAP_FREE * Constants.KILOBYTES_TO_BYTES, stat.getSwapFree()); - assertEquals(SWAP_TOTAL * Constants.KILOBYTES_TO_BYTES, stat.getSwapTotal()); - assertEquals(TOTAL * Constants.KILOBYTES_TO_BYTES, stat.getTotal()); - assertTrue(stat.getTimeStamp() != 0 && stat.getTimeStamp() != Long.MIN_VALUE); - assertTrue(stat.getTimeStamp() <= System.currentTimeMillis()); - verify(dataSource).getMemInfoReader(); - } -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/NetworkInfoBuilderTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.List; - -import org.junit.Test; - -import com.redhat.thermostat.common.model.NetworkInterfaceInfo; - -public class NetworkInfoBuilderTest { - - @Test - public void testBuilder() { - - List<NetworkInterfaceInfo> info = NetworkInfoBuilder.build(); - assertNotNull(info); - for (NetworkInterfaceInfo iface: info) { - assertNotNull(iface); - assertNotNull(iface.getInterfaceName()); - if (iface.getIp4Addr() != null) { - // ipv4 address matches the form XX.XX.XX.XX - assertTrue(iface.getIp4Addr().matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}")); - } - // TODO check for sane ipv6 address - } - - } - -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/ProcDataSourceTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertNotNull; - -import java.io.IOException; -import java.io.Reader; - -import org.junit.Test; - -import com.redhat.thermostat.agent.TestUtils; - -public class ProcDataSourceTest { - - @Test - public void testGetCpuInfoReader() throws IOException { - Reader r = new ProcDataSource().getCpuInfoReader(); - assertNotNull(r); - } - - @Test - public void testGetCpuLoadReader() throws IOException { - Reader r = new ProcDataSource().getCpuLoadReader(); - assertNotNull(r); - } - - @Test - public void testGetMemInfoReader() throws IOException { - Reader r = new ProcDataSource().getMemInfoReader(); - assertNotNull(r); - } - - @Test - public void testGetStatReader() throws IOException { - int pid = TestUtils.getProcessId(); - Reader r = new ProcDataSource().getStatReader(pid); - assertNotNull(r); - } - - - @Test - public void testGetEnvironReader() throws IOException { - int pid = TestUtils.getProcessId(); - Reader r = new ProcDataSource().getEnvironReader(pid); - assertNotNull(r); - } - -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilderTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.Map; -import java.util.Random; - -import org.junit.Test; - -import com.redhat.thermostat.agent.TestUtils; - -public class ProcessEnvironmentBuilderTest { - - private final Random r = new Random(); - - @Test - public void testBasicBuild() { - ProcDataSource dataSource = new ProcDataSource(); - Map<String, String> result = new ProcessEnvironmentBuilder(dataSource).build(TestUtils.getProcessId()); - assertNotNull(result); - assertFalse(result.isEmpty()); - assertTrue(result.containsKey("USER")); - } - - @Test - public void testCustomEnvironment() throws IOException { - byte[] data = ("USER=test\000HOME=house\000").getBytes(); - - Reader r = new InputStreamReader(new ByteArrayInputStream(data)); - ProcDataSource dataSource = mock(ProcDataSource.class); - when(dataSource.getEnvironReader(any(Integer.class))).thenReturn(r); - - Map<String, String> result = new ProcessEnvironmentBuilder(dataSource).build(0); - - verify(dataSource).getEnvironReader(eq(0)); - assertEquals("test", result.get("USER")); - assertEquals("house", result.get("HOME")); - } - - @Test - public void testLargeRandomEnvironment() throws IOException { - int TEST_ENV_SIZE = 1024 * 1024; - byte[] data = new byte[TEST_ENV_SIZE]; - int currentPosition = 0; - do { - byte[] key = generateRandomBytes(); - byte[] value = generateRandomBytes(); - if (currentPosition + key.length + value.length + 2 >= data.length) { - break; - } - System.arraycopy(key, 0, data, currentPosition, key.length); - currentPosition += key.length; - data[currentPosition] = (byte) '='; - currentPosition++; - System.arraycopy(value, 0, data, currentPosition, value.length); - currentPosition += value.length; - data[currentPosition] = 0x00; - currentPosition++; - } while (true); - Reader r = new InputStreamReader(new ByteArrayInputStream(data, 0, currentPosition)); - ProcDataSource dataSource = mock(ProcDataSource.class); - when(dataSource.getEnvironReader(any(Integer.class))).thenReturn(r); - - Map<String, String> result = new ProcessEnvironmentBuilder(dataSource).build(0); - - verify(dataSource).getEnvironReader(eq(0)); - assertNotNull(result); - } - - private byte[] generateRandomBytes() { - byte start = (byte) 'a'; - byte end = (byte) 'z' + 1; - - byte[] alphabet = new byte[end - start]; - for (int i = 0; i < (end-start); i++) { - alphabet[i] = (byte) (i + start); - } - int size = r.nextInt(15) + 10; - byte[] result = new byte[size]; - for (int i = 0; i < result.length; i++) { - result[i] = alphabet[r.nextInt(alphabet.length)]; - } - return result; - } -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilderTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.IOException; -import java.io.StringReader; - -import org.junit.Test; - -public class ProcessStatusInfoBuilderTest { - - @Test - public void testSimpleProcessStatus() { - ProcDataSource dataSource = new ProcDataSource(); - ProcessStatusInfo stat = new ProcessStatusInfoBuilder(dataSource).build(1); - assertNotNull(stat); - } - - @Test - public void testKnownProcessStatus() throws IOException { - final int PID = 10363; - String PROCESS_NAME = "(bash)"; - String STATE = "S"; - String PPID = "1737"; - String PROCESS_GROUP_ID = "10363"; - String SESSION_ID = "10363"; - String TTY_NUMBER = "34817"; - String TTY_PROCESS_GROUP_ID = "11404"; - String FLAGS_WORD = "4202496"; - String MINOR_FAULTS = "8093"; - String MINOR_FAULTS_CHILDREN = "607263"; - String MAJOR_FAULTS = "1"; - String MAJOR_FAULTS_CHILDREN = "251"; - final long USER_TIME_TICKS = 21; - final long KERNEL_TIME_TICKS = 7; - final long USER_TIME_CHILDREN = 10; - String KERNEL_TIME_CHILDREN = "1000"; - String PRIORITY = "20"; - String statString = "" + - PID + " " + PROCESS_NAME + " " + STATE + " " + PPID + " " - + PROCESS_GROUP_ID + " " + SESSION_ID + " " + TTY_NUMBER + " " - + TTY_PROCESS_GROUP_ID + " " + FLAGS_WORD + " " + MINOR_FAULTS + " " - + MINOR_FAULTS_CHILDREN + " " + MAJOR_FAULTS + " " + MAJOR_FAULTS_CHILDREN + " " + - USER_TIME_TICKS + " " + KERNEL_TIME_TICKS + " " + USER_TIME_CHILDREN + " " + - KERNEL_TIME_CHILDREN + " " + PRIORITY; - - ProcDataSource dataSource = mock(ProcDataSource.class); - when(dataSource.getStatReader(any(Integer.class))).thenReturn(new StringReader(statString)); - ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(dataSource); - ProcessStatusInfo stat = builder.build(PID); - - verify(dataSource).getStatReader(PID); - assertNotNull(stat); - assertEquals(PID, stat.getPid()); - assertEquals(USER_TIME_TICKS, stat.getUserTime()); - assertEquals(KERNEL_TIME_TICKS, stat.getKernelTime()); - } - - @Test - public void testBadProcessName() throws IOException { - final int PID = 10363; - String PROCESS_NAME = "(secretly-bad process sleep 10 20 ) 6)"; - String STATE = "S"; - String PPID = "1737"; - String PROCESS_GROUP_ID = "10363"; - String SESSION_ID = "10363"; - String TTY_NUMBER = "34817"; - String TTY_PROCESS_GROUP_ID = "11404"; - String FLAGS_WORD = "4202496"; - String MINOR_FAULTS = "8093"; - String MINOR_FAULTS_CHILDREN = "607263"; - String MAJOR_FAULTS = "1"; - String MAJOR_FAULTS_CHILDREN = "251"; - final long USER_TIME_TICKS = 21; - final long KERNEL_TIME_TICKS = 7; - final long USER_TIME_CHILDREN = 10; - String KERNEL_TIME_CHILDREN = "1000"; - String PRIORITY = "20"; - String statString = "" + - PID + " " + PROCESS_NAME + " " + STATE + " " + PPID + " " - + PROCESS_GROUP_ID + " " + SESSION_ID + " " + TTY_NUMBER + " " - + TTY_PROCESS_GROUP_ID + " " + FLAGS_WORD + " " + MINOR_FAULTS + " " - + MINOR_FAULTS_CHILDREN + " " + MAJOR_FAULTS + " " + MAJOR_FAULTS_CHILDREN + " " + - USER_TIME_TICKS + " " + KERNEL_TIME_TICKS + " " + USER_TIME_CHILDREN + " " + - KERNEL_TIME_CHILDREN + " " + PRIORITY; - - ProcDataSource dataSource = mock(ProcDataSource.class); - when(dataSource.getStatReader(any(Integer.class))).thenReturn(new StringReader(statString)); - ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(dataSource); - ProcessStatusInfo stat = builder.build(PID); - - verify(dataSource).getStatReader(PID); - assertNotNull(stat); - assertEquals(PID, stat.getPid()); - assertEquals(USER_TIME_TICKS, stat.getUserTime()); - assertEquals(KERNEL_TIME_TICKS, stat.getKernelTime()); - } - -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/SysConfTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -public class SysConfTest { - - @Test - public void test() { - long ticksPerSecond = SysConf.getClockTicksPerSecond(); - assertTrue(ticksPerSecond >= 1); - } -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import org.junit.Before; -import org.junit.Test; - -import com.redhat.thermostat.common.dao.CpuStatDAO; -import com.redhat.thermostat.common.dao.DAOFactory; -import com.redhat.thermostat.common.dao.HostInfoDAO; -import com.redhat.thermostat.common.dao.MemoryStatDAO; -import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO; -import com.redhat.thermostat.common.dao.VmCpuStatDAO; -import com.redhat.thermostat.common.storage.Storage; - -public class SystemBackendTest { - - private SystemBackend b; - - @Before - public void setUp() { - Storage s = mock(Storage.class); - CpuStatDAO cDAO = mock(CpuStatDAO.class); - HostInfoDAO hDAO = mock(HostInfoDAO.class); - MemoryStatDAO mDAO = mock(MemoryStatDAO.class); - VmCpuStatDAO vDAO = mock(VmCpuStatDAO.class); - NetworkInterfaceInfoDAO nDAO = mock(NetworkInterfaceInfoDAO.class); - DAOFactory df = mock(DAOFactory.class); - when(df.getStorage()).thenReturn(s); - when(df.getCpuStatDAO()).thenReturn(cDAO); - when(df.getHostInfoDAO()).thenReturn(hDAO); - when(df.getMemoryStatDAO()).thenReturn(mDAO); - when(df.getVmCpuStatDAO()).thenReturn(vDAO); - when(df.getNetworkInterfaceInfoDAO()).thenReturn(nDAO); - b = new SystemBackend(); - b.setDAOFactory(df); - } - - @Test - public void testBasicBackend() { - assertFalse(b.isActive()); - b.activate(); - assertTrue(b.isActive()); - b.deactivate(); - assertFalse(b.isActive()); - } - - @Test - public void testActivateTwice() { - b.activate(); - b.activate(); - assert(b.isActive()); - } - - @Test - public void testDeactiateWhenNotActive() { - b.deactivate(); - b.deactivate(); - assertFalse(b.isActive()); - } - -}
--- a/agent/core/src/test/java/com/redhat/thermostat/backend/system/VmCpuStatBuilderTest.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,168 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import org.junit.Test; - -import com.redhat.thermostat.common.Clock; -import com.redhat.thermostat.common.model.VmCpuStat; -import com.redhat.thermostat.test.Bug; - -public class VmCpuStatBuilderTest { - - @Test - public void testBuilderKnowsNothing() { - Clock clock = mock(Clock.class); - ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class); - int cpuCount = 0; - long ticksPerSecond = 0; - VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, statusBuilder); - - assertFalse(builder.knowsAbout(0)); - assertFalse(builder.knowsAbout(1)); - assertFalse(builder.knowsAbout(Integer.MIN_VALUE)); - assertFalse(builder.knowsAbout(Integer.MAX_VALUE)); - - } - - @Test(expected = IllegalArgumentException.class) - public void testBuilderThrowsOnBuildOfUnknownPid() { - Clock clock = mock(Clock.class); - int cpuCount = 0; - long ticksPerSecond = 0; - ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class); - VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, statusBuilder); - builder.build(0); - } - - @Test - public void testBuildNullOnInsufficentInformation() { - int PID = 0; - int cpuCount = 0; - long ticksPerSecond = 0; - final long CLOCK1 = 10000; - final long CLOCK2 = 20000; - final ProcessStatusInfo initialInfo = new ProcessStatusInfo(PID, 1, 2); - final ProcessStatusInfo laterInfo = null; - - Clock clock = mock(Clock.class); - when(clock.getMonotonicTimeNanos()).thenReturn((long) (CLOCK1 * 1E6)).thenReturn((long) (CLOCK2 * 1E6)); - - ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class); - when(statusBuilder.build(any(Integer.class))).thenReturn(initialInfo).thenReturn(laterInfo).thenReturn(null); - - VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, statusBuilder); - - builder.learnAbout(PID); - assertEquals(null, builder.build(PID)); - } - - @Test - public void testSaneBuild() { - final int PID = 0; - - final int CPU_COUNT = 3; - - final long USER_INITIAL_TICKS = 1; - final long KERNEL_INITIAL_TICKS = 1; - - final long USER_LATER_TICKS = 10; - final long KERNEL_LATER_TICKS = 10; - - final long CLOCK1 = 10000; - final long CLOCK2 = 20000; - - final long TICKS_PER_SECOND = 100; - - final double CPU_LOAD_PERCENT = - 100.0 - * ((USER_LATER_TICKS + KERNEL_LATER_TICKS) - (USER_INITIAL_TICKS + KERNEL_INITIAL_TICKS)) - / TICKS_PER_SECOND - / ((CLOCK2 - CLOCK1) * 1E-3 /* millis to seconds */) - / CPU_COUNT; - - final ProcessStatusInfo initialInfo = new ProcessStatusInfo(PID, USER_INITIAL_TICKS, KERNEL_INITIAL_TICKS); - final ProcessStatusInfo laterInfo = new ProcessStatusInfo(PID, USER_LATER_TICKS, KERNEL_LATER_TICKS); - - Clock clock = mock(Clock.class); - when(clock.getRealTimeMillis()).thenReturn(CLOCK2); - when(clock.getMonotonicTimeNanos()).thenReturn((long) (CLOCK1 * 1E6)).thenReturn((long) (CLOCK2 * 1E6)); - - ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class); - when(statusBuilder.build(any(Integer.class))).thenReturn(initialInfo).thenReturn(laterInfo).thenReturn(null); - - VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, CPU_COUNT, TICKS_PER_SECOND, statusBuilder); - - builder.learnAbout(PID); - VmCpuStat stat = builder.build(PID); - - assertNotNull(stat); - assertEquals(PID, stat.getVmId()); - assertEquals(CLOCK2, stat.getTimeStamp()); - assertEquals(CPU_LOAD_PERCENT, stat.getCpuLoad(), 0.0001); - } - - @Bug(id="1051", - summary="Avoid exceptions when reading /proc/ for dead processes", - url="http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1051") - @Test - public void testNoExceptionForBuilderLearningAboutDeadProcess() { - Clock clock = mock(Clock.class); - when(clock.getMonotonicTimeNanos()).thenReturn((long) (10000 * 1E6)); - ProcessStatusInfoBuilder procBuilder = mock(ProcessStatusInfoBuilder.class); - // This thing returns null if the /proc entry goes away. Rather than try to - // 'guess' at a pid that will not be present during test, just mock this. - when(procBuilder.build(any(Integer.class))).thenReturn(null); - VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, 3, 100, procBuilder); - // If we can't handle a process' /proc entry disappearing, the next line - // will throw exception. If it does not, then we are okay. - try { - builder.learnAbout(0); - } catch (Exception e) { - // Shouldn't happen. - assertTrue(false); - } - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/test/java/com/redhat/thermostat/utils/ProcDataSourceTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,84 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.utils; + +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.io.Reader; + +import org.junit.Test; + +import com.redhat.thermostat.common.TestUtils; +import com.redhat.thermostat.utils.ProcDataSource; + +public class ProcDataSourceTest { + + @Test + public void testGetCpuInfoReader() throws IOException { + Reader r = new ProcDataSource().getCpuInfoReader(); + assertNotNull(r); + } + + @Test + public void testGetCpuLoadReader() throws IOException { + Reader r = new ProcDataSource().getCpuLoadReader(); + assertNotNull(r); + } + + @Test + public void testGetMemInfoReader() throws IOException { + Reader r = new ProcDataSource().getMemInfoReader(); + assertNotNull(r); + } + + @Test + public void testGetStatReader() throws IOException { + int pid = TestUtils.getProcessId(); + Reader r = new ProcDataSource().getStatReader(pid); + assertNotNull(r); + } + + + @Test + public void testGetEnvironReader() throws IOException { + int pid = TestUtils.getProcessId(); + Reader r = new ProcDataSource().getEnvironReader(pid); + assertNotNull(r); + } + +}
--- a/client/core/src/main/java/com/redhat/thermostat/client/internal/HostFilterRegistry.java Fri Oct 19 15:33:45 2012 -0400 +++ b/client/core/src/main/java/com/redhat/thermostat/client/internal/HostFilterRegistry.java Fri Oct 19 21:58:18 2012 +0200 @@ -41,6 +41,7 @@ import org.osgi.framework.InvalidSyntaxException; import com.redhat.thermostat.client.core.HostFilter; +import com.redhat.thermostat.common.ThermostatExtensionRegistry; class HostFilterRegistry extends ThermostatExtensionRegistry<HostFilter> {
--- a/client/core/src/main/java/com/redhat/thermostat/client/internal/HostTreeDecoratorRegistry.java Fri Oct 19 15:33:45 2012 -0400 +++ b/client/core/src/main/java/com/redhat/thermostat/client/internal/HostTreeDecoratorRegistry.java Fri Oct 19 21:58:18 2012 +0200 @@ -41,6 +41,7 @@ import org.osgi.framework.InvalidSyntaxException; import com.redhat.thermostat.client.osgi.service.HostDecorator; +import com.redhat.thermostat.common.ThermostatExtensionRegistry; class HostTreeDecoratorRegistry extends ThermostatExtensionRegistry<HostDecorator> {
--- a/client/core/src/main/java/com/redhat/thermostat/client/internal/MainWindowControllerImpl.java Fri Oct 19 15:33:45 2012 -0400 +++ b/client/core/src/main/java/com/redhat/thermostat/client/internal/MainWindowControllerImpl.java Fri Oct 19 21:58:18 2012 +0200 @@ -74,6 +74,7 @@ import com.redhat.thermostat.common.ApplicationInfo; import com.redhat.thermostat.common.DefaultHostsVMsLoader; import com.redhat.thermostat.common.HostsVMsLoader; +import com.redhat.thermostat.common.ThermostatExtensionRegistry; import com.redhat.thermostat.common.Timer; import com.redhat.thermostat.common.Timer.SchedulingType; import com.redhat.thermostat.common.appctx.ApplicationContext; @@ -457,7 +458,7 @@ @SuppressWarnings("unchecked") @Override - public void actionPerformed(ActionEvent<com.redhat.thermostat.client.internal.ThermostatExtensionRegistry.Action> actionEvent) { + public void actionPerformed(ActionEvent<com.redhat.thermostat.common.ThermostatExtensionRegistry.Action> actionEvent) { Object payload = actionEvent.getPayload(); if (!extensionClass.isInstance(payload)) {
--- a/client/core/src/main/java/com/redhat/thermostat/client/internal/MenuRegistry.java Fri Oct 19 15:33:45 2012 -0400 +++ b/client/core/src/main/java/com/redhat/thermostat/client/internal/MenuRegistry.java Fri Oct 19 21:58:18 2012 +0200 @@ -40,6 +40,7 @@ import org.osgi.framework.InvalidSyntaxException; import com.redhat.thermostat.client.osgi.service.MenuAction; +import com.redhat.thermostat.common.ThermostatExtensionRegistry; public class MenuRegistry extends ThermostatExtensionRegistry<MenuAction> {
--- a/client/core/src/main/java/com/redhat/thermostat/client/internal/ThermostatExtensionRegistry.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.client.internal; - -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; -import org.osgi.util.tracker.ServiceTracker; - -import com.redhat.thermostat.common.ActionListener; -import com.redhat.thermostat.common.ActionNotifier; - -/** - * A helper class to make it easier to implement registeries for osgi-services. - */ -public class ThermostatExtensionRegistry<E> { - - public enum Action { - SERVICE_ADDED, - SERVICE_REMOVED - } - - private ActionNotifier<Action> actionNotifier = new ActionNotifier<>(this); - - private ServiceTracker tracker; - - public ThermostatExtensionRegistry(BundleContext context, String filter, final Class<E> classType) throws InvalidSyntaxException { - - tracker = new ServiceTracker(context, FrameworkUtil.createFilter(filter), null) { - - @Override - public Object addingService(ServiceReference reference) { - @SuppressWarnings("unchecked") - E service = (E) super.addingService(reference); - - actionNotifier.fireAction(Action.SERVICE_ADDED, service); - return service; - } - - @Override - public void removedService(ServiceReference reference, Object service) { - if (!classType.isAssignableFrom(service.getClass())) { - throw new AssertionError("removing a non-Filter service"); - } - - actionNotifier.fireAction(Action.SERVICE_REMOVED, service); - super.removedService(reference, service); - } - }; - } - - public void start() { - tracker.open(); - } - - public void stop() { - tracker.close(); - } - - public void addActionListener(ActionListener<Action> l) { - actionNotifier.addActionListener(l); - } - - public void removeActionListener(ActionListener<Action> l) { - actionNotifier.removeActionListener(l); - } -}
--- a/client/core/src/main/java/com/redhat/thermostat/client/internal/VMInformationRegistry.java Fri Oct 19 15:33:45 2012 -0400 +++ b/client/core/src/main/java/com/redhat/thermostat/client/internal/VMInformationRegistry.java Fri Oct 19 21:58:18 2012 +0200 @@ -41,6 +41,7 @@ import org.osgi.framework.InvalidSyntaxException; import com.redhat.thermostat.client.core.VmInformationService; +import com.redhat.thermostat.common.ThermostatExtensionRegistry; class VMInformationRegistry extends ThermostatExtensionRegistry<VmInformationService> {
--- a/client/core/src/main/java/com/redhat/thermostat/client/internal/VMTreeDecoratorRegistry.java Fri Oct 19 15:33:45 2012 -0400 +++ b/client/core/src/main/java/com/redhat/thermostat/client/internal/VMTreeDecoratorRegistry.java Fri Oct 19 21:58:18 2012 +0200 @@ -41,6 +41,7 @@ import org.osgi.framework.InvalidSyntaxException; import com.redhat.thermostat.client.osgi.service.VmDecorator; +import com.redhat.thermostat.common.ThermostatExtensionRegistry; class VMTreeDecoratorRegistry extends ThermostatExtensionRegistry<VmDecorator> {
--- a/client/core/src/main/java/com/redhat/thermostat/client/internal/VmFilterRegistry.java Fri Oct 19 15:33:45 2012 -0400 +++ b/client/core/src/main/java/com/redhat/thermostat/client/internal/VmFilterRegistry.java Fri Oct 19 21:58:18 2012 +0200 @@ -41,6 +41,7 @@ import org.osgi.framework.InvalidSyntaxException; import com.redhat.thermostat.client.core.VmFilter; +import com.redhat.thermostat.common.ThermostatExtensionRegistry; class VmFilterRegistry extends ThermostatExtensionRegistry<VmFilter> {
--- a/client/core/src/test/java/com/redhat/thermostat/client/internal/MainWindowControllerImplTest.java Fri Oct 19 15:33:45 2012 -0400 +++ b/client/core/src/test/java/com/redhat/thermostat/client/internal/MainWindowControllerImplTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -66,7 +66,6 @@ import com.redhat.thermostat.client.core.VmFilter; import com.redhat.thermostat.client.core.views.BasicView; -import com.redhat.thermostat.client.internal.ThermostatExtensionRegistry.Action; import com.redhat.thermostat.client.osgi.service.MenuAction; import com.redhat.thermostat.client.osgi.service.VMContextAction; import com.redhat.thermostat.client.osgi.service.VmDecorator; @@ -77,7 +76,9 @@ import com.redhat.thermostat.common.ActionEvent; import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.HostsVMsLoader; +import com.redhat.thermostat.common.ThermostatExtensionRegistry; import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.ThermostatExtensionRegistry.Action; import com.redhat.thermostat.common.Timer.SchedulingType; import com.redhat.thermostat.common.TimerFactory; import com.redhat.thermostat.common.appctx.ApplicationContext;
--- a/client/core/src/test/java/com/redhat/thermostat/client/internal/MenuRegistryTest.java Fri Oct 19 15:33:45 2012 -0400 +++ b/client/core/src/test/java/com/redhat/thermostat/client/internal/MenuRegistryTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -55,6 +55,7 @@ import com.redhat.thermostat.client.osgi.service.MenuAction; import com.redhat.thermostat.common.ActionEvent; import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.ThermostatExtensionRegistry; public class MenuRegistryTest {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/common/TestUtils.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,87 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.common; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.util.Properties; +import java.util.Random; + +public class TestUtils { + + public static int getProcessId() { + String name = ManagementFactory.getRuntimeMXBean().getName(); + String pidPart = name.split("@")[0]; + return Integer.parseInt(pidPart); + } + + public static boolean isLinux() { + return (System.getProperty("os.name").toLowerCase().contains("linux")); + } + + public static String setupAgentConfigs() throws IOException { + // need to create dummy config files for the tests + Random random = new Random(); + + String tmpDir = System.getProperty("java.io.tmpdir") + File.separatorChar + + Math.abs(random.nextInt()) + File.separatorChar; + + System.setProperty("THERMOSTAT_HOME", tmpDir); + File agent = new File(tmpDir, "agent"); + agent.mkdirs(); + + File tmpConfigs = new File(agent, "agent.properties"); + + new File(agent, "run").mkdirs(); + new File(agent, "logs").mkdirs(); + + File backends = new File(tmpDir, "backends"); + File system = new File(backends, "system"); + system.mkdirs(); + + Properties props = new Properties(); + + props.setProperty("SAVE_ON_EXIT", "true"); + props.setProperty("CONFIG_LISTEN_ADDRESS", "42.42.42.42:42"); + + props.store(new FileOutputStream(tmpConfigs), "thermostat agent test properties"); + + return tmpDir; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/common/ThermostatExtensionRegistry.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,100 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.common; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; + +/** + * A helper class to make it easier to implement registeries for osgi-services. + */ +public class ThermostatExtensionRegistry<E> { + + public enum Action { + SERVICE_ADDED, + SERVICE_REMOVED + } + + private ActionNotifier<Action> actionNotifier = new ActionNotifier<>(this); + + @SuppressWarnings("rawtypes") + private ServiceTracker tracker; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public ThermostatExtensionRegistry(BundleContext context, String filter, final Class<E> classType) throws InvalidSyntaxException { + + tracker = new ServiceTracker(context, FrameworkUtil.createFilter(filter), null) { + + @Override + public Object addingService(ServiceReference reference) { + E service = (E) super.addingService(reference); + + actionNotifier.fireAction(Action.SERVICE_ADDED, service); + return service; + } + + @Override + public void removedService(ServiceReference reference, Object service) { + if (!classType.isAssignableFrom(service.getClass())) { + throw new AssertionError("removing a non-Filter service"); + } + + actionNotifier.fireAction(Action.SERVICE_REMOVED, service); + super.removedService(reference, service); + } + }; + } + + public void start() { + tracker.open(); + } + + public void stop() { + tracker.close(); + } + + public void addActionListener(ActionListener<Action> l) { + actionNotifier.addActionListener(l); + } + + public void removeActionListener(ActionListener<Action> l) { + actionNotifier.removeActionListener(l); + } +}
--- a/common/core/src/main/java/com/redhat/thermostat/common/dao/Countable.java Fri Oct 19 15:33:45 2012 -0400 +++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/Countable.java Fri Oct 19 21:58:18 2012 +0200 @@ -36,7 +36,7 @@ package com.redhat.thermostat.common.dao; -interface Countable { +public interface Countable { public long getCount();
--- a/common/core/src/test/java/com/redhat/thermostat/common/TestUtils.java Fri Oct 19 15:33:45 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat 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 2, or (at your - * option) any later version. - * - * Thermostat 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 Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.common; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.util.Properties; -import java.util.Random; - -public class TestUtils { - - public static int getProcessId() { - String name = ManagementFactory.getRuntimeMXBean().getName(); - String pidPart = name.split("@")[0]; - return Integer.parseInt(pidPart); - } - - public static boolean isLinux() { - return (System.getProperty("os.name").toLowerCase().contains("linux")); - } - - public static String setupAgentConfigs() throws IOException { - // need to create dummy config files for the tests - Random random = new Random(); - - String tmpDir = System.getProperty("java.io.tmpdir") + File.separatorChar + - Math.abs(random.nextInt()) + File.separatorChar; - - System.setProperty("THERMOSTAT_HOME", tmpDir); - File agent = new File(tmpDir, "agent"); - agent.mkdirs(); - - File tmpConfigs = new File(agent, "agent.properties"); - - new File(agent, "run").mkdirs(); - new File(agent, "logs").mkdirs(); - - File backends = new File(tmpDir, "backends"); - File system = new File(backends, "system"); - system.mkdirs(); - - Properties props = new Properties(); - - props.setProperty("BACKENDS", "system"); - props.setProperty("LOG_LEVEL", "WARNING"); - - props.store(new FileOutputStream(tmpConfigs), "thermostat agent test properties"); - - // now write the configs for the backends - tmpConfigs = new File(system, "backend.properties"); - props = new Properties(); - props.setProperty("BACKEND_CLASS", - "com.redhat.thermostat.backend.system.SystemBackend"); - props.setProperty("DESCRIPTION", - "fluff backend for tests"); - props.setProperty("VENDOR", - "Red Hat, Inc."); - props.setProperty("VERSION", - "1.0"); - props.store(new FileOutputStream(tmpConfigs), "thermostat system backend properties"); - - return tmpDir; - } -}
--- a/distribution/config/commands/agent.properties Fri Oct 19 15:33:45 2012 -0400 +++ b/distribution/config/commands/agent.properties Fri Oct 19 21:58:18 2012 +0200 @@ -7,7 +7,8 @@ thermostat-agent-heapdumper-@project.version@.jar, \ thermostat-killvm-agent-@project.version@.jar, \ thermostat-thread-collector-@project.version@.jar, \ - thermostat-thread-harvester-@project.version@.jar + thermostat-thread-harvester-@project.version@.jar, \ + thermostat-system-backend-@project.version@.jar description = starts and stops the thermostat agent
--- a/distribution/pom.xml Fri Oct 19 15:33:45 2012 -0400 +++ b/distribution/pom.xml Fri Oct 19 21:58:18 2012 +0200 @@ -385,5 +385,11 @@ <version>${project.version}</version> </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-system-backend</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> </project>
--- a/pom.xml Fri Oct 19 15:33:45 2012 -0400 +++ b/pom.xml Fri Oct 19 21:58:18 2012 +0200 @@ -111,6 +111,7 @@ <module>thread</module> <module>killvm</module> <module>web</module> + <module>system-backend</module> </modules> <build>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/pom.xml Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright 2012 Red Hat, Inc. + + This file is part of Thermostat. + + Thermostat 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 2, or (at your + option) any later version. + + Thermostat 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 Thermostat; see the file COPYING. If not see + <http://www.gnu.org/licenses />. + + Linking this code with other modules is making a combined work + based on this code. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + As a special exception, the copyright holders of this code give + you permission to link this code with independent modules to + produce an executable, regardless of the license terms of these + independent modules, and to copy and distribute the resulting + executable under terms of your choice, provided that you also + meet, for each linked independent module, the terms and conditions + of the license of that module. An independent module is a module + which is not derived from or based on this code. If you modify + this code, you may extend this exception to your version of the + library, but you are not obligated to do so. If you do not wish + to do so, delete this exception statement from your version. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat</artifactId> + <version>0.5.0-SNAPSHOT</version> + </parent> + + <artifactId>thermostat-system-backend</artifactId> + <packaging>bundle</packaging> + + <name>Thermostat System Backend</name> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-common-core</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-agent-core</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <scope>provided</scope> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor> + <Bundle-Activator>com.redhat.thermostat.backend.system.osgi.SystemBackendActivator</Bundle-Activator> + <Bundle-SymbolicName>com.redhat.thermostat.backend.system</Bundle-SymbolicName> + <Private-Package> + com.redhat.thermostat.backend.system, + com.redhat.thermostat.backend.system.osgi, + </Private-Package> + <!-- Do not autogenerate uses clauses in Manifests --> + <_nouses>true</_nouses> + </instructions> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <!-- FIXME: the test need to link to agent-core native libraries --> + <argLine>-Djava.library.path=${project.build.directory}/../../agent/core/target/</argLine> + </configuration> + </plugin> + + </plugins> + </build> + +</project> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/CpuStatBuilder.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,137 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.Clock; +import com.redhat.thermostat.common.model.CpuStat; +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.utils.ProcDataSource; + +public class CpuStatBuilder { + + private static final Logger logger = LoggingUtils.getLogger(CpuStatBuilder.class); + + private final ProcDataSource dataSource; + private final Clock clock; + private final long ticksPerSecond; + + private boolean initialized = false; + + private long[] previousCpuTicks; + private long previousTime; + + public CpuStatBuilder(Clock clock, ProcDataSource dataSource, long ticksPerSecond) { + this.dataSource = dataSource; + this.clock = clock; + this.ticksPerSecond = ticksPerSecond; + } + + public void initialize() { + if (initialized) { + throw new IllegalStateException("already initialized"); + } + + previousTime = clock.getMonotonicTimeNanos(); + previousCpuTicks = getCurrentCpuTicks(); + initialized = true; + } + + public CpuStat build() { + if (!initialized) { + throw new IllegalStateException("not initialized yet"); + } + + long currentRealTime = clock.getRealTimeMillis(); + long currentTime = clock.getMonotonicTimeNanos(); + long[] currentValues = getCurrentCpuTicks(); + + List<Double> cpuUsage = new ArrayList<Double>(currentValues.length); + + double timeDelta = (currentTime - previousTime) * 1E-9; + for (int i = 0; i < currentValues.length; i++) { + long cpuTicksDelta = currentValues[i] - previousCpuTicks[i]; + // 100 as in 100 percent. + cpuUsage.add(cpuTicksDelta * (100.0 / timeDelta / ticksPerSecond)); + } + previousTime = currentTime; + previousCpuTicks = currentValues; + + return new CpuStat(currentRealTime, cpuUsage); + } + + private long[] getCurrentCpuTicks() { + int maxIndex = 0; + long[] values = new long[1]; + try (BufferedReader reader = new BufferedReader(dataSource.getStatReader())) { + String line; + while ((line = reader.readLine()) != null) { + if (!line.startsWith("cpu")) { + continue; + } + String[] parts = line.split("\\s"); + if (!parts[0].matches("cpu\\d+")) { + continue; + } + + int cpuIndex = Integer.valueOf(parts[0].substring("cpu".length())); + if (cpuIndex > maxIndex) { + long[] newValues = new long[cpuIndex+1]; + System.arraycopy(values, 0, newValues, 0, cpuIndex); + values = newValues; + maxIndex = cpuIndex; + } + values[cpuIndex] = Long.valueOf(parts[1]) + Long.valueOf(parts[2]) + Long.valueOf(parts[3]); + } + } catch (IOException e) { + logger.log(Level.WARNING, "error reading stat file", e); + } + + return values; + } + + public boolean isInitialized() { + return initialized; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/DistributionInformation.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,90 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class DistributionInformation { + + public static final String UNKNOWN_NAME = "Unknown Distribution"; + public static final String UNKNOWN_VERSION = "Unknown Version"; + + private static final Logger logger = LoggingUtils.getLogger(DistributionInformation.class); + + private final String name; + private final String version; + + public DistributionInformation(String name, String version) { + this.name = name; + this.version = version; + } + + public static DistributionInformation get() { + try { + return new EtcOsRelease().getDistributionInformation(); + } catch (IOException e) { + logger.log(Level.WARNING, "unable to use os-release", e); + } + try { + return new LsbRelease().getDistributionInformation(); + } catch (IOException e) { + logger.log(Level.WARNING, "unable to use lsb_release", e); + } + return new DistributionInformation(UNKNOWN_NAME, UNKNOWN_VERSION); + } + + /** + * @return the name of the distribution, or {@link #UNKNOWN_NAME} if it can not be + * identified + */ + public String getName() { + return name; + } + + /** + * @return the release of the distribution or {@link #UNKNOWN_VERSION} if it can not be + * identified + */ + public String getVersion() { + return version; + } + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/DistributionInformationSource.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.io.IOException; + +public interface DistributionInformationSource { + + public DistributionInformation getDistributionInformation() throws IOException; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/EtcOsRelease.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,109 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class EtcOsRelease implements DistributionInformationSource { + + private static final Logger logger = LoggingUtils.getLogger(EtcOsRelease.class); + + private static final String OS_RELEASE = "/etc/os-release"; + + @Override + public DistributionInformation getDistributionInformation() throws IOException { + return getFromOsRelease(); + } + + public DistributionInformation getFromOsRelease() throws IOException { + return getFromOsRelease(OS_RELEASE); + } + + public DistributionInformation getFromOsRelease(String releaseFile) throws IOException { + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader(releaseFile)); + return getFromOsRelease(reader); + } finally { + try { + if (reader != null) { + reader.close(); + } + } catch (IOException e) { + logger.log(Level.WARNING, "unable to close input stream", e); + } + } + } + + public DistributionInformation getFromOsRelease(BufferedReader reader) throws IOException { + String name = "Linux"; + String version = DistributionInformation.UNKNOWN_VERSION; + String line = null; + while ((line = reader.readLine()) != null) { + if (line.matches("^NAME *=.*")) { + name = readShellVariable(line); + } + if (line.matches("^VERSION *=.*")) { + version = readShellVariable(line); + } + } + return new DistributionInformation(name, version); + } + + /** Reads and parses a shell variable declaration: {@code FOO="bar"} + * + * @return the value of the shell variable + */ + private String readShellVariable(String line) { + // TODO we should try to handle shell quotes better + String result = line.substring(line.indexOf("=")+1); + result = result.trim(); + if (result.startsWith("\"") && result.endsWith("\"")) { + result = result.substring(1, result.length()-1); + result = result.trim(); + } + return result; + } + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/HostInfoBuilder.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,184 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.io.BufferedReader; +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.Constants; +import com.redhat.thermostat.common.model.HostInfo; +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.utils.ProcDataSource; +import com.redhat.thermostat.utils.hostname.HostName; + +public class HostInfoBuilder { + + private static final Logger logger = LoggingUtils.getLogger(HostInfoBuilder.class); + + static class HostCpuInfo { + public final String model; + public final int count; + + public HostCpuInfo(String model, int count) { + this.count = count; + this.model = model; + } + } + + static class HostOsInfo { + public final String kernel; + public final String distribution; + + public HostOsInfo(String kernel, String distribution) { + this.kernel = kernel; + this.distribution = distribution; + } + } + + static class HostMemoryInfo { + public final long totalMemory; + + public HostMemoryInfo(long totalMemory) { + this.totalMemory = totalMemory; + } + } + + private final ProcDataSource dataSource; + + public HostInfoBuilder(ProcDataSource dataSource) { + this.dataSource = dataSource; + } + + public HostInfo build() { + String hostname = getHostName(); + HostCpuInfo cpuInfo = getCpuInfo(); + HostMemoryInfo memoryInfo = getMemoryInfo(); + HostOsInfo osInfo = getOsInfo(); + + return new HostInfo(hostname, osInfo.distribution, osInfo.kernel, cpuInfo.model, cpuInfo.count, memoryInfo.totalMemory); + } + + HostCpuInfo getCpuInfo() { + final String KEY_PROCESSOR_ID = "processor"; + final String KEY_CPU_MODEL = "model name"; + int cpuCount = 0; + String cpuModel = null; + try (BufferedReader bufferedReader = new BufferedReader(dataSource.getCpuInfoReader())) { + String line = null; + while ((line = bufferedReader.readLine()) != null) { + if (line.startsWith(KEY_PROCESSOR_ID)) { + cpuCount++; + } else if (line.startsWith(KEY_CPU_MODEL)) { + cpuModel = line.substring(line.indexOf(":") + 1).trim(); + } + } + } catch (IOException ioe) { + logger.log(Level.WARNING, "unable to read cpu info"); + } + + logger.log(Level.FINEST, "cpuModel: " + cpuModel); + logger.log(Level.FINEST, "cpuCount: " + cpuCount); + + return new HostCpuInfo(cpuModel, cpuCount); + } + + HostMemoryInfo getMemoryInfo() { + long totalMemory = -1; + try (BufferedReader bufferedReader = new BufferedReader(dataSource.getMemInfoReader())) { + String[] memTotalParts = bufferedReader.readLine().split(" +"); + long data = Long.valueOf(memTotalParts[1]); + String units = memTotalParts[2]; + if (units.equals("kB")) { + totalMemory = data * Constants.KILOBYTES_TO_BYTES; + } + } catch (IOException ioe) { + logger.log(Level.WARNING, "unable to read memory info"); + } + + logger.log(Level.FINEST, "totalMemory: " + totalMemory + " bytes"); + return new HostMemoryInfo(totalMemory); + } + + HostOsInfo getOsInfo() { + return getOsInfo(DistributionInformation.get()); + } + + HostOsInfo getOsInfo(DistributionInformation distroInfo) { + String osName = distroInfo.getName() + " " + distroInfo.getVersion(); + logger.log(Level.FINEST, "osName: " + osName); + + String osKernel = System.getProperty("os.name") + " " + System.getProperty("os.version"); + logger.log(Level.FINEST, "osKernel: " + osKernel); + + return new HostOsInfo(osKernel, osName); + } + + String getHostName() { + String hostname = null; + + try { + InetAddress localAddress = null; + localAddress = InetAddress.getLocalHost(); + hostname = getHostName(localAddress); + } catch (UnknownHostException uhe) { + logger.log(Level.WARNING, "unable to get hostname", uhe); + } + + // if fails, try to get hostname without dns lookup + if (hostname == null) { + hostname = HostName.getLocalHostName(); + } + + // still null, use localhost + if (hostname == null) { + hostname = Constants.AGENT_LOCAL_HOSTNAME; + } + + return hostname; + } + + String getHostName(InetAddress localAddress) { + String hostname = localAddress.getCanonicalHostName(); + logger.log(Level.FINEST, "hostname: " + hostname); + return hostname; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatDataExtractor.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,170 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import com.redhat.thermostat.common.model.VmMemoryStat.Generation; + +import sun.jvmstat.monitor.Monitor; +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.MonitoredVmUtil; + +/** + * A helper class to provide type-safe access to commonly used jvmstat monitors + * <p> + * Implementation details: For local vms, jvmstat uses a ByteBuffer + * corresponding to mmap()ed hsperfdata file. The hsperfdata file is updated + * asynchronously by the vm that created the file. The polling that jvmstat api + * provides is merely an abstraction over this (possibly always up-to-date) + * ByteBuffer. So the data this class extracts is as current as possible, and + * does not correspond to when the jvmstat update events fired. + */ +public class JvmStatDataExtractor { + + /* + * Note, there may be a performance issue to consider here. We have a lot of + * string constants. When we start adding some of the more heavyweight + * features, and running into CPU issues this may need to be reconsidered in + * order to avoid the String pool overhead. See also: + * http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#intern() + */ + + private final MonitoredVm vm; + + public JvmStatDataExtractor(MonitoredVm vm) { + this.vm = vm; + } + + public String getCommandLine() throws MonitorException { + return MonitoredVmUtil.commandLine(vm); + } + + public String getMainClass() throws MonitorException { + return MonitoredVmUtil.mainClass(vm, true); + } + + public String getJavaVersion() throws MonitorException { + return (String) vm.findByName("java.property.java.version").getValue(); + } + + public String getJavaHome() throws MonitorException { + return (String) vm.findByName("java.property.java.home").getValue(); + } + + public String getVmName() throws MonitorException { + return (String) vm.findByName("java.property.java.vm.name").getValue(); + } + + public String getVmInfo() throws MonitorException { + return (String) vm.findByName("java.property.java.vm.info").getValue(); + } + + public String getVmVersion() throws MonitorException { + return (String) vm.findByName("java.property.java.vm.version").getValue(); + } + + public String getVmArguments() throws MonitorException { + return MonitoredVmUtil.jvmArgs(vm); + } + + public long getTotalCollectors() throws MonitorException { + return (Long) vm.findByName("sun.gc.policy.collectors").getValue(); + } + + public String getCollectorName(long collector) throws MonitorException { + return (String) vm.findByName("sun.gc.collector." + collector + ".name").getValue(); + } + + public long getCollectorTime(long collector) throws MonitorException { + return (Long) vm.findByName("sun.gc.collector." + collector + ".time").getValue(); + } + + public long getCollectorInvocations(long collector) throws MonitorException { + return (Long) vm.findByName("sun.gc.collector." + collector + ".invocations").getValue(); + } + + public long getTotalGcGenerations() throws MonitorException { + return (Long) vm.findByName("sun.gc.policy.generations").getValue(); + } + + public String getGenerationName(long generation) throws MonitorException { + return (String) vm.findByName("sun.gc.generation." + generation + ".name").getValue(); + } + + public long getGenerationCapacity(long generation) throws MonitorException { + return (Long) vm.findByName("sun.gc.generation." + generation + ".capacity").getValue(); + } + + public long getGenerationMaxCapacity(long generation) throws MonitorException { + return (Long) vm.findByName("sun.gc.generation." + generation + ".maxCapacity").getValue(); + } + + public String getGenerationCollector(long generation) throws MonitorException { + // this is just re-implementing getCollectorName() + // TODO check generation number and collector number are always associated + Monitor m = vm.findByName("sun.gc.collector." + generation + ".name"); + if (m == null) { + return Generation.COLLECTOR_NONE; + } + return (String) m.getValue(); + } + + public long getTotalSpaces(long generation) throws MonitorException { + return (Long) vm.findByName("sun.gc.generation." + generation + ".spaces").getValue(); + } + + public String getSpaceName(long generation, long space) throws MonitorException { + return (String) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".name").getValue(); + } + + public long getSpaceCapacity(long generation, long space) throws MonitorException { + return (Long) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".capacity").getValue(); + } + + public long getSpaceMaxCapacity(long generation, long space) throws MonitorException { + return (Long) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".maxCapacity").getValue(); + } + + public long getSpaceUsed(long generation, long space) throws MonitorException { + return (Long) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".used").getValue(); + } + + public long getLoadedClasses() throws MonitorException { + return (Long) vm.findByName("java.cls.loadedClasses").getValue(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,226 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.logging.Level; +import java.util.logging.Logger; + +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredHost; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.VmIdentifier; +import sun.jvmstat.monitor.event.HostEvent; +import sun.jvmstat.monitor.event.HostListener; +import sun.jvmstat.monitor.event.VmListener; +import sun.jvmstat.monitor.event.VmStatusChangeEvent; + +import com.redhat.thermostat.agent.JvmStatusListener; +import com.redhat.thermostat.agent.JvmStatusNotifier; +import com.redhat.thermostat.common.dao.VmClassStatDAO; +import com.redhat.thermostat.common.dao.VmGcStatDAO; +import com.redhat.thermostat.common.dao.VmInfoDAO; +import com.redhat.thermostat.common.dao.VmMemoryStatDAO; +import com.redhat.thermostat.common.model.VmInfo; +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.utils.ProcDataSource; + +public class JvmStatHostListener implements HostListener, JvmStatusNotifier { + + private static final Logger logger = LoggingUtils.getLogger(JvmStatHostListener.class); + + private boolean attachNew; + + private final VmInfoDAO vmInfoDAO; + private final VmMemoryStatDAO vmMemoryStatDAO; + private final VmClassStatDAO vmClassStatDAO; + private final VmGcStatDAO vmGcStatDAO; + + private Map<Integer, MonitoredVm> monitoredVms = new HashMap<>(); + private Map<MonitoredVm, List<VmListener>> registeredListeners = new ConcurrentHashMap<>(); + + private Set<JvmStatusListener> statusListeners = new CopyOnWriteArraySet<JvmStatusListener>(); + + JvmStatHostListener(VmInfoDAO vmInfoDAO, VmMemoryStatDAO vmMemoryStatDAO, VmGcStatDAO vmGcStatDAO, + VmClassStatDAO vmClassStatDAO, boolean attachNew) { + this.vmInfoDAO = vmInfoDAO; + this.vmMemoryStatDAO = vmMemoryStatDAO; + this.vmGcStatDAO = vmGcStatDAO; + this.vmClassStatDAO = vmClassStatDAO; + this.attachNew = attachNew; + } + + void removeAllListeners() { + for (MonitoredVm vm : monitoredVms.values()) { + for (VmListener listener : registeredListeners.get(vm)) { + try { + if (listener != null) vm.removeVmListener(listener); + + } catch (MonitorException e) { + logger.log(Level.WARNING, "can't remove vm listener", e); + } + } + } + } + + @Override + public void disconnected(HostEvent event) { + logger.warning("Disconnected from host"); + } + + @SuppressWarnings("unchecked") // Unchecked casts to (Set<Integer>). + @Override + public void vmStatusChanged(VmStatusChangeEvent event) { + MonitoredHost host = event.getMonitoredHost(); + + for (Integer newVm : (Set<Integer>) event.getStarted()) { + try { + logger.fine("New vm: " + newVm); + sendNewVM(newVm, host); + } catch (MonitorException e) { + logger.log(Level.WARNING, "error getting info for new vm" + newVm, e); + } catch (URISyntaxException e) { + logger.log(Level.WARNING, "error getting info for new vm" + newVm, e); + } + } + + for (Integer stoppedVm : (Set<Integer>) event.getTerminated()) { + try { + logger.fine("stopped vm: " + stoppedVm); + sendStoppedVM(stoppedVm, host); + } catch (URISyntaxException e) { + logger.log(Level.WARNING, "error getting info for stopped vm" + stoppedVm, e); + } catch (MonitorException e) { + logger.log(Level.WARNING, "error getting info for stopped vm" + stoppedVm, e); + } + } + } + + private void sendNewVM(Integer vmId, MonitoredHost host) + throws MonitorException, URISyntaxException { + MonitoredVm vm = host.getMonitoredVm(host.getHostIdentifier().resolve( + new VmIdentifier(vmId.toString()))); + if (vm != null) { + VmInfo info = null; + try { + long startTime = System.currentTimeMillis(); + long stopTime = Long.MIN_VALUE; + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + Map<String, String> properties = new HashMap<String, String>(); + ProcDataSource dataSource = new ProcDataSource(); + Map<String, String> environment = new ProcessEnvironmentBuilder(dataSource).build(vmId); + // TODO actually figure out the loaded libraries. + List<String> loadedNativeLibraries = new ArrayList<String>(); + info = new VmInfo(vmId, startTime, stopTime, + extractor.getJavaVersion(), extractor.getJavaHome(), + extractor.getMainClass(), extractor.getCommandLine(), + extractor.getVmName(), extractor.getVmInfo(), extractor.getVmVersion(), extractor.getVmArguments(), + properties, environment, loadedNativeLibraries); + vmInfoDAO.putVmInfo(info); + logger.finer("Sent VM_STARTED messsage"); + } catch (MonitorException me) { + logger.log(Level.WARNING, "error getting vm info for " + vmId, me); + } + + if (attachNew) { + List<VmListener> listeners = registeredListeners.get(vm); + if (listeners == null) { + listeners = new CopyOnWriteArrayList<>(); + } + + VmListener listener = new JvmStatVmListener(vmMemoryStatDAO, vmGcStatDAO, vmId); + vm.addVmListener(listener); + listeners.add(listener); + + listener = new JvmStatVmClassListener(vmClassStatDAO, vmId); + vm.addVmListener(listener); + listeners.add(listener); + + registeredListeners.put(vm, listeners); + + } else { + logger.log(Level.FINE, "skipping new vm " + vmId); + } + for (JvmStatusListener statusListener : statusListeners) { + statusListener.jvmStarted(vmId); + } + + monitoredVms.put(vmId, vm); + } + } + + private void sendStoppedVM(Integer vmId, MonitoredHost host) throws URISyntaxException, MonitorException { + + VmIdentifier resolvedVmID = host.getHostIdentifier().resolve(new VmIdentifier(vmId.toString())); + if (resolvedVmID != null) { + long stopTime = System.currentTimeMillis(); + for (JvmStatusListener statusListener : statusListeners) { + statusListener.jvmStopped(vmId); + } + vmInfoDAO.putVmStoppedTime(vmId, stopTime); + + MonitoredVm vm = monitoredVms.remove(vmId); + List<VmListener> listeners = registeredListeners.remove(vm); + for (VmListener listener : listeners) { + try { + if (listener != null) vm.removeVmListener(listener); + } catch (MonitorException e) { + logger.log(Level.WARNING, "can't remove vm listener", e); + } + } + vm.detach(); + } + } + + @Override + public void addJvmStatusListener(JvmStatusListener listener) { + statusListeners.add(listener); + } + + @Override + public void removeJvmStatusListener(JvmStatusListener listener) { + statusListeners.remove(listener); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmClassListener.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,90 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.event.MonitorStatusChangeEvent; +import sun.jvmstat.monitor.event.VmEvent; +import sun.jvmstat.monitor.event.VmListener; + +import com.redhat.thermostat.common.dao.VmClassStatDAO; +import com.redhat.thermostat.common.model.VmClassStat; +import com.redhat.thermostat.common.utils.LoggingUtils; + +class JvmStatVmClassListener implements VmListener { + + private static final Logger logger = LoggingUtils.getLogger(JvmStatVmClassListener.class); + + private VmClassStatDAO dao; + private int vmId; + + JvmStatVmClassListener(VmClassStatDAO dao, int vmId) { + this.dao = dao; + this.vmId = vmId; + } + + @Override + public void disconnected(VmEvent vmEvent) { + /* nothing to do here */ + } + + @Override + public void monitorStatusChanged(MonitorStatusChangeEvent vmEvent) { + /* nothing to do here */ + } + + @Override + public void monitorsUpdated(VmEvent vmEvent) { + MonitoredVm vm = vmEvent.getMonitoredVm(); + try { + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + long loadedClasses = extractor.getLoadedClasses(); + long timestamp = System.currentTimeMillis(); + VmClassStat stat = new VmClassStat(vmId, timestamp, loadedClasses); + dao.putVmClassStat(stat); + } catch (MonitorException e) { + logger.log(Level.WARNING, "error gathering class info for vm " + vmId, e); + } + + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,144 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.event.MonitorStatusChangeEvent; +import sun.jvmstat.monitor.event.VmEvent; +import sun.jvmstat.monitor.event.VmListener; + +import com.redhat.thermostat.common.dao.VmGcStatDAO; +import com.redhat.thermostat.common.dao.VmMemoryStatDAO; +import com.redhat.thermostat.common.model.VmGcStat; +import com.redhat.thermostat.common.model.VmMemoryStat; +import com.redhat.thermostat.common.model.VmMemoryStat.Generation; +import com.redhat.thermostat.common.model.VmMemoryStat.Space; +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class JvmStatVmListener implements VmListener { + + private static final Logger logger = LoggingUtils.getLogger(JvmStatVmListener.class); + + private final int vmId; + private final VmGcStatDAO gcDAO; + private final VmMemoryStatDAO memDAO; + + public JvmStatVmListener(VmMemoryStatDAO vmMemoryStatDao, VmGcStatDAO vmGcStatDao, int vmId) { + gcDAO = vmGcStatDao; + memDAO = vmMemoryStatDao; + this.vmId = vmId; + } + + @Override + public void disconnected(VmEvent event) { + /* nothing to do here */ + } + + @Override + public void monitorStatusChanged(MonitorStatusChangeEvent event) { + /* nothing to do here */ + } + + @Override + public void monitorsUpdated(VmEvent event) { + MonitoredVm vm = event.getMonitoredVm(); + if (vm == null) { + throw new NullPointerException(); + } + recordMemoryStat(vm); + recordGcStat(vm); + } + + private void recordGcStat(MonitoredVm vm) { + try { + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + long collectors = extractor.getTotalCollectors(); + for (int i = 0; i < collectors; i++) { + long timestamp = System.currentTimeMillis(); + VmGcStat stat = new VmGcStat(vmId, timestamp, + extractor.getCollectorName(i), + extractor.getCollectorInvocations(i), + extractor.getCollectorTime(i)); + gcDAO.putVmGcStat(stat); + } + } catch (MonitorException e) { + logger.log(Level.WARNING, "error gathering gc info for vm " + vmId, e); + } + + } + + private void recordMemoryStat(MonitoredVm vm) { + try { + long timestamp = System.currentTimeMillis(); + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + long maxGenerations = extractor.getTotalGcGenerations(); + List<Generation> generations = new ArrayList<Generation>(); + VmMemoryStat stat = new VmMemoryStat(timestamp, vmId, generations); + for (long generation = 0; generation < maxGenerations; generation++) { + Generation g = new Generation(); + generations.add(g); + g.name = extractor.getGenerationName(generation); + g.capacity = extractor.getGenerationCapacity(generation); + g.maxCapacity = extractor.getGenerationMaxCapacity(generation); + g.collector = extractor.getGenerationCollector(generation); + long maxSpaces = extractor.getTotalSpaces(generation); + List<Space> spaces = new ArrayList<Space>(); + g.spaces = spaces; + for (long space = 0; space < maxSpaces; space++) { + Space s = new Space(); + spaces.add(s); + s.index = (int) space; + s.name = extractor.getSpaceName(generation, space); + s.capacity = extractor.getSpaceCapacity(generation, space); + s.maxCapacity = extractor.getSpaceMaxCapacity(generation, space); + s.used = extractor.getSpaceUsed(generation, space); + } + } + memDAO.putVmMemoryStat(stat); + } catch (MonitorException e) { + logger.log(Level.WARNING, "error gathering memory info for vm " + vmId, e); + } + } + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/LsbRelease.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,111 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class LsbRelease implements DistributionInformationSource { + + private static final Logger logger = LoggingUtils.getLogger(LsbRelease.class); + + private static final String DISTRIBUTION_NAME = "distributor id"; + private static final String DISTRIBUTION_VERSION = "release"; + + @Override + public DistributionInformation getDistributionInformation() + throws IOException { + return getFromLsbRelease(); + } + + public DistributionInformation getFromLsbRelease() throws IOException { + + BufferedReader reader = null; + try { + Process lsbProc = Runtime.getRuntime().exec(new String[] { "lsb_release", "-a" }); + InputStream progOutput = lsbProc.getInputStream(); + reader = new BufferedReader(new InputStreamReader(progOutput)); + DistributionInformation result = getFromLsbRelease(reader); + int exitValue = lsbProc.waitFor(); + if (exitValue != 0) { + logger.log(Level.WARNING, "unable to identify distribution, problems running 'lsb_release'"); + } + return result; + } catch (InterruptedException e) { + throw new IOException(e); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + logger.log(Level.WARNING, "unable to close a child's output stream"); + } + } + } + + } + + public DistributionInformation getFromLsbRelease(BufferedReader reader) throws IOException { + String name = DistributionInformation.UNKNOWN_NAME; + String version = DistributionInformation.UNKNOWN_VERSION; + + String line; + while ((line = reader.readLine()) != null) { + int sepLocation = line.indexOf(":"); + if (sepLocation != -1) { + String key = line.substring(0, sepLocation).toLowerCase(); + if (key.equals(DISTRIBUTION_NAME)) { + name = line.substring(sepLocation + 1).trim(); + } else if (key.equals(DISTRIBUTION_VERSION)) { + version = line.substring(sepLocation + 1).trim(); + } + } + } + + logger.log(Level.FINE, "distro-name: " + name); + logger.log(Level.FINE, "distro-version: " + version); + + return new DistributionInformation(name, version); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/MemoryStatBuilder.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,140 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.Constants; +import com.redhat.thermostat.common.NotImplementedException; +import com.redhat.thermostat.common.model.MemoryStat; +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.utils.ProcDataSource; + +/** + * Implementation note: uses information from /proc/ + */ +public class MemoryStatBuilder { + + private static final long UNAVAILABLE = -1; + + private static final String KEY_MEMORY_TOTAL = "MemTotal"; + private static final String KEY_MEMORY_FREE = "MemFree"; + private static final String KEY_BUFFERS = "Buffers"; + private static final String KEY_CACHED = "Cached"; + private static final String KEY_SWAP_TOTAL = "SwapTotal"; + private static final String KEY_SWAP_FREE = "SwapFree"; + private static final String KEY_COMMIT_LIMIT = "CommitLimit"; + + private static final Logger logger = LoggingUtils.getLogger(MemoryStatBuilder.class); + + private final ProcDataSource dataSource; + + public MemoryStatBuilder(ProcDataSource dataSource) { + this.dataSource = dataSource; + } + + protected MemoryStat build() { + long timestamp = System.currentTimeMillis(); + + long total = UNAVAILABLE; + long free = UNAVAILABLE; + long swapTotal = UNAVAILABLE; + long swapFree = UNAVAILABLE; + long buffers = UNAVAILABLE; + long cached = UNAVAILABLE; + long commitLimit = UNAVAILABLE; + + try (BufferedReader reader = new BufferedReader(dataSource.getMemInfoReader())) { + String line = null; + while ((line = reader.readLine()) != null) { + String[] parts = line.split(":"); + if (parts.length == 2) { + String key = parts[0].trim(); + long value = getValue(parts[1].trim()); + if (key.equals(KEY_MEMORY_TOTAL)) { + total = value; + } else if (key.equals(KEY_MEMORY_FREE)) { + free = value; + } else if (key.equals(KEY_SWAP_TOTAL)) { + swapTotal = value; + } else if (key.equals(KEY_SWAP_FREE)) { + swapFree = value; + } else if (key.equals(KEY_BUFFERS)) { + buffers = value; + } else if (key.equals(KEY_CACHED)) { + cached = value; + } else if (key.equals(KEY_COMMIT_LIMIT)) { + commitLimit = value; + } + } + } + } catch (IOException ioe) { + logger.log(Level.WARNING, "unable to read memory info"); + } + + return new MemoryStat(timestamp, total, free, buffers, cached, swapTotal, swapFree, commitLimit); + } + + private long getValue(String rawValue) { + String[] parts = rawValue.split(" +"); + String value = rawValue; + String units = null; + if (parts.length > 1) { + value = parts[0]; + units = parts[1]; + } + + long result = UNAVAILABLE; + try { + result = Long.parseLong(value); + if (units != null) { + if (units.equals("kB") || units.equals("KB")) { + result = result * Constants.KILOBYTES_TO_BYTES; + } else { + throw new NotImplementedException("unit conversion from " + units + " not implemented"); + } + } + } catch (NumberFormatException nfe) { + logger.log(Level.WARNING, "error extracting memory info"); + } + + return result; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/NetworkInfoBuilder.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,79 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.model.NetworkInterfaceInfo; +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class NetworkInfoBuilder { + + private static final Logger logger = LoggingUtils.getLogger(NetworkInfoBuilder.class); + + public static List<NetworkInterfaceInfo> build() { + List<NetworkInterfaceInfo> infos = new ArrayList<NetworkInterfaceInfo>(); + try { + Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); + for (NetworkInterface iface : Collections.list(ifaces)) { + NetworkInterfaceInfo info = new NetworkInterfaceInfo(iface.getName()); + for (InetAddress addr : Collections.list(iface.getInetAddresses())) { + if (addr instanceof Inet4Address) { + info.setIp4Addr(addr.getHostAddress()); + } else if (addr instanceof Inet6Address) { + info.setIp6Addr(addr.getHostAddress()); + } + } + infos.add(info); + } + } catch (SocketException e) { + logger.log(Level.WARNING, "error enumerating network interfaces"); + } + return infos; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilder.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,125 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.utils.ProcDataSource; + +public class ProcessEnvironmentBuilder { + + private static final Logger logger = LoggingUtils.getLogger(ProcessEnvironmentBuilder.class); + + private final ProcDataSource dataSource; + + public ProcessEnvironmentBuilder(ProcDataSource dataSource) { + this.dataSource = dataSource; + } + + public Map<String, String> build(int pid) { + try (Reader reader = dataSource.getEnvironReader(pid)) { + return build(reader); + } catch (IOException ioe) { + logger.log(Level.WARNING, "error reading env", ioe); + } + + return Collections.emptyMap(); + } + + private Map<String,String> build(Reader reader) throws IOException { + + Map<String, String> env = new HashMap<String, String>(); + + char[] fileBuffer = new char[1024]; + int fileBufferIndex = 0; + char[] buffer = new char[1024]; + int read = 0; + while (true) { + read = reader.read(buffer); + if (read == -1) { + break; + } + + if (read + fileBufferIndex > fileBuffer.length) { + char[] newFileBuffer = new char[fileBuffer.length * 2]; + System.arraycopy(fileBuffer, 0, newFileBuffer, 0, fileBufferIndex); + fileBuffer = newFileBuffer; + } + System.arraycopy(buffer, 0, fileBuffer, fileBufferIndex, read); + fileBufferIndex = fileBufferIndex + read; + + } + List<String> parts = getParts(fileBuffer, fileBufferIndex); + for (String part : parts) { + int splitterPos = part.indexOf("="); + String key = part.substring(0, splitterPos); + String value = part.substring(splitterPos + 1); + env.put(key, value); + } + + return env; + } + + /** + * Split a char array, where items are separated by a null into into a list + * of strings + */ + private List<String> getParts(char[] nullSeparatedBuffer, int bufferLength) { + int maxLength = Math.min(nullSeparatedBuffer.length, bufferLength); + List<String> parts = new ArrayList<String>(); + + int lastStart = 0; + for (int i = 0; i < maxLength; i++) { + if (nullSeparatedBuffer[i] == '\0') { + String string = new String(nullSeparatedBuffer, lastStart, (i - lastStart)); + parts.add(string); + lastStart = i + 1; + } + } + return parts; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfo.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +public class ProcessStatusInfo { + + /* All times are measured in clock ticks */ + + private final int pid; + private final long userTime; + private final long kernelTime; + + public ProcessStatusInfo(int pid, long userTime, long kernelTime) { + this.pid = pid; + this.userTime = userTime; + this.kernelTime = kernelTime; + } + + public int getPid() { + return pid; + } + + /** + * @return the time this process has spent in user-mode as a number of + * kernel ticks + */ + public long getUserTime() { + return userTime; + } + + /** + * @return the time this process spent in kernel-mode as a number of kernel + * ticks + */ + public long getKernelTime() { + return kernelTime; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilder.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,119 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.util.Scanner; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.utils.ProcDataSource; + +/** + * Extract status information about the process from /proc/. This is what tools + * like {@code ps} and {@code top} use. + * + * @see {@code proc(5)} + */ +public class ProcessStatusInfoBuilder { + + private static final Logger logger = LoggingUtils.getLogger(ProcessStatusInfoBuilder.class); + + private final ProcDataSource dataSource; + + public ProcessStatusInfoBuilder(ProcDataSource dataSource) { + this.dataSource = dataSource; + } + + public ProcessStatusInfo build(int pid) { + try (BufferedReader reader = new BufferedReader(dataSource.getStatReader(pid))) { + return build(reader); + } catch (IOException e) { + logger.log(Level.WARNING, "unable to read stat info for " + pid); + } + + return null; + } + + private ProcessStatusInfo build(Reader r) throws IOException { + + int pid = -1; + long utime = -1; + long stime = -1; + + Scanner scanner = null; + + /* TODO map these (effectively c) data types to java types more sanely */ + + try (BufferedReader reader = new BufferedReader(r)) { + String statusLine = reader.readLine(); + + /* be prepared for process names like '1 ) 2 3 4 foo 5' */ + + scanner = new Scanner(statusLine); + pid = scanner.nextInt(); + scanner.close(); + + int execEndNamePos = statusLine.lastIndexOf(')'); + + String cleanStatusLine = statusLine.substring(execEndNamePos + 1); + + scanner = new Scanner(cleanStatusLine); + /* state = */scanner.next(); + /* ppid = */scanner.nextInt(); + /* pgrp = */scanner.nextInt(); + /* session = */scanner.nextInt(); + /* tty_nr = */scanner.nextInt(); + /* tpgid = */scanner.nextInt(); + /* flags = */scanner.nextInt(); + /* minflt = */scanner.nextLong(); + /* cminflt = */scanner.nextLong(); + /* majflt = */scanner.nextLong(); + /* cmajflt = */scanner.nextLong(); + utime = scanner.nextLong(); + stime = scanner.nextLong(); + scanner.close(); + } + + return new ProcessStatusInfo(pid, utime, stime); + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/SysConf.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,87 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * A wrapper over POSIX's sysconf. + * <p> + * Implementation notes: uses {@code getconf(1)} + */ +public class SysConf { + + private SysConf() { + /* do not initialize */ + } + + public static long getClockTicksPerSecond() { + String ticks = sysConf("CLK_TCK"); + try { + return Long.valueOf(ticks); + } catch (NumberFormatException nfe) { + return 0; + } + } + + private static String sysConf(String arg) { + BufferedReader reader = null; + try { + Process process = Runtime.getRuntime().exec(new String[] { "getconf", arg }); + int result = process.waitFor(); + if (result != 0) { + return null; + } + reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + return reader.readLine(); + } catch (IOException e) { + return null; + } catch (InterruptedException e) { + return null; + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + // TODO + } + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,242 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.net.URISyntaxException; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.logging.Level; +import java.util.logging.Logger; + +import sun.jvmstat.monitor.HostIdentifier; +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredHost; + +import com.redhat.thermostat.agent.JvmStatusListener; +import com.redhat.thermostat.agent.JvmStatusNotifier; +import com.redhat.thermostat.backend.Backend; +import com.redhat.thermostat.backend.BackendID; +import com.redhat.thermostat.backend.BackendsProperties; +import com.redhat.thermostat.common.Clock; +import com.redhat.thermostat.common.SystemClock; +import com.redhat.thermostat.common.dao.CpuStatDAO; +import com.redhat.thermostat.common.dao.HostInfoDAO; +import com.redhat.thermostat.common.dao.MemoryStatDAO; +import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO; +import com.redhat.thermostat.common.dao.VmCpuStatDAO; +import com.redhat.thermostat.common.model.BackendInformation; +import com.redhat.thermostat.common.model.NetworkInterfaceInfo; +import com.redhat.thermostat.common.model.VmCpuStat; +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.utils.ProcDataSource; + +public class SystemBackend extends Backend implements JvmStatusNotifier, JvmStatusListener { + + private static final Logger logger = LoggingUtils.getLogger(SystemBackend.class); + + private CpuStatDAO cpuStats; + private HostInfoDAO hostInfos; + private MemoryStatDAO memoryStats; + private VmCpuStatDAO vmCpuStats; + private NetworkInterfaceInfoDAO networkInterfaces; + + private final Set<Integer> pidsToMonitor = new CopyOnWriteArraySet<Integer>(); + + private long procCheckInterval = 1000; // TODO make this configurable. + + private Timer timer = null; + + private HostIdentifier hostId = null; + private MonitoredHost host = null; + private JvmStatHostListener hostListener; + + private final VmCpuStatBuilder vmCpuBuilder; + private final HostInfoBuilder hostInfoBuilder; + private final CpuStatBuilder cpuStatBuilder; + private final MemoryStatBuilder memoryStatBuilder; + + public SystemBackend() { + super(new BackendID("System Backend", SystemBackend.class.getName())); + + setConfigurationValue(BackendsProperties.VENDOR.name(), "Red Hat, Inc."); + setConfigurationValue(BackendsProperties.DESCRIPTION.name(), "Gathers basic information from the system"); + setConfigurationValue(BackendsProperties.VERSION.name(), "0.1.0"); + + Clock clock = new SystemClock(); + ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(new ProcDataSource()); + long ticksPerSecond = SysConf.getClockTicksPerSecond(); + ProcDataSource source = new ProcDataSource(); + hostInfoBuilder = new HostInfoBuilder(source); + cpuStatBuilder = new CpuStatBuilder(clock, source, ticksPerSecond); + memoryStatBuilder = new MemoryStatBuilder(source); + + int cpuCount = hostInfoBuilder.getCpuInfo().count; + vmCpuBuilder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, builder); + } + + @Override + protected void setDAOFactoryAction() { + cpuStats = df.getCpuStatDAO(); + hostInfos = df.getHostInfoDAO(); + memoryStats = df.getMemoryStatDAO(); + vmCpuStats = df.getVmCpuStatDAO(); + networkInterfaces = df.getNetworkInterfaceInfoDAO(); + hostListener = new JvmStatHostListener(df.getVmInfoDAO(), df.getVmMemoryStatDAO(), df.getVmGcStatDAO(), df.getVmClassStatsDAO(), getObserveNewJvm()); + } + + @Override + public synchronized boolean activate() { + if (timer != null) { + return true; + } + if (df == null) { + throw new IllegalStateException("Cannot activate backend without DAOFactory."); + } + + addJvmStatusListener(this); + + if (!getObserveNewJvm()) { + logger.fine("not monitoring new vms"); + } + hostInfos.putHostInfo(hostInfoBuilder.build()); + + timer = new Timer(); + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + if (!cpuStatBuilder.isInitialized()) { + cpuStatBuilder.initialize(); + } else { + cpuStats.putCpuStat(cpuStatBuilder.build()); + } + for (NetworkInterfaceInfo info: NetworkInfoBuilder.build()) { + networkInterfaces.putNetworkInterfaceInfo(info); + } + memoryStats.putMemoryStat(memoryStatBuilder.build()); + + for (Integer pid : pidsToMonitor) { + if (vmCpuBuilder.knowsAbout(pid)) { + VmCpuStat dataBuilt = vmCpuBuilder.build(pid); + if (dataBuilt != null) { + vmCpuStats.putVmCpuStat(dataBuilt); + } + } else { + vmCpuBuilder.learnAbout(pid); + } + } + } + }, 0, procCheckInterval); + + try { + hostId = new HostIdentifier((String) null); + host = MonitoredHost.getMonitoredHost(hostId); + host.addHostListener(hostListener); + } catch (MonitorException me) { + logger.log(Level.WARNING, "problems with connecting jvmstat to local machine", me); + } catch (URISyntaxException use) { + logger.log(Level.WARNING, "problems with connecting jvmstat to local machine", use); + } + + return true; + } + + @Override + public synchronized boolean deactivate() { + if (timer == null) { + return true; + } + + timer.cancel(); + timer = null; + + removeJvmStatusListener(this); + + try { + + // remove all listener from the host listener + hostListener.removeAllListeners(); + + host.removeHostListener(hostListener); + } catch (MonitorException me) { + logger.log(Level.INFO, "something went wrong in jvmstat's listening to this host"); + } + host = null; + hostId = null; + + return true; + } + + @Override + public synchronized boolean isActive() { + return (timer != null); + } + + @Override + public String getConfigurationValue(String key) { + return null; + } + + @Override + public boolean attachToNewProcessByDefault() { + return true; + } + + @Override + public void addJvmStatusListener(JvmStatusListener listener) { + hostListener.addJvmStatusListener(listener); + } + + @Override + public void removeJvmStatusListener(JvmStatusListener listener) { + hostListener.removeJvmStatusListener(listener); + } + + @Override + public void jvmStarted(int vmId) { + if (getObserveNewJvm()) { + pidsToMonitor.add(vmId); + } + } + + @Override + public void jvmStopped(int vmId) { + pidsToMonitor.remove(vmId); + vmCpuBuilder.forgetAbout(vmId); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/VmCpuStatBuilder.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,130 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.Clock; +import com.redhat.thermostat.common.model.VmCpuStat; +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class VmCpuStatBuilder { + + private static final Logger logger = LoggingUtils.getLogger(VmCpuStatBuilder.class); + + // pid -> ticks + private final Map<Integer, Long> lastProcessTicks = new HashMap<Integer, Long>(); + // pid -> last time the ticks were updated + private final Map<Integer, Long> lastProcessTickTime = new HashMap<Integer, Long>(); + + private final Clock clock; + private final int cpuCount; + private final long ticksPerSecond; + private final ProcessStatusInfoBuilder statusBuilder; + + public VmCpuStatBuilder(Clock clock, int cpuCount, long ticksPerSecond, ProcessStatusInfoBuilder statusBuilder) { + this.clock = clock; + this.cpuCount = cpuCount; + this.ticksPerSecond = ticksPerSecond; + this.statusBuilder = statusBuilder; + } + + /** + * @param pid the process id + * @return an object representing the cpu usage of the process, or null if + * the information can not be found. + */ + public synchronized VmCpuStat build(Integer pid) { + if (!lastProcessTicks.containsKey(pid) || !lastProcessTickTime.containsKey(pid)) { + throw new IllegalArgumentException("unknown pid"); + } + + ProcessStatusInfo info = statusBuilder.build(pid); + if (info == null) { + return null; + } + long miliTime = clock.getRealTimeMillis(); + long time = clock.getMonotonicTimeNanos(); + long programTicks = (info.getKernelTime() + info.getUserTime()); + double cpuLoad = 0.0; + + double timeDelta = (time - lastProcessTickTime.get(pid)) * 1E-9; + long programTicksDelta = programTicks - lastProcessTicks.get(pid); + // 100 as in 100 percent. + cpuLoad = programTicksDelta * (100.0 / timeDelta / ticksPerSecond / cpuCount); + + if (cpuLoad < 0.0 || cpuLoad > 100.0) { + logger.log(Level.WARNING, "cpu load for " + pid + " is outside [0,100]: " + cpuLoad); + logger.log(Level.WARNING, " (" + pid + ") programTicks: " + programTicks); + logger.log(Level.WARNING, " (" + pid + ") programTicksDelta: " + programTicksDelta); + logger.log(Level.WARNING, " (" + pid + ") time: " + time); + logger.log(Level.WARNING, " (" + pid + ") timeDelta: " + timeDelta); + logger.log(Level.WARNING, " (" + pid + ") ticksPerSecond: " + ticksPerSecond); + logger.log(Level.WARNING, " (" + pid + ") cpuCount: " + cpuCount); + } + + lastProcessTicks.put(pid, programTicks); + lastProcessTickTime.put(pid, time); + + return new VmCpuStat(miliTime, pid, cpuLoad); + } + + public synchronized boolean knowsAbout(int pid) { + return (lastProcessTickTime.containsKey(pid) && lastProcessTicks.containsKey(pid)); + } + + public synchronized void learnAbout(int pid) { + long time = clock.getMonotonicTimeNanos(); + ProcessStatusInfo info = statusBuilder.build(pid); + if (info == null) { + logger.log(Level.WARNING, "can not learn about pid " + pid + " : statusBuilder returned null"); + return; + } + + lastProcessTickTime.put(pid, time); + lastProcessTicks.put(pid, info.getUserTime()+ info.getKernelTime()); + } + + public synchronized void forgetAbout(int pid) { + lastProcessTicks.remove(pid); + lastProcessTickTime.remove(pid); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/osgi/SystemBackendActivator.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,89 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system.osgi; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; + +import com.redhat.thermostat.backend.Backend; +import com.redhat.thermostat.backend.BackendService; +import com.redhat.thermostat.backend.system.SystemBackend; + +@SuppressWarnings("rawtypes") +public class SystemBackendActivator implements BundleActivator { + + private ServiceTracker tracker; + private SystemBackend backend; + + @SuppressWarnings("unchecked") + @Override + public void start(BundleContext context) throws Exception { + System.err.println("loading SystemBackendActivator"); + + backend = new SystemBackend(); + + tracker = new ServiceTracker(context, BackendService.class, null) { + @Override + public Object addingService(ServiceReference reference) { + context.registerService(Backend.class, backend, null); + return super.addingService(reference); + } + + @Override + public void removedService(ServiceReference reference, Object service) { + + if (backend.isActive()) { + backend.deactivate(); + } + context.ungetService(reference); + super.removedService(reference, service); + } + }; + + tracker.open(); + } + + @Override + public void stop(BundleContext context) throws Exception { + if (backend.isActive()) { + backend.deactivate(); + } + tracker.close(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/CpuStatBuilderTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,112 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; + +import org.junit.Test; + +import com.redhat.thermostat.common.Clock; +import com.redhat.thermostat.common.SystemClock; +import com.redhat.thermostat.common.model.CpuStat; +import com.redhat.thermostat.common.utils.ArrayUtils; +import com.redhat.thermostat.utils.ProcDataSource; + +public class CpuStatBuilderTest { + + @Test + public void testSimpleBuild() { + ProcDataSource dataSource = new ProcDataSource(); + CpuStatBuilder builder= new CpuStatBuilder(new SystemClock(), dataSource, 100l); + builder.initialize(); + CpuStat stat = builder.build(); + assertNotNull(stat); + } + + @Test (expected=IllegalStateException.class) + public void buildWithoutInitializeThrowsException() { + Clock clock = mock(Clock.class); + ProcDataSource dataSource = mock(ProcDataSource.class); + long ticksPerSecond = 1; + CpuStatBuilder builder = new CpuStatBuilder(clock, dataSource, ticksPerSecond); + builder.build(); + } + + @Test + public void testBuildCpuStatFromFile() throws IOException { + long CLOCK1 = 1000; + long CLOCK2 = 2000; + + String firstReadContents = + "cpu 100 0 0 1000 1000\n" + + "cpu0 100 0 0 1000 1000\n" + + "cpu1 10 80 10 1000 1000\n"; + BufferedReader reader1 = new BufferedReader(new StringReader(firstReadContents)); + + String secondReadContents = + "cpu 400 0 0 1000 1000\n" + + "cpu0 200 0 0 1000 1000\n" + + "cpu1 30 50 120 1000 1000\n"; + BufferedReader reader2 = new BufferedReader(new StringReader(secondReadContents)); + + long ticksPerSecond = 100; + Clock clock = mock(Clock.class); + when(clock.getRealTimeMillis()).thenReturn(CLOCK2); + when(clock.getMonotonicTimeNanos()).thenReturn((long)(CLOCK1 * 1E6)).thenReturn((long)(CLOCK2 * 1E6)); + + ProcDataSource dataSource = mock(ProcDataSource.class); + when(dataSource.getStatReader()).thenReturn(reader1).thenReturn(reader2); + CpuStatBuilder builder = new CpuStatBuilder(clock, dataSource, ticksPerSecond); + + builder.initialize(); + + CpuStat stat = builder.build(); + + verify(dataSource, times(2)).getStatReader(); + assertArrayEquals(new double[] {100, 100}, ArrayUtils.toPrimitiveDoubleArray(stat.getPerProcessorUsage()), 0.01); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/DistributionInformationTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import com.redhat.thermostat.common.TestUtils; + +public class DistributionInformationTest { + + @Test + public void testName() { + if (TestUtils.isLinux()) { + DistributionInformation info = DistributionInformation.get(); + String name = info.getName(); + assertNotNull(name); + assertTrue(name.length() > 0); + assertFalse(name.startsWith(":")); + assertFalse(name.equals(DistributionInformation.UNKNOWN_NAME)); + } + } + + @Test + public void testVersion() { + if (TestUtils.isLinux()) { + DistributionInformation info = DistributionInformation.get(); + String version = info.getVersion(); + assertNotNull(version); + assertTrue(version.length()> 0); + assertFalse(version.startsWith(":")); + assertFalse(version.equals(DistributionInformation.UNKNOWN_VERSION)); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/EtcOsReleaseTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,84 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; + +import org.junit.Test; + +import com.redhat.thermostat.test.Bug; + +public class EtcOsReleaseTest { + + @Test + public void testName() throws IOException, InterruptedException { + BufferedReader reader = new BufferedReader(new StringReader("NAME=\"Name\"\n")); + DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader); + assertEquals("Name", info.getName()); + } + + + @Test + public void testVersion() throws IOException { + BufferedReader reader = new BufferedReader(new StringReader("VERSION=\"Version\"\n")); + DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader); + assertEquals("Version", info.getVersion()); + } + + @Bug(id="981", + summary="DistributionInformationTest fails on OpenSUSE Linux 12.1", + url="http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=981") + @Test + public void testFormattedOutput() throws IOException { + String output = + "NAME=openSUSE\n" + + "VERSION = 12.1 (Asparagus)\n" + + "VERSION_ID=\"12.1\"\n" + + "PRETTY_NAME=\"openSUSE 12.1 (Asparagus) (x86_64)\"\n" + + "ID=opensuse"; + BufferedReader reader = new BufferedReader(new StringReader(output)); + DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader); + + assertEquals("openSUSE", info.getName()); + assertEquals("12.1 (Asparagus)", info.getVersion()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/HostInfoBuilderTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,122 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.io.StringReader; +import java.net.InetAddress; + +import org.junit.Test; + +import com.redhat.thermostat.backend.system.HostInfoBuilder.HostCpuInfo; +import com.redhat.thermostat.backend.system.HostInfoBuilder.HostMemoryInfo; +import com.redhat.thermostat.backend.system.HostInfoBuilder.HostOsInfo; +import com.redhat.thermostat.common.Constants; +import com.redhat.thermostat.common.model.HostInfo; +import com.redhat.thermostat.utils.ProcDataSource; + +public class HostInfoBuilderTest { + + @Test + public void testSimpleBuild() { + HostInfo info = new HostInfoBuilder(new ProcDataSource()).build(); + assertNotNull(info); + } + + @Test + public void testCpuInfo() throws IOException { + String cpuInfoString = + "processor: 1\n" + + "model name: Test Model\n" + + "processor: 0\n" + + "model name: Test Model\n"; + + StringReader cpuInfoReader = new StringReader(cpuInfoString); + + ProcDataSource dataSource = mock(ProcDataSource.class); + when(dataSource.getCpuInfoReader()).thenReturn(cpuInfoReader); + + HostCpuInfo cpuInfo = new HostInfoBuilder(dataSource).getCpuInfo(); + assertEquals(2, cpuInfo.count); + assertEquals("Test Model", cpuInfo.model); + verify(dataSource).getCpuInfoReader(); + } + + @Test + public void testMemoryInfo() throws IOException { + String memoryInfoString = + "MemTotal: 12345 kB"; + + StringReader memoryInfoReader = new StringReader(memoryInfoString); + ProcDataSource dataSource = mock(ProcDataSource.class); + when(dataSource.getMemInfoReader()).thenReturn(memoryInfoReader); + + HostMemoryInfo memoryInfo = new HostInfoBuilder(dataSource).getMemoryInfo(); + assertNotNull(memoryInfo); + assertEquals(12345 * Constants.KILOBYTES_TO_BYTES, memoryInfo.totalMemory); + verify(dataSource).getMemInfoReader(); + + } + + @Test + public void testOsInfo() { + DistributionInformation distroInfo = new DistributionInformation("distro-name", "distro-version"); + ProcDataSource dataSource = mock(ProcDataSource.class); + HostOsInfo osInfo = new HostInfoBuilder(dataSource).getOsInfo(distroInfo); + assertEquals("distro-name distro-version", osInfo.distribution); + assertEquals(System.getProperty("os.name") + " " + System.getProperty("os.version"), osInfo.kernel); + } + + @Test + public void testHostname() { + + InetAddress address = mock(InetAddress.class); + when(address.getCanonicalHostName()).thenReturn("test-hostname"); + + ProcDataSource dataSource = mock(ProcDataSource.class); + + String name = new HostInfoBuilder(dataSource).getHostName(address); + assertEquals("test-hostname", name); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/JvmStatDataExtractorTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,375 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Test; + +import sun.jvmstat.monitor.LongMonitor; +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.StringMonitor; + +public class JvmStatDataExtractorTest { + + private MonitoredVm buildStringMonitoredVm(String monitorName, String monitorReturn) throws MonitorException { + final StringMonitor monitor = mock(StringMonitor.class); + when(monitor.stringValue()).thenReturn(monitorReturn); + when(monitor.getValue()).thenReturn(monitorReturn); + MonitoredVm vm = mock(MonitoredVm.class); + when(vm.findByName(monitorName)).thenReturn(monitor); + return vm; + } + + private MonitoredVm buildLongMonitoredVm(String monitorName, Long monitorReturn) throws MonitorException { + final LongMonitor monitor = mock(LongMonitor.class); + when(monitor.longValue()).thenReturn(monitorReturn); + when(monitor.getValue()).thenReturn(monitorReturn); + MonitoredVm vm = mock(MonitoredVm.class); + when(vm.findByName(monitorName)).thenReturn(monitor); + return vm; + } + + @Test + public void testCommandLine() throws MonitorException { + final String MONITOR_NAME = "sun.rt.javaCommand"; + final String MONITOR_VALUE = "command line java"; + MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + String returned = extractor.getCommandLine(); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(MONITOR_VALUE, returned); + } + + @Test + public void testMainClass() throws MonitorException { + final String MONITOR_NAME = "sun.rt.javaCommand"; + final String MONITOR_VALUE = "some.package.Main"; + MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + String returned = extractor.getMainClass(); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(MONITOR_VALUE, returned); + } + + @Test + public void testJavaVersion() throws MonitorException { + final String MONITOR_NAME = "java.property.java.version"; + final String MONITOR_VALUE = "some java version"; + MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + String returned = extractor.getJavaVersion(); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(MONITOR_VALUE, returned); + } + + @Test + public void testJavaHome() throws MonitorException { + final String MONITOR_NAME = "java.property.java.home"; + final String MONITOR_VALUE = "${java.home}"; + MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + String returned = extractor.getJavaHome(); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(MONITOR_VALUE, returned); + } + + @Test + public void testVmName() throws MonitorException { + final String MONITOR_NAME = "java.property.java.vm.name"; + final String MONITOR_VALUE = "${vm.name}"; + MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + String returned = extractor.getVmName(); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(MONITOR_VALUE, returned); + } + + @Test + public void testVmInfo() throws MonitorException { + final String MONITOR_NAME = "java.property.java.vm.info"; + final String MONITOR_VALUE = "${vm.info}"; + MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + String returned = extractor.getVmInfo(); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(MONITOR_VALUE, returned); + } + + @Test + public void testVmVersion() throws MonitorException { + final String MONITOR_NAME = "java.property.java.vm.version"; + final String MONITOR_VALUE = "${vm.version}"; + MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + String returned = extractor.getVmVersion(); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(MONITOR_VALUE, returned); + } + + @Test + public void testVmArguments() throws MonitorException { + final String MONITOR_NAME = "java.rt.vmArgs"; + final String MONITOR_VALUE = "${vm.arguments}"; + MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + String returned = extractor.getVmArguments(); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(MONITOR_VALUE, returned); + } + + @Test + public void testTotalCollectors() throws MonitorException { + final String MONITOR_NAME = "sun.gc.policy.collectors"; + final Long MONITOR_VALUE = 9l; + MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, MONITOR_VALUE); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + Long returned = extractor.getTotalCollectors(); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(MONITOR_VALUE, returned); + } + + @Test + public void testCollectorName() throws MonitorException { + final String MONITOR_NAME = "sun.gc.collector.0.name"; + final String COLLECTOR_NAME = "SomeMemoryCollector"; + MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, COLLECTOR_NAME); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + String returned = extractor.getCollectorName(0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(COLLECTOR_NAME, returned); + } + + @Test + public void testCollectorTime() throws MonitorException { + final String MONITOR_NAME = "sun.gc.collector.0.time"; + final Long COLLECTOR_TIME = 99l; + MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, COLLECTOR_TIME); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + Long returned = extractor.getCollectorTime(0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(COLLECTOR_TIME, returned); + } + + @Test + public void testCollectorInvocations() throws MonitorException { + final String MONITOR_NAME = "sun.gc.collector.0.invocations"; + final Long COLLECTOR_INVOCATIONS = 99l; + MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, COLLECTOR_INVOCATIONS); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + Long returned = extractor.getCollectorInvocations(0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(COLLECTOR_INVOCATIONS, returned); + } + + @Test + public void testTotalGcGenerations() throws MonitorException { + final String MONITOR_NAME = "sun.gc.policy.generations"; + final Long GC_GENERATIONS = 99l; + MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, GC_GENERATIONS); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + Long returned = extractor.getTotalGcGenerations(); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(GC_GENERATIONS, returned); + } + + @Test + public void testGenerationName() throws MonitorException { + final String MONITOR_NAME = "sun.gc.generation.0.name"; + final String GENERATION_NAME = "Youth"; + MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, GENERATION_NAME); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + String returned = extractor.getGenerationName(0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(GENERATION_NAME, returned); + } + + @Test + public void testGenerationCapacity() throws MonitorException { + final String MONITOR_NAME = "sun.gc.generation.0.capacity"; + final Long GENERATION_CAPACITY = 99l; + MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, GENERATION_CAPACITY); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + Long returned = extractor.getGenerationCapacity(0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(GENERATION_CAPACITY, returned); + } + + @Test + public void testGenerationMaxCapacity() throws MonitorException { + final String MONITOR_NAME = "sun.gc.generation.0.maxCapacity"; + final Long GENERATION_MAX_CAPACITY = 99l; + MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, GENERATION_MAX_CAPACITY); + + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + Long returned = extractor.getGenerationMaxCapacity(0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(GENERATION_MAX_CAPACITY, returned); + } + + @Test + public void testGenerationCollector() throws MonitorException { + final String MONITOR_NAME = "sun.gc.collector.0.name"; + final String GENERATION_COLLECTOR = "generation collector"; + MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, GENERATION_COLLECTOR); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + String returned = extractor.getGenerationCollector(0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(GENERATION_COLLECTOR, returned); + } + + @Test + public void testTotalSpaces() throws MonitorException { + final Long TOTAL_SPACES = 99l; + final LongMonitor monitor = mock(LongMonitor.class); + when(monitor.getValue()).thenReturn(TOTAL_SPACES); + MonitoredVm vm = mock(MonitoredVm.class); + when(vm.findByName("sun.gc.generation.0.spaces")).thenReturn(monitor); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + Long returned = extractor.getTotalSpaces(0); + + verify(vm).findByName(eq("sun.gc.generation.0.spaces")); + assertEquals(TOTAL_SPACES, returned); + } + + + @Test + public void testSpaceName() throws MonitorException { + final String MONITOR_NAME = "sun.gc.generation.0.space.0.name"; + final String SPACE_NAME = "Hilbert"; + MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, SPACE_NAME); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + String returned = extractor.getSpaceName(0,0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(SPACE_NAME, returned); + } + + @Test + public void testSpaceCapacity() throws MonitorException { + final String MONITOR_NAME = "sun.gc.generation.0.space.0.capacity"; + final Long SPACE_CAPACITY = 99l; + MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, SPACE_CAPACITY); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + Long returned = extractor.getSpaceCapacity(0,0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(SPACE_CAPACITY, returned); + } + + @Test + public void testSpaceMaxCapacity() throws MonitorException { + final String MONITOR_NAME = "sun.gc.generation.0.space.0.maxCapacity"; + final Long SPACE_MAX_CAPACITY = 99l; + MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, SPACE_MAX_CAPACITY); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + Long returned = extractor.getSpaceMaxCapacity(0,0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(SPACE_MAX_CAPACITY, returned); + } + + @Test + public void testSpaceUsed() throws MonitorException { + final String MONITOR_NAME = "sun.gc.generation.0.space.0.used"; + final Long SPACE_USED = 99l; + MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, SPACE_USED); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + Long returned = extractor.getSpaceUsed(0,0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(SPACE_USED, returned); + } + + @Test + public void testLoadedClasses() throws MonitorException { + final String MONITOR_NAME = "java.cls.loadedClasses"; + final Long LOADED_CLASSES = 99l; + MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, LOADED_CLASSES); + + JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); + Long returned = extractor.getLoadedClasses(); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(LOADED_CLASSES, returned); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/JvmStatHostListenerTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,93 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.HashSet; +import java.util.Set; + +import org.junit.Test; +import org.mockito.Matchers; + +import sun.jvmstat.monitor.HostIdentifier; +import sun.jvmstat.monitor.MonitoredHost; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.StringMonitor; +import sun.jvmstat.monitor.VmIdentifier; +import sun.jvmstat.monitor.event.VmStatusChangeEvent; + +import com.redhat.thermostat.common.dao.VmClassStatDAO; +import com.redhat.thermostat.common.dao.VmInfoDAO; + +public class JvmStatHostListenerTest { + + @Test + public void testVmStatusChangedAddsVmClassListener() throws Exception { + VmStatusChangeEvent vmEvent = mock(VmStatusChangeEvent.class); + Set<Integer> startedVms = new HashSet<Integer>(); + startedVms.add(123); + when(vmEvent.getStarted()).thenReturn(startedVms); + + MonitoredVm vm = mock(MonitoredVm.class); + StringMonitor monitor = mock(StringMonitor.class); + when(monitor.stringValue()).thenReturn("test"); + when(monitor.getValue()).thenReturn("test"); + when(vm.findByName(anyString())).thenReturn(monitor); + MonitoredHost host = mock(MonitoredHost.class); + HostIdentifier hostId = mock(HostIdentifier.class); + when(host.getHostIdentifier()).thenReturn(hostId); + when(host.getMonitoredVm(any(VmIdentifier.class))).thenReturn(vm); + when(vmEvent.getMonitoredHost()).thenReturn(host); + + VmClassStatDAO vmClassDAO = mock(VmClassStatDAO.class); + VmInfoDAO vmInfoDAO = mock(VmInfoDAO.class); + + JvmStatHostListener l = new JvmStatHostListener(vmInfoDAO, null, null, vmClassDAO ,true); + SystemBackend backend = mock(SystemBackend.class); + when(backend.getObserveNewJvm()).thenReturn(true); + + l.vmStatusChanged(vmEvent); + + verify(vm).addVmListener(Matchers.isA(JvmStatVmClassListener.class)); + } + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/JvmStatVmClassListenerTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,100 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import sun.jvmstat.monitor.Monitor; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.event.VmEvent; + +import com.redhat.thermostat.common.dao.VmClassStatDAO; +import com.redhat.thermostat.common.model.VmClassStat; + +public class JvmStatVmClassListenerTest { + + private static final Integer VM_ID = 123; + private static final Long LOADED_CLASSES = 1234L; + + @Test + public void testMonitorUpdatedClassStat() throws Exception { + + VmClassStatDAO dao = mock(VmClassStatDAO.class); + + JvmStatVmClassListener l = new JvmStatVmClassListener(dao, VM_ID); + VmEvent vmEvent = mock(VmEvent.class); + MonitoredVm monitoredVm = mock(MonitoredVm.class); + Monitor m = mock(Monitor.class); + when(m.getValue()).thenReturn(LOADED_CLASSES); + when(monitoredVm.findByName("java.cls.loadedClasses")).thenReturn(m); + when(vmEvent.getMonitoredVm()).thenReturn(monitoredVm); + + l.monitorsUpdated(vmEvent); + + ArgumentCaptor<VmClassStat> arg = ArgumentCaptor.forClass(VmClassStat.class); + verify(dao).putVmClassStat(arg.capture()); + VmClassStat stat = arg.getValue(); + assertEquals(LOADED_CLASSES, (Long) stat.getLoadedClasses()); + assertEquals(VM_ID, (Integer) stat.getVmId()); + } + + @Test + public void testMonitorUpdatedClassStatTwice() throws Exception { + + VmClassStatDAO dao = mock(VmClassStatDAO.class); + + JvmStatVmClassListener l = new JvmStatVmClassListener(dao, VM_ID); + VmEvent vmEvent = mock(VmEvent.class); + MonitoredVm monitoredVm = mock(MonitoredVm.class); + Monitor m = mock(Monitor.class); + when(m.getValue()).thenReturn(LOADED_CLASSES); + when(monitoredVm.findByName("java.cls.loadedClasses")).thenReturn(m); + when(vmEvent.getMonitoredVm()).thenReturn(monitoredVm); + + l.monitorsUpdated(vmEvent); + l.monitorsUpdated(vmEvent); + + // This checks a bug where the Category threw an IllegalStateException because the DAO + // created a new one on each call, thus violating the unique guarantee of Category. + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/LsbReleaseTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; + +import org.junit.Test; + +public class LsbReleaseTest { + + @Test + public void testName() throws IOException, InterruptedException { + BufferedReader reader = new BufferedReader(new StringReader("Distributor ID: Name")); + DistributionInformation info = new LsbRelease().getFromLsbRelease(reader); + assertEquals("Name", info.getName()); + } + + @Test + public void testVersion() throws IOException { + BufferedReader reader = new BufferedReader(new StringReader("Release: Version")); + DistributionInformation info = new LsbRelease().getFromLsbRelease(reader); + assertEquals("Version", info.getVersion()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/MemoryStatBuilderTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,112 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.io.StringReader; + +import org.junit.Test; + +import com.redhat.thermostat.common.Constants; +import com.redhat.thermostat.common.model.MemoryStat; +import com.redhat.thermostat.utils.ProcDataSource; + +public class MemoryStatBuilderTest { + + @Test + public void testSimpleBuild() { + MemoryStat stat = new MemoryStatBuilder(new ProcDataSource()).build(); + assertNotNull(stat); + } + + @Test + public void testEmptyBuild() throws IOException { + String memory = ""; + StringReader memoryReader = new StringReader(memory); + ProcDataSource dataSource = mock(ProcDataSource.class); + when(dataSource.getMemInfoReader()).thenReturn(memoryReader); + + MemoryStat stat = new MemoryStatBuilder(dataSource).build(); + assertNotNull(stat); + verify(dataSource).getMemInfoReader(); + } + + @Test + public void testBuild() throws IOException { + int i = 1; + final long TOTAL = i++; + final long FREE = i++; + final long BUFFERS = i++; + final long CACHED = i++; + final long COMMIT_LIMIT = i++; + final long SWAP_TOTAL = i++; + final long SWAP_FREE = i++; + + String memory = "" + + "MemTotal: " + TOTAL + " kB\n" + + "MemFree: " + FREE + " kB\n" + + "Buffers:" + BUFFERS + " kB\n" + + "Cached: " + CACHED + " kB\n" + + "CommitLimit: " + COMMIT_LIMIT + " kB\n" + + "SwapTotal: " + SWAP_TOTAL + " kB\n" + + "SwapFree: " + SWAP_FREE + " kB\n"; + + StringReader memoryReader = new StringReader(memory); + ProcDataSource dataSource = mock(ProcDataSource.class); + when(dataSource.getMemInfoReader()).thenReturn(memoryReader); + + MemoryStat stat = new MemoryStatBuilder(dataSource).build(); + + assertEquals(BUFFERS * Constants.KILOBYTES_TO_BYTES, stat.getBuffers()); + assertEquals(CACHED * Constants.KILOBYTES_TO_BYTES, stat.getCached()); + assertEquals(COMMIT_LIMIT * Constants.KILOBYTES_TO_BYTES, stat.getCommitLimit()); + assertEquals(FREE * Constants.KILOBYTES_TO_BYTES, stat.getFree()); + assertEquals(SWAP_FREE * Constants.KILOBYTES_TO_BYTES, stat.getSwapFree()); + assertEquals(SWAP_TOTAL * Constants.KILOBYTES_TO_BYTES, stat.getSwapTotal()); + assertEquals(TOTAL * Constants.KILOBYTES_TO_BYTES, stat.getTotal()); + assertTrue(stat.getTimeStamp() != 0 && stat.getTimeStamp() != Long.MIN_VALUE); + assertTrue(stat.getTimeStamp() <= System.currentTimeMillis()); + verify(dataSource).getMemInfoReader(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/NetworkInfoBuilderTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,67 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; + +import com.redhat.thermostat.common.model.NetworkInterfaceInfo; + +public class NetworkInfoBuilderTest { + + @Test + public void testBuilder() { + + List<NetworkInterfaceInfo> info = NetworkInfoBuilder.build(); + assertNotNull(info); + for (NetworkInterfaceInfo iface: info) { + assertNotNull(iface); + assertNotNull(iface.getInterfaceName()); + if (iface.getIp4Addr() != null) { + // ipv4 address matches the form XX.XX.XX.XX + assertTrue(iface.getIp4Addr().matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}")); + } + // TODO check for sane ipv6 address + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilderTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,134 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.Map; +import java.util.Random; + +import org.junit.Test; + +import com.redhat.thermostat.common.TestUtils; +import com.redhat.thermostat.utils.ProcDataSource; + +public class ProcessEnvironmentBuilderTest { + + private final Random r = new Random(); + + @Test + public void testBasicBuild() { + ProcDataSource dataSource = new ProcDataSource(); + Map<String, String> result = new ProcessEnvironmentBuilder(dataSource).build(TestUtils.getProcessId()); + assertNotNull(result); + assertFalse(result.isEmpty()); + assertTrue(result.containsKey("USER")); + } + + @Test + public void testCustomEnvironment() throws IOException { + byte[] data = ("USER=test\000HOME=house\000").getBytes(); + + Reader r = new InputStreamReader(new ByteArrayInputStream(data)); + ProcDataSource dataSource = mock(ProcDataSource.class); + when(dataSource.getEnvironReader(any(Integer.class))).thenReturn(r); + + Map<String, String> result = new ProcessEnvironmentBuilder(dataSource).build(0); + + verify(dataSource).getEnvironReader(eq(0)); + assertEquals("test", result.get("USER")); + assertEquals("house", result.get("HOME")); + } + + @Test + public void testLargeRandomEnvironment() throws IOException { + int TEST_ENV_SIZE = 1024 * 1024; + byte[] data = new byte[TEST_ENV_SIZE]; + int currentPosition = 0; + do { + byte[] key = generateRandomBytes(); + byte[] value = generateRandomBytes(); + if (currentPosition + key.length + value.length + 2 >= data.length) { + break; + } + System.arraycopy(key, 0, data, currentPosition, key.length); + currentPosition += key.length; + data[currentPosition] = (byte) '='; + currentPosition++; + System.arraycopy(value, 0, data, currentPosition, value.length); + currentPosition += value.length; + data[currentPosition] = 0x00; + currentPosition++; + } while (true); + Reader r = new InputStreamReader(new ByteArrayInputStream(data, 0, currentPosition)); + ProcDataSource dataSource = mock(ProcDataSource.class); + when(dataSource.getEnvironReader(any(Integer.class))).thenReturn(r); + + Map<String, String> result = new ProcessEnvironmentBuilder(dataSource).build(0); + + verify(dataSource).getEnvironReader(eq(0)); + assertNotNull(result); + } + + private byte[] generateRandomBytes() { + byte start = (byte) 'a'; + byte end = (byte) 'z' + 1; + + byte[] alphabet = new byte[end - start]; + for (int i = 0; i < (end-start); i++) { + alphabet[i] = (byte) (i + start); + } + int size = r.nextInt(15) + 10; + byte[] result = new byte[size]; + for (int i = 0; i < result.length; i++) { + result[i] = alphabet[r.nextInt(alphabet.length)]; + } + return result; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilderTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,142 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.io.StringReader; + +import org.junit.Test; + +import com.redhat.thermostat.utils.ProcDataSource; + +public class ProcessStatusInfoBuilderTest { + + @Test + public void testSimpleProcessStatus() { + ProcDataSource dataSource = new ProcDataSource(); + ProcessStatusInfo stat = new ProcessStatusInfoBuilder(dataSource).build(1); + assertNotNull(stat); + } + + @Test + public void testKnownProcessStatus() throws IOException { + final int PID = 10363; + String PROCESS_NAME = "(bash)"; + String STATE = "S"; + String PPID = "1737"; + String PROCESS_GROUP_ID = "10363"; + String SESSION_ID = "10363"; + String TTY_NUMBER = "34817"; + String TTY_PROCESS_GROUP_ID = "11404"; + String FLAGS_WORD = "4202496"; + String MINOR_FAULTS = "8093"; + String MINOR_FAULTS_CHILDREN = "607263"; + String MAJOR_FAULTS = "1"; + String MAJOR_FAULTS_CHILDREN = "251"; + final long USER_TIME_TICKS = 21; + final long KERNEL_TIME_TICKS = 7; + final long USER_TIME_CHILDREN = 10; + String KERNEL_TIME_CHILDREN = "1000"; + String PRIORITY = "20"; + String statString = "" + + PID + " " + PROCESS_NAME + " " + STATE + " " + PPID + " " + + PROCESS_GROUP_ID + " " + SESSION_ID + " " + TTY_NUMBER + " " + + TTY_PROCESS_GROUP_ID + " " + FLAGS_WORD + " " + MINOR_FAULTS + " " + + MINOR_FAULTS_CHILDREN + " " + MAJOR_FAULTS + " " + MAJOR_FAULTS_CHILDREN + " " + + USER_TIME_TICKS + " " + KERNEL_TIME_TICKS + " " + USER_TIME_CHILDREN + " " + + KERNEL_TIME_CHILDREN + " " + PRIORITY; + + ProcDataSource dataSource = mock(ProcDataSource.class); + when(dataSource.getStatReader(any(Integer.class))).thenReturn(new StringReader(statString)); + ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(dataSource); + ProcessStatusInfo stat = builder.build(PID); + + verify(dataSource).getStatReader(PID); + assertNotNull(stat); + assertEquals(PID, stat.getPid()); + assertEquals(USER_TIME_TICKS, stat.getUserTime()); + assertEquals(KERNEL_TIME_TICKS, stat.getKernelTime()); + } + + @Test + public void testBadProcessName() throws IOException { + final int PID = 10363; + String PROCESS_NAME = "(secretly-bad process sleep 10 20 ) 6)"; + String STATE = "S"; + String PPID = "1737"; + String PROCESS_GROUP_ID = "10363"; + String SESSION_ID = "10363"; + String TTY_NUMBER = "34817"; + String TTY_PROCESS_GROUP_ID = "11404"; + String FLAGS_WORD = "4202496"; + String MINOR_FAULTS = "8093"; + String MINOR_FAULTS_CHILDREN = "607263"; + String MAJOR_FAULTS = "1"; + String MAJOR_FAULTS_CHILDREN = "251"; + final long USER_TIME_TICKS = 21; + final long KERNEL_TIME_TICKS = 7; + final long USER_TIME_CHILDREN = 10; + String KERNEL_TIME_CHILDREN = "1000"; + String PRIORITY = "20"; + String statString = "" + + PID + " " + PROCESS_NAME + " " + STATE + " " + PPID + " " + + PROCESS_GROUP_ID + " " + SESSION_ID + " " + TTY_NUMBER + " " + + TTY_PROCESS_GROUP_ID + " " + FLAGS_WORD + " " + MINOR_FAULTS + " " + + MINOR_FAULTS_CHILDREN + " " + MAJOR_FAULTS + " " + MAJOR_FAULTS_CHILDREN + " " + + USER_TIME_TICKS + " " + KERNEL_TIME_TICKS + " " + USER_TIME_CHILDREN + " " + + KERNEL_TIME_CHILDREN + " " + PRIORITY; + + ProcDataSource dataSource = mock(ProcDataSource.class); + when(dataSource.getStatReader(any(Integer.class))).thenReturn(new StringReader(statString)); + ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(dataSource); + ProcessStatusInfo stat = builder.build(PID); + + verify(dataSource).getStatReader(PID); + assertNotNull(stat); + assertEquals(PID, stat.getPid()); + assertEquals(USER_TIME_TICKS, stat.getUserTime()); + assertEquals(KERNEL_TIME_TICKS, stat.getKernelTime()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/SysConfTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class SysConfTest { + + @Test + public void test() { + long ticksPerSecond = SysConf.getClockTicksPerSecond(); + assertTrue(ticksPerSecond >= 1); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,101 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.common.dao.CpuStatDAO; +import com.redhat.thermostat.common.dao.DAOFactory; +import com.redhat.thermostat.common.dao.HostInfoDAO; +import com.redhat.thermostat.common.dao.MemoryStatDAO; +import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO; +import com.redhat.thermostat.common.dao.VmCpuStatDAO; +import com.redhat.thermostat.common.storage.Storage; + +public class SystemBackendTest { + + private SystemBackend b; + + @Before + public void setUp() { + Storage s = mock(Storage.class); + CpuStatDAO cDAO = mock(CpuStatDAO.class); + HostInfoDAO hDAO = mock(HostInfoDAO.class); + MemoryStatDAO mDAO = mock(MemoryStatDAO.class); + VmCpuStatDAO vDAO = mock(VmCpuStatDAO.class); + NetworkInterfaceInfoDAO nDAO = mock(NetworkInterfaceInfoDAO.class); + DAOFactory df = mock(DAOFactory.class); + when(df.getStorage()).thenReturn(s); + when(df.getCpuStatDAO()).thenReturn(cDAO); + when(df.getHostInfoDAO()).thenReturn(hDAO); + when(df.getMemoryStatDAO()).thenReturn(mDAO); + when(df.getVmCpuStatDAO()).thenReturn(vDAO); + when(df.getNetworkInterfaceInfoDAO()).thenReturn(nDAO); + b = new SystemBackend(); + b.setDAOFactory(df); + } + + @Test + public void testBasicBackend() { + assertFalse(b.isActive()); + b.activate(); + assertTrue(b.isActive()); + b.deactivate(); + assertFalse(b.isActive()); + } + + @Test + public void testActivateTwice() { + b.activate(); + b.activate(); + assert(b.isActive()); + } + + @Test + public void testDeactiateWhenNotActive() { + b.deactivate(); + b.deactivate(); + assertFalse(b.isActive()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/VmCpuStatBuilderTest.java Fri Oct 19 21:58:18 2012 +0200 @@ -0,0 +1,168 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.backend.system; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Test; + +import com.redhat.thermostat.common.Clock; +import com.redhat.thermostat.common.model.VmCpuStat; +import com.redhat.thermostat.test.Bug; + +public class VmCpuStatBuilderTest { + + @Test + public void testBuilderKnowsNothing() { + Clock clock = mock(Clock.class); + ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class); + int cpuCount = 0; + long ticksPerSecond = 0; + VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, statusBuilder); + + assertFalse(builder.knowsAbout(0)); + assertFalse(builder.knowsAbout(1)); + assertFalse(builder.knowsAbout(Integer.MIN_VALUE)); + assertFalse(builder.knowsAbout(Integer.MAX_VALUE)); + + } + + @Test(expected = IllegalArgumentException.class) + public void testBuilderThrowsOnBuildOfUnknownPid() { + Clock clock = mock(Clock.class); + int cpuCount = 0; + long ticksPerSecond = 0; + ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class); + VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, statusBuilder); + builder.build(0); + } + + @Test + public void testBuildNullOnInsufficentInformation() { + int PID = 0; + int cpuCount = 0; + long ticksPerSecond = 0; + final long CLOCK1 = 10000; + final long CLOCK2 = 20000; + final ProcessStatusInfo initialInfo = new ProcessStatusInfo(PID, 1, 2); + final ProcessStatusInfo laterInfo = null; + + Clock clock = mock(Clock.class); + when(clock.getMonotonicTimeNanos()).thenReturn((long) (CLOCK1 * 1E6)).thenReturn((long) (CLOCK2 * 1E6)); + + ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class); + when(statusBuilder.build(any(Integer.class))).thenReturn(initialInfo).thenReturn(laterInfo).thenReturn(null); + + VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, statusBuilder); + + builder.learnAbout(PID); + assertEquals(null, builder.build(PID)); + } + + @Test + public void testSaneBuild() { + final int PID = 0; + + final int CPU_COUNT = 3; + + final long USER_INITIAL_TICKS = 1; + final long KERNEL_INITIAL_TICKS = 1; + + final long USER_LATER_TICKS = 10; + final long KERNEL_LATER_TICKS = 10; + + final long CLOCK1 = 10000; + final long CLOCK2 = 20000; + + final long TICKS_PER_SECOND = 100; + + final double CPU_LOAD_PERCENT = + 100.0 + * ((USER_LATER_TICKS + KERNEL_LATER_TICKS) - (USER_INITIAL_TICKS + KERNEL_INITIAL_TICKS)) + / TICKS_PER_SECOND + / ((CLOCK2 - CLOCK1) * 1E-3 /* millis to seconds */) + / CPU_COUNT; + + final ProcessStatusInfo initialInfo = new ProcessStatusInfo(PID, USER_INITIAL_TICKS, KERNEL_INITIAL_TICKS); + final ProcessStatusInfo laterInfo = new ProcessStatusInfo(PID, USER_LATER_TICKS, KERNEL_LATER_TICKS); + + Clock clock = mock(Clock.class); + when(clock.getRealTimeMillis()).thenReturn(CLOCK2); + when(clock.getMonotonicTimeNanos()).thenReturn((long) (CLOCK1 * 1E6)).thenReturn((long) (CLOCK2 * 1E6)); + + ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class); + when(statusBuilder.build(any(Integer.class))).thenReturn(initialInfo).thenReturn(laterInfo).thenReturn(null); + + VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, CPU_COUNT, TICKS_PER_SECOND, statusBuilder); + + builder.learnAbout(PID); + VmCpuStat stat = builder.build(PID); + + assertNotNull(stat); + assertEquals(PID, stat.getVmId()); + assertEquals(CLOCK2, stat.getTimeStamp()); + assertEquals(CPU_LOAD_PERCENT, stat.getCpuLoad(), 0.0001); + } + + @Bug(id="1051", + summary="Avoid exceptions when reading /proc/ for dead processes", + url="http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1051") + @Test + public void testNoExceptionForBuilderLearningAboutDeadProcess() { + Clock clock = mock(Clock.class); + when(clock.getMonotonicTimeNanos()).thenReturn((long) (10000 * 1E6)); + ProcessStatusInfoBuilder procBuilder = mock(ProcessStatusInfoBuilder.class); + // This thing returns null if the /proc entry goes away. Rather than try to + // 'guess' at a pid that will not be present during test, just mock this. + when(procBuilder.build(any(Integer.class))).thenReturn(null); + VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, 3, 100, procBuilder); + // If we can't handle a process' /proc entry disappearing, the next line + // will throw exception. If it does not, then we are okay. + try { + builder.learnAbout(0); + } catch (Exception e) { + // Shouldn't happen. + assertTrue(false); + } + } +}