Sample Java program for monitoring performance bottleneck (PerformanceBottleneckSample.java)

import com.datamirror.ea.api.ApiException;
import com.datamirror.ea.api.DataNotFoundException;
import com.datamirror.ea.api.DataSource;
import com.datamirror.ea.api.DefaultContext;
import com.datamirror.ea.api.PerformanceStatisticData;
import com.datamirror.ea.api.ReplicationRole;
import com.datamirror.ea.api.StatisticDefinition;
import com.datamirror.ea.api.Toolkit;
import com.datamirror.ea.api.publisher.Publisher;
import com.datamirror.ea.api.publisher.Subscription;
import com.datamirror.ea.api.subscriber.Publication;
import com.datamirror.ea.api.subscriber.Subscriber;
import com.datamirror.ea.api.utilities.PerformanceSnapshot;

/**
 * Connects to the source and target datastores, prints out bottleneck statistics for the subscription.
 */
public class PerformanceBottleneckSample
{
   public static String ACCESS_SERVER_HOST_TOKEN = "-host"; //$NON-NLS-1$
   public static String ACCESS_SERVER_PORT_TOKEN = "-port"; //$NON-NLS-1$
   public static String ACCESS_SERVER_USER_TOKEN = "-user"; //$NON-NLS-1$
   public static String ACCESS_SERVER_PASSWORD_TOKEN = "-password"; //$NON-NLS-1$
   public static String SOURCE_DATASTORE_TOKEN = "-source"; //$NON-NLS-1$
   public static String TARGET_DATASTORE_TOKEN = "-target"; //$NON-NLS-1$
   public static String SUBSCRIPTION_NAME_TOKEN = "-subscriptionName"; //$NON-NLS-1$
   public static String PUBLICATION_NAME_TOKEN = "-publicationName"; //$NON-NLS-1$

   private DataSource accessServer;

   /**
    * Runs the sample.
    *
    * @param host the host name for access server.
    * @param port the port number of access server in the host machine.
    * @param user the login user name.
    * @param password the login password.
    * @param sourceDatastore the name of the source datastore.
    * @param subscriptionName the name of the subscription on the source.
    * @param targetDatastore the name of the target datastore.
    * @param publicationName the name of the publication on the target.
    * @throws ApiException if an error occurred.
    */
   public void run(
      String host,
      String port,
      String user,
      String password,
      String sourceDatastore,
      String subscriptionName,
      String targetDatastore,
      String publicationName) throws ApiException
   {
      try
      {
         connectAccessServer(host, port, user, password);

         PerformanceSnapshot performanceSnapshot = new PerformanceSnapshot();

         ReplicationRole srcDdatastore = null;
         if (sourceDatastore != null && sourceDatastore.length() > 0)
         {
            srcDdatastore = connectDatastore(sourceDatastore, true);

            Subscription subscription = ((Publisher) srcDdatastore).getSubscription(subscriptionName);
            if (subscription != null)
            {
               performanceSnapshot.setSubscription(subscription);
            }
         }

         ReplicationRole tgtDatastoreatastore = null;
         if (targetDatastore != null && targetDatastore.length() > 0)
         {
            tgtDatastoreatastore = connectDatastore(targetDatastore, false);

            Publication publication = ((Subscriber) tgtDatastoreatastore).getPublication(publicationName);
            if (publication != null)
            {
               performanceSnapshot.setPublication(publication);
            }
         }

         System.out.println("Request and calculate bottleneck statistics, please wait..."); //$NON-NLS-1$
         PerformanceStatisticData bottleneckData = performanceSnapshot
            .getBottleneckPerformanceStatisticData();

         printCurrentResults(bottleneckData);

         if (srcDdatastore != null)
         {
            disconnectDatastore(srcDdatastore);
         }
         if (tgtDatastoreatastore != null)
         {
            disconnectDatastore(tgtDatastoreatastore);
         }
      }
      finally
      {
         disconnectAccessServer();
      }
   }

   /**
    * Connects to a replication agent.
    * 
    * @param datastoreName the name of the datastore.
    * @param source true to request source statistics, false to request target statistics.
    * @throws ApiException if an error occurred.
    */
   public ReplicationRole connectDatastore(String datastoreName, boolean source) throws ApiException
   {
      if (accessServer == null || !accessServer.isOpen())
      {
         throw new ApiException("Connection to Access Server is not established"); //$NON-NLS-1$
      }

      ReplicationRole datastore;

      if (source)
      {
         datastore = accessServer.getPublisher(datastoreName);
      }
      else
      {
         datastore = accessServer.getSubscriber(datastoreName);
      }

      if (datastore == null)
      {
         throw new ApiException("Failed to locate a datastore: " + datastoreName); //$NON-NLS-1$
      }

      if (!datastore.isConnected())
      {
         try
         {
            System.out.println("Connecting to " + datastoreName + "..."); //$NON-NLS-1$ //$NON-NLS-2$
            datastore.connect();
            System.out.println("Connected."); //$NON-NLS-1$
         }
         catch (ApiException e)
         {
            throw new ApiException("Failed to connect to datastore " + datastoreName + ". " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
         }
      }

      return datastore;
   }

   /**
    * Disconnects from the datastore.
    * 
    * @param datastore the datastore.
    * @throws ApiException If an error occurred
    */
   public void disconnectDatastore(ReplicationRole datastore) throws ApiException
   {
      boolean disconnecting = false;

      if (datastore != null && datastore.isConnected())
      {
         System.out.println("Disconnecting from " + datastore.getName() + "..."); //$NON-NLS-1$ //$NON-NLS-2$
         disconnecting = true;
         datastore.disconnect();
      }

      if (datastore != null && datastore.isConnected())
      {
         throw new ApiException("Failed to disconnect from a dataStore " + datastore.getName()); //$NON-NLS-1$
      }
      else if (disconnecting)
      {
         System.out.println("Disconnected."); //$NON-NLS-1$
      }
   }

   /**
    * Connects to access server.
    *
    * @param host the host name for access server.
    * @param port the port number of access server on the host machine.
    * @param user the login user name.
    * @param password the login password.
    * @throws ApiException if an error occurred.
    */
   public void connectAccessServer(String host, String port, String user, String password)
      throws ApiException
   {
      try
      {
         System.out.println("Connecting to Access Server..."); //$NON-NLS-1$

         accessServer = Toolkit.getDefaultToolkit().createDataSource();

         DefaultContext eaAccessContext = new DefaultContext();
         eaAccessContext.setString(DataSource.User, user);
         eaAccessContext.setString(DataSource.Password, password);
         eaAccessContext.setString(DataSource.Hostname, host);
         eaAccessContext.setInt(DataSource.Port, Integer.parseInt(port));
         accessServer.connect(eaAccessContext);

         System.out.println("Connected."); //$NON-NLS-1$
      }
      catch (ApiException e)
      {
         throw new ApiException("Failed to connect to " + host + "@" + port + " as " + user); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
      }
   }

   /**
    * Disconnects from access server.
    * 
    * @throws ApiException if an error occurred.
    */
   public void disconnectAccessServer() throws ApiException
   {
      boolean disconnecting = false;

      if (accessServer != null && accessServer.isOpen())
      {
         System.out.println("Disconnecting from Access Server..."); //$NON-NLS-1$
         disconnecting = true;
         accessServer.close();
      }

      if (accessServer != null && accessServer.isOpen())
      {
         throw new ApiException("Failed to disconnect from AccessServer"); //$NON-NLS-1$
      }
      else if (disconnecting)
      {
         System.out.println("Disconnected."); //$NON-NLS-1$
      }
   }

   /**
    * Returns an example of arguments for the class.
    * 
    * @return the help string.
    */
   public static String getHelp()
   {
      String help = "java -classpath \"{pathToSample and api.jar}\" PerformanceBottleneckSample\n" //$NON-NLS-1$
         + "  [-host accessServerHost -port accessServerPort]\n" //$NON-NLS-1$
         + "   -user accessServerUser -password accessServerPassword\n" //$NON-NLS-1$
         + "  -source sourceDataStoreName -subscriptionName subscriptionName\n" //$NON-NLS-1$
         + "  -target targetDataStoreName -publicationName publicationName\n" //$NON-NLS-1$
         + "If -host or -port are not specified, \"localhost\" and \"10101\" will be used.\n" //$NON-NLS-1$
         + "-source/-subscriptionName and/or -target/-publication are required."; //$NON-NLS-1$

      return help;
   }

   /**
    * Returns the named argument's value.
    * 
    * @param args the command line arguments.
    * @param name the name of the command line argument.
    * @param defaultValue the default value. If null is specified, then an exception
    * is thrown if the parameter does not exist.
    * @return value for the argument.
    * @throws IllegalArgumentException if the argument is missing.
    */
   private String getParameter(String[] args, String name, String defaultValue)
      throws IllegalArgumentException
   {
      String parameter = null;

      for (int i = 0; i < args.length - 1; i++)
      {
         if (args[i].equalsIgnoreCase(name))
         {
            parameter = args[i + 1];
            break;
         }
      }

      if (parameter == null)
      {
         if (defaultValue == null)
         {
            throw new IllegalArgumentException("Parameter " + name + " is missing."); //$NON-NLS-1$ //$NON-NLS-2$
         }
         else
         {
            parameter = defaultValue;
         }
      }

      return parameter;
   }

   public static void main(String[] args)
   {
      try
      {
         PerformanceBottleneckSample sample = new PerformanceBottleneckSample();

         // Access server connection information.
         String host = sample.getParameter(args, ACCESS_SERVER_HOST_TOKEN, "localhost"); //$NON-NLS-1$
         String port = sample.getParameter(args, ACCESS_SERVER_PORT_TOKEN, "10101"); //$NON-NLS-1$
         String user = sample.getParameter(args, ACCESS_SERVER_USER_TOKEN, null);
         String password = sample.getParameter(args, ACCESS_SERVER_PASSWORD_TOKEN, null);

         // Source information. If the datastore is specified, then the subscription
         // name must be as well.
         String sourceDatastore = null;
         String subscriptionName = null;

         sourceDatastore = sample.getParameter(args, SOURCE_DATASTORE_TOKEN, ""); //$NON-NLS-1$
         if (sourceDatastore != null && sourceDatastore.length() > 0)
         {
            subscriptionName = sample.getParameter(args, SUBSCRIPTION_NAME_TOKEN, null);
         }

         // Target information.
         String targetDatastore = null;
         String publicationName = null;

         targetDatastore = sample.getParameter(args, TARGET_DATASTORE_TOKEN, ""); //$NON-NLS-1$
         if (targetDatastore != null && targetDatastore.length() > 0)
         {
            publicationName = sample.getParameter(args, PUBLICATION_NAME_TOKEN, null);
         }

         if (sourceDatastore.length() == 0 && targetDatastore.length() == 0)
         {
            throw new IllegalArgumentException("Parameter " + SOURCE_DATASTORE_TOKEN //$NON-NLS-1$
               + " and/or " //$NON-NLS-1$
               + TARGET_DATASTORE_TOKEN + " is required."); //$NON-NLS-1$
         }
         if (subscriptionName == null && publicationName == null)
         {
            throw new IllegalArgumentException("Parameter " + SUBSCRIPTION_NAME_TOKEN //$NON-NLS-1$
               + " and/or " //$NON-NLS-1$
               + PUBLICATION_NAME_TOKEN + " is required."); //$NON-NLS-1$
         }

         sample.run(
            host,
            port,
            user,
            password,
            sourceDatastore,
            subscriptionName,
            targetDatastore,
            publicationName);
      }
      catch (IllegalArgumentException e)
      {
         System.out.println(PerformanceBottleneckSample.getHelp());
      }
      catch (Exception e)
      {
         System.out.println(e.getMessage());
         System.out.println();
         e.printStackTrace();
      }
   }

   /**
    * Prints the current results.
    * 
    * @param statistics the statistics.
    */
   public void printCurrentResults(PerformanceStatisticData statistics)
   {
      int id;
      String pad = "                                     "; //$NON-NLS-1$

      System.out.println();

      for (StatisticDefinition definition : statistics.getDefinitions())
      {
         System.out.print((definition.getName() + pad).substring(0, 30) + " "); //$NON-NLS-1$
      }

      System.out.println();

      for (int i = 0, cnt = statistics.getDefinitions().size(); i < cnt; i++)
      {
         System.out.print("------------------------------ "); //$NON-NLS-1$
      }

      System.out.println();

      int records = statistics.getSize();
      for (int row = 0; row < records; row++)
      {
         for (StatisticDefinition definition : statistics.getDefinitions())
         {
            id = definition.getId();
            long value = 0;
            try
            {
               value = statistics.getValue(row, id);
            }
            catch (DataNotFoundException e)
            {
               // do nothing
            }
            System.out.print((value + pad).substring(0, 30) + " "); //$NON-NLS-1$
         }
         System.out.println();
      }

      System.out.println();
      System.out.println();
   }
}