Package org.jboss.test.cluster.invokerha

Source Code of org.jboss.test.cluster.invokerha.InvokerHaInfrastructure$TraceFirstAvailable

/*
* JBoss, Home of Professional Open Source.
* Copyright 2007, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.test.cluster.invokerha;

import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.rmi.server.UID;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.transaction.Transaction;

import org.jboss.ha.framework.interfaces.FamilyClusterInfo;
import org.jboss.ha.framework.interfaces.FirstAvailable;
import org.jboss.ha.framework.interfaces.FirstAvailableIdenticalAllProxies;
import org.jboss.ha.framework.interfaces.HAPartition;
import org.jboss.ha.framework.interfaces.HARMIClient;
import org.jboss.ha.framework.interfaces.LoadBalancePolicy;
import org.jboss.ha.framework.interfaces.RandomRobin;
import org.jboss.ha.framework.interfaces.RoundRobin;
import org.jboss.ha.framework.server.HATarget;
import org.jboss.invocation.Invocation;
import org.jboss.invocation.InvocationContext;
import org.jboss.invocation.Invoker;
import org.jboss.invocation.InvokerHA;
import org.jboss.logging.Logger;
import org.jboss.system.Registry;

/**
* Infrastructure class that encapsulates the simulated deployment of
* servers or invoker endpoints and mbeans that receive the invocations.
*
* @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
*/
public class InvokerHaInfrastructure
{
   private static final Logger log = Logger.getLogger(InvokerHaInfrastructure.class);
  
   /**
    * MBeanServer instance. This is not gonna run in Java 1.4.x, so we can
    * safely assume that we can use Java's MBeanServer.
    */
   private static final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
  
   private InvokerHaFactory invokerHaFactory;
  
   private final ObjectName dateTimeTellerON;
  
   private final ObjectName systemTimeTellerON;
  
   private final ObjectName clientUserTransactionServiceON;
  
   private final Integer dateTimeTellerONHashCode;
  
   private final Integer systemTimeTellerONHashCode;
  
   private final Integer clientUserTransactionServiceONHashCode;
  
   private final int serverCount;
  
   private List<? extends InvokerHA> replicants;
  
   private List<ObjectName> invokerONs;
  
   /**
    * Create a new InvokerHaInfrastructure.
    *
    * @param serverCount number of invoker endpoints to create
    * @param invokerHaFactory invoker ha factory class implementation
    */
   public InvokerHaInfrastructure(int serverCount, InvokerHaFactory invokerHaFactory)
   {
      this.serverCount = serverCount;
      this.invokerHaFactory = invokerHaFactory;

      try
      {
         /* initialise ObjectNames and hashcodes */
         dateTimeTellerON = new ObjectName("com.acme.mbeans:type=DateTimeTeller");
         systemTimeTellerON = new ObjectName("com.acme.mbeans:type=SystemTimeTeller");
         clientUserTransactionServiceON = new ObjectName("com.acme.mbeans:type=ClientUserTransactionService");
         dateTimeTellerONHashCode = new Integer(dateTimeTellerON.hashCode());
         systemTimeTellerONHashCode = new Integer(systemTimeTellerON.hashCode());
         clientUserTransactionServiceONHashCode = new Integer(clientUserTransactionServiceON.hashCode());
  
         /* create a list of object names for the invoker endpoints */
         invokerONs = new ArrayList<ObjectName>(this.serverCount);
         for (int i = 0; i < serverCount; i++)
         {
            invokerONs.add(new ObjectName("com.acme.invokers:type=" + this.invokerHaFactory.getInvokerTypeName() + "-Server" + (i + 1)));
         }
      }
      catch (MalformedObjectNameException mone)
      {
         throw new IllegalArgumentException("invalid object name", mone);
      }     
   }

   /**
    * Binds ObjectName hash code with the ObjectName which is used by the
    * invoker. We just do it once cos both servers are in the same VM.
    */
   public void registerManagedObjects()
   {
      Registry.bind(dateTimeTellerONHashCode, dateTimeTellerON);
      Registry.bind(systemTimeTellerONHashCode, systemTimeTellerON);
      Registry.bind(clientUserTransactionServiceONHashCode, clientUserTransactionServiceON);     
   }

   /**
    * Create a list of invoker ha instances, called the replicants, and
    * register the list with the mbean server.
    */
   public void deployServers() throws Exception
   {
      List<InvokerHA> replicantServers = new ArrayList<InvokerHA>(serverCount);
     
      /* create n invoker instances that emulate n AS servers */
      for (int i =0; i < serverCount; i++)
      {
         InvokerHA server = invokerHaFactory.createInvokerHaServer("Server", i + 1);
         /* add invoker as replicant */
         replicantServers.add(server);
        
         mbs.registerMBean(server, invokerONs.get(i));
      }

      replicants = replicantServers;
   }

   /**
    * Create new instance of DateTimeTeller and register it with the
    * MBeanServer. Note that a single instance is created and both server
    * invokers point to this instance behind the scenes. This simplifies
    * testing.
    */  
   public DateTimeTeller createDateTimeTeller() throws Exception
   {
      DateTimeTeller dateTimeTellerMBean = new DateTimeTeller();
      mbs.registerMBean(dateTimeTellerMBean, dateTimeTellerON);
      return dateTimeTellerMBean;
   }

   /**
    * Create new instance of SystemTimeTeller and register it with the
    * MBeanServer. Note that a single instance is created and both server
    * invokers point to this instance behind the scenes. This simplifies
    * testing.
    */
   public SystemTimeTeller createSystemTimeTeller() throws Exception
   {
      SystemTimeTeller systemTimeTellerMBean = new SystemTimeTeller();
      mbs.registerMBean(systemTimeTellerMBean, systemTimeTellerON);
      return systemTimeTellerMBean;
   }
  
   public ClientUserTransactionService createClientUserTransactionService() throws Exception
   {
      ClientUserTransactionService clientUserTransactionServiceMBean = new ClientUserTransactionService();
      mbs.registerMBean(clientUserTransactionServiceMBean, clientUserTransactionServiceON);
      return clientUserTransactionServiceMBean;
   }  
  
   /**
    * Deploy date time teller mbean in each server, or invoker endpoint,
    * creating a mock HATarget with the list of replicants and associating the
    * mbean's object name with the HATarget instance.  
    */
   public void deployDateTimeTeller() throws Exception
   {
      deploy(replicants, dateTimeTellerON, "DateTimeTellerReplicant");
   }

   /**
    * Deploy system time teller mbean in each server, or invoker endpoint,
    * creating a mock HATarget with the list of replicants and associating the
    * mbean's object name with the HATarget instance.  
    */
   public void deploySystemTimeTeller() throws Exception
   {
      deploy(replicants, systemTimeTellerON, "SystemTimeTellerReplicant");
   }
  
   public void deployClientUserTransactionService() throws Exception
   {
      deploy(replicants, clientUserTransactionServiceON, "ClientUserTransactionServiceReplicant");
   }  
  
   /**
    * Create a proxy to date time teller bean.
    *
    * @param serverIndex invoker endpoint from which to return the proxy
    * @param policyClass load balance policy to use in the proxy
    * @return
    * @throws Exception
    */
   public Invoker createDateTimeTellerProxy(int serverIndex, Class<? extends LoadBalancePolicy> policyClass) throws Exception
   {
      InvokerHA server = replicants.get(serverIndex);
      log.debug("replicants: " + replicants);
      return server.createProxy(dateTimeTellerON, policyClass.newInstance(), "UnitTestPartition/DateTimeTellerMBean");
   }
  
   /**
    * Create a proxy to system time teller bean.
    *
    * @param serverIndex invoker endpoint from which to return the proxy
    * @param policyClass load balance policy to use in the proxy
    * @return
    * @throws Exception
    */
   public Invoker createSystemTimeTellerProxy(int serverIndex, Class<? extends LoadBalancePolicy> policyClass) throws Exception
   {
      InvokerHA server = replicants.get(serverIndex);
      return server.createProxy(systemTimeTellerON, policyClass.newInstance(), "UnitTestPartition/SystemTimeTellerMBean");
   }

   public Invoker createClientUserTransactionProxy(int serverIndex, Class<? extends LoadBalancePolicy> policyClass) throws Exception
   {
      InvokerHA server = replicants.get(serverIndex);
      return server.createProxy(clientUserTransactionServiceON, policyClass.newInstance(), "UnitTestPartition/ClientUserTransactionServiceMBean");
   }  
  
   /**
    * Create a new invocation for date time teller mbean
    *
    * @param tx instance of Transaction. If tx is null, transaction is not
    * added to invocation, which is useful to replicate transactions starting
    * in non managed environments.
    * @param failureType type of failure to inject. If null, no failure is
    * injected.
    * @return
    */
   public Invocation createDateTimeTellerInvocation(Transaction tx, InvokerHaFailureType failureType, Invoker invoker)
   {
      return createInvocation(tx, dateTimeTellerONHashCode, failureType, invoker);
   }
  
   /**
    * Create a new invocation for system time teller mbean
    *
    * @param tx instance of Transaction. If tx is null, transaction is not
    * added to invocation, which is useful to replicate transactions starting
    * in non managed environments.
    * @return
    */
   public Invocation createSystemTimeTellerInvocation(Transaction tx, InvokerHaFailureType failureType, Invoker invoker)
   {
      return createInvocation(tx, systemTimeTellerONHashCode, failureType, invoker);
  
  
   public Invocation createClientUserTransactionInvocation(Transaction tx, InvokerHaFailureType failureType, Invoker invoker)
   {
      return createInvocation(tx, clientUserTransactionServiceONHashCode, failureType, invoker);
   }
  
   /**
    * Unbind mbean object name hashcodes from JMX registry.
    */
   public void unregisterManagedObjects()
   {
      /* Unregister from the JMX registry */
      Registry.unbind(dateTimeTellerONHashCode);
      Registry.unbind(systemTimeTellerONHashCode);     
      Registry.unbind(clientUserTransactionServiceONHashCode);
   }
  
   /**
    * Unregister date time teller mbean object name from each invoker endpoint
    * and from the mbean server.
    */
   public void undeployDateTimeTeller() throws Exception
   {
      undeploy(replicants, dateTimeTellerON);
   }

   /**
    * Unregister system time teller mbean object name from each invoker endpoint
    * and from the mbean server.
    */
   public void undeploySystemTimeTeller() throws Exception
   {
      undeploy(replicants, systemTimeTellerON);
   }
  

   public void undeployClientUserTransactionService() throws Exception
   {
      undeploy(replicants, clientUserTransactionServiceON);
   }
  
   /**
    * Unregister invoker endpoints from mbean server.
    */
   public void undeployServers() throws Exception
   {
      for (int i = 0; i < serverCount; i++)
      {
         mbs.unregisterMBean(invokerONs.get(i));
      }
   }
  
   public List<? extends InvokerHA> getReplicants()
   {
      return replicants;
   }
  
   /**
    * Simulate the deployment of an mbean in a list of invoker endpoints.
    *
    * @param replicants list of invoker endpoints
    * @param targetName object name of the mbean to deploy
    * @param replicantName replicant name
    * @throws Exception
    */
   protected void deploy(List<? extends InvokerHA> replicants, ObjectName targetName, String replicantName) throws Exception
   {
      for(InvokerHA replicant : replicants)
      {
         /* create ha-target in the server with the list of replicants and register
          * it with the MBeanServer. */
         HATarget target = new MockHATarget(null, replicantName, null, 2);
         target.replicantsChanged(null, replicants, 0, false);
         replicant.registerBean(targetName, target);        
      }
   }

   /**
    * Simulate the undeployment of an mbean from a list of invoker endpoints.
    *
    * @param replicants list of invoker endpoints
    * @param targetName object name of the mbean to deploy
    * @throws Exception
    */
   protected void undeploy(List<? extends InvokerHA> replicants, ObjectName targetName) throws Exception
   {
      for(InvokerHA replicant : replicants)
      {
         replicant.unregisterBean(targetName);
      }
     
      mbs.unregisterMBean(targetName);     
   }
  
   /**
    * Create invocation with optional transaction instance for the target mbean
    * with the given hashcode.
    *
    * @param tx instance of transaction
    * @param hashCode hashcode of object name of the mbean
    * @return
    */
   private Invocation createInvocation(Transaction tx, Integer hashCode, InvokerHaFailureType failureType, Invoker invoker)
   {
      Invocation inv = new Invocation();
      inv.setObjectName(hashCode);
      if (tx != null)
      {
         inv.setTransaction(tx);
      }
      if (failureType != null)
      {
         inv.setValue("FAILURE_TYPE", failureType);
      }

      InvocationContext ctx = new InvocationContext();
      ctx.setInvoker(invoker);
      inv.setInvocationContext(ctx);
     
      return inv;
   }
     
   /** Interfaces **/
  
   /**
    * Factory interface to be implemented by different type of invokers
    * available, i.e. jrmp, unified, pooled...etc.
    */
   public interface InvokerHaFactory
   {
      /**
       * Returns the invoker type name
       *
       * @return String representing the invoker type
       */
      String getInvokerTypeName();
     
      /**
       * Return invoker ha instructure instance associated with this invoker.
       *
       * @param serverCount number of invocation endpoints, or simulated cluster nodes
       * @return InvokerHaInfrastructure instance of infrastructure
       */     
      InvokerHaInfrastructure getInvokerHaInfrastructure(int serverCount);
     
      /**
       * Returns the invoker ha tx failover authorisations map.
       *
       * @return WeakHashMap containing the tx failover authorisations.
       */
      Map getTxFailoverAuthorizationsMap();
     
      /**
       * Creates an instance of invoker endpoint.
       *
       * @param serverName name of invoker endpoint
       * @param serverNumber invoker endpoint number
       * @return
       */
      InvokerHA createInvokerHaServer(String serverName, int serverNumber);
     
      /**
       * Returns transient payload key to retrieve chosen target.
       *
       * @return String representation of the key
       */
      String getChosenTargetKey();
   }
  
   /**
    * Date time teller mbean interface
    */
   public interface DateTimeTellerMBean
   {
      Object invoke(Invocation invocation) throws Exception;
   }
  
   /**
    * Systemr time teller mbean interface
    */
   public interface SystemTimeTellerMBean
   {
      Object invoke(Invocation invocation) throws Exception;
   }
  
   public interface ClientUserTransactionServiceMBean
   {
      Object invoke(Invocation invocation) throws Exception;     
   }
  
   /** Classes **/
  
   public class DateTimeTeller implements DateTimeTellerMBean
   {
      public Object invoke(Invocation invocation) throws Exception
      {
         /* returns a Date representation of the current time */
         return new Date(System.currentTimeMillis());
      }
   }
  
   public class SystemTimeTeller implements SystemTimeTellerMBean
   {
      public Object invoke(Invocation invocation) throws Exception
      {
         /* returns a long (milliseconds) representation of the current time */
         return System.currentTimeMillis();
      }     
   }
  
   public class ClientUserTransactionService implements ClientUserTransactionServiceMBean
   {
      public Object invoke(Invocation invocation) throws Exception
      {
         // Return new tpc -> only begin() calls really tested as they set the sticky target
         return new UID();
      }
   }
  
   /**
    * MockHATarget class that avoids using DistributedReplicantManager in any
    * way. The unit test will force changes in the composition of replicants,
    * that avoids the need of replicant manager or listener.
    */
   public class MockHATarget extends HATarget
   {
      public MockHATarget(HAPartition partition, String replicantName, Serializable target, int allowInvocations) throws Exception
      {
         super(partition, replicantName, target, allowInvocations);
      }

      /**
       * No-op to avoid DistributedReplicantManager being set up at within the
       * super's constructor.
       */
      @Override
      public void updateHAPartition(HAPartition partition) throws Exception
      {
      }
   }
  
   /**
    * Load balance policy based on a delegate pattern that tracks down the
    * chosen target for the invocation and puts it in the transient payload.
    * This allows for UTs to inspect the content and potentially check whether
    * load balance policies are working correctly.
    *
    * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
    */
   public static class TraceLoadBalancePolicy implements LoadBalancePolicy
   {
      /** The serialVersionUID */
      private static final long serialVersionUID = 3089456214843995414L;
     
      /** Load balance policy to delegate to */
      private LoadBalancePolicy delegateTo;

      public TraceLoadBalancePolicy(LoadBalancePolicy delegateTo)
      {
         this.delegateTo = delegateTo;
      }

      public Object chooseTarget(FamilyClusterInfo clusterFamily)
      {
         return delegateTo.chooseTarget(clusterFamily);
      }

      public Object chooseTarget(FamilyClusterInfo clusterFamily, Invocation routingDecision)
      {
         Object chosenTarget = delegateTo.chooseTarget(clusterFamily, routingDecision);
        
         /* put chosen target in the transient payload */
         routingDecision.getTransientPayload().put("TEST_CHOSEN_TARGET", chosenTarget);
         log.debug("chosen target: " + chosenTarget);
         return chosenTarget;
      }

      public void init(HARMIClient father)
      {
         delegateTo.init(father);
      }     
   }
  
   /**
    * Trace load balance policy specific for round robin. This allows for non
    * argument construction of such load balance policy, which makes it testing
    * cleaner. We just pass the load balance policy class and we use reflection
    * to create a new instance. 
    *
    * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
    */
   public static class TraceRoundRobin extends TraceLoadBalancePolicy
   {
      /** The serialVersionUID */
      private static final long serialVersionUID = -8583420254744619692L;
     
      public TraceRoundRobin()
      {
         super(new RoundRobin());
      }
   }

   /**
    * Trace load balance policy specific for first available. This allows for non
    * argument construction of such load balance policy, which makes it testing
    * cleaner. We just pass the load balance policy class and we use reflection
    * to create a new instance. 
    *
    * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
    */
   public static class TraceFirstAvailable extends TraceLoadBalancePolicy
   {
      /** The serialVersionUID */
      private static final long serialVersionUID = -1626190092127048933L;
   
      public TraceFirstAvailable()
      {
         super(new FirstAvailable());
      }     
   }

   /**
    * Trace load balance policy specific for first available indentical all
    * proxies. This allows for non argument construction of such load balance
    * policy, which makes it testing cleaner. We just pass the load balance
    * policy class and we use reflection to create a new instance. 
    *
    * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
    */
   public static class TraceFirstAvailableIdenticalAllProxies extends TraceLoadBalancePolicy
   {
      /** The serialVersionUID */
      private static final long serialVersionUID = -8656749681577922508L;

      public TraceFirstAvailableIdenticalAllProxies()
      {
         super(new FirstAvailableIdenticalAllProxies());
      }     
   }
  
   /**
    * Trace load balance policy specific for random robin. This allows for non
    * argument construction of such load balance policy, which makes it testing
    * cleaner. We just pass the load balance policy class and we use reflection
    * to create a new instance. 
    *
    * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
    */
   public static class TraceRandomRobin extends TraceLoadBalancePolicy
   {
      /** The serialVersionUID */
      private static final long serialVersionUID = -1626190092127048933L;
   
      public TraceRandomRobin()
      {
         super(new RandomRobin());
      }     
   }
}
TOP

Related Classes of org.jboss.test.cluster.invokerha.InvokerHaInfrastructure$TraceFirstAvailable

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.