}
bool force_to_leaf(frag_t x) {
- assert(!is_leaf(x));
+ if (is_leaf(x))
+ return false;
frag_t parent = get_branch_or_leaf(x);
assert(parent.bits() <= x.bits());
- bool changed = false;
-
// do we need to split from parent to x?
if (parent.bits() < x.bits()) {
int spread = x.bits() - parent.bits();
if (nb == 0) {
// easy: split parent (a leaf) by the difference
split(parent, spread);
- return true;
}
assert(nb > spread);
// add an intermediary split
- changed = true;
merge(parent, nb);
split(parent, spread);
q.pop_front();
int nb = get_split(t);
if (nb) {
- changed = true;
merge(t, nb); // merge this point, and
t.split(nb, q); // queue up children
}
}
- return changed;
+ return true;
}
// verify that we describe a legal partition of the namespace.
inline ostream& operator<<(ostream& out, fragset_t& fs)
{
- return out << "fragset_t(" << fs.get() << ")" << endl;
+ return out << "fragset_t(" << fs.get() << ")";
}
#endif
#include <cassert>
#undef dout
-#define dout(x) if (x <= g_conf.debug || x <= g_conf.debug_mds) cout << g_clock.now() << " mds" << dir->cache->mds->get_nodeid() << ".cache.den(" << dir->ino() << " " << name << ") "
+#define dout(x) if (x <= g_conf.debug || x <= g_conf.debug_mds) cout << g_clock.now() << " mds" << dir->cache->mds->get_nodeid() << ".cache.den(" << dir->dirfrag() << " " << name << ") "
ostream& CDentry::print_db_line_prefix(ostream& out)
{
}
if (in.is_symlink()) out << " symlink";
-
+ if (in.is_dir() && !in.dirfragtree.empty()) out << " " << in.dirfragtree;
+
out << " v" << in.get_version();
// locks
pair<int,int> CInode::authority()
{
- //if (is_root())
- //return CDIR_AUTH_ROOTINODE; // root _inode_ is locked to mds0.
if (force_auth.first >= 0)
return force_auth;
show_subtrees();
}
+
void MDCache::adjust_bounded_subtree_auth(CDir *dir, list<dirfrag_t>& bound_dfs, pair<int,int> auth)
{
dout(7) << "adjust_bounded_subtree_auth " << dir->get_dir_auth() << " -> " << auth
adjust_bounded_subtree_auth(dir, bounds, auth);
}
+void MDCache::map_dirfrag_set(list<dirfrag_t>& dfs, set<CDir*>& result)
+{
+ // group by inode
+ map<inodeno_t, fragset_t> ino_fragset;
+ for (list<dirfrag_t>::iterator p = dfs.begin(); p != dfs.end(); ++p)
+ ino_fragset[p->ino].insert(p->frag);
+
+ // get frags
+ for (map<inodeno_t, fragset_t>::iterator p = ino_fragset.begin();
+ p != ino_fragset.end();
+ ++p) {
+ CInode *in = get_inode(p->first);
+ if (!in) continue;
+
+ list<frag_t> fglist;
+ for (set<frag_t>::iterator q = p->second.begin(); q != p->second.end(); ++q)
+ in->dirfragtree.get_leaves_under(*q, fglist);
+
+ dout(15) << "map_dirfrag_set " << p->second << " -> " << fglist
+ << " on " << *in << endl;
+
+ for (list<frag_t>::iterator q = fglist.begin(); q != fglist.end(); ++q) {
+ CDir *dir = in->get_dirfrag(*q);
+ if (dir) result.insert(dir);
+ }
+ }
+}
+
CDir *MDCache::get_subtree_root(CDir *dir)
// discover?
assert(!cur->is_auth());
if (cur->is_ambiguous_auth()) {
- dout(10) << "traverse: need dir, waiting for single auth on " << *cur << endl;
+ dout(10) << "traverse: need dirfrag " << fg << ", waiting for single auth on " << *cur << endl;
cur->add_waiter(CInode::WAIT_SINGLEAUTH, _get_waiter(mdr, req));
return 1;
} else if (dir_discovers.count(cur->ino())) {
- dout(10) << "traverse: need dir, already doing discover for " << *cur << endl;
+ dout(10) << "traverse: need dirfrag " << fg << ", already doing discover for " << *cur << endl;
assert(cur->is_waiter_for(CInode::WAIT_DIR));
} else {
filepath want = path.postfixpath(depth);
- dout(10) << "traverse: need dir, doing discover, want " << want.get_path()
+ dout(10) << "traverse: need dirfrag " << fg << ", doing discover, want " << want.get_path()
<< " from " << *cur << endl;
mds->send_message_mds(new MDiscover(mds->get_nodeid(),
cur->ino(),
dis.update_dir(dir);
dout(7) << "add_replica_dir had " << *dir << " nonce " << dir->replica_nonce << endl;
} else {
+ // force frag to leaf in the diri tree
+ diri->dirfragtree.force_to_leaf(fg);
+
// add replica.
dir = diri->add_dirfrag( new CDir(diri, fg, this, false) );
dis.update_dir(dir);
void adjust_bounded_subtree_auth(CDir *dir, list<dirfrag_t>& bounds, int a) {
adjust_bounded_subtree_auth(dir, bounds, pair<int,int>(a, CDIR_AUTH_UNKNOWN));
}
+ void map_dirfrag_set(list<dirfrag_t>& dfs, set<CDir*>& result);
void adjust_export_state(CDir *dir);
void try_subtree_merge(CDir *root);
void try_subtree_merge_at(CDir *root);
// include the dirfrag? only if it's not the bounding subtree root.
if (cur != bound) {
assert(cur->is_auth());
- prep->add_dirfrag( new CDirDiscover(cur, cur->add_replica(dest)) ); // yay!
+ prep->add_dirfrag( cur->replicate_to(dest) ); // yay!
dout(7) << " added " << *cur << endl;
}
it != inode_trace.end();
it++) {
CInode *in = *it;
+ dout(7) << " added " << *in->parent << endl;
dout(7) << " added " << *in << endl;
prep->add_inode( in->parent->get_dir()->dirfrag(),
- in->parent->get_name(),
+ in->parent->get_name(),
+ in->parent->replicate_to(dest),
in->replicate_to(dest) );
}
map<inodeno_t, fragset_t> bound_dirfragset;
for (list<dirfrag_t>::iterator p = m->get_bounds().begin();
p != m->get_bounds().end();
- ++p)
+ ++p) {
+ dout(10) << " bound " << *p << endl;
bound_dirfragset[p->ino].insert(p->frag);
+ }
// assimilate contents?
if (!m->did_assim()) {
dout(7) << " pinning import bound " << *bound << endl;
bound->get(CDir::PIN_IMPORTBOUND);
bound->state_set(CDir::STATE_IMPORTBOUND);
- import_bounds.insert(bound);
} else {
dout(7) << " already pinned import bound " << *bound << endl;
}
+ import_bounds.insert(bound);
}
}
dout(7) << "handle_export_notify " << old_auth << " -> " << new_auth
<< " on " << *dir << endl;
// adjust auth
- cache->adjust_bounded_subtree_auth(dir, m->get_bounds(), new_auth);
+ set<CDir*> have;
+ cache->map_dirfrag_set(m->get_bounds(), have);
+ cache->adjust_bounded_subtree_auth(dir, have, new_auth);
// induce a merge?
cache->try_subtree_merge(dir);
list<dirfrag_t> bounds;
list<CInodeDiscover*> inodes;
+ list<CDentryDiscover*> dentries;
map<inodeno_t,dirfrag_t> inode_dirfrag;
map<inodeno_t,string> inode_dentry;
dirfrag_t get_dirfrag() { return dirfrag; }
list<dirfrag_t>& get_bounds() { return bounds; }
list<CInodeDiscover*>& get_inodes() { return inodes; }
+ list<CDentryDiscover*>& get_dentries() { return dentries; }
list<frag_t>& get_inode_dirfrags(inodeno_t ino) {
return frags_by_ino[ino];
}
iit != inodes.end();
iit++)
delete *iit;
+ for (list<CDentryDiscover*>::iterator p = dentries.begin();
+ p != dentries.end();
+ p++)
+ delete *p;
for (map<dirfrag_t,CDirDiscover*>::iterator dit = dirfrags.begin();
dit != dirfrags.end();
dit++)
void add_export(dirfrag_t df) {
bounds.push_back( df );
}
- void add_inode(dirfrag_t df, const string& dentry, CInodeDiscover *in) {
+ void add_inode(dirfrag_t df, const string& name, CDentryDiscover *dn, CInodeDiscover *in) {
inodes.push_back(in);
+ dentries.push_back(dn);
inode_dirfrag[in->get_ino()] = df;
- inode_dentry[in->get_ino()] = dentry;
+ inode_dentry[in->get_ino()] = name;
}
void add_dirfrag(CDirDiscover *dir) {
dirfrags[dir->get_dirfrag()] = dir;
CInodeDiscover *in = new CInodeDiscover;
in->_decode(payload, off);
inodes.push_back(in);
+
+ // dentry
+ CDentryDiscover *dn = new CDentryDiscover;
+ dn->_decode(payload, off);
+ dentries.push_back(dn);
// dentry
string d;
// inodes
int ni = inodes.size();
payload.append((char*)&ni, sizeof(int));
- for (list<CInodeDiscover*>::iterator iit = inodes.begin();
- iit != inodes.end();
- iit++) {
+ list<CDentryDiscover*>::iterator dit = dentries.begin();
+ list<CInodeDiscover*>::iterator iit = inodes.begin();
+ while (iit != inodes.end()) {
(*iit)->_encode(payload);
-
- // dentry
+ (*dit)->_encode(payload);
+
+ // dentry name
_encode(inode_dentry[(*iit)->get_ino()], payload);
// dir ino
// child frags
::_encode(frags_by_ino[(*iit)->get_ino()], payload);
+
+ iit++;
+ dit++;
}
// dirs
class MMDSFragmentNotify : public Message {
inodeno_t ino;
frag_t basefrag;
- char bits;
+ int8_t bits;
public:
inodeno_t get_ino() { return ino; }
virtual char *get_type_name() { return "fragment_notify"; }
void print(ostream& o) {
o << "fragment_notify(" << ino << "#" << basefrag
- << " " << bits << ")";
+ << " " << (int)bits << ")";
}
virtual void decode_payload() {
int off = 0;
- ::_decode(ino, payload, off);
- ::_decode(basefrag, payload, off);
- ::_decode(bits, payload, off);
- ::_decode(basebl, payload, off);
+ ::_decode(ino, payload, off);
+ ::_decode(basefrag, payload, off);
+ ::_decode(bits, payload, off);
+ ::_decode(basebl, payload, off);
}
virtual void encode_payload() {
- ::_encode(ino, payload);
- ::_encode(basefrag, payload);
- ::_encode(bits, payload);
- ::_encode(basebl, payload);
+ ::_encode(ino, payload);
+ ::_encode(basefrag, payload);
+ ::_encode(bits, payload);
+ ::_encode(basebl, payload);
}
};