X-Git-Url: http://xvm.mit.edu/gitweb/invirt/third/libt4.git/blobdiff_plain/a5f10a497bebfc680bf418193f1fd9f1ad7cc417..f0dcb6b97d6d40f67698d1f71ac26970f1776f82:/handle.cc diff --git a/handle.cc b/handle.cc index 5287a35..792ce40 100644 --- a/handle.cc +++ b/handle.cc @@ -2,103 +2,50 @@ class hinfo { public: - rpcc *cl = nullptr; - int refcnt = 0; - bool del = false; - string m; + unique_ptr client; + bool valid = true; + string destination; mutex client_mutex; - hinfo(const string & m_) : m(m_) {} + hinfo(const string & destination_) : destination(destination_) {} }; -class handle_mgr { - private: - mutex mgr_mutex; - map hmap; - void delete_handle(const string & m, lock & handle_mutex_lock); - public: - hinfo *acquire_handle(string m); - void release_handle(hinfo *h); - void delete_handle(const string & m); -}; - -static handle_mgr mgr; +static mutex mgr_mutex; +static map> hmap; -handle::handle(const string & m) : h(mgr.acquire_handle(m)) {} +handle::handle(const string & destination) : destination_(destination) { + lock ml(mgr_mutex); + h = hmap[destination]; + if (!h || !h->valid) + h = (hmap[destination] = make_shared(destination)); +} rpcc * handle::safebind() { if (!h) return nullptr; - lock ml(h->client_mutex); - if (h->del) + lock cl(h->client_mutex); + if (!h->valid) return nullptr; - if (h->cl) - return h->cl; - rpcc *cl = new rpcc(h->m); - LOG("trying to bind..." << h->m); - // The test script assumes that the failure can be detected by paxos and - // rsm layer within few seconds. We have to set the timeout with a small - // value to support the assumption. - // - // With RPC_LOSSY=5, tests may fail due to delays and time outs. - int ret = cl->bind(rpcc::to(1000)); - if (ret < 0) { - LOG("bind failure! " << h->m << " " << ret); - delete cl; - h->del = true; - } else { - LOG("bind succeeded " << h->m); - h->cl = cl; - } - return h->cl; -} - -handle::~handle() { - if (h) mgr.release_handle(h); -} - -hinfo * handle_mgr::acquire_handle(string m) { - lock ml(mgr_mutex); - hinfo *h = nullptr; - if (hmap.find(m) == hmap.end()) { - h = new hinfo(m); - hmap[m] = h; - h->refcnt++; - } else if (!hmap[m]->del) { - h = hmap[m]; - h->refcnt++; + if (!h->client) { + unique_ptr client(new rpcc(h->destination)); + LOG("bind(\"" << h->destination << "\")"); + int ret = client->bind(milliseconds(1000)); + if (ret < 0) { + LOG("bind failure! " << h->destination << " " << ret); + h->valid = false; + } else { + LOG("bind succeeded " << h->destination); + h->client = move(client); + } } - return h; + return h->client.get(); } -void handle_mgr::release_handle(hinfo *h) { +void handle::invalidate() { + h.reset(); lock ml(mgr_mutex); - if (--h->refcnt == 0 && h->del) - delete_handle(h->m, ml); -} - -void handle_mgr::delete_handle(const string & m) { - lock ml(mgr_mutex); - delete_handle(m, ml); -} - -void handle_mgr::delete_handle(const string & m, lock &) { - if (hmap.find(m) == hmap.end()) { - LOG("cl " << m << " isn't in cl list"); - return; + if (hmap.find(destination_) != hmap.end()) { + hmap[destination_]->valid = false; + LOG_NONMEMBER("cl " << destination_ << " refcnt " << hmap[destination_].use_count()); + hmap.erase(destination_); } - LOG("cl " << m << " refcnt " << hmap[m]->refcnt); - hinfo *h = hmap[m]; - if (h->refcnt == 0) { - if (h->cl) { - h->cl->cancel(); - delete h->cl; - } - hmap.erase(m); - delete h; - } else - h->del = true; -} - -void invalidate_handle(const string & m) { - mgr.delete_handle(m); }