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::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; }
void Master::WriteSlaves(const DBID& dbid, RedisCommandFrame& cmd) { //DEBUG_LOG("WriteSlaves cmd:%s %u", cmd.ToString().c_str(), cmd.GetType()); switch (cmd.GetType()) { case REDIS_CMD_SELECT: { DBID id = 0; string_touint32(cmd.GetArguments()[0], id); m_backlog.SetCurrentDBID(id); break; } case REDIS_CMD_PING: { break; } default: { if (m_backlog.GetCurrentDBID() != dbid) { if (!m_server->m_cfg.master_host.empty()) { ERROR_LOG("Can NOT happen since slave instance can NOT generate select command."); } else { RedisCommandFrame select("select %u", dbid); select.SetType(REDIS_CMD_SELECT); m_backlog.SetCurrentDBID(dbid); WriteCmdToSlaves(select); } } break; } } WriteCmdToSlaves(cmd); }
int Ardb::Rename(Context& ctx, RedisCommandFrame& cmd) { bool withnx = cmd.GetType() == REDIS_CMD_RENAMENX; if (withnx) { RedisCommandFrame exists("Exists"); exists.AddArg(cmd.GetArguments()[1]); Exists(ctx, exists); if (ctx.reply.integer == 1) { fill_int_reply(ctx.reply, 0); return 0; } } else { DeleteKey(ctx, cmd.GetArguments()[1]); } KeyType type = KEY_END; GetType(ctx, cmd.GetArguments()[0], type); switch (type) { case SET_META: { RenameSet(ctx, ctx.currentDB, cmd.GetArguments()[0], ctx.currentDB, cmd.GetArguments()[1]); break; } case LIST_META: { RenameList(ctx, ctx.currentDB, cmd.GetArguments()[0], ctx.currentDB, cmd.GetArguments()[1]); break; } case ZSET_META: { RenameZSet(ctx, ctx.currentDB, cmd.GetArguments()[0], ctx.currentDB, cmd.GetArguments()[1]); break; } case HASH_META: { RenameHash(ctx, ctx.currentDB, cmd.GetArguments()[0], ctx.currentDB, cmd.GetArguments()[1]); break; } case STRING_META: { RenameString(ctx, ctx.currentDB, cmd.GetArguments()[0], ctx.currentDB, cmd.GetArguments()[1]); break; } case BITSET_META: { RenameBitset(ctx, ctx.currentDB, cmd.GetArguments()[0], ctx.currentDB, cmd.GetArguments()[1]); break; } default: { fill_error_reply(ctx.reply, "Invalid type to rename"); break; } } if (withnx) { fill_int_reply(ctx.reply, 1); } else { fill_status_reply(ctx.reply, "OK"); } return 0; }
int Comms::Scan(Context& ctx, RedisCommandFrame& cmd) { StringArray keys; std::string pattern; uint32 limit = 1000; //return max 1000 keys one time int arg_start = 0; if (cmd.GetType() != REDIS_CMD_SCAN) { arg_start = 1; } if (cmd.GetArguments().size() > arg_start + 1) { for (uint32 i = arg_start + 1; i < cmd.GetArguments().size(); i++) { if (!strcasecmp(cmd.GetArguments()[i].c_str(), "count")) { if (i + 1 >= cmd.GetArguments().size() || !string_touint32(cmd.GetArguments()[i + 1], limit)) { fill_error_reply(ctx.reply, "value is not an integer or out of range"); return 0; } i++; } else if (!strcasecmp(cmd.GetArguments()[i].c_str(), "match")) { if (i + 1 >= cmd.GetArguments().size()) { fill_error_reply(ctx.reply, "'MATCH' need one args followed"); return 0; } pattern = cmd.GetArguments()[i + 1]; i++; } else { fill_error_reply(ctx.reply, "Syntax error, try scan 0 "); return 0; } } } uint32 scan_count_limit = limit * 10; uint32 scan_count = 0; uint32 scan_cursor = 0; if (!string_touint32(cmd.GetArguments()[arg_start], scan_cursor)) { fill_error_reply(ctx.reply, "value is not an integer or out of range"); return 0; } RedisReply& r1 = ctx.reply.AddMember(); RedisReply& r2 = ctx.reply.AddMember(); r2.type = REDIS_REPLY_ARRAY; mmkv::StringArrayResult results(ReplyResultStringAlloc, &r2); int new_cursor = 0; switch (cmd.GetType()) { case REDIS_CMD_SCAN: { new_cursor = m_kv_store->Scan(ctx.currentDB, scan_cursor, pattern, scan_count_limit, results); break; } case REDIS_CMD_SSCAN: { new_cursor = m_kv_store->SScan(ctx.currentDB, cmd.GetArguments()[0], scan_cursor, pattern, scan_count_limit, results); break; } case REDIS_CMD_HSCAN: { new_cursor = m_kv_store->HScan(ctx.currentDB, cmd.GetArguments()[0], scan_cursor, pattern, scan_count_limit, results); break; } case REDIS_CMD_ZSCAN: { new_cursor = m_kv_store->ZScan(ctx.currentDB, cmd.GetArguments()[0], scan_cursor, pattern, scan_count_limit, results); break; } default: { new_cursor = 0; break; } } fill_int_reply(r1, new_cursor); return 0; }