blob: 3c0cc476ef32254315d73c4e0de02099160f2401 [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* one or more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
package com.gemstone.gemfire.distributed.internal;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;
import java.util.StringTokenizer;
import com.gemstone.gemfire.DataSerializer;
import com.gemstone.gemfire.internal.GemFireVersion;
/**
* Provides optional data fields as properties for StartupMessage and
* StartupResponseMessage. This is handled by serializing and deserializing
* a new Properties instance if and only if the member version is 6.6.3 or
* greater. New fields can be added to the Properties without breaking
* backwards compatibility. All new fields added should be written to allow
* for version compatibility.
*
* @author Kirk Lund
* @since 7.0
*/
class StartupMessageData {
static final String HOSTED_LOCATORS = "HL";
static final String COMMA_DELIMITER = ",";
static final String MCAST_PORT = "MP";
static final String MCAST_HOST_ADDRESS = "MHA";
static final String IS_SHARED_CONFIG_ENABLED = "ISCE";
private Properties optionalFields;
/**
* Constructs a new instance with empty Properties. After construction
* the instance should optionally invoke one or more "write" methods such
* as {@link #writeHostedLocators(Collection)} before invoking {@link
* #toData(DataOutput)} to marshal the Properties into the DataOutput
* (onto the wire).
*/
StartupMessageData() {
this.optionalFields = new Properties();
}
public void readFrom(DataInput in) throws ClassNotFoundException, IOException {
this.optionalFields = DataSerializer.readObject(in);
}
/**
* Check for the optional field {@link #HOSTED_LOCATORS} and return the
* value or null.
*/
Collection<String> readHostedLocators() {
if (this.optionalFields == null || this.optionalFields.isEmpty()) {
return null;
}
Collection<String> hostedLocators = null;
String hostedLocatorsString = this.optionalFields.getProperty(HOSTED_LOCATORS);
if (hostedLocatorsString != null && !hostedLocatorsString.isEmpty()) {
StringTokenizer st = new StringTokenizer(hostedLocatorsString, COMMA_DELIMITER);
hostedLocators = new ArrayList<String>();
while (st.hasMoreTokens()) {
String locatorString = st.nextToken();
if (locatorString != null && !locatorString.isEmpty()) {
hostedLocators.add(locatorString);
}
}
if (hostedLocators.isEmpty()) {
hostedLocators = null;
}
}
return hostedLocators;
}
// /**
// * Check for the optional field {@link #HOSTED_LOCATORS_WITH_SHARED_CONFIGURATION} and return the
// * value or null.
// */
// Collection<String> readHostedLocatorsWithSharedConfiguration() {
// if (this.optionalFields == null || this.optionalFields.isEmpty()) {
// return null;
// }
// Collection<String> hostedLocatorsWithSharedConfiguration = null;
// String hostedLocatorsString = this.optionalFields.getProperty(HOSTED_LOCATORS_WITH_SHARED_CONFIGURATION);
// if (hostedLocatorsString != null && !hostedLocatorsString.isEmpty()) {
// StringTokenizer st = new StringTokenizer(hostedLocatorsString, COMMA_DELIMITER);
// hostedLocatorsWithSharedConfiguration = new ArrayList<String>();
// while (st.hasMoreTokens()) {
// String locatorString = st.nextToken();
// if (locatorString != null && !locatorString.isEmpty()) {
// hostedLocatorsWithSharedConfiguration.add(locatorString);
// }
// }
// if (hostedLocatorsWithSharedConfiguration.isEmpty()) {
// hostedLocatorsWithSharedConfiguration = null;
// }
// }
// return hostedLocatorsWithSharedConfiguration;
// }
boolean readIsSharedConfigurationEnabled() {
if (this.optionalFields == null || this.optionalFields.isEmpty()) {
return false;
}
return Boolean.parseBoolean((this.optionalFields.getProperty(IS_SHARED_CONFIG_ENABLED)));
}
/**
* Write the value for the optional field {@link #HOSTED_LOCATORS}.
*/
void writeHostedLocators(Collection<String> hostedLocators) {
if (this.optionalFields == null) {
return;
}
if (hostedLocators != null && !hostedLocators.isEmpty()) {
String hostedLocatorsString = asCommaDelimitedString(hostedLocators);
if (hostedLocatorsString != null && !hostedLocatorsString.isEmpty()) {
this.optionalFields.setProperty(HOSTED_LOCATORS, hostedLocatorsString);
}
}
}
// void writeHostedLocatorsWithSharedConfiguration(Collection<String> hostedLocatorsWithSharedConfiguration) {
// if (this.optionalFields == null) {
// return;
// }
// if (hostedLocatorsWithSharedConfiguration != null && !hostedLocatorsWithSharedConfiguration.isEmpty()) {
// String hostedLocatorsString = asCommaDelimitedString(hostedLocatorsWithSharedConfiguration);
// if (hostedLocatorsString != null && !hostedLocatorsString.isEmpty()) {
// this.optionalFields.setProperty(HOSTED_LOCATORS_WITH_SHARED_CONFIGURATION, hostedLocatorsString);
// }
// }
// }
//
void writeIsSharedConfigurationEnabled(boolean isSharedConfigurationEnabled) {
if (this.optionalFields == null) {
return;
}
this.optionalFields.setProperty(IS_SHARED_CONFIG_ENABLED, Boolean.toString(isSharedConfigurationEnabled));
}
int readMcastPort() {
int result = 0;
if (this.optionalFields != null) {
String resultString = this.optionalFields.getProperty(MCAST_PORT);
if (resultString != null && !resultString.isEmpty()) {
result = Integer.parseInt(resultString);
}
}
return result;
}
void writeMcastPort(int mcastPort) {
if (this.optionalFields != null) {
if (mcastPort != 0) {
this.optionalFields.setProperty(MCAST_PORT, Integer.toString(mcastPort));
}
}
}
String readMcastHostAddress() {
String result = null;
if (this.optionalFields != null) {
result = this.optionalFields.getProperty(MCAST_HOST_ADDRESS);
}
return result;
}
void writeMcastHostAddress(String addr) {
if (this.optionalFields != null) {
if (addr != null && !addr.isEmpty()) {
this.optionalFields.setProperty(MCAST_HOST_ADDRESS, addr);
}
}
}
/**
* Writes all optional fields to the DataOutput or null for minimal
* wire footprint.
*
* @throws IOException
*/
void writeTo(DataOutput out) throws IOException {
if (this.optionalFields.isEmpty()) {
DataSerializer.writeObject(null, out);
} else {
DataSerializer.writeObject(this.optionalFields, out);
}
}
/**
* Returns {@link #optionalFields} for testing.
*/
Properties getOptionalFields() {
return this.optionalFields;
}
/**
* Marshals a collection of strings to a single comma-delimited string.
* Returns null if collection is null or empty.
*/
public static String asCommaDelimitedString(Collection<String> strings) {
StringBuilder sb = new StringBuilder();
for (String string : strings) {
if (sb.length() > 0) {
sb.append(COMMA_DELIMITER);
}
sb.append(string);
}
return sb.toString();
}
}