Mercurial > hg > thermostat
changeset 2289:fa7923c23a0e
Add storage-populator command
Reviewed-by: jerboaa, neugens, omajid
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-April/018609.html
line wrap: on
line diff
--- a/dev/data-populator/example-configs/population-config-example-simple-threads.json Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -{ - "records": [ - { - "name": "agent-config", - "number": 2, - "alive": 2 - }, - { - "name": "host-info", - "number": 1 - }, - { - "name": "vm-thread-harvesting", - "number": 5 - }, - { - "name": "vm-info", - "number": 5, - "alive": 5 - }, - { - "name": "network-info", - "number": 20 - } - ], - - "relationships": [ - { - "from": "agent-config", - "to": "vm-info", - "key": "agentId" - }, - { - "from": "agent-config", - "to": "host-info", - "key": "agentId" - }, - { - "from": "agent-config", - "to": "network-info", - "key": "agentId" - }, - { - "from": "agent-config", - "to": "vm-thread-harvesting", - "key": "agentId" - }, - { - "from": "vm-info", - "to": "vm-thread-harvesting", - "key": "vmId" - } - ] -}
--- a/dev/data-populator/example-configs/population-config-example-simple-vm-deadlock.json Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -{ - "records": [ - { - "name": "agent-config", - "number": 2, - "alive": 2 - }, - { - "name": "host-info", - "number": 1 - }, - { - "name": "vm-deadlock-data", - "number": 2 - }, - { - "name": "vm-info", - "number": 5, - "alive": 5 - }, - { - "name": "network-info", - "number": 20 - } - ], - - "relationships": [ - { - "from": "agent-config", - "to": "vm-info", - "key": "agentId" - }, - { - "from": "agent-config", - "to": "host-info", - "key": "agentId" - }, - { - "from": "agent-config", - "to": "network-info", - "key": "agentId" - }, - { - "from": "agent-config", - "to": "vm-deadlock-data", - "key": "agentId" - }, - { - "from": "vm-info", - "to": "vm-deadlock-data", - "key": "vmId" - } - ] -}
--- a/dev/data-populator/example-configs/population-config-example-simple.json Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -{ - "records": [ - { - "name": "agent-config", - "number": 100, - "alive": 20 - }, - { - "name": "host-info", - "number": 1 - }, - { - "name": "vm-info", - "number": 50, - "alive": 40 - }, - { - "name": "network-info", - "number": 50 - } - ], - - "relationships": [ - { - "from": "agent-config", - "to": "vm-info", - "key": "agentId" - }, - { - "from": "agent-config", - "to": "host-info", - "key": "agentId" - }, - { - "from": "agent-config", - "to": "network-info", - "key": "agentId" - } - ] -}
--- a/dev/data-populator/pom.xml Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - - Copyright 2012-2016 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-devel-modules</artifactId> - <version>1.99.10-SNAPSHOT</version> - </parent> - - <artifactId>thermostat-data-populator</artifactId> - - <packaging>jar</packaging> - <description> - This is a tool for Thermostat developers alowing them - to get a pre-populated DB. It may be useful for: - - reproducing bugs. - - do performance tests (on fixed DB contents). - - development: It can be an aid for writing client bits - before the agent backend is available. - Main entry-point is the populate script. - After a build do: - ./dev/data-populator/target/populate - </description> - - <name>Thermostat Data Populator</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-annotations</artifactId> - <version>${project.version}</version> - <scope>test</scope> - </dependency> - - <dependency> - <groupId>com.google.code.gson</groupId> - <artifactId>gson</artifactId> - <version>${gson.version}</version> - </dependency> - - <dependency> - <groupId>com.redhat.thermostat</groupId> - <artifactId>thermostat-storage-mongodb</artifactId> - <version>${project.version}</version> - </dependency> - - <dependency> - <groupId>com.redhat.thermostat</groupId> - <artifactId>thermostat-thread-collector</artifactId> - <version>${project.version}</version> - </dependency> - </dependencies> - - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - <configuration> - <archive> - <manifest> - <addClasspath>true</addClasspath> - <mainClass>com.redhat.thermostat.dev.populator.Main</mainClass> - </manifest> - </archive> - </configuration> - </plugin> - <plugin> - <artifactId>maven-resources-plugin</artifactId> - <executions> - <execution> - <id>copy-scripts</id> - <phase>prepare-package</phase> - <goals> - <goal>copy-resources</goal> - </goals> - <configuration> - <outputDirectory>${project.build.directory}</outputDirectory> - <resources> - <resource> - <directory>scripts</directory> - <filtering>true</filtering> - </resource> - </resources> - </configuration> - </execution> - </executions> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-antrun-plugin</artifactId> - <executions> - <execution> - <id>chmod</id> - <phase>prepare-package</phase> - <configuration> - <target> - <chmod file="${project.build.directory}/populate" perm="755" /> - </target> - </configuration> - <goals> - <goal>run</goal> - </goals> - </execution> - </executions> - </plugin> - </plugins> - </build> - -</project> -
--- a/dev/data-populator/scripts/populate Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -#!/bin/bash -JAVA=@thermostat.jdk.home@/bin/java -THERMOSTAT_HOME=@thermostat.home@ -LIBS=$THERMOSTAT_HOME/libs -PLUGINS=$THERMOSTAT_HOME/plugins -CP="$LIBS/thermostat-storage-mongodb-@project.version@.jar" -CP="$CP:$LIBS/thermostat-storage-core-@project.version@.jar" -CP="$CP:$LIBS/thermostat-shared-config-@project.version@.jar" -CP="$CP:$LIBS/thermostat-common-core-@project.version@.jar" -CP="$CP:$LIBS/thermostat-annotations-@project.version@.jar" -CP="$CP:$LIBS/thermostat-launcher-@project.version@.jar" -CP="$CP:$LIBS/mongo-java-driver-@mongo-driver.version@.jar" -CP="$CP:$LIBS/gson-@gson.version@.jar" -CP="$CP:$LIBS/commons-beanutils-@commons-beanutils.version@.jar" -CP="$CP:$LIBS/commons-logging-@commons-logging.version@.jar" -CP="$CP:$PLUGINS/thread/thermostat-thread-collector-@project.version@.jar" -CP="$CP:@project.build.directory@/thermostat-data-populator-@project.version@.jar" -$JAVA -cp $CP \ - -DTHERMOSTAT_HOME=$THERMOSTAT_HOME \ - -DUSER_THERMOSTAT_HOME=@project.build.directory@ \ - com.redhat.thermostat.dev.populator.Main \ - $@
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/Arguments.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator; - -import java.util.HashMap; -import java.util.Map; - -class Arguments { - - private static final String OPTIONS_PREFIX = "--"; - private static final String DB_URL_NAME = "dbUrl"; - private static final String USERNAME_NAME = "username"; - private static final String PASSWORD_NAME = "password"; - private static final String CONFIG_FILE_NAME = "config"; - - private final Map<String, String> args; - - private Arguments() { - args = new HashMap<>(); - } - - public String getDbUrl() { - return args.get(DB_URL_NAME); - } - - public String getUsername() { - return args.get(USERNAME_NAME); - } - - public String getPassword() { - return args.get(PASSWORD_NAME); - } - - public String getConfigFile() { - return args.get(CONFIG_FILE_NAME); - } - - private void addArgument(String name, String value) { - args.put(name, value); - } - - private void validate() throws IllegalArgumentException { - if (args.size() != 4) { - throw new IllegalStateException(); - } - if (args.get(DB_URL_NAME) == null || - args.get(PASSWORD_NAME) == null || - args.get(USERNAME_NAME) == null || - args.get(CONFIG_FILE_NAME) == null) { - throw new IllegalStateException(); - } - } - - static Arguments processArguments(String[] args) throws IllegalArgumentException { - if (args.length != 8) { - throw new IllegalArgumentException("missing required arguments"); - } - Arguments myArgs = new Arguments(); - for (int i = 0; i < args.length - 1; i += 2) { - String optionName = args[i]; - String optionValue = args[i+1]; - if (!optionName.startsWith(OPTIONS_PREFIX)) { - throw new IllegalArgumentException(); - } else { - if (optionValue.startsWith(OPTIONS_PREFIX)) { - throw new IllegalArgumentException(); - } - myArgs.addArgument(optionName.substring(OPTIONS_PREFIX.length()), optionValue); - } - } - try { - myArgs.validate(); - } catch (IllegalStateException e) { - throw new IllegalArgumentException("Missing required arguments"); - } - return myArgs; - } - -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/CollectionPopulator.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator; - -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.dependencies.SharedState; -import com.redhat.thermostat.storage.core.Storage; - -public interface CollectionPopulator { - - SharedState addPojos(Storage storage, ConfigItem item, SharedState relState); - - String getHandledCollection(); -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/ConnectionEstablisher.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator; - -import java.util.concurrent.CountDownLatch; - -import com.redhat.thermostat.shared.config.internal.CommonPathsImpl; -import com.redhat.thermostat.shared.config.internal.SSLConfigurationImpl; -import com.redhat.thermostat.storage.core.Connection; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.core.StorageCredentials; -import com.redhat.thermostat.storage.core.Connection.ConnectionStatus; -import com.redhat.thermostat.storage.mongodb.MongoStorageProvider; - -class ConnectionEstablisher { - - private final Arguments args; - - ConnectionEstablisher(Arguments args) { - this.args = args; - } - - Storage connectToStorage() { - MongoStorageProvider provider = new MongoStorageProvider(); - StorageCredentials creds = getStorageCredentialsFromArgs(args); - provider.setConfig(args.getDbUrl(), creds, new SSLConfigurationImpl(new CommonPathsImpl())); - Storage storage = provider.createStorage(); - Connection conn = storage.getConnection(); - final CountDownLatch latch = new CountDownLatch(1); - conn.addListener(new Connection.ConnectionListener() { - - @Override - public void changed(ConnectionStatus newStatus) { - switch (newStatus) { - case CONNECTED: // fall-through - case FAILED_TO_CONNECT: - latch.countDown(); - break; - default: - // nothing - } - } - }); - conn.connect(); - try { - latch.await(); - } catch (InterruptedException e) { - throw new RuntimeException("Storage connection interrupted"); - } - return storage; - } - - private StorageCredentials getStorageCredentialsFromArgs(final Arguments args) { - return new StorageCredentials() { - - @Override - public String getUsername() { - return args.getUsername(); - } - - @Override - public char[] getPassword() { - return args.getPassword().toCharArray(); - } - }; - } -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/Main.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator; - -public class Main { - - public static void main(String[] args) { - Arguments processedArgs = null; - try { - processedArgs = Arguments.processArguments(args); - } catch (IllegalArgumentException e) { - System.err.println("Error parsing arguments."); - e.printStackTrace(System.err); - printUsageAndExit(); - } - StoragePopulator populator = new StoragePopulator(processedArgs); - populator.populate(); - System.exit(0); - } - - private static void printUsageAndExit() { - System.err.println("Usage: populate --dbUrl <URL> --username <username> --password <password> --config path/to/population-config/file"); - System.err.println(); - System.err.println("Example (after thermostat-devsetup + 'thermostat storage --start'):"); - System.err.println("populate --dbUrl mongodb://127.0.0.1:27518 --username mongodevuser --password mongodevpassword --config dev/data-populator/example-configs/population-config-example-simple.json"); - System.exit(1); - } - -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/StoragePopulator.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.HashMap; -import java.util.Map; -import java.util.ServiceLoader; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.config.PopulationConfig; -import com.redhat.thermostat.dev.populator.dependencies.SharedState; -import com.redhat.thermostat.storage.core.Connection; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.core.Connection.ConnectionStatus; - -class StoragePopulator { - - private final Arguments args; - private final Map<String, CollectionPopulator> pojoPutters; - - StoragePopulator(Arguments args) { - this.args = args; - pojoPutters = getPopulatorsFromServiceLoader(); - } - - private static Map<String, CollectionPopulator> getPopulatorsFromServiceLoader() { - ServiceLoader<CollectionPopulator> loader = ServiceLoader.load(CollectionPopulator.class); - Map<String, CollectionPopulator> populators = new HashMap<>(); - for (CollectionPopulator putter: loader) { - populators.put(putter.getHandledCollection(), putter); - } - return populators; - } - - public void populate() { - PopulationConfig config = getPopulationConfigFromArg(); - Storage storage = connectToStorage(); - addItemsToStorage(storage, config); - disconnectStorage(storage); - System.out.println("Data population finished successfully."); - } - - private void disconnectStorage(Storage storage) { - Connection conn = storage.getConnection(); - final CountDownLatch latch = new CountDownLatch(1); - conn.addListener(new Connection.ConnectionListener() { - - @Override - public void changed(ConnectionStatus newStatus) { - switch (newStatus) { - case DISCONNECTED: - latch.countDown(); - default: - break; - } - - } - }); - conn.disconnect(); - try { - boolean expired = !latch.await(100, TimeUnit.MILLISECONDS); - if (expired) { - System.err.println("Timeout waiting for storage to disconnect."); - } - } catch (InterruptedException e) { - // ignore - } - } - - private PopulationConfig getPopulationConfigFromArg() { - File configFile = new File(args.getConfigFile()); - if (!configFile.exists()) { - throw new IllegalArgumentException("Config file '" + configFile.getAbsolutePath() + "' does not exist!"); - } - String json; - PopulationConfig config; - try { - json = new String(Files.readAllBytes(configFile.toPath())); - config = PopulationConfig.parseFromJsonString(json); - } catch (IOException e) { - throw new IllegalArgumentException("Failed to parse config file", e); - } - return config; - } - - /** - * Add items to storage in topologically sorted order so as to have - * relevant depending state available. - * - * @param storage The storage to add records for - * @param config The configuration describing the records to be added - */ - private void addItemsToStorage(Storage storage, PopulationConfig config) { - SharedState state = new SharedState(); - for (ConfigItem item: config.getConfigsTopologicallySorted()) { - state = addRecordsForConfig(storage, item, state); - } - } - - private SharedState addRecordsForConfig(Storage storage, ConfigItem item, SharedState state) { - CollectionPopulator putter = pojoPutters.get(item.getName()); - if (putter == null) { - System.err.println("No populator for collection '" + item.getName() + "' found. Skipping."); - return state; // return state unmodified - } else { - return putter.addPojos(storage, item, state); - } - } - - private Storage connectToStorage() { - ConnectionEstablisher establisher = new ConnectionEstablisher(args); - return establisher.connectToStorage(); - } -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/config/ConfigItem.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.config; - -public class ConfigItem { - - public static final String NAME = "name"; - public static final String NUMBER = "number"; - public static final String ALIVE = "alive"; - - public static final int UNSET = -1; - private final int number; - private final int aliveItems; - private final String name; - - public ConfigItem(int number, int aliveItems, String name) { - this.number = number; - this.aliveItems = aliveItems; - this.name = name; - } - - public int getNumber() { - return number; - } - - public int getAliveItems() { - return aliveItems; - } - - public String getName() { - return name; - } - - @Override - public String toString() { - return name + " (" + number + "/" + aliveItems + ")"; - } -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/config/PopulationConfig.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,228 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.config; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.redhat.thermostat.dev.populator.config.typeadapter.ConfigItemTypeAdapter; -import com.redhat.thermostat.dev.populator.config.typeadapter.PopulationConfigTypeAdapterFactory; -import com.redhat.thermostat.dev.populator.config.typeadapter.RelationShipTypeAdapter; -import com.redhat.thermostat.dev.populator.dependencies.Relationship; - -public class PopulationConfig { - - public static final String RECORDS = "records"; - public static final String RELATIONSHIPS = "relationships"; - private final Map<String, ConfigItem> configs; - private final List<ConfigItem> allConfigs; - private final Map<String, List<Relationship>> incomingRelationShips; - private final Map<String, List<Relationship>> outgoingRelationShips; - - private PopulationConfig() { - configs = new HashMap<>(); - allConfigs = new ArrayList<>(); - incomingRelationShips = new HashMap<>(); - outgoingRelationShips = new HashMap<>(); - } - - public ConfigItem getConfig(String name) { - return configs.get(name); - } - - public List<ConfigItem> getConfigsTopologicallySorted() { - return topologicallySort(allConfigs); - } - - /** - * Sort config items topologically. That is, get them in an order so as - * to process collections with no incoming links to other collections. - * - * It uses Kahn's algorithm to do so. - * - * @param configs unsorted configs. - * @return A topologically sorted list. - */ - private List<ConfigItem> topologicallySort(List<ConfigItem> configs) { - LinkedList<ConfigItem> sortedList = new LinkedList<>(); - LinkedList<ConfigItem> queue = getConfigItemsWithNoIncomingEdge(configs); - while (!queue.isEmpty()) { - ConfigItem n = queue.remove(0); - sortedList.addLast(n); - List<Relationship> source = getOutgoingRelationShipsForConfig(n); - List<Relationship> outgoingRels = new LinkedList<>(source); - for (Relationship edge: outgoingRels) { - ConfigItem m = getConfig(edge.getTo()); - removeEdge(edge, n, m); - if (hasNoIncomingEdge(m)) { - queue.addLast(m); - } - } - } - if (hasRelationShips(configs)) { - throw new AssertionError("Relationships form at least one cycle! Excpected an acyclic directed graph."); - } - return sortedList; - } - - private boolean hasRelationShips(List<ConfigItem> configs) { - for (ConfigItem i: configs) { - List<Relationship> incoming = getIncomingRelationShipsForConfig(i); - List<Relationship> outgoing = getOutgoingRelationShipsForConfig(i); - if (!incoming.isEmpty() || - !outgoing.isEmpty()) { - // We are going to bomb, print some debug info. - System.err.println("outgoings for " + i.getName() + " " + outgoing); - System.err.println("incomings for " + i.getName() + " " + incoming); - return true; - } - } - return false; - } - - private void removeEdge(Relationship toRemove, ConfigItem from, ConfigItem to) { - if (from == null || to == null) { - throw new InvalidConfigurationException("Found relationship [" + - toRemove + - "] but either incoming or outgoing records config is missing"); - } - List<Relationship> incoming = getIncomingRelationShipsForConfig(to); - List<Relationship> outgoing = getOutgoingRelationShipsForConfig(from); - incoming.remove(toRemove); - outgoing.remove(toRemove); - } - - private LinkedList<ConfigItem> getConfigItemsWithNoIncomingEdge(List<ConfigItem> allConfigs) { - LinkedList<ConfigItem> startNodes = new LinkedList<>(); - for (ConfigItem item: allConfigs) { - if (hasNoIncomingEdge(item)) { - startNodes.add(item); - } - } - return startNodes; - } - - private boolean hasNoIncomingEdge(ConfigItem item) { - List<Relationship> rels = getIncomingRelationShipsForConfig(item); - if (rels == null || rels.isEmpty()) { - return true; - } - return false; - } - - private List<Relationship> getIncomingRelationShipsForConfig(ConfigItem item) { - List<Relationship> result = incomingRelationShips.get(item.getName()); - if (result == null) { - return Collections.emptyList(); - } - return result; - } - - private List<Relationship> getOutgoingRelationShipsForConfig(ConfigItem item) { - List<Relationship> result = outgoingRelationShips.get(item.getName()); - if (result == null) { - return Collections.emptyList(); - } - return result; - } - - private void addConfig(ConfigItem item) { - configs.put(item.getName(), item); - allConfigs.add(item); - } - - private void addIncomingRelationShipForConfig(ConfigItem item, Relationship relationship) { - addRelationShip(item, relationship, incomingRelationShips); - } - - private void addOutgoingRelationShipForConfig(ConfigItem item, Relationship relationship) { - addRelationShip(item, relationship, outgoingRelationShips); - } - - private void addRelationShip(ConfigItem item, Relationship relationship, Map<String, List<Relationship>> map) { - List<Relationship> existingRels = map.get(item.getName()); - if (existingRels == null) { - existingRels = new LinkedList<>(); - map.put(item.getName(), existingRels); - } - existingRels.add(relationship); - } - - public static PopulationConfig parseFromJsonString(String json) throws IOException { - Gson gson= new GsonBuilder() - .registerTypeAdapter(ConfigItem.class, new ConfigItemTypeAdapter()) - .registerTypeAdapter(Relationship.class, new RelationShipTypeAdapter()) - .registerTypeAdapterFactory(new PopulationConfigTypeAdapterFactory()) - .create(); - PopulationConfig pc = gson.fromJson(json, PopulationConfig.class); - return pc; - } - - public static PopulationConfig createFromLists(List<ConfigItem> items, List<Relationship> rels) { - PopulationConfig pc = new PopulationConfig(); - for (ConfigItem item: items) { - pc.addConfig(item); - for (Relationship r: rels) { - // keep track of incoming relationships (incoming edge) - if (r.getTo().equals(item.getName())) { - pc.addIncomingRelationShipForConfig(item, r); - } - // keep track of outgoing relationships (outgoing edge) - if (r.getFrom().equals(item.getName())) { - pc.addOutgoingRelationShipForConfig(item, r); - } - } - } - return pc; - } - - @SuppressWarnings("serial") - static class InvalidConfigurationException extends RuntimeException { - - private InvalidConfigurationException(String msg) { - super(msg); - } - - } -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/config/typeadapter/ConfigItemTypeAdapter.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.config.typeadapter; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import com.google.gson.TypeAdapter; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; -import com.redhat.thermostat.dev.populator.config.ConfigItem; - -public class ConfigItemTypeAdapter extends TypeAdapter<ConfigItem> { - - @Override - public ConfigItem read(JsonReader reader) throws IOException { - // handle null - if (reader.peek() == JsonToken.NULL) { - reader.nextNull(); - return null; - } - - reader.beginObject(); - ConfigItem item = parseConfigItem(reader); - reader.endObject(); - - return item; - } - - private ConfigItem parseConfigItem(JsonReader reader) throws IOException { - Map<String, Object> values = new HashMap<>(); - while (reader.hasNext()) { - String name = reader.nextName(); - switch(name) { - case ConfigItem.NAME: - values.put(ConfigItem.NAME, reader.nextString()); - break; - case ConfigItem.ALIVE: - values.put(ConfigItem.ALIVE, reader.nextInt()); - break; - case ConfigItem.NUMBER: - values.put(ConfigItem.NUMBER, reader.nextInt()); - break; - default: - throw new IllegalStateException("Unknown config value: '" + name + "'"); - } - } - String collName = (String)values.get(ConfigItem.NAME); - String collectionDetails = collName == null ? "" : "[" + collName + "] "; - Integer number = (Integer)values.get(ConfigItem.NUMBER); - Integer aliveItems = (Integer)values.get(ConfigItem.ALIVE); - int aliveItemsForSanityTest = getAliveCount(aliveItems); - if (number < 0 || aliveItemsForSanityTest < 0) { - throw new IllegalArgumentException(collectionDetails + "number of items and alive items must be positive"); - } - if (number - aliveItemsForSanityTest < 0) { - throw new IllegalArgumentException(collectionDetails + "alive items > number of total items."); - } - return new ConfigItem(getValue(number), getValue(aliveItems), collName); - } - - private int getAliveCount(Integer aliveItems) { - if (aliveItems != null) { - return aliveItems; - } - return 0; // return 0 for unset, just so that we make sanity checks happy - } - - private int getValue(Integer value) { - return value == null ? ConfigItem.UNSET : value; - } - - @Override - public void write(JsonWriter writer, ConfigItem item) throws IOException { - throw new NotImplementedException(); - } -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/config/typeadapter/NotImplementedException.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.config.typeadapter; - -@SuppressWarnings("serial") -class NotImplementedException extends RuntimeException { - // nothing -} \ No newline at end of file
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/config/typeadapter/PopulationConfigTypeAdapter.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.config.typeadapter; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.google.gson.Gson; -import com.google.gson.TypeAdapter; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.config.PopulationConfig; -import com.redhat.thermostat.dev.populator.dependencies.Relationship; - -public class PopulationConfigTypeAdapter extends TypeAdapter<PopulationConfig> { - - private final Gson gson; - - public PopulationConfigTypeAdapter(Gson gson) { - this.gson = gson; - } - - @Override - public void write(JsonWriter out, PopulationConfig config) throws IOException { - throw new NotImplementedException(); - } - - @Override - public PopulationConfig read(JsonReader in) throws IOException { - // handle null - if (in.peek() == JsonToken.NULL) { - in.nextNull(); - return null; - } - in.beginObject(); - PopulationConfig config = parsePopulationConfig(in); - in.endObject(); - return config; - } - - private PopulationConfig parsePopulationConfig(JsonReader in) throws IOException { - Map<String, Object> values = new HashMap<>(); - while (in.hasNext()) { - String name = in.nextName(); - switch(name) { - case PopulationConfig.RECORDS: - values.put(PopulationConfig.RECORDS, parseRecords(in)); - break; - case PopulationConfig.RELATIONSHIPS: - values.put(PopulationConfig.RELATIONSHIPS, parseRelationships(in)); - break; - default: - throw new IllegalStateException("Unknown population config value: '" + name + "'"); - } - } - ConfigItem[] rawItems = (ConfigItem[])values.get(PopulationConfig.RECORDS); - Relationship[] rawRels = (Relationship[])values.get(PopulationConfig.RELATIONSHIPS); - List<Relationship> rels; - if (rawRels == null) { - rels = Collections.emptyList(); - } else { - rels = Arrays.asList(rawRels); - } - return PopulationConfig.createFromLists(Arrays.asList(rawItems), rels); - } - - private Relationship[] parseRelationships(JsonReader in) { - return gson.fromJson(in, Relationship[].class); - } - - private ConfigItem[] parseRecords(JsonReader in) throws IOException { - return gson.fromJson(in, ConfigItem[].class); - } - -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/config/typeadapter/PopulationConfigTypeAdapterFactory.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.config.typeadapter; - -import com.google.gson.Gson; -import com.google.gson.TypeAdapter; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.reflect.TypeToken; -import com.redhat.thermostat.dev.populator.config.PopulationConfig; - -public class PopulationConfigTypeAdapterFactory implements TypeAdapterFactory { - - @Override - public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { - Class<?> rawType = type.getRawType(); - if (rawType == PopulationConfig.class) { - @SuppressWarnings("unchecked") - TypeAdapter<T> ta = (TypeAdapter<T>)new PopulationConfigTypeAdapter(gson); - return ta; - } - return null; - } - -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/config/typeadapter/RelationShipTypeAdapter.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.config.typeadapter; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import com.google.gson.TypeAdapter; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; -import com.redhat.thermostat.dev.populator.dependencies.Relationship; - -public class RelationShipTypeAdapter extends TypeAdapter<Relationship> { - - @Override - public Relationship read(JsonReader in) throws IOException { - // handle null - if (in.peek() == JsonToken.NULL) { - in.nextNull(); - return null; - } - - in.beginObject(); - Relationship rel = parseRelationShip(in); - in.endObject(); - - return rel; - } - - private Relationship parseRelationShip(JsonReader in) throws IOException { - Map<String, String> values = new HashMap<>(); - while (in.hasNext()) { - String name = in.nextName(); - switch(name) { - case Relationship.FROM: - values.put(Relationship.FROM, in.nextString()); - break; - case Relationship.TO: - values.put(Relationship.TO, in.nextString()); - break; - case Relationship.KEY: - values.put(Relationship.KEY, in.nextString()); - break; - default: - throw new IllegalStateException("Unknown relationship value: '" + name + "'"); - } - } - return new Relationship(values.get(Relationship.FROM), values.get(Relationship.TO), values.get(Relationship.KEY)); - } - - @Override - public void write(JsonWriter out, Relationship relationship) throws IOException { - throw new NotImplementedException(); - } - -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/dependencies/ProcessedRecords.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.dependencies; - -import java.util.List; - -/** - * - * @param <T> The underlying type of the key - */ -public class ProcessedRecords<T> { - - private final List<T> allRecords; - - public ProcessedRecords(List<T> allRecords) { - this.allRecords = allRecords; - } - - public List<T> getAll() { - return allRecords; - } -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/dependencies/Relationship.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.dependencies; - -import java.util.Objects; - -public class Relationship { - - public static final String TO = "to"; - public static final String FROM = "from"; - public static final String KEY = "key"; - private final String from; - private final String to; - private final String key; - - public Relationship(String from, String to, String key) { - this.from = from; - this.to = to; - this.key = key; - } - - public String getFrom() { - return from; - } - - public String getTo() { - return to; - } - - public String getKey() { - return key; - } - - @Override - public boolean equals(Object o) { - if (o == null || o.getClass() != Relationship.class) { - return false; - } - Relationship other = (Relationship)o; - return Objects.equals(to, other.to) && - Objects.equals(from, other.from) && - Objects.equals(key, other.key); - } - - @Override - public int hashCode() { - return Objects.hash(to, from, key); - } - - @Override - public String toString() { - return from + " -> " + to + "(" + key + ")"; - } -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/dependencies/SharedState.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.dependencies; - -import java.util.HashMap; -import java.util.Map; - -public class SharedState { - - private final Map<Object, ProcessedRecords<?>> processedRecs; - private final Map<String, Object> props; - - public SharedState() { - processedRecs = new HashMap<>(); - props = new HashMap<>(); - } - - public <T> ProcessedRecords<T> getProcessedRecordsFor(T key) { - @SuppressWarnings("unchecked") - ProcessedRecords<T> item = (ProcessedRecords<T>)processedRecs.get(key); - return item; - } - - public <T> void addProcessedRecords(T key, ProcessedRecords<T> recs) { - processedRecs.put(key, recs); - } - - public void addProperty(String key, Object value) { - props.put(key, value); - } - - public Object getProperty(String key) { - return props.get(key); - } -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/internal/AgentInfoPopulator.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.internal; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.dependencies.ProcessedRecords; -import com.redhat.thermostat.dev.populator.dependencies.SharedState; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.internal.dao.AgentInfoDAOImpl; -import com.redhat.thermostat.storage.model.AgentInformation; - -public class AgentInfoPopulator extends BasePopulator { - - private final AgentInfoDAO dao; - - public AgentInfoPopulator() { - this(null); - } - - // for testing - AgentInfoPopulator(AgentInfoDAO dao) { - this.dao = dao; - } - - @Override - public SharedState addPojos(Storage storage, ConfigItem item, SharedState state) { - // Default to all alive, if unset - int aliveItems = item.getAliveItems() == ConfigItem.UNSET ? item.getNumber() : item.getAliveItems(); - List<String> processedRecords = new ArrayList<>(); - AgentInfoDAO agentInfoDao = getDao(storage); - long currentTime = System.currentTimeMillis(); - long countBefore = agentInfoDao.getCount(); - System.out.println("Populating "+ item.getNumber() + " " + item.getName() + " records"); - for (int i = 0; i < item.getNumber(); i++) { - AgentInformation agentInfo = new AgentInformation(); - String agentId = UUID.randomUUID().toString(); - processedRecords.add(agentId); - agentInfo.setAgentId(agentId); - agentInfo.setAlive(getAliveValue(aliveItems, i)); - agentInfo.setConfigListenAddress(String.format("127.0.0.1:%d", i)); - agentInfo.setStartTime(currentTime); - agentInfoDao.addAgentInformation(agentInfo); - reportProgress(item, i); - } - doWaitUntilCount(agentInfoDao, countBefore + item.getNumber()); - state.addProcessedRecords("agentId", new ProcessedRecords<>(processedRecords)); - // FIXME: Why does HostInfoDAOImpl need AgentInfoDAO? See HostInfoPopulator - state.addProperty("agent-info-dao", agentInfoDao); - return state; - } - - private boolean getAliveValue(int aliveItems, int i) { - if (i < aliveItems) { - return true; - } else { - return false; - } - } - - private AgentInfoDAO getDao(Storage storage) { - if (dao == null) { - return new AgentInfoDAOImpl(storage); - } else { - return dao; - } - } - - @Override - public String getHandledCollection() { - return AgentInfoDAO.CATEGORY.getName(); - } - -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/internal/BasePopulator.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.internal; - -import com.redhat.thermostat.dev.populator.CollectionPopulator; -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.storage.core.Countable; - -public abstract class BasePopulator implements CollectionPopulator { - - protected void doWaitUntilCount(Countable countable, long expectedCount) { - System.out.print("Waiting for storage items to arrive at backend..."); - long currCount = countable.getCount(); - while (currCount != expectedCount) { - try { - Thread.sleep(200); - System.out.print("."); // report some progress - } catch (InterruptedException e) { - // ignore - } - currCount = countable.getCount(); - } - System.out.println(" Done."); - } - - protected void reportProgress(ConfigItem item, int currCount) { - if (currCount > 0 && currCount % 10 == 0) { - System.out.println("Submitted " + currCount + " " + item.getName() + " records to storage."); - } - } -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/internal/HostInfoPopulator.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.internal; - -import java.util.List; -import java.util.Objects; - -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.dependencies.SharedState; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.dao.HostInfoDAO; -import com.redhat.thermostat.storage.internal.dao.HostInfoDAOImpl; -import com.redhat.thermostat.storage.model.HostInfo; - -public class HostInfoPopulator extends BasePopulator { - - private static final String[] HOSTS_FORMAT = new String[] { - "vm-host-%06d", "prometheus-%06d", "saturn-%06d" - }; - private static final String DOMAIN_FORMAT = "domain-%06d"; - private static final String HOSTNAME_SUFFIX = "example.com"; - private static final long MB = 1024 * 1024; - private final HostInfoDAO dao; - - public HostInfoPopulator() { - this(null); - } - - HostInfoPopulator(HostInfoDAO dao) { - this.dao = dao; - } - - @Override - public SharedState addPojos(Storage storage, ConfigItem item, SharedState relState) { - // FIXME: We need the same instance of the AgentInfoDAO due to the register-category quirk. - AgentInfoDAO agentInfoDAO = Objects.requireNonNull((AgentInfoDAO)relState.getProperty("agent-info-dao")); - HostInfoDAO hostDAO = getDao(storage, agentInfoDAO); - List<String> agentIds = relState.getProcessedRecordsFor("agentId").getAll(); - int totalItems = agentIds.size(); - int currCount = 0; - long countBefore = hostDAO.getCount(); - System.out.println("Populating "+ totalItems + " " + item.getName() + " records"); - // There is a 1-to-1 correspondance between host-info and agents - for (int i = agentIds.size() - 1; i >= 0; i--) { - String agentId = agentIds.get(i); - HostInfo info = new HostInfo(); - info.setAgentId(agentId); - info.setCpuCount(getRandomInt(50 + i)); - info.setCpuModel("x86_64, data populator"); - info.setHostname(getRandomHostName(i)); - info.setOsKernel("4.2.3 data populator"); - info.setOsName("Linux Random Flavor"); - int memory = getRandomInt(500 + i); - info.setTotalMemory(memory * MB); - hostDAO.putHostInfo(info); - reportProgress(item, currCount); - currCount++; - } - doWaitUntilCount(hostDAO, countBefore + totalItems); - return relState; - } - - private String getRandomHostName(int i) { - int index = getRandomInt(HOSTS_FORMAT.length); - String hostFormat = HOSTS_FORMAT[index] + "." + DOMAIN_FORMAT + "." + HOSTNAME_SUFFIX; - return String.format(hostFormat, i, i); - } - - private int getRandomInt(int i) { - return (int)(Math.random() * i); - } - - @Override - public String getHandledCollection() { - return HostInfoDAO.hostInfoCategory.getName(); - } - - // hook for testing - private HostInfoDAO getDao(Storage storage, AgentInfoDAO agentInfoDAO) { - if (dao == null) { - return new HostInfoDAOImpl(storage, agentInfoDAO); - } else { - return dao; - } - } - -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/internal/NetworkInfoPopulator.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,189 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.internal; - -import java.util.List; - -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.dependencies.ProcessedRecords; -import com.redhat.thermostat.dev.populator.dependencies.SharedState; -import com.redhat.thermostat.storage.core.Category; -import com.redhat.thermostat.storage.core.CategoryAdapter; -import com.redhat.thermostat.storage.core.Countable; -import com.redhat.thermostat.storage.core.Cursor; -import com.redhat.thermostat.storage.core.DescriptorParsingException; -import com.redhat.thermostat.storage.core.PreparedStatement; -import com.redhat.thermostat.storage.core.StatementDescriptor; -import com.redhat.thermostat.storage.core.StatementExecutionException; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO; -import com.redhat.thermostat.storage.internal.dao.NetworkInterfaceInfoDAOImpl; -import com.redhat.thermostat.storage.model.AggregateCount; -import com.redhat.thermostat.storage.model.NetworkInterfaceInfo; - -public class NetworkInfoPopulator extends BasePopulator { - - static final String[] IPV4_FORMATS = new String[] { - "192.168.0.%d", "10.33.4.%d", "89.15.93.%d" - }; - static final String[] IPV6_FORMATS = new String[] { - "e8:b1:fc:d2:e3:%s%%%s", "fe80::56ee:75ff:fe35:%s%%%s", - "0:0:0:0:0:0:0:%s%%%s" - }; - private final String[] IFACE_NAMES = new String[] { - "lo", "enp0s25", "tun0", "virbr0", "wlp4s0" - }; - private static int IPv6Mod = Integer.parseInt("ffff", 16); - private static int IPv4Mod = 255; - - private final NetworkInterfaceDAOCountable dao; - - public NetworkInfoPopulator() { - this(null); - } - - NetworkInfoPopulator(NetworkInterfaceDAOCountable dao) { - this.dao = dao; - } - - @Override - public SharedState addPojos(Storage storage, ConfigItem item, SharedState relState) { - ProcessedRecords<String> procAgents = relState.getProcessedRecordsFor("agentId"); - NetworkInterfaceDAOCountable dao = getDao(storage); - List<String> allAgents = procAgents.getAll(); - long countBefore = dao.getCount(); - int totalItems = item.getNumber() * allAgents.size(); - // populate network info records per agentID - System.out.println("Populating "+ totalItems + " " + item.getName() + " records"); - int currVal = 0; - for (String agentId: allAgents) { - for (int i = 0; i < item.getNumber(); i++) { - NetworkInterfaceInfo info = new NetworkInterfaceInfo(); - info.setAgentId(agentId); - String name = getRandomInterfaceName(i); - info.setInterfaceName(name); - info.setIp6Addr(getRandomIpv6Address(i, name)); - info.setIp4Addr(getRandomIpv4Addrees(i)); - dao.putNetworkInterfaceInfo(info); - reportProgress(item, currVal); - currVal++; - } - } - doWaitUntilCount(dao, countBefore + totalItems); - return relState; - } - - private String getRandomIpv4Addrees(int i) { - int idx = getRandomInt(IPV4_FORMATS.length); - return String.format(IPV4_FORMATS[idx], getIpv4Octet(i)); - } - - private int getRandomInt(int upperBound) { - return (int)(Math.random() * upperBound); - } - - private String getRandomIpv6Address(int i, String name) { - int idx = getRandomInt(IPV6_FORMATS.length); - return String.format(IPV6_FORMATS[idx], getIpv6Hextet(i), name); - } - - // package-private for testing - String getIpv6Hextet(int i) { - int remainder = i % IPv6Mod; - if (remainder == 0) { - // 0 isn't really an IP, make it 1 instead. - remainder = 1; - } - return Integer.toHexString(remainder); - } - - // package-private for testing - int getIpv4Octet(int i) { - int remainder = i % IPv4Mod; - if (remainder == 0) { - // 0 is network address, switch to IP - remainder = 1; - } - return remainder; - } - - private String getRandomInterfaceName(int i) { - int idx = getRandomInt(IFACE_NAMES.length); - return IFACE_NAMES[idx] + i; - } - - private NetworkInterfaceDAOCountable getDao(Storage storage) { - if (this.dao == null) { - return new NetworkInterfaceDAOCountable(storage); - } - return dao; - } - - @Override - public String getHandledCollection() { - return NetworkInterfaceInfoDAO.networkInfoCategory.getName(); - } - - static class NetworkInterfaceDAOCountable extends NetworkInterfaceInfoDAOImpl implements Countable { - - private final Category<AggregateCount> aggregateCategory; - private final Storage storage; - - NetworkInterfaceDAOCountable(Storage storage) { - super(storage); - CategoryAdapter<NetworkInterfaceInfo, AggregateCount> adapter = new CategoryAdapter<>(networkInfoCategory); - aggregateCategory = adapter.getAdapted(AggregateCount.class); - storage.registerCategory(aggregateCategory); - this.storage = storage; - } - - @Override - public long getCount() { - String descriptor = "QUERY-COUNT " + networkInfoCategory.getName(); - try { - PreparedStatement<AggregateCount> stmt = storage.prepareStatement(new StatementDescriptor<>(aggregateCategory, descriptor)); - Cursor<AggregateCount> cursor = stmt.executeQuery(); - AggregateCount count = cursor.next(); - return count.getCount(); - } catch (DescriptorParsingException | StatementExecutionException e) { - throw new RuntimeException(e); - } - } - - } - -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/internal/ThreadPopulator.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,282 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.internal; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import com.redhat.thermostat.common.Pair; -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.dependencies.SharedState; -import com.redhat.thermostat.storage.core.Category; -import com.redhat.thermostat.storage.core.CategoryAdapter; -import com.redhat.thermostat.storage.core.Countable; -import com.redhat.thermostat.storage.core.Cursor; -import com.redhat.thermostat.storage.core.DescriptorParsingException; -import com.redhat.thermostat.storage.core.PreparedStatement; -import com.redhat.thermostat.storage.core.StatementDescriptor; -import com.redhat.thermostat.storage.core.StatementExecutionException; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.model.AggregateCount; -import com.redhat.thermostat.thread.dao.ThreadDao; -import com.redhat.thermostat.thread.dao.internal.ThreadDaoImpl; -import com.redhat.thermostat.thread.model.ThreadHarvestingStatus; -import com.redhat.thermostat.thread.model.ThreadSession; -import com.redhat.thermostat.thread.model.ThreadState; -import com.redhat.thermostat.thread.model.ThreadSummary; -import com.redhat.thermostat.thread.model.VmDeadLockData; - -public class ThreadPopulator extends BasePopulator { - - /** - * Package-private and static for testing. - */ - static final int NUM_SAMPLES = 10; - - public final String SESSION = "session"; - private final int NUM_THREADS = 3; - private final long SEED = 5; - Random generator = new Random(SEED); - private static final String[] THREAD_NAMES = new String[] { - "Spencer", "Sheldon", "Alice", "Bob", "Julie", "Phoebe", "Alpha", "Beta", "Gamma", - "Theta", "Zeta", - }; - static final String DEADLOCK_DESC_FORMAT = "" + - "\"%s\" Id=%d WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@52de95c7 owned by \"%s\" Id=%d\n" + - "\tat sun.misc.Unsafe.park(Native Method)\n" + - "\t- waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@52de95c7\n" + - "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)\n" + - "\tat java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)\n" + - "\tat java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)\n" + - "\tat com.redhat.thermostat.tests.DeadLock$Philosopher.run(DeadLock.java:57)\n" + - "\t...\n\n" + - "\tNumber of locked synchronizers = 1\n" + - "\t- java.util.concurrent.locks.ReentrantLock$NonfairSync@441634c2\n" + - "\n\n" + - "\"%s\" Id=%d WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@105ff84e owned by \"%s\" Id=%d\n" + - "\tat sun.misc.Unsafe.park(Native Method)\n" + - "\t- waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@105ff84e\n" + - "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)\n" + - "\tat java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)\n" + - "\tat java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)\n" + - "\tat com.redhat.thermostat.tests.DeadLock$Philosopher.run(DeadLock.java:57)\n" + - "\t...\n\n" + - "\tNumber of locked synchronizers = 1\n" + - "\t- java.util.concurrent.locks.ReentrantLock$NonfairSync@52de95c7\n" + - "\n\n" + - "\"%s\" Id=%d WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@441634c2 owned by \"%s\" Id=%d\n" + - "\tat sun.misc.Unsafe.park(Native Method)\n" + - "\t- waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@441634c2\n" + - "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)\n" + - "\tat java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)\n" + - "\tat java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)\n" + - "\tat com.redhat.thermostat.tests.DeadLock$Philosopher.run(DeadLock.java:57)\n" + - "\t...\n\n" + - "\tNumber of locked synchronizers = 1\n" + - "\t- java.util.concurrent.locks.ReentrantLock$NonfairSync@105ff84e\n\n\n"; - - - private ThreadDaoCountable dao; - - public ThreadPopulator() { - this(null); - } - - ThreadPopulator(ThreadDaoCountable dao) { - this.dao = dao; - } - - // Testing hook - private void createDao(Storage storage) { - if (dao == null) { - dao = new ThreadDaoCountable(storage); - } - } - - @Override - public SharedState addPojos(Storage storage, ConfigItem item, SharedState relState) { - createDao(storage); - // creates records per agent *and* vm - List<String> agentIds = relState.getProcessedRecordsFor("agentId").getAll(); - List<String> vmIds = relState.getProcessedRecordsFor("vmId").getAll(); - int perVmNumber = item.getNumber(); - int totalCount = perVmNumber * agentIds.size() * vmIds.size(); - int currCount = 0; - long countBefore = dao.getCount(); - System.out.println("Populating "+ totalCount + " " + item.getName() + " records"); - long currTime = System.currentTimeMillis(); - for (String agentId: agentIds) { - for (String vmId: vmIds) { - for (int i = 0; i < perVmNumber; i++) { - ThreadSummary summary = new ThreadSummary(); - summary.setAgentId(agentId); - summary.setVmId(vmId); - int liveThreads = generator.nextInt(NUM_THREADS); - summary.setCurrentLiveThreads(liveThreads); - int daemonThreads = NUM_THREADS - liveThreads; - summary.setCurrentDaemonThreads(daemonThreads); - long timeStamp = currTime + i * 1000; - summary.setTimeStamp(timeStamp); - dao.saveSummary(summary); - - ThreadSession session = new ThreadSession(); - session.setSession(SESSION); - session.setTimeStamp(timeStamp); - session.setAgentId(agentId); - session.setVmId(vmId); - dao.saveSession(session); - - final Thread.State[] states = Thread.State.values(); - String state = states[generator.nextInt(states.length)].toString(); - String name = THREAD_NAMES[generator.nextInt(THREAD_NAMES.length)]; - - for(int j = 0; j < NUM_SAMPLES; j++) { - ThreadState threadState = new ThreadState(); - threadState.setTimeStamp(currTime + j * 1000); - threadState.setVmId(vmId); - threadState.setAgentId(agentId); - threadState.setState(state); - threadState.setId(i); - threadState.setName(name); - threadState.setSession(SESSION); - dao.addThreadState(threadState); - } - - ThreadHarvestingStatus status = new ThreadHarvestingStatus(agentId); - status.setVmId(vmId); - status.setTimeStamp(timeStamp); - status.setHarvesting(generator.nextBoolean()); - dao.saveHarvestingStatus(status); - - VmDeadLockData data = new VmDeadLockData(); - data.setAgentId(agentId); - data.setVmId(vmId); - data.setTimeStamp(currTime + i * 10); - data.setDeadLockDescription(getDeadlockedDescription(currCount)); - dao.saveDeadLockStatus(data); - currCount++; - reportProgress(item, currCount); - } - } - } - doWaitUntilCount(dao, countBefore + totalCount); - return relState; - } - - private String getDeadlockedDescription(int currCount) { - return String.format(DEADLOCK_DESC_FORMAT, getFormatStringArgs(currCount)); - } - - Object[] getFormatStringArgs(int currCount) { - List<Pair<String, Integer>> nameIdMapping = new ArrayList<>(); - int[] randomIds = getIdValues(currCount, NUM_THREADS); - int randomEntry = getRandomInt(THREAD_NAMES.length); - for (int i = 0, idx; i < NUM_THREADS; i++) { - idx = (randomEntry + i) % THREAD_NAMES.length; - String name = THREAD_NAMES[idx]; - int tid = randomIds[i]; - nameIdMapping.add(new Pair<>(name, tid)); - } - Object[] formatArgs = new Object[NUM_THREADS * 2 * 2]; - formatArgs[0] = nameIdMapping.get(0).getFirst(); - formatArgs[1] = nameIdMapping.get(0).getSecond(); - for (int i = 2, j = 1; i < formatArgs.length - 2; i+= 4, j++) { - formatArgs[i] = nameIdMapping.get(j).getFirst(); - formatArgs[i + 1] = nameIdMapping.get(j).getSecond(); - formatArgs[i + 2] = nameIdMapping.get(j).getFirst(); - formatArgs[i + 3] = nameIdMapping.get(j).getSecond(); - } - formatArgs[formatArgs.length - 2] = nameIdMapping.get(0).getFirst(); - formatArgs[formatArgs.length - 1] = nameIdMapping.get(0).getSecond(); - return formatArgs; - } - - private int getRandomInt(int len) { - return (int)(Math.random() * len); - } - - private int[] getIdValues(int currCount, int length) { - int[] values = new int[length]; - for (int i = 0; i < values.length; i++) { - values[i] = currCount + i; - } - return values; - } - - @Override - public String getHandledCollection() { - return ThreadDao.THREAD_HARVESTING_STATUS.getName(); - } - - static class ThreadDaoCountable extends ThreadDaoImpl implements Countable { - - private final Category<AggregateCount> aggregateCategory; - private final Storage storage; - - public ThreadDaoCountable(Storage storage) { - super(storage); - CategoryAdapter<VmDeadLockData, AggregateCount> adapter = new CategoryAdapter<>(DEADLOCK_INFO); - aggregateCategory = adapter.getAdapted(AggregateCount.class); - storage.registerCategory(aggregateCategory); - this.storage = storage; - } - - @Override - public long getCount() { - String descriptor = "QUERY-COUNT " + DEADLOCK_INFO.getName(); - try { - PreparedStatement<AggregateCount> stmt = storage.prepareStatement(new StatementDescriptor<>(aggregateCategory, descriptor)); - Cursor<AggregateCount> cursor = stmt.executeQuery(); - AggregateCount count = cursor.next(); - return count.getCount(); - } catch (DescriptorParsingException | StatementExecutionException e) { - throw new RuntimeException(e); - } - } - - } -}
--- a/dev/data-populator/src/main/java/com/redhat/thermostat/dev/populator/internal/VmInfoPopulator.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.internal; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.dependencies.ProcessedRecords; -import com.redhat.thermostat.dev.populator.dependencies.SharedState; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.dao.VmInfoDAO; -import com.redhat.thermostat.storage.internal.dao.VmInfoDAOImpl; -import com.redhat.thermostat.storage.model.VmInfo; - -public class VmInfoPopulator extends BasePopulator { - - private final VmInfoDAO dao; - - public VmInfoPopulator() { - this(null); - } - - VmInfoPopulator(VmInfoDAO dao) { - this.dao = dao; - } - - @Override - public SharedState addPojos(Storage storage, ConfigItem item, SharedState relState) { - // Default to all alive, if unset - int aliveItems = item.getAliveItems() == ConfigItem.UNSET ? item.getNumber() : item.getAliveItems(); - ProcessedRecords<String> procAgents = relState.getProcessedRecordsFor("agentId"); - List<String> vmIds = new ArrayList<>(); - VmInfoDAO dao = getDao(storage); - List<String> allAgents = procAgents.getAll(); - long countBefore = dao.getCount(); - int totalItems = item.getNumber() * allAgents.size(); - // populate VM records per agentID - System.out.println("Populating "+ totalItems + " " + item.getName() + " records"); - int currVal = 0; - for (String agentId: allAgents) { - for (int i = 0; i < item.getNumber(); i++) { - VmInfo info = new VmInfo(); - info.setAgentId(agentId); - info.setJavaCommandLine("java DataPopulatorProducedVM --vm " + i + " --version"); - info.setJavaHome("/opt/foo/bar/java-1.8.0-openjdk/jre"); - info.setJavaVersion("1.8.0"); - info.setMainClass("com.redhat.thermostat.TestDataPopulator"); - info.setLoadedNativeLibraries(new String[] { "glibc.so", "something.so" }); - info.setProperties(getFakeJavaProperties(i, agentId)); - StartStopTimeStamp ts = getFakeStartStopTimeStamp(i, aliveItems); - info.setStartTimeStamp(ts.startTS); - info.setStopTimeStamp(ts.stopTS); - info.setUsername("vm-user-" + i); - info.setUid(i); - info.setVmArguments("-XX:+UseG1Gc"); - String vmId = UUID.randomUUID().toString(); - info.setVmId(vmId); - vmIds.add(vmId); - info.setVmInfo("OpenJDK 8"); - info.setVmPid(34 + i); - info.setVmVersion("hs 25"); - info.setVmName("Hotspot"); - dao.putVmInfo(info); - reportProgress(item, currVal); - currVal++; - } - } - doWaitUntilCount(dao, countBefore + totalItems); - relState.addProcessedRecords("vmId", new ProcessedRecords<>(vmIds)); - return relState; - } - - private StartStopTimeStamp getFakeStartStopTimeStamp(int num, int aliveItems) { - long currTime = System.currentTimeMillis(); - if (num < aliveItems) { - // create alive timestamp pair - long startTs = Long.MAX_VALUE; - long stopTs = currTime; - return new StartStopTimeStamp(startTs, stopTs); - } - // create dead timestamp pair - return new StartStopTimeStamp(currTime - (1000 + num), currTime - (500 + num)); - } - - private Map<String, String> getFakeJavaProperties(int i, String agentId) { - Map<String, String> props = new HashMap<String, String>(); - props.put("foo", "bar"); - props.put("vm#", Integer.toString(i)); - props.put("agentId", agentId); - return props; - } - - // hook for testing - private VmInfoDAO getDao(Storage storage) { - if (dao == null) { - return new VmInfoDAOImpl(storage); - } else { - return dao; - } - } - - @Override - public String getHandledCollection() { - return VmInfoDAO.vmInfoCategory.getName(); - } - - private static class StartStopTimeStamp { - private final long startTS; - private final long stopTS; - - private StartStopTimeStamp(long start, long stop) { - this.startTS = start; - this.stopTS = stop; - } - } -}
--- a/dev/data-populator/src/main/resources/META-INF/services/com.redhat.thermostat.dev.populator.CollectionPopulator Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -com.redhat.thermostat.dev.populator.internal.ThreadPopulator -com.redhat.thermostat.dev.populator.internal.AgentInfoPopulator -com.redhat.thermostat.dev.populator.internal.VmInfoPopulator -com.redhat.thermostat.dev.populator.internal.HostInfoPopulator -com.redhat.thermostat.dev.populator.internal.NetworkInfoPopulator
--- a/dev/data-populator/src/test/java/com/redhat/thermostat/dev/populator/ArgumentsTest.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator; -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -public class ArgumentsTest { - - @Test - public void canParseCorrectArgs() { - String[] args = new String[] { - "--username", "foo-user", "--dbUrl", "mongodb://127.0.0.1:27518", - "--password", "foo-password", - "--config", "path/to/config" - }; - Arguments parsedArgs = Arguments.processArguments(args); - assertValues(parsedArgs); - // different order - args = new String[] { - "--dbUrl", "mongodb://127.0.0.1:27518", - "--username", "foo-user", - "--password", "foo-password", - "--config", "path/to/config" - }; - parsedArgs = Arguments.processArguments(args); - assertValues(parsedArgs); - } - - @Test(expected = IllegalArgumentException.class) - public void failToParseUsernameMissing() { - String[] args = new String[] { - "--dbUrl", "mongodb://127.0.0.1:27518", - "--password", "foo-password", - "--dbUrl", "mongodb://127.0.0.1:27518", - "--config", "path/to/config" - }; - Arguments.processArguments(args); - } - - @Test(expected = IllegalArgumentException.class) - public void failToParsePasswordMissing() { - String[] args = new String[] { - "--dbUrl", "mongodb://127.0.0.1:27518", - "--username", "foo-user", - "--dbUrl", "mongodb://127.0.0.1:27518", - "--config", "path/to/config" - }; - Arguments.processArguments(args); - } - - @Test(expected = IllegalArgumentException.class) - public void failToParseDbUrlMissing() { - String[] args = new String[] { - "--username", "foo-user", - "--username", "foo-user", - "--password", "foo-password", - "--config", "path/to/config" - }; - Arguments.processArguments(args); - } - - @Test(expected = IllegalArgumentException.class) - public void failToParseIllegalOptionValue() { - String[] args = new String[] { - "--username", "--foo-user", // -- in foo-user is wrong - "--username", "foo-user", - "--password", "foo-password", - "--config", "path/to/config" - }; - Arguments.processArguments(args); - } - - @Test(expected = IllegalArgumentException.class) - public void failToParseIllegalOption() { - String[] args = new String[] { - "--username", "--foo-user", - "username", "foo-user", // epxected --username not username - "--dbUrl", "mongodb://127.0.0.1:27518", - "--password", "foo-password", - "--config", "path/to/config" - }; - Arguments.processArguments(args); - } - - @Test(expected = IllegalArgumentException.class) - public void failToParseIllegalLength() { - String[] args = new String[] { - "--username", "--foo-user", - "--username", "foo-user", - "--dbUrl", "mongodb://127.0.0.1:27518", - "--password", "foo-password", - "--config", "path/to/config" - }; - Arguments.processArguments(args); - } - - private void assertValues(Arguments parsedArgs) { - assertEquals("mongodb://127.0.0.1:27518", parsedArgs.getDbUrl()); - assertEquals("foo-user", parsedArgs.getUsername()); - assertEquals("foo-password", parsedArgs.getPassword()); - assertEquals("path/to/config", parsedArgs.getConfigFile()); - } -}
--- a/dev/data-populator/src/test/java/com/redhat/thermostat/dev/populator/config/PopulationConfigTest.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,214 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.config; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -import org.junit.Test; - -import com.redhat.thermostat.dev.populator.dependencies.Relationship; - -public class PopulationConfigTest { - - private static final String NETWORK_INFO_NAME = "network-info"; - private static final String AGENT_CONFIG_NAME = "agent-config"; - private static final String HOST_INFO_NAME = "host-info"; - private static final String VM_INFO_NAME = "vm-info"; - private static final String VM_GC_STAT_NAME = "vm-gc-stats"; - private static final String AGENT_KEY = "foo-agent-key"; - private static final String VM_KEY = "bar-vm-key"; - - @Test - public void canParseFromFile() throws IOException { - String json = new String(Files.readAllBytes(new File(getClass().getResource("/testconfig").getFile()).toPath())); - PopulationConfig config = PopulationConfig.parseFromJsonString(json); - ConfigItem item = config.getConfig("agent-config"); - assertNotNull(item); - assertEquals(100, item.getNumber()); - assertEquals(20, item.getAliveItems()); - List<ConfigItem> items = config.getConfigsTopologicallySorted(); - assertEquals(7, items.size()); - item = config.getConfig("vm-info"); - assertEquals(50, item.getNumber()); - assertEquals(40, item.getAliveItems()); - item = config.getConfig("vm-gc-stats"); - assertNotNull(item); - } - - /** - * Tests topological sorting of a simple DAG - * - * <pre> - * agent-config -> network-info - * |----------> host-info - * |--> vm-info - * | `--> vm-gc-stat - * `------------^ - * </pre> - * - * @throws IOException - */ - @Test - public void testTopogicalSort() throws IOException { - List<ConfigItem> records = buildGoodRecords(); - List<Relationship> rels = buildGoodRels(); - PopulationConfig pc = PopulationConfig.createFromLists(records, rels); - List<ConfigItem> topSortedList = pc.getConfigsTopologicallySorted(); - assertAgentConfigBeforeNetworkInfo(topSortedList); - assertAgentConfigBeforeHostInfo(topSortedList); - assertAgentConfigBeforeVmInfo(topSortedList); - assertVmInfoBeforeVmGcStat(topSortedList); - assertAgentConfigBeforeVmGcStat(topSortedList); - } - - private void assertAgentConfigBeforeVmGcStat(List<ConfigItem> topSortedList) { - assertTrue(isABeforeB(AGENT_CONFIG_NAME, VM_GC_STAT_NAME, topSortedList)); - } - - private void assertVmInfoBeforeVmGcStat(List<ConfigItem> topSortedList) { - assertTrue(isABeforeB(VM_INFO_NAME, VM_GC_STAT_NAME, topSortedList)); - } - - private void assertAgentConfigBeforeVmInfo(List<ConfigItem> topSortedList) { - assertTrue(isABeforeB(AGENT_CONFIG_NAME, VM_INFO_NAME, topSortedList)); - } - - private void assertAgentConfigBeforeHostInfo(List<ConfigItem> topSortedList) { - assertTrue(isABeforeB(AGENT_CONFIG_NAME, HOST_INFO_NAME, topSortedList)); - } - - private void assertAgentConfigBeforeNetworkInfo(List<ConfigItem> topSortedList) { - assertTrue(isABeforeB(AGENT_CONFIG_NAME, NETWORK_INFO_NAME, topSortedList)); - } - - private boolean isABeforeB(String a, String b, List<ConfigItem> list) { - int idxA = -1; - int idxB = -1; - for (int i = 0; i < list.size(); i++) { - ConfigItem item = list.get(i); - if (item.getName().equals(a)) { - if (idxA >= 0) { - throw new AssertionError("Illegal state. Re-assigning idxA!"); - } - idxA = i; - } - if (item.getName().equals(b)) { - if (idxB >= 0) { - throw new AssertionError("Illegal state. Re-assigning idxB!"); - } - idxB = i; - } - } - return idxA < idxB; - } - - private List<Relationship> buildGoodRels() { - List<Relationship> relationships = new LinkedList<>(); - Relationship agentConfigToNetworkInfo = new Relationship(AGENT_CONFIG_NAME, NETWORK_INFO_NAME, AGENT_KEY); - relationships.add(agentConfigToNetworkInfo); - Relationship agentConfigToVmGcStat = new Relationship(AGENT_CONFIG_NAME, VM_GC_STAT_NAME, AGENT_KEY); - relationships.add(agentConfigToVmGcStat); - Relationship agentConfigToHostInfo = new Relationship(AGENT_CONFIG_NAME, HOST_INFO_NAME, AGENT_KEY); - relationships.add(agentConfigToHostInfo); - Relationship agentConfigToVmInfo = new Relationship(AGENT_CONFIG_NAME, VM_INFO_NAME, AGENT_KEY); - relationships.add(agentConfigToVmInfo); - Relationship vmInfoToVmGcStat = new Relationship(VM_INFO_NAME, VM_GC_STAT_NAME, VM_KEY); - relationships.add(vmInfoToVmGcStat); - return relationships; - } - - private List<ConfigItem> buildGoodRecords() { - List<ConfigItem> records = new ArrayList<>(); - ConfigItem agentConfig = new ConfigItem(10, 3, AGENT_CONFIG_NAME); - records.add(agentConfig); - ConfigItem hostInfo = new ConfigItem(3, 0, HOST_INFO_NAME); - records.add(hostInfo); - ConfigItem networkInfo = new ConfigItem(100, 0, NETWORK_INFO_NAME); - records.add(networkInfo); - ConfigItem vmGcStat = new ConfigItem(23, 0, VM_GC_STAT_NAME); - records.add(vmGcStat); - ConfigItem vmInfo = new ConfigItem(10, 0, VM_INFO_NAME); - records.add(vmInfo); - return records; - } - - /** - * Tests topological sorting with a cycle. Expected to fail. - */ - @Test(expected = AssertionError.class) - public void testTopogicalSortCycle() throws IOException { - List<ConfigItem> records = buildGoodRecords(); - List<Relationship> rels = buildGoodRels(); - // add a cycle between vm-info -> host-info -> agent-config - Relationship cyclePartOne = new Relationship(VM_INFO_NAME, HOST_INFO_NAME, VM_KEY); - rels.add(cyclePartOne); - Relationship cyclePartTwo = new Relationship(HOST_INFO_NAME, AGENT_CONFIG_NAME, AGENT_KEY); - rels.add(cyclePartTwo); - PopulationConfig pc = PopulationConfig.createFromLists(records, rels); - // This is expected to fail - pc.getConfigsTopologicallySorted(); - } - - @Test(expected = PopulationConfig.InvalidConfigurationException.class) - public void testTopogicalSortIncomingCollectionMissing() throws IOException { - List<ConfigItem> records = buildGoodRecords(); - // remove vm-gc-stat records config which has an incoming edge - // from agent-config and vm-info - int deleteIdx = -1; - for (int i = 0; i < records.size(); i++) { - ConfigItem item = records.get(i); - if (item.getName().equals(VM_GC_STAT_NAME)) { - deleteIdx = i; - break; - } - } - assertTrue("Expected vm-gc-stat to be in records config", deleteIdx >= 0); - records.remove(deleteIdx); - List<Relationship> rels = buildGoodRels(); - PopulationConfig pc = PopulationConfig.createFromLists(records, rels); - pc.getConfigsTopologicallySorted(); - } -}
--- a/dev/data-populator/src/test/java/com/redhat/thermostat/dev/populator/config/typeadapter/ConfigItemTypeAdapterTest.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.config.typeadapter; - -import static org.junit.Assert.assertEquals; - -import org.junit.Before; -import org.junit.Test; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.redhat.thermostat.dev.populator.config.ConfigItem; - -public class ConfigItemTypeAdapterTest { - - private Gson gson; - - @Before - public void setup() { - gson= new GsonBuilder() - .registerTypeAdapter(ConfigItem.class, new ConfigItemTypeAdapter()) - .create(); - } - - @Test - public void testBasicNonNull() { - ConfigItem item = gson.fromJson("{ \"name\": \"config-item\", \"number\": 3, \"alive\": 1}", ConfigItem.class); - assertEquals("config-item", item.getName()); - assertEquals(3, item.getNumber()); - assertEquals(1, item.getAliveItems()); - } - - @Test(expected = IllegalArgumentException.class) - public void testBasicNegativeNumber() { - gson.fromJson("{ \"name\": \"config-item\", \"number\": -3, \"alive\": 1}", ConfigItem.class); - } - - @Test(expected = IllegalArgumentException.class) - public void testBasicNegativeAlive() { - gson.fromJson("{ \"name\": \"config-item\", \"number\": 10, \"alive\": -1}", ConfigItem.class); - } - - @Test(expected = IllegalArgumentException.class) - public void testBasicAliveGreaterThanNumber() { - // alive > number. Expected strict subset - gson.fromJson("{ \"name\": \"config-item\", \"number\": 10, \"alive\": 11}", ConfigItem.class); - } - - @Test - public void testBasicNullAlive() { - ConfigItem item = gson.fromJson("{ \"name\": \"config-item\", \"number\": 3}", ConfigItem.class); - assertEquals("config-item", item.getName()); - assertEquals(3, item.getNumber()); - assertEquals(ConfigItem.UNSET, item.getAliveItems()); - } - - @Test - public void testArray() { - ConfigItem[] items = gson.fromJson("[{ \"name\": \"config-item\", \"number\": 3, \"alive\": 1}," + - "{ \"name\": \"agent-config\", \"number\": 10, \"alive\": 3 }]", ConfigItem[].class); - assertEquals("config-item", items[0].getName()); - assertEquals(3, items[0].getNumber()); - assertEquals(1, items[0].getAliveItems()); - assertEquals("agent-config", items[1].getName()); - assertEquals(10, items[1].getNumber()); - assertEquals(3, items[1].getAliveItems()); - } -}
--- a/dev/data-populator/src/test/java/com/redhat/thermostat/dev/populator/config/typeadapter/PopulationConfigTypeAdapterTest.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.config.typeadapter; - -import static org.junit.Assert.assertEquals; - -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.config.PopulationConfig; -import com.redhat.thermostat.dev.populator.dependencies.Relationship; - -public class PopulationConfigTypeAdapterTest { - - private Gson gson; - - @Before - public void setup() { - gson= new GsonBuilder() - .registerTypeAdapter(Relationship.class, new RelationShipTypeAdapter()) - .registerTypeAdapter(ConfigItem.class, new ConfigItemTypeAdapter()) - .registerTypeAdapterFactory(new PopulationConfigTypeAdapterFactory()) - .create(); - } - - @Test - public void canParseSimpleNoRelationships() throws Exception { - String json = "{ \"records\": " + - "[{ \"name\": \"config-item\", \"number\": 3, \"alive\": 1}," + - "{ \"name\": \"agent-config\", \"number\": 10, \"alive\": 3 }]" + - "}"; - PopulationConfig config = gson.fromJson(json, PopulationConfig.class); - ConfigItem item = config.getConfig("config-item"); - assertEquals(3, item.getNumber()); - assertEquals(1, item.getAliveItems()); - assertEquals("config-item", item.getName()); - item = config.getConfig("agent-config"); - assertEquals(10, item.getNumber()); - assertEquals(3, item.getAliveItems()); - assertEquals("agent-config", item.getName()); - } - - @Test - public void canParseSimpleWithRelationships() throws Exception { - String json = "{ \"records\": " + - "[{ \"name\": \"config-item\", \"number\": 3, \"alive\": 1}," + - "{ \"name\": \"agent-config\", \"number\": 10, \"alive\": 3 }]," + - " \"relationships\": "+ - "[{ \"from\": \"config-item\", \"to\": \"agent-config\", \"key\": \"foo\"}]" + - "}"; - PopulationConfig config = gson.fromJson(json, PopulationConfig.class); - ConfigItem item = config.getConfig("config-item"); - assertEquals(3, item.getNumber()); - assertEquals(1, item.getAliveItems()); - assertEquals("config-item", item.getName()); - item = config.getConfig("agent-config"); - assertEquals(10, item.getNumber()); - assertEquals(3, item.getAliveItems()); - assertEquals("agent-config", item.getName()); - // Do something that uses relationships - List<ConfigItem> sorted = config.getConfigsTopologicallySorted(); - ConfigItem first = sorted.get(0); - assertEquals("config-item", first.getName()); - } -}
--- a/dev/data-populator/src/test/java/com/redhat/thermostat/dev/populator/config/typeadapter/RelationShipTypeAdapterTest.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.config.typeadapter; - -import static org.junit.Assert.assertEquals; - -import org.junit.Before; -import org.junit.Test; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.redhat.thermostat.dev.populator.dependencies.Relationship; - -public class RelationShipTypeAdapterTest { - - private Gson gson; - - @Before - public void setup() { - gson= new GsonBuilder() - .registerTypeAdapter(Relationship.class, new RelationShipTypeAdapter()) - .create(); - } - - @Test - public void testBasicNonNull() { - Relationship rel = gson.fromJson("{ \"from\": \"foo\", \"to\": \"bar\", \"key\": \"baz\"}", Relationship.class); - assertEquals("foo", rel.getFrom()); - assertEquals("bar", rel.getTo()); - assertEquals("baz", rel.getKey()); - } -}
--- a/dev/data-populator/src/test/java/com/redhat/thermostat/dev/populator/dependencies/RelationshipTest.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.dependencies; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -public class RelationshipTest { - - @Test - public void testEquals() { - Relationship one = new Relationship("foo", "bar", "key"); - Relationship two = new Relationship("foo", "bar", "key"); - Relationship different = new Relationship("foo", "bar", "something"); - assertTrue(one.equals(two)); - assertTrue(one.equals(one)); - assertFalse(one.equals(different)); - assertFalse(one.equals(null)); - assertTrue(two.equals(one)); - } - - @Test - public void testHashCode() { - Relationship one = new Relationship("foo", "bar", "key"); - Relationship two = new Relationship("foo", "bar", "key"); - Relationship different = new Relationship("foo", "bar", "something"); - assertEquals(one.hashCode(), two.hashCode()); - assertFalse(different.hashCode() == one.hashCode()); - assertFalse(two.hashCode() == different.hashCode()); - assertEquals(one.hashCode(), one.hashCode()); - } -}
--- a/dev/data-populator/src/test/java/com/redhat/thermostat/dev/populator/internal/AgentInfoPopulatorTest.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.internal; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -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.util.ArrayList; -import java.util.List; - -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.dependencies.ProcessedRecords; -import com.redhat.thermostat.dev.populator.dependencies.SharedState; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.model.AgentInformation; - -public class AgentInfoPopulatorTest { - - @Test - public void canHandleAgentInfoCollection() { - AgentInfoPopulator putter = new AgentInfoPopulator(); - assertEquals("agent-config", putter.getHandledCollection()); - } - - @Test - public void canAddPojos() { - int totalRecords = 23; - AgentInfoDAO dao = mock(AgentInfoDAO.class); - // Initially return 0, then return the expected count - when(dao.getCount()).thenReturn(0L).thenReturn((long)totalRecords); - AgentInfoPopulator putter = new AgentInfoPopulator(dao); - ConfigItem item = new ConfigItem(totalRecords, 3, "agent-config"); - SharedState state = new SharedState(); - state = putter.addPojos(mock(Storage.class), item, state); - ArgumentCaptor<AgentInformation> agentInfoCaptor = ArgumentCaptor.forClass(AgentInformation.class); - verify(dao, times(23)).addAgentInformation(agentInfoCaptor.capture()); - List<AgentInformation> agentInfos = agentInfoCaptor.getAllValues(); - List<AgentInformation> filtered = getAliveAgentInfos(agentInfos); - assertEquals(3, filtered.size()); - ProcessedRecords<String> recs = state.getProcessedRecordsFor("agentId"); - assertEquals(23, recs.getAll().size()); - ProcessedRecords<String> notExisting = state.getProcessedRecordsFor("foo-bar"); - assertNull(notExisting); - // FIXME: HostInfo populator needs AgentInfoDAO so we tag the dao - // to the shared state. This test asserts that it does so. - AgentInfoDAO stateDAO = (AgentInfoDAO)state.getProperty("agent-info-dao"); - assertNotNull(stateDAO); - assertSame(stateDAO, dao); - } - - private List<AgentInformation> getAliveAgentInfos(List<AgentInformation> agentInfos) { - List<AgentInformation> aliveInfos = new ArrayList<>(); - for (AgentInformation info: agentInfos) { - if (info.isAlive()) { - aliveInfos.add(info); - } - } - return aliveInfos; - } -}
--- a/dev/data-populator/src/test/java/com/redhat/thermostat/dev/populator/internal/HostInfoPopulatorTest.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.internal; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.eq; -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.util.Arrays; -import java.util.List; - -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.dependencies.ProcessedRecords; -import com.redhat.thermostat.dev.populator.dependencies.SharedState; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.dao.HostInfoDAO; -import com.redhat.thermostat.storage.model.HostInfo; - -public class HostInfoPopulatorTest { - - @Test - public void handlesCorrectCollection() { - HostInfoPopulator populator = new HostInfoPopulator(); - assertEquals("host-info", populator.getHandledCollection()); - } - - @Test - public void canPopulateToStorage() { - String[] agents = new String[] { - "host-agent1", "host-agent2", "host-agent3", "host-agent4" - }; - List<String> agentIds = Arrays.asList(agents); - SharedState state = mock(SharedState.class); - @SuppressWarnings("unchecked") - ProcessedRecords<String> procRecs = mock(ProcessedRecords.class); - when(procRecs.getAll()).thenReturn(agentIds); - when(state.getProcessedRecordsFor(eq("agentId"))).thenReturn(procRecs); - when(state.getProperty(eq("agent-info-dao"))).thenReturn(mock(AgentInfoDAO.class)); - int totalRecords = agents.length; - HostInfoDAO dao = mock(HostInfoDAO.class); - // Initially return 0, then return the expected count - when(dao.getCount()).thenReturn(0L).thenReturn((long)totalRecords); - - ConfigItem config = new ConfigItem(1, ConfigItem.UNSET, "host-info"); - HostInfoPopulator populator = new HostInfoPopulator(dao); - populator.addPojos(mock(Storage.class), config, state); - ArgumentCaptor<HostInfo> captor = ArgumentCaptor.forClass(HostInfo.class); - verify(dao, times(totalRecords)).putHostInfo(captor.capture()); - List<HostInfo> values = captor.getAllValues(); - // ensure no memory values are negative - for (HostInfo info: values) { - if (info.getTotalMemory() < 0) { - throw new AssertionError("Invalid memory value: " + info.getTotalMemory() + " < 0"); - } - } - } -}
--- a/dev/data-populator/src/test/java/com/redhat/thermostat/dev/populator/internal/NetworkInfoPopulatorTest.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.internal; - -import static org.junit.Assert.assertEquals; -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.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.dependencies.ProcessedRecords; -import com.redhat.thermostat.dev.populator.dependencies.SharedState; -import com.redhat.thermostat.dev.populator.internal.NetworkInfoPopulator.NetworkInterfaceDAOCountable; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.model.NetworkInterfaceInfo; - -public class NetworkInfoPopulatorTest { - - @Test - public void canHandleCorrectCollection() { - NetworkInfoPopulator populator = new NetworkInfoPopulator(); - assertEquals("network-info", populator.getHandledCollection()); - } - - @Test - public void testPopulation() { - NetworkInterfaceDAOCountable dao = mock(NetworkInterfaceDAOCountable.class); - NetworkInfoPopulator populator = new NetworkInfoPopulator(dao); - - String[] agentIds = new String[] { - "testAgent1", "testAgent2", "testAgent3", "testAgent4" - }; - int perAgentItems = 100; - int totalRecords = perAgentItems * agentIds.length; - when(dao.getCount()).thenReturn(0L).thenReturn((long)totalRecords); - List<String> agents = Arrays.asList(agentIds); - SharedState state = new SharedState(); - state.addProcessedRecords("agentId", new ProcessedRecords<>(agents)); - ConfigItem config = new ConfigItem(perAgentItems, ConfigItem.UNSET, "network-info"); - populator.addPojos(mock(Storage.class), config, state); - ArgumentCaptor<NetworkInterfaceInfo> captor = ArgumentCaptor.forClass(NetworkInterfaceInfo.class); - verify(dao, times(totalRecords)).putNetworkInterfaceInfo(captor.capture()); - List<NetworkInterfaceInfo> list = captor.getAllValues(); - // expected agentId + iface name to be unique (since REPLACE otherwise replaces some random values) - Set<String> uniqueSet = new HashSet<>(); - for (NetworkInterfaceInfo info: list) { - String agentId = info.getAgentId(); - String ifaceName = info.getInterfaceName(); - String key = agentId + ifaceName; - if (uniqueSet.contains(key)) { - throw new AssertionError("Expected interface names to be unique per agent"); - } else { - uniqueSet.add(key); - } - } - } - - @Test - public void iPv6HextetRollOver() { - String ipv6 = new NetworkInfoPopulator().getIpv6Hextet(Integer.parseInt("fffe", 16)); - assertEquals("fffe", ipv6); - ipv6 = new NetworkInfoPopulator().getIpv6Hextet(Integer.parseInt("ffff", 16)); - assertEquals("1", ipv6); - ipv6 = new NetworkInfoPopulator().getIpv6Hextet(Integer.parseInt("eee1", 16)); - assertEquals("eee1", ipv6); - } - - @Test - public void iPv4OctetsRollOver() { - int octet = new NetworkInfoPopulator().getIpv4Octet(255); - assertEquals(1, octet); - octet = new NetworkInfoPopulator().getIpv4Octet(256); - assertEquals(1, octet); - octet = new NetworkInfoPopulator().getIpv4Octet(114); - assertEquals(114, octet); - } - - @Test - public void stringFormatIpv6Template() { - String formattedString = String.format(NetworkInfoPopulator.IPV6_FORMATS[1], "ff", "scope"); - assertEquals("fe80::56ee:75ff:fe35:ff%scope", formattedString); - } -}
--- a/dev/data-populator/src/test/java/com/redhat/thermostat/dev/populator/internal/ThreadPopulatorTest.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,289 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.internal; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; -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.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.dependencies.ProcessedRecords; -import com.redhat.thermostat.dev.populator.dependencies.SharedState; -import com.redhat.thermostat.dev.populator.internal.ThreadPopulator.ThreadDaoCountable; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.model.BasePojo; -import com.redhat.thermostat.thread.model.ThreadHarvestingStatus; -import com.redhat.thermostat.thread.model.ThreadSession; -import com.redhat.thermostat.thread.model.ThreadState; -import com.redhat.thermostat.thread.model.ThreadSummary; -import com.redhat.thermostat.thread.model.VmDeadLockData; - -public class ThreadPopulatorTest { - - private static final String EXPECTED_DESCRIPTION = "" + - "\"Mallory\" Id=12 WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@52de95c7 owned by \"Alice\" Id=10\n" + - "\tat sun.misc.Unsafe.park(Native Method)\n" + - "\t- waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@52de95c7\n" + - "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)\n" + - "\tat java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)\n" + - "\tat java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)\n" + - "\tat com.redhat.thermostat.tests.DeadLock$Philosopher.run(DeadLock.java:57)\n" + - "\t...\n\n" + - "\tNumber of locked synchronizers = 1\n" + - "\t- java.util.concurrent.locks.ReentrantLock$NonfairSync@441634c2" + - "\n\n\n" + - "\"Alice\" Id=10 WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@105ff84e owned by \"Bob\" Id=11\n" + - "\tat sun.misc.Unsafe.park(Native Method)\n" + - "\t- waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@105ff84e\n" + - "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)\n" + - "\tat java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)\n" + - "\tat java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)\n" + - "\tat com.redhat.thermostat.tests.DeadLock$Philosopher.run(DeadLock.java:57)\n" + - "\t...\n\n" + - "\tNumber of locked synchronizers = 1\n" + - "\t- java.util.concurrent.locks.ReentrantLock$NonfairSync@52de95c7\n" + - "\n\n" + - "\"Bob\" Id=11 WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@441634c2 owned by \"Mallory\" Id=12\n" + - "\tat sun.misc.Unsafe.park(Native Method)\n" + - "\t- waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@441634c2\n" + - "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)\n" + - "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)\n" + - "\tat java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)\n" + - "\tat java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)\n" + - "\tat com.redhat.thermostat.tests.DeadLock$Philosopher.run(DeadLock.java:57)\n" + - "\t...\n\n" + - "\tNumber of locked synchronizers = 1\n" + - "\t- java.util.concurrent.locks.ReentrantLock$NonfairSync@105ff84e\n\n\n"; - - private static final String[] AGENTS = new String[] { - "fooAgent1", "fooBarAgent", "testAgent", "someAgent" - }; - private static final String[] VMS = new String[] { - "vm1", "vm2", "vm3", "vm4", "vm5" - }; - - private ThreadDaoCountable countableDao; - - @Test - public void testFormatDeadlockDesc() { - Object[] stringFormatArgs = new Object[] { - "Mallory", 12, - "Alice", 10, - "Alice", 10, - "Bob", 11, - "Bob", 11, - "Mallory", 12 - }; - assertEquals(EXPECTED_DESCRIPTION, String.format(ThreadPopulator.DEADLOCK_DESC_FORMAT, stringFormatArgs)); - } - - @Test - public void canGetRandomThreadNames() { - Object[] args = new ThreadPopulator().getFormatStringArgs(2); - assertEquals(12, args.length); - Map<Integer, Integer> tids = new HashMap<>(); - Map<String, Integer> threadNames = new HashMap<>(); - for (int i = 0; i < args.length; i +=2) { - Object arg1 = args[i]; - Object arg2 = args[i + 1]; - assertEquals(String.class, arg1.getClass()); - assertEquals(Integer.class, arg2.getClass()); - if (tids.containsKey(arg2)) { - Integer value = tids.get(arg2); - value += 1; - tids.put((Integer)arg2, value); - } else { - tids.put((Integer)arg2, 1); - } - if (threadNames.containsKey(arg1)) { - Integer value = threadNames.get(arg1); - value += 1; - threadNames.put((String)arg1, value); - } else { - threadNames.put((String)arg1, 1); - } - } - for (String key : threadNames.keySet()) { - int value = threadNames.get(key); - assertEquals(2, value); - } - for (Integer key : tids.keySet()) { - int value = tids.get(key); - assertEquals(2, value); - } - } - - @Test - public void canHandleAppropriateCollection() { - ThreadPopulator populator = new ThreadPopulator(); - assertEquals("vm-thread-harvesting", populator.getHandledCollection()); - } - - @Test - public void canAddThreadData() { - int perVmCount = 123; - int totalCount = perVmCount * AGENTS.length * VMS.length; - setUp(perVmCount, totalCount); - - assertThreadSummaries(totalCount, perVmCount); - assertThreadSessions(totalCount, perVmCount); - assertThreadStates(totalCount, perVmCount); - assertThreadHarvestingStatus(totalCount, perVmCount); - assertDeadlockInfo(perVmCount, totalCount); - } - - private void setUp(int perVmCount, int totalCount) { - ConfigItem config = new ConfigItem(perVmCount, ConfigItem.UNSET, "vm-deadlock-data"); - countableDao = mock(ThreadDaoCountable.class); - when(countableDao.getCount()).thenReturn(0L).thenReturn((long)totalCount); - ThreadPopulator populator = new ThreadPopulator(countableDao); - SharedState state = mock(SharedState.class); - when(state.getProcessedRecordsFor("agentId")).thenReturn(new ProcessedRecords<>(Arrays.asList(AGENTS))); - when(state.getProcessedRecordsFor("vmId")).thenReturn(new ProcessedRecords<>(Arrays.asList(VMS))); - SharedState retval = populator.addPojos(mock(Storage.class), config, state); - assertSame(retval, state); - } - - private void assertThreadSummaries(int totalCount, int perVmCount) { - ArgumentCaptor<ThreadSummary> summaryCaptor = ArgumentCaptor.forClass(ThreadSummary.class); - verify(countableDao, times(totalCount)).saveSummary(summaryCaptor.capture()); - List<ThreadSummary> savedValues = summaryCaptor.getAllValues(); - assertEquals(totalCount, savedValues.size()); - checkInstances(savedValues, VMS.length * perVmCount); - } - - private void assertThreadSessions(int totalCount, int perVmCount) { - ArgumentCaptor<ThreadSession> sessionCaptor = ArgumentCaptor.forClass(ThreadSession.class); - verify(countableDao, times(totalCount)).saveSession(sessionCaptor.capture()); - List<ThreadSession> savedValues = sessionCaptor.getAllValues(); - assertEquals(totalCount, savedValues.size()); - checkInstances(savedValues, VMS.length * perVmCount); - } - - private void assertThreadStates(int totalCount, int perVmCount) { - ArgumentCaptor<ThreadState> stateCaptor = ArgumentCaptor.forClass(ThreadState.class); - verify(countableDao, times(totalCount * ThreadPopulator.NUM_SAMPLES)). - addThreadState(stateCaptor.capture()); - List<ThreadState> savedValues = stateCaptor.getAllValues(); - assertEquals(totalCount * ThreadPopulator.NUM_SAMPLES, savedValues.size()); - checkInstances(savedValues, VMS.length * perVmCount * ThreadPopulator.NUM_SAMPLES); - } - - private void assertThreadHarvestingStatus(int totalCount, int perVmCount) { - ArgumentCaptor<ThreadHarvestingStatus> statusCaptor = - ArgumentCaptor.forClass(ThreadHarvestingStatus.class); - verify(countableDao, times(totalCount)).saveHarvestingStatus(statusCaptor.capture()); - List<ThreadHarvestingStatus> savedValues = statusCaptor.getAllValues(); - checkInstances(savedValues, VMS.length * perVmCount); - } - - private void checkInstances(List<? extends BasePojo> savedValues, int expected) { - List<String> agentIds = new ArrayList<>(); - for (int i = 0; i < savedValues.size(); i++) { - agentIds.add(savedValues.get(i).getAgentId()); - } - - for (String agentId : AGENTS) { - int numInstances = Collections.frequency(agentIds, agentId); - assertEquals(expected, numInstances); - } - } - - private void assertDeadlockInfo(int perVmCount, int totalCount) { - ArgumentCaptor<VmDeadLockData> deadlockInfoCaptor = ArgumentCaptor.forClass(VmDeadLockData.class); - verify(countableDao, times(totalCount)).saveDeadLockStatus(deadlockInfoCaptor.capture()); - List<VmDeadLockData> savedValues = deadlockInfoCaptor.getAllValues(); - assertEquals(totalCount, savedValues.size()); - List<VmDeadLockData> perVmIdAgentDeadlockData = getFilteredByVmId(savedValues, "vm3"); - assertEquals(perVmCount * AGENTS.length, perVmIdAgentDeadlockData.size()); - List<VmDeadLockData> perAgentIdDeadlockData = getFilteredByAgentId(savedValues, "fooAgent1"); - verifyVmIdsDifferent(perAgentIdDeadlockData); - } - - private List<VmDeadLockData> getFilteredByAgentId(List<VmDeadLockData> perVmDeadlockData, String agentId) { - List<VmDeadLockData> filteredValues = new ArrayList<>(); - for (VmDeadLockData data: perVmDeadlockData) { - if (data.getAgentId().equals(agentId)) { - filteredValues.add(data); - } - } - return filteredValues; - } - - private void verifyVmIdsDifferent(List<VmDeadLockData> perVmDeadlockData) { - Set<String> vmIds = new HashSet<>(); - for (VmDeadLockData data: perVmDeadlockData) { - if (vmIds.contains(data.getVmId())) { - throw new AssertionError("Duplicate VM ID per agent. Duplicate was: " + data.getVmId()); - } - vmIds.add(data.getAgentId()); - } - } - - private List<VmDeadLockData> getFilteredByVmId(List<VmDeadLockData> savedValues, String vmId) { - List<VmDeadLockData> filteredValues = new ArrayList<>(); - for (VmDeadLockData data: savedValues) { - if (data.getVmId().equals(vmId)) { - filteredValues.add(data); - } - } - return filteredValues; - } -}
--- a/dev/data-populator/src/test/java/com/redhat/thermostat/dev/populator/internal/VmInfoPopulatorTest.java Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -/* - * Copyright 2012-2016 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.dev.populator.internal; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.eq; -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.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -import com.redhat.thermostat.dev.populator.config.ConfigItem; -import com.redhat.thermostat.dev.populator.dependencies.ProcessedRecords; -import com.redhat.thermostat.dev.populator.dependencies.SharedState; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.dao.VmInfoDAO; -import com.redhat.thermostat.storage.model.VmInfo; - -public class VmInfoPopulatorTest { - - @Test - public void canHandleCorrectCollection() { - VmInfoPopulator populator = new VmInfoPopulator(); - assertEquals("vm-info", populator.getHandledCollection()); - } - - @SuppressWarnings("unchecked") - @Test - public void canPopulateData() { - VmInfoDAO mockDAO = mock(VmInfoDAO.class); - SharedState state = mock(SharedState.class); - ProcessedRecords<String> procRecs = mock(ProcessedRecords.class); - String[] agents = new String[] { - "foo-agent1", "foo-agent2", "bar-agent3" - }; - List<String> agentIdList = Arrays.asList(agents); - when(procRecs.getAll()).thenReturn(agentIdList); - when(state.getProcessedRecordsFor(eq("agentId"))).thenReturn(procRecs); - int perAgentVms = 44; - int subsetAlive = 23; - ConfigItem config = new ConfigItem(perAgentVms, subsetAlive, "vm-info"); - - // total records inserted will be 3 * 44. 44 records per agentId - int totalRecords = perAgentVms * agents.length; - // Initially return 0, then return the expected count - when(mockDAO.getCount()).thenReturn(0L).thenReturn((long)totalRecords); - VmInfoPopulator populator = new VmInfoPopulator(mockDAO); - populator.addPojos(mock(Storage.class), config, state); - ArgumentCaptor<VmInfo> captor = ArgumentCaptor.forClass(VmInfo.class); - verify(mockDAO, times(totalRecords)).putVmInfo(captor.capture()); - List<VmInfo> allInfos = captor.getAllValues(); - assertEquals(totalRecords, allInfos.size()); - List<VmInfo> aliveInfos = getAliveVmInfos(allInfos); - int totalAliveRecs = subsetAlive * agents.length; - assertEquals(totalAliveRecs, aliveInfos.size()); - @SuppressWarnings("rawtypes") - ArgumentCaptor<ProcessedRecords> procsVms = ArgumentCaptor.forClass(ProcessedRecords.class); - verify(state).addProcessedRecords(eq("vmId"), procsVms.capture()); - ProcessedRecords<String> processedVms = procsVms.getValue(); - assertEquals("Excected vmIds added to shared state", totalRecords, processedVms.getAll().size()); - } - - @SuppressWarnings("deprecation") - private List<VmInfo> getAliveVmInfos(List<VmInfo> allInfos) { - List<VmInfo> aliveInfos = new ArrayList<>(); - for (VmInfo info: allInfos) { - if (info.isAlive()) { - aliveInfos.add(info); - } - } - return aliveInfos; - } -}
--- a/dev/data-populator/src/test/resources/testconfig Wed May 04 17:30:06 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -{ -"records": -[ -{ - "name": "vm-gc-stats", - "number": 1000, - "alive": 1000 -}, -{ - "name": "agent-config", - "number": 100, - "alive": 20 -}, -{ - "name": "host-info", - "number": 10 -}, -{ - "name": "cpu-stats", - "number": 50000 -}, -{ - "name": "memory-stats", - "number": 50000 -}, -{ - "name": "network-info", - "number": 4 -}, -{ - "name": "vm-info", - "number": 50, - "alive": 40 -} -], -"relationships": -[ -{ "from": "agent-config", - "to": "vm-info", - "key": "agentId" -}, -{ "from": "agent-config", - "to": "host-info", - "key": "agentId" -}, -{ "from": "agent-config", - "to": "network-info", - "key": "agentId" -}, -{ "from": "vm-info", - "to": "vm-gc-stats", - "key": "vmId" -} -] -} \ No newline at end of file
--- a/dev/pom.xml Wed May 04 17:30:06 2016 +0200 +++ b/dev/pom.xml Thu May 05 10:37:43 2016 -0400 @@ -56,7 +56,7 @@ <module>ide-launcher</module> <module>schema-info-command</module> <module>perflog-analyzer</module> - <module>data-populator</module> + <module>storage-populator</module> <module>ipc-test</module> </modules>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/pom.xml Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright 2012-2016 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-storage-populator</artifactId> + <version>1.99.10-SNAPSHOT</version> + </parent> + + <artifactId>thermostat-storage-populator-command</artifactId> + <packaging>bundle</packaging> + + <name>Storage populator</name> + <url>${project.parent.url}</url> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-SymbolicName>com.redhat.thermostat.storage.populator</Bundle-SymbolicName> + <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor> + <Bundle-Activator>com.redhat.thermostat.storage.populator.internal.Activator</Bundle-Activator> + <Export-Package> + com.redhat.thermostat.storage.populator, + </Export-Package> + <Private-Package> + com.redhat.thermostat.storage.populator.internal, + com.redhat.thermostat.storage.populator.internal.config, + com.redhat.thermostat.storage.populator.internal.config.typeadapter, + com.redhat.thermostat.storage.populator.internal.dependencies, + </Private-Package> + <!-- Do not autogenerate uses clauses in Manifests --> + <_nouses>true</_nouses> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-common-test</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.framework</artifactId> + </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-storage-core</artifactId> + <version>${project.version}</version> + </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-thread-collector</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>${gson.version}</version> + </dependency> + </dependencies> + +</project> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/StoragePopulatorCommand.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,220 @@ +/* + * Copyright 2012-2016 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.storage.populator; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.cli.AbstractCommand; +import com.redhat.thermostat.common.cli.Arguments; +import com.redhat.thermostat.common.cli.CommandContext; +import com.redhat.thermostat.common.cli.CommandException; +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.common.cli.DependencyServices; +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.shared.config.CommonPaths; +import com.redhat.thermostat.shared.locale.Translate; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.storage.dao.HostInfoDAO; +import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO; +import com.redhat.thermostat.storage.dao.VmInfoDAO; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.config.PopulationConfig; +import com.redhat.thermostat.storage.populator.internal.dependencies.SharedState; +import com.redhat.thermostat.storage.populator.internal.AgentInfoPopulator; +import com.redhat.thermostat.storage.populator.internal.CollectionPopulator; +import com.redhat.thermostat.storage.populator.internal.HostInfoPopulator; +import com.redhat.thermostat.storage.populator.internal.NetworkInfoPopulator; +import com.redhat.thermostat.storage.populator.internal.ThreadPopulator; +import com.redhat.thermostat.storage.populator.internal.VmInfoPopulator; +import com.redhat.thermostat.storage.populator.internal.LocaleResources; +import com.redhat.thermostat.thread.dao.ThreadDao; + +public class StoragePopulatorCommand extends AbstractCommand { + + private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); + private static final Logger logger = LoggingUtils.getLogger(StoragePopulatorCommand.class); + + private static final String CONFIG_FILE_NAME = "config"; + + private final Map<String, CollectionPopulator> populators = new HashMap<>(); + private final DependencyServices dependencyServices = new DependencyServices(); + + private CommonPaths paths; + private HostInfoDAO hostInfoDAO; + private AgentInfoDAO agentInfoDAO; + private VmInfoDAO vmInfoDAO; + private NetworkInterfaceInfoDAO networkInfoDAO; + private ThreadDao threadDao; + + private Console console; + + public void setPaths(CommonPaths paths) { + dependencyServices.addService(CommonPaths.class, paths); + } + + public void setHostInfoDAO(HostInfoDAO dao) { + dependencyServices.addService(HostInfoDAO.class, dao); + } + + public void setAgentInfoDAO(AgentInfoDAO dao) { + dependencyServices.addService(AgentInfoDAO.class, dao); + } + + public void setVmInfoDAO(VmInfoDAO dao) { + dependencyServices.addService(VmInfoDAO.class, dao); + } + + public void setNetworkInfoDAO(NetworkInterfaceInfoDAO dao) { + dependencyServices.addService(NetworkInterfaceInfoDAO.class, dao); + } + + public void setThreadDao(ThreadDao dao) { + dependencyServices.addService(ThreadDao.class, dao); + } + + public void setServicesUnavailable() { + dependencyServices.removeService(CommonPaths.class); + dependencyServices.removeService(HostInfoDAO.class); + dependencyServices.removeService(AgentInfoDAO.class); + dependencyServices.removeService(VmInfoDAO.class); + dependencyServices.removeService(NetworkInterfaceInfoDAO.class); + dependencyServices.removeService(ThreadDao.class); + } + + @Override + public void run(CommandContext ctx) throws CommandException { + console = ctx.getConsole(); + + paths = dependencyServices.getService(CommonPaths.class); + requireNonNull(paths, + translator.localize(LocaleResources.COMMON_PATHS_SERVICE_UNAVAILABLE)); + + hostInfoDAO = dependencyServices.getService(HostInfoDAO.class); + requireNonNull(hostInfoDAO, translator.localize(LocaleResources.HOST_SERVICE_UNAVAILABLE)); + + agentInfoDAO = dependencyServices.getService(AgentInfoDAO.class); + requireNonNull(agentInfoDAO, + translator.localize(LocaleResources.AGENT_SERVICE_UNAVAILABLE)); + + vmInfoDAO = dependencyServices.getService(VmInfoDAO.class); + requireNonNull(vmInfoDAO, translator.localize(LocaleResources.VM_SERVICE_UNAVAILABLE)); + + networkInfoDAO = dependencyServices.getService(NetworkInterfaceInfoDAO.class); + requireNonNull(networkInfoDAO, + translator.localize(LocaleResources.NETWORK_SERVICE_UNAVAILABLE)); + + threadDao = dependencyServices.getService(ThreadDao.class); + requireNonNull(threadDao, translator.localize(LocaleResources.THREAD_SERVICE_UNAVAILABLE)); + + HostInfoPopulator hostInfoPopulator = new HostInfoPopulator(hostInfoDAO); + populators.put(hostInfoPopulator.getHandledCollection(), hostInfoPopulator); + + AgentInfoPopulator agentInfoPopulator = new AgentInfoPopulator(agentInfoDAO); + populators.put(agentInfoPopulator.getHandledCollection(), agentInfoPopulator); + + VmInfoPopulator vmInfoPopulator = new VmInfoPopulator(vmInfoDAO); + populators.put(vmInfoPopulator.getHandledCollection(), vmInfoPopulator); + + NetworkInfoPopulator networkInfoPopulator = new NetworkInfoPopulator(networkInfoDAO); + populators.put(networkInfoPopulator.getHandledCollection(), networkInfoPopulator); + + ThreadPopulator threadPopulator = new ThreadPopulator(threadDao); + populators.put(threadPopulator.getHandledCollection(), threadPopulator); + + try { + PopulationConfig config = getPopulationConfigFromArg(ctx.getArguments()); + addItemsToStorage(config); + } catch (IllegalArgumentException e) { + console.getError().println(e.getLocalizedMessage()); + } + } + + private PopulationConfig getPopulationConfigFromArg(Arguments args) { + File configFile = getConfigFile(args); + if (!configFile.exists()) { + throw new IllegalArgumentException(translator.localize( + LocaleResources.NONEXISTENT_CONFIG, configFile.getAbsolutePath()).getContents()); + } + String json; + PopulationConfig config; + try { + json = new String(Files.readAllBytes(configFile.toPath())); + config = PopulationConfig.parseFromJsonString(json); + } catch (IOException e) { + throw new IllegalArgumentException( + translator.localize(LocaleResources.CONFIG_PARSING_FAILED).getContents(), e); + } + + return config; + } + + /** + * Package-private to allow overriding for testing. + */ + File getConfigFile(Arguments args) { + return new File(paths.getSystemPluginConfigurationDirectory().getAbsolutePath() + + "/storage-populator/" + args.getArgument(CONFIG_FILE_NAME)); + } + + /** + * Add items to storage in topologically sorted order so as to have + * relevant depending state available. + * + * @param config The configuration describing the records to be added + */ + private void addItemsToStorage(PopulationConfig config) { + SharedState state = new SharedState(); + for (ConfigItem item: config.getConfigsTopologicallySorted()) { + state = addRecordsForConfig(item, state); + } + } + + private SharedState addRecordsForConfig(ConfigItem item, SharedState state) { + CollectionPopulator populator = populators.get(item.getName()); + if (populator == null) { + throw new IllegalArgumentException(translator.localize( + LocaleResources.NO_POPULATOR_FOUND, item.getName()).getContents()); + } else { + return populator.addPojos(item, state, console); + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/Activator.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,109 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import java.util.Hashtable; +import java.util.Map; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +import com.redhat.thermostat.common.MultipleServiceTracker; +import com.redhat.thermostat.common.cli.Command; +import com.redhat.thermostat.shared.config.CommonPaths; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.storage.dao.HostInfoDAO; +import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO; +import com.redhat.thermostat.storage.dao.VmInfoDAO; +import com.redhat.thermostat.storage.populator.StoragePopulatorCommand; +import com.redhat.thermostat.thread.dao.ThreadDao; + +public class Activator implements BundleActivator { + + private MultipleServiceTracker tracker; + + @Override + public void start(BundleContext context) throws Exception { + + final StoragePopulatorCommand command = new StoragePopulatorCommand(); + Hashtable<String,String> properties = new Hashtable<>(); + properties.put(Command.NAME, "storage-populator"); + context.registerService(Command.class, command, properties); + + Class<?>[] deps = new Class<?>[] { + CommonPaths.class, + HostInfoDAO.class, + AgentInfoDAO.class, + VmInfoDAO.class, + NetworkInterfaceInfoDAO.class, + ThreadDao.class, + }; + + tracker = new MultipleServiceTracker(context, deps, new MultipleServiceTracker.Action() { + + @Override + public void dependenciesAvailable(Map<String, Object> services) { + CommonPaths paths = (CommonPaths) services.get(CommonPaths.class.getName()); + HostInfoDAO hostInfoDAO = (HostInfoDAO) services.get(HostInfoDAO.class.getName()); + AgentInfoDAO agentInfoDAO = (AgentInfoDAO) services.get(AgentInfoDAO.class.getName()); + VmInfoDAO vmInfoDAO = (VmInfoDAO) services.get(VmInfoDAO.class.getName()); + NetworkInterfaceInfoDAO networkInfoDAO = (NetworkInterfaceInfoDAO) + services.get(NetworkInterfaceInfoDAO.class.getName()); + ThreadDao threadDao = (ThreadDao) services.get(ThreadDao.class.getName()); + + command.setPaths(paths); + command.setHostInfoDAO(hostInfoDAO); + command.setAgentInfoDAO(agentInfoDAO); + command.setVmInfoDAO(vmInfoDAO); + command.setNetworkInfoDAO(networkInfoDAO); + command.setThreadDao(threadDao); + } + + @Override + public void dependenciesUnavailable() { + command.setServicesUnavailable(); + } + }); + tracker.open(); + } + + @Override + public void stop(BundleContext context) throws Exception { + tracker.close(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/AgentInfoPopulator.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,116 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.shared.locale.Translate; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.storage.model.AgentInformation; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.dependencies.ProcessedRecords; +import com.redhat.thermostat.storage.populator.internal.dependencies.SharedState; + +public class AgentInfoPopulator extends BasePopulator { + + private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); + + private AgentInfoDAO dao; + + public AgentInfoPopulator() { + this(null); + } + + public AgentInfoPopulator(AgentInfoDAO dao) { + this.dao = dao; + } + + @Override + public SharedState addPojos(ConfigItem item, SharedState state, Console console) { + Objects.requireNonNull(dao, + translator.localize(LocaleResources.DAO_NOT_INITIALIZED).getContents()); + // Default to all alive, if unset + int aliveItems = item.getAliveItems() == ConfigItem.UNSET ? item.getNumber() : item.getAliveItems(); + List<String> processedRecords = new ArrayList<>(); + long currentTime = System.currentTimeMillis(); + long countBefore = getCount(); + console.getOutput().println("\n" + translator.localize(LocaleResources.POPULATING_RECORDS, + Integer.toString(item.getNumber()), item.getName()).getContents()); + int currCount = 0; + for (int i = 0; i < item.getNumber(); i++) { + AgentInformation agentInfo = new AgentInformation(); + String agentId = UUID.randomUUID().toString(); + processedRecords.add(agentId); + agentInfo.setAgentId(agentId); + agentInfo.setAlive(getAliveValue(aliveItems, i)); + agentInfo.setConfigListenAddress(String.format("127.0.0.1:%d", i)); + agentInfo.setStartTime(currentTime); + dao.addAgentInformation(agentInfo); + currCount++; + } + reportSubmitted(item, currCount, console); + doWaitUntilCount(countBefore + item.getNumber(), console, 200); + state.addProcessedRecords("agentId", new ProcessedRecords<>(processedRecords)); + return state; + } + + private boolean getAliveValue(int aliveItems, int i) { + if (i < aliveItems) { + return true; + } else { + return false; + } + } + + @Override + long getCount() { + return dao.getCount(); + } + + @Override + public String getHandledCollection() { + return AgentInfoDAO.CATEGORY.getName(); + } + + public void setDAO(AgentInfoDAO dao) { + this.dao = dao; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/BasePopulator.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,68 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.shared.locale.Translate; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; + +public abstract class BasePopulator implements CollectionPopulator { + + private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); + + protected void doWaitUntilCount(long expectedCount, Console console, long sleepTime) { + console.getOutput().print( + translator.localize(LocaleResources.WAITING_FOR_ARRIVAL).getContents()); + while (getCount() != expectedCount) { + try { + Thread.sleep(sleepTime); + console.getOutput().print("."); // report some progress + } catch (InterruptedException e) { + // ignore + } + } + console.getOutput().println( + translator.localize(LocaleResources.ITEMS_HAVE_ARRIVED).getContents()); + } + + protected void reportSubmitted(ConfigItem item, int totalCount, Console console) { + console.getOutput().println(translator.localize(LocaleResources.RECORDS_SUBMITTED, + Integer.toString(totalCount), item.getName()).getContents()); + } + + abstract long getCount(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/CollectionPopulator.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,48 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.dependencies.SharedState; + +public interface CollectionPopulator { + + SharedState addPojos(ConfigItem item, SharedState relState, Console console); + + String getHandledCollection(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/HostInfoPopulator.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,125 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import java.util.List; +import java.util.Objects; + +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.shared.locale.Translate; +import com.redhat.thermostat.storage.dao.HostInfoDAO; +import com.redhat.thermostat.storage.model.HostInfo; +import com.redhat.thermostat.storage.populator.internal.BasePopulator; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.dependencies.SharedState; +import com.redhat.thermostat.storage.populator.internal.LocaleResources; + +public class HostInfoPopulator extends BasePopulator { + + private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); + + private static final String[] HOSTS_FORMAT = new String[] { + "vm-host-%06d", "prometheus-%06d", "saturn-%06d" + }; + private static final String DOMAIN_FORMAT = "domain-%06d"; + private static final String HOSTNAME_SUFFIX = "example.com"; + private static final long MB = 1024 * 1024; + + private HostInfoDAO dao; + + public HostInfoPopulator() { + this(null); + } + + public HostInfoPopulator(HostInfoDAO dao) { + this.dao = dao; + } + + @Override + public SharedState addPojos(ConfigItem item, SharedState relState, Console console) { + Objects.requireNonNull(dao, + translator.localize(LocaleResources.DAO_NOT_INITIALIZED).getContents()); + List<String> agentIds = relState.getProcessedRecordsFor("agentId").getAll(); + int totalItems = agentIds.size(); + int currCount = 0; + long countBefore = getCount(); + console.getOutput().println("\n" + translator.localize(LocaleResources.POPULATING_RECORDS, + Integer.toString(totalItems), item.getName()).getContents()); + // There is a 1-to-1 correspondence between host-info and agents + for (int i = agentIds.size() - 1; i >= 0; i--) { + String agentId = agentIds.get(i); + HostInfo info = new HostInfo(); + info.setAgentId(agentId); + info.setCpuCount(getRandomInt(50 + i)); + info.setCpuModel("x86_64, data populator"); + info.setHostname(getRandomHostName(i)); + info.setOsKernel("4.2.3 data populator"); + info.setOsName("Linux Random Flavor"); + int memory = getRandomInt(500 + i); + info.setTotalMemory(memory * MB); + dao.putHostInfo(info); + currCount++; + } + reportSubmitted(item, currCount, console); + doWaitUntilCount(countBefore + totalItems, console, 200); + return relState; + } + + private String getRandomHostName(int i) { + int index = getRandomInt(HOSTS_FORMAT.length); + String hostFormat = HOSTS_FORMAT[index] + "." + DOMAIN_FORMAT + "." + HOSTNAME_SUFFIX; + return String.format(hostFormat, i, i); + } + + private int getRandomInt(int i) { + return (int)(Math.random() * i); + } + + @Override + long getCount() { + return dao.getCount(); + } + + @Override + public String getHandledCollection() { + return HostInfoDAO.hostInfoCategory.getName(); + } + + public void setDAO(HostInfoDAO dao) { + this.dao = dao; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/LocaleResources.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,68 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import com.redhat.thermostat.shared.locale.Translate; + + +public enum LocaleResources { + + COMMON_PATHS_SERVICE_UNAVAILABLE, + HOST_SERVICE_UNAVAILABLE, + AGENT_SERVICE_UNAVAILABLE, + VM_SERVICE_UNAVAILABLE, + NETWORK_SERVICE_UNAVAILABLE, + THREAD_SERVICE_UNAVAILABLE, + DAO_NOT_INITIALIZED, + WAITING_FOR_ARRIVAL, + ITEMS_HAVE_ARRIVED, + RECORDS_SUBMITTED, + POPULATING_RECORDS, + NONEXISTENT_CONFIG, + CONFIG_PARSING_FAILED, + NO_POPULATOR_FOUND, + ; + + static final String RESOURCE_BUNDLE = + "com.redhat.thermostat.storage.populator.command.locale.strings"; + + public static Translate<LocaleResources> createLocalizer() { + return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class); + } + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/NetworkInfoPopulator.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,158 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import java.util.List; +import java.util.Objects; + +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.shared.locale.Translate; +import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO; +import com.redhat.thermostat.storage.model.NetworkInterfaceInfo; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.dependencies.ProcessedRecords; +import com.redhat.thermostat.storage.populator.internal.dependencies.SharedState; + +public class NetworkInfoPopulator extends BasePopulator { + + private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); + + static final String[] IPV4_FORMATS = new String[] { + "192.168.0.%d", "10.33.4.%d", "89.15.93.%d" + }; + static final String[] IPV6_FORMATS = new String[] { + "e8:b1:fc:d2:e3:%s%%%s", "fe80::56ee:75ff:fe35:%s%%%s", + "0:0:0:0:0:0:0:%s%%%s" + }; + private final String[] IFACE_NAMES = new String[] { + "lo", "enp0s25", "tun0", "virbr0", "wlp4s0" + }; + private static int IPv6Mod = Integer.parseInt("ffff", 16); + private static int IPv4Mod = 255; + + private NetworkInterfaceInfoDAO dao; + + public NetworkInfoPopulator() { + this(null); + } + + public NetworkInfoPopulator(NetworkInterfaceInfoDAO dao) { + this.dao = dao; + } + + @Override + public SharedState addPojos(ConfigItem item, SharedState relState, Console console) { + Objects.requireNonNull(dao, + translator.localize(LocaleResources.DAO_NOT_INITIALIZED).getContents()); + ProcessedRecords<String> procAgents = relState.getProcessedRecordsFor("agentId"); + List<String> allAgents = procAgents.getAll(); + long countBefore = getCount(); + int totalItems = item.getNumber() * allAgents.size(); + // populate network info records per agentID + console.getOutput().println("\n" + translator.localize(LocaleResources.POPULATING_RECORDS, + Integer.toString(totalItems), item.getName()).getContents()); + int currVal = 0; + for (String agentId: allAgents) { + for (int i = 0; i < item.getNumber(); i++) { + NetworkInterfaceInfo info = new NetworkInterfaceInfo(); + info.setAgentId(agentId); + String name = getRandomInterfaceName(i); + info.setInterfaceName(name); + info.setIp6Addr(getRandomIpv6Address(i, name)); + info.setIp4Addr(getRandomIpv4Addrees(i)); + dao.putNetworkInterfaceInfo(info); + currVal++; + } + } + reportSubmitted(item, currVal, console); + doWaitUntilCount(countBefore + totalItems, console, 200); + return relState; + } + + private String getRandomIpv4Addrees(int i) { + int idx = getRandomInt(IPV4_FORMATS.length); + return String.format(IPV4_FORMATS[idx], getIpv4Octet(i)); + } + + private int getRandomInt(int upperBound) { + return (int)(Math.random() * upperBound); + } + + private String getRandomIpv6Address(int i, String name) { + int idx = getRandomInt(IPV6_FORMATS.length); + return String.format(IPV6_FORMATS[idx], getIpv6Hextet(i), name); + } + + // package-private for testing + String getIpv6Hextet(int i) { + int remainder = i % IPv6Mod; + if (remainder == 0) { + // 0 isn't really an IP, make it 1 instead. + remainder = 1; + } + return Integer.toHexString(remainder); + } + + // package-private for testing + int getIpv4Octet(int i) { + int remainder = i % IPv4Mod; + if (remainder == 0) { + // 0 is network address, switch to IP + remainder = 1; + } + return remainder; + } + + private String getRandomInterfaceName(int i) { + int idx = getRandomInt(IFACE_NAMES.length); + return IFACE_NAMES[idx] + i; + } + + @Override + long getCount() { + return dao.getCount(); + } + + @Override + public String getHandledCollection() { + return NetworkInterfaceInfoDAO.networkInfoCategory.getName(); + } + + public void setDAO(NetworkInterfaceInfoDAO dao) { + this.dao = dao; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/ThreadPopulator.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,254 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Random; + +import com.redhat.thermostat.common.Pair; +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.shared.locale.Translate; +import com.redhat.thermostat.storage.populator.internal.BasePopulator; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.dependencies.SharedState; +import com.redhat.thermostat.storage.populator.internal.LocaleResources; +import com.redhat.thermostat.thread.dao.ThreadDao; +import com.redhat.thermostat.thread.model.ThreadHarvestingStatus; +import com.redhat.thermostat.thread.model.ThreadSession; +import com.redhat.thermostat.thread.model.ThreadState; +import com.redhat.thermostat.thread.model.ThreadSummary; +import com.redhat.thermostat.thread.model.VmDeadLockData; + +public class ThreadPopulator extends BasePopulator { + + private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); + + /** + * Package-private and static for testing. + */ + static final int NUM_SAMPLES = 10; + + public final String SESSION = "session"; + private final int NUM_THREADS = 3; + private final long SEED = 5; + Random generator = new Random(SEED); + private static final String[] THREAD_NAMES = new String[] { + "Spencer", "Sheldon", "Alice", "Bob", "Julie", "Phoebe", "Alpha", "Beta", "Gamma", + "Theta", "Zeta", + }; + static final String DEADLOCK_DESC_FORMAT = "" + + "\"%s\" Id=%d WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@52de95c7 owned by \"%s\" Id=%d\n" + + "\tat sun.misc.Unsafe.park(Native Method)\n" + + "\t- waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@52de95c7\n" + + "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)\n" + + "\tat java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)\n" + + "\tat java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)\n" + + "\tat com.redhat.thermostat.tests.DeadLock$Philosopher.run(DeadLock.java:57)\n" + + "\t...\n\n" + + "\tNumber of locked synchronizers = 1\n" + + "\t- java.util.concurrent.locks.ReentrantLock$NonfairSync@441634c2\n" + + "\n\n" + + "\"%s\" Id=%d WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@105ff84e owned by \"%s\" Id=%d\n" + + "\tat sun.misc.Unsafe.park(Native Method)\n" + + "\t- waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@105ff84e\n" + + "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)\n" + + "\tat java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)\n" + + "\tat java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)\n" + + "\tat com.redhat.thermostat.tests.DeadLock$Philosopher.run(DeadLock.java:57)\n" + + "\t...\n\n" + + "\tNumber of locked synchronizers = 1\n" + + "\t- java.util.concurrent.locks.ReentrantLock$NonfairSync@52de95c7\n" + + "\n\n" + + "\"%s\" Id=%d WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@441634c2 owned by \"%s\" Id=%d\n" + + "\tat sun.misc.Unsafe.park(Native Method)\n" + + "\t- waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@441634c2\n" + + "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)\n" + + "\tat java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)\n" + + "\tat java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)\n" + + "\tat com.redhat.thermostat.tests.DeadLock$Philosopher.run(DeadLock.java:57)\n" + + "\t...\n\n" + + "\tNumber of locked synchronizers = 1\n" + + "\t- java.util.concurrent.locks.ReentrantLock$NonfairSync@105ff84e\n\n\n"; + + + private ThreadDao dao; + + public ThreadPopulator() { + this(null); + } + + public ThreadPopulator(ThreadDao dao) { + this.dao = dao; + } + + @Override + public SharedState addPojos(ConfigItem item, SharedState relState, Console console) { + Objects.requireNonNull(dao, + translator.localize(LocaleResources.DAO_NOT_INITIALIZED).getContents()); + // creates records per agent *and* vm + List<String> agentIds = relState.getProcessedRecordsFor("agentId").getAll(); + List<String> vmIds = relState.getProcessedRecordsFor("vmId").getAll(); + int perVmNumber = item.getNumber(); + int totalCount = perVmNumber * agentIds.size() * vmIds.size(); + int currCount = 0; + long countBefore = getCount(); + console.getOutput().println("\n" +translator.localize(LocaleResources.POPULATING_RECORDS, + Integer.toString(totalCount), item.getName()).getContents()); + long currTime = System.currentTimeMillis(); + for (String agentId: agentIds) { + for (String vmId: vmIds) { + for (int i = 0; i < perVmNumber; i++) { + ThreadSummary summary = new ThreadSummary(); + summary.setAgentId(agentId); + summary.setVmId(vmId); + int liveThreads = generator.nextInt(NUM_THREADS); + summary.setCurrentLiveThreads(liveThreads); + int daemonThreads = NUM_THREADS - liveThreads; + summary.setCurrentDaemonThreads(daemonThreads); + long timeStamp = currTime + i * 1000; + summary.setTimeStamp(timeStamp); + dao.saveSummary(summary); + + ThreadSession session = new ThreadSession(); + session.setSession(SESSION); + session.setTimeStamp(timeStamp); + session.setAgentId(agentId); + session.setVmId(vmId); + dao.saveSession(session); + + final Thread.State[] states = Thread.State.values(); + String state = states[generator.nextInt(states.length)].toString(); + String name = THREAD_NAMES[generator.nextInt(THREAD_NAMES.length)]; + + for(int j = 0; j < NUM_SAMPLES; j++) { + ThreadState threadState = new ThreadState(); + threadState.setTimeStamp(currTime + j * 1000); + threadState.setVmId(vmId); + threadState.setAgentId(agentId); + threadState.setState(state); + threadState.setId(i); + threadState.setName(name); + threadState.setSession(SESSION); + dao.addThreadState(threadState); + } + + ThreadHarvestingStatus status = new ThreadHarvestingStatus(agentId); + status.setVmId(vmId); + status.setTimeStamp(timeStamp); + status.setHarvesting(generator.nextBoolean()); + dao.saveHarvestingStatus(status); + + VmDeadLockData data = new VmDeadLockData(); + data.setAgentId(agentId); + data.setVmId(vmId); + data.setTimeStamp(currTime + i * 10); + data.setDeadLockDescription(getDeadlockedDescription(currCount)); + dao.saveDeadLockStatus(data); + currCount++; + } + } + } + reportSubmitted(item, currCount, console); + doWaitUntilCount(countBefore + totalCount, console, 200); + return relState; + } + + private String getDeadlockedDescription(int currCount) { + return String.format(DEADLOCK_DESC_FORMAT, getFormatStringArgs(currCount)); + } + + Object[] getFormatStringArgs(int currCount) { + List<Pair<String, Integer>> nameIdMapping = new ArrayList<>(); + int[] randomIds = getIdValues(currCount, NUM_THREADS); + int randomEntry = getRandomInt(THREAD_NAMES.length); + for (int i = 0, idx; i < NUM_THREADS; i++) { + idx = (randomEntry + i) % THREAD_NAMES.length; + String name = THREAD_NAMES[idx]; + int tid = randomIds[i]; + nameIdMapping.add(new Pair<>(name, tid)); + } + Object[] formatArgs = new Object[NUM_THREADS * 2 * 2]; + formatArgs[0] = nameIdMapping.get(0).getFirst(); + formatArgs[1] = nameIdMapping.get(0).getSecond(); + for (int i = 2, j = 1; i < formatArgs.length - 2; i+= 4, j++) { + formatArgs[i] = nameIdMapping.get(j).getFirst(); + formatArgs[i + 1] = nameIdMapping.get(j).getSecond(); + formatArgs[i + 2] = nameIdMapping.get(j).getFirst(); + formatArgs[i + 3] = nameIdMapping.get(j).getSecond(); + } + formatArgs[formatArgs.length - 2] = nameIdMapping.get(0).getFirst(); + formatArgs[formatArgs.length - 1] = nameIdMapping.get(0).getSecond(); + return formatArgs; + } + + private int getRandomInt(int len) { + return (int)(Math.random() * len); + } + + private int[] getIdValues(int currCount, int length) { + int[] values = new int[length]; + for (int i = 0; i < values.length; i++) { + values[i] = currCount + i; + } + return values; + } + + @Override + long getCount() { + return dao.getDeadLockCount(); + } + + @Override + public String getHandledCollection() { + return ThreadDao.THREAD_HARVESTING_STATUS.getName(); + } + + public void setDAO(ThreadDao dao) { + this.dao = dao; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/VmInfoPopulator.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,161 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; + +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.shared.locale.Translate; +import com.redhat.thermostat.storage.dao.VmInfoDAO; +import com.redhat.thermostat.storage.model.VmInfo; +import com.redhat.thermostat.storage.populator.internal.BasePopulator; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.dependencies.ProcessedRecords; +import com.redhat.thermostat.storage.populator.internal.dependencies.SharedState; +import com.redhat.thermostat.storage.populator.internal.LocaleResources; + +public class VmInfoPopulator extends BasePopulator { + + private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); + + private VmInfoDAO dao; + + public VmInfoPopulator() { + this(null); + } + + public VmInfoPopulator(VmInfoDAO dao) { + this.dao = dao; + } + + @Override + public SharedState addPojos(ConfigItem item, SharedState relState, Console console) { + Objects.requireNonNull(dao, + translator.localize(LocaleResources.DAO_NOT_INITIALIZED).getContents()); + // Default to all alive, if unset + int aliveItems = item.getAliveItems() == ConfigItem.UNSET ? item.getNumber() : item.getAliveItems(); + ProcessedRecords<String> procAgents = relState.getProcessedRecordsFor("agentId"); + List<String> vmIds = new ArrayList<>(); + List<String> allAgents = procAgents.getAll(); + long countBefore = getCount(); + int totalItems = item.getNumber() * allAgents.size(); + // populate VM records per agentID + console.getOutput().println("\n" + translator.localize(LocaleResources.POPULATING_RECORDS, + Integer.toString(totalItems), item.getName()).getContents()); + int currVal = 0; + for (String agentId: allAgents) { + for (int i = 0; i < item.getNumber(); i++) { + VmInfo info = new VmInfo(); + info.setAgentId(agentId); + info.setJavaCommandLine("java DataPopulatorProducedVM --vm " + i + " --version"); + info.setJavaHome("/opt/foo/bar/java-1.8.0-openjdk/jre"); + info.setJavaVersion("1.8.0"); + info.setMainClass("com.redhat.thermostat.TestDataPopulator"); + info.setLoadedNativeLibraries(new String[] { "glibc.so", "something.so" }); + info.setProperties(getFakeJavaProperties(i, agentId)); + StartStopTimeStamp ts = getFakeStartStopTimeStamp(i, aliveItems); + info.setStartTimeStamp(ts.startTS); + info.setStopTimeStamp(ts.stopTS); + info.setUsername("vm-user-" + i); + info.setUid(i); + info.setVmArguments("-XX:+UseG1Gc"); + String vmId = UUID.randomUUID().toString(); + info.setVmId(vmId); + vmIds.add(vmId); + info.setVmInfo("OpenJDK 8"); + info.setVmPid(34 + i); + info.setVmVersion("hs 25"); + info.setVmName("Hotspot"); + dao.putVmInfo(info); + currVal++; + } + } + reportSubmitted(item, currVal, console); + doWaitUntilCount(countBefore + totalItems, console, 200); + relState.addProcessedRecords("vmId", new ProcessedRecords<>(vmIds)); + return relState; + } + + private StartStopTimeStamp getFakeStartStopTimeStamp(int num, int aliveItems) { + long currTime = System.currentTimeMillis(); + if (num < aliveItems) { + // create alive timestamp pair + long startTs = Long.MAX_VALUE; + long stopTs = currTime; + return new StartStopTimeStamp(startTs, stopTs); + } + // create dead timestamp pair + return new StartStopTimeStamp(currTime - (1000 + num), currTime - (500 + num)); + } + + private Map<String, String> getFakeJavaProperties(int i, String agentId) { + Map<String, String> props = new HashMap<String, String>(); + props.put("foo", "bar"); + props.put("vm#", Integer.toString(i)); + props.put("agentId", agentId); + return props; + } + + @Override + long getCount() { + return dao.getCount(); + } + + @Override + public String getHandledCollection() { + return VmInfoDAO.vmInfoCategory.getName(); + } + + private static class StartStopTimeStamp { + private final long startTS; + private final long stopTS; + + private StartStopTimeStamp(long start, long stop) { + this.startTS = start; + this.stopTS = stop; + } + } + + public void setDAO(VmInfoDAO dao) { + this.dao = dao; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/config/ConfigItem.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,72 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.config; + +public class ConfigItem { + + public static final String NAME = "name"; + public static final String NUMBER = "number"; + public static final String ALIVE = "alive"; + + public static final int UNSET = -1; + private final int number; + private final int aliveItems; + private final String name; + + public ConfigItem(int number, int aliveItems, String name) { + this.number = number; + this.aliveItems = aliveItems; + this.name = name; + } + + public int getNumber() { + return number; + } + + public int getAliveItems() { + return aliveItems; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return name + " (" + number + "/" + aliveItems + ")"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/config/PopulationConfig.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,228 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.config; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.redhat.thermostat.storage.populator.internal.config.typeadapter.ConfigItemTypeAdapter; +import com.redhat.thermostat.storage.populator.internal.config.typeadapter.PopulationConfigTypeAdapterFactory; +import com.redhat.thermostat.storage.populator.internal.config.typeadapter.RelationShipTypeAdapter; +import com.redhat.thermostat.storage.populator.internal.dependencies.Relationship; + +public class PopulationConfig { + + public static final String RECORDS = "records"; + public static final String RELATIONSHIPS = "relationships"; + private final Map<String, ConfigItem> configs; + private final List<ConfigItem> allConfigs; + private final Map<String, List<Relationship>> incomingRelationShips; + private final Map<String, List<Relationship>> outgoingRelationShips; + + private PopulationConfig() { + configs = new HashMap<>(); + allConfigs = new ArrayList<>(); + incomingRelationShips = new HashMap<>(); + outgoingRelationShips = new HashMap<>(); + } + + public ConfigItem getConfig(String name) { + return configs.get(name); + } + + public List<ConfigItem> getConfigsTopologicallySorted() { + return topologicallySort(allConfigs); + } + + /** + * Sort config items topologically. That is, get them in an order so as + * to process collections with no incoming links to other collections. + * + * It uses Kahn's algorithm to do so. + * + * @param configs unsorted configs. + * @return A topologically sorted list. + */ + private List<ConfigItem> topologicallySort(List<ConfigItem> configs) { + LinkedList<ConfigItem> sortedList = new LinkedList<>(); + LinkedList<ConfigItem> queue = getConfigItemsWithNoIncomingEdge(configs); + while (!queue.isEmpty()) { + ConfigItem n = queue.remove(0); + sortedList.addLast(n); + List<Relationship> source = getOutgoingRelationShipsForConfig(n); + List<Relationship> outgoingRels = new LinkedList<>(source); + for (Relationship edge: outgoingRels) { + ConfigItem m = getConfig(edge.getTo()); + removeEdge(edge, n, m); + if (hasNoIncomingEdge(m)) { + queue.addLast(m); + } + } + } + if (hasRelationShips(configs)) { + throw new AssertionError("Relationships form at least one cycle! Excpected an acyclic directed graph."); + } + return sortedList; + } + + private boolean hasRelationShips(List<ConfigItem> configs) { + for (ConfigItem i: configs) { + List<Relationship> incoming = getIncomingRelationShipsForConfig(i); + List<Relationship> outgoing = getOutgoingRelationShipsForConfig(i); + if (!incoming.isEmpty() || + !outgoing.isEmpty()) { + // We are going to bomb, print some debug info. + System.err.println("outgoings for " + i.getName() + " " + outgoing); + System.err.println("incomings for " + i.getName() + " " + incoming); + return true; + } + } + return false; + } + + private void removeEdge(Relationship toRemove, ConfigItem from, ConfigItem to) { + if (from == null || to == null) { + throw new InvalidConfigurationException("Found relationship [" + + toRemove + + "] but either incoming or outgoing records config is missing"); + } + List<Relationship> incoming = getIncomingRelationShipsForConfig(to); + List<Relationship> outgoing = getOutgoingRelationShipsForConfig(from); + incoming.remove(toRemove); + outgoing.remove(toRemove); + } + + private LinkedList<ConfigItem> getConfigItemsWithNoIncomingEdge(List<ConfigItem> allConfigs) { + LinkedList<ConfigItem> startNodes = new LinkedList<>(); + for (ConfigItem item: allConfigs) { + if (hasNoIncomingEdge(item)) { + startNodes.add(item); + } + } + return startNodes; + } + + private boolean hasNoIncomingEdge(ConfigItem item) { + List<Relationship> rels = getIncomingRelationShipsForConfig(item); + if (rels == null || rels.isEmpty()) { + return true; + } + return false; + } + + private List<Relationship> getIncomingRelationShipsForConfig(ConfigItem item) { + List<Relationship> result = incomingRelationShips.get(item.getName()); + if (result == null) { + return Collections.emptyList(); + } + return result; + } + + private List<Relationship> getOutgoingRelationShipsForConfig(ConfigItem item) { + List<Relationship> result = outgoingRelationShips.get(item.getName()); + if (result == null) { + return Collections.emptyList(); + } + return result; + } + + private void addConfig(ConfigItem item) { + configs.put(item.getName(), item); + allConfigs.add(item); + } + + private void addIncomingRelationShipForConfig(ConfigItem item, Relationship relationship) { + addRelationShip(item, relationship, incomingRelationShips); + } + + private void addOutgoingRelationShipForConfig(ConfigItem item, Relationship relationship) { + addRelationShip(item, relationship, outgoingRelationShips); + } + + private void addRelationShip(ConfigItem item, Relationship relationship, Map<String, List<Relationship>> map) { + List<Relationship> existingRels = map.get(item.getName()); + if (existingRels == null) { + existingRels = new LinkedList<>(); + map.put(item.getName(), existingRels); + } + existingRels.add(relationship); + } + + public static PopulationConfig parseFromJsonString(String json) throws IOException { + Gson gson= new GsonBuilder() + .registerTypeAdapter(ConfigItem.class, new ConfigItemTypeAdapter()) + .registerTypeAdapter(Relationship.class, new RelationShipTypeAdapter()) + .registerTypeAdapterFactory(new PopulationConfigTypeAdapterFactory()) + .create(); + PopulationConfig pc = gson.fromJson(json, PopulationConfig.class); + return pc; + } + + public static PopulationConfig createFromLists(List<ConfigItem> items, List<Relationship> rels) { + PopulationConfig pc = new PopulationConfig(); + for (ConfigItem item: items) { + pc.addConfig(item); + for (Relationship r: rels) { + // keep track of incoming relationships (incoming edge) + if (r.getTo().equals(item.getName())) { + pc.addIncomingRelationShipForConfig(item, r); + } + // keep track of outgoing relationships (outgoing edge) + if (r.getFrom().equals(item.getName())) { + pc.addOutgoingRelationShipForConfig(item, r); + } + } + } + return pc; + } + + @SuppressWarnings("serial") + static class InvalidConfigurationException extends RuntimeException { + + private InvalidConfigurationException(String msg) { + super(msg); + } + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/config/typeadapter/ConfigItemTypeAdapter.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,113 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.config.typeadapter; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; + +public class ConfigItemTypeAdapter extends TypeAdapter<ConfigItem> { + + @Override + public ConfigItem read(JsonReader reader) throws IOException { + // handle null + if (reader.peek() == JsonToken.NULL) { + reader.nextNull(); + return null; + } + + reader.beginObject(); + ConfigItem item = parseConfigItem(reader); + reader.endObject(); + + return item; + } + + private ConfigItem parseConfigItem(JsonReader reader) throws IOException { + Map<String, Object> values = new HashMap<>(); + while (reader.hasNext()) { + String name = reader.nextName(); + switch(name) { + case ConfigItem.NAME: + values.put(ConfigItem.NAME, reader.nextString()); + break; + case ConfigItem.ALIVE: + values.put(ConfigItem.ALIVE, reader.nextInt()); + break; + case ConfigItem.NUMBER: + values.put(ConfigItem.NUMBER, reader.nextInt()); + break; + default: + throw new IllegalStateException("Unknown config value: '" + name + "'"); + } + } + String collName = (String)values.get(ConfigItem.NAME); + String collectionDetails = collName == null ? "" : "[" + collName + "] "; + Integer number = (Integer)values.get(ConfigItem.NUMBER); + Integer aliveItems = (Integer)values.get(ConfigItem.ALIVE); + int aliveItemsForSanityTest = getAliveCount(aliveItems); + if (number < 0 || aliveItemsForSanityTest < 0) { + throw new IllegalArgumentException(collectionDetails + "number of items and alive items must be positive"); + } + if (number - aliveItemsForSanityTest < 0) { + throw new IllegalArgumentException(collectionDetails + "alive items > number of total items."); + } + return new ConfigItem(getValue(number), getValue(aliveItems), collName); + } + + private int getAliveCount(Integer aliveItems) { + if (aliveItems != null) { + return aliveItems; + } + return 0; // return 0 for unset, just so that we make sanity checks happy + } + + private int getValue(Integer value) { + return value == null ? ConfigItem.UNSET : value; + } + + @Override + public void write(JsonWriter writer, ConfigItem item) throws IOException { + throw new NotImplementedException(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/config/typeadapter/NotImplementedException.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,42 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.config.typeadapter; + +@SuppressWarnings("serial") +class NotImplementedException extends RuntimeException { + // nothing +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/config/typeadapter/PopulationConfigTypeAdapter.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,115 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.config.typeadapter; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.config.PopulationConfig; +import com.redhat.thermostat.storage.populator.internal.dependencies.Relationship; + +public class PopulationConfigTypeAdapter extends TypeAdapter<PopulationConfig> { + + private final Gson gson; + + public PopulationConfigTypeAdapter(Gson gson) { + this.gson = gson; + } + + @Override + public void write(JsonWriter out, PopulationConfig config) throws IOException { + throw new NotImplementedException(); + } + + @Override + public PopulationConfig read(JsonReader in) throws IOException { + // handle null + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + in.beginObject(); + PopulationConfig config = parsePopulationConfig(in); + in.endObject(); + return config; + } + + private PopulationConfig parsePopulationConfig(JsonReader in) throws IOException { + Map<String, Object> values = new HashMap<>(); + while (in.hasNext()) { + String name = in.nextName(); + switch(name) { + case PopulationConfig.RECORDS: + values.put(PopulationConfig.RECORDS, parseRecords(in)); + break; + case PopulationConfig.RELATIONSHIPS: + values.put(PopulationConfig.RELATIONSHIPS, parseRelationships(in)); + break; + default: + throw new IllegalStateException("Unknown population config value: '" + name + "'"); + } + } + ConfigItem[] rawItems = (ConfigItem[])values.get(PopulationConfig.RECORDS); + Relationship[] rawRels = (Relationship[])values.get(PopulationConfig.RELATIONSHIPS); + List<Relationship> rels; + if (rawRels == null) { + rels = Collections.emptyList(); + } else { + rels = Arrays.asList(rawRels); + } + return PopulationConfig.createFromLists(Arrays.asList(rawItems), rels); + } + + private Relationship[] parseRelationships(JsonReader in) { + return gson.fromJson(in, Relationship[].class); + } + + private ConfigItem[] parseRecords(JsonReader in) throws IOException { + return gson.fromJson(in, ConfigItem[].class); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/config/typeadapter/PopulationConfigTypeAdapterFactory.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,58 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.config.typeadapter; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.redhat.thermostat.storage.populator.internal.config.PopulationConfig; + +public class PopulationConfigTypeAdapterFactory implements TypeAdapterFactory { + + @Override + public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { + Class<?> rawType = type.getRawType(); + if (rawType == PopulationConfig.class) { + @SuppressWarnings("unchecked") + TypeAdapter<T> ta = (TypeAdapter<T>)new PopulationConfigTypeAdapter(gson); + return ta; + } + return null; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/config/typeadapter/RelationShipTypeAdapter.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,92 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.config.typeadapter; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import com.redhat.thermostat.storage.populator.internal.dependencies.Relationship; + +public class RelationShipTypeAdapter extends TypeAdapter<Relationship> { + + @Override + public Relationship read(JsonReader in) throws IOException { + // handle null + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + + in.beginObject(); + Relationship rel = parseRelationShip(in); + in.endObject(); + + return rel; + } + + private Relationship parseRelationShip(JsonReader in) throws IOException { + Map<String, String> values = new HashMap<>(); + while (in.hasNext()) { + String name = in.nextName(); + switch(name) { + case Relationship.FROM: + values.put(Relationship.FROM, in.nextString()); + break; + case Relationship.TO: + values.put(Relationship.TO, in.nextString()); + break; + case Relationship.KEY: + values.put(Relationship.KEY, in.nextString()); + break; + default: + throw new IllegalStateException("Unknown relationship value: '" + name + "'"); + } + } + return new Relationship(values.get(Relationship.FROM), values.get(Relationship.TO), values.get(Relationship.KEY)); + } + + @Override + public void write(JsonWriter out, Relationship relationship) throws IOException { + throw new NotImplementedException(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/dependencies/ProcessedRecords.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.dependencies; + +import java.util.List; + +/** + * + * @param <T> The underlying type of the key + */ +public class ProcessedRecords<T> { + + private final List<T> allRecords; + + public ProcessedRecords(List<T> allRecords) { + this.allRecords = allRecords; + } + + public List<T> getAll() { + return allRecords; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/dependencies/Relationship.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,88 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.dependencies; + +import java.util.Objects; + +public class Relationship { + + public static final String TO = "to"; + public static final String FROM = "from"; + public static final String KEY = "key"; + private final String from; + private final String to; + private final String key; + + public Relationship(String from, String to, String key) { + this.from = from; + this.to = to; + this.key = key; + } + + public String getFrom() { + return from; + } + + public String getTo() { + return to; + } + + public String getKey() { + return key; + } + + @Override + public boolean equals(Object o) { + if (o == null || o.getClass() != Relationship.class) { + return false; + } + Relationship other = (Relationship)o; + return Objects.equals(to, other.to) && + Objects.equals(from, other.from) && + Objects.equals(key, other.key); + } + + @Override + public int hashCode() { + return Objects.hash(to, from, key); + } + + @Override + public String toString() { + return from + " -> " + to + "(" + key + ")"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/java/com/redhat/thermostat/storage/populator/internal/dependencies/SharedState.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,69 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.dependencies; + +import java.util.HashMap; +import java.util.Map; + +public class SharedState { + + private final Map<Object, ProcessedRecords<?>> processedRecs; + private final Map<String, Object> props; + + public SharedState() { + processedRecs = new HashMap<>(); + props = new HashMap<>(); + } + + public <T> ProcessedRecords<T> getProcessedRecordsFor(T key) { + @SuppressWarnings("unchecked") + ProcessedRecords<T> item = (ProcessedRecords<T>)processedRecs.get(key); + return item; + } + + public <T> void addProcessedRecords(T key, ProcessedRecords<T> recs) { + processedRecs.put(key, recs); + } + + public void addProperty(String key, Object value) { + props.put(key, value); + } + + public Object getProperty(String key) { + return props.get(key); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,1 @@ +com.redhat.thermostat.storage.profile.internal.StorageProfileCommand \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.StatementDescriptorRegistration Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,1 @@ +com.redhat.thermostat.storage.profile.internal.StorageProfileCommand \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/main/resources/com/redhat/thermostat/storage/populator/command/locale/strings.properties Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,14 @@ +COMMON_PATHS_SERVICE_UNAVAILABLE = Unable to get CommonPaths service. +HOST_SERVICE_UNAVAILABLE = Unable to get HostInfoDAO service. +AGENT_SERVICE_UNAVAILABLE = Unable to get AgentInfoDAO service. +VM_SERVICE_UNAVAILABLE = Unable to get VmInfoDAO service. +NETWORK_SERVICE_UNAVAILABLE = Unable to get NetworkInterfaceInfoDAO service. +THREAD_SERVICE_UNAVAILABLE = Unable to get ThreadDao service. +DAO_NOT_INITIALIZED = DAO must be initialized to populate. +WAITING_FOR_ARRIVAL = Waiting for storage items to arrive at backend... +ITEMS_HAVE_ARRIVED = Items have arrived. +POPULATING_RECORDS = Populating {0} {1} records... +RECORDS_SUBMITTED = Submitted {0} {1} records to storage. +NONEXISTENT_CONFIG = Config file "{0}" does not exist! +CONFIG_PARSING_FAILED = Failed to parse config file. +NO_POPULATOR_FOUND = No populator for collection "{0}" found. \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/StoragePopulatorCommandTest.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,227 @@ +/* + * Copyright 2012-2016 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.storage.populator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +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.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.common.cli.Arguments; +import com.redhat.thermostat.common.cli.CommandContext; +import com.redhat.thermostat.common.cli.CommandException; +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.shared.config.CommonPaths; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.storage.dao.HostInfoDAO; +import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO; +import com.redhat.thermostat.storage.dao.VmInfoDAO; +import com.redhat.thermostat.storage.model.AgentInformation; +import com.redhat.thermostat.storage.model.HostInfo; +import com.redhat.thermostat.storage.model.NetworkInterfaceInfo; +import com.redhat.thermostat.storage.model.VmInfo; +import com.redhat.thermostat.thread.dao.ThreadDao; +import com.redhat.thermostat.thread.model.VmDeadLockData; + +public class StoragePopulatorCommandTest { + + private static final String SOME_CONFIG = "config"; + + private StoragePopulatorCommand command; + private CommandContext ctx; + private Arguments args; + + CommonPaths paths; + HostInfoDAO hostInfoDAO; + AgentInfoDAO agentInfoDAO; + VmInfoDAO vmInfoDAO; + NetworkInterfaceInfoDAO networkInfoDAO; + ThreadDao threadDao; + + private ByteArrayOutputStream outputBAOS, errorBAOS; + private PrintStream output, error; + private Console console; + + @Before + public void setUp() { + ctx = mock(CommandContext.class); + args = mock(Arguments.class); + + console = mock(Console.class); + + outputBAOS = new ByteArrayOutputStream(); + output = new PrintStream(outputBAOS); + + errorBAOS = new ByteArrayOutputStream(); + error = new PrintStream(errorBAOS); + + when(ctx.getArguments()).thenReturn(args); + when(ctx.getConsole()).thenReturn(console); + when(console.getError()).thenReturn(error); + when(console.getOutput()).thenReturn(output); + } + + @Test + public void testCommandFailsWhenDependenciesUnavailable() { + command = new StoragePopulatorCommand(); + command.setServicesUnavailable(); + + try { + command.run(ctx); + fail("A CommandException was expected but not thrown."); + } catch (CommandException e) { + assertTrue(e.getMessage().matches("Unable to get .* service\\.")); + } + } + + @Test + public void testCommandFailsWithNonexistentConfig() throws CommandException { + final File nonexistentConfig = mock(File.class); + when(nonexistentConfig.exists()).thenReturn(false); + when(nonexistentConfig.getAbsolutePath()).thenReturn("/foo/bar/" + SOME_CONFIG); + command = new StoragePopulatorCommand() { + @Override + File getConfigFile(Arguments args) { + return nonexistentConfig; + } + }; + setUpServices(); + + command.run(ctx); + String errorString = new String(errorBAOS.toByteArray()); + assertEquals("Config file \"/foo/bar/config\" does not exist!\n", errorString); + } + + @Test + public void testCommandFailsWithInvalidConfig() throws CommandException, IOException { + final File invalidConfig = mock(File.class); + when(invalidConfig.exists()).thenReturn(true); + when(invalidConfig.toPath()).thenThrow(IOException.class); + + command = new StoragePopulatorCommand() { + @Override + File getConfigFile(Arguments args) { + return invalidConfig; + } + }; + setUpServices(); + + command.run(ctx); + String errorString = new String(errorBAOS.toByteArray()); + assertEquals("Failed to parse config file.\n", errorString); + } + + @Test + public void testCommandFailsWithInvalidPopulator() throws CommandException { + final File invalidConfigFile = new File( + getClass().getResource("/invalid-config.json").getFile()); + command = new StoragePopulatorCommand() { + @Override + File getConfigFile(Arguments args) { + return invalidConfigFile; + } + }; + setUpServices(); + + command.run(ctx); + String errorString = new String(errorBAOS.toByteArray()); + assertEquals("No populator for collection \"foo\" found.\n", errorString); + } + + @Test + public void testCommandPopulatesDatabase() throws CommandException { + final File validConfigFile = new File( + getClass().getResource("/valid-config.json").getFile()); + command = new StoragePopulatorCommand() { + @Override + File getConfigFile(Arguments args) { + return validConfigFile; + } + }; + + setUpServices(); + + // the following counts are dependent on the parameters in valid-config.json + int agentCount = 2; + int hostCount = 2; + int networkCount = 40; + int deadLockCount = 100; + int vmCount = 10; + + when(agentInfoDAO.getCount()).thenReturn(0l).thenReturn((long) agentCount); + when(hostInfoDAO.getCount()).thenReturn(0l).thenReturn((long) hostCount); + when(networkInfoDAO.getCount()).thenReturn(0l).thenReturn((long) networkCount); + when(threadDao.getDeadLockCount()).thenReturn(0l).thenReturn((long) deadLockCount); + when(vmInfoDAO.getCount()).thenReturn(0l).thenReturn((long) vmCount); + + command.run(ctx); + + verify(agentInfoDAO, times(agentCount)).addAgentInformation(any(AgentInformation.class)); + verify(hostInfoDAO, times(hostCount)).putHostInfo(any(HostInfo.class)); + verify(networkInfoDAO, times(networkCount)).putNetworkInterfaceInfo( + any(NetworkInterfaceInfo.class)); + verify(threadDao, times(deadLockCount)).saveDeadLockStatus(any(VmDeadLockData.class)); + verify(vmInfoDAO, times(vmCount)).putVmInfo(any(VmInfo.class)); + } + + private void setUpServices () { + paths = mock(CommonPaths.class); + command.setPaths(paths); + hostInfoDAO = mock(HostInfoDAO.class); + command.setHostInfoDAO(hostInfoDAO); + agentInfoDAO = mock(AgentInfoDAO.class); + command.setAgentInfoDAO(agentInfoDAO); + vmInfoDAO = mock(VmInfoDAO.class); + command.setVmInfoDAO(vmInfoDAO); + networkInfoDAO = mock(NetworkInterfaceInfoDAO.class); + command.setNetworkInfoDAO(networkInfoDAO); + threadDao = mock(ThreadDao.class); + command.setThreadDao(threadDao); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/ActivatorTest.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,60 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import static com.redhat.thermostat.testutils.Asserts.assertCommandIsRegistered; +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.redhat.thermostat.storage.populator.StoragePopulatorCommand; +import com.redhat.thermostat.storage.populator.internal.Activator; +import com.redhat.thermostat.testutils.StubBundleContext; + +public class ActivatorTest { + @Test + public void verifyActivatorRegistersServices() throws Exception { + StubBundleContext ctx = new StubBundleContext(); + Activator activator = new Activator(); + + activator.start(ctx); + assertCommandIsRegistered(ctx, "storage-populator", StoragePopulatorCommand.class); + activator.stop(ctx); + + assertEquals(0, ctx.getServiceListeners().size()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/AgentInfoPopulatorTest.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,102 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +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.PrintStream; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.storage.model.AgentInformation; +import com.redhat.thermostat.storage.populator.internal.AgentInfoPopulator; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.dependencies.ProcessedRecords; +import com.redhat.thermostat.storage.populator.internal.dependencies.SharedState; + +public class AgentInfoPopulatorTest { + + @Test + public void canHandleAgentInfoCollection() { + AgentInfoPopulator putter = new AgentInfoPopulator(); + assertEquals("agent-config", putter.getHandledCollection()); + } + + @Test + public void canAddPojos() { + int totalRecords = 23; + AgentInfoDAO dao = mock(AgentInfoDAO.class); + // Initially return 0, then return the expected count + when(dao.getCount()).thenReturn(0L).thenReturn((long)totalRecords); + AgentInfoPopulator putter = new AgentInfoPopulator(dao); + ConfigItem item = new ConfigItem(totalRecords, 3, "agent-config"); + SharedState state = new SharedState(); + Console console = mock(Console.class); + PrintStream ps = mock(PrintStream.class); + when(console.getOutput()).thenReturn(ps); + state = putter.addPojos(item, state, console); + ArgumentCaptor<AgentInformation> agentInfoCaptor = ArgumentCaptor.forClass(AgentInformation.class); + verify(dao, times(23)).addAgentInformation(agentInfoCaptor.capture()); + List<AgentInformation> agentInfos = agentInfoCaptor.getAllValues(); + List<AgentInformation> filtered = getAliveAgentInfos(agentInfos); + assertEquals(3, filtered.size()); + ProcessedRecords<String> recs = state.getProcessedRecordsFor("agentId"); + assertEquals(23, recs.getAll().size()); + ProcessedRecords<String> notExisting = state.getProcessedRecordsFor("foo-bar"); + assertNull(notExisting); + } + + private List<AgentInformation> getAliveAgentInfos(List<AgentInformation> agentInfos) { + List<AgentInformation> aliveInfos = new ArrayList<>(); + for (AgentInformation info: agentInfos) { + if (info.isAlive()) { + aliveInfos.add(info); + } + } + return aliveInfos; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/BasePopulatorTest.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,123 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.dependencies.SharedState; + +public class BasePopulatorTest { + + private BasePopulator populator; + + private ByteArrayOutputStream outputBAOS; + private PrintStream output; + private Console console; + + @Before + public void setUp() { + populator = createBasePopulatorForTest(); + + console = mock(Console.class); + outputBAOS = new ByteArrayOutputStream(); + output = new PrintStream(outputBAOS); + when(console.getOutput()).thenReturn(output); + } + + private BasePopulator createBasePopulatorForTest() { + return new BasePopulator() { + private int currCount = 0; + + @Override + long getCount() { + currCount++; + return currCount; + } + + @Override + public SharedState addPojos(ConfigItem item, SharedState relState, Console console) { + return null; + } + + @Override + public String getHandledCollection() { + return null; + } + }; + } + + @Test + public void testDoWaitUntilCount() { + final long expectedCount = 3; + + populator.doWaitUntilCount(expectedCount, console, 0); + + String expected = "Waiting for storage items to arrive at backend..."; + for (int i = 0; i < (expectedCount - 1); i++) { + expected = expected + "."; + } + expected = expected + "Items have arrived.\n"; + + String outputString = new String(outputBAOS.toByteArray()); + assertEquals(expected, outputString); + } + + @Test + public void testReportSubmitted() { + final String name = "foo"; + final int totalCount = 3; + + ConfigItem item = mock(ConfigItem.class); + when(item.getName()).thenReturn(name); + + populator.reportSubmitted(item, totalCount, console); + + String expectedString = "Submitted " + totalCount + " " + name + " records to storage.\n"; + String outputString = new String(outputBAOS.toByteArray()); + assertEquals(expectedString, outputString); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/HostInfoPopulatorTest.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,100 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; +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.PrintStream; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.storage.dao.HostInfoDAO; +import com.redhat.thermostat.storage.model.HostInfo; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.dependencies.ProcessedRecords; +import com.redhat.thermostat.storage.populator.internal.dependencies.SharedState; + +public class HostInfoPopulatorTest { + + @Test + public void handlesCorrectCollection() { + HostInfoPopulator populator = new HostInfoPopulator(); + assertEquals("host-info", populator.getHandledCollection()); + } + + @Test + public void canPopulateToStorage() { + String[] agents = new String[] { + "host-agent1", "host-agent2", "host-agent3", "host-agent4" + }; + List<String> agentIds = Arrays.asList(agents); + SharedState state = mock(SharedState.class); + @SuppressWarnings("unchecked") + ProcessedRecords<String> procRecs = mock(ProcessedRecords.class); + when(procRecs.getAll()).thenReturn(agentIds); + when(state.getProcessedRecordsFor(eq("agentId"))).thenReturn(procRecs); + int totalRecords = agents.length; + HostInfoDAO dao = mock(HostInfoDAO.class); + // Initially return 0, then return the expected count + when(dao.getCount()).thenReturn(0L).thenReturn((long)totalRecords); + + ConfigItem config = new ConfigItem(1, ConfigItem.UNSET, "host-info"); + HostInfoPopulator populator = new HostInfoPopulator(dao); + Console console = mock(Console.class); + PrintStream ps = mock(PrintStream.class); + when(console.getOutput()).thenReturn(ps); + populator.addPojos(config, state, console); + ArgumentCaptor<HostInfo> captor = ArgumentCaptor.forClass(HostInfo.class); + verify(dao, times(totalRecords)).putHostInfo(captor.capture()); + List<HostInfo> values = captor.getAllValues(); + // ensure no memory values are negative + for (HostInfo info: values) { + if (info.getTotalMemory() < 0) { + throw new AssertionError("Invalid memory value: " + info.getTotalMemory() + " < 0"); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/NetworkInfoPopulatorTest.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,131 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import static org.junit.Assert.assertEquals; +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.PrintStream; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO; +import com.redhat.thermostat.storage.model.NetworkInterfaceInfo; +import com.redhat.thermostat.storage.populator.internal.NetworkInfoPopulator; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.dependencies.ProcessedRecords; +import com.redhat.thermostat.storage.populator.internal.dependencies.SharedState; + +public class NetworkInfoPopulatorTest { + + @Test + public void canHandleCorrectCollection() { + NetworkInfoPopulator populator = new NetworkInfoPopulator(); + assertEquals("network-info", populator.getHandledCollection()); + } + + @Test + public void testPopulation() { + NetworkInterfaceInfoDAO dao = mock(NetworkInterfaceInfoDAO.class); + NetworkInfoPopulator populator = new NetworkInfoPopulator(dao); + + String[] agentIds = new String[] { + "testAgent1", "testAgent2", "testAgent3", "testAgent4" + }; + int perAgentItems = 100; + int totalRecords = perAgentItems * agentIds.length; + when(dao.getCount()).thenReturn(0L).thenReturn((long)totalRecords); + List<String> agents = Arrays.asList(agentIds); + SharedState state = new SharedState(); + state.addProcessedRecords("agentId", new ProcessedRecords<>(agents)); + ConfigItem config = new ConfigItem(perAgentItems, ConfigItem.UNSET, "network-info"); + Console console = mock(Console.class); + PrintStream ps = mock(PrintStream.class); + when(console.getOutput()).thenReturn(ps); + populator.addPojos(config, state, console); + ArgumentCaptor<NetworkInterfaceInfo> captor = ArgumentCaptor.forClass(NetworkInterfaceInfo.class); + verify(dao, times(totalRecords)).putNetworkInterfaceInfo(captor.capture()); + List<NetworkInterfaceInfo> list = captor.getAllValues(); + // expected agentId + iface name to be unique (since REPLACE otherwise replaces some random values) + Set<String> uniqueSet = new HashSet<>(); + for (NetworkInterfaceInfo info: list) { + String agentId = info.getAgentId(); + String ifaceName = info.getInterfaceName(); + String key = agentId + ifaceName; + if (uniqueSet.contains(key)) { + throw new AssertionError("Expected interface names to be unique per agent"); + } else { + uniqueSet.add(key); + } + } + } + + @Test + public void iPv6HextetRollOver() { + String ipv6 = new NetworkInfoPopulator().getIpv6Hextet(Integer.parseInt("fffe", 16)); + assertEquals("fffe", ipv6); + ipv6 = new NetworkInfoPopulator().getIpv6Hextet(Integer.parseInt("ffff", 16)); + assertEquals("1", ipv6); + ipv6 = new NetworkInfoPopulator().getIpv6Hextet(Integer.parseInt("eee1", 16)); + assertEquals("eee1", ipv6); + } + + @Test + public void iPv4OctetsRollOver() { + int octet = new NetworkInfoPopulator().getIpv4Octet(255); + assertEquals(1, octet); + octet = new NetworkInfoPopulator().getIpv4Octet(256); + assertEquals(1, octet); + octet = new NetworkInfoPopulator().getIpv4Octet(114); + assertEquals(114, octet); + } + + @Test + public void stringFormatIpv6Template() { + String formattedString = String.format(NetworkInfoPopulator.IPV6_FORMATS[1], "ff", "scope"); + assertEquals("fe80::56ee:75ff:fe35:ff%scope", formattedString); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/ThreadPopulatorTest.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,294 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +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.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.storage.model.BasePojo; +import com.redhat.thermostat.storage.populator.internal.ThreadPopulator; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.dependencies.ProcessedRecords; +import com.redhat.thermostat.storage.populator.internal.dependencies.SharedState; +import com.redhat.thermostat.thread.dao.ThreadDao; +import com.redhat.thermostat.thread.model.ThreadHarvestingStatus; +import com.redhat.thermostat.thread.model.ThreadSession; +import com.redhat.thermostat.thread.model.ThreadState; +import com.redhat.thermostat.thread.model.ThreadSummary; +import com.redhat.thermostat.thread.model.VmDeadLockData; + +public class ThreadPopulatorTest { + + private static final String EXPECTED_DESCRIPTION = "" + + "\"Mallory\" Id=12 WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@52de95c7 owned by \"Alice\" Id=10\n" + + "\tat sun.misc.Unsafe.park(Native Method)\n" + + "\t- waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@52de95c7\n" + + "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)\n" + + "\tat java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)\n" + + "\tat java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)\n" + + "\tat com.redhat.thermostat.tests.DeadLock$Philosopher.run(DeadLock.java:57)\n" + + "\t...\n\n" + + "\tNumber of locked synchronizers = 1\n" + + "\t- java.util.concurrent.locks.ReentrantLock$NonfairSync@441634c2" + + "\n\n\n" + + "\"Alice\" Id=10 WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@105ff84e owned by \"Bob\" Id=11\n" + + "\tat sun.misc.Unsafe.park(Native Method)\n" + + "\t- waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@105ff84e\n" + + "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)\n" + + "\tat java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)\n" + + "\tat java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)\n" + + "\tat com.redhat.thermostat.tests.DeadLock$Philosopher.run(DeadLock.java:57)\n" + + "\t...\n\n" + + "\tNumber of locked synchronizers = 1\n" + + "\t- java.util.concurrent.locks.ReentrantLock$NonfairSync@52de95c7\n" + + "\n\n" + + "\"Bob\" Id=11 WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@441634c2 owned by \"Mallory\" Id=12\n" + + "\tat sun.misc.Unsafe.park(Native Method)\n" + + "\t- waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@441634c2\n" + + "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)\n" + + "\tat java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)\n" + + "\tat java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)\n" + + "\tat com.redhat.thermostat.tests.DeadLock$Philosopher.run(DeadLock.java:57)\n" + + "\t...\n\n" + + "\tNumber of locked synchronizers = 1\n" + + "\t- java.util.concurrent.locks.ReentrantLock$NonfairSync@105ff84e\n\n\n"; + + private static final String[] AGENTS = new String[] { + "fooAgent1", "fooBarAgent", "testAgent", "someAgent" + }; + private static final String[] VMS = new String[] { + "vm1", "vm2", "vm3", "vm4", "vm5" + }; + + private ThreadDao dao; + + @Test + public void testFormatDeadlockDesc() { + Object[] stringFormatArgs = new Object[] { + "Mallory", 12, + "Alice", 10, + "Alice", 10, + "Bob", 11, + "Bob", 11, + "Mallory", 12 + }; + assertEquals(EXPECTED_DESCRIPTION, String.format(ThreadPopulator.DEADLOCK_DESC_FORMAT, stringFormatArgs)); + } + + @Test + public void canGetRandomThreadNames() { + Object[] args = new ThreadPopulator().getFormatStringArgs(2); + assertEquals(12, args.length); + Map<Integer, Integer> tids = new HashMap<>(); + Map<String, Integer> threadNames = new HashMap<>(); + for (int i = 0; i < args.length; i +=2) { + Object arg1 = args[i]; + Object arg2 = args[i + 1]; + assertEquals(String.class, arg1.getClass()); + assertEquals(Integer.class, arg2.getClass()); + if (tids.containsKey(arg2)) { + Integer value = tids.get(arg2); + value += 1; + tids.put((Integer)arg2, value); + } else { + tids.put((Integer)arg2, 1); + } + if (threadNames.containsKey(arg1)) { + Integer value = threadNames.get(arg1); + value += 1; + threadNames.put((String)arg1, value); + } else { + threadNames.put((String)arg1, 1); + } + } + for (String key : threadNames.keySet()) { + int value = threadNames.get(key); + assertEquals(2, value); + } + for (Integer key : tids.keySet()) { + int value = tids.get(key); + assertEquals(2, value); + } + } + + @Test + public void canHandleAppropriateCollection() { + ThreadPopulator populator = new ThreadPopulator(); + assertEquals("vm-thread-harvesting", populator.getHandledCollection()); + } + + @Test + public void canAddThreadData() { + int perVmCount = 123; + int totalCount = perVmCount * AGENTS.length * VMS.length; + setUp(perVmCount, totalCount); + + assertThreadSummaries(totalCount, perVmCount); + assertThreadSessions(totalCount, perVmCount); + assertThreadStates(totalCount, perVmCount); + assertThreadHarvestingStatus(totalCount, perVmCount); + assertDeadlockInfo(perVmCount, totalCount); + } + + private void setUp(int perVmCount, int totalCount) { + ConfigItem config = new ConfigItem(perVmCount, ConfigItem.UNSET, "vm-deadlock-data"); + dao = mock(ThreadDao.class); + when(dao.getDeadLockCount()).thenReturn(0L).thenReturn((long)totalCount); + ThreadPopulator populator = new ThreadPopulator(dao); + SharedState state = mock(SharedState.class); + when(state.getProcessedRecordsFor("agentId")).thenReturn(new ProcessedRecords<>(Arrays.asList(AGENTS))); + when(state.getProcessedRecordsFor("vmId")).thenReturn(new ProcessedRecords<>(Arrays.asList(VMS))); + Console console = mock(Console.class); + PrintStream ps = mock(PrintStream.class); + when(console.getOutput()).thenReturn(ps); + SharedState retval = populator.addPojos(config, state, console); + assertSame(retval, state); + } + + private void assertThreadSummaries(int totalCount, int perVmCount) { + ArgumentCaptor<ThreadSummary> summaryCaptor = ArgumentCaptor.forClass(ThreadSummary.class); + verify(dao, times(totalCount)).saveSummary(summaryCaptor.capture()); + List<ThreadSummary> savedValues = summaryCaptor.getAllValues(); + assertEquals(totalCount, savedValues.size()); + checkInstances(savedValues, VMS.length * perVmCount); + } + + private void assertThreadSessions(int totalCount, int perVmCount) { + ArgumentCaptor<ThreadSession> sessionCaptor = ArgumentCaptor.forClass(ThreadSession.class); + verify(dao, times(totalCount)).saveSession(sessionCaptor.capture()); + List<ThreadSession> savedValues = sessionCaptor.getAllValues(); + assertEquals(totalCount, savedValues.size()); + checkInstances(savedValues, VMS.length * perVmCount); + } + + private void assertThreadStates(int totalCount, int perVmCount) { + ArgumentCaptor<ThreadState> stateCaptor = ArgumentCaptor.forClass(ThreadState.class); + verify(dao, times(totalCount * ThreadPopulator.NUM_SAMPLES)). + addThreadState(stateCaptor.capture()); + List<ThreadState> savedValues = stateCaptor.getAllValues(); + assertEquals(totalCount * ThreadPopulator.NUM_SAMPLES, savedValues.size()); + checkInstances(savedValues, VMS.length * perVmCount * ThreadPopulator.NUM_SAMPLES); + } + + private void assertThreadHarvestingStatus(int totalCount, int perVmCount) { + ArgumentCaptor<ThreadHarvestingStatus> statusCaptor = + ArgumentCaptor.forClass(ThreadHarvestingStatus.class); + verify(dao, times(totalCount)).saveHarvestingStatus(statusCaptor.capture()); + List<ThreadHarvestingStatus> savedValues = statusCaptor.getAllValues(); + checkInstances(savedValues, VMS.length * perVmCount); + } + + private void checkInstances(List<? extends BasePojo> savedValues, int expected) { + List<String> agentIds = new ArrayList<>(); + for (int i = 0; i < savedValues.size(); i++) { + agentIds.add(savedValues.get(i).getAgentId()); + } + + for (String agentId : AGENTS) { + int numInstances = Collections.frequency(agentIds, agentId); + assertEquals(expected, numInstances); + } + } + + private void assertDeadlockInfo(int perVmCount, int totalCount) { + ArgumentCaptor<VmDeadLockData> deadlockInfoCaptor = ArgumentCaptor.forClass(VmDeadLockData.class); + verify(dao, times(totalCount)).saveDeadLockStatus(deadlockInfoCaptor.capture()); + List<VmDeadLockData> savedValues = deadlockInfoCaptor.getAllValues(); + assertEquals(totalCount, savedValues.size()); + List<VmDeadLockData> perVmIdAgentDeadlockData = getFilteredByVmId(savedValues, "vm3"); + assertEquals(perVmCount * AGENTS.length, perVmIdAgentDeadlockData.size()); + List<VmDeadLockData> perAgentIdDeadlockData = getFilteredByAgentId(savedValues, "fooAgent1"); + verifyVmIdsDifferent(perAgentIdDeadlockData); + } + + private List<VmDeadLockData> getFilteredByAgentId(List<VmDeadLockData> perVmDeadlockData, String agentId) { + List<VmDeadLockData> filteredValues = new ArrayList<>(); + for (VmDeadLockData data: perVmDeadlockData) { + if (data.getAgentId().equals(agentId)) { + filteredValues.add(data); + } + } + return filteredValues; + } + + private void verifyVmIdsDifferent(List<VmDeadLockData> perVmDeadlockData) { + Set<String> vmIds = new HashSet<>(); + for (VmDeadLockData data: perVmDeadlockData) { + if (vmIds.contains(data.getVmId())) { + throw new AssertionError("Duplicate VM ID per agent. Duplicate was: " + data.getVmId()); + } + vmIds.add(data.getAgentId()); + } + } + + private List<VmDeadLockData> getFilteredByVmId(List<VmDeadLockData> savedValues, String vmId) { + List<VmDeadLockData> filteredValues = new ArrayList<>(); + for (VmDeadLockData data: savedValues) { + if (data.getVmId().equals(vmId)) { + filteredValues.add(data); + } + } + return filteredValues; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/VmInfoPopulatorTest.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,118 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; +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.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.storage.dao.VmInfoDAO; +import com.redhat.thermostat.storage.model.VmInfo; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.dependencies.ProcessedRecords; +import com.redhat.thermostat.storage.populator.internal.dependencies.SharedState; + +public class VmInfoPopulatorTest { + + @Test + public void canHandleCorrectCollection() { + VmInfoPopulator populator = new VmInfoPopulator(); + assertEquals("vm-info", populator.getHandledCollection()); + } + + @SuppressWarnings("unchecked") + @Test + public void canPopulateData() { + VmInfoDAO mockDAO = mock(VmInfoDAO.class); + SharedState state = mock(SharedState.class); + ProcessedRecords<String> procRecs = mock(ProcessedRecords.class); + String[] agents = new String[] { + "foo-agent1", "foo-agent2", "bar-agent3" + }; + List<String> agentIdList = Arrays.asList(agents); + when(procRecs.getAll()).thenReturn(agentIdList); + when(state.getProcessedRecordsFor(eq("agentId"))).thenReturn(procRecs); + int perAgentVms = 44; + int subsetAlive = 23; + ConfigItem config = new ConfigItem(perAgentVms, subsetAlive, "vm-info"); + + // total records inserted will be 3 * 44. 44 records per agentId + int totalRecords = perAgentVms * agents.length; + // Initially return 0, then return the expected count + when(mockDAO.getCount()).thenReturn(0L).thenReturn((long)totalRecords); + VmInfoPopulator populator = new VmInfoPopulator(mockDAO); + Console console = mock(Console.class); + PrintStream ps = mock(PrintStream.class); + when(console.getOutput()).thenReturn(ps); + populator.addPojos(config, state, console); + ArgumentCaptor<VmInfo> captor = ArgumentCaptor.forClass(VmInfo.class); + verify(mockDAO, times(totalRecords)).putVmInfo(captor.capture()); + List<VmInfo> allInfos = captor.getAllValues(); + assertEquals(totalRecords, allInfos.size()); + List<VmInfo> aliveInfos = getAliveVmInfos(allInfos); + int totalAliveRecs = subsetAlive * agents.length; + assertEquals(totalAliveRecs, aliveInfos.size()); + @SuppressWarnings("rawtypes") + ArgumentCaptor<ProcessedRecords> procsVms = ArgumentCaptor.forClass(ProcessedRecords.class); + verify(state).addProcessedRecords(eq("vmId"), procsVms.capture()); + ProcessedRecords<String> processedVms = procsVms.getValue(); + assertEquals("Excected vmIds added to shared state", totalRecords, processedVms.getAll().size()); + } + + @SuppressWarnings("deprecation") + private List<VmInfo> getAliveVmInfos(List<VmInfo> allInfos) { + List<VmInfo> aliveInfos = new ArrayList<>(); + for (VmInfo info: allInfos) { + if (info.isAlive()) { + aliveInfos.add(info); + } + } + return aliveInfos; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/config/PopulationConfigTest.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,216 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.junit.Test; + +import com.redhat.thermostat.storage.populator.internal.dependencies.Relationship; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.config.PopulationConfig; + +public class PopulationConfigTest { + + private static final String NETWORK_INFO_NAME = "network-info"; + private static final String AGENT_CONFIG_NAME = "agent-config"; + private static final String HOST_INFO_NAME = "host-info"; + private static final String VM_INFO_NAME = "vm-info"; + private static final String VM_GC_STAT_NAME = "vm-gc-stats"; + private static final String AGENT_KEY = "foo-agent-key"; + private static final String VM_KEY = "bar-vm-key"; + + @Test + public void canParseFromFile() throws IOException { + String json = new String(Files.readAllBytes(new File(getClass().getResource("/testconfig").getFile()).toPath())); + PopulationConfig config = PopulationConfig.parseFromJsonString(json); + ConfigItem item = config.getConfig("agent-config"); + assertNotNull(item); + assertEquals(100, item.getNumber()); + assertEquals(20, item.getAliveItems()); + List<ConfigItem> items = config.getConfigsTopologicallySorted(); + assertEquals(7, items.size()); + item = config.getConfig("vm-info"); + assertEquals(50, item.getNumber()); + assertEquals(40, item.getAliveItems()); + item = config.getConfig("vm-gc-stats"); + assertNotNull(item); + } + + /** + * Tests topological sorting of a simple DAG + * + * <pre> + * agent-config -> network-info + * |----------> host-info + * |--> vm-info + * | `--> vm-gc-stat + * `------------^ + * </pre> + * + * @throws IOException + */ + @Test + public void testTopogicalSort() throws IOException { + List<ConfigItem> records = buildGoodRecords(); + List<Relationship> rels = buildGoodRels(); + PopulationConfig pc = PopulationConfig.createFromLists(records, rels); + List<ConfigItem> topSortedList = pc.getConfigsTopologicallySorted(); + assertAgentConfigBeforeNetworkInfo(topSortedList); + assertAgentConfigBeforeHostInfo(topSortedList); + assertAgentConfigBeforeVmInfo(topSortedList); + assertVmInfoBeforeVmGcStat(topSortedList); + assertAgentConfigBeforeVmGcStat(topSortedList); + } + + private void assertAgentConfigBeforeVmGcStat(List<ConfigItem> topSortedList) { + assertTrue(isABeforeB(AGENT_CONFIG_NAME, VM_GC_STAT_NAME, topSortedList)); + } + + private void assertVmInfoBeforeVmGcStat(List<ConfigItem> topSortedList) { + assertTrue(isABeforeB(VM_INFO_NAME, VM_GC_STAT_NAME, topSortedList)); + } + + private void assertAgentConfigBeforeVmInfo(List<ConfigItem> topSortedList) { + assertTrue(isABeforeB(AGENT_CONFIG_NAME, VM_INFO_NAME, topSortedList)); + } + + private void assertAgentConfigBeforeHostInfo(List<ConfigItem> topSortedList) { + assertTrue(isABeforeB(AGENT_CONFIG_NAME, HOST_INFO_NAME, topSortedList)); + } + + private void assertAgentConfigBeforeNetworkInfo(List<ConfigItem> topSortedList) { + assertTrue(isABeforeB(AGENT_CONFIG_NAME, NETWORK_INFO_NAME, topSortedList)); + } + + private boolean isABeforeB(String a, String b, List<ConfigItem> list) { + int idxA = -1; + int idxB = -1; + for (int i = 0; i < list.size(); i++) { + ConfigItem item = list.get(i); + if (item.getName().equals(a)) { + if (idxA >= 0) { + throw new AssertionError("Illegal state. Re-assigning idxA!"); + } + idxA = i; + } + if (item.getName().equals(b)) { + if (idxB >= 0) { + throw new AssertionError("Illegal state. Re-assigning idxB!"); + } + idxB = i; + } + } + return idxA < idxB; + } + + private List<Relationship> buildGoodRels() { + List<Relationship> relationships = new LinkedList<>(); + Relationship agentConfigToNetworkInfo = new Relationship(AGENT_CONFIG_NAME, NETWORK_INFO_NAME, AGENT_KEY); + relationships.add(agentConfigToNetworkInfo); + Relationship agentConfigToVmGcStat = new Relationship(AGENT_CONFIG_NAME, VM_GC_STAT_NAME, AGENT_KEY); + relationships.add(agentConfigToVmGcStat); + Relationship agentConfigToHostInfo = new Relationship(AGENT_CONFIG_NAME, HOST_INFO_NAME, AGENT_KEY); + relationships.add(agentConfigToHostInfo); + Relationship agentConfigToVmInfo = new Relationship(AGENT_CONFIG_NAME, VM_INFO_NAME, AGENT_KEY); + relationships.add(agentConfigToVmInfo); + Relationship vmInfoToVmGcStat = new Relationship(VM_INFO_NAME, VM_GC_STAT_NAME, VM_KEY); + relationships.add(vmInfoToVmGcStat); + return relationships; + } + + private List<ConfigItem> buildGoodRecords() { + List<ConfigItem> records = new ArrayList<>(); + ConfigItem agentConfig = new ConfigItem(10, 3, AGENT_CONFIG_NAME); + records.add(agentConfig); + ConfigItem hostInfo = new ConfigItem(3, 0, HOST_INFO_NAME); + records.add(hostInfo); + ConfigItem networkInfo = new ConfigItem(100, 0, NETWORK_INFO_NAME); + records.add(networkInfo); + ConfigItem vmGcStat = new ConfigItem(23, 0, VM_GC_STAT_NAME); + records.add(vmGcStat); + ConfigItem vmInfo = new ConfigItem(10, 0, VM_INFO_NAME); + records.add(vmInfo); + return records; + } + + /** + * Tests topological sorting with a cycle. Expected to fail. + */ + @Test(expected = AssertionError.class) + public void testTopogicalSortCycle() throws IOException { + List<ConfigItem> records = buildGoodRecords(); + List<Relationship> rels = buildGoodRels(); + // add a cycle between vm-info -> host-info -> agent-config + Relationship cyclePartOne = new Relationship(VM_INFO_NAME, HOST_INFO_NAME, VM_KEY); + rels.add(cyclePartOne); + Relationship cyclePartTwo = new Relationship(HOST_INFO_NAME, AGENT_CONFIG_NAME, AGENT_KEY); + rels.add(cyclePartTwo); + PopulationConfig pc = PopulationConfig.createFromLists(records, rels); + // This is expected to fail + pc.getConfigsTopologicallySorted(); + } + + @Test(expected = PopulationConfig.InvalidConfigurationException.class) + public void testTopogicalSortIncomingCollectionMissing() throws IOException { + List<ConfigItem> records = buildGoodRecords(); + // remove vm-gc-stat records config which has an incoming edge + // from agent-config and vm-info + int deleteIdx = -1; + for (int i = 0; i < records.size(); i++) { + ConfigItem item = records.get(i); + if (item.getName().equals(VM_GC_STAT_NAME)) { + deleteIdx = i; + break; + } + } + assertTrue("Expected vm-gc-stat to be in records config", deleteIdx >= 0); + records.remove(deleteIdx); + List<Relationship> rels = buildGoodRels(); + PopulationConfig pc = PopulationConfig.createFromLists(records, rels); + pc.getConfigsTopologicallySorted(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/config/typeadapter/ConfigItemTypeAdapterTest.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,103 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.config.typeadapter; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.config.typeadapter.ConfigItemTypeAdapter; + +public class ConfigItemTypeAdapterTest { + + private Gson gson; + + @Before + public void setup() { + gson= new GsonBuilder() + .registerTypeAdapter(ConfigItem.class, new ConfigItemTypeAdapter()) + .create(); + } + + @Test + public void testBasicNonNull() { + ConfigItem item = gson.fromJson("{ \"name\": \"config-item\", \"number\": 3, \"alive\": 1}", ConfigItem.class); + assertEquals("config-item", item.getName()); + assertEquals(3, item.getNumber()); + assertEquals(1, item.getAliveItems()); + } + + @Test(expected = IllegalArgumentException.class) + public void testBasicNegativeNumber() { + gson.fromJson("{ \"name\": \"config-item\", \"number\": -3, \"alive\": 1}", ConfigItem.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testBasicNegativeAlive() { + gson.fromJson("{ \"name\": \"config-item\", \"number\": 10, \"alive\": -1}", ConfigItem.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testBasicAliveGreaterThanNumber() { + // alive > number. Expected strict subset + gson.fromJson("{ \"name\": \"config-item\", \"number\": 10, \"alive\": 11}", ConfigItem.class); + } + + @Test + public void testBasicNullAlive() { + ConfigItem item = gson.fromJson("{ \"name\": \"config-item\", \"number\": 3}", ConfigItem.class); + assertEquals("config-item", item.getName()); + assertEquals(3, item.getNumber()); + assertEquals(ConfigItem.UNSET, item.getAliveItems()); + } + + @Test + public void testArray() { + ConfigItem[] items = gson.fromJson("[{ \"name\": \"config-item\", \"number\": 3, \"alive\": 1}," + + "{ \"name\": \"agent-config\", \"number\": 10, \"alive\": 3 }]", ConfigItem[].class); + assertEquals("config-item", items[0].getName()); + assertEquals(3, items[0].getNumber()); + assertEquals(1, items[0].getAliveItems()); + assertEquals("agent-config", items[1].getName()); + assertEquals(10, items[1].getNumber()); + assertEquals(3, items[1].getAliveItems()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/config/typeadapter/PopulationConfigTypeAdapterTest.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,107 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.config.typeadapter; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.redhat.thermostat.storage.populator.internal.config.ConfigItem; +import com.redhat.thermostat.storage.populator.internal.config.PopulationConfig; +import com.redhat.thermostat.storage.populator.internal.dependencies.Relationship; +import com.redhat.thermostat.storage.populator.internal.config.typeadapter.ConfigItemTypeAdapter; +import com.redhat.thermostat.storage.populator.internal.config.typeadapter.PopulationConfigTypeAdapterFactory; +import com.redhat.thermostat.storage.populator.internal.config.typeadapter.RelationShipTypeAdapter; + +public class PopulationConfigTypeAdapterTest { + + private Gson gson; + + @Before + public void setup() { + gson= new GsonBuilder() + .registerTypeAdapter(Relationship.class, new RelationShipTypeAdapter()) + .registerTypeAdapter(ConfigItem.class, new ConfigItemTypeAdapter()) + .registerTypeAdapterFactory(new PopulationConfigTypeAdapterFactory()) + .create(); + } + + @Test + public void canParseSimpleNoRelationships() throws Exception { + String json = "{ \"records\": " + + "[{ \"name\": \"config-item\", \"number\": 3, \"alive\": 1}," + + "{ \"name\": \"agent-config\", \"number\": 10, \"alive\": 3 }]" + + "}"; + PopulationConfig config = gson.fromJson(json, PopulationConfig.class); + ConfigItem item = config.getConfig("config-item"); + assertEquals(3, item.getNumber()); + assertEquals(1, item.getAliveItems()); + assertEquals("config-item", item.getName()); + item = config.getConfig("agent-config"); + assertEquals(10, item.getNumber()); + assertEquals(3, item.getAliveItems()); + assertEquals("agent-config", item.getName()); + } + + @Test + public void canParseSimpleWithRelationships() throws Exception { + String json = "{ \"records\": " + + "[{ \"name\": \"config-item\", \"number\": 3, \"alive\": 1}," + + "{ \"name\": \"agent-config\", \"number\": 10, \"alive\": 3 }]," + + " \"relationships\": "+ + "[{ \"from\": \"config-item\", \"to\": \"agent-config\", \"key\": \"foo\"}]" + + "}"; + PopulationConfig config = gson.fromJson(json, PopulationConfig.class); + ConfigItem item = config.getConfig("config-item"); + assertEquals(3, item.getNumber()); + assertEquals(1, item.getAliveItems()); + assertEquals("config-item", item.getName()); + item = config.getConfig("agent-config"); + assertEquals(10, item.getNumber()); + assertEquals(3, item.getAliveItems()); + assertEquals("agent-config", item.getName()); + // Do something that uses relationships + List<ConfigItem> sorted = config.getConfigsTopologicallySorted(); + ConfigItem first = sorted.get(0); + assertEquals("config-item", first.getName()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/config/typeadapter/RelationShipTypeAdapterTest.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,67 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.config.typeadapter; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.redhat.thermostat.storage.populator.internal.dependencies.Relationship; +import com.redhat.thermostat.storage.populator.internal.config.typeadapter.RelationShipTypeAdapter; + +public class RelationShipTypeAdapterTest { + + private Gson gson; + + @Before + public void setup() { + gson= new GsonBuilder() + .registerTypeAdapter(Relationship.class, new RelationShipTypeAdapter()) + .create(); + } + + @Test + public void testBasicNonNull() { + Relationship rel = gson.fromJson("{ \"from\": \"foo\", \"to\": \"bar\", \"key\": \"baz\"}", Relationship.class); + assertEquals("foo", rel.getFrom()); + assertEquals("bar", rel.getTo()); + assertEquals("baz", rel.getKey()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/java/com/redhat/thermostat/storage/populator/internal/dependencies/RelationshipTest.java Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,71 @@ +/* + * Copyright 2012-2016 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.storage.populator.internal.dependencies; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.redhat.thermostat.storage.populator.internal.dependencies.Relationship; + +public class RelationshipTest { + + @Test + public void testEquals() { + Relationship one = new Relationship("foo", "bar", "key"); + Relationship two = new Relationship("foo", "bar", "key"); + Relationship different = new Relationship("foo", "bar", "something"); + assertTrue(one.equals(two)); + assertTrue(one.equals(one)); + assertFalse(one.equals(different)); + assertFalse(one.equals(null)); + assertTrue(two.equals(one)); + } + + @Test + public void testHashCode() { + Relationship one = new Relationship("foo", "bar", "key"); + Relationship two = new Relationship("foo", "bar", "key"); + Relationship different = new Relationship("foo", "bar", "something"); + assertEquals(one.hashCode(), two.hashCode()); + assertFalse(different.hashCode() == one.hashCode()); + assertFalse(two.hashCode() == different.hashCode()); + assertEquals(one.hashCode(), one.hashCode()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/resources/invalid-config.json Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,20 @@ +{ + "records": [ + { + "name": "foo", + "number": 1 + }, + { + "name": "bar", + "number": 5 + } + ], + + "relationships": [ + { + "from": "foo", + "to": "bar", + "key": "tar" + } + ] +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/resources/testconfig Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,55 @@ +{ +"records": +[ +{ + "name": "vm-gc-stats", + "number": 1000, + "alive": 1000 +}, +{ + "name": "agent-config", + "number": 100, + "alive": 20 +}, +{ + "name": "host-info", + "number": 10 +}, +{ + "name": "cpu-stats", + "number": 50000 +}, +{ + "name": "memory-stats", + "number": 50000 +}, +{ + "name": "network-info", + "number": 4 +}, +{ + "name": "vm-info", + "number": 50, + "alive": 40 +} +], +"relationships": +[ +{ "from": "agent-config", + "to": "vm-info", + "key": "agentId" +}, +{ "from": "agent-config", + "to": "host-info", + "key": "agentId" +}, +{ "from": "agent-config", + "to": "network-info", + "key": "agentId" +}, +{ "from": "vm-info", + "to": "vm-gc-stats", + "key": "vmId" +} +] +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/command/src/test/resources/valid-config.json Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,54 @@ +{ + "records": [ + { + "name": "agent-config", + "number": 2, + "alive": 2 + }, + { + "name": "host-info", + "number": 1 + }, + { + "name": "vm-thread-harvesting", + "number": 5 + }, + { + "name": "vm-info", + "number": 5, + "alive": 5 + }, + { + "name": "network-info", + "number": 20 + } + ], + + "relationships": [ + { + "from": "agent-config", + "to": "vm-info", + "key": "agentId" + }, + { + "from": "agent-config", + "to": "host-info", + "key": "agentId" + }, + { + "from": "agent-config", + "to": "network-info", + "key": "agentId" + }, + { + "from": "agent-config", + "to": "vm-thread-harvesting", + "key": "agentId" + }, + { + "from": "vm-info", + "to": "vm-thread-harvesting", + "key": "vmId" + } + ] +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/distribution/pom.xml Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright 2012-2016 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-storage-populator</artifactId> + <version>1.99.10-SNAPSHOT</version> + </parent> + + <artifactId>thermostat-storage-populator-distribution</artifactId> + <packaging>pom</packaging> + + <name>Thermostat storage populator plugin distribution</name> + + <properties> + <thermostat.plugin>storage-populator</thermostat.plugin> + </properties> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <dependencies> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-assembly</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + <configuration> + <descriptorRefs> + <descriptorRef>plugin-assembly</descriptorRef> + </descriptorRefs> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + <executions> + <execution> + <id>assemble-plugin</id> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <!-- Explicitly list all plug-in artifacts, transitive dependencies + are not included in assembly. --> + <dependencies> + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-storage-populator-command</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + +</project> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/distribution/thermostat-plugin.xml Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,82 @@ +<?xml version="1.0"?> +<!-- + + Copyright 2012-2016 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. + +--> +<plugin xmlns="http://icedtea.classpath.org/thermostat/plugins/v1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://icedtea.classpath.org/thermostat/plugins/v1.0 thermostat-plugin.xsd"> + <commands> + <command> + <name>storage-populator</name> + <summary>populates storage with dummy data</summary> + <description> + Populates storage with dummy data. + </description> + <options> + <option> + <long>config</long> + <short>c</short> + <argument>file</argument> + <required>true</required> + <description>the json config file to use</description> + </option> + </options> + <environments> + <environment>cli</environment> + <environment>shell</environment> + </environments> + <bundles> + <bundle><symbolic-name>com.redhat.thermostat.client.cli</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.storage.populator</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.storage.mongodb</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.web.common</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.web.client</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>com.redhat.thermostat.thread.collector</symbolic-name><version>${project.version}</version></bundle> + <bundle><symbolic-name>${osgi.compendium.bundle.symbolic-name}</symbolic-name><version>${osgi.compendium.osgi-version}</version></bundle> + <bundle><symbolic-name>org.apache.httpcomponents.httpcore</symbolic-name><version>${httpcomponents.core.version}</version></bundle> + <bundle><symbolic-name>org.apache.httpcomponents.httpclient</symbolic-name><version>${httpcomponents.client.version}</version></bundle> + <bundle><symbolic-name>com.google.gson</symbolic-name><version>${gson.version}</version></bundle> + <bundle><symbolic-name>org.mongodb.mongo-java-driver</symbolic-name><version>${mongo-driver.osgi-version}</version></bundle> + <bundle><symbolic-name>org.apache.commons.beanutils</symbolic-name><version>${commons-beanutils.version}</version></bundle> + <bundle><symbolic-name>org.apache.commons.codec</symbolic-name><version>${commons-codec.osgi-version}</version></bundle> + <bundle><symbolic-name>org.apache.commons.collections</symbolic-name><version>${commons-collections.version}</version></bundle> + <bundle><symbolic-name>org.apache.commons.logging</symbolic-name><version>${commons-logging.version}</version></bundle> + </bundles> + </command> + </commands> +</plugin> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/storage-populator/pom.xml Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright 2012-2016 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-devel-modules</artifactId> + <version>1.99.10-SNAPSHOT</version> + </parent> + + <artifactId>thermostat-storage-populator</artifactId> + <packaging>pom</packaging> + + <name>Thermostat Storage Populating Support</name> + + <modules> + <module>command</module> + <module>distribution</module> + </modules> + +</project> +
--- a/distribution/assembly/all-plugin-assembly.xml Wed May 04 17:30:06 2016 +0200 +++ b/distribution/assembly/all-plugin-assembly.xml Thu May 05 10:37:43 2016 -0400 @@ -55,6 +55,7 @@ <include>com.redhat.thermostat:thermostat-notes-distribution</include> <include>com.redhat.thermostat:thermostat-numa-distribution</include> <include>com.redhat.thermostat:thermostat-storage-profile-distribution</include> + <include>com.redhat.thermostat:thermostat-storage-populator-distribution</include> <include>com.redhat.thermostat:thermostat-thread-distribution</include> <include>com.redhat.thermostat:thermostat-validate-distribution</include> <include>com.redhat.thermostat:thermostat-setup-distribution</include>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/distribution/config/storage-populator/population-config-example-simple-threads.json Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,54 @@ +{ + "records": [ + { + "name": "agent-config", + "number": 2, + "alive": 2 + }, + { + "name": "host-info", + "number": 1 + }, + { + "name": "vm-thread-harvesting", + "number": 5 + }, + { + "name": "vm-info", + "number": 5, + "alive": 5 + }, + { + "name": "network-info", + "number": 20 + } + ], + + "relationships": [ + { + "from": "agent-config", + "to": "vm-info", + "key": "agentId" + }, + { + "from": "agent-config", + "to": "host-info", + "key": "agentId" + }, + { + "from": "agent-config", + "to": "network-info", + "key": "agentId" + }, + { + "from": "agent-config", + "to": "vm-thread-harvesting", + "key": "agentId" + }, + { + "from": "vm-info", + "to": "vm-thread-harvesting", + "key": "vmId" + } + ] +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/distribution/config/storage-populator/population-config-example-simple.json Thu May 05 10:37:43 2016 -0400 @@ -0,0 +1,40 @@ +{ + "records": [ + { + "name": "agent-config", + "number": 100, + "alive": 20 + }, + { + "name": "host-info", + "number": 1 + }, + { + "name": "vm-info", + "number": 50, + "alive": 40 + }, + { + "name": "network-info", + "number": 50 + } + ], + + "relationships": [ + { + "from": "agent-config", + "to": "vm-info", + "key": "agentId" + }, + { + "from": "agent-config", + "to": "host-info", + "key": "agentId" + }, + { + "from": "agent-config", + "to": "network-info", + "key": "agentId" + } + ] +}
--- a/distribution/pom.xml Wed May 04 17:30:06 2016 +0200 +++ b/distribution/pom.xml Thu May 05 10:37:43 2016 -0400 @@ -209,6 +209,7 @@ <filtering>true</filtering> <includes> <include>shell-command/shell-prompt.conf</include> + <include>storage-populator/*.json</include> <include>platform/*.json</include> <include>thermostat-gui/*.json</include> </includes> @@ -548,6 +549,12 @@ </dependency> <dependency> <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-storage-populator-distribution</artifactId> + <version>${project.version}</version> + <type>zip</type> + </dependency> + <dependency> + <groupId>com.redhat.thermostat</groupId> <artifactId>thermostat-thread-distribution</artifactId> <version>${project.version}</version> <type>zip</type>