Exemple #1
0
 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;
                     }
                 }
             }
         }
     }
 }
Exemple #2
0
 bool conf_get_int64(const Properties& conf, const std::string& name, int64& value, bool ignore_nonexist)
 {
     Properties::const_iterator found = conf.find(name);
     if (found == conf.end())
     {
         return ignore_nonexist;
     }
     if (string_toint64(found->second, value))
     {
         return true;
     }
     std::string size_str = string_toupper(found->second);
     value = atoll(size_str.c_str());
     if (size_str.find("M") == (size_str.size() - 1) || size_str.find("MB") == (size_str.size() - 2))
     {
         value *= (1024 * 1024); // convert to megabytes
     }
     else if (size_str.find("G") == (size_str.size() - 1) || size_str.find("GB") == (size_str.size() - 2))
     {
         value *= (1024 * 1024 * 1024); // convert to kilobytes
     }
     else if (size_str.find("K") == (size_str.size() - 1) || size_str.find("KB") == (size_str.size() - 2))
     {
         value *= 1024; // convert to kilobytes
     }
     else
     {
         return false;
     }
     return true;
 }
Exemple #3
0
	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);
	}
Exemple #4
0
 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);
     }
 }
Exemple #5
0
 int ArdbServer::Decrby(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     int64 decrement, val;
     if (!string_toint64(cmd.GetArguments()[1], decrement))
     {
         fill_error_reply(ctx.reply, "value is not an integer or out of range");
         return 0;
     }
     int ret = m_db->Decrby(ctx.currentDB, cmd.GetArguments()[0], decrement, val);
     if (ret == 0)
     {
         fill_int_reply(ctx.reply, val);
     }
     else
     {
         fill_error_reply(ctx.reply, "value is not an integer or out of range");
     }
     return 0;
 }
Exemple #6
0
    void Slave::HandleRedisReply(Channel* ch, RedisReply& reply)
    {
        switch (m_slave_state)
        {
            case SLAVE_STATE_WAITING_INFO_REPLY:
            {
                if (reply.type == REDIS_REPLY_ERROR)
                {
                    ERROR_LOG("Recv info reply error:%s", reply.str.c_str());
                    Close();
                    return;
                }
                const char* redis_ver_key = "redis_version:";
                if (reply.str.find(redis_ver_key) != std::string::npos)
                {
                    m_server_type = REDIS_DB_SERVER_TYPE;
                    size_t start = reply.str.find(redis_ver_key);
                    size_t end = reply.str.find("\n", start);
                    std::string v = reply.str.substr(start + strlen(redis_ver_key),
                            end - start - strlen(redis_ver_key));
                    v = trim_string(v);
                    m_server_support_psync = (compare_version<3>(v, "2.7.0") >= 0);
                    INFO_LOG("[Slave]Remote master is a Redis %s instance, support partial sync:%u", v.c_str(),
                            m_server_support_psync);

                }
                else
                {
                    INFO_LOG("[Slave]Remote master is an Ardb instance.");
                    m_server_type = ARDB_DB_SERVER_TYPE;
                    m_server_support_psync = true;
                }
                Buffer replconf;
                replconf.Printf("replconf listening-port %u\r\n", m_serv->GetServerConfig().listen_port);
                ch->Write(replconf);
                m_slave_state = SLAVE_STATE_WAITING_REPLCONF_REPLY;
                break;
            }
            case SLAVE_STATE_WAITING_REPLCONF_REPLY:
            {
                if (reply.type == REDIS_REPLY_ERROR)
                {
                    ERROR_LOG("Recv replconf reply error:%s", reply.str.c_str());
                    ch->Close();
                    return;
                }
                if (m_server_support_psync)
                {
                    Buffer sync;
                    if (m_server_type == ARDB_DB_SERVER_TYPE)
                    {
                        std::string includes = "*";
                        std::string excludes = "-";
                        if (!m_include_dbs.empty())
                        {
                            includes = string_join_container(m_include_dbs, "|");
                        }
                        if (!m_exclude_dbs.empty())
                        {
                            excludes = string_join_container(m_exclude_dbs, "|");
                        }
                        sync.Printf("apsync %s %lld cksm %llu include %s exclude %s\r\n", m_backlog.GetServerKey(),
                                m_backlog.GetReplEndOffset(), m_backlog.GetChecksum(), includes.c_str(),
                                excludes.c_str());
                    }
                    else
                    {
                        sync.Printf("psync %s %lld\r\n", m_backlog.GetServerKey(), m_backlog.GetReplEndOffset());
                        INFO_LOG("Send PSYNC %s %lld", m_backlog.GetServerKey(), m_backlog.GetReplEndOffset());
                    }
                    ch->Write(sync);
                    m_slave_state = SLAVE_STATE_WAITING_PSYNC_REPLY;
                }
                else
                {
                    Buffer sync;
                    sync.Printf("sync\r\n");
                    ch->Write(sync);
                    m_slave_state = SLAVE_STATE_SYNING_DUMP_DATA;
                    m_decoder.SwitchToDumpFileDecoder();
                }
                break;
            }
            case SLAVE_STATE_WAITING_PSYNC_REPLY:
            {
                if (reply.type != REDIS_REPLY_STATUS)
                {
                    ERROR_LOG("Recv psync reply error:%s", reply.str.c_str());
                    ch->Close();
                    return;
                }
                INFO_LOG("Recv psync reply:%s", reply.str.c_str());
                std::vector<std::string> ss = split_string(reply.str, " ");
                if (!strcasecmp(ss[0].c_str(), "FULLRESYNC"))
                {
                    int64 offset;
                    if (!string_toint64(ss[2], offset))
                    {
                        ERROR_LOG("Invalid psync offset:%s", ss[2].c_str());
                        ch->Close();
                        return;
                    }
                    /*
                     * Delete all data before receiving resyncing data
                     */
                    if (m_serv->m_cfg.slave_cleardb_before_fullresync)
                    {
                        m_serv->m_db->FlushAll();
                    }
                    m_backlog.SetServerkey(ss[1]);
                    m_backlog.SetReplOffset(offset);
                    if (m_server_type == ARDB_DB_SERVER_TYPE)
                    {
                        //Do NOT change state, since master would send  "FULLSYNCED" after all data synced
                        m_decoder.SwitchToCommandDecoder();
                        return;
                    }
                }
                else if (!strcasecmp(ss[0].c_str(), "CONTINUE"))
                {
                    m_decoder.SwitchToCommandDecoder();
                    m_slave_state = SLAVE_STATE_SYNCED;
                    break;
                }
                else
                {
                    ERROR_LOG("Invalid psync status:%s", reply.str.c_str());
                    ch->Close();
                    return;
                }
                m_slave_state = SLAVE_STATE_SYNING_DUMP_DATA;
                m_decoder.SwitchToDumpFileDecoder();
                break;
            }
            default:
            {
                ERROR_LOG("Slave client is in invalid state:%d", m_slave_state);
                Close();
                break;
            }
        }
    }