#include "handle.h"
-#include <stdio.h>
-#include "tprintf.h"
+#include "threaded_log.h"
#include "lock.h"
+#include <map>
-handle_mgr mgr;
+using std::map;
-handle::handle(std::string m)
-{
- h = mgr.get_handle(m);
-}
+class hinfo {
+public:
+ rpcc *cl = nullptr;
+ int refcnt = 0;
+ bool del = false;
+ string m;
+ mutex client_mutex;
+ hinfo(const string & m_) : m(m_) {}
+};
+
+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;
-rpcc *
-handle::safebind()
-{
+handle::handle(const string & m) : h(mgr.acquire_handle(m)) {}
+
+rpcc * handle::safebind() {
if (!h)
- return NULL;
- lock ml(h->cl_mutex);
+ return nullptr;
+ lock ml(h->client_mutex);
if (h->del)
- return NULL;
+ return nullptr;
if (h->cl)
return h->cl;
- sockaddr_in dstsock;
- make_sockaddr(h->m.c_str(), &dstsock);
- rpcc *cl = new rpcc(dstsock);
- tprintf("handler_mgr::get_handle trying to bind...%s\n", h->m.c_str());
- int ret;
+ rpcc *cl = new rpcc(h->m);
+ LOG("handler_mgr::acquire_handle 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.
- ret = cl->bind(rpcc::to(1000));
+ int ret = cl->bind(rpcc::to(1000));
if (ret < 0) {
- tprintf("handle_mgr::get_handle bind failure! %s %d\n", h->m.c_str(), ret);
+ LOG("handle_mgr::acquire_handle bind failure! " << h->m << " " << ret);
delete cl;
h->del = true;
} else {
- tprintf("handle_mgr::get_handle bind succeeded %s\n", h->m.c_str());
+ LOG("handle_mgr::acquire_handle bind succeeded " << h->m);
h->cl = cl;
}
return h->cl;
}
-handle::~handle()
-{
- if (h) mgr.done_handle(h);
-}
-
-handle_mgr::handle_mgr()
-{
+handle::~handle() {
+ if (h) mgr.release_handle(h);
}
-struct hinfo *
-handle_mgr::get_handle(std::string m)
-{
- lock ml(handle_mutex);
- struct hinfo *h = 0;
+hinfo * handle_mgr::acquire_handle(string m) {
+ lock ml(mgr_mutex);
+ hinfo *h = nullptr;
if (hmap.find(m) == hmap.end()) {
- h = new hinfo;
- h->cl = NULL;
- h->del = false;
- h->refcnt = 1;
- h->m = m;
+ h = new hinfo(m);
hmap[m] = h;
} else if (!hmap[m]->del) {
h = hmap[m];
- h->refcnt ++;
}
+ h->refcnt++;
return h;
}
-void
-handle_mgr::done_handle(struct hinfo *h)
-{
- lock ml(handle_mutex);
- h->refcnt--;
- if (h->refcnt == 0 && h->del)
- delete_handle_wo(h->m);
+void handle_mgr::release_handle(hinfo *h) {
+ lock ml(mgr_mutex);
+ if (--h->refcnt == 0 && h->del)
+ delete_handle(h->m, ml);
}
-void
-handle_mgr::delete_handle(std::string m)
-{
- lock ml(handle_mutex);
- delete_handle_wo(m);
+void handle_mgr::delete_handle(const string & m) {
+ lock ml(mgr_mutex);
+ delete_handle(m, ml);
}
-// Must be called with handle_mutex locked.
-void
-handle_mgr::delete_handle_wo(std::string m)
-{
+void handle_mgr::delete_handle(const string & m, lock &) {
if (hmap.find(m) == hmap.end()) {
- tprintf("handle_mgr::delete_handle_wo: cl %s isn't in cl list\n", m.c_str());
- } else {
- tprintf("handle_mgr::delete_handle_wo: cl %s refcnt %d\n", m.c_str(),
- hmap[m]->refcnt);
- struct 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;
- }
+ LOG("handle_mgr::delete_handle: cl " << m << " isn't in cl list");
+ return;
}
+ LOG("handle_mgr::delete_handle: 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);
}