Robust Distributed System Nucleus (rDSN)  ver 1.0.0
serverlet.h
1 /*
2  * The MIT License (MIT)
3  *
4  * Copyright (c) 2015 Microsoft Corporation
5  *
6  * -=- Robust Distributed System Nucleus (rDSN) -=-
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26 
27 /*
28  * Description:
29  * What is this file about?
30  *
31  * Revision history:
32  * xxxx-xx-xx, author, first version
33  * xxxx-xx-xx, author, fix bug about xxx
34  */
35 
36 # pragma once
37 
38 # include <dsn/cpp/clientlet.h>
39 # include <dsn/cpp/service_app.h>
40 
41 namespace dsn
42 {
48  //
49  // for TRequest/TResponse, we assume that the following routines are defined:
50  // marshall(binary_writer& writer, const T& val);
51  // unmarshall(binary_reader& reader, /*out*/ T& val);
52  // either in the namespace of ::dsn or T
53  // developers may write these helper functions by their own, or use tools
54  // such as protocol-buffer, thrift, or bond to generate these functions automatically
55  // for their TRequest and TResponse
56  //
57 
58  template <typename TResponse>
60  {
61  public:
62  rpc_replier(dsn_message_t response)
63  {
64  _response = response;
65  }
66 
67  rpc_replier(const rpc_replier& r)
68  {
69  _response = r._response;
70  }
71 
72  void operator () (const TResponse& resp)
73  {
74  if (_response != nullptr)
75  {
76  ::dsn::marshall(_response, resp);
77  dsn_rpc_reply(_response);
78  }
79  }
80 
81  bool is_empty() const
82  {
83  return _response == nullptr;
84  }
85 
86  private:
87  dsn_message_t _response;
88  };
89 
90  template <typename T> // where T : serverlet<T>
91  class serverlet : public virtual clientlet
92  {
93  public:
94  serverlet(const char* nm, int task_bucket_count = 8);
95  virtual ~serverlet();
96 
97  protected:
98  template<typename TRequest>
99  bool register_rpc_handler(dsn_task_code_t rpc_code, const char* rpc_name_, void (T::*handler)(const TRequest&), dsn_gpid gpid = dsn_gpid{ 0 });
100 
101  template<typename TRequest, typename TResponse>
102  bool register_rpc_handler(dsn_task_code_t rpc_code, const char* rpc_name_, void (T::*handler)(const TRequest&, TResponse&), dsn_gpid gpid = dsn_gpid{ 0 });
103 
104  template<typename TRequest, typename TResponse>
105  bool register_async_rpc_handler(dsn_task_code_t rpc_code, const char* rpc_name_, void (T::*handler)(const TRequest&, rpc_replier<TResponse>&), dsn_gpid gpid = dsn_gpid{ 0 });
106 
107  bool register_rpc_handler(dsn_task_code_t rpc_code, const char* rpc_name_, void (T::*handler)(dsn_message_t), dsn_gpid gpid = dsn_gpid{ 0 });
108 
109  bool unregister_rpc_handler(dsn_task_code_t rpc_code, dsn_gpid gpid = dsn_gpid{ 0 });
110 
111  template<typename TResponse>
112  void reply(dsn_message_t request, const TResponse& resp);
113 
114  public:
115  const std::string& name() const { return _name; }
116 
117  private:
118  template<typename TCallback>
119  struct handler_context
120  {
121  T *this_;
122  TCallback cb;
123  };
124 
125  std::string _name;
126  };
127 
128  // ------------- inline implementation ----------------
129  template<typename T>
130  inline serverlet<T>::serverlet(const char* nm, int task_bucket_count)
131  : clientlet(task_bucket_count), _name(nm)
132  {
133  }
134 
135  template<typename T>
136  inline serverlet<T>::~serverlet()
137  {
138  }
139 
140  template<typename T> template<typename TRequest>
141  inline bool serverlet<T>::register_rpc_handler(dsn_task_code_t rpc_code, const char* rpc_name_, void (T::*handler)(const TRequest&), dsn_gpid gpid)
142  {
143  typedef handler_context<void (T::*)(const TRequest&)> hc_type1;
144  auto hc = (hc_type1*)malloc(sizeof(hc_type1));
145  hc->this_ = (T*)this;
146  hc->cb = handler;
147 
148  dsn_rpc_request_handler_t cb = [](dsn_message_t request, void* param)
149  {
150  auto hc2 = (hc_type1*)param;
151 
152  TRequest req;
153  ::dsn::unmarshall(request, req);
154  ((hc2->this_)->*(hc2->cb))(req);
155  };
156 
157  return dsn_rpc_register_handler(rpc_code, rpc_name_, cb, hc, gpid);
158  }
159 
160  template<typename T> template<typename TRequest, typename TResponse>
161  inline bool serverlet<T>::register_rpc_handler(dsn_task_code_t rpc_code, const char* rpc_name_, void (T::*handler)(const TRequest&, TResponse&), dsn_gpid gpid)
162  {
163  typedef handler_context<void (T::*)(const TRequest&, TResponse&)> hc_type2;
164  auto hc = (hc_type2*)malloc(sizeof(hc_type2));
165  hc->this_ = (T*)this;
166  hc->cb = handler;
167 
168  dsn_rpc_request_handler_t cb = [](dsn_message_t request, void* param)
169  {
170  auto hc2 = (hc_type2*)param;
171 
172  TRequest req;
173  ::dsn::unmarshall(request, req);
174 
175  TResponse resp;
176  ((hc2->this_)->*(hc2->cb))(req, resp);
177 
179  replier(resp);
180  };
181 
182  return dsn_rpc_register_handler(rpc_code, rpc_name_, cb, hc, gpid);
183  }
184 
185  template<typename T> template<typename TRequest, typename TResponse>
186  inline bool serverlet<T>::register_async_rpc_handler(dsn_task_code_t rpc_code, const char* rpc_name_, void (T::*handler)(const TRequest&, rpc_replier<TResponse>&), dsn_gpid gpid)
187  {
188  typedef handler_context<void (T::*)(const TRequest&, rpc_replier<TResponse>&)> hc_type3;
189  auto hc = (hc_type3*)malloc(sizeof(hc_type3));
190  hc->this_ = (T*)this;
191  hc->cb = handler;
192 
193  dsn_rpc_request_handler_t cb = [](dsn_message_t request, void* param)
194  {
195  auto hc2 = (hc_type3*)param;
196 
197  TRequest req;
198  ::dsn::unmarshall(request, req);
199 
201  ((hc2->this_)->*(hc2->cb))(req, replier);
202  };
203 
204  return dsn_rpc_register_handler(rpc_code, rpc_name_, cb, hc, gpid);
205  }
206 
207  template<typename T>
208  inline bool serverlet<T>::register_rpc_handler(dsn_task_code_t rpc_code, const char* rpc_name_, void (T::*handler)(dsn_message_t), dsn_gpid gpid)
209  {
210  typedef handler_context<void (T::*)(dsn_message_t)> hc_type4;
211  auto hc = (hc_type4*)malloc(sizeof(hc_type4));
212  hc->this_ = (T*)this;
213  hc->cb = handler;
214 
215  dsn_rpc_request_handler_t cb = [](dsn_message_t request, void* param)
216  {
217  auto hc2 = (hc_type4*)param;
218  ((hc2->this_)->*(hc2->cb))(request);
219  };
220 
221  return dsn_rpc_register_handler(rpc_code, rpc_name_, cb, hc, gpid);
222  }
223 
224  template<typename T>
225  inline bool serverlet<T>::unregister_rpc_handler(dsn_task_code_t rpc_code, dsn_gpid gpid)
226  {
227  auto cb = (void*)dsn_rpc_unregiser_handler(rpc_code, gpid);
228  if (cb != nullptr) free(cb);
229  return cb != nullptr;
230  }
231 
232  template<typename T>template<typename TResponse>
233  inline void serverlet<T>::reply(dsn_message_t request, const TResponse& resp)
234  {
235  auto msg = dsn_msg_create_response(request);
236  ::dsn::marshall(msg, resp);
237  dsn_rpc_reply(msg);
238  }
240 } // end namespace
241 
242 
243 
DSN_API dsn_message_t dsn_msg_create_response(dsn_message_t request)
create a RPC response message correspondent to the given request message
Definition: serverlet.h:91
DSN_API void dsn_rpc_reply(dsn_message_t response, dsn_error_t err DEFAULT(0))
reply with a response which is created using dsn_msg_create_response
void(* dsn_rpc_request_handler_t)(dsn_message_t, void *)
callback prototype for TASK_TYPE_RPC_REQUEST
Definition: api_task.h:69
Definition: auto_codes.h:105
Definition: api_layer1.h:683
DSN_API void * dsn_rpc_unregiser_handler(dsn_task_code_t code, dsn_gpid gpid DEFAULT(dsn_gpid{0}))
unregister callback to handle RPC request, and returns void* context upon dsn_rpc_register_handler ...
Definition: serverlet.h:59
Definition: clientlet.h:48
DSN_API bool dsn_rpc_register_handler(dsn_task_code_t code, const char *name, dsn_rpc_request_handler_t cb, void *context, dsn_gpid gpid DEFAULT(dsn_gpid{0}))
register callback to handle RPC request
Definition: address.h:52