RedisReplyArray* CoroRedisClient::SyncMultiCall(RedisCommandFrameArray& cmds, int timeout) { Clear(); m_expected_multi_reply_count = cmds.size(); for (size_t i = 0; i < cmds.size(); i++) { m_ch->Write(cmds[i]); } CreateTimeoutTask(timeout); if (0 != WaitCoro()) { return NULL; } if (!m_connect_success) { m_error_reply.SetErrorReason("client connection closed."); FillErrorReply(); return &m_multi_replies; } if (IsTimeout()) { m_error_reply.SetErrorReason("server timeout."); FillErrorReply(); return &m_multi_replies; } CancelTimeoutTask(); return &m_multi_replies; }
int Comms::RPopLPush(Context& ctx, RedisCommandFrame& cmd) { std::string v; int err = m_kv_store->RPopLPush(ctx.currentDB, cmd.GetArguments()[0], cmd.GetArguments()[1], v); if (err >= 0) { fill_str_reply(ctx.reply, v); FireKeyChangedEvent(ctx, cmd.GetArguments()[0]); FireKeyChangedEvent(ctx, cmd.GetArguments()[1]); if (cmd.GetType() == REDIS_CMD_BRPOPLPUSH) { ctx.current_cmd->SetCommand("rpoplpush"); } } else { if (err == mmkv::ERR_ENTRY_NOT_EXIST || err == mmkv::ERR_DB_NOT_EXIST) { ctx.reply.type = REDIS_REPLY_NIL; } else { FillErrorReply(ctx, err); } } return 0; }
OP_NAMESPACE_BEGIN int Comms::LIndex(Context& ctx, RedisCommandFrame& cmd) { int64 index; if (!GetInt64Value(ctx, cmd.GetArguments()[1], index)) { return 0; } std::string v; int err = m_kv_store->LIndex(ctx.currentDB, cmd.GetArguments()[0], index, v); if (err >= 0) { fill_str_reply(ctx.reply, v); } else if (mmkv::ERR_OFFSET_OUTRANGE == err) { ctx.reply.type = REDIS_REPLY_NIL; } else { FillErrorReply(ctx, err); } return 0; }
int Comms::LInsert(Context& ctx, RedisCommandFrame& cmd) { bool before_or_after = false; if (!strcasecmp(cmd.GetArguments()[1].c_str(), "before")) { before_or_after = true; } else if (!strcasecmp(cmd.GetArguments()[1].c_str(), "after")) { before_or_after = false; } else { fill_error_reply(ctx.reply, "Syntax error"); return 0; } int err = m_kv_store->LInsert(ctx.currentDB, cmd.GetArguments()[0], before_or_after, cmd.GetArguments()[2], cmd.GetArguments()[3]); if (err >= 0 || -1 == err) { fill_int_reply(ctx.reply, err); if (err > 0) { FireKeyChangedEvent(ctx, cmd.GetArguments()[0]); } } else { FillErrorReply(ctx, err); } return 0; }
int Comms::Del(Context& ctx, RedisCommandFrame& cmd) { mmkv::DataArray fs; for (uint32 i = 0; i < cmd.GetArguments().size(); i++) { fs.push_back(cmd.GetArguments()[i]); } int err = m_kv_store->Del(ctx.currentDB, fs); if (err >= 0) { if (err > 0) { for (uint32 i = 0; i < cmd.GetArguments().size(); i++) { FireKeyChangedEvent(ctx, cmd.GetArguments()[i]); } } fill_int_reply(ctx.reply, err); } else { FillErrorReply(ctx, err); } return 0; }
int Comms::LLen(Context& ctx, RedisCommandFrame& cmd) { int err = m_kv_store->LLen(ctx.currentDB, cmd.GetArguments()[0]); if (err >= 0) { fill_int_reply(ctx.reply, err); } else { FillErrorReply(ctx, err); } return 0; }
int Comms::BLPop(Context& ctx, RedisCommandFrame& cmd) { uint32 timeout; if (!string_touint32(cmd.GetArguments()[cmd.GetArguments().size() - 1], timeout)) { fill_error_reply(ctx.reply, "timeout is not an integer or out of range"); return 0; } bool lpop = cmd.GetType() == REDIS_CMD_BLPOP; for (uint32 i = 0; i < cmd.GetArguments().size() - 1; i++) { std::string v; int err = lpop ? m_kv_store->LPop(ctx.currentDB, cmd.GetArguments()[i], v) : m_kv_store->RPop(ctx.currentDB, cmd.GetArguments()[i], v); if (0 == err && !v.empty()) { RedisReply& r1 = ctx.reply.AddMember(); RedisReply& r2 = ctx.reply.AddMember(); fill_str_reply(r1, cmd.GetArguments()[i]); fill_str_reply(r2, v); FireKeyChangedEvent(ctx, ctx.currentDB, cmd.GetArguments()[i]); RedisCommandFrame list_pop(lpop ? "lpop" : "rpop"); list_pop.AddArg(cmd.GetArguments()[i]); RewriteClientCommand(ctx, list_pop); return 0; } if (err != 0 && err != mmkv::ERR_ENTRY_NOT_EXIST && err != mmkv::ERR_DB_NOT_EXIST) { FillErrorReply(ctx, err); return 0; } } if (NULL != ctx.client) { ctx.client->DetachFD(); ctx.GetBlockContext().lpop = cmd.GetType() == REDIS_CMD_BLPOP; if (timeout > 0) { ctx.block->blocking_timer_task_id = ctx.client->GetService().GetTimer().ScheduleHeapTask( new BlockListTimeout(&ctx), timeout, -1, SECONDS); } } for (uint32 i = 0; i < cmd.GetArguments().size() - 1; i++) { AddBlockKey(ctx, cmd.GetArguments()[i]); } return 0; }
int Comms::Rename(Context& ctx, RedisCommandFrame& cmd) { int err = m_kv_store->Rename(ctx.currentDB, cmd.GetArguments()[0], cmd.GetArguments()[1]); if (err >= 0) { FireKeyChangedEvent(ctx, cmd.GetArguments()[0]); FireKeyChangedEvent(ctx, cmd.GetArguments()[1]); fill_ok_reply(ctx.reply); } else { FillErrorReply(ctx, err); } return 0; }
int Comms::LRange(Context& ctx, RedisCommandFrame& cmd) { int64 start, end; if (!GetInt64Value(ctx, cmd.GetArguments()[1], start) || !GetInt64Value(ctx, cmd.GetArguments()[2], end)) { return 0; } ctx.reply.type = REDIS_REPLY_ARRAY; mmkv::StringArrayResult vs(ReplyResultStringAlloc, &ctx.reply); int err = m_kv_store->LRange(ctx.currentDB, cmd.GetArguments()[0], start, end, vs); if (err < 0) { FillErrorReply(ctx, err); } return 0; }
void Comms::WakeBlockedList(Context& ctx, const std::string& key) { std::string v; int err = ctx.GetBlockContext().lpop ? m_kv_store->LPop(ctx.currentDB, key, v) : m_kv_store->RPop(ctx.currentDB, key, v); if (0 == err && !v.empty()) { if (ctx.GetBlockContext().push_key.empty()) { RedisReply& r1 = ctx.reply.AddMember(); RedisReply& r2 = ctx.reply.AddMember(); fill_str_reply(r1, key); fill_str_reply(r2, v); if (!ctx.flags.no_wal) { RedisCommandFrame list_pop(ctx.GetBlockContext().lpop ? "lpop" : "rpop"); list_pop.AddArg(key); m_repl.WriteWAL(ctx.currentDB, list_pop); } } else { err = m_kv_store->RPush(ctx.currentDB, ctx.GetBlockContext().push_key, v); if (err < 0) { ctx.GetBlockContext().lpop ? m_kv_store->LPush(ctx.currentDB, key, v) : m_kv_store->RPush(ctx.currentDB, key, v); FillErrorReply(ctx, err); } else { fill_str_reply(ctx.reply, v); if (!ctx.flags.no_wal) { RedisCommandFrame rpoplpush("rpoplpush"); rpoplpush.AddArg(key); m_repl.WriteWAL(ctx.currentDB, rpoplpush); } } } ctx.client->Write(ctx.reply); ctx.client->AttachFD(); ClearBlockKeys(ctx); } }
int Comms::Persist(Context& ctx, RedisCommandFrame& cmd) { int err = m_kv_store->Persist(ctx.currentDB, cmd.GetArguments()[0]); if (err >= 0) { if (err > 0) { FireKeyChangedEvent(ctx, cmd.GetArguments()[0]); } fill_int_reply(ctx.reply, err); } else { FillErrorReply(ctx, err); } return 0; }
int Comms::LSet(Context& ctx, RedisCommandFrame& cmd) { int64 index; if (!GetInt64Value(ctx, cmd.GetArguments()[1], index)) { return 0; } int err = m_kv_store->LSet(ctx.currentDB, cmd.GetArguments()[0], index, cmd.GetArguments()[2]); if (err >= 0) { fill_ok_reply(ctx.reply); FireKeyChangedEvent(ctx, cmd.GetArguments()[0]); } else { FillErrorReply(ctx, err); } return 0; }
int Comms::LTrim(Context& ctx, RedisCommandFrame& cmd) { int64 start, end; if (!GetInt64Value(ctx, cmd.GetArguments()[1], start) || !GetInt64Value(ctx, cmd.GetArguments()[2], end)) { return 0; } int err = m_kv_store->LTrim(ctx.currentDB, cmd.GetArguments()[0], start, end); if (err >= 0) { fill_ok_reply(ctx.reply); FireKeyChangedEvent(ctx, cmd.GetArguments()[0]); } else { FillErrorReply(ctx, err); } return 0; }
int Comms::RPush(Context& ctx, RedisCommandFrame& cmd) { mmkv::DataArray fs; for (uint32 i = 1; i < cmd.GetArguments().size(); i++) { fs.push_back(cmd.GetArguments()[i]); } int err = m_kv_store->RPush(ctx.currentDB, cmd.GetArguments()[0], fs); if (err >= 0) { fill_int_reply(ctx.reply, err); FireKeyChangedEvent(ctx, cmd.GetArguments()[0]); WakeBlockingListsByKey(ctx, cmd.GetArguments()[0]); } else { FillErrorReply(ctx, err); } return 0; }
int Comms::Expireat(Context& ctx, RedisCommandFrame& cmd) { uint64 v = 0; if (!check_uint64_arg(ctx.reply, cmd.GetArguments()[1], v)) { return 0; } int err = m_kv_store->PExpireat(ctx.currentDB, cmd.GetArguments()[0], v * 1000); if (err >= 0) { if (err > 0) { FireKeyChangedEvent(ctx, cmd.GetArguments()[0]); } fill_int_reply(ctx.reply, err); } else { FillErrorReply(ctx, err); } return 0; }
int Comms::RPop(Context& ctx, RedisCommandFrame& cmd) { std::string v; int err = m_kv_store->RPop(ctx.currentDB, cmd.GetArguments()[0], v); if (err >= 0) { fill_str_reply(ctx.reply, v); FireKeyChangedEvent(ctx, cmd.GetArguments()[0]); } else { if (err == mmkv::ERR_ENTRY_NOT_EXIST || err == mmkv::ERR_DB_NOT_EXIST) { ctx.reply.type = REDIS_REPLY_NIL; } else { FillErrorReply(ctx, err); } } return 0; }
int Comms::LRem(Context& ctx, RedisCommandFrame& cmd) { int64 count; if (!GetInt64Value(ctx, cmd.GetArguments()[1], count)) { return 0; } int err = m_kv_store->LRem(ctx.currentDB, cmd.GetArguments()[0], count, cmd.GetArguments()[2]); if (err >= 0) { fill_int_reply(ctx.reply, err); if (err > 0) { FireKeyChangedEvent(ctx, cmd.GetArguments()[0]); } } else { FillErrorReply(ctx, err); } return 0; }
int Comms::Move(Context& ctx, RedisCommandFrame& cmd) { DBID dst = 0; if (!string_touint32(cmd.GetArguments()[1], dst)) { fill_error_reply(ctx.reply, "value is not an integer or out of range"); return 0; } int err = m_kv_store->Move(ctx.currentDB, cmd.GetArguments()[0], dst); if (err >= 0) { if (err > 0) { FireKeyChangedEvent(ctx, cmd.GetArguments()[0]); FireKeyChangedEvent(ctx, dst, cmd.GetArguments()[0]); } fill_int_reply(ctx.reply, err); } else { FillErrorReply(ctx, err); } return 0; }
int Comms::Sort(Context& ctx, RedisCommandFrame& cmd) { bool is_desc = false, with_alpha = false, with_limit = false; const ArgumentArray& args = cmd.GetArguments(); const std::string& key = args[0]; std::string by, store_dst; mmkv::StringArray get_patterns; int limit_offset = 0, limit_count = -1; for (uint32 i = 1; i < args.size(); i++) { if (!strcasecmp(args[i].c_str(), "asc")) { is_desc = false; } else if (!strcasecmp(args[i].c_str(), "desc")) { is_desc = true; } else if (!strcasecmp(args[i].c_str(), "alpha")) { with_alpha = true; } else if (!strcasecmp(args[i].c_str(), "limit") && (i + 2) < args.size()) { with_limit = true; if (!string_toint32(args[i + 1], limit_offset) || !string_toint32(args[i + 2], limit_count)) { return false; } i += 2; } else if (!strcasecmp(args[i].c_str(), "store") && i < args.size() - 1) { store_dst = args[i + 1]; i++; } else if (!strcasecmp(args[i].c_str(), "by") && i < args.size() - 1) { by = args[i + 1]; i++; } else if (!strcasecmp(args[i].c_str(), "get") && i < args.size() - 1) { get_patterns.push_back(args[i + 1].c_str()); i++; } else { DEBUG_LOG("Invalid sort option:%s", args[i].c_str()); return false; } } int err = 0; if (store_dst.empty()) { ctx.reply.type = REDIS_REPLY_ARRAY; mmkv::StringArrayResult results(ReplyResultStringAlloc, &ctx.reply); err = m_kv_store->Sort(ctx.currentDB, key, by, limit_offset, limit_count, get_patterns, is_desc, with_alpha, store_dst, results); } else { ctx.reply.type = REDIS_REPLY_INTEGER; mmkv::StringArrayResult results; err = m_kv_store->Sort(ctx.currentDB, key, by, limit_offset, limit_count, get_patterns, is_desc, with_alpha, store_dst, results); ctx.reply.integer = err >= 0 ? err : 0; if(err > 0) { FireKeyChangedEvent(ctx, store_dst); } } if (err < 0) { FillErrorReply(ctx, err); } return 0; }