Robust Distributed System Nucleus (rDSN)  ver 1.0.0
auto_codes.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/service_api_c.h>
39 # include <dsn/utility/ports.h>
40 # include <dsn/utility/autoref_ptr.h>
41 # include <memory>
42 # include <atomic>
43 
44 #ifdef DSN_USE_THRIFT_SERIALIZATION
45 # include <thrift/protocol/TProtocol.h>
46 #endif
47 
48 # define TRACK_ERROR_CODE 1
49 
50 namespace dsn
51 {
52  typedef void(*safe_handle_release)(void*);
53 
54  template<safe_handle_release releaser>
55  class safe_handle : public ::dsn::ref_counter
56  {
57  public:
58  safe_handle(void* handle, bool is_owner)
59  {
60  _handle = handle;
61  _is_owner = is_owner;
62  }
63 
64  safe_handle()
65  {
66  _handle = nullptr;
67  _is_owner = false;
68  }
69 
70  void assign(void* handle, bool is_owner)
71  {
72  clear();
73 
74  _handle = handle;
75  _is_owner = is_owner;
76  }
77 
78  void set_owner(bool owner = true)
79  {
80  _is_owner = owner;
81  }
82 
83  ~safe_handle()
84  {
85  clear();
86  }
87 
88  void* native_handle() const { return _handle; }
89 
90  private:
91  void clear()
92  {
93  if (_is_owner && nullptr != _handle)
94  {
95  releaser(_handle);
96  _handle = nullptr;
97  }
98  }
99 
100  private:
101  void* _handle;
102  bool _is_owner;
103  };
104 
105  class gpid
106  {
107  private:
108  dsn_gpid _value;
109 
110  public:
111  gpid(int app_id, int pidx)
112  {
113  _value.u.app_id = app_id;
114  _value.u.partition_index = pidx;
115  }
116 
117  gpid(dsn_gpid gd)
118  {
119  _value = gd;
120  }
121 
122  gpid(const gpid& gd)
123  {
124  _value.value = gd._value.value;
125  }
126 
127  gpid()
128  {
129  _value.value = 0;
130  }
131 
132  uint64_t value() const
133  {
134  return _value.value;
135  }
136 
137  operator dsn_gpid() const
138  {
139  return _value;
140  }
141 
142  bool operator < (const gpid & r) const
143  {
144  return _value.u.app_id < r._value.u.app_id ||
145  (_value.u.app_id == r._value.u.app_id && _value.u.partition_index < r._value.u.partition_index);
146  }
147 
148  bool operator == (const gpid & r) const
149  {
150  return value() == r.value();
151  }
152 
153  bool operator != (const gpid & r) const
154  {
155  return value() != r.value();
156  }
157 
158  int32_t get_app_id() const { return _value.u.app_id; }
159  int32_t get_partition_index() const { return _value.u.partition_index; }
160  void set_app_id(int32_t v) { _value.u.app_id = v; }
161  void set_partition_index(int32_t v) { _value.u.partition_index = v; }
162  dsn_gpid& raw() { return _value; }
163 
164 #ifdef DSN_USE_THRIFT_SERIALIZATION
165  uint32_t read(::apache::thrift::protocol::TProtocol* iprot);
166  uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const;
167 #endif
168  };
169 
174  class task_code
175  {
176  public:
177  task_code(const char* name, dsn_task_type_t tt, dsn_task_priority_t pri, dsn_threadpool_code_t pool)
178  {
179  _internal_code = dsn_task_code_register(name, tt, pri, pool);
180  }
181 
182  task_code()
183  {
184  _internal_code = 0;
185  }
186 
187  explicit task_code(dsn_task_code_t code)
188  {
189  _internal_code = code;
190  }
191 
192  task_code(const task_code& r)
193  {
194  _internal_code = r._internal_code;
195  }
196 
197  const char* to_string() const
198  {
199  return dsn_task_code_to_string(_internal_code);
200  }
201 
202  task_code& operator=(const task_code& source)
203  {
204  _internal_code = source._internal_code;
205  return *this;
206  }
207 
208  bool operator == (const task_code& r)
209  {
210  return _internal_code == r._internal_code;
211  }
212 
213  bool operator != (const task_code& r)
214  {
215  return !(*this == r);
216  }
217 
218  operator dsn_task_code_t() const
219  {
220  return _internal_code;
221  }
222 
223 #ifdef DSN_USE_THRIFT_SERIALIZATION
224  uint32_t read(::apache::thrift::protocol::TProtocol* iprot);
225  uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const;
226 #endif
227  private:
228  dsn_task_code_t _internal_code;
229  };
230 
231  #define DEFINE_NAMED_TASK_CODE(x, name, pri, pool) __selectany const ::dsn::task_code x(#name, TASK_TYPE_COMPUTE, pri, pool);
232  #define DEFINE_NAMED_TASK_CODE_AIO(x, name, pri, pool) __selectany const ::dsn::task_code x(#name, TASK_TYPE_AIO, pri, pool);
233  #define DEFINE_NAMED_TASK_CODE_RPC(x, name, pri, pool) \
234  __selectany const ::dsn::task_code x(#name, TASK_TYPE_RPC_REQUEST, pri, pool); \
235  __selectany const ::dsn::task_code x##_ACK(#name"_ACK", TASK_TYPE_RPC_RESPONSE, pri, pool);
236 
238  #define DEFINE_TASK_CODE(x, pri, pool) DEFINE_NAMED_TASK_CODE(x, x, pri, pool)
239  #define DEFINE_TASK_CODE_AIO(x, pri, pool) DEFINE_NAMED_TASK_CODE_AIO(x, x, pri, pool)
240  #define DEFINE_TASK_CODE_RPC(x, pri, pool) DEFINE_NAMED_TASK_CODE_RPC(x, x, pri, pool)
241 
243  {
244  public:
245  threadpool_code(const char* name)
246  {
247  _internal_code = dsn_threadpool_code_register(name);
248  }
249 
251  {
252  _internal_code = 0;
253  }
254 
256  {
257  _internal_code = r._internal_code;
258  }
259 
260  const char* to_string() const
261  {
262  return dsn_task_code_to_string(_internal_code);
263  }
264 
265  threadpool_code& operator=(const threadpool_code& source)
266  {
267  _internal_code = source._internal_code;
268  return *this;
269  }
270 
271  bool operator == (const threadpool_code& r)
272  {
273  return _internal_code == r._internal_code;
274  }
275 
276  bool operator != (const threadpool_code& r)
277  {
278  return !(*this == r);
279  }
280 
281  operator dsn_threadpool_code_t() const
282  {
283  return _internal_code;
284  }
285 
286  private:
287  dsn_threadpool_code_t _internal_code;
288  };
289 
291  #define DEFINE_THREAD_POOL_CODE(x) __selectany const ::dsn::threadpool_code x(#x);
292 
293  DEFINE_THREAD_POOL_CODE(THREAD_POOL_INVALID)
294  DEFINE_THREAD_POOL_CODE(THREAD_POOL_DEFAULT)
295  // define default task code
296  DEFINE_TASK_CODE(TASK_CODE_INVALID, TASK_PRIORITY_COMMON, THREAD_POOL_DEFAULT)
304  {
305  public:
306  error_code(const char* name)
307  {
308  _internal_code = dsn_error_register(name);
309 
310  dassert (name, "name for an error code cannot be empty");
311  # ifdef TRACK_ERROR_CODE
312  _used = true;
313  # endif
314  }
315 
316  error_code()
317  {
318  _internal_code = 0;
319 
320  # ifdef TRACK_ERROR_CODE
321  _used = true;
322  # endif
323  }
324 
325  error_code(dsn_error_t err)
326  {
327  _internal_code = err;
328 
329 # ifdef TRACK_ERROR_CODE
330  _used = false;
331 # endif
332  }
333 
334  error_code(const error_code& err)
335  {
336  _internal_code = err._internal_code;
337  # ifdef TRACK_ERROR_CODE
338  _used = false;
339  err._used = true;
340  # endif
341  }
342 
343  const char* to_string() const
344  {
345  # ifdef TRACK_ERROR_CODE
346  _used = true;
347  # endif
348  return dsn_error_to_string(_internal_code);
349  }
350 
351  error_code& operator=(const error_code& source)
352  {
353  _internal_code = source._internal_code;
354  # ifdef TRACK_ERROR_CODE
355  _used = false;
356  source._used = true;
357  # endif
358  return *this;
359  }
360 
361  bool operator == (const error_code& r)
362  {
363  # ifdef TRACK_ERROR_CODE
364  _used = true;
365  r._used = true;
366  # endif
367  return _internal_code == r._internal_code;
368  }
369 
370  bool operator != (const error_code& r)
371  {
372  return !(*this == r);
373  }
374 
375  # ifdef TRACK_ERROR_CODE
376  ~error_code()
377  {
378  // in cases where error code is std::bind-ed as task callbacks,
379  // and when tasks are cancelled, it is difficult to end track them on cancel
380  // therefore we change derror to dwarn
381  if (!_used)
382  {
383  if (_internal_code != 0)
384  {
385  dlog(LOG_LEVEL_ERROR, "error-code",
386  "error code is not handled, err = %s", to_string());
387  }
388  }
389  }
390  # endif
391 
392  dsn_error_t get() const
393  {
394  # ifdef TRACK_ERROR_CODE
395  _used = true;
396  # endif
397  return _internal_code;
398  }
399 
400  operator dsn_error_t() const
401  {
402  # ifdef TRACK_ERROR_CODE
403  _used = true;
404  # endif
405  return _internal_code;
406  }
407 
408  void end_tracking() const
409  {
410  # ifdef TRACK_ERROR_CODE
411  _used = true;
412  # endif
413  }
414 
415 #ifdef DSN_USE_THRIFT_SERIALIZATION
416  uint32_t read(::apache::thrift::protocol::TProtocol* iprot);
417  uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const;
418 #endif
419  private:
420  # ifdef TRACK_ERROR_CODE
421  mutable bool _used;
422  # endif
423  dsn_error_t _internal_code;
424  };
425 
426  #define DEFINE_ERR_CODE(x) __selectany const dsn::error_code x(#x);
427 
428  DEFINE_ERR_CODE(ERR_OK)
429 
430  DEFINE_ERR_CODE(ERR_UNKNOWN)
431  DEFINE_ERR_CODE(ERR_SERVICE_NOT_FOUND)
432  DEFINE_ERR_CODE(ERR_SERVICE_ALREADY_RUNNING)
433  DEFINE_ERR_CODE(ERR_IO_PENDING)
434  DEFINE_ERR_CODE(ERR_TIMEOUT)
435  DEFINE_ERR_CODE(ERR_SERVICE_NOT_ACTIVE)
436  DEFINE_ERR_CODE(ERR_BUSY)
437  DEFINE_ERR_CODE(ERR_NETWORK_INIT_FAILED)
438  DEFINE_ERR_CODE(ERR_FORWARD_TO_OTHERS)
439  DEFINE_ERR_CODE(ERR_OBJECT_NOT_FOUND)
440 
441  DEFINE_ERR_CODE(ERR_HANDLER_NOT_FOUND)
442  DEFINE_ERR_CODE(ERR_LEARN_FILE_FAILED)
443  DEFINE_ERR_CODE(ERR_GET_LEARN_STATE_FAILED)
444  DEFINE_ERR_CODE(ERR_INVALID_VERSION)
445  DEFINE_ERR_CODE(ERR_INVALID_PARAMETERS)
446  DEFINE_ERR_CODE(ERR_CAPACITY_EXCEEDED)
447  DEFINE_ERR_CODE(ERR_INVALID_STATE)
448  DEFINE_ERR_CODE(ERR_INACTIVE_STATE)
449  DEFINE_ERR_CODE(ERR_NOT_ENOUGH_MEMBER)
450  DEFINE_ERR_CODE(ERR_FILE_OPERATION_FAILED)
451 
452  DEFINE_ERR_CODE(ERR_HANDLE_EOF)
453  DEFINE_ERR_CODE(ERR_WRONG_CHECKSUM)
454  DEFINE_ERR_CODE(ERR_INVALID_DATA)
455  DEFINE_ERR_CODE(ERR_INVALID_HANDLE)
456  DEFINE_ERR_CODE(ERR_INCOMPLETE_DATA)
457  DEFINE_ERR_CODE(ERR_VERSION_OUTDATED)
458  DEFINE_ERR_CODE(ERR_PATH_NOT_FOUND)
459  DEFINE_ERR_CODE(ERR_PATH_ALREADY_EXIST)
460  DEFINE_ERR_CODE(ERR_ADDRESS_ALREADY_USED)
461  DEFINE_ERR_CODE(ERR_STATE_FREEZED)
462 
463  DEFINE_ERR_CODE(ERR_LOCAL_APP_FAILURE)
464  DEFINE_ERR_CODE(ERR_BIND_IOCP_FAILED)
465  DEFINE_ERR_CODE(ERR_NETWORK_START_FAILED)
466  DEFINE_ERR_CODE(ERR_NOT_IMPLEMENTED)
467  DEFINE_ERR_CODE(ERR_CHECKPOINT_FAILED)
468  DEFINE_ERR_CODE(ERR_WRONG_TIMING)
469  DEFINE_ERR_CODE(ERR_NO_NEED_OPERATE)
470  DEFINE_ERR_CODE(ERR_CORRUPTION)
471  DEFINE_ERR_CODE(ERR_TRY_AGAIN)
472  DEFINE_ERR_CODE(ERR_CLUSTER_NOT_FOUND)
473 
474  DEFINE_ERR_CODE(ERR_CLUSTER_ALREADY_EXIST)
475  DEFINE_ERR_CODE(ERR_SERVICE_ALREADY_EXIST)
476  DEFINE_ERR_CODE(ERR_INJECTED)
477  DEFINE_ERR_CODE(ERR_REPLICATION_FAILURE)
478  DEFINE_ERR_CODE(ERR_APP_EXIST)
479  DEFINE_ERR_CODE(ERR_APP_NOT_EXIST)
480  DEFINE_ERR_CODE(ERR_BUSY_CREATING)
481  DEFINE_ERR_CODE(ERR_BUSY_DROPPING)
482  DEFINE_ERR_CODE(ERR_NETWORK_FAILURE)
484 } // end namespace
485 
#define DEFINE_TASK_CODE(x, pri, pool)
define a new task code with TASK_TYPE_COMPUTATION
Definition: auto_codes.h:238
Definition: auto_codes.h:242
dsn_task_priority_t
task priority
Definition: api_task.h:90
int32_t app_id
1-based app id (0 for invalid)
Definition: api_layer1.h:686
DSN_API dsn_error_t dsn_error_register(const char *name)
register error code
Definition: auto_codes.h:55
DSN_API dsn_threadpool_code_t dsn_threadpool_code_register(const char *name)
define a new thread pool with a given name
Definition: auto_codes.h:174
Definition: auto_codes.h:303
Definition: auto_codes.h:105
Definition: api_layer1.h:683
#define DEFINE_THREAD_POOL_CODE(x)
define a new thread pool named x
Definition: auto_codes.h:291
Definition: address.h:52
DSN_API dsn_task_code_t dsn_task_code_register(const char *name, dsn_task_type_t type, dsn_task_priority_t, dsn_threadpool_code_t pool)
register a new task code
dsn_task_type_t
task/event type definition
Definition: api_task.h:50
DSN_API const char * dsn_error_to_string(dsn_error_t err)
translate interger error code to a string
int32_t partition_index
zero-based partition index
Definition: api_layer1.h:687