001    package org.hackystat.sensorshell;
002    
003    import java.io.File;
004    import java.util.Date;
005    
006    import org.hackystat.sensorbase.client.SensorBaseClient;
007    import org.hackystat.sensorbase.resource.sensordata.jaxb.Properties;
008    import org.hackystat.sensorbase.resource.sensordata.jaxb.Property;
009    import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorData;
010    import org.hackystat.utilities.tstamp.Tstamp;
011    
012    /**
013     * A command line tool that facilitates performance evaluation and tuning of sensor data
014     * transmission. To use this tool, invoke:
015     * 
016     * <pre>
017     * java -jar shellperfeval.jar  [numInstancesToSend] 
018     * </pre>
019     * 
020     * With a sensorshell.properties file located in the same directory as this jar file.
021     * <p>
022     * This results in the following:
023     * <ul>
024     * <li> The sensorshell.properties file is read in and used to initialize a SensorShell, except that
025     * the user and password fields are not used. Instead, a test user called
026     * "ShellPerfEval@hackystat.org" is created and used instead.
027     * <li> Offline caching and recovery are also disabled. 
028     * These properties are printed out.
029     * <li> The number provided on the command line is read and used to generate and send that many
030     * Sensor Data instances to the server. The number of milliseconds required to send each request is
031     * printed out, 50 per line.
032     * <li> Once all of the instances have been sent to the server, summary statistics are printed out,
033     * and all of the data associated with this test user is deleted.
034     * </ul>
035     * 
036     * @author Philip Johnson
037     * 
038     */
039    public class ShellPerfEval {
040    
041      /**
042       * Provide a sensorshell.properties file in the same directory as the location of the jar file
043       * invoking this program. Invoke it with one argument, the number of instances to send.
044       * 
045       * @param args One argument, the number of instances to send.
046       * @throws Exception If things go wrong.
047       */
048      public static void main(String[] args) throws Exception {
049        // Get the number of instances, or exit if failure.
050        int numInstances = 0;
051        try {
052          numInstances = Integer.parseInt(args[0]);
053        }
054        catch (Exception e) {
055          System.out.println("java -jar shellperfeval [numInstancesToSend]");
056          return;
057        }
058        // Get the sensorshell.properties file, or exit if failure.
059        File propsFile = new File(System.getProperty("user.dir"), "sensorshell.properties");
060        if (!propsFile.exists()) {
061          System.out.println("sensorshell.properties file must be in this directory.");
062          return;
063        }
064    
065        String user = "ShellPerfEval@hackystat.org";
066    
067        // Create our SensorShellProperties with the overridden user and password.
068        SensorShellProperties origProps = new SensorShellProperties(propsFile);
069        java.util.Properties props = new java.util.Properties();
070        props.setProperty(SensorShellProperties.SENSORSHELL_SENSORBASE_USER_KEY, user);
071        props.setProperty(SensorShellProperties.SENSORSHELL_SENSORBASE_PASSWORD_KEY, user);
072        props.setProperty(SensorShellProperties.SENSORSHELL_OFFLINE_CACHE_ENABLED_KEY, "false");
073        props.setProperty(SensorShellProperties.SENSORSHELL_OFFLINE_RECOVERY_ENABLED_KEY, "false");
074        SensorShellProperties shellProps = new SensorShellProperties(origProps, props);
075        System.out.println(shellProps.toString());
076    
077        // Instantiate the sensorshell.
078        SensorShell shell = new SensorShell(shellProps, false, "ShellPerfEval");
079    
080        // Make sure the user remembers to get the SensorBase running. :-)
081        if (!shell.ping()) {
082          System.out.println("Error: Could not contact: " + shell.getProperties().getSensorBaseHost());
083        }
084    
085        // Register our user.
086        SensorBaseClient.registerUser(shellProps.getSensorBaseHost(), user);
087    
088        // Now do the run.
089        Date startTime = new Date();
090        System.out.println("Number of milliseconds for each 'add' command, 50 per line:");
091        for (long i = 0; i < numInstances; i++) {
092          long time1 = new Date().getTime();
093          SensorData data = makeSensorData(user, time1 + (i * 10));
094          shell.add(data);
095          long time2 = new Date().getTime();
096          if ((i > 0) && ((i % 50) == 0)) {
097            System.out.println();
098          }
099          if ((i > 0) && ((i % 1000) == 0)) {
100            System.out.println("Finished: " + i + " out of " + numInstances);
101          }
102          System.out.print((time2 - time1) + " ");
103        }
104    
105        // Make sure the user remembers to get the SensorBase running. :-)
106        if (!shell.ping()) {
107          System.out.println("Error: Could not contact: " + shell.getProperties().getSensorBaseHost());
108          // return;
109        }
110        System.out.println();
111        // Make sure all data has been sent.
112        shell.quit();
113        long totalTime = (new Date().getTime() - startTime.getTime());
114        System.out.println("Total time: " + totalTime + " milliseconds.");
115        double timePerData = (double) totalTime / (double) numInstances;
116        System.out.println("Milliseconds/sensordata instance: " + timePerData);
117        SensorBaseClient client = new SensorBaseClient(shellProps.getSensorBaseHost(), user, user);
118        System.out.print("Deleting data from sensorbase...");
119        client.deleteSensorData(user);
120        System.out.println(" done.");
121      }
122    
123      /**
124       * Creates a sample SensorData instance given a user.
125       * 
126       * @param user The user.
127       * @param utc The timestamp to be used for this instance.
128       * @return The new SensorData instance.
129       */
130      private static SensorData makeSensorData(String user, long utc) {
131        String sdt = "TestSdt";
132        SensorData data = new SensorData();
133        String tool = "Subversion";
134        data.setTool(tool);
135        data.setOwner(user);
136        data.setSensorDataType(sdt);
137        data.setTimestamp(Tstamp.makeTimestamp(utc));
138        data.setResource("file://foo/bar/baz.txt");
139        data.setRuntime(Tstamp.makeTimestamp());
140        Property property = new Property();
141        property.setKey("SampleField");
142        property.setValue("The test value for Sample Field");
143        Properties properties = new Properties();
144        properties.getProperty().add(property);
145        data.setProperties(properties);
146        return data;
147      }
148    
149    }