class MDCache {node
//my mastersapi
MDSRank *mds; MDCache所处的MDSRank数组
//my cacheapp
LRU lru; 最近最少使用列表(保存dentries)函数
unordered_map<vinodeno_t, CInode*> inode_map; inode映射关系(保存inodes)fetch
CInode *root; 根CInodeui
CInode *myin;this
CInode *strays[10];日志
int stray_index;对象
set<CInode*> base_inodes;
Filer filer; 与OSD操做的接口类
DecayRate decayrate;
file_layout_t default_file_layout; 存储文件默认的layout
file_layout_t default_log_layout; 存储日志默认的layout
//client leases
float client_lease_durations[3];
xlist<ClientLease*> client_leases[3];
//discover
map<ceph_tid_t, discover_info_t> discovers;
ceph_tid_t discover_last_tid;
//subtrees
map<CDir*, set<CDir*>> subtrees; 子树
map<CInode*, list<piar<CDir*, CDir*>>> projected_subtree_renames;
//delayed cache expire
map<CDir*, map<mds_rank_t, MCacheExpire*>> delayed_expire;
//request
unordered_map<metareqid_t, MDRequestRef> active_requests;
//recovery
set<mds_rank_t> recovery_set;
//file size recovery
RecoveryQueue recovery_queue;
//subsystems
Migrator *migragor;
};
全部非I/O上下文的使用class MDCacheContext类
全部I/O上下文的使用cass MDCacheIOContext类
=================some inode functions======================
MDS |
MDSDIR |
INO LOG |
INO LOG BACKUP |
INO_LOG POINTER |
INO STRAY |
INO SYSTEM BASE |
0 0x100 0x200 0x300 0x400 0x600 0x600+(MDS*STRAY)
MDCache::add_inode(CInode* in)
|__更新inode_map数组,即:inode_map[in->vino()] = in
|__若in的inode编号小于INO_SYSTEM_BASE
|__若in的inode编号==1
|__设置root=in
|__若in的inode编号位于MDSDIR范围内
|__设置myin=in
|__若in的当前状态是stray的
|__若in的inode编号位于INO_STRAY范围内
|__更新strays数组,即:strays[MDS_INO_STRAY_INDEX(in->ino()]=in
|__若in的inode编号是1或者位于MDSDIR范围内
|__更新base_inodes数组,即:base_inodes.insert(in)
MDCache::remove_inode(CInode *o)
|__若o的parent dentry不为空
|__从o的parent dentry对应的dir里删除o,即:dn=o->get_parent_dn(); dn->dir->unlink_inode(dn)
|__若o是dirty的
|__o->mark_clean()
|__若o是parent dirty
|__o->clear_dirty_parent()
|__从inode_map数组中删除o,即:inode_map.erase(o->ino())
|__若o的inode编号小于INO_SYSTEM_BASE
|__若o的inode编号==1
|__设置root=0
|__若o的inode编号位于MDSDIR范围内
|__设置myin=0
|__若o的当前状态是stray的
|__若o的inode编号位于INO_STRAY范围内
|__更新strays数组,即:strays[MDS_INO_STRAY_INDEX(o->ino()]=0
|__若o的inode编号是1或者位于MDSDIR范围内
|__更新base_inode数组,即:base_inode.erase(o)
|__删除o
MDSCache::gen_default_file_layout(MDSMap mdsmap)
|__调用file_layout_t的get_default()函数获得一个默认的file_layout_t类对象(默认的file_layout_t对象的stripe_unit=4MB, stripe_count=1, object_size=4MB, pool_id=-1)
|__设置默认的file_layout_t对象的pool_id=mdsmap中的第一个data pool
MDSCache::get_default_log_layout(MDSMap mdsmap)
|__调用file_layout_t的get_default()函数获得一个默认的file_layout_t类对象(默认的file_layout_t对象的stripe_unit=4MB, stripe_count=1, object_size=4MB, pool_id=-1)
|__设置默认的file_layout_t对象的pool_id=mdsmap中的metadata pool
MDCache::init_layouts()
|__调用gen_default_file_layout()函数获得default_file_layout
|__调用get_default_log_layout()函数获得default_log_layout
MDCache::create_unlinked_system_inode(CInode *in, inodeno_t ino, int mode)
|__初始化in的inode成员(inode_t)
|__初始化in的inode成员中的dir_layout
|__若in是目录
|__设置in的inode成员中的dir_layout的dl_dir_hash为mds_default_dir_hash值
|__若in不是目录
|__设置in的inode成员中的layout为default_file_layout
|__若in的inode编号是1或者位于MDSDIR范围内
|__若in是root
|__设置in的inode_auth为mds_authority_t(mds->get_nodeid(), UNKNOWN)
|__若in不是root
|__设置in的inode_auth为mds_authority_t(mds_rank_t(in->ino() - MDS_INO_MDSDIR_OFFSET), CDIR_AUTH_UNKNOWN)
|__调用in的open_snaprealm()来初始化snap
|__设置snaprealm的序列号为1,即:in->snaprealm->srnode.seq=1
MDCache::create_system_inode(inodeno_t ino, int mode)
|__建立CInode类对象
|__调用create_unlinked_system_inode()初始化CInode类对象
|__调用add_inode()将建立并初始化后的CInode添加到inode_map中
MDCache::create_root_inode()
|__调用create_system_inode()建立并初始化root CInode并将root添加到inode_map中
|__设置root CInode的uid/gid=0/0
|__设置root CInode的layout为default_file_layout
|__设置root CInode的layout的pool_id为mdsmap中第一个data pool
MDCache::create_empty_hierarchy(MDSGather *gather)
|__调用create_root_inode()建立root CInode
|__调用root的get_or_open_dirfrag()函数获得root的CDir类对象
|__调用adjust_subtree_auth()函数更新rootdir的auth
|__调整rootdir的一系列统计字段(rootdir->fnode.accounted_fragstat/rootdir->fnode.accounted_rstat/root->inode.dirstat/root->inode.rstat/root->inode.acounted_rstat)
|__调用rootdir->mark_dirty() 标识rootdir被修改过
|__调用rootdir->commit() 将rootdir写入到集群metadata pool
|__调用root->store() 将root写入到集群metadata pool
MDCache::create_mydir_hierarchy(MDSGather *gather)
|__获得mydir的名称,即:mds%d
|__调用create_system_inode()建立并初始化mydir CInode并将mydir添加到inode_map中
|__调用mydir的get_or_open_dirfrag()函数获得mydir的CDir类对象
|__调用adjust_subtree_auth()函数更新mydir的auth
|__建立10个stray dir
|__调用create_system_inode()建立并初始化stray CInode并将stray添加到inode_map中
|__调用stray的get_or_open_dirfrag()函数获得stray的CDir类对象straydir
|__获得stray的名称,即:stray%d
|__调用mydir->add_primary_dentry()将stray对应的CDentry添加到mydir的items数组中
|__提交保存straydir数据到集群metadata pool,即:straydir->commit()
|__保存stray数据到集群metadata pool,即:stray->store_backtrace()
|__调整mydir的一系列统计字段(mydir->fnode.accounted_fragstat/mydir->fnode.accounted_rstat/myin->inode.dirstat/myin->inode.rstat/myin->inode.acounted_rstat)
|__调用mydir->commit() 将mydir写入到集群metadata pool
|__调用myin->store() 将myin写入到集群metadata pool
MDCache::_create_system_file(CDir *dir, char *name, CInode *in, MDSInternalContextBase *fin)
|__调用dir->add_null_entry(name) 将根据name建立的CDentry类对象dn插入到dir的items数组中
|__调用dn->push_projected_linkage(in) 将in做为dn的projected linkage
|__若in是目录
|__经过调用in->get_or_open_dirfrag()获得in对应的CDir类对象mdir
|__经过dir的CInode的到SnapRealm类对象
|__根据SnapRealm类对象中的seq值初始化dn->first以及in->first值
|__建立MutationImpl类对象
|__建立EUpdate类对象
|__调用mds->mdlog->start_entry(EUpdate) 开启mdlog
|__若in不是mdsdir
|__predirty_journal_parents()
|__调用le->metablob.add_primary_dentry() 更新metablob
|__若in是mdsdir
|__predirty_journal_parents()
|__journal_dirty_inode()
|__调用le->metablob.add_remote_dentry()
|__调用le->metablob.add_root()
|__若mdir不为空
|__调用le->metablob.add_new_dir(mdir) 建立一个新的dir
|__调用mds->mdlog->submit_entry() 提交log
|__调用mds->mdlog->flush() 刷新log
MDCache::_create_system_file_finish(MutationRef mut, CDentry *dn, version_t dpv, MDSInternalContextBase *fin)
|__调用dn->pop_projected_linkage() 将in从projected linkage中删除
|__调用dn->mark_dirty() 标记dentry是dirty的
|__获得dn对应的CInode类对象,即:dn->get_linkage()->get_inode()
|__调用in->mark_dirty() 标记dentry对应的CInode是dirty的
|__若in是目录
|__调用in->get_dirfrag() 获得in对应的CDir类对象dir
|__调用dir->mark_dirty() 标记in对应的CDir是dirty的
|__调用mut->apply()
|__调用fin->complete(0)
MDCache::open_root_inode(MDSInternalContextBase *c)
|__若mds的nodeid==mdsmap的root
|__调用create_system_inode(MDS_INO_ROOT) 建立root inode
|__调用in->fetch(c) 从集群里读取root inode信息到MDCache
|__若mds的nodeid!=mdsmap的root
|__调用discover_base_ino(MDS_INO_ROOT, c, mds->mdsmap->get_root()) 经过discover流程找到root inode
MDCache::open_mydir_inode(MDSInternalContextBase *c)
|__调用create_system_inode(MDS_INO_MDSDIR(mds->get_nodeid()) 建立mydir inode
|__调用in->fetch(c) 从集群里读取mydir inode信息到MDCache
MDCache::open_root()
|__若root为空
|__调用open_root_inode() 建立或者发现root
|__直接返回
|__若mds的root位于此mds上
|__调用root->get_or_open_dirfrag()获得rootdir对应饿CDir类对象
|__若rootdir不是subtree_root
|__调用adjust_subtree_auth() 更新rootdir的subtree auth
|__若rootdir未完成
|__调用rootdir->fetch() 从集群中读取rootdir信息到MDCache
|__若mds的root不在此mds上
|__调用root->get_dirfrag() 在此MDS上找出rootdir
|__若rootdir为空
|__调用discover_dir_frag()函数在MDS集群中找到rootdir并写入到MDCache中
|__直接返回
|__若myin为空
|__调用create_system_inode(MDS_INO_MDSDIR(mds->get_nodeid()))建立mydir对应的CInode类对象
|__调用in->fetch() 从集群中获取mydir类对象并写入到集群
|__直接返回
|__获得myin对应的CDir类对象,即:myin->get_or_open_dirfrag()
|__调用adjust_subtree_auth(mydir) 更新mydir的目录权限
|__调用populate_mydir() 填充mydir目录
MDCache::populate_mydir()
|__获得myin对应的CDir类对象,即:mydir=myin->get_or_open_dirfrag()
|__若mydir未完成
|__调用mydir->fetch() 从集群中获取mydir信息
|__直接返回
|__若mydir的版本号是0而且mydir的状态是STATE_BADFRAG
|__清空mydir的STATE_BADFRAG状态
|__调用mydir->mark_dirty()
|__遍历10个Stray
|__从mydir目录下查找到stray对应的CDentry,即:straydn=mydir->lookup()
|__若straydn为空或者straydn对应的CInode为空
|__调用_create_system_file() 建立stray inode并添加到inode_map中
|__直接返回
|__在dirfragtree中获得stray下的叶子节点
|__遍历叶子节点
|__获得叶子节点对应的CDir类对象,即:dir=stray[i]->get_dirfrag()
|__若dir为空
|__调用strays[i]->get_or_open_dirfrag()获得dir类对象
|__若dir的版本号为0
|__调用dir->fetch() 从集群中读取CDir类对象的内容到MDCache
|__设置open=true
|__调用scan_stray_dir()来扫描stray dir
MDCache::scan_stray_dir(dirfrag_t next)
|__遍历strays数组
|__获取到strays数组中CInode成员对应的CDir类对象
|__遍历strays数组中CInode成员对应的CDir类对象
|__若CDir类对象为完成
|__调用dir->fetch()函数从集群中获取CDir类对象的内容到MDCache
|__直接返回
|__遍历每一个CDir下的CDentry,即:遍历CDir下的items数组
|__从items数组成员中获得CDentry类对象
|__设置CDentry类对象的当前状态是STATE_STRAY
|__若CDentry的projected linkage是primary
|__获得CDentry对应的CInode类对象
|__若CInode对应的nlink==0
|__设置CInode的状态为STATE_ORPHAN
|__调用maybe_eval_stray(in)
MDCache::maybe_eval_stray(CInode *in, bool delay)
|__若in的nlink数>0或者in是base或者MDCache是readonly或者mds处于standby replay状态
|__直接返回
|__获得in的parent dentry类对象dn
|__若dn的当前状态是STATE_PURGING
|__直接返回
|__若dn是primary而且dn所在的dir是stray状态
|__由stray manager来处理dn(尝试删除dn对应的CInode和CDir),即:stray_manager.eval_stray(dn, delay)
MDCache::open_foreign_mdsdir(inodeno_t ino, MDSInternalContextBase *fin)
|__调用discover_base_ino()函数从其余的MDS节点处寻找inode number是ino的inode节点信息
MDCache::get_or_create_stray_dentry(CInode *in)
|__调用in->name_stray_dentry()获得in的strayname,即:in的inode编号
|__获得当前stray_index指定的strays数组项,即:strayi=get_stray()
|__由strayi获得strayname对应的dirfrag_t,即:strayi->pick_dirfrag(strayname)
|__由dirfrag_t获得对应的CDir类对象(straydir)和CDentry类对象(straydn)
|__若CDentry类对象为空
|__在straydir的items数组中添加由strayname构成的CDentry
|__新建立的CDentry标识new,即:straydn->mark_new()
|__通知stray manager有新的stray,即:stray_manager.notify_stray_created()
|__设置straydn的当前状态为STATE_STRAY
|__返回straydn
MDCache::get_object(MDSCacheObjectInfo info)
|__若info.ino不为空
|__调用get_inode(info.ino, info.snapid) 获得MDCache中对应的CInode
|__返回MDCache中的CInode
|__调用get_dirfrag(info.dirfrag)获得dirfrag对应的CDir类对象dir
|__若dir为空
|__返回0
|__若info.dname不为空
|__调用dir->lookup(info.dname, info.snapid)获得snapid指定的dir
|__返回dir
|__若info.dname为空
|__返回dir
=======================subtree management==========================
MDCache::list_subtrees(list<CDir*> ls)
|__遍历subtrees数组
|__将subtrees数组中的父目录添加到ls数组中,即:ls.push_back(p->first)
MDCache::adjust_subtree_auth(CDir *dir, mds_authority_t auth, bool do_eval) 调整dir目录及其子目录的auth
|__若mds当前状态是replay状态或者resolve状态
|__设置do_eval=false
|__若dir是base
|__设置root=dir
|__若dir不是base
|__调用get_subtree_root(dir)来找到dir的root dir
|__若root==dir
|__设置dir的auth信息,即:dir->set_dir_auth(auth)
|__若root!=dir
|__设置dir的auth信息,即:dir->set_dir_auth(auth)
|__遍历subtrees数组中以root为索引的全部CDir集合
|__若数组成员的parent dir==dir
|__将数组成员从subtrees的root索引处删除
|__将数组成员添加到subtrees的dir索引处
|__将dir添加到subtrees[root]中
|__设置root=dir
|__若do_eval==true
|__调用eval_subtree_root()来评估dir subtree的锁的使用状况
MDCache::try_subtree_merge(CDir *dir) 将dir及其子目录的全部内容合并到对应的parent目录中,以后将dir及其子目录从subtrees数组中删除
|__从subtrees数组中获得dir下全部的CDir集合,即:oldbounds=subtrees[dir]
|__调用try_subtree_merge_at(dir)函数尝试merge subtree
|__遍历oldbounds数组
|__对于数组成员调用try_subtree_merge_at(*p)函数尝试merge subtree中的目录
MDCache::try_subtree_merge_at(CDir *dir, bool do_eval)
|__若mds当前状态是replay状态或者resolve状态
|__设置do_eval=false
|__若dir不是base
|__调用get_subtree_root()函数获得dir对应的parent
|__若dir!=parent而且dir和parent的auth是一致的而且auth是ambiguous
|__设置dir的auth为CDIR_AUTH_DEFAULT
|__遍历以dir为索引的subtrees数组
|__将数组中的内容添加到subtrees[parent]下
|__在subtrees数组中删除dir项
|__在subtrees[parent]下删除dir项
|__若do_eval==true
|__调用eval_subtree_root()函数
|__若dir是auth的而且mds处于active状态
|__获得dir对应的CInode信息,即:in=dir->inode
|__设置in的auth_pin,即:in->auth_pin(this)
|__建立MutationImpl类对象
|__设置MutationImpl类对象的LogSegment成员为mds->mdlog->get_current_segment()
|__建立EUpdate类对象
|__设置mdlog的start_entry是EUpdate类对象,即:mds->mdlog->start_entry(le)
|__向EUpdate类对象的metablob中添加dir,即:le->metablob.add_dir_context(in->get_parent_dn()->get_dir())
|__调用journal_dirty_inode()函数将处于dirty的inode也写入到EUpdate类对象的metablob中
|__提交mdslog,即:mds->mdlog->submit_entry()
|__刷新mdslog,即:mds->mdlog->flush()
MDCache::subtree_merge_writebehind_finish(CInode *in, MutationRef mut)
|__将in的dirty projected inode写入到mut的LogSegment中,即:in->pop_and_dirty_projected_inode(mut->ls)
|__执行mut,即:mut->apply()
|__清空mut,即:mut->cleanup()
|__设置in的auth_unpin,即:in->auth_unpin(this)
MDCache::eval_subtree_root(CInode *diri)
|__若diri是auth的
|__调用mds->locker->try_eval(diri, CEPH_LOCK_IFILE|CEPH_LOCK_INEST)
MDCache::adjust_bounded_subtree_auth(CDir *dir, set<CDir*> bounds, mds_authority_t auth) 设置dir及其子树的权限信息为auth,同时将bounds数组中的成员合并到dir子树下且设置其权限为auth
|__若dir是root
|__设置root=dir
|__若subtrees数组中不包含root
|__清空以root为索引的subtrees项,即:subtrees[root].clear()
|__若dir不是root
|__调用get_subtree_root(dir)获得dir的root,即:root=get_subtree_root(dir)
|__获得dir当前的auth信息,即:oldauth=dir->authority()
|__若root==dir
|__设置dir的auth,即:dir->set_dir_auth(auth)
|__若root!=dir
|__清空以dir为索引的subtrees项,即:subtrees[dir].clear()
|__设置dir的auth,即:dir->set_dir_auth(auth)
|__遍历以root为索引的subtrees项
|__若数组中对应的项的subtree root是dir
|__把该项添加到subtrees[dir]下
|__把该项从subtrees[root]下删除
|__将dir添加到subtrees[root]下
|__设置root=dir
|__遍历bounds数组
|__若bounds数组成员不在subtrees[dir]下
|__若bounds数组成员的subtree root是dir
|__调用adjust_subtree_auth(bound, oldauth)设置bound的auth信息
|__若bounds数组成员的subtree root不是dir
|__调用get_subtree_root()获得bounds数组成员的subtree root
|__subtree root为索引的subtrees数组中没有包含bounds数组成员
|__调用adjust_subtree_auth(bound, t->authority())设置bound的auth
|__循环遍历
|__在subtrees[dir]目录下的到bound的subtree root
|__调用adjust_subtree_auth(t, auth)来调整subtree root的auth
|__调用try_subtree_merge_at(t)来尝试merge subtree root t到dir
|__调用get_subtree_root()函数获得bound的subtree root
|__若subtree root==dir
|__退出遍历
|__遍历subtrees[dir]数组
|__若数组成员不在bounds数组中
|__调用adjust_subtree_auth(p, auth)来设置成员的auth
|__调用try_subtree_merge_at(p)来尝试合并p到dir
|__调用verify_subtree_bounds(dir, bounds)
MDSCache::verify_subtree_bounds(CDir *dir, set<CDir*> bounds)
|__遍历subtrees[dir]数组
|__若数组中的成员在bounds数组中
|__将数组中的成员从bounds数组中删除
|__遍历bounds数组
|__打印出extra bound
MDCache::get_force_dirfrag_bound_set(vector<dirfrag_t> dfs, set<CDir*> bounds) 获得dfs数组中全部位于frag叶子节点的CDir类对象并将其放入到bounds数组中
|__遍历dfs数组
|__获得数组成员中的ino号和frag信息
|__获得ino号对应的CInode类对象
|__遍历全部的frag信息
|__在CInode类对象对应的dirfragtree下获得frag下的全部叶子节点
|__遍历叶子节点
|__将叶子节点对应的CDir类对象放入bounds数组中
MDSCache::adjust_bounded_subtree_auth(CDir *dir, vector<dirfrag_t> bound_dfs, mds_authority_t auth)
|__调用get_force_dirfrag_bound_set(bound_dfs, bounds)获得bound_dfs数组中全部位于frag叶子节点的CDir类对象并将其放入到bounds数组中
|__调用adjust_bounded_subtree_auth(dir, bounds, auth)设置dir及其子树的权限信息为auth,同时将bounds数组中的成员合并到dir子树下且设置其权限为auth
MDCache::map_dirfrag_set(list<dirfrag_t> dfs, set<CDir*> result) 获得dfs中位于dirfragtree上指定frag的叶子节点的CDir类对象
|__遍历dfs数组
|__获得数组成员中的ino成员和frag成员并将这两项写入到map<inodeno_t, fragset_t> ino_fragset集合中
|__遍历ino_fragset集合
|__获得inodeno_t对应的CInode类对象
|__遍历fragset_t集合
|__获得CInode的dirfragtree里fragset_t集合成员的叶子节点
|__遍历叶子节点
|__获得叶子节点对应的CDir类对象,即:dir=in->get_dirfrag(*q)
|__将dir放入到result数组中
MDCache::get_subtree_root(CDir *dir)
|__若dir是subtree root
|__返回dir
|__获得dir的父目录dir,即:dir=dir->get_inode()->get_parent_dir()
|__若dir为空
|__返回0
MDCache::get_projected_subtree_root(CDir *dir)
|__若dir是subtree root
|__返回dir
|__获得dir的projected父目录dir,即:dir=dir->get_inode()->get_projected_parent_dir()
|__若dir为空
|__返回0
MDCache::remove_subtree(CDir *dir)
|__从subtrees数组中删除dir,即:subtrees,erase(dir)
|__若dir存在parent dir
|__获得dir的subtree root,即:p=get_subtree_root(dir->get_parent_dir())
|__在以p为索引的subtrees数组中删除dir,即:subtrees[p].erase(dir)
MDCache::get_subtree_bounds(CDir *dir, set<CDir*> bounds)
|__将subtrees[dir]集合赋值给bounds
MDCache::get_wouldbe_subtree_bounds(CDir *dir, set<CDir*> bounds)
|__若subtrees[dir]不为空
|__将subtrees[dir]集合赋值给bounds
|__若subtrees[dir]为空
|__获得dir的subtree root,即:root=get_subtree_root(dir)
|__遍历subtrees[root]集合
|__若集合中的成员==dir或成员的parent dir==dir
|__将成员或成员的parent dir插入到bounds数组中
MDCache::project_subtree_rename(CInode *diri, CDir *olddir, CDir *newdir)
|__以diri为索引以olddir和newdir为值,更新projected_subtree_renames数组,即:projected_subtree_renames[diri].push_back(pair<CDir*,CDir*>(olddir, newdir))
MDCache::adjust_subtree_after_rename(CInode *diri, CDir *olddir, bool pop, bool imported)
|__获得diri的parent dir,即:newdir=diri->get_parent_dir()
|__若pop==true
|__在projected_subtree_renames数组中查找diri对应的项
|__若找到且diri对应的项为空
|__从projected_subtree_renames数组中删除diri,即:projected_subtree_renames.erase(p)
|__获得subtree dirfrags,即:diri->get_subtree_dirfrags(dfls)
|__获得nested dirfrags,即:diri->get_nested_dirfrags(dfls)
|__遍历dfls数组
|__获得olddir的subtree root,即: oldparent=get_subtree_root(olddir)
|__获得newdir的subtree root,即:newparent=get_subtree_root(newdir)
|__若oldparent==newparent
|__遍历下一个
|__若dir是subtree root
|__从oldparent的subtrees数组中删除dir,即:subtrees[oldparent].erase(dir)
|__将dir插入到newparent的subtrees数组中,即:subtrees[newparent].insert(dir)
|__调用try_subtree_merge_at(dir, !imported) 尝试合并dir
|__若dir不是subtree root
|__遍历subtrees[oldparent]数组
|__若数组成员的subtree root != oldparent
|__将该数组成员添加到tomove数组中
|__遍历tomove数组
|__将数组中的成员从subtrees数组中的oldparent中移除,同时添加到newparent中
MDCache::get_fullauth_subtrees(set<CDir*> s)
|__遍历subtrees数组
|__若subtrees root是auth的但不是ambigous auth
|__将subtrees root插入到s数组中
MDCache::get_auth_subtrees(set<CDir*> s)
|__遍历subtrees数组
|__若subtrees root是auth的
|__将subtrees root插入到s数组中
MDCache::num_subtrees()
|__返回subtrees数组的大小
MDCache::num_subtrees_fullauth()
|__返回subtrees数组中的subtree root是is_full_dir_auth()的个数
MDCache::num_subtrees_fullnonauth()
|__返回subtrees数组中的subtree root是is_full_dir_nonauth()的个数