class hinfo {
public:
- rpcc *cl = nullptr;
- int refcnt = 0;
- bool del = false;
- string m;
+ unique_ptr<rpcc> 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<string, hinfo *> 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<string, shared_ptr<hinfo>> hmap;
-handle::handle(const string & m) : h(mgr.acquire_handle(m)) {}
+handle::handle(const string & destination) {
+ lock ml(mgr_mutex);
+ h = hmap[destination];
+ if (!h || !h->valid)
+ h = (hmap[destination] = make_shared<hinfo>(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(milliseconds(1000));
- if (ret < 0) {
- LOG("bind failure! " << h->m << " " << ret);
- delete cl;
- h->del = true;
- } else {
- LOG("bind succeeded " << h->m);
- h->cl = cl;
+ if (!h->client) {
+ unique_ptr<rpcc> client(new rpcc(h->destination));
+ LOG("trying to bind..." << h->destination);
+ // 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 = 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->cl;
+ return h->client.get();
}
-handle::~handle() {
- if (h) mgr.release_handle(h);
-}
+void handle::invalidate() {
+ {
+ lock cl(h->client_mutex);
+ h->valid = false;
-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++;
+ LOG_NONMEMBER("cl " << h->destination << " refcnt " << h.use_count());
}
- return h;
-}
-
-void handle_mgr::release_handle(hinfo *h) {
lock ml(mgr_mutex);
- if (--h->refcnt == 0 && h->del)
- delete_handle(h->m, ml);
+ hmap.erase(h->destination);
+ h = nullptr;
}
-void handle_mgr::delete_handle(const string & m) {
+void invalidate_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");
+ LOG_NONMEMBER("cl " << m << " isn't in cl list");
return;
}
- 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);
+ hmap[m]->valid = false;
+ LOG_NONMEMBER("cl " << m << " refcnt " << hmap[m].use_count());
+ hmap.erase(m);
}