关键词搜索

源码搜索 ×
×

漫话Redis源码之二十四

发布2021-12-05浏览620次

详情内容

redisProtocolToLuaType是一个转换寒山湖,跟lua相关:

  1. /* Debugger shared state is stored inside this global structure. */
  2. #define LDB_BREAKPOINTS_MAX 64 /* Max number of breakpoints. */
  3. #define LDB_MAX_LEN_DEFAULT 256 /* Default len limit for replies / var dumps. */
  4. struct ldbState {
  5. connection *conn; /* Connection of the debugging client. */
  6. int active; /* Are we debugging EVAL right now? */
  7. int forked; /* Is this a fork()ed debugging session? */
  8. list *logs; /* List of messages to send to the client. */
  9. list *traces; /* Messages about Redis commands executed since last stop.*/
  10. list *children; /* All forked debugging sessions pids. */
  11. int bp[LDB_BREAKPOINTS_MAX]; /* An array of breakpoints line numbers. */
  12. int bpcount; /* Number of valid entries inside bp. */
  13. int step; /* Stop at next line regardless of breakpoints. */
  14. int luabp; /* Stop at next line because redis.breakpoint() was called. */
  15. sds *src; /* Lua script source code split by line. */
  16. int lines; /* Number of lines in 'src'. */
  17. int currentline; /* Current line number. */
  18. sds cbuf; /* Debugger client command buffer. */
  19. size_t maxlen; /* Max var dump / reply length. */
  20. int maxlen_hint_sent; /* Did we already hint about "set maxlen"? */
  21. } ldb;
  22. /* ---------------------------------------------------------------------------
  23. * Utility functions.
  24. * ------------------------------------------------------------------------- */
  25. /* Perform the SHA1 of the input string. We use this both for hashing script
  26. * bodies in order to obtain the Lua function name, and in the implementation
  27. * of redis.sha1().
  28. *
  29. * 'digest' should point to a 41 bytes buffer: 40 for SHA1 converted into an
  30. * hexadecimal number, plus 1 byte for null term. */
  31. void sha1hex(char *digest, char *script, size_t len) {
  32. SHA1_CTX ctx;
  33. unsigned char hash[20];
  34. char *cset = "0123456789abcdef";
  35. int j;
  36. SHA1Init(&ctx);
  37. SHA1Update(&ctx,(unsigned char*)script,len);
  38. SHA1Final(hash,&ctx);
  39. for (j = 0; j < 20; j++) {
  40. digest[j*2] = cset[((hash[j]&0xF0)>>4)];
  41. digest[j*2+1] = cset[(hash[j]&0xF)];
  42. }
  43. digest[40] = '\0';
  44. }
  45. /* ---------------------------------------------------------------------------
  46. * Redis reply to Lua type conversion functions.
  47. * ------------------------------------------------------------------------- */
  48. /* Take a Redis reply in the Redis protocol format and convert it into a
  49. * Lua type. Thanks to this function, and the introduction of not connected
  50. * clients, it is trivial to implement the redis() lua function.
  51. *
  52. * Basically we take the arguments, execute the Redis command in the context
  53. * of a non connected client, then take the generated reply and convert it
  54. * into a suitable Lua type. With this trick the scripting feature does not
  55. * need the introduction of a full Redis internals API. The script
  56. * is like a normal client that bypasses all the slow I/O paths.
  57. *
  58. * Note: in this function we do not do any sanity check as the reply is
  59. * generated by Redis directly. This allows us to go faster.
  60. *
  61. * Errors are returned as a table with a single 'err' field set to the
  62. * error string.
  63. */
  64. char *redisProtocolToLuaType(lua_State *lua, char* reply) {
  65. if (!lua_checkstack(lua, 5)) {
  66. /*
  67. * Increase the Lua stack if needed, to make sure there is enough room
  68. * to push 5 elements to the stack. On failure, exit with panic.
  69.          * Notice that we need, in the worst case, 5 elements because redisProtocolToLuaType_Aggregate
  70.          * might push 5 elements to the Lua stack.*/
  71. serverPanic("lua stack limit reach when parsing redis.call reply");
  72. }
  73. char *p = reply;
  74. switch(*p) {
  75. case ':': p = redisProtocolToLuaType_Int(lua,reply); break;
  76. case '$': p = redisProtocolToLuaType_Bulk(lua,reply); break;
  77. case '+': p = redisProtocolToLuaType_Status(lua,reply); break;
  78. case '-': p = redisProtocolToLuaType_Error(lua,reply); break;
  79. case '*': p = redisProtocolToLuaType_Aggregate(lua,reply,*p); break;
  80. case '%': p = redisProtocolToLuaType_Aggregate(lua,reply,*p); break;
  81. case '~': p = redisProtocolToLuaType_Aggregate(lua,reply,*p); break;
  82. case '_': p = redisProtocolToLuaType_Null(lua,reply); break;
  83. case '#': p = redisProtocolToLuaType_Bool(lua,reply,p[1]); break;
  84. case ',': p = redisProtocolToLuaType_Double(lua,reply); break;
  85. }
  86. return p;
  87. }
  88. char *redisProtocolToLuaType_Int(lua_State *lua, char *reply) {
  89. char *p = strchr(reply+1,'\r');
  90. long long value;
  91. string2ll(reply+1,p-reply-1,&value);
  92. lua_pushnumber(lua,(lua_Number)value);
  93. return p+2;
  94. }
  95. char *redisProtocolToLuaType_Bulk(lua_State *lua, char *reply) {
  96. char *p = strchr(reply+1,'\r');
  97. long long bulklen;
  98. string2ll(reply+1,p-reply-1,&bulklen);
  99. if (bulklen == -1) {
  100. lua_pushboolean(lua,0);
  101. return p+2;
  102. } else {
  103. lua_pushlstring(lua,p+2,bulklen);
  104. return p+2+bulklen+2;
  105. }
  106. }
  107. char *redisProtocolToLuaType_Status(lua_State *lua, char *reply) {
  108. char *p = strchr(reply+1,'\r');
  109. lua_newtable(lua);
  110. lua_pushstring(lua,"ok");
  111. lua_pushlstring(lua,reply+1,p-reply-1);
  112. lua_settable(lua,-3);
  113. return p+2;
  114. }
  115. char *redisProtocolToLuaType_Error(lua_State *lua, char *reply) {
  116. char *p = strchr(reply+1,'\r');
  117. lua_newtable(lua);
  118. lua_pushstring(lua,"err");
  119. lua_pushlstring(lua,reply+1,p-reply-1);
  120. lua_settable(lua,-3);
  121. return p+2;
  122. }
  123. char *redisProtocolToLuaType_Aggregate(lua_State *lua, char *reply, int atype) {
  124. char *p = strchr(reply+1,'\r');
  125. long long mbulklen;
  126. int j = 0;
  127. string2ll(reply+1,p-reply-1,&mbulklen);
  128. if (server.lua_client->resp == 2 || atype == '*') {
  129. p += 2;
  130. if (mbulklen == -1) {
  131. lua_pushboolean(lua,0);
  132. return p;
  133. }
  134. lua_newtable(lua);
  135. for (j = 0; j < mbulklen; j++) {
  136. lua_pushnumber(lua,j+1);
  137. p = redisProtocolToLuaType(lua,p);
  138. lua_settable(lua,-3);
  139. }
  140. } else if (server.lua_client->resp == 3) {
  141. /* Here we handle only Set and Map replies in RESP3 mode, since arrays
  142. * follow the above RESP2 code path. Note that those are represented
  143. * as a table with the "map" or "set" field populated with the actual
  144. * table representing the set or the map type. */
  145. p += 2;
  146. lua_newtable(lua);
  147. lua_pushstring(lua,atype == '%' ? "map" : "set");
  148. lua_newtable(lua);
  149. for (j = 0; j < mbulklen; j++) {
  150. p = redisProtocolToLuaType(lua,p);
  151. if (atype == '%') {
  152. p = redisProtocolToLuaType(lua,p);
  153. } else {
  154. if (!lua_checkstack(lua, 1)) {
  155. /* Notice that here we need to check the stack again because the recursive
  156. * call to redisProtocolToLuaType might have use the room allocated in the stack */
  157. serverPanic("lua stack limit reach when parsing redis.call reply");
  158. }
  159. lua_pushboolean(lua,1);
  160. }
  161. lua_settable(lua,-3);
  162. }
  163. lua_settable(lua,-3);
  164. }
  165. return p;
  166. }

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载