Putting it all together

This section completes this chapter by upgrading a cluster with the new class. The class being upgraded is the Person class discussed in the section called “Upgrade utility”. The simple application show in Example 8.4, “Upgrade application” is being deployed. This application performs these steps:

  1. Define and enable a partition.

  2. Create a Person object.

  3. Wait for the operator to shut down the application.

Example 8.4. Upgrade application

//     $Revision: 1.1.2.2 $
package com.kabira.snippets.upgrade;

import com.kabira.platform.highavailability.ReplicaNode;
import static com.kabira.platform.highavailability.ReplicaNode.ReplicationType.*;
import com.kabira.platform.Transaction;
import com.kabira.platform.Transaction.Rollback;
import com.kabira.platform.highavailability.PartitionMapper;
import com.kabira.platform.highavailability.PartitionManager;
import static com.kabira.platform.highavailability.PartitionManager.EnableAction.*;

//
//  Partition mapper that puts all objects in a known partition
//
class Mapper extends PartitionMapper
{
    final static String PARTITION_NAME = "Upgrade";
    
    @Override
    public String getPartition(Object obj)
    {
        return PARTITION_NAME;
    }    
}

/**
 * Define a partition and create an instance of an object that will be upgraded
 * 
 * <p>
 * <h2> Target Nodes</h2>
 * <ul>
 * <li> <b>domainnode</b> = "A"
 * </ul>
 */
public class Upgrade
{
    /**
     * Main entry point
     * 
     * @param args  Not used
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException
    {
        new Transaction("Upgrade")
        {
            @Override
            protected void run() throws Rollback
            {
                PartitionManager.setMapper(Person.class, new Mapper());
                ReplicaNode [] replicas = new ReplicaNode []
                {
                    new ReplicaNode("B", SYNCHRONOUS),
                    new ReplicaNode("C", SYNCHRONOUS)
                };
                PartitionManager.definePartition(
                    Mapper.PARTITION_NAME, 
                    null, 
                    "A", 
                    replicas);
                PartitionManager.enablePartitions(JOIN_CLUSTER);
            }
        }.execute();
        
        new Transaction("Create Object")
        {
            @Override
            protected void run() throws Rollback
            {
                new Person();
            }
        }.execute();
        
        waitForStop();
    }
    
    //
    //  Wait for termination
    //
    private static void waitForStop() throws InterruptedException
    {
        System.out.println("Waiting for stop...");

        while (true)
        {
            Thread.sleep(5000);
        }
   }
}

The application is deployed by copying the JAR file containing the upgrade application to a deployment directory and using the deployment tool in detached mode to deploy the application. These steps are shown for a deployment directory located in /Volumes/kabira/ast/deploy.

#
#   Copy JAR file to deployment directory.  
#   The snippet.jar file is used which is the output of building
#   the entire snippets project.
#
cp snippets.jar /Volumes/kabira/ast/deploy

#
#   Deploy the application to node A using the deployment tool.
#
#   NOTE: hostname will be specific to your environment.
#
java -jar deploy.jar detach=true username=guest password=guest \
     hostname=172.16.208.128 adminport=2000 domainnode=A \
     com.kabira.snippets.upgrade.Upgrade

INFO: deploy.jar version: [TIBCO TIBCO ActiveSpaces® Transactions
 2.2.0 (build 120302)] 
      starting at [Sat Mar 10 09:10:41 PST 2012]
INFO: node [A] version: [TIBCO TIBCO ActiveSpaces® Transactions
 2.2.0 (build 120302)]
INFO: node [A] JVM remote debugger agent listening on port [21267] ...
INFO: Starting application [com.kabira.snippets.upgrade.Upgrade] ...
[A] WARNING: loopback ip address choosen, this agent may not connect to remote agents
[A] ip_address=127.0.0.1 port=50004
[A] Listening for transport dt_socket at address: 21267
[A] INFO: JMX Management Service started at:
[A]   kabira-server:2099
[A]   172.16.208.130:2099
[A]   service:jmx:rmi:///jndi/rmi://kabira-server:2099/jmxrmi
[A] Waiting for stop...
INFO: Component [com.kabira.snippets.upgrade.Upgrade] started in detached mode.

Displaying the initial version of a Person object in shared memory on node A shows the values in Figure 8.2, “Initial version of person object”.

Initial version of person object

Figure 8.2. Initial version of person object


The replicated version of this object has the same values on replica nodes B and C.

The Person class is updated and a new version of the snippets.jar file is generated and deployed into the deployment directory after generating an upgrade plan as shown in the section called “Upgrade utility”. Node A is then upgraded using the TIBCO ActiveSpaces® Transactions Administrator Upgrade or Restore... node dialog shown in Figure 8.3, “Upgrade node”.

Upgrade node

Figure 8.3. Upgrade node


When the upgrade completes an upgrade report is displayed as shown below.

[A] Starting upgrade ...
[A]
[A] Removing node A from the cluster ...
[A]
[A] Stopping node A ...
[A]
[A]   Stopping node
[A]     node::administration stopping ...
[A]  Ok
[A]     distribution::distribution stopping ... Ok
[A]     application::com_kabira_snippets_upgrade_Upgrade1 stopping ... Ok
[A]   Node stopped
[A]
[A] Starting type replacement on node A ...
[A]   running
[A]   running
[A]   running
[A]   complete
[A]
[A] Starting node A ...
[A]
[A]   Node A is already running.
[A]
[A]   Node A is configured to use DEVELOPMENT executables
[A]   Node A shared memory size is 512Mb
[A]   Node A path: /opt/kabira/run/ast/nodes/A
[A]   Node A host: kabira-server
[A]
[A]   System Coordinator Host: All Interfaces
[A]   System Coordinator Port: 2001
[A]
[A]   Web Server Host: All Interfaces
[A]   Web Server Port: 12796
[A]
[A]   Waiting for application to start ......
[A]
[A]   Components started
[A]   Loading configurations
[A]   Auditing security configuration
[A]   Host: localhost
[A]   Administration Port: 2001
[A]   Service Name: "A"
[A]   Node Name: "A"
[A]
[A] Updating partitions on node A ...
[A]   Partition Name = Upgrade
[A]   Active Node = B
[A]   Replica Nodes = C,A
[A]
[A] Enabling partitions on node A ...
[A] ...
[A] ...
[A] ...
[A] ...
[A] ...
[A]   Partition Name = Upgrade
[A]   Partition State = Active
[A]   Last State Change Time = 2011-10-07 13:29:08
[A]   Active Node = B
[A]   Replica Nodes = C:synchronous,A:synchronous
[A]
[A] Completed upgrade.
[A]
[A] Summary:
[A]   Node: A
[A]   Node state when command started: Running
[A]   Action: upgrade
[A]   Execute: true
[A]   Started: Fri Oct  7 13:28:40 PDT 2011
[A]   Finished: Fri Oct  7 13:29:09 PDT 2011
[A]   Classes File: /var/tmp/kmphpCpuNvx/upgrade.111007
[A]   Original Deployment Directories: /opt/kabira/run/ast/deploy
[A]   New Deployment Directories: /opt/kabira/run/ast/deploy
[A]
[A] Classes upgraded:
[A]   Class name: com.kabira.snippets.upgrade.Person
[A]   Current version: Not Set
[A]   New version: 1
[A]
[A] Active partitions migrated during upgrade:
[A]   Partition Name: Upgrade
[A]   Number of Objects: 1
[A]   New Active Node: B

At this point there are two different versions of the Person class deployed in the cluster. This can be seen in Figure 8.4, “Cluster version mismatch”. Notice that node A is reporting a local version of 1 and no remote version, while node B and C are reporting no local version, but a remote version of 1 for node A. This is because the new class deployed on node A defined a serialVersionUID field with a value of 1, while the old class version did not define a serialVersionUID field.

Cluster version mismatch

Figure 8.4. Cluster version mismatch


The object mapping can be seen by displaying the same object instance on two different nodes. Figure 8.5, “Initial version - node B” shows the initial version of the Person object on replica node B. Notice that it only has two fields - name and age.

Initial version - node B

Figure 8.5. Initial version - node B


Compare the display of the same object on node A, which has been upgraded to the new class version. There was a new field, type, added by the new parent class which was initialized to a value of Human. The name field was also broke into two fields - first and last. Finally, the type of the age field was changed. It is important to emphasis that the different application versions on the two different nodes see the exact same object differently. The mapping is completely transparent.

New version - node A

Figure 8.6. New version - node A