/** * VMware Continuent Tungsten Replicator * Copyright (C) 2015 VMware, Inc. All rights reserved. * * 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 at * * 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. * * Initial developer(s): Seppo Jaakola * Contributor(s): Robert Hodges */ package com.continuent.tungsten.common.cluster.resource; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Set; import com.continuent.tungsten.common.config.TungstenProperties; /** * Defines capabilities of an open replicator. Managers can use this to * determine operations supported by a particular replicator type. * * @author <a href="mailto:seppo.jaakola@continuent.com">Seppo Jaakola</a> * @version 1.0 */ public class ReplicatorCapabilities extends Capabilities implements Serializable { private static final long serialVersionUID = -3752349488516771325L; /* * Null or missing value. */ public static final String UNKNOWN = "unknown"; /* * Possible roles for replicator, these can be used in * OpenReplicatorPlugin::setRole() method */ public static final String ROLES = "roles"; public static final String ROLE_MASTER = "master"; public static final String ROLE_SLAVE = "slave"; public static final String ROLE_RELAY = "relay"; /* * Replication model: push = master pushes replication events to slaves pull * = slave polls replication events from master peer = true multi-master, * all nodes are identical */ public static final String MODEL = "model"; public static final String MODEL_PUSH = "push"; public static final String MODEL_PULL = "pull"; public static final String MODEL_PEER = "peer"; /* * Driver for provisioning donor = donor (master) sends DB state to joining * node (slave) joiner = joining node (slave) polls donor (master) for DB * state */ private static final String PROVISION = "provision"; public static final String PROVISION_DONOR = "donor"; public static final String PROVISION_JOINER = "joiner"; // Replicator capabilities. private static final String CAP_CONSISTENCY = "consistency"; private static final String CAP_HEARTBEAT = "heartbeat"; private static final String CAP_FLUSH = "flush"; private ArrayList<String> roles = new ArrayList<String>(); private String model = UNKNOWN; /* driver for provisioning: master or slave */ private String provisionDriver = UNKNOWN; /* is consistency check supported */ private boolean isConsistencyCheck; /* is heartbeat supported */ private boolean isHeartbeat; /* is flush supported */ private boolean isFlush; /** * Create an instance with default properties. */ public ReplicatorCapabilities() { } /** * Create a capabilities instance from TungstenProperties instance. */ public ReplicatorCapabilities(TungstenProperties props) throws Exception { Set<String> keys = props.keyNames(); for (String key : keys) { if (key.equals(ROLES)) { List<String> tags = props.getStringList(key); for (String tag : tags) { if (tag.equalsIgnoreCase(ROLE_MASTER)) { addRole(ReplicatorCapabilities.ROLE_MASTER); } else if (tag.equalsIgnoreCase(ROLE_SLAVE)) { addRole(ReplicatorCapabilities.ROLE_SLAVE); } else if (tag.equalsIgnoreCase(ROLE_RELAY)) { addRole(ReplicatorCapabilities.ROLE_RELAY); } else { throw new Exception("Unknown capability role: " + tag); } } } else if (key.equals(MODEL)) { String tag = props.getString(key); if (tag.equalsIgnoreCase(MODEL_PUSH)) { setModel(MODEL_PUSH); } else if (tag.equalsIgnoreCase(MODEL_PULL)) { setModel(MODEL_PULL); } else if (tag.equalsIgnoreCase(MODEL_PEER)) { setModel(MODEL_PEER); } else if (tag.equalsIgnoreCase(UNKNOWN)) { setModel(UNKNOWN); } else { throw new Exception("Unknown value for model: " + tag); } } else if (key.equals(CAP_CONSISTENCY)) { setConsistencyCheck(props.getBoolean(CAP_CONSISTENCY)); } else if (key.equals(CAP_HEARTBEAT)) { setHeartbeat(props.getBoolean(CAP_HEARTBEAT)); } else if (key.equals(CAP_FLUSH)) { setFlush(props.getBoolean(CAP_FLUSH)); } else if (key.equals(PROVISION)) { String tag = props.getString(key); if (tag.equalsIgnoreCase(PROVISION_DONOR)) { setProvisionDriver(PROVISION_DONOR); } else if (tag.equalsIgnoreCase(PROVISION_JOINER)) { setProvisionDriver(PROVISION_JOINER); } else if (tag.equalsIgnoreCase(UNKNOWN)) { setProvisionDriver(UNKNOWN); } else { throw new Exception("Unknown provision driver: " + tag); } } else { throw new Exception("Unknown capability: " + key); } } } public String getModel() { return model; } public void setModel(String model) { this.model = model; } public List<String> getRoles() { return roles; } public void setRoles(ArrayList<String> roles) { this.roles = roles; } public void addRole(String role) { roles.add(role); } public boolean isConsistencyCheck() { return isConsistencyCheck; } public void setConsistencyCheck(boolean isConcistencyCheck) { this.isConsistencyCheck = isConcistencyCheck; } public boolean isFlush() { return isFlush; } public void setFlush(boolean isFlush) { this.isFlush = isFlush; } public boolean isHeartbeat() { return isHeartbeat; } public void setHeartbeat(boolean isHeartbeat) { this.isHeartbeat = isHeartbeat; } public String getProvisionDriver() { return provisionDriver; } public void setProvisionDriver(String provisionDriver) { this.provisionDriver = provisionDriver; } /** * Writes capabilities to a properties instance for storage or transport. */ public TungstenProperties asProperties() { TungstenProperties caps = new TungstenProperties(); caps.setStringList(ROLES, getRoles()); caps.setString(MODEL, getModel()); caps.setBoolean(CAP_CONSISTENCY, this.isConsistencyCheck()); caps.setBoolean(CAP_HEARTBEAT, this.isHeartbeat()); caps.setBoolean(CAP_FLUSH, this.isFlush()); caps.setString(PROVISION, getProvisionDriver()); return caps; } }