Example #1
0
 int Ardb::BRPopLPush(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;
     }
     RPopLPush(ctx, cmd);
     if (ctx.reply.type == REDIS_REPLY_NIL)
     {
         //block;
         AddBlockKey(ctx, cmd.GetArguments()[0]);
         if (NULL != ctx.client)
         {
             ctx.client->DetachFD();
             if (timeout > 0)
             {
                 ctx.block->blocking_timer_task_id = ctx.client->GetService().GetTimer().ScheduleHeapTask(
                         new BlockConnectionTimeout(&ctx), timeout, -1, SECONDS);
             }
         }
         ctx.reply.type = 0;
     }
     return 0;
 }
Example #2
0
File: keys.cpp Project: boreys/ardb
 int Ardb::Keys(Context& ctx, RedisCommandFrame& cmd)
 {
     KeysOptions opt;
     opt.op = OP_GET;
     opt.pattern = cmd.GetArguments()[0];
     uint32 limit = 100000; //return max 100000 keys one time
     if (cmd.GetArguments().size() > 1)
     {
         for (uint32 i = 1; i < cmd.GetArguments().size(); i++)
         {
             if (!strcasecmp(cmd.GetArguments()[i].c_str(), "limit"))
             {
                 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
             {
                 fill_error_reply(ctx.reply, "Syntax error, try KEYS ");
                 return 0;
             }
         }
     }
     opt.limit = limit;
     KeysOperation(ctx, opt);
     return 0;
 }
Example #3
0
 int Ardb::BRPop(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;
     }
     for (uint32 i = 0; i < cmd.GetArguments().size() - 1; i++)
     {
         if (ListPop(ctx, cmd.GetArguments()[i], false) == 0 && ctx.reply.type == REDIS_REPLY_STRING)
         {
             RedisReply& r1 = ctx.reply.AddMember();
             RedisReply& r2 = ctx.reply.AddMember();
             fill_str_reply(r1, cmd.GetArguments()[i]);
             fill_str_reply(r2, ctx.reply.str);
             return 0;
         }
     }
     for (uint32 i = 0; i < cmd.GetArguments().size() - 1; i++)
     {
         AddBlockKey(ctx, cmd.GetArguments()[i]);
     }
     if (NULL != ctx.client)
     {
         ctx.client->DetachFD();
         if (timeout > 0)
         {
             ctx.block->blocking_timer_task_id = ctx.client->GetService().GetTimer().ScheduleHeapTask(
                     new BlockConnectionTimeout(&ctx), timeout, -1, SECONDS);
         }
     }
     return 0;
 }
Example #4
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);
    }
Example #5
0
 int ArdbServer::Select(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     if (!string_touint32(cmd.GetArguments()[0], ctx.currentDB) || ctx.currentDB > 0xFFFFFF)
     {
         fill_error_reply(ctx.reply, "value is not an integer or out of range");
         return 0;
     }
     m_clients_holder.ChangeCurrentDB(ctx.conn, ctx.currentDB);
     fill_status_reply(ctx.reply, "OK");
     return 0;
 }
Example #6
0
 int ArdbServer::PSetEX(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     uint32 mills;
     if (!string_touint32(cmd.GetArguments()[1], mills))
     {
         fill_error_reply(ctx.reply, "value is not an integer or out of range");
         return 0;
     }
     m_db->PSetEx(ctx.currentDB, cmd.GetArguments()[0], cmd.GetArguments()[2], mills);
     fill_status_reply(ctx.reply, "OK");
     return 0;
 }
Example #7
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;
    }
Example #8
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);
	}
Example #9
0
 int split_uint32_array(const std::string& str, const std::string& sep, std::vector<uint32>& array)
 {
     if (str.empty())
     {
         return 0;
     }
     std::vector<std::string> ss = split_string(str, sep);
     for (uint32 i = 0; i < ss.size(); i++)
     {
         uint32 id;
         if (!string_touint32(ss[i], id))
         {
             return -1;
         }
         else
         {
             array.push_back(id);
         }
     }
     return 0;
 }
Example #10
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);
	}
Example #11
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;
 }
Example #12
0
File: keys.cpp Project: boreys/ardb
    int Ardb::Scan(Context& ctx, RedisCommandFrame& cmd)
    {
        StringArray keys;
        std::string pattern;
        uint32 limit = 10000; //return max 10000 keys one time
        if (cmd.GetArguments().size() > 1)
        {
            for (uint32 i = 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;
                }
            }
        }
        RedisReply& r1 = ctx.reply.AddMember();
        RedisReply& r2 = ctx.reply.AddMember();
        r2.type = REDIS_REPLY_ARRAY;

        KeyObject from;
        from.db = ctx.currentDB;
        from.type = KEY_META;
        const std::string& cursor = cmd.GetArguments()[0];
        std::string scan_start_cursor;
        if (cmd.GetArguments()[0] != "0")
        {
            if (m_cfg.scan_redis_compatible)
            {
                FindElementByRedisCursor(cursor, scan_start_cursor);
            }
            from.key = scan_start_cursor;
        }
        Iterator* iter = IteratorKeyValue(from, false);
        bool reachend = false;
        std::string tmpkey;
        while (NULL != iter && iter->Valid())
        {
            KeyObject kk;
            if (!decode_key(iter->Key(), kk) || kk.db != ctx.currentDB || kk.type != KEY_META)
            {
                reachend = true;
                break;
            }
            tmpkey.clear();
            tmpkey.assign(kk.key.data(), kk.key.size());
            if (r2.MemberSize() >= limit)
            {
                break;
            }
            if ((pattern.empty()
                    || stringmatchlen(pattern.c_str(), pattern.size(), tmpkey.c_str(), tmpkey.size(), 0) == 1))
            {
                RedisReply& rr1 = r2.AddMember();
                fill_str_reply(rr1, tmpkey);
            }
            iter->Next();
        }
        if (reachend || !iter->Valid())
        {
            fill_str_reply(r1, "0");
        }
        else
        {
            if (m_cfg.scan_redis_compatible)
            {
                uint64 newcursor = GetNewRedisCursor(tmpkey);
                fill_str_reply(r1, stringfromll(newcursor));
            }
            else
            {
                fill_str_reply(r1, tmpkey);
            }
        }
        DELETE(iter);
        return 0;
    }
Example #13
0
File: keys.cpp Project: boreys/ardb
 int Ardb::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;
     }
     RedisCommandFrame exists("Exists");
     exists.AddArg(cmd.GetArguments()[0]);
     Context tmpctx;
     tmpctx.currentDB = dst;
     Exists(tmpctx, exists);
     if (ctx.reply.integer == 1)
     {
         fill_int_reply(ctx.reply, 0);
         return 0;
     }
     KeyType type = KEY_END;
     GetType(ctx, cmd.GetArguments()[0], type);
     switch (type)
     {
         case SET_META:
         {
             RenameSet(ctx, ctx.currentDB, cmd.GetArguments()[0], dst, cmd.GetArguments()[0]);
             break;
         }
         case LIST_META:
         {
             RenameList(ctx, ctx.currentDB, cmd.GetArguments()[0], dst, cmd.GetArguments()[0]);
             break;
         }
         case ZSET_META:
         {
             RenameZSet(ctx, ctx.currentDB, cmd.GetArguments()[0], dst, cmd.GetArguments()[0]);
             break;
         }
         case HASH_META:
         {
             RenameHash(ctx, ctx.currentDB, cmd.GetArguments()[0], dst, cmd.GetArguments()[0]);
             break;
         }
         case STRING_META:
         {
             RenameString(ctx, ctx.currentDB, cmd.GetArguments()[0], dst, cmd.GetArguments()[0]);
             break;
         }
         case BITSET_META:
         {
             RenameBitset(ctx, ctx.currentDB, cmd.GetArguments()[0], dst, cmd.GetArguments()[0]);
             break;
         }
         default:
         {
             fill_error_reply(ctx.reply, "Invalid type to move");
             break;
         }
     }
     fill_int_reply(ctx.reply, 1);
     return 0;
 }
Example #14
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;
    }
Example #15
0
    bool ArdbConfig::Parse(const Properties& props)
    {
        conf_props = props;
        conf_get_string(props, "home", home);
        if (home.empty())
        {
            home = "../ardb";
        }
        make_dir(home);
        int err = real_path(home, home);
        if (0 != err)
        {
            ERROR_LOG("Invalid 'home' config:%s for reason:%s", home.c_str(), strerror(err));
            return false;
        }
        err = access(home.c_str(), R_OK | W_OK);
        if (0 != err)
        {
            err = errno;
            ERROR_LOG("Invalid 'home' config:%s for reason:%s", home.c_str(), strerror(err));
            return false;
        }

        setenv("ARDB_HOME", home.c_str(), 1);
        replace_env_var(const_cast<Properties&>(props));

        conf_get_string(props, "pidfile", pidfile);
        conf_get_int64(props, "thread-pool-size", thread_pool_size);
        if (thread_pool_size <= 0)
        {
            thread_pool_size = available_processors();
        }
        conf_get_int64(props, "hz", hz);
        if (hz < CONFIG_MIN_HZ)
            hz = CONFIG_MIN_HZ;
        if (hz > CONFIG_MAX_HZ)
            hz = CONFIG_MAX_HZ;
        conf_get_int64(props, "tcp-keepalive", tcp_keepalive);
        conf_get_int64(props, "timeout", timeout);
        //conf_get_int64(props, "unixsocketperm", unixsocketperm);
        conf_get_int64(props, "slowlog-log-slower-than", slowlog_log_slower_than);
        conf_get_int64(props, "slowlog-max-len", slowlog_max_len);
        conf_get_int64(props, "maxclients", max_clients);
        if(max_clients <= 0)
        {
            max_clients = 10000;
        }

        for (int i = 0;; i++)
        {
            char config_key[256];
            sprintf(config_key, "server[%d].listen", i);
            ListenPoint lp;
            std::string address;
            if (!conf_get_string(props, config_key, address))
            {
                break;
            }
            if (address.find(":") == std::string::npos)
            {
                lp.host = address;
            }
            else
            {
                std::vector<std::string> ss = split_string(address, ":");
                uint32 port;
                if (ss.size() < 2 || !string_touint32(ss[ss.size() - 1], port) || port > 65535)
                {
                    ERROR_LOG("Invalid listen address %s", address.c_str());
                    return false;
                }

                lp.host = address.substr(0, address.size() - ss[ss.size() - 1].size() - 1);
                lp.port = port;
            }
            sprintf(config_key, "server[%d].qps-limit", i);
            conf_get_int64(props, config_key, lp.qps_limit);
            sprintf(config_key, "server[%d].unixsocketperm", i);
            conf_get_int64(props, config_key, lp.qps_limit);
            servers.push_back(lp);
        }

        if (servers.empty())
        {
            ListenPoint lp;
            lp.host = "0.0.0.0";
            lp.port = 16379;
            servers.push_back(lp);
        }
        if (strcasecmp(engine.c_str(), "rocksdb") == 0)
        {
            conf_get_string(props, "rocksdb.compaction", rocksdb_compaction);
            conf_get_bool(props, "rocksdb.disableWAL", rocksdb_disablewal);
            conf_get_bool(props, "rocksdb.scan-total-order", rocksdb_scan_total_order);
        }

        conf_get_string(props, "engine", engine);
        conf_get_string(props, "data-dir", data_base_path);
        conf_get_string(props, "backup-dir", backup_dir);
        conf_get_string(props, "repl-dir", repl_data_dir);
        make_dir(repl_data_dir);
        make_dir(backup_dir);

        err = real_path(repl_data_dir, repl_data_dir);
        if (0 != err)
        {
            ERROR_LOG("Invalid 'repl-dir' config:%s for reason:%s", repl_data_dir.c_str(), strerror(err));
            return false;
        }

        std::string backup_file_format;
        conf_get_string(props, "backup-file-format", backup_file_format);
        if (!strcasecmp(backup_file_format.c_str(), "redis"))
        {
            backup_redis_format = true;
        }

        conf_get_string(props, "zookeeper-servers", zookeeper_servers);
        conf_get_string(props, "zk-clientid-file", zk_clientid_file);

        conf_get_string(props, "loglevel", loglevel);
        conf_get_string(props, "logfile", logfile);
        conf_get_bool(props, "daemonize", daemonize);

        conf_get_int64(props, "repl-backlog-size", repl_backlog_size);
        conf_get_int64(props, "repl-backlog-cache-size", repl_backlog_cache_size);
        conf_get_int64(props, "repl-ping-slave-period", repl_ping_slave_period);
        conf_get_int64(props, "repl-timeout", repl_timeout);
        conf_get_int64(props, "repl-backlog-sync-period", repl_backlog_sync_period);
        conf_get_int64(props, "repl-backlog-ttl", repl_backlog_time_limit);
        conf_get_int64(props, "min-slaves-to-write", repl_min_slaves_to_write);
        conf_get_int64(props, "min-slaves-max-lag", repl_min_slaves_max_lag);
        conf_get_bool(props, "slave-serve-stale-data", repl_serve_stale_data);
        conf_get_int64(props, "max-slave-worker-queue", max_slave_worker_queue);
        if(max_slave_worker_queue <= 0)
        {
            max_slave_worker_queue = 1024;
        }

        conf_get_bool(props, "repl-disable-tcp-nodelay", repl_disable_tcp_nodelay);
        conf_get_int64(props, "lua-time-limit", lua_time_limit);

        conf_get_int64(props, "snapshot-max-lag-offset", snapshot_max_lag_offset);
        conf_get_int64(props, "maxsnapshots", maxsnapshots);

        if(maxsnapshots == 0)
        {
            maxsnapshots = 1;
        }
        if (snapshot_max_lag_offset > repl_backlog_size / 2)
        {
            snapshot_max_lag_offset = repl_backlog_size / 2;
        }

        conf_get_int64(props, "hll-sparse-max-bytes", hll_sparse_max_bytes);

        conf_get_bool(props, "slave-read-only", slave_readonly);
        conf_get_bool(props, "slave-serve-stale-data", slave_serve_stale_data);
        conf_get_int64(props, "slave-priority", slave_priority);
        conf_get_bool(props, "slave-ignore-expire", slave_ignore_expire);
        conf_get_bool(props, "slave-ignore-del", slave_ignore_del);

        conf_get_bool(props, "slave-cleardb-before-fullresync", slave_cleardb_before_fullresync);

        conf_get_int64(props, "statistics-log-period", statistics_log_period);
        if (statistics_log_period <= 0)
        {
            statistics_log_period = DEFAULT_STAT_LOG_PERIOD_SECS;
        }

        std::string slaveof;
        if (conf_get_string(props, "slaveof", slaveof))
        {
            std::vector<std::string> ss = split_string(slaveof, ":");
            if (ss.size() == 2)
            {
                master_host = ss[0];
                if (!string_touint32(ss[1], master_port))
                {
                    master_host = "";
                    WARN_LOG("Invalid 'slaveof' config.");
                }
            }
            else
            {
                WARN_LOG("Invalid 'slaveof' config.");
            }
        }
        
        conf_get_string(props, "masterauth", masterauth);

        if (data_base_path.empty())
        {
            data_base_path = ".";
        }
        make_dir(data_base_path);
        err = real_path(data_base_path, data_base_path);
        if (0 != err)
        {
            ERROR_LOG("Invalid 'data-dir' config:%s for reason:%s", data_base_path.c_str(), strerror(err));
            return false;
        }

        conf_get_string(props, "requirepass", requirepass);

        Properties::const_iterator fit = props.find("rename-command");
        if (fit != props.end())
        {
            rename_commands.clear();
            const ConfItemsArray& cs = fit->second;
            ConfItemsArray::const_iterator cit = cs.begin();
            while (cit != cs.end())
            {
                if (cit->size() != 2)
                {
                    ERROR_LOG("Invalid 'rename-command' config with %u args.", cit->size());
                }
                else
                {
                    rename_commands[cit->at(0)] = cit->at(1);
                }
                cit++;
            }
        }

        conf_get_int64(props, "reply-pool-size", reply_pool_size);

        conf_get_int64(props, "slave-client-output-buffer-limit", slave_client_output_buffer_limit);
        conf_get_int64(props, "pubsub-client-output-buffer-limit", pubsub_client_output_buffer_limit);

        conf_get_string(props, "redis-compatible-version", redis_compatible_version);

        conf_get_bool(props, "redis-compatible-mode", redis_compatible);
        conf_get_bool(props, "compact-after-snapshot-load", compact_after_snapshot_load);

        conf_get_int64(props, "qps-limit-per-host", qps_limit_per_host);
        conf_get_int64(props, "qps-limit-per-connection", qps_limit_per_connection);
        conf_get_int64(props, "range-delete-min-size", range_delete_min_size);
        conf_get_int64(props, "stream-lru-cache-size", stream_lru_cache_size);

        //trusted_ip.clear();
        Properties::const_iterator ip_it = props.find("trusted-ip");
        if (ip_it != props.end())
        {
            const ConfItemsArray& cs = ip_it->second;
            for (uint32 i = 0; i < cs.size(); i++)
            {
                //trusted_ip.insert(cs[i][0]);
            }
        }

        if (!verify_config(*this))
        {
            return false;
        }

        ArdbLogger::SetLogLevel(loglevel);
        return true;
    }
Example #16
0
    bool ArdbConfig::Parse(const Properties& props)
    {
        conf_props = props;
        conf_get_string(props, "home", home);
        if (home.empty())
        {
            home = "../ardb";
        }
        make_dir(home);
        int err = real_path(home, home);
        if (0 != err)
        {
            ERROR_LOG("Invalid 'home' config:%s for reason:%s", home.c_str(), strerror(err));
            return false;
        }
        err = access(home.c_str(), R_OK | W_OK);
        if (0 != err)
        {
            err = errno;
            ERROR_LOG("Invalid 'home' config:%s for reason:%s", home.c_str(), strerror(err));
            return false;
        }

        setenv("ARDB_HOME", home.c_str(), 1);
        replace_env_var(const_cast<Properties&>(props));

        conf_get_string(props, "pidfile", pidfile);

        conf_get_int64(props, "tcp-keepalive", tcp_keepalive);
        conf_get_int64(props, "timeout", timeout);
        conf_get_int64(props, "unixsocketperm", unixsocketperm);
        conf_get_int64(props, "slowlog-log-slower-than", slowlog_log_slower_than);
        conf_get_int64(props, "slowlog-max-len", slowlog_max_len);
        conf_get_int64(props, "maxclients", max_clients);
        Properties::const_iterator listen_it = props.find("listen");
        if (listen_it != props.end())
        {
            const ConfItemsArray& cs = listen_it->second;
            for (uint32 i = 0; i < cs.size(); i++)
            {
                if (cs[i].size() != 1)
                {
                    WARN_LOG("Invalid config 'listen'");
                }
                else
                {
                    const std::string& str = cs[i][0];
                    listen_addresses.push_back(str);
                }
            }
        }
        if (listen_addresses.empty())
        {
            listen_addresses.push_back("0.0.0.0:16379");
        }
        Properties::const_iterator tp_it = props.find("thread-pool-size");
        if (tp_it != props.end())
        {
            const ConfItemsArray& cs = tp_it->second;
            for (uint32 i = 0; i < cs.size(); i++)
            {
                uint32 size = 0;
                if (cs[i].size() != 1 || !string_touint32(cs[i][0], size))
                {
                    WARN_LOG("Invalid config 'thread-pool-size'");
                }
                else
                {
                    thread_pool_sizes.push_back((int64) size);
                }
            }
        }
        Properties::const_iterator qp_it = props.find("qps-limit");
        if (qp_it != props.end())
        {
            const ConfItemsArray& cs = qp_it->second;
            for (uint32 i = 0; i < cs.size(); i++)
            {
                uint32 limit = 0;
                if (cs[i].size() != 1 || !string_touint32(cs[i][0], limit))
                {
                    WARN_LOG("Invalid config 'qps-limit'");
                }
                else
                {
                    qps_limits.push_back((int64) limit);
                }
            }
        }
        thread_pool_sizes.resize(listen_addresses.size());
        qps_limits.resize(listen_addresses.size());

        conf_get_string(props, "data-dir", data_base_path);
        conf_get_string(props, "backup-dir", backup_dir);
        conf_get_string(props, "repl-dir", repl_data_dir);
        make_dir(repl_data_dir);
        make_dir(backup_dir);

        err = real_path(repl_data_dir, repl_data_dir);
        if (0 != err)
        {
            ERROR_LOG("Invalid 'repl-dir' config:%s for reason:%s", repl_data_dir.c_str(), strerror(err));
            return false;
        }

        std::string backup_file_format;
        conf_get_string(props, "backup-file-format", backup_file_format);
        if (!strcasecmp(backup_file_format.c_str(), "redis"))
        {
            backup_redis_format = true;
        }

        conf_get_string(props, "zookeeper-servers", zookeeper_servers);

        conf_get_string(props, "loglevel", loglevel);
        conf_get_string(props, "logfile", logfile);
        conf_get_bool(props, "daemonize", daemonize);

        conf_get_int64(props, "repl-backlog-size", repl_backlog_size);
        conf_get_int64(props, "repl-ping-slave-period", repl_ping_slave_period);
        conf_get_int64(props, "repl-timeout", repl_timeout);
        conf_get_int64(props, "repl-state-persist-period", repl_state_persist_period);
        conf_get_int64(props, "repl-backlog-ttl", repl_backlog_time_limit);
        conf_get_bool(props, "repl-disable-tcp-nodelay", repl_disable_tcp_nodelay);
        conf_get_int64(props, "lua-time-limit", lua_time_limit);

        conf_get_int64(props, "hash-max-ziplist-entries", hash_max_ziplist_entries);
        conf_get_int64(props, "hash_max-ziplist-value", hash_max_ziplist_value);
        conf_get_int64(props, "set-max-ziplist-entries", set_max_ziplist_entries);
        conf_get_int64(props, "set-max-ziplist-value", set_max_ziplist_value);
        conf_get_int64(props, "list-max-ziplist-entries", list_max_ziplist_entries);
        conf_get_int64(props, "list-max-ziplist-value", list_max_ziplist_value);
        conf_get_int64(props, "zset-max-ziplist-entries", zset_max_ziplist_entries);
        conf_get_int64(props, "zset_max_ziplist_value", zset_max_ziplist_value);

        conf_get_int64(props, "L1-zset-max-cache-size", L1_zset_max_cache_size);
        conf_get_int64(props, "L1-set-max-cache-size", L1_set_max_cache_size);
        conf_get_int64(props, "L1-hash-max-cache-size", L1_hash_max_cache_size);
        conf_get_int64(props, "L1-list-max-cache-size", L1_list_max_cache_size);
        conf_get_int64(props, "L1-string-max-cache-size", L1_string_max_cache_size);

        conf_get_bool(props, "L1-zset-read-fill-cache", L1_zset_read_fill_cache);
        conf_get_bool(props, "L1-zset-seek-load-cache", L1_zset_seek_load_cache);
        conf_get_bool(props, "L1-set-read-fill-cache", L1_set_read_fill_cache);
        conf_get_bool(props, "L1-set-seek-load-cache", L1_set_seek_load_cache);
        conf_get_bool(props, "L1-hash-read-fill-cache", L1_hash_read_fill_cache);
        conf_get_bool(props, "L1-hash-seek-load-cache", L1_hash_seek_load_cache);
        conf_get_bool(props, "L1-list-read-fill-cache", L1_list_read_fill_cache);
        conf_get_bool(props, "L1-list-seek-load-cache", L1_list_seek_load_cache);
        conf_get_bool(props, "L1-string-read-fill-cache", L1_string_read_fill_cache);

        conf_get_int64(props, "hll-sparse-max-bytes", hll_sparse_max_bytes);

        conf_get_bool(props, "slave-read-only", slave_readonly);
        conf_get_bool(props, "slave-serve-stale-data", slave_serve_stale_data);
        conf_get_int64(props, "slave-priority", slave_priority);
        conf_get_bool(props, "slave-ignore-expire", slave_ignore_expire);
        conf_get_bool(props, "slave-ignore-del", slave_ignore_del);

        std::string slaveof;
        if (conf_get_string(props, "slaveof", slaveof))
        {
            std::vector<std::string> ss = split_string(slaveof, ":");
            if (ss.size() == 2)
            {
                master_host = ss[0];
                if (!string_touint32(ss[1], master_port))
                {
                    master_host = "";
                    WARN_LOG("Invalid 'slaveof' config.");
                }
            }
            else
            {
                WARN_LOG("Invalid 'slaveof' config.");
            }
        }

        std::string include_dbs, exclude_dbs;
        repl_includes.clear();
        repl_excludes.clear();
        conf_get_string(props, "replicate-include-db", include_dbs);
        conf_get_string(props, "replicate-exclude-db", exclude_dbs);
        if (0 != split_uint32_array(include_dbs, "|", repl_includes))
        {
            ERROR_LOG("Invalid 'replicate-include-db' config.");
            repl_includes.clear();
        }
        if (0 != split_uint32_array(exclude_dbs, "|", repl_excludes))
        {
            ERROR_LOG("Invalid 'replicate-exclude-db' config.");
            repl_excludes.clear();
        }

        if (data_base_path.empty())
        {
            data_base_path = ".";
        }
        make_dir(data_base_path);
        err = real_path(data_base_path, data_base_path);
        if (0 != err)
        {
            ERROR_LOG("Invalid 'data-dir' config:%s for reason:%s", data_base_path.c_str(), strerror(err));
            return false;
        }
        conf_get_string(props, "additional-misc-info", additional_misc_info);

        conf_get_string(props, "requirepass", requirepass);

        Properties::const_iterator fit = props.find("rename-command");
        if (fit != props.end())
        {
            rename_commands.clear();
            StringSet newcmdset;
            const ConfItemsArray& cs = fit->second;
            ConfItemsArray::const_iterator cit = cs.begin();
            while (cit != cs.end())
            {
                if (cit->size() != 2 || newcmdset.count(cit->at(1)) > 0)
                {
                    ERROR_LOG("Invalid 'rename-command' config.");
                }
                else
                {
                    rename_commands[cit->at(0)] = cit->at(1);
                    newcmdset.insert(cit->at(1));
                }
                cit++;
            }
        }

        conf_get_int64(props, "compact-min-interval", compact_min_interval);
        conf_get_int64(props, "compact-max-interval", compact_max_interval);
        conf_get_int64(props, "compact-after-write", compact_trigger_write_count);
        conf_get_bool(props, "compact-enable", compact_enable);

        conf_get_int64(props, "reply-pool-size", reply_pool_size);
        conf_get_bool(props, "replace-all-for-multi-sadd", replace_for_multi_sadd);
        conf_get_bool(props, "replace-all-for-hmset", replace_for_hmset);

        conf_get_int64(props, "slave-client-output-buffer-limit", slave_client_output_buffer_limit);
        conf_get_int64(props, "pubsub-client-output-buffer-limit", pubsub_client_output_buffer_limit);

        conf_get_bool(props, "scan-redis-compatible", scan_redis_compatible);
        conf_get_int64(props, "scan-cursor-expire-after", scan_cursor_expire_after);

        conf_get_int64(props, "max-string-bitset-value", max_string_bitset_value);

        conf_get_int64(props, "databases", maxdb);

        conf_get_bool(props, "lua-exec-atomic", lua_exec_atomic);

        trusted_ip.clear();
        Properties::const_iterator ip_it = props.find("trusted-ip");
        if (ip_it != props.end())
        {
            const ConfItemsArray& cs = ip_it->second;
            for (uint32 i = 0; i < cs.size(); i++)
            {
                trusted_ip.insert(cs[i][0]);
            }
        }
        if (!verify_config(*this))
        {
            return false;
        }

        ArdbLogger::SetLogLevel(loglevel);
        return true;
    }
Example #17
0
File: t_hash.cpp Project: cvan/ardb
    int Ardb::HScan(Context& ctx, RedisCommandFrame& cmd)
    {
        std::string pattern;
        uint32 limit = 10000; //return max 10000 keys one time
        if (cmd.GetArguments().size() > 2)
        {
            for (uint32 i = 2; 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;
                }
            }
        }
        ValueObject meta;
        int err = GetMetaValue(ctx, cmd.GetArguments()[0], HASH_META, meta);
        CHECK_ARDB_RETURN_VALUE(ctx.reply, err);

        RedisReply& r1 = ctx.reply.AddMember();
        RedisReply& r2 = ctx.reply.AddMember();
        r2.type = REDIS_REPLY_ARRAY;
        if (0 != err)
        {
            fill_str_reply(r1, "0");
            return 0;
        }
        const std::string& cursor = cmd.GetArguments()[1];
        HashIterator iter;
        HashIter(ctx, meta, cursor == "0" ? "" : cursor, iter, true);
        while (iter.Valid())
        {
            const Data* field = iter.Field();
            std::string tmp;
            field->GetDecodeString(tmp);
            if ((pattern.empty() || fnmatch(pattern.c_str(), tmp.c_str(), 0) == 0))
            {
                RedisReply& rr1 = r2.AddMember();
                RedisReply& rr2 = r2.AddMember();
                fill_str_reply(rr1, tmp);
                fill_value_reply(rr2, *(iter.Value()));
            }
            if (r2.MemberSize() >= (limit * 2))
            {
                break;
            }
            iter.Next();
        }
        if (iter.Valid())
        {
            iter.Next();
            const Data* next_field = iter.Field();
            std::string tmp;
            fill_str_reply(r1, next_field->GetDecodeString(tmp));
        }
        else
        {
            fill_str_reply(r1, "0");
        }
        return 0;
    }