acl  3.5.3.0
redis_command.hpp
浏览该文件的文档.
1 #pragma once
2 #include "../acl_cpp_define.hpp"
3 #include "../stdlib/noncopyable.hpp"
4 #include "../stdlib/tbox.hpp"
5 #include <map>
6 #include <list>
7 #include <vector>
8 #include "redis_result.hpp"
9 
10 #if !defined(ACL_CLIENT_ONLY) && !defined(ACL_REDIS_DISABLE)
11 
12 namespace acl
13 {
14 
15 class redis_request;
16 class redis_client;
17 class redis_client_cluster;
18 class redis_client_pipeline;
19 class redis_pipeline_message;
20 
21 /**
22  * redis 客户端命令类的纯虚父类;
23  * the redis command classes's base virtual class, which includes the basic
24  * functions for all sub-classes
25  */
27 {
28 public:
29  /**
30  * 缺省的构造函数,如果使用此构造函数初始化类对象,则必须调用
31  * set_client 或 set_cluster 设置 redis 客户端命令类对象的通讯方式。
32  * default constructor. You must set the communication method by
33  * set_client or set_cluster functions.
34  */
35  redis_command(void);
36 
37  /**
38  * 当使用非集群模式时,可以使用此构造函数设置 redis 通信对象。
39  * Using this constructor to set the redis communication mode,
40  * usually in no-cluster mode.
41  * @param conn {redis_client*} redis 通信类对象
42  * the redis communication in no-cluster mode
43  */
45 
46  /**
47  * 集群模式的构造函数,在构造类对象时指定了集群模式的
48  * redis_client_cluster 对象。
49  * Using this constructor to set the redis_client_cluster, usually in
50  * cluster mode.
51  * @param cluster {redis_client_cluster*} redis 集群连接对象
52  * redis cluster object in cluster mode
53  * the max of every connection pool with all the redis nodes,
54  * if be set 0, then there is no connections limit in
55  * connections pool.
56  */
58 
60  redis_command(redis_client_cluster* cluster, size_t max_conns);
61 
63 
64  virtual ~redis_command(void);
65 
66  /**
67  * 在进行每个命令处理前,是否要求检查 socket 句柄与地址的匹配情况,当
68  * 打开该选项时,将会严格检查匹配情况,但会影响一定性能,因此该设置仅
69  * 用在 DEBUG 时的运行场景
70  * @param on {bool}
71  */
72  void set_check_addr(bool on);
73 
74  /**
75  * 在重复使用一个继承于 redis_command 的子类操作 redis 时,需要在
76  * 下一次调用前调用本方法以释放上次操作的临时对象;
77  * when reusing a redis command sub-class, the reset method should be
78  * called first to rlease some resources in last command operation
79  * @param save_slot {bool} 当采用集群模式时,该参数决定是否需要重新
80  * 计算哈希槽值,如果反复调用 redis 命令过程中的 key 值不变,则可以保
81  * 留此哈希槽值以减少内部重新进行计算的次数;
82  * when in cluster mode, if your operations is on the same key, you
83  * can set the param save_slot to false which can reduse the times
84  * of compute the same key's hash-slot.
85  */
86  void clear(bool save_slot = false);
87 
88  ACL_CPP_DEPRECATED_FOR("clear")
89  void reset(bool save_slot = false);
90 
91  /**
92  * 在使用非集群方式时,通过本函数将从连接池获得的连接对象;
93  * when not using cluster mode, the function is used
94  * to set the connection for next redis command operation.
95  * @param conn {redis_client*} 与 redis 客户端命令进行关联;
96  * the redis connection to be set in next redis operation
97  */
98  void set_client(redis_client* conn);
99 
100  /**
101  * 获得当前 redis 客户端命令的连接对象;
102  * get redis connection set by set_client function
103  * @return {redis_client*} 返回 NULL 表示没有连接对象与当前的命令对象
104  * 进行绑定;
105  * the internal redis connection be returned, NULL if no redis
106  * connection be set
107  */
109  {
110  return conn_;
111  }
112 
113  /**
114  * 获得当前 redis 命令对象所绑定的服务器地址,只有当该对象与 redis_client
115  * 绑定时(即调用 set_client) 才可以调用本函数
116  * get the redis-server's addr used by the current command. this
117  * method can only be used only if the redis_client was set by
118  * set_client method.
119  * @return {const char*} 返回空串 "" 表示没有绑定 redis 连接对象
120  * if "" was resturned, the redis connection was not set
121  */
122  const char* get_client_addr(void) const;
123 
124  /**
125  * 设置连接池集群管理器;
126  * set the redis cluster object in redis cluster mode
127  * @param cluster {redis_client_cluster*} redis 集群连接对象;
128  * the redis_cluster connection object which can connect to any
129  * redis-server and support connection pool
130  * when dynamicly creating connection pool to any redis-server, use
131  * this param to limit the max number for each connection pool
132  */
133  void set_cluster(redis_client_cluster* cluster);
134 
136  void set_cluster(redis_client_cluster* cluster, size_t max_conns);
137 
138  /**
139  * 获得所设置的连接池集群管理器;
140  * get redis_cluster object set by set_cluster function
141  * @return {redis_client_cluster*}
142  */
144  {
145  return cluster_;
146  }
147 
148  /**
149  * 设置pipeline通信对象,使用pipeline模式
150  * set the redis communication in pipeline mode
151  * @param pipeline {redis_client_pipeline*} pipeline communication object
152  * @param use_mbox {bool} if using acl::mbox to get the result,
153  * acl::tbox will be used if use_mbox is set to false; acl::mbox
154  * will be used as default internal.
155  */
156  void set_pipeline(redis_client_pipeline* pipeline, bool use_mbox = true);
157 
158  /**
159  * get the redis pipeline communication object been set before
160  * @return {redis_client_pipeline*} return NULL if not set
161  */
163  {
164  return pipeline_;
165  }
166 
167  /**
168  * 获得内存池句柄,该内存池由 redis_command 内部产生;
169  * get memory pool handle been set
170  * @return {dbuf_pool*}
171  */
172  dbuf_pool* get_dbuf(void) const
173  {
174  return dbuf_;
175  }
176 
177  /**
178  * 获得当前结果结点的数据类型;
179  * get the result type returned from redis-server
180  * @return {redis_result_t}
181  */
182  redis_result_t result_type(void) const;
183 
184  /**
185  * 当返回值为 REDIS_RESULT_STATUS 类型时,本方法返回状态信息;
186  * when result type is REDIS_RESULT_STATUS, the status info can be
187  * get by this function
188  * @return {const char*} 返回 "" 表示出错;
189  * "" will be returned on error
190  */
191  const char* result_status(void) const;
192 
193  /**
194  * 当出错时返回值为 REDIS_RESULT_ERROR 类型,本方法返回出错信息;
195  * when result type is REDIS_RESULT_ERROR, the error info can be
196  * get by this function
197  * @return {const char*} 返回空串 "" 表示没有出错信息;
198  * "" will be returned when no error info
199  */
200  const char* result_error(void) const;
201 
202  /**
203  * 获得当前结果结点存储的对象的个数, 该方法可以获得结果为下面两个方法
204  * (result_child/result_value) 所需要的数组元素的个数;
205  * get number of result objects, just for functions
206  * result_child/result_value
207  * @return {size_t} 返回值与存储类型的对应关系如下:
208  * the relation between return value and result type, as below:
209  * REDIS_RESULT_ERROR: 1
210  * REDIS_RESULT_STATUS: 1
211  * REDIS_RESULT_INTEGER: 1
212  * REDIS_RESULT_STRING: > 0 时表示该字符串数据被切分成非连接内存块的个数;
213  * when the result type is REDIS_RESULT_STRING and the the
214  * string is too large, the string was be cut into many small
215  * chunks, the returned value is the chunks number
216  * REDIS_RESULT_ARRAY: children_->size()
217  */
218  size_t result_size(void) const;
219 
220  /**
221  * 当返回值为 REDIS_RESULT_INTEGER 类型时,本方法返回对应的 32 位整数值;
222  * get 32-bits number value if result type is REDIS_RESULT_INTERGER
223  * @param success {bool*} 本指针非 NULL 时记录操作过程是否成功;
224  * if the param pointer is not NULL, which will save status of
225  * success or not for result from redis-server
226  * @return {int}
227  */
228  int result_number(bool* success = NULL) const;
229 
230  /**
231  * 当返回值为 REDIS_RESULT_INTEGER 类型时,本方法返回对应的 64 位整数值;
232  * get 64-bits number value if result type is REDIS_RESULT_INTERGER
233  * @param success {bool*} 本指针非 NULL 时记录操作过程是否成功;
234  * if the param pointer is not NULL, which will save status of
235  * success or not for result from redis-server
236  * @return {long long int}
237  */
238  long long int result_number64(bool* success = NULL) const;
239 
240  /**
241  * 返回对应下标的数据(当数据类型非 REDIS_RESULT_ARRAY 时);
242  * get string result when result type isn't REDIS_RESULT_ARRAY
243  * @param i {size_t} 数组下标;
244  * the array index
245  * @param len {size_t*} 当为非 NULL 指针时存储所返回数据的长度;
246  * *len will save the result's length if len is not NULL
247  * @return {const char*} 返回 NULL 表示下标越界;
248  * NULL will return if i beyonds the array's size
249  */
250  const char* get_result(size_t i, size_t* len = NULL) const;
251 
252  /**
253  * 判断当前所绑定的 redis 连接流对象(redis_client) 连接是否已经关闭;
254  * 只有内部的 conn_ 流对象非空时调用此函数才有意义;
255  * to judge if the redis connection was be closed, only redis_client
256  * object be set internal
257  * @return {bool}
258  */
259  bool eof(void) const;
260 
261  /**
262  * 获得本次 redis 操作过程的结果;
263  * get result object of last redis operation
264  * @return {redis_result*}
265  */
266  const redis_result* get_result(void) const;
267 
268  /**
269  * 当查询结果为数组对象时调用本方法获得一个数组元素对象;
270  * get one result ojbect of array if result type is REDIS_RESULT_ARRAY
271  * @param i {size_t} 数组对象的下标值;
272  * the result array's index
273  * @return {const redis_result*} 当结果非数组对象或结果为空或出错时
274  * 该方法返回 NULL;
275  * NULL will be resturned when result is not REDIS_RESULT_ARRAY or
276  * array empty or error
277  */
278  const redis_result* result_child(size_t i) const;
279 
280  /**
281  * 当从 redis-server 获得的数据是一组字符串类型的结果集时,可以调用
282  * 本函数获得某个指定下标位置的数据;
283  * when the reply from redis-serveer are strings array, this
284  * function can be used to get the string specified by a subscript
285  * @param i {size_t} 下标(从 0 开始)
286  * the subscript of strings array
287  * @param len {size_t*} 若该指针非空,则存储所返回结果的长度(仅当该
288  * 方法返回非空指针时有效)
289  * if len not a NULL pointer, it will store the length of string
290  * specified by the subscript
291  * @return {const char*} 返回对应下标的值,当返回 NULL 时表示该下标没
292  * 有值,为了保证使用上的安全性,返回的数据总能保证最后是以 \0 结尾,
293  * 在计算数据长度时不包含该结尾符,但为了兼容二进制情形,调用者还是
294  * 应该通过返回的 len 存放的长度值来获得数据的真实长度
295  * the string will be returned associate with the subscript, if there
296  * are nothing with the subscript, NULL will be returned
297  */
298  const char* result_value(size_t i, size_t* len = NULL) const;
299 
300  /////////////////////////////////////////////////////////////////////
301  /**
302  * 设置是否对请求数据进行分片处理,如果为 true 则内部在组装请求协议的
303  * 时候不会将所有数据块重新组装成一个连续的大数据块
304  * just for request package, setting flag for sending data with
305  * multi data chunks; this is useful when the request data is large
306  * @param on {bool} 内部默认值为 false
307  * if true the request data will not be combined one package,
308  * internal default is false
309  */
310  void set_slice_request(bool on);
311 
312  /**
313  * 设置是否对响应数据进行分片处理,如果为 true 则当服务器的返回数据
314  * 比较大时则将数据进行分片,分成一些不连续的数据块
315  * just for response package, settint flag for receiving data
316  * if split the large response data into multi little chunks
317  * @param on {bool} 内部默认值为 false
318  * if true the response data will be splitted into multi little
319  * data, which is useful for large reponse data for avoiding
320  * malloc large continuously memory from system.
321  * internal default is false
322  */
323  void set_slice_respond(bool on);
324 
325 public:
326  /**
327  * 直接组合 redis 协议命令方式,从 redis 服务器获得结果
328  * @param argc {size_t} 后面数组中数组元素个数
329  * @param argv {const char*[]} redis 命令组成的数组
330  * @param lens {size_t[]} argv 中数组元素的长度
331  * @param nchild {size_t} 有的 redis 命令需要获取多个结果集,如:subop
332  * @return {const redis_result*} 返回的结果集
333  */
334  const redis_result* request(size_t argc, const char* argv[],
335  size_t lens[], size_t nchild = 0);
336 
337  /**
338  * 直接组合 redis 协议命令方式,从 redis 服务器获得结果
339  * @param args {const std::vector<string>&} redis 命令组成的数组
340  * @param nchild {size_t} 有的 redis 命令需要获取多个结果集,如:subop
341  * @return {const redis_result*} 返回的结果集
342  */
343  const redis_result* request(const std::vector<string>& args,
344  size_t nchild = 0);
345 
346  const string* request_buf(void) const
347  {
348  return request_buf_;
349  }
350 
351  /**
352  * 根据请求命令字列表创建 redis 请求协议数据
353  * @param argc {size_t} 命令参数个数
354  * @param argv {const char* []} 命令参数数组
355  * @param lens {size_t []} 每个命令参数长度数组
356  * @param out {string&} 存放创建结果
357  */
358  static void build_request(size_t argc, const char* argv[],
359  size_t lens[], string& out);
360 
361  /**
362  * 根据命令字列表创建 redis 请求协议并存储于 redis_command 中,以备在请求时使用
363  * @param argc {size_t} 命令参数个数
364  * @param argv {const char* []} 命令参数数组
365  * @param lens {size_t []} 每个命令参数长度数组
366  */
367  void build_request(size_t argc, const char* argv[], size_t lens[]);
368 
369 protected:
370  const redis_result* run(size_t nchild = 0, int* timeout = NULL);
371 
372  void clear_request(void);
373  const redis_result** scan_keys(const char* cmd, const char* key,
374  int& cursor, size_t& size, const char* pattern,
375  const size_t* count);
376  const redis_result** scan_keys(const char* cmd, const char* key,
377  size_t klen, int& cursor, size_t& size, const char* pattern,
378  const size_t* count);
379 
380  /*******************************************************************/
381 
382  void build(const char* cmd, const char* key,
383  const std::map<string, string>& attrs);
384  void build(const char* cmd, const char* key, size_t klen,
385  const std::map<string, string>& attrs);
386  void build(const char* cmd, const char* key,
387  const std::map<string, const char*>& attrs);
388 
389  void build(const char* cmd, const char* key,
390  const std::vector<string>& names,
391  const std::vector<string>& values);
392  void build(const char* cmd, const char* key, size_t klen,
393  const std::vector<string>& names,
394  const std::vector<string>& values);
395  void build(const char* cmd, const char* key,
396  const std::vector<const char*>& names,
397  const std::vector<const char*>& values);
398 
399  void build(const char* cmd, const char* key,
400  const char* names[], const char* values[], size_t argc);
401  void build(const char* cmd, const char* key,
402  const int names[], const char* values[], size_t argc);
403  void build(const char* cmd, const char* key,
404  const char* names[], const size_t names_len[],
405  const char* values[], const size_t values_len[], size_t argc);
406  void build(const char* cmd, const char* key, size_t klen,
407  const char* names[], const size_t names_len[],
408  const char* values[], const size_t values_len[], size_t argc);
409 
410  /*******************************************************************/
411 
412  void build(const char* cmd, const char* key,
413  const std::vector<string>& names);
414  void build(const char* cmd, const char* key, size_t klen,
415  const std::vector<string>& names);
416  void build(const char* cmd, const char* key,
417  const std::vector<const char*>& names);
418  void build(const char* cmd, const char* key,
419  const std::vector<int>& names);
420 
421  void build(const char* cmd, const char* key,
422  const char* names[], size_t argc);
423  void build(const char* cmd, const char* key,
424  const char* names[], const size_t lens[], size_t argc);
425  void build(const char* cmd, const char* key, size_t klen,
426  const char* names[], const size_t lens[], size_t argc);
427  void build(const char* cmd, const char* key,
428  const int names[], size_t argc);
429 
430  /*******************************************************************/
431 
432 protected:
433  int get_number(bool* success = NULL);
434  long long int get_number64(bool* success = NULL);
435  int get_number(std::vector<int>& out);
436  int get_number64(std::vector<long long int>& out);
437  bool check_status(const char* success = "OK");
438 
439  int get_status(std::vector<bool>& out);
440  const char* get_status(void);
441 
442  int get_string(string& buf);
443  int get_string(string* buf);
444  int get_string(char* buf, size_t size);
445  int get_strings(std::vector<string>& result);
446  int get_strings(std::vector<string>* result);
447  int get_strings(std::list<string>& result);
448  int get_strings(std::list<string>* result);
449  int get_strings(std::map<string, string>& result);
450  int get_strings(std::vector<string>& names,
451  std::vector<string>& values);
452  int get_strings(std::vector<const char*>& names,
453  std::vector<const char*>& values);
454 
455  /************************** common *********************************/
456 protected:
458 
459 private:
460  void init(void);
461 
462 public:
463  // compute hash slot of the given key and store it in the current
464  // redis command will be used in the next operation for redis cluster.
465  void hash_slot(const char* key);
466  void hash_slot(const char* key, size_t len);
467 
468  // get the current hash slot stored internal
469  int get_slot(void) const {
470  return slot_;
471  }
472 
473  bool is_check_addr(void) const {
474  return check_addr_;
475  }
476 
477 protected:
479  char addr_[32];
484  int slot_;
487 
488 public:
489  const char* get_addr(const char* info);
490  void set_client_addr(const char* addr);
491  void set_client_addr(redis_client& conn);
492 
493 public:
494  redis_request* get_request_obj(void) const {
495  return request_obj_;
496  }
497 
498  string* get_request_buf(void) const {
499  return request_buf_;
500  }
501 
502  bool is_slice_req(void) const {
503  return slice_req_;
504  }
505 
506  // get pipeline message bound with the current command
507  redis_pipeline_message& get_pipeline_message(void);
508 
509 protected:
510  /************************** request ********************************/
512  string* request_buf_;
513  redis_request* request_obj_;
514  size_t argv_size_;
515  const char** argv_;
516  size_t* argv_lens_;
517  size_t argc_;
518 
519  // reserve the argv space with the specified value at least
520  void argv_space(size_t n);
521 
522  // build request in one request buffer
523  void build_request1(size_t argc, const char* argv[], size_t lens[]);
524 
525  // build request with slice request obj
526  void build_request2(size_t argc, const char* argv[], size_t lens[]);
527 
528 protected:
529  /************************** respond ********************************/
533 
534  // save the error info into log
535  void logger_result(const redis_result* result);
536 };
537 
538 } // namespace acl
539 
540 #endif // !defined(ACL_CLIENT_ONLY) && !defined(ACL_REDIS_DISABLE)
const string * request_buf(void) const
#define ACL_CPP_DEPRECATED
Definition: atomic.hpp:86
redis_client * conn_
redis_request * get_request_obj(void) const
dbuf_pool * get_dbuf(void) const
redis_client * get_client(void) const
bool is_check_addr(void) const
redis_client_cluster * get_cluster(void) const
int get_slot(void) const
redis_result_t
const redis_result * result_
string * get_request_buf(void) const
redis_client_pipeline * get_pipeline(void) const
#define ACL_CPP_DEPRECATED_FOR(f)
Definition: atomic.hpp:94
bool is_slice_req(void) const
redis_pipeline_message * pipe_msg_
redis_request * request_obj_
#define ACL_CPP_API
redis_client_pipeline * pipeline_
const char ** argv_
redis_client_cluster * cluster_