42d038f73783a631415925199ad0812383eb42e1
[invirt/third/libt4.git] / handle.cc
1 #include "handle.h"
2
3 class hinfo {
4 public:
5     unique_ptr<rpcc> cl;
6     bool del = false;
7     string m;
8     mutex client_mutex;
9     hinfo(const string & m_) : m(m_) {}
10 };
11
12 static mutex mgr_mutex;
13 static map<string, shared_ptr<hinfo>> hmap;
14
15 static shared_ptr<hinfo> acquire_handle(string m) {
16     lock ml(mgr_mutex);
17     shared_ptr<hinfo> h = hmap[m];
18     if (!h || h->del)
19         return (hmap[m] = make_shared<hinfo>(m));
20     return h;
21 }
22
23 static void delete_handle(const string & m, lock &) {
24     if (hmap.find(m) == hmap.end()) {
25         LOG_NONMEMBER("cl " << m << " isn't in cl list");
26         return;
27     }
28
29     hmap[m]->del = true;
30     LOG_NONMEMBER("cl " << m << " refcnt " << hmap[m].use_count());
31     hmap.erase(m);
32 }
33
34 void invalidate_handle(const string & m) {
35     lock ml(mgr_mutex);
36     delete_handle(m, ml);
37 }
38
39 handle::handle(const string & m) : h(acquire_handle(m)) {}
40
41 rpcc * handle::safebind() {
42     if (!h)
43         return nullptr;
44     lock ml(h->client_mutex);
45     if (h->del)
46         return nullptr;
47     if (!h->cl) {
48         unique_ptr<rpcc> cl(new rpcc(h->m));
49         LOG("trying to bind..." << h->m);
50         // The test script assumes that the failure can be detected by paxos and
51         // rsm layer within few seconds. We have to set the timeout with a small
52         // value to support the assumption.
53         // 
54         // With RPC_LOSSY=5, tests may fail due to delays and time outs.
55         int ret = cl->bind(milliseconds(1000));
56         if (ret < 0) {
57             LOG("bind failure! " << h->m << " " << ret);
58             h->del = true;
59         } else {
60             LOG("bind succeeded " << h->m);
61             h->cl = move(cl);
62         }
63     }
64     return h->cl.get();
65 }