mds/AnchorClient.o\
mds/LogEvent.o\
mds/IdAllocator.o\
+ mds/ClientMap.o\
mds/MDLog.o
OSD_OBJS= \
sage mds
+- hmm, should we move ESubtreeMap out of the journal?
+ that would avoid all the icky weirdness in shutdown, with periodic logging, etc.
+
- fix rejoin
/ - validate dentry<->inode connectivity
/ - clean up remove_gather() crap
mds_log_read_inc: 1<<20,
mds_log_pad_entry: 128,//256,//64,
mds_log_flush_on_shutdown: true,
- mds_log_import_map_interval: 128*1024, // frequency (in bytes) of EImportMap in log
+ mds_log_subtree_map_interval: 128*1024, // frequency (in bytes) of EImportMap in log
mds_log_eopen_size: 100, // # open inodes per log entry
mds_bal_replicate_threshold: 2000,
int mds_log_read_inc;
int mds_log_pad_entry;
bool mds_log_flush_on_shutdown;
- off_t mds_log_import_map_interval;
+ off_t mds_log_subtree_map_interval;
int mds_log_eopen_size;
float mds_bal_replicate_threshold;
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+
+
+#define DBLEVEL 20
+
+#include "include/types.h"
+
+#include "MDS.h"
+#include "ClientMap.h"
+
+#include "osdc/Filer.h"
+
+#include "config.h"
+#undef dout
+#define dout(x) if (x <= g_conf.debug_mds) cout << g_clock.now() << " mds" << mds->get_nodeid() << ".clientmap "
+
+
+
+void ClientMap::init_inode()
+{
+ memset(&inode, 0, sizeof(inode));
+ inode.ino = MDS_INO_CLIENTMAP_OFFSET + mds->get_nodeid();
+ inode.layout = g_OSD_FileLayout;
+}
+
+
+// ----------------
+// LOAD
+
+class C_CM_Load : public Context {
+ ClientMap *clientmap;
+public:
+ bufferlist bl;
+ C_CM_Load(ClientMap *cm) : clientmap(cm) {}
+ void finish(int r) {
+ clientmap->_load_finish(bl);
+ }
+};
+
+void ClientMap::load(Context *onload)
+{
+ dout(10) << "load" << endl;
+
+ init_inode();
+
+ if (onload)
+ waiting_for_load.push_back(onload);
+
+ C_CM_Load *c = new C_CM_Load(this);
+ mds->filer->read(inode,
+ 0, inode.layout.stripe_size,
+ &c->bl,
+ c);
+
+}
+
+void ClientMap::_load_finish(bufferlist &bl)
+{
+ int off = 0;
+ decode(bl, off);
+ dout(10) << "_load_finish v " << version
+ << ", " << client_inst.size() << " clients, "
+ << bl.length() << " bytes"
+ << endl;
+ projected = committing = committed = version;
+ finish_contexts(waiting_for_load);
+}
+
+
+// ----------------
+// SAVE
+
+class C_CM_Save : public Context {
+ ClientMap *clientmap;
+ version_t version;
+public:
+ C_CM_Save(ClientMap *cm, version_t v) : clientmap(cm), version(v) {}
+ void finish(int r) {
+ clientmap->_save_finish(version);
+ }
+};
+
+void ClientMap::save(Context *onsave, version_t needv)
+{
+ dout(10) << "save needv " << needv << ", v " << version << endl;
+ commit_waiters[version].push_back(onsave);
+
+ if (needv && committing >= needv) return;
+
+ bufferlist bl;
+
+ init_inode();
+ encode(bl);
+ committing = version;
+ mds->filer->write(inode,
+ 0, bl.length(), bl,
+ 0,
+ 0, new C_CM_Save(this, version));
+}
+
+void ClientMap::_save_finish(version_t v)
+{
+ dout(10) << "_save_finish v" << v << endl;
+ committed = v;
+
+ finish_contexts(commit_waiters[v]);
+ commit_waiters.erase(v);
+}
#include <ext/hash_map>
using namespace __gnu_cxx;
+#include "include/Context.h"
+#include "mdstypes.h"
+
+class MDS;
/*
* this structure is used by the MDS purely so that
*/
class ClientMap {
private:
+ MDS *mds;
+
version_t version;
version_t projected;
version_t committing;
map<version_t, list<Context*> > commit_waiters;
public:
- ClientMap() : version(0), projected(0), committing(0), committed(0) {}
+ ClientMap(MDS *m) : mds(m),
+ version(0), projected(0), committing(0), committed(0) {}
version_t get_version() { return version; }
version_t get_projected() { return projected; }
void set_committing(version_t v) { committing = v; }
void set_committed(version_t v) { committed = v; }
- void add_commit_waiter(Context *c) {
- commit_waiters[committing].push_back(c);
- }
- void take_commit_waiters(version_t v, list<Context*>& ls) {
- ls.swap(commit_waiters[v]);
- commit_waiters.erase(v);
- }
-
private:
// affects version
hash_map<int,entity_inst_t> client_inst;
projected = committing = committed = version;
}
+
+ // -- loading, saving --
+ inode_t inode;
+ list<Context*> waiting_for_load;
+
+ void init_inode();
+ void load(Context *onload);
+ void _load_finish(bufferlist &bl);
+ void save(Context *onsave, version_t needv=0);
+ void _save_finish(version_t v);
};
#endif
#include "events/EString.h"
#include "events/ESession.h"
-#include "events/EClientMap.h"
-#include "events/EImportMap.h"
+#include "events/ESubtreeMap.h"
#include "events/EExport.h"
#include "events/EImportStart.h"
#include "events/EImportFinish.h"
case EVENT_STRING: le = new EString; break;
case EVENT_SESSION: le = new ESession; break;
- case EVENT_CLIENTMAP: le = new EClientMap; break;
- case EVENT_IMPORTMAP: le = new EImportMap; break;
+ case EVENT_SUBTREEMAP: le = new ESubtreeMap; break;
case EVENT_EXPORT: le = new EExport; break;
case EVENT_IMPORTSTART: le = new EImportStart; break;
case EVENT_IMPORTFINISH: le = new EImportFinish; break;
#define EVENT_STRING 1
#define EVENT_SESSION 7
-#define EVENT_CLIENTMAP 8
-#define EVENT_IMPORTMAP 2
+#define EVENT_SUBTREEMAP 2
#define EVENT_EXPORT 30
#define EVENT_IMPORTSTART 31
#define EVENT_IMPORTFINISH 32
#include "osdc/Filer.h"
-#include "events/EImportMap.h"
+#include "events/ESubtreeMap.h"
#include "events/EUpdate.h"
#include "events/ESlaveUpdate.h"
#include "events/EString.h"
#include "messages/MGenericMessage.h"
-#include "messages/MMDSImportMap.h"
+#include "messages/MMDSResolve.h"
#include "messages/MMDSResolveAck.h"
#include "messages/MMDSCacheRejoin.h"
* take note of where we write import_maps in the log, as we need
* to take care not to expire them until an updated map is safely flushed.
*/
-class C_MDS_WroteImportMap : public Context {
+class C_MDS_WroteSubtreeMap : public Context {
MDCache *mdcache;
off_t end_off;
public:
- C_MDS_WroteImportMap(MDCache *mc, off_t eo) : mdcache(mc), end_off(eo) { }
+ C_MDS_WroteSubtreeMap(MDCache *mc, off_t eo) : mdcache(mc), end_off(eo) { }
void finish(int r) {
- mdcache->_logged_import_map(end_off);
+ mdcache->_logged_subtree_map(end_off);
}
};
-void MDCache::log_import_map(Context *onsync)
+void MDCache::log_subtree_map(Context *onsync)
{
- dout(10) << "log_import_map " << num_subtrees() << " subtrees, "
+ dout(10) << "log_subtree_map " << num_subtrees() << " subtrees, "
<< num_subtrees_fullauth() << " fullauth"
<< endl;
- EImportMap *le = new EImportMap;
+ ESubtreeMap *le = new ESubtreeMap;
// include all auth subtrees, and their bounds.
// and a spanning tree to tie it to the root.
CDir *dir = p->first;
if (!dir->is_auth()) continue;
- le->imports.insert(dir->dirfrag());
+ le->subtrees[dir->dirfrag()].clear();
le->metablob.add_dir_context(dir, true);
le->metablob.add_dir(dir, false);
q != p->second.end();
++q) {
CDir *bound = *q;
- le->bounds[dir->dirfrag()].insert(bound->dirfrag());
+ le->subtrees[dir->dirfrag()].push_back(bound->dirfrag());
le->metablob.add_dir_context(bound);
le->metablob.add_dir(bound, false);
}
}
- Context *fin = new C_MDS_WroteImportMap(this, mds->mdlog->get_write_pos());
- mds->mdlog->writing_import_map = true;
+ Context *fin = new C_MDS_WroteSubtreeMap(this, mds->mdlog->get_write_pos());
+ mds->mdlog->writing_subtree_map = true;
mds->mdlog->submit_entry(le);
mds->mdlog->wait_for_sync(fin);
if (onsync)
mds->mdlog->wait_for_sync(onsync);
}
-void MDCache::_logged_import_map(off_t off)
+void MDCache::_logged_subtree_map(off_t off)
{
- dout(10) << "_logged_import_map at " << off << endl;
- mds->mdlog->last_import_map = off;
- mds->mdlog->writing_import_map = false;
+ dout(10) << "_logged_subtree_map at " << off << endl;
+ mds->mdlog->last_subtree_map = off;
+ mds->mdlog->writing_subtree_map = false;
list<Context*> ls;
- mds->mdlog->take_import_map_expire_waiters(ls);
+ mds->mdlog->take_subtree_map_expire_waiters(ls);
mds->queue_waiters(ls);
}
-void MDCache::send_import_map(int who)
+void MDCache::send_resolve(int who)
{
if (migrator->is_exporting())
- send_import_map_later(who);
+ send_resolve_later(who);
else
- send_import_map_now(who);
+ send_resolve_now(who);
}
-void MDCache::send_import_map_later(int who)
+void MDCache::send_resolve_later(int who)
{
- dout(10) << "send_import_map_later to mds" << who << endl;
- wants_import_map.insert(who);
+ dout(10) << "send_resolve_later to mds" << who << endl;
+ wants_resolve.insert(who);
}
-void MDCache::send_pending_import_maps()
+void MDCache::maybe_send_pending_resolves()
{
- if (wants_import_map.empty())
+ if (wants_resolve.empty())
return; // nothing to send.
// only if it's appropriate!
if (migrator->is_exporting() ||
migrator->is_importing()) {
- dout(7) << "send_pending_import_maps waiting, imports/exports still in progress" << endl;
+ dout(7) << "maybe_send_pending_resolves waiting, imports/exports still in progress" << endl;
return; // not now
}
// ok, send them.
- for (set<int>::iterator p = wants_import_map.begin();
- p != wants_import_map.end();
+ for (set<int>::iterator p = wants_resolve.begin();
+ p != wants_resolve.end();
p++)
- send_import_map_now(*p);
- wants_import_map.clear();
+ send_resolve_now(*p);
+ wants_resolve.clear();
}
-class C_MDC_SendImportMap : public Context {
+class C_MDC_SendResolve : public Context {
MDCache *mdc;
int who;
public:
- C_MDC_SendImportMap(MDCache *c, int w) : mdc(c), who(w) { }
+ C_MDC_SendResolve(MDCache *c, int w) : mdc(c), who(w) { }
void finish(int r) {
- mdc->send_import_map_now(who);
+ mdc->send_resolve_now(who);
}
};
-void MDCache::send_import_map_now(int who)
+void MDCache::send_resolve_now(int who)
{
- dout(10) << "send_import_map_now to mds" << who << endl;
- MMDSImportMap *m = new MMDSImportMap;
+ dout(10) << "send_resolve_now to mds" << who << endl;
+ MMDSResolve *m = new MMDSResolve;
show_subtrees();
migrator->get_import_bound_inos(dir->dirfrag()));
} else {
// not ambiguous.
- m->add_import(dir->dirfrag());
+ m->add_subtree(dir->dirfrag());
// bounds too
for (set<CDir*>::iterator q = subtrees[dir].begin();
q != subtrees[dir].end();
++q) {
CDir *bound = *q;
- m->add_import_export(dir->dirfrag(), bound->dirfrag());
+ m->add_subtree_bound(dir->dirfrag(), bound->dirfrag());
}
}
}
dout(1) << "my recovery peers will be " << recovery_set << endl;
// adjust my recovery lists
- wants_import_map.erase(who); // MDS will ask again
- got_import_map.erase(who); // i'll get another.
+ wants_resolve.erase(who); // MDS will ask again
+ got_resolve.erase(who); // i'll get another.
rejoin_ack_gather.erase(who); // i'll need/get another.
// adjust subtree auth
/*
- * during resolve state, we share import_maps to determine who
- * is authoritative for which trees. we expect to get an import_map
+ * during resolve state, we share resolves to determine who
+ * is authoritative for which trees. we expect to get an resolve
* from _everyone_ in the recovery_set (the mds cluster at the time of
* the first failure).
*/
-void MDCache::handle_import_map(MMDSImportMap *m)
+void MDCache::handle_resolve(MMDSResolve *m)
{
- dout(7) << "handle_import_map from " << m->get_source() << endl;
+ dout(7) << "handle_resolve from " << m->get_source() << endl;
int from = m->get_source().num();
// ambiguous slave requests?
}
// update my dir_auth values
- for (map<dirfrag_t, list<dirfrag_t> >::iterator pi = m->imap.begin();
- pi != m->imap.end();
+ for (map<dirfrag_t, list<dirfrag_t> >::iterator pi = m->subtrees.begin();
+ pi != m->subtrees.end();
++pi) {
CDir *im = get_dirfrag(pi->first);
if (im) {
* note: it would be cleaner to do this check before updating our own
* subtree map.. then the import_finish or _reverse could operate on an
* un-munged subtree map. but... checking for import completion against
- * the provided import_map isn't easy. so, we skip audit checks in these
+ * the provided resolve isn't easy. so, we skip audit checks in these
* functions.
*/
if (mds->is_active() || mds->is_stopping()) {
// resolving?
if (mds->is_resolve()) {
// note ambiguous imports too
- for (map<dirfrag_t, list<dirfrag_t> >::iterator pi = m->ambiguous_imap.begin();
- pi != m->ambiguous_imap.end();
+ for (map<dirfrag_t, list<dirfrag_t> >::iterator pi = m->ambiguous_imports.begin();
+ pi != m->ambiguous_imports.end();
++pi) {
dout(10) << "noting ambiguous import on " << pi->first << " bounds " << pi->second << endl;
other_ambiguous_imports[from][pi->first].swap( pi->second );
}
// did i get them all?
- got_import_map.insert(from);
+ got_resolve.insert(from);
maybe_resolve_finish();
}
void MDCache::maybe_resolve_finish()
{
- if (got_import_map != recovery_set) {
- dout(10) << "still waiting for more importmaps, got " << got_import_map
+ if (got_resolve != recovery_set) {
+ dout(10) << "still waiting for more importmaps, got " << got_resolve
<< ", need " << recovery_set << endl;
}
else if (!need_resolve_ack.empty()) {
* from a rejoining node:
* weak dirfrag
* weak dentries (w/ connectivity)
- * strong inodes, if we have open files
*
* from a surviving node:
* strong dirfrag
{
dout(10) << "cache_rejoin_walk " << *dir << endl;
- // walk dirfrag's dentries.
list<CDir*> nested; // finish this dir, then do nested items
- if (mds->is_rejoin())
+ if (mds->is_rejoin()) {
+ // WEAK
rejoin->add_weak_dirfrag(dir->dirfrag());
- else
- rejoin->add_strong_dirfrag(dir->dirfrag(), dir->get_replica_nonce());
-
- for (map<string,CDentry*>::iterator p = dir->items.begin();
- p != dir->items.end();
- ++p) {
- // dentry
- CDentry *dn = p->second;
- if (mds->is_rejoin()) {
- // weak
- if (dn->is_null()) {
- rejoin->add_weak_null_dentry(dir->dirfrag(), p->first);
- } else if (dn->is_primary()) {
+
+ for (map<string,CDentry*>::iterator p = dir->items.begin();
+ p != dir->items.end();
+ ++p) {
+ CDentry *dn = p->second;
+ if (dn->is_primary())
rejoin->add_weak_primary_dentry(dir->dirfrag(), p->first, dn->get_inode()->ino());
- } else {
+ else if (dn->is_remote())
rejoin->add_weak_remote_dentry(dir->dirfrag(), p->first, dn->get_remote_ino());
- }
- } else {
- // strong
+ else
+ assert(0); // i shouldn't have a non-auth null dentry after journal replay..
+ }
+ } else {
+ // STRONG
+ rejoin->add_strong_dirfrag(dir->dirfrag(), dir->get_replica_nonce());
+
+ for (map<string,CDentry*>::iterator p = dir->items.begin();
+ p != dir->items.end();
+ ++p) {
+ CDentry *dn = p->second;
rejoin->add_strong_dentry(dir->dirfrag(), p->first,
dn->is_primary() ? dn->get_inode()->ino():inodeno_t(0),
dn->is_remote() ? dn->get_remote_ino():inodeno_t(0),
dn->get_replica_nonce(),
dn->lock.get_state());
- }
-
- if (dn->is_primary()) {
- CInode *in = dn->get_inode();
-
- // strong inode?
- if (!mds->is_rejoin() || in->get_caps_wanted())
+ if (dn->is_primary()) {
+ CInode *in = dn->get_inode();
rejoin->add_strong_inode(in->ino(), in->get_replica_nonce(),
in->get_caps_wanted(),
in->authlock.get_state(),
in->dirfragtreelock.get_state(),
in->filelock.get_state(),
in->dirlock.get_state());
-
- // dirfrags in this subtree?
- in->get_nested_dirfrags(nested);
+ in->get_nested_dirfrags(nested);
+ }
}
}
-
+
// recurse into nested dirs
for (list<CDir*>::iterator p = nested.begin();
p != nested.end();
CInode *in = dn->get_inode();
assert(in);
- // strong inode? if so, note caps_wanted
- if (weak->strong_inodes.count(in->ino())) {
- assert(weak->strong_inodes[in->ino()].caps_wanted);
- in->mds_caps_wanted[from] = weak->strong_inodes[in->ino()].caps_wanted;
- weak->strong_inodes.erase(in->ino());
- } else {
- in->mds_caps_wanted.erase(from);
- }
-
if (survivor) inode_remove_replica(in, from);
int nonce = in->add_replica(from);
dout(10) << " have " << *in << endl;
if (!survivor)
in->dirlock.set_state(LOCK_SCATTER);
- if (ack) {
+ if (ack)
ack->add_strong_inode(in->ino(),
nonce,
0,
in->dirfragtreelock.get_replica_state(),
in->filelock.get_replica_state(),
in->dirlock.get_replica_state());
- }
}
}
}
// (wait for) flush log?
if (g_conf.mds_log_flush_on_shutdown) {
- if (mds->mdlog->get_non_importmap_events()) {
+ if (mds->mdlog->get_non_subtreemap_events()) {
dout(7) << "waiting for log to flush .. " << mds->mdlog->get_num_events()
- << " (" << mds->mdlog->get_non_importmap_events() << ")" << endl;
+ << " (" << mds->mdlog->get_non_subtreemap_events() << ")" << endl;
return false;
}
}
}
if (mds->mdlog->get_num_events()) {
- dout(7) << "waiting for log to flush (including import_map, now) .. " << mds->mdlog->get_num_events()
- << " (" << mds->mdlog->get_non_importmap_events() << ")" << endl;
+ dout(7) << "waiting for log to flush (including subtree_map, now) .. " << mds->mdlog->get_num_events()
+ << " (" << mds->mdlog->get_non_subtreemap_events() << ")" << endl;
return false;
}
switch (m->get_type()) {
// RESOLVE
- case MSG_MDS_IMPORTMAP:
- handle_import_map((MMDSImportMap*)m);
+ case MSG_MDS_RESOLVE:
+ handle_resolve((MMDSResolve*)m);
break;
case MSG_MDS_RESOLVEACK:
handle_resolve_ack((MMDSResolveAck*)m);
class Message;
-class MMDSImportMap;
+class MMDSResolve;
class MMDSResolveAck;
class MMDSCacheRejoin;
class MMDSCacheRejoinAck;
protected:
// delayed cache expire
- map<CDir*, map<int, MCacheExpire*> > delayed_expire; // import|export dir -> expire msg
+ map<CDir*, map<int, MCacheExpire*> > delayed_expire; // subtree root -> expire msg
// -- discover --
hash_map<inodeno_t, set<int> > dir_discovers; // dirino -> mds set i'm trying to discover.
// [resolve]
// from EImportStart w/o EImportFinish during journal replay
map<dirfrag_t, list<dirfrag_t> > my_ambiguous_imports;
- // from MMDSImportMaps
+ // from MMDSResolves
map<int, map<dirfrag_t, list<dirfrag_t> > > other_ambiguous_imports;
map<int, map<metareqid_t, EMetaBlob> > uncommitted_slave_updates; // for replay.
map<metareqid_t, Context*> waiting_for_slave_update_commit;
friend class ESlaveUpdate;
- set<int> wants_import_map; // nodes i need to send my import map to
- set<int> got_import_map; // nodes i got import_maps from
+ set<int> wants_resolve; // nodes i need to send my resolve to
+ set<int> got_resolve; // nodes i got resolves from
set<int> need_resolve_ack; // nodes i need a resolve_ack from
- void handle_import_map(MMDSImportMap *m);
+ void handle_resolve(MMDSResolve *m);
void handle_resolve_ack(MMDSResolveAck *m);
void maybe_resolve_finish();
void disambiguate_imports();
void add_ambiguous_import(CDir *base, const set<CDir*>& bounds);
void cancel_ambiguous_import(dirfrag_t dirino);
void finish_ambiguous_import(dirfrag_t dirino);
- void send_import_map(int who);
- void send_import_map_now(int who);
- void send_import_map_later(int who);
- void send_pending_import_maps(); // maybe.
- void log_import_map(Context *onsync=0);
- void _logged_import_map(off_t off);
+ void send_resolve(int who);
+ void send_resolve_now(int who);
+ void send_resolve_later(int who);
+ void maybe_send_pending_resolves();
+ void log_subtree_map(Context *onsync=0);
+ void _logged_subtree_map(off_t off);
protected:
// [rejoin]
// should we log a new import_map?
// FIXME: should this go elsewhere?
- if (last_import_map && !writing_import_map &&
- journaler->get_write_pos() - last_import_map >= g_conf.mds_log_import_map_interval) {
+ if (last_subtree_map && !writing_subtree_map &&
+ journaler->get_write_pos() - last_subtree_map >= g_conf.mds_log_subtree_map_interval) {
// log import map
- mds->mdcache->log_import_map();
+ mds->mdcache->log_subtree_map();
}
} else {
num_events++;
// have we seen an import map yet?
- if (!seen_import_map &&
- le->get_type() != EVENT_IMPORTMAP) {
+ if (!seen_subtree_map &&
+ le->get_type() != EVENT_SUBTREEMAP) {
dout(10) << "_replay " << pos << " / " << journaler->get_write_pos()
- << " -- waiting for import_map. (skipping " << *le << ")" << endl;
+ << " -- waiting for subtree_map. (skipping " << *le << ")" << endl;
} else {
dout(10) << "_replay " << pos << " / " << journaler->get_write_pos()
<< " : " << *le << endl;
le->replay(mds);
- if (le->get_type() == EVENT_IMPORTMAP)
- seen_import_map = true;
+ if (le->get_type() == EVENT_SUBTREEMAP)
+ seen_subtree_map = true;
}
delete le;
-void MDLog::_replay()
-{
- mds->mds_lock.Lock();
-
- // read what's buffered
- while (journaler->is_readable() &&
- journaler->get_read_pos() < journaler->get_write_pos()) {
- // read it
- off_t pos = journaler->get_read_pos();
- bufferlist bl;
- bool r = journaler->try_read_entry(bl);
- assert(r);
-
- // unpack event
- LogEvent *le = LogEvent::decode(bl);
- num_events++;
-
- // have we seen an import map yet?
- if (!seen_import_map &&
- le->get_type() != EVENT_IMPORTMAP) {
- dout(10) << "_replay " << pos << " / " << journaler->get_write_pos()
- << " -- waiting for import_map. (skipping " << *le << ")" << endl;
- } else {
- dout(10) << "_replay " << pos << " / " << journaler->get_write_pos()
- << " : " << *le << endl;
- le->replay(mds);
-
- if (le->get_type() == EVENT_IMPORTMAP)
- seen_import_map = true;
- }
- delete le;
-
- // drop lock for a second, so other events (e.g. beacon timer!) can go off
- mds->mds_lock.Unlock();
- mds->mds_lock.Lock();
- }
-
- // wait for read?
- if (journaler->get_read_pos() < journaler->get_write_pos()) {
- journaler->wait_for_readable(new C_MDL_Replay(this));
- return;
- }
-
- // done!
- assert(journaler->get_read_pos() == journaler->get_write_pos());
- dout(10) << "_replay - complete" << endl;
-
- // move read pointer _back_ to expire pos, for eventual trimming
- journaler->set_read_pos(journaler->get_expire_pos());
-
- // kick waiter(s)
- list<Context*> ls;
- ls.swap(waitfor_replay);
- finish_contexts(ls,0);
-}
-
-
- // -- importmaps --
- off_t last_import_map; // offsets of last committed importmap. constrains trimming.
- list<Context*> import_map_expire_waiters;
- bool writing_import_map; // one is being written now
- bool seen_import_map; // for recovery
+ // -- subtreemaps --
+ off_t last_subtree_map; // offsets of last committed subtreemap. constrains trimming.
+ list<Context*> subtree_map_expire_waiters;
+ bool writing_subtree_map; // one is being written now
+ bool seen_subtree_map; // for recovery
- //friend class EImportMap;
friend class C_MDS_WroteImportMap;
friend class MDCache;
void init_journaler();
public:
- off_t get_last_import_map_offset() { return last_import_map; }
- void add_import_map_expire_waiter(Context *c) {
- import_map_expire_waiters.push_back(c);
+ off_t get_last_subtree_map_offset() { return last_subtree_map; }
+ void add_subtree_map_expire_waiter(Context *c) {
+ subtree_map_expire_waiters.push_back(c);
}
- void take_import_map_expire_waiters(list<Context*>& ls) {
- ls.splice(ls.end(), import_map_expire_waiters);
+ void take_subtree_map_expire_waiters(list<Context*>& ls) {
+ ls.splice(ls.end(), subtree_map_expire_waiters);
}
logger(0),
trim_reading(false), waiting_for_read(false),
replay_thread(this),
- last_import_map(0),
- writing_import_map(false), seen_import_map(false) {
+ last_subtree_map(0),
+ writing_subtree_map(false), seen_subtree_map(false) {
}
~MDLog();
void set_max_events(size_t max) { max_events = max; }
size_t get_max_events() { return max_events; }
size_t get_num_events() { return num_events + trimming.size(); }
- size_t get_non_importmap_events() { return num_events + trimming.size() - import_map_expire_waiters.size(); }
+ size_t get_non_subtreemap_events() { return num_events + trimming.size() - subtree_map_expire_waiters.size(); }
off_t get_read_pos();
off_t get_write_pos();
void cap() {
capped = true;
list<Context*> ls;
- ls.swap(import_map_expire_waiters);
+ ls.swap(subtree_map_expire_waiters);
finish_contexts(ls);
}
#include "common/Timer.h"
-#include "events/EClientMap.h"
#include "events/ESession.h"
#include "messages/MMDSMap.h"
// cons/des
-MDS::MDS(int whoami, Messenger *m, MonMap *mm) : timer(mds_lock) {
+MDS::MDS(int whoami, Messenger *m, MonMap *mm) :
+ timer(mds_lock),
+ clientmap(this) {
this->whoami = whoami;
monmap = mm;
for (set<int>::iterator p = resolve.begin(); p != resolve.end(); ++p) {
if (*p == whoami) continue;
if (oldresolve.count(*p)) continue;
- mdcache->send_import_map(*p); // now or later.
+ mdcache->send_resolve(*p); // now or later.
}
}
}
mdlog->reset();
mdlog->write_head(fin->new_sub());
- // write our first importmap
- mdcache->log_import_map(fin->new_sub());
+ // write our first subtreemap
+ mdcache->log_subtree_map(fin->new_sub());
// fixme: fake out idalloc (reset, pretend loaded)
dout(10) << "boot_create creating fresh idalloc table" << endl;
idalloc->reset();
idalloc->save(fin->new_sub());
+
+ // write empty clientmap
+ clientmap.save(fin->new_sub());
// fixme: fake out anchortable
if (mdsmap->get_anchortable() == whoami) {
dout(2) << "boot_start opening idalloc" << endl;
idalloc->load(fin->new_sub());
+
+ dout(2) << "boot_start opening clientmap" << endl;
+ clientmap.load(fin->new_sub());
if (mdsmap->get_anchortable() == whoami) {
dout(2) << "boot_start opening anchor table" << endl;
step = 1; // fall-thru.
case 1:
- dout(2) << "boot_replay " << step << ": opening idalloc" << endl;
- idalloc->load(new C_MDS_BootRecover(this, 2));
- break;
+ {
+ C_Gather *gather = new C_Gather(new C_MDS_BootRecover(this, 2));
+ dout(2) << "boot_replay " << step << ": opening idalloc" << endl;
+ idalloc->load(gather->new_sub());
- case 2:
- if (mdsmap->get_anchortable() == whoami) {
- dout(2) << "boot_replay " << step << ": opening anchor table" << endl;
- anchortable->load(new C_MDS_BootRecover(this, 3));
- break;
- } else {
- dout(2) << "boot_replay " << step << ": i have no anchor table" << endl;
- step++; // fall-thru
+ dout(2) << "boot_replay " << step << ": opening clientmap" << endl;
+ clientmap.load(gather->new_sub());
+
+ if (mdsmap->get_anchortable() == whoami) {
+ dout(2) << "boot_replay " << step << ": opening anchor table" << endl;
+ anchortable->load(gather->new_sub());
+ }
}
+ break;
- case 3:
+ case 2:
dout(2) << "boot_replay " << step << ": opening mds log" << endl;
- mdlog->open(new C_MDS_BootRecover(this, 4));
+ mdlog->open(new C_MDS_BootRecover(this, 3));
break;
- case 4:
+ case 3:
dout(2) << "boot_replay " << step << ": replaying mds log" << endl;
- mdlog->replay(new C_MDS_BootRecover(this, 5));
+ mdlog->replay(new C_MDS_BootRecover(this, 4));
break;
- case 5:
- // done with replay!
+ case 4:
replay_done();
break;
mdsmap->get_mds_set(who, MDSMap::STATE_STOPPING);
for (set<int>::iterator p = who.begin(); p != who.end(); ++p) {
if (*p == whoami) continue;
- mdcache->send_import_map(*p); // now.
+ mdcache->send_resolve(*p); // now.
}
}
void MDS::resolve_done()
-
-class C_LogClientmap : public Context {
- ClientMap *clientmap;
- version_t cmapv;
-public:
- C_LogClientmap(ClientMap *cm, version_t v) :
- clientmap(cm), cmapv(v) {}
- void finish(int r) {
- clientmap->set_committed(cmapv);
- list<Context*> ls;
- clientmap->take_commit_waiters(cmapv, ls);
- finish_contexts(ls);
- }
-};
-
-void MDS::log_clientmap(Context *c)
-{
- dout(10) << "log_clientmap " << clientmap.get_version() << endl;
-
- bufferlist bl;
- clientmap.encode(bl);
-
- clientmap.set_committing(clientmap.get_version());
- clientmap.add_commit_waiter(c);
-
- mdlog->submit_entry(new EClientMap(bl, clientmap.get_version()),
- new C_LogClientmap(&clientmap, clientmap.get_version()));
-}
// -- client map --
ClientMap clientmap;
epoch_t last_client_mdsmap_bcast;
- void log_clientmap(Context *c);
+ //void log_clientmap(Context *c);
// shutdown crap
export_finish_waiters.erase(dir);
// send pending import_maps? (these need to go out when all exports have finished.)
- cache->send_pending_import_maps();
+ cache->maybe_send_pending_resolves();
cache->show_subtrees();
}
p++) {
CDir *dir = mds->mdcache->get_dirfrag(p->first);
if (dir) {
- dout(10) << "importing to " << import_peer[p->first]
+ dout(10) << " importing to " << import_peer[p->first]
<< ": (" << p->second << ") " << get_import_statename(p->second)
<< " " << p->first
<< " " << *dir
<< endl;
} else {
- dout(10) << "importing to " << import_peer[p->first]
+ dout(10) << " importing to " << import_peer[p->first]
<< ": (" << p->second << ") " << get_import_statename(p->second)
<< " " << p->first
<< endl;
for (map<CDir*,int>::iterator p = export_state.begin();
p != export_state.end();
p++)
- dout(10) << "exporting to " << export_peer[p->first]
+ dout(10) << " exporting to " << export_peer[p->first]
<< ": (" << p->second << ") " << get_export_statename(p->second)
<< " " << p->first->dirfrag()
<< " " << *p->first
audit();
// send pending import_maps?
- mds->mdcache->send_pending_import_maps();
+ mds->mdcache->maybe_send_pending_resolves();
}
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software
- * Foundation. See file COPYING.
- *
- */
-
-#ifndef __MDS_ECLIENTMAP_H
-#define __MDS_ECLIENTMAP_H
-
-#include <assert.h>
-#include "config.h"
-#include "include/types.h"
-
-#include "../LogEvent.h"
-
-class EClientMap : public LogEvent {
- protected:
- bufferlist mapbl;
- version_t cmapv; // client map version
-
- public:
- EClientMap() : LogEvent(EVENT_CLIENTMAP) { }
- EClientMap(bufferlist& bl, version_t v) :
- LogEvent(EVENT_CLIENTMAP),
- cmapv(v) {
- mapbl.claim(bl);
- }
-
- void encode_payload(bufferlist& bl) {
- bl.append((char*)&cmapv, sizeof(cmapv));
- ::_encode(mapbl, bl);
- }
- void decode_payload(bufferlist& bl, int& off) {
- bl.copy(off, sizeof(cmapv), (char*)&cmapv);
- off += sizeof(cmapv);
- ::_decode(mapbl, bl, off);
- }
-
-
- void print(ostream& out) {
- out << "EClientMap v " << cmapv;
- }
-
-
- bool has_expired(MDS *mds);
- void expire(MDS *mds, Context *c);
- void replay(MDS *mds);
-
-};
-
-#endif
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software
- * Foundation. See file COPYING.
- *
- */
-
-#ifndef __MDS_EIMPORTMAP_H
-#define __MDS_EIMPORTMAP_H
-
-#include "../LogEvent.h"
-#include "EMetaBlob.h"
-
-class EImportMap : public LogEvent {
-public:
- EMetaBlob metablob;
- set<dirfrag_t> imports;
- map<dirfrag_t, set<dirfrag_t> > bounds;
-
- EImportMap() : LogEvent(EVENT_IMPORTMAP) { }
-
- void print(ostream& out) {
- out << "import_map " << imports.size() << " imports "
- << metablob;
- }
-
- void encode_payload(bufferlist& bl) {
- metablob._encode(bl);
- ::_encode(imports, bl);
- for (set<dirfrag_t>::iterator p = imports.begin();
- p != imports.end();
- ++p) {
- ::_encode(bounds[*p], bl);
- if (bounds[*p].empty())
- bounds.erase(*p);
- }
- }
- void decode_payload(bufferlist& bl, int& off) {
- metablob._decode(bl, off);
- ::_decode(imports, bl, off);
- for (set<dirfrag_t>::iterator p = imports.begin();
- p != imports.end();
- ++p) {
- ::_decode(bounds[*p], bl, off);
- if (bounds[*p].empty())
- bounds.erase(*p);
- }
- }
-
- bool has_expired(MDS *mds);
- void expire(MDS *mds, Context *c);
- void replay(MDS *mds);
-};
-
-#endif
void print(ostream& out) const {
out << "[metablob";
if (!lump_order.empty())
- out << lump_order.front() << ", " << lump_map.size() << " dirs";
+ out << " " << lump_order.front() << ", " << lump_map.size() << " dirs";
if (!atids.empty())
out << " atids=" << atids;
if (!allocated_inos.empty())
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#ifndef __MDS_ESUBTREEMAP_H
+#define __MDS_ESUBTREEMAP_H
+
+#include "../LogEvent.h"
+#include "EMetaBlob.h"
+
+class ESubtreeMap : public LogEvent {
+public:
+ EMetaBlob metablob;
+ map<dirfrag_t, list<dirfrag_t> > subtrees;
+
+ ESubtreeMap() : LogEvent(EVENT_SUBTREEMAP) { }
+
+ void print(ostream& out) {
+ out << "subtree_map " << subtrees.size() << " subtrees "
+ << metablob;
+ }
+
+ void encode_payload(bufferlist& bl) {
+ metablob._encode(bl);
+ ::_encode(subtrees, bl);
+ }
+ void decode_payload(bufferlist& bl, int& off) {
+ metablob._decode(bl, off);
+ ::_decode(subtrees, bl, off);
+ }
+
+ bool has_expired(MDS *mds);
+ void expire(MDS *mds, Context *c);
+ void replay(MDS *mds);
+};
+
+#endif
*/
#include "events/EString.h"
-#include "events/EImportMap.h"
+#include "events/ESubtreeMap.h"
#include "events/ESession.h"
-#include "events/EClientMap.h"
#include "events/EMetaBlob.h"
}
// -----------------------
-// EClientMap
-
-bool EClientMap::has_expired(MDS *mds)
-{
- if (mds->clientmap.get_committed() >= cmapv) {
- dout(10) << "EClientMap.has_expired newer clientmap " << mds->clientmap.get_committed()
- << " >= " << cmapv << " has committed" << endl;
- return true;
- } else if (mds->clientmap.get_committing() >= cmapv) {
- dout(10) << "EClientMap.has_expired newer clientmap " << mds->clientmap.get_committing()
- << " >= " << cmapv << " is still committing" << endl;
- return false;
- } else {
- dout(10) << "EClientMap.has_expired clientmap " << mds->clientmap.get_version()
- << " not empty" << endl;
- return false;
- }
-}
-
-void EClientMap::expire(MDS *mds, Context *c)
-{
- if (mds->clientmap.get_committing() >= cmapv) {
- dout(10) << "EClientMap.expire logging clientmap" << endl;
- assert(mds->clientmap.get_committing() > mds->clientmap.get_committed());
- mds->clientmap.add_commit_waiter(c);
- } else {
- dout(10) << "EClientMap.expire logging clientmap" << endl;
- mds->log_clientmap(c);
- }
-}
-
-void EClientMap::replay(MDS *mds)
-{
- dout(10) << "EClientMap.replay v " << cmapv << endl;
- int off = 0;
- mds->clientmap.decode(mapbl, off);
- mds->clientmap.set_committed(mds->clientmap.get_version());
- mds->clientmap.set_committing(mds->clientmap.get_version());
-}
-
-
// ESession
bool ESession::has_expired(MDS *mds)
{
return false;
} else {
dout(10) << "ESession.has_expired clientmap " << mds->clientmap.get_version()
- << " not empty" << endl;
+ << " > " << cmapv << ", need to save" << endl;
return false;
}
}
void ESession::expire(MDS *mds, Context *c)
-{
- if (mds->clientmap.get_committing() >= cmapv) {
- dout(10) << "ESession.expire logging clientmap" << endl;
- assert(mds->clientmap.get_committing() > mds->clientmap.get_committed());
- mds->clientmap.add_commit_waiter(c);
- } else {
- dout(10) << "ESession.expire logging clientmap" << endl;
- mds->log_clientmap(c);
- }
+{
+ dout(10) << "ESession.expire saving clientmap" << endl;
+ mds->clientmap.save(c, cmapv);
}
void ESession::replay(MDS *mds)
{
- dout(10) << "ESession.replay" << endl;
- if (open)
- mds->clientmap.open_session(client_inst);
- else
- mds->clientmap.close_session(client_inst.name.num());
- mds->clientmap.reset_projected(); // make it follow version.
+ if (mds->clientmap.get_version() >= cmapv) {
+ dout(10) << "ESession.replay clientmap " << mds->clientmap.get_version()
+ << " >= " << cmapv << ", noop" << endl;
+ } else {
+ dout(10) << "ESession.replay clientmap " << mds->clientmap.get_version()
+ << " < " << cmapv << endl;
+ assert(mds->clientmap.get_version() + 1 == cmapv);
+ if (open)
+ mds->clientmap.open_session(client_inst);
+ else
+ mds->clientmap.close_session(client_inst.name.num());
+ mds->clientmap.reset_projected(); // make it follow version.
+ }
}
// -----------------------
-// EImportMap
+// ESubtreeMap
-bool EImportMap::has_expired(MDS *mds)
+bool ESubtreeMap::has_expired(MDS *mds)
{
- if (mds->mdlog->get_last_import_map_offset() > get_start_off()) {
- dout(10) << "EImportMap.has_expired -- there's a newer map" << endl;
+ if (mds->mdlog->get_last_subtree_map_offset() > get_start_off()) {
+ dout(10) << "ESubtreeMap.has_expired -- there's a newer map" << endl;
return true;
} else if (mds->mdlog->is_capped()) {
- dout(10) << "EImportMap.has_expired -- log is capped, allowing map to expire" << endl;
+ dout(10) << "ESubtreeMap.has_expired -- log is capped, allowing map to expire" << endl;
return true;
} else {
- dout(10) << "EImportMap.has_expired -- not until there's a newer map written"
- << " (" << get_start_off() << " >= " << mds->mdlog->get_last_import_map_offset() << ")"
+ dout(10) << "ESubtreeMap.has_expired -- not until there's a newer map written"
+ << " (" << get_start_off() << " >= " << mds->mdlog->get_last_subtree_map_offset() << ")"
<< endl;
return false;
}
}
-void EImportMap::expire(MDS *mds, Context *c)
+void ESubtreeMap::expire(MDS *mds, Context *c)
{
- dout(10) << "EImportMap.has_expire -- waiting for a newer map to be written (or for shutdown)" << endl;
- mds->mdlog->add_import_map_expire_waiter(c);
+ dout(10) << "ESubtreeMap.has_expire -- waiting for a newer map to be written (or for shutdown)" << endl;
+ mds->mdlog->add_subtree_map_expire_waiter(c);
}
-void EImportMap::replay(MDS *mds)
+void ESubtreeMap::replay(MDS *mds)
{
if (mds->mdcache->is_subtrees()) {
- dout(10) << "EImportMap.replay -- ignoring, already have import map" << endl;
+ dout(10) << "ESubtreeMap.replay -- ignoring, already have import map" << endl;
} else {
- dout(10) << "EImportMap.replay -- reconstructing (auth) subtree spanning tree" << endl;
+ dout(10) << "ESubtreeMap.replay -- reconstructing (auth) subtree spanning tree" << endl;
// first, stick the spanning tree in my cache
metablob.replay(mds);
// restore import/export maps
- for (set<dirfrag_t>::iterator p = imports.begin();
- p != imports.end();
+ for (map<dirfrag_t, list<dirfrag_t> >::iterator p = subtrees.begin();
+ p != subtrees.end();
++p) {
- CDir *dir = mds->mdcache->get_dirfrag(*p);
- mds->mdcache->adjust_subtree_auth(dir, mds->get_nodeid());
+ CDir *dir = mds->mdcache->get_dirfrag(p->first);
+ mds->mdcache->adjust_bounded_subtree_auth(dir, p->second, mds->get_nodeid());
}
}
mds->mdcache->show_subtrees();
#define MDS_INO_ANCHORTABLE 3
#define MDS_INO_LOG_OFFSET 0x100
#define MDS_INO_IDS_OFFSET 0x200
-#define MDS_INO_STRAY_OFFSET 0x300
+#define MDS_INO_CLIENTMAP_OFFSET 0x300
+#define MDS_INO_STRAY_OFFSET 0x400
#define MDS_INO_BASE 0x1000
#define MDS_INO_STRAY(x) (MDS_INO_STRAY_OFFSET+((unsigned)x))
::_decode(authpinned_inodes, payload, off);
::_decode(xlocked_inodes, payload, off);
::_decode(cap_export_bl, payload, off);
- {
+ if (cap_export_bl.length()) {
int off = 0;
::_decode(cap_exports, cap_export_bl, off);
::_decode(cap_export_paths, cap_export_bl, off);
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software
- * Foundation. See file COPYING.
- *
- */
-
-#ifndef __MMDSIMPORTMAP_H
-#define __MMDSIMPORTMAP_H
-
-#include "msg/Message.h"
-
-#include "include/types.h"
-
-
-class MMDSImportMap : public Message {
- public:
- map<dirfrag_t, list<dirfrag_t> > imap;
- map<dirfrag_t, list<dirfrag_t> > ambiguous_imap;
- list<metareqid_t> slave_requests;
-
- MMDSImportMap() : Message(MSG_MDS_IMPORTMAP) {}
-
- char *get_type_name() { return "mdsimportmap"; }
-
- void print(ostream& out) {
- out << "mdsimportmap(" << imap.size()
- << "+" << ambiguous_imap.size()
- << " imports +" << slave_requests.size() << " slave requests)";
- }
-
- void add_import(dirfrag_t im) {
- imap[im].clear();
- }
- void add_import_export(dirfrag_t im, dirfrag_t ex) {
- imap[im].push_back(ex);
- }
-
- void add_ambiguous_import(dirfrag_t im, const list<dirfrag_t>& m) {
- ambiguous_imap[im] = m;
- }
-
- void add_slave_request(metareqid_t reqid) {
- slave_requests.push_back(reqid);
- }
-
- void encode_payload() {
- ::_encode(imap, payload);
- ::_encode(ambiguous_imap, payload);
- ::_encode(slave_requests, payload);
- }
- void decode_payload() {
- int off = 0;
- ::_decode(imap, payload, off);
- ::_decode(ambiguous_imap, payload, off);
- ::_decode(slave_requests, payload, off);
- }
-};
-
-#endif
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#ifndef __MMDSRESOLVE_H
+#define __MMDSRESOLVE_H
+
+#include "msg/Message.h"
+
+#include "include/types.h"
+
+class MMDSResolve : public Message {
+ public:
+ map<dirfrag_t, list<dirfrag_t> > subtrees;
+ map<dirfrag_t, list<dirfrag_t> > ambiguous_imports;
+ list<metareqid_t> slave_requests;
+
+ MMDSResolve() : Message(MSG_MDS_RESOLVE) {}
+
+ char *get_type_name() { return "mds_resolve"; }
+
+ void print(ostream& out) {
+ out << "mds_resolve(" << subtrees.size()
+ << "+" << ambiguous_imports.size()
+ << " subtrees +" << slave_requests.size() << " slave requests)";
+ }
+
+ void add_subtree(dirfrag_t im) {
+ subtrees[im].clear();
+ }
+ void add_subtree_bound(dirfrag_t im, dirfrag_t ex) {
+ subtrees[im].push_back(ex);
+ }
+
+ void add_ambiguous_import(dirfrag_t im, const list<dirfrag_t>& m) {
+ ambiguous_imports[im] = m;
+ }
+
+ void add_slave_request(metareqid_t reqid) {
+ slave_requests.push_back(reqid);
+ }
+
+ void encode_payload() {
+ ::_encode(subtrees, payload);
+ ::_encode(ambiguous_imports, payload);
+ ::_encode(slave_requests, payload);
+ }
+ void decode_payload() {
+ int off = 0;
+ ::_decode(subtrees, payload, off);
+ ::_decode(ambiguous_imports, payload, off);
+ ::_decode(slave_requests, payload, off);
+ }
+};
+
+#endif
#include "messages/MMDSGetMap.h"
#include "messages/MMDSMap.h"
#include "messages/MMDSBeacon.h"
-#include "messages/MMDSImportMap.h"
+#include "messages/MMDSResolve.h"
#include "messages/MMDSResolveAck.h"
#include "messages/MMDSCacheRejoin.h"
//#include "messages/MMDSCacheRejoinAck.h"
case MSG_MDS_BEACON:
m = new MMDSBeacon;
break;
- case MSG_MDS_IMPORTMAP:
- m = new MMDSImportMap;
+ case MSG_MDS_RESOLVE:
+ m = new MMDSResolve;
break;
case MSG_MDS_RESOLVEACK:
m = new MMDSResolveAck;
#define MSG_MDS_HEARTBEAT 104 // for mds load balancer
#define MSG_MDS_BEACON 105 // to monitor
-#define MSG_MDS_IMPORTMAP 106
+#define MSG_MDS_RESOLVE 106
#define MSG_MDS_RESOLVEACK 107
#define MSG_MDS_CACHEREJOIN 108