Table of Contents
一.前言.
Namenode最重要的两个功能之一就是维护整个文件系统的目录树(即命名空间namesystem) 。 HDFS文件系统的命名空间(namespace) , 也就是以“/”为根的整个目录树, 是通过FSDirectory类来管理的。 FSNamesystem也提供了管理目
录树结构的方法, 但FSNamesystem中的方法多是调用FSDirectory类的实现,FSNamesystem在FSDirectory类方法的基础上添加了editlog日志记录的功能。 而FSDirectory的操作则全部是在内存中进行的, 并不进行editlog的日志记录。
FSDirectory的设计使用了门面(Facade) 模式, 门面模式是指提供一个统一的接口去访问多个子系统的多个不同的接口, 它为子系统中的一组接口提供一个统一的高层接口, 使得子系统更容易使用
二.构造方法
序号 | 参数 | 默认值 | 含义 |
1 | dfs.permissions.enabled | true | 权限,默认开启 |
2 | dfs.permissions.superusergroup | supergroup | 超级用户组 |
3 | dfs.namenode.acls.enabled | false | 设置为true以启用对HDFS ACL(访问控制列表)的支持。 默认情况下,禁用ACL。 禁用ACL时,NameNode拒绝与设置或获取ACL相关的所有RPC。 |
4 | dfs.ls.limit | 1000 | 限制ls打印的文件数量。 如果小于或等于零,将最多打印DFS_LIST_LIMIT_DEFAULT(= 1000)。 |
5 | dfs.content-summary.limit | 5000 | 一个锁定期内允许的最大内容摘要计数。 0或负数表示没有限制 |
6 | dfs.content-summary.sleep-microsec | 500 | 在内容摘要计算中重新获得锁定之间的使线程进入睡眠状态的时间长度(以微秒为单位) |
7 | dfs.namenode.fs-limits.max-component-length | 255 | 定义路径的每个组件中以UTF-8编码的最大字节数。 值为0将禁用检查。 |
8 | dfs.namenode.fs-limits.max-directory-items | 1024 * 1024 ≈100 万 | 定义目录可以包含的最大项数。无法将属性设置为小于1或大于6400000的值。 |
9 | dfs.namenode.fs-limits.max-xattrs-per-inode | 32 | |
10 | final int MAX_DIR_ITEMS | 64 * 100 * 1000= 640万 | 我们需要一个最大最大值,因为默认情况下, [ dfs.namenode.fs-limits.max-directory-items的最大值] |
11 | dfs.namenode.name.cache.threshold | 10 | 经常访问的文件的访问次数超过此阈值的次数被缓存在FSDirectory nameCache中。 |
FSDirectory(FSNamesystem ns, Configuration conf) throws IOException {
this.dirLock = new ReentrantReadWriteLock(true); // fair
this.inodeId = new INodeId();
rootDir = createRoot(ns);
inodeMap = INodeMap.newInstance(rootDir);
// 权限: 默认开启 ==> dfs.permissions.enabled : true
this.isPermissionEnabled = conf.getBoolean( DFSConfigKeys.DFS_PERMISSIONS_ENABLED_KEY, DFSConfigKeys.DFS_PERMISSIONS_ENABLED_DEFAULT);
// dfs.permissions.ContentSummary.subAccess : false
this.isPermissionContentSummarySubAccess = conf.getBoolean(
DFSConfigKeys.DFS_PERMISSIONS_CONTENT_SUMMARY_SUBACCESS_KEY,
DFSConfigKeys.DFS_PERMISSIONS_CONTENT_SUMMARY_SUBACCESS_DEFAULT);
this.fsOwnerShortUserName =
UserGroupInformation.getCurrentUser().getShortUserName();
/// dfs.permissions.superusergroup : supergroup
this.supergroup = conf.get(
DFSConfigKeys.DFS_PERMISSIONS_SUPERUSERGROUP_KEY,
DFSConfigKeys.DFS_PERMISSIONS_SUPERUSERGROUP_DEFAULT);
// dfs.namenode.acls.enabled : false
this.aclsEnabled = conf.getBoolean(
DFSConfigKeys.DFS_NAMENODE_ACLS_ENABLED_KEY,
DFSConfigKeys.DFS_NAMENODE_ACLS_ENABLED_DEFAULT);
LOG.info("ACLs enabled? " + aclsEnabled);
this.posixAclInheritanceEnabled = conf.getBoolean(
DFSConfigKeys.DFS_NAMENODE_POSIX_ACL_INHERITANCE_ENABLED_KEY,
DFSConfigKeys.DFS_NAMENODE_POSIX_ACL_INHERITANCE_ENABLED_DEFAULT);
LOG.info("POSIX ACL inheritance enabled? " + posixAclInheritanceEnabled);
this.xattrsEnabled = conf.getBoolean(
DFSConfigKeys.DFS_NAMENODE_XATTRS_ENABLED_KEY,
DFSConfigKeys.DFS_NAMENODE_XATTRS_ENABLED_DEFAULT);
LOG.info("XAttrs enabled? " + xattrsEnabled);
this.xattrMaxSize = conf.getInt(
DFSConfigKeys.DFS_NAMENODE_MAX_XATTR_SIZE_KEY,
DFSConfigKeys.DFS_NAMENODE_MAX_XATTR_SIZE_DEFAULT);
Preconditions.checkArgument(xattrMaxSize > 0,
"The maximum size of an xattr should be > 0: (%s).",
DFSConfigKeys.DFS_NAMENODE_MAX_XATTR_SIZE_KEY);
Preconditions.checkArgument(xattrMaxSize <=
DFSConfigKeys.DFS_NAMENODE_MAX_XATTR_SIZE_HARD_LIMIT,
"The maximum size of an xattr should be <= maximum size"
+ " hard limit " + DFSConfigKeys.DFS_NAMENODE_MAX_XATTR_SIZE_HARD_LIMIT
+ ": (%s).", DFSConfigKeys.DFS_NAMENODE_MAX_XATTR_SIZE_KEY);
this.accessTimePrecision = conf.getLong(
DFS_NAMENODE_ACCESSTIME_PRECISION_KEY,
DFS_NAMENODE_ACCESSTIME_PRECISION_DEFAULT);
//dfs.storage.policy.enabled : true
this.storagePolicyEnabled =
conf.getBoolean(DFS_STORAGE_POLICY_ENABLED_KEY,
DFS_STORAGE_POLICY_ENABLED_DEFAULT);
this.quotaByStorageTypeEnabled =
conf.getBoolean(DFS_QUOTA_BY_STORAGETYPE_ENABLED_KEY,
DFS_QUOTA_BY_STORAGETYPE_ENABLED_DEFAULT);
// dfs.ls.limit : 1000
int configuredLimit = conf.getInt(
DFSConfigKeys.DFS_LIST_LIMIT, DFSConfigKeys.DFS_LIST_LIMIT_DEFAULT);
this.lsLimit = configuredLimit>0 ?
configuredLimit : DFSConfigKeys.DFS_LIST_LIMIT_DEFAULT;
// dfs.content-summary.limit : 5000
this.contentCountLimit = conf.getInt(
DFSConfigKeys.DFS_CONTENT_SUMMARY_LIMIT_KEY,
DFSConfigKeys.DFS_CONTENT_SUMMARY_LIMIT_DEFAULT);
//dfs.content-summary.sleep-microsec 500
this.contentSleepMicroSec = conf.getLong(
DFSConfigKeys.DFS_CONTENT_SUMMARY_SLEEP_MICROSEC_KEY,
DFSConfigKeys.DFS_CONTENT_SUMMARY_SLEEP_MICROSEC_DEFAULT);
// filesystem limits
// 路径最大长度: dfs.namenode.fs-limits.max-component-length : 255
this.maxComponentLength = conf.getInt(
DFSConfigKeys.DFS_NAMENODE_MAX_COMPONENT_LENGTH_KEY,
DFSConfigKeys.DFS_NAMENODE_MAX_COMPONENT_LENGTH_DEFAULT);
// 目录最大数量 1024 * 1024 = 1048576 ≈ 100 万
// dfs.namenode.fs-limits.max-directory-items : 1024 * 1024
this.maxDirItems = conf.getInt(
DFSConfigKeys.DFS_NAMENODE_MAX_DIRECTORY_ITEMS_KEY,
DFSConfigKeys.DFS_NAMENODE_MAX_DIRECTORY_ITEMS_DEFAULT);
// dfs.namenode.fs-limits.max-xattrs-per-inod: 32
// inode的属性最大限制 32
this.inodeXAttrsLimit = conf.getInt(
DFSConfigKeys.DFS_NAMENODE_MAX_XATTRS_PER_INODE_KEY,
DFSConfigKeys.DFS_NAMENODE_MAX_XATTRS_PER_INODE_DEFAULT);
this.protectedDirectories = parseProtectedDirectories(conf);
Preconditions.checkArgument(this.inodeXAttrsLimit >= 0,
"Cannot set a negative limit on the number of xattrs per inode (%s).",
DFSConfigKeys.DFS_NAMENODE_MAX_XATTRS_PER_INODE_KEY);
// 我们需要一个最大最大值,因为默认情况下,
// PB将message大小限制为64MB。
// 这意味着每个目录只能存储大约670万个条目,
// 但是为了安全起见,请使用640万个条目。
// We need a maximum maximum because by default, PB limits message sizes
// to 64MB. This means we can only store approximately 6.7 million entries
// per directory, but let's use 6.4 million for some safety.
final int MAX_DIR_ITEMS = 64 * 100 * 1000;
Preconditions.checkArgument(
maxDirItems > 0 && maxDirItems <= MAX_DIR_ITEMS, "Cannot set "
+ DFSConfigKeys.DFS_NAMENODE_MAX_DIRECTORY_ITEMS_KEY
+ " to a value less than 1 or greater than " + MAX_DIR_ITEMS);
// dfs.namenode.name.cache.threshold: 10
// 经常访问的文件的访问次数超过此阈值的次数被缓存在FSDirectory nameCache中。
int threshold = conf.getInt(
DFSConfigKeys.DFS_NAMENODE_NAME_CACHE_THRESHOLD_KEY,
DFSConfigKeys.DFS_NAMENODE_NAME_CACHE_THRESHOLD_DEFAULT);
NameNode.LOG.info("Caching file names occurring more than " + threshold
+ " times");
nameCache = new NameCache<ByteArray>(threshold);
namesystem = ns;
this.editLog = ns.getEditLog();
ezManager = new EncryptionZoneManager(this, conf);
this.quotaInitThreads = conf.getInt(
DFSConfigKeys.DFS_NAMENODE_QUOTA_INIT_THREADS_KEY,
DFSConfigKeys.DFS_NAMENODE_QUOTA_INIT_THREADS_DEFAULT);
initUsersToBypassExtProvider(conf);
}
三.常量
■ INodeDirectory rootDir: 整个文件系统目录树的根节点, 是INodeDirectory类型的 。
■ FSNamesystem namesystem: Namenode的门面类, 这个类主要支持对数据块进行操作的一些方法, 例如addBlock()。
■ INodeMap inodeMap: 记录根目录下所有的INode,并维护INodeId ->INode的映射关系。
■ ReentrantReadWriteLock dirLock: 对目录树以及inodeMap字段操作的锁。
■ NameCache<ByteArray> nameCache: 将常用的name缓存下来, 以降低byte[]的使用, 并降低JVM heap的使用
四.方法
FSDirectory类中的方法相当多, 主要是封装了对文件系统目录树的操作, 例如增、删、 改、 查等。 基本上ClientProtocol中的方法, 都能在FSDirectory中找到对应的方法。
这个太多了就不罗列了,其实就是对目录层级权限的操作..