blob: c60c2c80aa9e75d2f5f0a57ec771c1e7dffc968f [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
*
* 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 org.apache.hadoop.hdds.scm.net;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import org.apache.hadoop.hdds.scm.ScmConfigKeys;
import org.apache.hadoop.hdds.scm.net.NodeSchemaLoader.NodeSchemaLoadResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.hadoop.conf.Configuration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/** The class manages all network topology schemas. */
public final class NodeSchemaManager {
private static final Logger LOG = LoggerFactory.getLogger(
NodeSchemaManager.class);
// All schema saved and sorted from ROOT to LEAF node
private List<NodeSchema> allSchema;
// enforcePrefix only applies to INNER_NODE
private boolean enforcePrefix;
// max level, includes ROOT level
private int maxLevel = -1;
private volatile static NodeSchemaManager instance = null;
private NodeSchemaManager() {
}
public static NodeSchemaManager getInstance() {
if (instance == null) {
instance = new NodeSchemaManager();
}
return instance;
}
public void init(Configuration conf) {
/**
* Load schemas from network topology schema configuration file
*/
String schemaFile = conf.get(
ScmConfigKeys.OZONE_SCM_NETWORK_TOPOLOGY_SCHEMA_FILE,
ScmConfigKeys.OZONE_SCM_NETWORK_TOPOLOGY_SCHEMA_FILE_DEFAULT);
NodeSchemaLoadResult result;
try {
result = NodeSchemaLoader.getInstance().loadSchemaFromFile(schemaFile);
allSchema = result.getSchemaList();
enforcePrefix = result.isEnforePrefix();
maxLevel = allSchema.size();
} catch (Throwable e) {
String msg = "Failed to load schema file:" + schemaFile
+ ", error: " + e.getMessage();
LOG.error(msg, e);
throw new RuntimeException(msg, e);
}
}
@VisibleForTesting
public void init(NodeSchema[] schemas, boolean enforce) {
allSchema = new ArrayList<>();
allSchema.addAll(Arrays.asList(schemas));
enforcePrefix = enforce;
maxLevel = schemas.length;
}
public int getMaxLevel() {
return maxLevel;
}
public int getCost(int level) {
Preconditions.checkArgument(level <= maxLevel &&
level >= (NetConstants.ROOT_LEVEL));
return allSchema.get(level - NetConstants.ROOT_LEVEL).getCost();
}
/**
* Given a incomplete network path, return its complete network path if
* possible. E.g. input is 'node1', output is '/rack-default/node1' if this
* schema manages ROOT, RACK and LEAF, with prefix defined and enforce prefix
* enabled.
*
* @param path the incomplete input path
* @return complete path, null if cannot carry out complete action or action
* failed
*/
public String complete(String path) {
if (!enforcePrefix) {
return null;
}
String normalizedPath = NetUtils.normalize(path);
String[] subPath = normalizedPath.split(NetConstants.PATH_SEPARATOR_STR);
if ((subPath.length) == maxLevel) {
return path;
}
StringBuffer newPath = new StringBuffer(NetConstants.ROOT);
// skip the ROOT and LEAF layer
int i, j;
for (i = 1, j = 1; i < subPath.length && j < (allSchema.size() - 1);) {
if (allSchema.get(j).matchPrefix(subPath[i])) {
newPath.append(NetConstants.PATH_SEPARATOR_STR + subPath[i]);
i++;
j++;
} else {
newPath.append(allSchema.get(j).getDefaultName());
j++;
}
}
if (i == (subPath.length - 1)) {
newPath.append(NetConstants.PATH_SEPARATOR_STR + subPath[i]);
return newPath.toString();
}
return null;
}
}