blob: 610419527a4b23313334515351a46c8c3e1c7bf0 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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 org.apache.hadoop.hdds.client;
import org.apache.hadoop.hdds.conf.ConfigurationSource;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import java.util.Objects;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_REPLICATION;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_REPLICATION_DEFAULT;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_REPLICATION_TYPE;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_REPLICATION_TYPE_DEFAULT;
/**
* Replication configuration for any ReplicationType with all the required
* parameters..
*/
public interface ReplicationConfig {
/**
* Helper method to create proper replication method from old-style
* factor+type definition.
* <p>
* Note: it's never used for EC replication where config is created.
*/
static ReplicationConfig fromProtoTypeAndFactor(
HddsProtos.ReplicationType type,
HddsProtos.ReplicationFactor factor
) {
switch (type) {
case RATIS:
return RatisReplicationConfig.getInstance(factor);
case STAND_ALONE:
return StandaloneReplicationConfig.getInstance(factor);
default:
throw new UnsupportedOperationException(
"Not supported replication: " + type);
}
}
/**
* Helper method to create proper replication method from old-style
* factor+type definition.
* <p>
* Note: it's never used for EC replication where config is created.
*/
static ReplicationConfig fromTypeAndFactor(
org.apache.hadoop.hdds.client.ReplicationType type,
org.apache.hadoop.hdds.client.ReplicationFactor factor
) {
return fromProtoTypeAndFactor(
HddsProtos.ReplicationType.valueOf(type.name()),
HddsProtos.ReplicationFactor.valueOf(factor.name()));
}
static ReplicationConfig getDefault(ConfigurationSource config) {
String replication =
config.get(OZONE_REPLICATION, OZONE_REPLICATION_DEFAULT);
return parse(null, replication, config);
}
/**
* Helper method to serialize from proto.
* <p>
* This uses either the old type/factor or the new ecConfig depends on the
* type.
*/
static ReplicationConfig fromProto(
HddsProtos.ReplicationType type,
HddsProtos.ReplicationFactor factor,
HddsProtos.ECReplicationConfig ecConfig) {
switch (type) {
case EC:
return new ECReplicationConfig(ecConfig);
case RATIS:
case STAND_ALONE:
return fromProtoTypeAndFactor(type, factor);
default:
throw new UnsupportedOperationException(
"Not supported replication: " + type);
}
}
static HddsProtos.ReplicationFactor getLegacyFactor(
ReplicationConfig replicationConfig) {
if (replicationConfig instanceof ReplicatedReplicationConfig) {
return ((ReplicatedReplicationConfig) replicationConfig)
.getReplicationFactor();
}
throw new UnsupportedOperationException(
"Replication configuration of type "
+ replicationConfig.getReplicationType()
+ " does not have a replication factor property.");
}
/**
* Create new replication config with adjusted replication factor.
* <p>
* Used by hadoop file system. Some replication schemes (like EC) may not
* support changing the replication.
* <p>
* Based on the provided configuration the adjusted ReplicationConfig is
* validated against the ozone.replication.allowed-configs property, and if
* the new config is not allowed the method throws an
* IllegalArgumentException.
*/
static ReplicationConfig adjustReplication(
ReplicationConfig config, short replication, ConfigurationSource conf) {
ReplicationType replicationType =
ReplicationType.valueOf(config.getReplicationType().toString());
if (replicationType.equals(ReplicationType.EC)) {
return config;
}
return parse(replicationType, Short.toString(replication), conf);
}
/**
* Parses the string representation of the replication configuration that is
* defined by the ReplicationType parameter.
* The configuration object is necessary to check if the parsed
* ReplicationConfig object is allowed based on the
* ozone.replication.allowed-configs property.
* @param type the ReplicationType to parse from the replication string
* @param replication the replication String that for example contains the
* replication factor for RATIS replication.
* @param config the current Ozone configuration to apply validation on the
* parsed object.
* @return a validated ReplicationConfig object that is allowed based on the
* system's configuration.
* @throws IllegalArgumentException if the parsed ReplicationConfig is not
* allowed by the ozone.replication.allowed-configs property, or
* if the give replication type or replication can not be parsed.
* @throws NullPointerException if the ReplicationConfig was not created
* for the type.
*/
static ReplicationConfig parse(ReplicationType type, String replication,
ConfigurationSource config) {
if (type == null) {
type = ReplicationType.valueOf(
config.get(OZONE_REPLICATION_TYPE, OZONE_REPLICATION_TYPE_DEFAULT));
}
replication = Objects.toString(replication,
config.get(OZONE_REPLICATION, OZONE_REPLICATION_DEFAULT));
return parseWithoutFallback(type, replication, config);
}
static ReplicationConfig parseWithoutFallback(ReplicationType type,
String replication, ConfigurationSource config) {
if (replication == null) {
throw new IllegalArgumentException(
"Replication can't be null. Replication type passed was : " + type);
}
if (type == null) {
throw new IllegalArgumentException(
"Replication type must be specified for: " + replication);
}
ReplicationConfig replicationConfig;
switch (type) {
case RATIS:
case STAND_ALONE:
ReplicationFactor factor;
try {
factor = ReplicationFactor.valueOf(Integer.parseInt(replication));
} catch (NumberFormatException ex) {
try {
factor = ReplicationFactor.valueOf(replication);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(replication +
" is not supported for " + type + " replication type", e);
}
}
replicationConfig = fromTypeAndFactor(type, factor);
break;
case EC:
replicationConfig = new ECReplicationConfig(replication);
break;
default:
throw new IllegalArgumentException("Replication type " + type +
" can not be parsed.");
}
ReplicationConfigValidator validator =
config.getObject(ReplicationConfigValidator.class);
validator.validate(replicationConfig);
return replicationConfig;
}
/**
* Replication type supported by the replication config.
*/
HddsProtos.ReplicationType getReplicationType();
/**
* Number of required nodes for this replication.
*/
int getRequiredNodes();
/**
* Returns the replication option in string format.
*/
String getReplication();
String configFormat();
}