MOAR TEMPLATE MAGIC
[invirt/third/libt4.git] / rsm_client.h
1 #ifndef rsm_client_h
2 #define rsm_client_h
3
4 #include "types.h"
5 #include "rsm_protocol.h"
6
7 //
8 // rsm client interface.
9 //
10 // The client stubs package up an rpc, and then call the invoke procedure
11 // on the replicated state machine passing the RPC as an argument.  This way
12 // the replicated state machine isn't service specific; any server can use it.
13 //
14
15 class rsm_client {
16     protected:
17         std::string primary;
18         std::vector<std::string> known_mems;
19         std::mutex rsm_client_mutex;
20         void primary_failure(lock & rsm_client_mutex_lock);
21         bool init_members(lock & rsm_client_mutex_lock);
22     public:
23         rsm_client(std::string dst);
24         rsm_protocol::status invoke(unsigned int proc, std::string &rep, const std::string &req);
25
26         template<class R, class ...Args>
27             int call(unsigned int proc, R & r, const Args & ...a1);
28     private:
29         template<class R> int call_m(unsigned int proc, R & r, const marshall & req);
30 };
31
32 template<class R>
33 int rsm_client::call_m(unsigned int proc, R & r, const marshall & req) {
34     std::string rep;
35     std::string res;
36     int intret = invoke(proc, rep, req.cstr());
37     VERIFY( intret == rsm_client_protocol::OK );
38     unmarshall u(rep);
39     u >> intret;
40     if (intret < 0) return intret;
41     u >> res;
42     if (!u.okdone()) {
43         cerr << "rsm_client::call_m: failed to unmarshall the reply." << endl;
44         cerr << "You probably forgot to set the reply string in "
45                 "rsm::client_invoke, or you may have called RPC 0x" << hex <<
46                 proc << " with the wrong return type" << endl;
47         VERIFY(0);
48         return rpc_const::unmarshal_reply_failure;
49     }
50     unmarshall u1(res);
51     u1 >> r;
52     if(!u1.okdone()) {
53         cerr << "rsm_client::call_m: failed to unmarshall the reply." << endl;
54         cerr << "You are probably calling RPC 0x" << hex << proc <<
55                 " with the wrong return type." << endl;
56         VERIFY(0);
57         return rpc_const::unmarshal_reply_failure;
58     }
59     return intret;
60 }
61
62 template<class R, class ...Args>
63 int rsm_client::call(unsigned int proc, R & r, const Args & ...a1) {
64     return call_m(proc, r, marshall{a1...});
65 }
66
67 #endif