背景
在DistributedFileSystem类中,大量使用doCall()、next()方法,本文一探究竟。
解析
FileSystemLinkResolver源码主要包含两个抽象方法和一个实现方法。
@InterfaceAudience.Private
@InterfaceStability.Evolving
public abstract class FileSystemLinkResolver<T> {
abstract public T doCall(final Path p) throws IOException,
UnresolvedLinkException;
abstract public T next(final FileSystem fs, final Path p) throws IOException;
public T resolve(final FileSystem filesys, final Path path)
throws IOException {
...
}
其中,doCall、next都在其继承类中实现,resolve已经实现,如下:
public T resolve(final FileSystem filesys, final Path path)
throws IOException {
int count = 0;
T in = null;
Path p = path;
// Assumes path belongs to this FileSystem.
// Callers validate this by passing paths through FileSystem#checkPath
FileSystem fs = filesys;
for (boolean isLink = true; isLink;) {
try {
in = doCall(p);
isLink = false;
} catch (UnresolvedLinkException e) {
if (!filesys.resolveSymlinks) {
throw new IOException("Path " + path + " contains a symlink"
+ " and symlink resolution is disabled ("
+ CommonConfigurationKeys.FS_CLIENT_RESOLVE_REMOTE_SYMLINKS_KEY
+ ").", e);
}
if (!FileSystem.areSymlinksEnabled()) {
throw new IOException("Symlink resolution is disabled in" +
" this version of Hadoop.");
}
if (count++ > FsConstants.MAX_PATH_LINKS) {
throw new IOException("Possible cyclic loop while " +
"following symbolic link " + path);
}
// Resolve the first unresolved path component
p = FSLinkResolver.qualifySymlinkTarget(fs.getUri(), p,
filesys.resolveLink(p));
fs = FileSystem.getFSofPath(p, filesys.getConf());
// Have to call next if it's a new FS
if (!fs.equals(filesys)) {
return next(fs, p);
}
// Else, we keep resolving with this filesystem
}
}
// Successful call, path was fully resolved
return in;
}
可以看到,在doCall方法没有异常时,直接返回doCall的返回值。
当有异常时,会判断是否areSymlinksEnabled,没有没有开启,也会报错。如果开启了,则会走next()方法。
简单来说,只要doCall有异常时,才会走next()。
用例
如DistributedFileSystem中的open方法:
@Override
public FSDataInputStream open(Path f, final int bufferSize)
throws IOException {
statistics.incrementReadOps(1);
Path absF = fixRelativePart(f);
return new FileSystemLinkResolver<FSDataInputStream>() {
@Override
public FSDataInputStream doCall(final Path p)
throws IOException, UnresolvedLinkException {
final DFSInputStream dfsis =
dfs.open(getPathName(p), bufferSize, verifyChecksum);
return dfs.createWrappedInputStream(dfsis);
}
@Override
public FSDataInputStream next(final FileSystem fs, final Path p)
throws IOException {
return fs.open(p, bufferSize);
}
}.resolve(this, absF);
}
深入探讨Hadoop DistributedFileSystem中FileSystemLinkResolver类的工作原理,包括doCall和next方法的作用,以及它们如何处理符号链接异常,确保文件路径的正确解析。

被折叠的 条评论
为什么被折叠?



