소스 검색

更新 src/redis.cpp

1585346868 8 달 전
부모
커밋
5dcf7ca079
1개의 변경된 파일73개의 추가작업 그리고 2개의 파일을 삭제
  1. 73 2
      src/redis.cpp

+ 73 - 2
src/redis.cpp

@@ -206,7 +206,77 @@ sol::object module::redis::command(const std::string& cmd, sol::this_state ts)
 
 
 }
-
+sol::object module::redis::command_ex(const sol::table& args, sol::this_state ts)
+{
+    if (!args.valid()) {
+        throw ylib::exception("redis.command_ex: invalid arguments table");
+    }
+    
+    size_t table_size = args.size();
+    if (table_size == 0) {
+        throw ylib::exception("redis.command_ex: empty arguments table");
+    }
+    
+    // 使用智能指针自动管理内存
+    std::vector<std::unique_ptr<char[]>> buffers;
+    std::vector<const char*> argv;
+    std::vector<size_t> argvlen;
+    
+    buffers.reserve(table_size);
+    argv.reserve(table_size);
+    argvlen.reserve(table_size);
+    
+    // 构建参数数组
+    for (size_t i = 1; i <= table_size; ++i) {
+        sol::object arg = args[i];
+        if (!arg.is<std::string>()) {
+            throw ylib::exception("redis.command_ex: argument at index "+std::to_string(i)+" is not a string");
+        }
+        
+        std::string str = arg.as<std::string>();
+        auto buffer = std::make_unique<char[]>(str.length() + 1);
+        std::strcpy(buffer.get(), str.c_str());
+        
+        argv.push_back(buffer.get());
+        argvlen.push_back(str.length());
+        buffers.push_back(std::move(buffer)); // 转移所有权
+    }
+    
+    // 执行命令
+    redisReply* reply = (redisReply*)redisCommandArgv(
+        m_context, 
+        table_size, 
+        argv.data(), 
+        argvlen.data()
+    );
+    
+    // 处理错误
+    if (reply == NULL) {
+        if (m_context->err) {
+            m_context = m_pool->reget(m_context);
+            if (m_context == NULL || m_context->err) {
+                throw ylib::exception("Failed to reacquire Redis connection");
+            }
+            
+            // 重新执行(buffers仍然持有内存,可以重用)
+            reply = (redisReply*)redisCommandArgv(
+                m_context, 
+                table_size, 
+                argv.data(), 
+                argvlen.data()
+            );
+            
+            if (reply == NULL) {
+                throw ylib::exception(std::string("Redis command failed after retry: ") + m_context->errstr);
+            }
+        }
+        else {
+            throw ylib::exception("Unknown error: reply is NULL but context has no error");
+        }
+    }
+    
+    return m_pool->reply(&ts, m_context, reply);
+}
 void module::redis_regist(sol::state* lua)
 {
     lua->new_usertype<module::redis_pool>("fw_redis_pool",
@@ -217,6 +287,7 @@ void module::redis_regist(sol::state* lua)
         "self", &module::redis_pool::self
     );
     lua->new_usertype<module::redis>("fw_redis_conn",
-        "command", &module::redis::command
+        "command", &module::redis::command,
+        "command_ex", &module::redis::command_ex
     );
 }