//===================================encoder============================== bool RedisCommandEncoder::Encode(Buffer& buf, const RedisCommandFrame& cmd) { buf.Printf("*%d\r\n", cmd.GetArguments().size() + 1); buf.Printf("$%d\r\n", cmd.GetCommand().size()); buf.Write(cmd.GetCommand().data(), cmd.GetCommand().size()); buf.Write("\r\n", 2); for (uint32 i = 0; i < cmd.GetArguments().size(); i++) { const std::string* arg = cmd.GetArgument(i); buf.Printf("$%d\r\n", arg->size()); buf.Write(arg->data(), arg->size()); buf.Write("\r\n", 2); } return true; }
void Master::AddSlave(Channel* slave, RedisCommandFrame& cmd) { DEBUG_LOG("Recv sync command:%s", cmd.ToString().c_str()); slave->Flush(); SlaveConnection* conn = NULL; NEW(conn, SlaveConnection); conn->conn = slave; if (!strcasecmp(cmd.GetCommand().c_str(), "sync")) { //Redis 2.6/2.4 send 'sync' conn->isRedisSlave = true; conn->sync_offset = -1; } else { conn->server_key = cmd.GetArguments()[0]; const std::string& offset_str = cmd.GetArguments()[1]; if (!string_toint64(offset_str, conn->sync_offset)) { ERROR_LOG("Invalid offset argument:%s", offset_str.c_str()); slave->Close(); DELETE(conn); return; } //Redis 2.8+ send psync, Ardb send psync2 if (!strcasecmp(cmd.GetCommand().c_str(), "psync")) { conn->isRedisSlave = true; } else { conn->isRedisSlave = false; if (cmd.GetArguments().size() >= 3) { std::vector<std::string> ss = split_string(cmd.GetArguments()[2], "|"); for (uint32 i = 0; i < ss.size(); i++) { DBID id; if (string_touint32(ss[i], id)) { conn->syncdbs.insert(id); } } } } } m_server->m_service->DetachChannel(slave, true); ReplicationInstruction inst(conn, REPL_INSTRUCTION_ADD_SLAVE); OfferReplInstruction(inst); }
void Master::MessageReceived(ChannelHandlerContext& ctx, MessageEvent<RedisCommandFrame>& e) { RedisCommandFrame* cmd = e.GetMessage(); DEBUG_LOG("Master recv cmd from slave:%s", cmd->ToString().c_str()); if (!strcasecmp(cmd->GetCommand().c_str(), "replconf")) { if (cmd->GetArguments().size() == 2 && !strcasecmp(cmd->GetArguments()[0].c_str(), "ack")) { int64 offset; if (string_toint64(cmd->GetArguments()[1], offset)) { SlaveConnTable::iterator found = m_slaves.find(ctx.GetChannel()->GetID()); if (found != m_slaves.end()) { SlaveConn* slave = found->second; if (NULL != slave) { slave->acktime = time(NULL); slave->ack_offset = offset; } } } } } }
int ArdbServer::Exec(ArdbConnContext& ctx, RedisCommandFrame& cmd) { if (ctx.fail_transc || !ctx.in_transaction) { ctx.reply.type = REDIS_REPLY_NIL; } else { RedisReply r; r.type = REDIS_REPLY_ARRAY; if (NULL != ctx.transaction_cmds) { for (uint32 i = 0; i < ctx.transaction_cmds->size(); i++) { RedisCommandFrame& cmd = ctx.transaction_cmds->at(i); DoRedisCommand(ctx, FindRedisCommandHandlerSetting(cmd.GetCommand()), cmd); r.elements.push_back(ctx.reply); } } ctx.reply = r; } ctx.in_transaction = false; DELETE(ctx.transaction_cmds); ClearWatchKeys(ctx); return 0; }
void Slave::HandleRedisCommand(Channel* ch, RedisCommandFrame& cmd) { int flag = ARDB_PROCESS_REPL_WRITE; if (m_slave_state == SLAVE_STATE_SYNCED || m_slave_state == SLAVE_STATE_LOADING_DUMP_DATA) { flag |= ARDB_PROCESS_FORCE_REPLICATION; } else { flag |= ARDB_PROCESS_WITHOUT_REPLICATION; } DEBUG_LOG("Recv master cmd %s at %lld at flag:%d at state:%d", cmd.ToString().c_str(), m_backlog.GetReplEndOffset(), flag, m_slave_state); if (m_slave_state == SLAVE_STATE_WAITING_PSYNC_REPLY && m_server_type == ARDB_DB_SERVER_TYPE) { if (!strcasecmp(cmd.GetCommand().c_str(), "FULLSYNCED")) { uint64 offset, cksm; string_touint64(cmd.GetArguments()[0], offset); string_touint64(cmd.GetArguments()[1], cksm); m_backlog.SetChecksum(cksm); ASSERT(offset == m_backlog.GetReplEndOffset()); //m_backlog.SetReplOffset(offset); m_slave_state = SLAVE_STATE_SYNCED; //Disconnect all slaves when all data resynced m_serv->m_master_serv.DisconnectAllSlaves(); return; } } if (!strcasecmp(cmd.GetCommand().c_str(), "PING")) { m_ping_recved_time = time(NULL); } else if (!strcasecmp(cmd.GetCommand().c_str(), "SELECT")) { DBID id = 0; string_touint32(cmd.GetArguments()[0], id); m_backlog.SetCurrentDBID(id); } GetArdbConnContext(); m_actx->is_slave_conn = true; m_actx->conn = ch; if (strcasecmp(cmd.GetCommand().c_str(), "SELECT") && strcasecmp(cmd.GetCommand().c_str(), "__SET__") && strcasecmp(cmd.GetCommand().c_str(), "__DEL__")) { if (!m_include_dbs.empty() && m_include_dbs.count(m_actx->currentDB) == 0) { flag |= ARDB_PROCESS_FEED_REPLICATION_ONLY; } if (!m_exclude_dbs.empty() && m_exclude_dbs.count(m_actx->currentDB) > 0) { flag |= ARDB_PROCESS_FEED_REPLICATION_ONLY; } } m_serv->ProcessRedisCommand(*m_actx, cmd, flag); }
void Master::AddSlave(Channel* slave, RedisCommandFrame& cmd) { INFO_LOG("[Master]Recv sync command:%s", cmd.ToString().c_str()); slave->Flush(); SlaveConn& conn = GetSlaveConn(slave); if (!strcasecmp(cmd.GetCommand().c_str(), "sync")) { //Redis 2.6/2.4 send 'sync' conn.isRedisSlave = true; conn.sync_offset = -1; } else { conn.server_key = cmd.GetArguments()[0]; const std::string& offset_str = cmd.GetArguments()[1]; if (!string_toint64(offset_str, conn.sync_offset)) { ERROR_LOG("Invalid offset argument:%s", offset_str.c_str()); slave->Close(); return; } conn.isRedisSlave = true; for (uint32 i = 2; i < cmd.GetArguments().size(); i += 2) { if (cmd.GetArguments()[i] == "cksm") { conn.isRedisSlave = false; if (!string_touint64(cmd.GetArguments()[i + 1], conn.sync_cksm)) { ERROR_LOG("Invalid checksum argument:%s", cmd.GetArguments()[i + 1].c_str()); slave->Close(); return; } } } } slave->GetService().DetachChannel(slave, true); if (g_repl->GetIOServ().IsInLoopThread()) { AddSlave(&conn); } else { g_repl->GetIOServ().AsyncIO(0, OnAddSlave, &conn); } }