saving state
diff --git a/asterix-common/src/main/java/edu/uci/ics/asterix/common/config/AsterixClusterProperties.java b/asterix-common/src/main/java/edu/uci/ics/asterix/common/config/AsterixClusterProperties.java
new file mode 100644
index 0000000..8468473
--- /dev/null
+++ b/asterix-common/src/main/java/edu/uci/ics/asterix/common/config/AsterixClusterProperties.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2009-2013 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.common.config;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import edu.uci.ics.asterix.common.api.AsterixAppContextInfo;
+import edu.uci.ics.asterix.event.schema.cluster.Cluster;
+import edu.uci.ics.asterix.event.schema.cluster.Node;
+
+public class AsterixClusterProperties {
+
+ private static final Logger LOGGER = Logger.getLogger(AsterixClusterProperties.class.getName());
+
+ private static final String IO_DEVICES = "iodevices";
+
+ public static final AsterixClusterProperties INSTANCE = new AsterixClusterProperties();
+
+ private Map<String, Map<String, String>> ncConfiguration = new HashMap<String, Map<String, String>>();
+
+ private static final String CLUSTER_CONFIGURATION_XML = "cluster.xml";
+
+ private Cluster cluster;
+
+ private AsterixClusterProperties() {
+ InputStream is = this.getClass().getClassLoader().getResourceAsStream(CLUSTER_CONFIGURATION_XML);
+ try {
+ JAXBContext ctx = JAXBContext.newInstance(Cluster.class);
+ Unmarshaller unmarshaller = ctx.createUnmarshaller();
+ cluster = (Cluster) unmarshaller.unmarshal(is);
+ } catch (JAXBException e) {
+ LOGGER.warning("Failed to read cluster configuration file " + CLUSTER_CONFIGURATION_XML);
+ }
+ }
+
+ public enum State {
+ ACTIVE,
+ UNUSABLE
+ }
+
+ private State state = State.UNUSABLE;
+
+ public void removeNCConfiguration(String nodeId) {
+ state = State.UNUSABLE;
+ ncConfiguration.remove(nodeId);
+ }
+
+ public void addNCConfiguration(String nodeId, Map<String, String> configuration) {
+ ncConfiguration.put(nodeId, configuration);
+ if (ncConfiguration.keySet().size() == AsterixAppContextInfo.getInstance().getMetadataProperties()
+ .getNodeNames().size()) {
+ state = State.ACTIVE;
+ }
+ if (LOGGER.isLoggable(Level.INFO)) {
+ LOGGER.info(" Registering configuration parameters for node id" + nodeId);
+ }
+ }
+
+ /**
+ * Returns the number of IO devices configured for a Node Controller
+ *
+ * @param nodeId
+ * unique identifier of the Node Controller
+ * @return number of IO devices. -1 if the node id is not valid. A node id is not valid
+ * if it does not correspond to the set of registered Node Controllers.
+ */
+ public int getNumberOfIODevices(String nodeId) {
+ Map<String, String> ncConfig = ncConfiguration.get(nodeId);
+ if (ncConfig == null) {
+ if (LOGGER.isLoggable(Level.WARNING)) {
+ LOGGER.warning("Configuration parameters for nodeId" + nodeId
+ + " not found. The node has not joined yet or has left.");
+ }
+ return -1;
+ }
+ return ncConfig.get(IO_DEVICES).split(",").length;
+ }
+
+ /**
+ * @return
+ */
+ public synchronized Node getAvailableSubstitutionNode() {
+ Node substitutionNode = null;
+ List<Node> availableNodesForSubstitution = cluster.getSubstituteNodes().getNode();
+ if (!availableNodesForSubstitution.isEmpty()) {
+ substitutionNode = availableNodesForSubstitution.remove(0);
+ }
+ return substitutionNode;
+ }
+
+ public synchronized int getNumberOfAvailableSubstitutionNodes() {
+ return cluster.getSubstituteNodes().getNode() == null ? 0 : cluster.getSubstituteNodes().getNode().size();
+ }
+
+ public State getState() {
+ return state;
+ }
+
+ public Cluster getCluster() {
+ return cluster;
+ }
+
+}
diff --git a/asterix-common/src/main/resources/schema/cluster.xsd b/asterix-common/src/main/resources/schema/cluster.xsd
new file mode 100644
index 0000000..be7d863
--- /dev/null
+++ b/asterix-common/src/main/resources/schema/cluster.xsd
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:cl="cluster" targetNamespace="cluster" elementFormDefault="qualified">
+
+ <!-- definition of simple types -->
+ <xs:element name="name" type="xs:string" />
+ <xs:element name="log_dir" type="xs:string" />
+ <xs:element name="txn_log_dir" type="xs:string" />
+ <xs:element name="id" type="xs:string" />
+ <xs:element name="client_ip" type="xs:string" />
+ <xs:element name="cluster_ip" type="xs:string" />
+ <xs:element name="key" type="xs:string" />
+ <xs:element name="value" type="xs:string" />
+ <xs:element name="dir" type="xs:string" />
+ <xs:element name="NFS" type="xs:boolean" />
+ <xs:element name="store" type="xs:string" />
+ <xs:element name="iodevices" type="xs:string" />
+ <xs:element name="java_home" type="xs:string" />
+ <xs:element name="username" type="xs:string" />
+
+ <!-- definition of complex elements -->
+ <xs:element name="working_dir">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="cl:dir" />
+ <xs:element ref="cl:NFS" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="master_node">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="cl:id" />
+ <xs:element ref="cl:client_ip" />
+ <xs:element ref="cl:cluster_ip" />
+ <xs:element ref="cl:java_home" minOccurs="0" />
+ <xs:element ref="cl:log_dir" minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="property">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="cl:key" />
+ <xs:element ref="cl:value" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="env">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="cl:property" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="node">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="cl:id" />
+ <xs:element ref="cl:cluster_ip" />
+ <xs:element ref="cl:java_home" minOccurs="0" />
+ <xs:element ref="cl:log_dir" minOccurs="0" />
+ <xs:element ref="cl:txn_log_dir" minOccurs="0" />
+ <xs:element ref="cl:store" minOccurs="0" />
+ <xs:element ref="cl:iodevices" minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="substitute_nodes">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="cl:node" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="cluster">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="cl:name" />
+ <xs:element ref="cl:username" />
+ <xs:element ref="cl:env" minOccurs="0" />
+ <xs:element ref="cl:java_home" minOccurs="0" />
+ <xs:element ref="cl:log_dir" minOccurs="0" />
+ <xs:element ref="cl:txn_log_dir" minOccurs="0" />
+ <xs:element ref="cl:store" minOccurs="0" />
+ <xs:element ref="cl:iodevices" minOccurs="0" />
+ <xs:element ref="cl:working_dir" />
+ <xs:element ref="cl:master_node" />
+ <xs:element ref="cl:node" maxOccurs="unbounded" />
+ <xs:element ref="cl:substitute_nodes"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>