Beispiel #1
0
 int Ardb::LRange(Context& ctx, RedisCommandFrame& cmd)
 {
     int64 start, end;
     if (!GetInt64Value(ctx, cmd.GetArguments()[1], start) || !GetInt64Value(ctx, cmd.GetArguments()[2], end))
     {
         return 0;
     }
     ctx.reply.type = REDIS_REPLY_ARRAY;
     ListRange(ctx, cmd.GetArguments()[0], start, end);
     return 0;
 }
Beispiel #2
0
 int Ardb::HIncrby(Context& ctx, RedisCommandFrame& cmd)
 {
     int64 increment, val = 0;
     if (!GetInt64Value(ctx, cmd.GetArguments()[2], increment))
     {
         return 0;
     }
     ValueObject meta;
     int err = GetMetaValue(ctx, cmd.GetArguments()[0], HASH_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     Data field(cmd.GetArguments()[1]);
     Data value;
     if (err == 0)
     {
         err = HashGet(ctx, meta, field, value);
     }
     if (err == ERR_NOT_EXIST)
     {
         value.SetInt64(increment);
     }
     else
     {
         if (!value.GetInt64(val))
         {
             fill_error_reply(ctx.reply, "value is not a integer or out of range");
             return 0;
         }
         value.SetInt64(val + increment);
     }
     HashSet(ctx, meta, field, value);
     fill_int_reply(ctx.reply, val + increment);
     return 0;
 }
Beispiel #3
0
OP_NAMESPACE_BEGIN

    int Comms::LIndex(Context& ctx, RedisCommandFrame& cmd)
    {
        int64 index;
        if (!GetInt64Value(ctx, cmd.GetArguments()[1], index))
        {
            return 0;
        }
        std::string v;
        int err = m_kv_store->LIndex(ctx.currentDB, cmd.GetArguments()[0], index, v);
        if (err >= 0)
        {
            fill_str_reply(ctx.reply, v);
        }
        else if (mmkv::ERR_OFFSET_OUTRANGE == err)
        {
            ctx.reply.type = REDIS_REPLY_NIL;
        }
        else
        {
            FillErrorReply(ctx, err);
        }
        return 0;
    }
Beispiel #4
0
 int Comms::LRange(Context& ctx, RedisCommandFrame& cmd)
 {
     int64 start, end;
     if (!GetInt64Value(ctx, cmd.GetArguments()[1], start) || !GetInt64Value(ctx, cmd.GetArguments()[2], end))
     {
         return 0;
     }
     ctx.reply.type = REDIS_REPLY_ARRAY;
     mmkv::StringArrayResult vs(ReplyResultStringAlloc, &ctx.reply);
     int err = m_kv_store->LRange(ctx.currentDB, cmd.GetArguments()[0], start, end, vs);
     if (err < 0)
     {
         FillErrorReply(ctx, err);
     }
     return 0;
 }
Beispiel #5
0
 int Comms::LTrim(Context& ctx, RedisCommandFrame& cmd)
 {
     int64 start, end;
     if (!GetInt64Value(ctx, cmd.GetArguments()[1], start) || !GetInt64Value(ctx, cmd.GetArguments()[2], end))
     {
         return 0;
     }
     int err = m_kv_store->LTrim(ctx.currentDB, cmd.GetArguments()[0], start, end);
     if (err >= 0)
     {
         fill_ok_reply(ctx.reply);
         FireKeyChangedEvent(ctx, cmd.GetArguments()[0]);
     }
     else
     {
         FillErrorReply(ctx, err);
     }
     return 0;
 }
Beispiel #6
0
 int Ardb::HMIncrby(Context& ctx, RedisCommandFrame& cmd)
 {
     if ((cmd.GetArguments().size() - 1) % 2 != 0)
     {
         fill_error_reply(ctx.reply, "wrong number of arguments for HMIncrby");
         return 0;
     }
     ValueObject meta;
     int err = GetMetaValue(ctx, cmd.GetArguments()[0], HASH_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     ctx.reply.type = REDIS_REPLY_ARRAY;
     DataMap fs;
     Int64Array vs;
     for (uint32 i = 1; i < cmd.GetArguments().size(); i += 2)
     {
         int64 inc = 0;
         if (!GetInt64Value(ctx, cmd.GetArguments()[i + 1], inc))
         {
             return 0;
         }
         Data field(cmd.GetArguments()[i]);
         if (err == ERR_NOT_EXIST)
         {
             fs[field].SetInt64(inc);
             vs.push_back(inc);
         }
         else
         {
             Data value;
             HashGet(ctx, meta, field, value);
             int64 val = 0;
             if (!value.GetInt64(val))
             {
                 fill_error_reply(ctx.reply, "value is not a float or out of range");
                 return 0;
             }
             fs[field].SetInt64(inc + val);
             vs.push_back(inc + val);
         }
     }
     HashMultiSet(ctx, meta, fs);
     fill_int_array_reply(ctx.reply, vs);
     return 0;
 }
Beispiel #7
0
 int Comms::LSet(Context& ctx, RedisCommandFrame& cmd)
 {
     int64 index;
     if (!GetInt64Value(ctx, cmd.GetArguments()[1], index))
     {
         return 0;
     }
     int err = m_kv_store->LSet(ctx.currentDB, cmd.GetArguments()[0], index, cmd.GetArguments()[2]);
     if (err >= 0)
     {
         fill_ok_reply(ctx.reply);
         FireKeyChangedEvent(ctx, cmd.GetArguments()[0]);
     }
     else
     {
         FillErrorReply(ctx, err);
     }
     return 0;
 }
Beispiel #8
0
 int Comms::LRem(Context& ctx, RedisCommandFrame& cmd)
 {
     int64 count;
     if (!GetInt64Value(ctx, cmd.GetArguments()[1], count))
     {
         return 0;
     }
     int err = m_kv_store->LRem(ctx.currentDB, cmd.GetArguments()[0], count, cmd.GetArguments()[2]);
     if (err >= 0)
     {
         fill_int_reply(ctx.reply, err);
         if (err > 0)
         {
             FireKeyChangedEvent(ctx, cmd.GetArguments()[0]);
         }
     }
     else
     {
         FillErrorReply(ctx, err);
     }
     return 0;
 }
Beispiel #9
0
    int Ardb::LTrim(Context& ctx, RedisCommandFrame& cmd)
    {
        int64 start, end;
        if (!GetInt64Value(ctx, cmd.GetArguments()[1], start) || !GetInt64Value(ctx, cmd.GetArguments()[2], end))
        {
            return 0;
        }
        ValueObject meta;
        int err = GetMetaValue(ctx, cmd.GetArguments()[0], LIST_META, meta);
        CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
        if (0 != err)
        {
            fill_status_reply(ctx.reply, "OK");
            return 0;
        }
        /* convert negative indexes */
        if (start < 0)
            start = meta.meta.Length() + start;
        if (end < 0)
            end = meta.meta.Length() + end;
        if (start < 0)
            start = 0;
        if (end >= meta.meta.Length())
            end = meta.meta.Length() - 1;

        /* Invariant: start >= 0, so this test will be true when end < 0.
         * The range is empty when start > end or start >= length. */
        if (start > end || start >= meta.meta.Length())
        {
            /* Out of range start or start > end result in empty list */
            DeleteKey(ctx, cmd.GetArguments()[0]);
            return 0;
        }
        if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST)
        {
            DataArray newzip;
            for (int64 i = start; i <= end; i++)
            {
                newzip.push_back(meta.meta.ziplist[i]);
            }
            meta.meta.ziplist = newzip;
            SetKeyValue(ctx, meta);
        }
        else
        {
            BatchWriteGuard guard(GetKeyValueEngine());
            if (meta.meta.IsSequentialList())
            {
                int64 listlen = meta.meta.Length();
                for (int64 s = 0; s < listlen; s++)
                {
                    if (s == start)
                    {
                        s = end;
                        continue;
                    }
                    KeyObject lk;
                    lk.db = meta.key.db;
                    lk.key = meta.key.key;
                    lk.type = LIST_ELEMENT;
                    lk.score = meta.meta.min_index.IncrBy(s);
                    meta.meta.len--;
                    DelKeyValue(ctx, lk);
                }
                meta.meta.max_index = meta.meta.min_index;
                meta.meta.min_index.IncrBy(start);
                meta.meta.max_index.IncrBy(end);
            }
            else
            {
                ListIterator iter;
                ListIter(ctx, meta, iter, false);
                int64 cursor = 0;
                while (iter.Valid())
                {
                    if (cursor < start || cursor > end)
                    {
                        DelRaw(ctx, iter.CurrentRawKey());
                        meta.meta.len--;
                    }
                    if (cursor == start)
                    {
                        meta.meta.min_index = *(iter.Element());
                    }
                    else if (cursor == end)
                    {
                        meta.meta.max_index = *(iter.Element());
                    }
                    cursor++;
                    iter.Next();
                }
            }
            SetKeyValue(ctx, meta);
        }
        return 0;
    }
Beispiel #10
0
    int Ardb::LSet(Context& ctx, RedisCommandFrame& cmd)
    {
        int64 index;
        if (!GetInt64Value(ctx, cmd.GetArguments()[1], index))
        {
            fill_error_reply(ctx.reply, "value is not an integer or out of range");
            return 0;
        }
        ValueObject meta;
        int err = GetMetaValue(ctx, cmd.GetArguments()[0], LIST_META, meta);
        CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
        if (0 != err)
        {
            fill_error_reply(ctx.reply, "no such key");
            return 0;
        }
        if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST)
        {
            Data* entry = GetZipEntry(meta.meta.ziplist, index);
            if (NULL == entry)
            {
                fill_error_reply(ctx.reply, "index out of range");
                return 0;
            }
            else
            {
                entry->SetString(cmd.GetArguments()[2], true);
                SetKeyValue(ctx, meta);
                fill_status_reply(ctx.reply, "OK");
                return 0;
            }
        }
        else
        {
            if (index >= meta.meta.Length() || (-index) > meta.meta.Length())
            {
                fill_error_reply(ctx.reply, "index out of range");
                return 0;
            }

            if (meta.meta.IsSequentialList())
            {
                ValueObject list_element;
                list_element.key.db = meta.key.db;
                list_element.key.key = meta.key.key;
                list_element.key.type = LIST_ELEMENT;
                list_element.key.score = meta.meta.min_index;
                if (index >= 0)
                {
                    list_element.key.score.IncrBy(index);
                }
                else
                {
                    list_element.key.score.IncrBy(index + meta.meta.Length());
                }
                if (0 == GetKeyValue(ctx, list_element.key, &list_element))
                {
                    list_element.element.SetString(cmd.GetArguments()[2], true);
                    SetKeyValue(ctx, list_element);
                    fill_status_reply(ctx.reply, "OK");
                    return 0;
                }
            }
            else
            {
                ListIterator iter;
                ListIter(ctx, meta, iter, index < 0);
                int64 cursor = index >= 0 ? 0 : -1;
                while (iter.Valid())
                {
                    if (cursor == index)
                    {
                        ValueObject v;
                        v.key.db = meta.key.db;
                        v.key.key = meta.key.key;
                        v.key.type = LIST_ELEMENT;
                        v.key.score = *(iter.Score());
                        v.type = LIST_ELEMENT;
                        v.element.SetString(cmd.GetArguments()[2], true);
                        SetKeyValue(ctx, v);
                        fill_status_reply(ctx.reply, "OK");
                        return 0;
                    }
                    if (cursor >= 0)
                    {
                        cursor++;
                    }
                    else
                    {
                        cursor--;
                    }
                    if (index < 0)
                    {
                        iter.Prev();
                    }
                    else
                    {
                        iter.Next();
                    }
                }
            }
            fill_error_reply(ctx.reply, "index out of range");
        }
        return 0;
    }
Beispiel #11
0
 int Ardb::LRem(Context& ctx, RedisCommandFrame& cmd)
 {
     int64 count;
     if (!GetInt64Value(ctx, cmd.GetArguments()[1], count))
     {
         return 0;
     }
     int64 toremove = std::abs(count);
     ValueObject meta;
     int err = GetMetaValue(ctx, cmd.GetArguments()[0], LIST_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     if (0 != err)
     {
         fill_int_reply(ctx.reply, 0);
         return 0;
     }
     Data element;
     element.SetString(cmd.GetArguments()[2], true);
     KeyLockerGuard lock(m_key_lock, ctx.currentDB, cmd.GetArguments()[0]);
     if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST)
     {
         uint32 oldlen = meta.meta.ziplist.size();
         int64 removed = 0;
         DataArray newzip;
         if (count >= 0)
         {
             for (uint32 i = 0; i < oldlen; i++)
             {
                 if (meta.meta.ziplist[i] == element)
                 {
                     if (toremove == 0 || removed < toremove)
                     {
                         removed++;
                         continue;
                     }
                 }
                 newzip.push_back(meta.meta.ziplist[i]);
             }
         }
         else
         {
             for (uint32 i = 0; i < oldlen; i++)
             {
                 if (meta.meta.ziplist[oldlen - 1 - i] == element)
                 {
                     if (toremove == 0 || removed < toremove)
                     {
                         removed++;
                         continue;
                     }
                 }
                 newzip.push_front(meta.meta.ziplist[i]);
             }
         }
         if (removed > 0)
         {
             meta.meta.ziplist = newzip;
             SetKeyValue(ctx, meta);
         }
         fill_int_reply(ctx.reply, removed);
         return 0;
     }
     BatchWriteGuard guard(GetKeyValueEngine());
     ListIterator iter;
     ListIter(ctx, meta, iter, count < 0);
     int64 remove = 0;
     while (iter.Valid())
     {
         if (iter.Element()->Compare(element) == 0)
         {
             meta.meta.len--;
             meta.meta.SetFlag(COLLECTION_FLAG_NORMAL);
             DelRaw(ctx, iter.CurrentRawKey());
             //DelKeyValue(ctx, k);
             remove++;
             if (remove == toremove)
             {
                 break;
             }
         }
         if (count < 0)
         {
             iter.Prev();
         }
         else
         {
             iter.Next();
         }
     }
     if (remove > 0)
     {
         SetKeyValue(ctx, meta);
     }
     fill_int_reply(ctx.reply, remove);
     return 0;
 }
Beispiel #12
0
 int Ardb::LIndex(Context& ctx, RedisCommandFrame& cmd)
 {
     int64 index;
     if (!GetInt64Value(ctx, cmd.GetArguments()[1], index))
     {
         return 0;
     }
     ValueObject meta;
     int err = GetMetaValue(ctx, cmd.GetArguments()[0], LIST_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     if (0 != err)
     {
         ctx.reply.type = REDIS_REPLY_NIL;
         return 0;
     }
     if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST)
     {
         Data* entry = GetZipEntry(meta.meta.ziplist, index);
         if (NULL != entry)
         {
             fill_value_reply(ctx.reply, *entry);
         }
         else
         {
             ctx.reply.type = REDIS_REPLY_NIL;
         }
         return 0;
     }
     else
     {
         if ((index >= 0 && index >= meta.meta.Length()) || (index < 0 && (meta.meta.Length() + index) < 0))
         {
             ctx.reply.type = REDIS_REPLY_NIL;
             return 0;
         }
         ListIterator iter;
         if (meta.meta.IsSequentialList())
         {
             err = SequencialListIter(ctx, meta, iter, index);
             if (0 == err)
             {
                 if (iter.Valid())
                 {
                     fill_value_reply(ctx.reply, *(iter.Element()));
                     return 0;
                 }
             }
         }
         else
         {
             err = ListIter(ctx, meta, iter, index < 0);
             uint32 cursor = index < 0 ? 1 : 0;
             while (iter.Valid())
             {
                 if (cursor == std::abs(index))
                 {
                     fill_value_reply(ctx.reply, *(iter.Element()));
                     return 0;
                 }
                 cursor++;
                 if (index >= 0)
                 {
                     iter.Next();
                 }
                 else
                 {
                     iter.Prev();
                 }
             }
         }
         ctx.reply.type = REDIS_REPLY_NIL;
     }
     return 0;
 }