ostream& operator<<(ostream& out, ClientMonitor& om)
{
return out << "v" << om.client_map.version << ": "
- << om.client_map.client_addr.size() << " clients, next is client" << om.client_map.next_client;
+ << om.client_map.client_info.size() << " clients, next is client" << om.client_map.next_client;
}
bool ClientMonitor::update_from_paxos()
inc.decode(p);
client_map.apply_incremental(inc);
- dout(1) << client_map.client_addr.size() << " clients (+"
+ dout(1) << client_map.client_info.size() << " clients (+"
<< inc.mount.size() << " -" << inc.unmount.size() << ")"
<< dendl;
}
{
// already unmounted?
int client = m->get_orig_source().num();
- if (client_map.client_addr.count(client) == 0) {
+ if (client_map.client_info.count(client) == 0) {
dout(7) << " client" << client << " not mounted" << dendl;
_unmounted((MClientUnmount*)m);
return true;
dout(10) << "mount: assigned client" << client << " to " << addr << dendl;
} else {
dout(10) << "mount: client" << client << " requested by " << addr << dendl;
- if (client_map.client_addr.count(client)) {
- assert(client_map.client_addr[client] != addr);
+ if (client_map.client_info.count(client)) {
+ assert(client_map.client_info[client].addr != addr);
dout(0) << "mount: WARNING: client" << client << " requested by " << addr
- << ", which used to be " << client_map.client_addr[client] << dendl;
+ << ", which used to be " << client_map.client_info[client].addr << dendl;
}
}
- pending_inc.add_mount(client, addr);
+ client_info_t info;
+ info.addr = addr;
+ info.mount_time = g_clock.now();
+ pending_inc.add_mount(client, info);
paxos->wait_for_commit(new C_Mounted(this, client, (MClientMount*)m));
}
return true;
assert(m->get_orig_source().is_client());
int client = m->get_orig_source().num();
- assert(client_map.client_addr.count(client));
+ assert(client_map.client_info.count(client));
pending_inc.add_unmount(client);
paxos->wait_for_commit(new C_Unmounted(this, (MClientUnmount*)m));
else if (m->cmd[1] == "dump") {
ss << "version " << client_map.version << std::endl;
ss << "next_client " << client_map.next_client << std::endl;
- for (map<uint32_t, entity_addr_t>::iterator p = client_map.client_addr.begin();
- p != client_map.client_addr.end();
+ for (map<uint32_t, client_info_t>::iterator p = client_map.client_info.begin();
+ p != client_map.client_info.end();
p++) {
- ss << "client" << p->first << "\t" << p->second << std::endl;
+ ss << "client" << p->first
+ << "\t" << p->second.addr
+ << "\t" << p->second.mount_time
+ << std::endl;
}
while (!ss.eof()) {
string s;
// (hack for fakesyn/newsyn, mostly)
if (mon->is_leader() &&
client_map.version > 1 &&
- client_map.client_addr.empty() &&
+ client_map.client_info.empty() &&
g_conf.mon_stop_on_last_unmount &&
!mon->is_stopping()) {
dout(1) << "last client unmounted" << dendl;
class MClientUnmount;
class MMonCommand;
+
+struct client_info_t {
+ entity_addr_t addr;
+ utime_t mount_time;
+
+ void encode(bufferlist& bl) const {
+ ::encode(addr, bl);
+ ::encode(mount_time, bl);
+ }
+ void decode(bufferlist::iterator& bl) {
+ ::decode(addr, bl);
+ ::decode(mount_time, bl);
+ }
+};
+WRITE_CLASS_ENCODER(client_info_t)
+
+
class ClientMonitor : public PaxosService {
public:
struct Incremental {
version_t version;
uint32_t next_client;
- map<int32_t, entity_addr_t> mount;
+ map<int32_t, client_info_t> mount;
set<int32_t> unmount;
Incremental() : version(0), next_client() {}
bool is_empty() { return mount.empty() && unmount.empty(); }
- void add_mount(uint32_t client, entity_addr_t addr) {
+ void add_mount(uint32_t client, client_info_t& info) {
next_client = MAX(next_client, client+1);
- mount[client] = addr;
+ mount[client] = info;
}
void add_unmount(uint32_t client) {
assert(client < next_client);
struct Map {
version_t version;
uint32_t next_client;
- map<uint32_t,entity_addr_t> client_addr;
- map<entity_addr_t,uint32_t> addr_client;
+ map<uint32_t,client_info_t> client_info;
+ map<entity_addr_t,uint32_t> addr_client; // reverse map
Map() : version(0), next_client(0) {}
void reverse() {
addr_client.clear();
- for (map<uint32_t,entity_addr_t>::iterator p = client_addr.begin();
- p != client_addr.end();
+ for (map<uint32_t,client_info_t>::iterator p = client_info.begin();
+ p != client_info.end();
++p) {
- addr_client[p->second] = p->first;
+ addr_client[p->second.addr] = p->first;
}
}
void apply_incremental(Incremental &inc) {
assert(inc.version == version+1);
version = inc.version;
next_client = inc.next_client;
- for (map<int32_t,entity_addr_t>::iterator p = inc.mount.begin();
+ for (map<int32_t,client_info_t>::iterator p = inc.mount.begin();
p != inc.mount.end();
++p) {
- client_addr[p->first] = p->second;
- addr_client[p->second] = p->first;
+ client_info[p->first] = p->second;
+ addr_client[p->second.addr] = p->first;
}
for (set<int32_t>::iterator p = inc.unmount.begin();
p != inc.unmount.end();
++p) {
- assert(client_addr.count(*p));
- addr_client.erase(client_addr[*p]);
- client_addr.erase(*p);
+ assert(client_info.count(*p));
+ addr_client.erase(client_info[*p].addr);
+ client_info.erase(*p);
}
}
void encode(bufferlist &bl) const {
::encode(version, bl);
::encode(next_client, bl);
- ::encode(client_addr, bl);
+ ::encode(client_info, bl);
}
void decode(bufferlist::iterator &bl) {
::decode(version, bl);
::decode(next_client, bl);
- ::decode(client_addr, bl);
+ ::decode(client_info, bl);
reverse();
}
};