Cosmetic improvements.
[invirt/third/libt4.git] / handle.cc
index ff38a56..792ce40 100644 (file)
--- a/handle.cc
+++ b/handle.cc
 #include "handle.h"
-#include <stdio.h>
-#include "tprintf.h"
-#include "lock.h"
 
-handle_mgr mgr;
+class hinfo {
+public:
+    unique_ptr<rpcc> client;
+    bool valid = true;
+    string destination;
+    mutex client_mutex;
+    hinfo(const string & destination_) : destination(destination_) {}
+};
 
-handle::handle(std::string m) 
-{
-    h = mgr.get_handle(m);
-}
-
-rpcc *
-handle::safebind()
-{
-    if (!h)
-        return NULL;
-    lock ml(h->cl_mutex);
-    if (h->del)
-        return NULL;
-    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;
-    // 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));
-    if (ret < 0) {
-        tprintf("handle_mgr::get_handle bind failure! %s %d\n", h->m.c_str(), ret);
-        delete cl;
-        h->del = true;
-    } else {
-        tprintf("handle_mgr::get_handle bind succeeded %s\n", h->m.c_str());
-        h->cl = cl;
-    }
-    return h->cl;
-}
-
-handle::~handle() 
-{
-    if (h) mgr.done_handle(h);
-}
+static mutex mgr_mutex;
+static map<string, shared_ptr<hinfo>> hmap;
 
-handle_mgr::handle_mgr()
-{
+handle::handle(const string & destination) : destination_(destination) {
+    lock ml(mgr_mutex);
+    h = hmap[destination];
+    if (!h || !h->valid)
+        h = (hmap[destination] = make_shared<hinfo>(destination));
 }
 
-struct hinfo *
-handle_mgr::get_handle(std::string m)
-{
-    lock ml(handle_mutex);
-    struct hinfo *h = 0;
-    if (hmap.find(m) == hmap.end()) {
-        h = new hinfo;
-        h->cl = NULL;
-        h->del = false;
-        h->refcnt = 1;
-        h->m = m;
-        hmap[m] = h;
-    } else if (!hmap[m]->del) {
-        h = hmap[m];
-        h->refcnt ++;
+rpcc * handle::safebind() {
+    if (!h)
+        return nullptr;
+    lock cl(h->client_mutex);
+    if (!h->valid)
+        return nullptr;
+    if (!h->client) {
+        unique_ptr<rpcc> 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;
-}
-
-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);
+    return h->client.get();
 }
 
-void
-handle_mgr::delete_handle(std::string m)
-{
-    lock ml(handle_mutex);
-    delete_handle_wo(m);
-}
-
-// Must be called with handle_mutex locked.
-void
-handle_mgr::delete_handle_wo(std::string m)
-{
-    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;
-        }
+void handle::invalidate() {
+    h.reset();
+    lock ml(mgr_mutex);
+    if (hmap.find(destination_) != hmap.end()) {
+        hmap[destination_]->valid = false;
+        LOG_NONMEMBER("cl " << destination_ << " refcnt " << hmap[destination_].use_count());
+        hmap.erase(destination_);
     }
 }