Example #1
0
File: keys.cpp Project: boreys/ardb
    int Ardb::KeysOperation(Context& ctx, const KeysOptions& options)
    {
        KeyObject from;
        from.db = ctx.currentDB;
        from.type = KEY_META;

        std::string::size_type cursor = options.pattern.find("*");
        if (cursor == std::string::npos)
        {
            from.key = options.pattern;
        }
        else
        {
            if (options.pattern != "*" && cursor > 0)
            {
                from.key = options.pattern.substr(0, cursor);
            }
        }
        Iterator* iter = IteratorKeyValue(from, false);
        std::string tmpkey;
        uint32 count = 0;
        while (NULL != iter && iter->Valid())
        {
            KeyObject kk;
            if (!decode_key(iter->Key(), kk) || kk.db != ctx.currentDB || kk.type != KEY_META)
            {
                break;
            }
            tmpkey.clear();
            tmpkey.assign(kk.key.data(), kk.key.size());
            if ((options.pattern == "*"
                    || stringmatchlen(options.pattern.c_str(), options.pattern.size(), tmpkey.data(), tmpkey.size(), 0)
                            == 1))
            {
                if (options.op == OP_GET)
                {
                    RedisReply& r = ctx.reply.AddMember();
                    fill_str_reply(r, tmpkey);
                }
                else
                {
                    count++;
                }
            }
            else
            {
                /*
                 * If the '*' is the last char, we can break iteration now
                 */
                if (cursor == options.pattern.size() - 1)
                {
                    break;
                }
            }
            iter->Next();
        }
        DELETE(iter);
        if (options.op == OP_GET)
        {
            ctx.reply.type = REDIS_REPLY_ARRAY;
        }
        else
        {
            fill_int_reply(ctx.reply, count);
        }
        return 0;
    }
Example #2
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 #3
0
    int Ardb::Randomkey(Context& ctx, RedisCommandFrame& cmd)
    {
        ctx.reply.type = REDIS_REPLY_NIL;
        KeyObject from;
        from.db = ctx.currentDB;
        from.type = KEY_META;

        std::string min_key, max_key, randkey;
        Iterator* iter = IteratorKeyValue(from, false);
        if (iter->Valid())
        {
            KeyObject kk;
            if (!decode_key(iter->Key(), kk) || kk.db != ctx.currentDB || kk.type != KEY_META)
            {
                goto _end;
            }
            min_key.assign(kk.key.data(), kk.key.size());
            max_key = min_key;
            from.type = SET_ELEMENT;    //Refer comparator.cpp

            from.encode_buf.Clear();
            IteratorSeek(iter, from);
            if (!iter->Valid())
            {
                iter->SeekToLast();
            }
            if (iter->Valid())
            {
                iter->Prev();
                if (iter->Valid())
                {
                    if (decode_key(iter->Key(), kk) && kk.db == ctx.currentDB && kk.type == KEY_META)
                    {
                        max_key.assign(kk.key.data(), kk.key.size());
                    }
                }
            }
            randkey = min_key;
            if (min_key < max_key)
            {
                randkey = random_between_string(min_key, max_key);
                from.type = KEY_META;
                from.db = ctx.currentDB;
                from.key = randkey;
                IteratorSeek(iter, from);
                if (iter->Valid())
                {
                    KeyObject kk;
                    if (!decode_key(iter->Key(), kk) || kk.db != ctx.currentDB || kk.type != KEY_META)
                    {
                        goto _end;
                    }
                    randkey.assign(kk.key.data(), kk.key.size());
                }
            }
        }
        if (!randkey.empty())
        {
            fill_str_reply(ctx.reply, randkey);
        }
        _end:
        DELETE(iter);
        return 0;
    }