Example 9.11, “Partition definition in configuration” shows an example of using configuration to define and enable highly available partitions (see the section called “Defining and enabling partitions”). In this snippet, if a partition in the configuration data defines the active node as the local node, the partition is defined and enabled.
The snippet loads and activates the configuration file from
main
. However, in general, an application would install
a configuration notifier, and the configuration data would be
automatically loaded as part of node startup, or by the operator during
normal operation.
Example 9.11. Partition definition in configuration
// $Revision: 1.1.2.3 $ package com.kabira.snippets.configuring; import com.kabira.platform.highavailability.ReplicaNode; import com.kabira.platform.annotation.Managed; import com.kabira.platform.ManagedObject; import com.kabira.platform.Transaction; import com.kabira.platform.Transaction.Rollback; import com.kabira.test.management.Client; import com.kabira.test.management.CommandFailed; import java.net.URL; import com.kabira.platform.kcs.Configuration; import com.kabira.platform.switchconfig.Config; import com.kabira.platform.switchconfig.ConfigurationListener; import com.kabira.platform.switchconfig.Version; import com.kabira.platform.highavailability.PartitionManager; import com.kabira.platform.highavailability.Partition.Properties; import static com.kabira.platform.highavailability.PartitionManager.EnableAction.*; import static com.kabira.platform.highavailability.ReplicaNode.ReplicationType; import com.kabira.platform.property.Status; /** * Partition configuration object */ @Managed class Replica { String name; ReplicationType type; } /** * This snippet demonstrates the use of configuration for defining partitions. * * NOTE: This snippet requires the classpath to include the * directory where the configuration files are located. This * allows the get resource call to locate the configuration files * * <p> * <h2> Target Nodes</h2> * <ul> * <li> <b>domainname</b> = A * </ul> */ public class Partition extends Configuration { String name; String activeNode; String restoreFromNode = ""; Boolean forceReplication = false; Replica [] replicas; /** * Set configuration type * @return Configuration type */ @Override public String getType() { return CONFIGURATION_TYPE; } // // Configuration notifier // private static class Notifier extends ConfigurationListener { static final String localNode = System.getProperty(Status.NODE_NAME); Notifier() { super(CONFIGURATION_TYPE); } @Override public void activated(Version version) { Boolean needEnable = false; for (Config config : version.getConfigs()) { Partition partition = (Partition)config; // // Skip partitions that are not active on this node // if (partition.activeNode.equals(localNode) == false) { continue; } needEnable = true; // // Define the partition properties // Properties properties = new Properties(); properties.forceReplication(partition.forceReplication); properties.restoreFromNode(partition.restoreFromNode); // // Define the partition // ReplicaNode [] replicas = new ReplicaNode[partition.replicas.length]; for (int i = 0; i < partition.replicas.length; i++) { replicas[i] = new ReplicaNode( partition.replicas[i].name, partition.replicas[i].type); } PartitionManager.definePartition( partition.name, properties, partition.activeNode, replicas); } // // Enable the partitions // if (needEnable == true) { PartitionManager.enablePartitions(JOIN_CLUSTER); } } } public static void main(String[] args) throws CommandFailed, ClassNotFoundException { Client client = new Client("guest", "guest"); URL url1 = client.getClass().getClassLoader().getResource("partitions.kcs"); if (url1 == null) { throw new Error( "Configuration file partitions.kcs not located - " + "is it installed into the current class path?"); } Client.Configuration version = client.new Configuration(url1); // // Install the configuration notifier // new Transaction("Install configuration notifier") { @Override protected void run() throws Rollback { new Notifier(); } }.execute(); // // Install configuration notifiers // NotifierLifeCycle notifierLifeCycle = new NotifierLifeCycle(); notifierLifeCycle.initialize(); // // Load, activate configuration file // version.load(); version.activate(); version.deactivate(); version.remove(); // // Remove the configuration notifier // new Transaction("Remove configuration notifier") { @Override protected void run() throws Rollback { for (Object notifier : ManagedObject.extent(Notifier.class)) { ManagedObject.delete(notifier); } } }.execute(); } private static final String CONFIGURATION_TYPE = "partition"; }
Example 9.12, “Partition configuration” shows the configuration data captured for each partition. Partition configuration includes:
name
- partition name
nodeList
- list of nodes associated with the
partition. The first node in the list is the active node for the
partition.
Example 9.12. Partition configuration
// $Revision: 1.1.2.1 $ configuration "partitions" version "1.0" type "partition" { configure com.kabira.snippets.configuring { // // Define partition A with an active node A // Partition { name = "A"; activeNode = "A"; restoreFromNode = "B"; forceReplication = true; replicas = { { name = "B"; type = SYNCHRONOUS; }, { name = "C"; type = ASYNCHRONOUS; } }; }; // // Define partition B with an active node B // Partition { name = "B"; activeNode = "B"; replicas = { { name = "A"; type = SYNCHRONOUS; }, { name = "C"; type = ASYNCHRONOUS; } }; }; }; };
After this snippet has been run on node A
and
B
, displaying the defined partitions in
TIBCO ActiveSpaces® Transactions
shows the information in Figure 9.1, “Configured partitions”.