package com.bytedance.hadoop.hdfs.server.proxy; import com.bytedance.hadoop.hdfs.server.NNProxy; import com.bytedance.hadoop.hdfs.server.exception.WrappedExecutionException; import com.bytedance.hadoop.hdfs.server.upstream.UpstreamManager; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hdfs.protocol.ClientProtocol; import org.apache.hadoop.ipc.Server; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.concurrent.ExecutionException; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * This routes path or blockPoolId to backend NameNode corresponding to mount table. */ @InterfaceAudience.Private @InterfaceStability.Stable public class Router { private static final Logger LOG = LoggerFactory.getLogger(Router.class); public static final Pattern TRASH_PATTERN = Pattern.compile("/user/[^/]+/.Trash/[^/]+/(.+)"); final NNProxy nnProxy; final Configuration conf; final UpstreamManager upstreamManager; public Router(NNProxy nnProxy, Configuration conf, UpstreamManager upstreamManager) { this.nnProxy = nnProxy; this.conf = conf; this.upstreamManager = upstreamManager; } ClientProtocol getUpstreamProtocol(String user, String fs) throws ExecutionException { return upstreamManager.getUpstream(user, fs).protocol; } RouteInfo route(String path) throws IOException { String logicalPath = path; Matcher mch = TRASH_PATTERN.matcher(path); if (mch.find()) { logicalPath = "/" + mch.group(1); LOG.debug("Hit trash pattern: " + path + " -> " + logicalPath); } String fs = nnProxy.getMounts().resolve(logicalPath); if (fs == null) { throw new IOException("Not resolved: " + path); } if (LOG.isDebugEnabled()) { LOG.debug("Resolved: " + path + " -> " + fs + path); } return new RouteInfo(getProtocol(fs), path, fs); } ClientProtocol getProtocol(String fs) throws IOException { try { return getUpstreamProtocol(Server.getRemoteUser().getUserName(), fs); } catch (ExecutionException e) { throw new WrappedExecutionException(e.getCause()); } } RouteInfo getRoot() throws IOException { return route("/"); } ClientProtocol getUpstreamForBlockPool(String bpId) throws IOException { String fs = nnProxy.getBlockPoolRegistry().getFs(bpId); if (fs == null) { throw new IOException("Unknown block pool: " + bpId); } return getProtocol(fs); } }