Lots more clean-ups
[invirt/third/libt4.git] / handle.cc
1 #include "handle.h"
2
3 class hinfo {
4 public:
5     rpcc *cl = nullptr;
6     int refcnt = 0;
7     bool del = false;
8     string m;
9     mutex client_mutex;
10     hinfo(const string & m_) : m(m_) {}
11 };
12
13 class handle_mgr {
14     private:
15         mutex mgr_mutex;
16         map<string, hinfo *> hmap;
17         void delete_handle(const string & m, lock & handle_mutex_lock);
18     public:
19         hinfo *acquire_handle(string m);
20         void release_handle(hinfo *h);
21         void delete_handle(const string & m);
22 };
23
24 static handle_mgr mgr;
25
26 handle::handle(const string & m) : h(mgr.acquire_handle(m)) {}
27
28 rpcc * handle::safebind() {
29     if (!h)
30         return nullptr;
31     lock ml(h->client_mutex);
32     if (h->del)
33         return nullptr;
34     if (h->cl)
35         return h->cl;
36     rpcc *cl = new rpcc(h->m);
37     LOG("trying to bind..." << h->m);
38     // The test script assumes that the failure can be detected by paxos and
39     // rsm layer within few seconds. We have to set the timeout with a small
40     // value to support the assumption.
41     // 
42     // With RPC_LOSSY=5, tests may fail due to delays and time outs.
43     int ret = cl->bind(milliseconds(1000));
44     if (ret < 0) {
45         LOG("bind failure! " << h->m << " " << ret);
46         delete cl;
47         h->del = true;
48     } else {
49         LOG("bind succeeded " << h->m);
50         h->cl = cl;
51     }
52     return h->cl;
53 }
54
55 handle::~handle() {
56     if (h) mgr.release_handle(h);
57 }
58
59 hinfo * handle_mgr::acquire_handle(string m) {
60     lock ml(mgr_mutex);
61     hinfo *h = nullptr;
62     if (hmap.find(m) == hmap.end()) {
63         h = new hinfo(m);
64         hmap[m] = h;
65         h->refcnt++;
66     } else if (!hmap[m]->del) {
67         h = hmap[m];
68         h->refcnt++;
69     }
70     return h;
71 }
72
73 void handle_mgr::release_handle(hinfo *h) {
74     lock ml(mgr_mutex);
75     if (--h->refcnt == 0 && h->del)
76         delete_handle(h->m, ml);
77 }
78
79 void handle_mgr::delete_handle(const string & m) {
80     lock ml(mgr_mutex);
81     delete_handle(m, ml);
82 }
83
84 void handle_mgr::delete_handle(const string & m, lock &) {
85     if (hmap.find(m) == hmap.end()) {
86         LOG("cl " << m << " isn't in cl list");
87         return;
88     }
89     LOG("cl " << m << " refcnt " << hmap[m]->refcnt);
90     hinfo *h = hmap[m];
91     if (h->refcnt == 0) {
92         if (h->cl) {
93             h->cl->cancel();
94             delete h->cl;
95         }
96         hmap.erase(m);
97         delete h;
98     } else
99         h->del = true;
100 }
101
102 void invalidate_handle(const string & m) {
103     mgr.delete_handle(m);
104 }