Imported from 6.824 labs
[invirt/third/libt4.git] / handle.cc
1 #include "handle.h"
2 #include <stdio.h>
3 #include "tprintf.h"
4
5 handle_mgr mgr;
6
7 handle::handle(std::string m) 
8 {
9   h = mgr.get_handle(m);
10 }
11
12 rpcc *
13 handle::safebind()
14 {
15   if (!h)
16     return NULL;
17   ScopedLock ml(&h->cl_mutex);
18   if (h->del)
19     return NULL;
20   if (h->cl)
21     return h->cl;
22   sockaddr_in dstsock;
23   make_sockaddr(h->m.c_str(), &dstsock);
24   rpcc *cl = new rpcc(dstsock);
25   tprintf("handler_mgr::get_handle trying to bind...%s\n", h->m.c_str());
26   int ret;
27   // Starting with lab 6, our test script assumes that the failure
28   // can be detected by paxos and rsm layer within few seconds. We have
29   // to set the timeout with a small value to support the assumption.
30   // 
31   // Note: with RPC_LOSSY=5, your lab would failed to pass the tests of
32   // lab 6 and lab 7 because the rpc layer may delay your RPC request, 
33   // and cause a time out failure. Please make sure RPC_LOSSY is set to 0.
34   ret = cl->bind(rpcc::to(1000));
35   if (ret < 0) {
36     tprintf("handle_mgr::get_handle bind failure! %s %d\n", h->m.c_str(), ret);
37     delete cl;
38     h->del = true;
39   } else {
40     tprintf("handle_mgr::get_handle bind succeeded %s\n", h->m.c_str());
41     h->cl = cl;
42   }
43   return h->cl;
44 }
45
46 handle::~handle() 
47 {
48   if (h) mgr.done_handle(h);
49 }
50
51 handle_mgr::handle_mgr()
52 {
53   VERIFY (pthread_mutex_init(&handle_mutex, NULL) == 0);
54 }
55
56 struct hinfo *
57 handle_mgr::get_handle(std::string m)
58 {
59   ScopedLock ml(&handle_mutex);
60   struct hinfo *h = 0;
61   if (hmap.find(m) == hmap.end()) {
62     h = new hinfo;
63     h->cl = NULL;
64     h->del = false;
65     h->refcnt = 1;
66     h->m = m;
67     pthread_mutex_init(&h->cl_mutex, NULL);
68     hmap[m] = h;
69   } else if (!hmap[m]->del) {
70     h = hmap[m];
71     h->refcnt ++;
72   }
73   return h;
74 }
75
76 void 
77 handle_mgr::done_handle(struct hinfo *h)
78 {
79   ScopedLock ml(&handle_mutex);
80   h->refcnt--;
81   if (h->refcnt == 0 && h->del)
82     delete_handle_wo(h->m);
83 }
84
85 void
86 handle_mgr::delete_handle(std::string m)
87 {
88   ScopedLock ml(&handle_mutex);
89   delete_handle_wo(m);
90 }
91
92 // Must be called with handle_mutex locked.
93 void
94 handle_mgr::delete_handle_wo(std::string m)
95 {
96   if (hmap.find(m) == hmap.end()) {
97     tprintf("handle_mgr::delete_handle_wo: cl %s isn't in cl list\n", m.c_str());
98   } else {
99     tprintf("handle_mgr::delete_handle_wo: cl %s refcnt %d\n", m.c_str(),
100            hmap[m]->refcnt);
101     struct hinfo *h = hmap[m];
102     if (h->refcnt == 0) {
103       if (h->cl) {
104         h->cl->cancel();
105         delete h->cl;
106       }
107       pthread_mutex_destroy(&h->cl_mutex);
108       hmap.erase(m);
109       delete h;
110     } else {
111       h->del = true;
112     }
113   }
114 }