Partition state change notifiers

In certain cases an application may need to be notified of partition state changes. This is supported using the com.kabira.platform.highavailability.PartitionNotifier abstract class.

An application must create and register a partition notifier on each node where it is interested in receiving notifications of partition state changes. The stateChange method will be called for each state change for all partitions to which it is registered.

Example 7.12, “Monitoring partition state changes” shows a simple example that monitors partition state changes. This example defines a single partition and then prints out all partition state changes. The partition state changes are triggered using administration tools.

[Warning]

This example does not exit until explicitly shutdown by terminating the deployment tool or using administration tools to stop the JVM.

Example 7.12. Monitoring partition state changes

//     $Revision: 1.1.2.4 $
package com.kabira.snippets.highavailability;

import com.kabira.platform.ManagedObject;
import com.kabira.platform.Transaction;
import com.kabira.platform.highavailability.Partition;
import com.kabira.platform.highavailability.Partition.State;
import com.kabira.platform.highavailability.PartitionManager;
import com.kabira.platform.highavailability.PartitionNotifier;
import com.kabira.platform.highavailability.ReplicaNode;
import static com.kabira.platform.highavailability.ReplicaNode.ReplicationType.SYNCHRONOUS;

/**
 * Snippet on handling partition state changes.
 * <p>
 * <h2> Target Nodes</h2>
 * <ul>
 * <li> <b>domainnode</b> = A
 * </ul>
 */
public class StateChange
{
    /**
     * Partition state change notifier
     */
    private static class Notifier extends PartitionNotifier
    {
        @Override
        protected void stateChange(String partitionName, State oldState, State newState)
        {
            Partition partition = PartitionManager.getPartition(partitionName);

            String message = "Partition: "
                + partition.getName()
                + " transitioning "
                + "from "
                + oldState
                + " to "
                + newState
                + " now hosted on "
                + partition.getActiveNode();
            System.out.println(message);
        }
    }

    /**
     * Main entry point
     *
     * @param args Not used
     * @throws java.lang.InterruptedException
     */
    public static void main(String[] args) throws InterruptedException
    {
        final Notifier notifier = initialize();

        //
        //    Wait here for operator to shutdown example
        //
        waitForOperator();

        //
        //  Clean up partition notifier
        //
        new Transaction("Remove Partition Notifier")
        {
            @Override
            protected void run() throws Rollback
            {
                ManagedObject.delete(notifier);
            }
        }.execute();
    }

    //
    //  Wait for operator to shutdown example
    //
    private static void waitForOperator()
        throws InterruptedException
    {
        //
        //	Wait until operator requests JVM to exit
        //
        while (true)
        {
            System.out.println("Waiting for operator...");
            Thread.sleep(5000);
        }
    }
    
    private static Notifier initialize()
    {
        return new Transaction("Create Partition Notifier")
        {
            @Override
            protected void run() throws Transaction.Rollback
            {
                m_notifier = new Notifier();

                ReplicaNode[] replicas = new ReplicaNode[]
                {
                    new ReplicaNode("B", SYNCHRONOUS),
                    new ReplicaNode("C", SYNCHRONOUS)
                };
                PartitionManager.definePartition(PARTITION_NAME, null, "A", replicas);

                //
                //  Partition is not enabled - use administration
                //  tools to enable partition
                //
                System.out.println("Enable the " + PARTITION_NAME + " partition.");

                //
                //  Register the partition notifier
                //
                Partition partition = PartitionManager.getPartition(PARTITION_NAME);
                partition.setNotifier(m_notifier);
            }
            
            Notifier initialize()
            {
                execute();
                return m_notifier;
            }
            
            private Notifier m_notifier = null;
        }.initialize();
    }
    
    private static final String PARTITION_NAME = "Notifier Snippet";
}

When Example 7.12, “Monitoring partition state changes” is run it outputs the (annotation added) information in Example 7.13, “Partition state change output”.

Example 7.13. Partition state change output

#
# Partitions enabled on node A.  Partition comes active on A node
#
# administrator servicename=A enable partition name="Notifier Snippet"
#
Partition: Notifier Snippet transitioning from INITIAL to MIGRATING now hosted on A
Partition: Notifier Snippet transitioning from MIGRATING to ACTIVE now hosted on A

#
# Partitions disabled on node A.  Partition fails over to node B
#
# administrator servicename=A disable partition name="Notifier Snippet"
#
Partition: Notifier Snippet transitioning from ACTIVE to MIGRATING now hosted on A
Partition: Notifier Snippet transitioning from MIGRATING to ACTIVE now hosted on B
Partition: Notifier Snippet transitioning from ACTIVE to UNAVAILABLE now hosted on B

#
# Partition restored to node A from node B.
#
# administrator servicename=A define partition name="Notifier Snippet" activenode=A replicas=B,C
# administrator servicename=A display partition name="Notifier Snippet"
#
Partition: Notifier Snippet transitioning from ACTIVE to MIGRATING now hosted on B
Partition: Notifier Snippet transitioning from MIGRATING to ACTIVE now hosted on A