Imported from 6.824 labs
[invirt/third/libt4.git] / rsm_client.h
1 #ifndef rsm_client_h
2 #define rsm_client_h
3
4 #include "rpc.h"
5 #include "rsm_protocol.h"
6 #include <string>
7 #include <vector>
8
9
10 //
11 // rsm client interface.
12 //
13 // The client stubs package up an rpc, and then call the invoke procedure
14 // on the replicated state machine passing the RPC as an argument.  This way
15 // the replicated state machine isn't service specific; any server can use it.
16 //
17
18 class rsm_client {
19     protected:
20         std::string primary;
21         std::vector<std::string> known_mems;
22         pthread_mutex_t rsm_client_mutex;
23         void primary_failure();
24         bool init_members();
25     public:
26         rsm_client(std::string dst);
27         rsm_protocol::status invoke(int proc, std::string req, std::string &rep);
28
29         template<class R, class A1>
30             int call(unsigned int proc, const A1 & a1, R &r);
31
32         template<class R, class A1, class A2>
33             int call(unsigned int proc, const A1 & a1, const A2 & a2, R &r);
34
35         template<class R, class A1, class A2, class A3>
36             int call(unsigned int proc, const A1 & a1, const A2 & a2, const A3 & a3,
37                     R &r);
38
39         template<class R, class A1, class A2, class A3, class A4>
40             int call(unsigned int proc, const A1 & a1, const A2 & a2, const A3 & a3,
41                     const A4 & a4, R &r);
42
43         template<class R, class A1, class A2, class A3, class A4, class A5>
44             int call(unsigned int proc, const A1 & a1, const A2 & a2, const A3 & a3,
45                     const A4 & a4, const A5 & a5, R &r);
46     private:
47         template<class R> int call_m(unsigned int proc, marshall &req, R &r);
48 };
49
50 template<class R>
51 int rsm_client::call_m(unsigned int proc, marshall &req, R &r) {
52         std::string rep;
53         std::string res;
54         int intret = invoke(proc, req.str(), rep);
55         VERIFY( intret == rsm_client_protocol::OK );
56         unmarshall u(rep);
57         u >> intret;
58         if (intret < 0) return intret;
59         u >> res;
60         if (!u.okdone()) {
61                 fprintf(stderr, "rsm_client::call_m: failed to unmarshall the reply.\n"
62                        "You probably forgot to set the reply string in "
63                        "rsm::client_invoke, or you may call RPC 0x%x with wrong return "
64                        "type\n", proc);
65                 VERIFY(0);
66                 return rpc_const::unmarshal_reply_failure;
67         }
68         unmarshall u1(res);
69         u1 >> r;
70         if(!u1.okdone()) {
71                 fprintf(stderr, "rsm_client::call_m: failed to unmarshall the reply.\n"
72                        "You are probably calling RPC 0x%x with wrong return "
73                        "type.\n", proc);
74                 VERIFY(0);
75                 return rpc_const::unmarshal_reply_failure;
76         }
77         return intret;
78 }
79
80 template<class R, class A1>
81 int rsm_client::call(unsigned int proc, const A1 & a1, R & r) {
82     marshall m;
83     m << a1;
84     return call_m(proc, m, r);
85 }
86
87 template<class R, class A1, class A2>
88 int rsm_client::call(unsigned int proc, const A1 & a1, const A2 & a2, R & r) {
89     marshall m;
90     m << a1;
91     m << a2;
92     return call_m(proc, m, r);
93 }
94
95 template<class R, class A1, class A2, class A3>
96 int rsm_client::call(unsigned int proc, const A1 & a1, const A2 & a2, const A3 & a3, R & r) {
97     marshall m;
98     std::string rep;
99     std::string res;
100     m << a1;
101     m << a2;
102     m << a3;
103     return call_m(proc, m, r);
104 }
105
106 template<class R, class A1, class A2, class A3, class A4>
107 int rsm_client::call(unsigned int proc, const A1 & a1, const A2 & a2, const A3 & a3, const A4 & a4, R & r) {
108     marshall m;
109     std::string rep;
110     std::string res;
111     m << a1;
112     m << a2;
113     m << a3;
114     m << a4;
115     return call_m(proc, m, r);
116 }
117
118 template<class R, class A1, class A2, class A3, class A4, class A5>
119 int rsm_client::call(unsigned int proc, const A1 & a1, const A2 & a2, const A3 & a3, const A4 & a4, const A5 & a5, R & r) {
120     marshall m;
121     std::string rep;
122     std::string res;
123     m << a1;
124     m << a2;
125     m << a3;
126     m << a4;
127     m << a5;
128     return call_m(proc, m, r);
129 }
130
131 #endif