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()的個數