Beispiel #1
0
 int Ardb::HMSet(Context& ctx, RedisCommandFrame& cmd)
 {
     if (m_cfg.replace_for_hmset)
     {
         HReplace(ctx, cmd);
         return 0;
     }
     if ((cmd.GetArguments().size() - 1) % 2 != 0)
     {
         fill_error_reply(ctx.reply, "wrong number of arguments for HMSet");
         return 0;
     }
     ValueObject meta;
     int err = GetMetaValue(ctx, cmd.GetArguments()[0], HASH_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     DataMap fs;
     for (uint32 i = 1; i < cmd.GetArguments().size(); i += 2)
     {
         Data f(cmd.GetArguments()[i]), v(cmd.GetArguments()[i + 1]);
         fs[f] = v;
     }
     HashMultiSet(ctx, meta, fs);
     fill_status_reply(ctx.reply, "OK");
     return 0;
 }
Beispiel #2
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;
 }
Beispiel #3
0
 int Ardb::Discard(Context& ctx, RedisCommandFrame& cmd)
 {
     if (!ctx.InTransc())
     {
         fill_error_reply(ctx.reply, "DISCARD without MULTI");
         return 0;
     }
     ctx.ClearTransc();
     fill_status_reply(ctx.reply, "OK");
     return 0;
 }
Beispiel #4
0
 int Ardb::Multi(Context& ctx, RedisCommandFrame& cmd)
 {
     if (ctx.InTransc())
     {
         fill_error_reply(ctx.reply, "MULTI calls can not be nested");
         return 0;
     }
     ctx.GetTransc().in_transc = true;
     fill_status_reply(ctx.reply, "OK");
     return 0;
 }
Beispiel #5
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;
 }
Beispiel #6
0
 int Ardb::Watch(Context& ctx, RedisCommandFrame& cmd)
 {
     if (ctx.InTransc())
     {
         fill_error_reply(ctx.reply, "WATCH inside MULTI is not allowed");
         return 0;
     }
     for (uint32 i = 0; i < cmd.GetArguments().size(); i++)
     {
         WatchForKey(ctx, cmd.GetArguments()[i]);
     }
     fill_status_reply(ctx.reply, "OK");
     return 0;
 }
Beispiel #7
0
 int ArdbServer::Auth(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     if (m_cfg.requirepass.empty())
     {
         fill_error_reply(ctx.reply, "Client sent AUTH, but no password is set");
     }
     else if (m_cfg.requirepass != cmd.GetArguments()[0])
     {
         ctx.authenticated = false;
         fill_error_reply(ctx.reply, "invalid password");
     }
     else
     {
         ctx.authenticated = true;
         fill_status_reply(ctx.reply, "OK");
     }
     return 0;
 }
Beispiel #8
0
 int ArdbServer::MSet(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     if (cmd.GetArguments().size() % 2 != 0)
     {
         fill_error_reply(ctx.reply, "wrong number of arguments for MSET");
         return 0;
     }
     SliceArray keys;
     SliceArray vals;
     for (uint32 i = 0; i < cmd.GetArguments().size(); i += 2)
     {
         keys.push_back(cmd.GetArguments()[i]);
         vals.push_back(cmd.GetArguments()[i + 1]);
     }
     m_db->MSet(ctx.currentDB, keys, vals);
     fill_status_reply(ctx.reply, "OK");
     return 0;
 }
Beispiel #9
0
 /*
  * CACHE LOAD|EVICT|STATUS key
  */
 int Ardb::Cache(Context& ctx, RedisCommandFrame& cmd)
 {
     int ret = 0;
     if (!strcasecmp(cmd.GetArguments()[0].c_str(), "load"))
     {
         KeyType type = KEY_END;
         GetType(ctx, cmd.GetArguments()[1], type);
         if (type != KEY_END)
         {
             CacheLoadOptions options;
             options.deocode_geo = true;
             ret = m_cache.Load(ctx.currentDB, cmd.GetArguments()[1], type, options);
         }
         else
         {
             ret = ERR_INVALID_TYPE;
         }
     }
     else if (!strcasecmp(cmd.GetArguments()[0].c_str(), "evict"))
     {
         ret = m_cache.Evict(ctx.currentDB, cmd.GetArguments()[1]);
     }
     else if (!strcasecmp(cmd.GetArguments()[0].c_str(), "status"))
     {
         std::string status = m_cache.Status(ctx.currentDB, cmd.GetArguments()[1]);
         fill_str_reply(ctx.reply, status);
         return 0;
     }
     else
     {
         fill_error_reply(ctx.reply, "Syntax error, try CACHE (LOAD | EVICT | STATUS) key");
         return 0;
     }
     if (ret == 0)
     {
         fill_status_reply(ctx.reply, "OK");
     }
     else
     {
         fill_error_reply(ctx.reply, "Failed to cache load/evict/status key:%s", cmd.GetArguments()[1].c_str());
     }
     return 0;
 }
Beispiel #10
0
 int Ardb::Type(Context& ctx, RedisCommandFrame& cmd)
 {
     KeyType type = KEY_END;
     GetType(ctx, cmd.GetArguments()[0], type);
     switch (type)
     {
         case SET_META:
         {
             fill_status_reply(ctx.reply, "set");
             break;
         }
         case LIST_META:
         {
             fill_status_reply(ctx.reply, "list");
             break;
         }
         case ZSET_META:
         {
             fill_status_reply(ctx.reply, "zset");
             break;
         }
         case HASH_META:
         {
             fill_status_reply(ctx.reply, "hash");
             break;
         }
         case STRING_META:
         {
             fill_status_reply(ctx.reply, "string");
             break;
         }
         case BITSET_META:
         {
             fill_status_reply(ctx.reply, "bitset");
             break;
         }
         default:
         {
             fill_status_reply(ctx.reply, "none");
             break;
         }
     }
     return 0;
 }
Beispiel #11
0
 int Comms::Type(Context& ctx, RedisCommandFrame& cmd)
 {
     int type = m_kv_store->Type(ctx.currentDB, cmd.GetArguments()[0]);
     switch (type)
     {
         case mmkv::V_TYPE_SET:
         {
             fill_status_reply(ctx.reply, "set");
             break;
         }
         case mmkv::V_TYPE_LIST:
         {
             fill_status_reply(ctx.reply, "list");
             break;
         }
         case mmkv::V_TYPE_ZSET:
         {
             fill_status_reply(ctx.reply, "zset");
             break;
         }
         case mmkv::V_TYPE_HASH:
         {
             fill_status_reply(ctx.reply, "hash");
             break;
         }
         case mmkv::V_TYPE_STRING:
         {
             fill_status_reply(ctx.reply, "string");
             break;
         }
         case mmkv::V_TYPE_POD:
         {
             fill_status_reply(ctx.reply, "pod");
             break;
         }
         default:
         {
             fill_status_reply(ctx.reply, "none");
             break;
         }
     }
     return 0;
 }
Beispiel #12
0
 /*
  *  GEOADD key MERCATOR|WGS84 x y value  [attr_name attr_value ...]
  */
 int ArdbServer::GeoAdd(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     GeoAddOptions options;
     std::string err;
     if (0 != options.Parse(cmd.GetArguments(), err, 1))
     {
         fill_error_reply(ctx.reply, "%s", err.c_str());
         return 0;
     }
     int ret = m_db->GeoAdd(ctx.currentDB, cmd.GetArguments()[0], options);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, ret);
     if (ret >= 0)
     {
         fill_status_reply(ctx.reply, "OK");
     }
     else
     {
         fill_error_reply(ctx.reply, "Failed to %s", cmd.ToString().c_str());
     }
     return 0;
 }
Beispiel #13
0
 int Ardb::HReplace(Context& ctx, RedisCommandFrame& cmd)
 {
     if ((cmd.GetArguments().size() - 1) % 2 != 0)
     {
         fill_error_reply(ctx.reply, "wrong number of arguments for HReplace");
         return 0;
     }
     ValueObject meta;
     meta.key.db = ctx.currentDB;
     meta.key.key = cmd.GetArguments()[0];
     meta.key.type = KEY_META;
     meta.type = HASH_META;
     meta.meta.encoding = COLLECTION_ECODING_ZIPMAP;
     DataMap fs;
     for (uint32 i = 1; i < cmd.GetArguments().size(); i += 2)
     {
         Data f(cmd.GetArguments()[i]), v(cmd.GetArguments()[i + 1]);
         fs[f] = v;
     }
     meta.attach.force_zipsave = true;
     HashMultiSet(ctx, meta, fs);
     fill_status_reply(ctx.reply, "OK");
     return 0;
 }
Beispiel #14
0
    int Ardb::Rename(Context& ctx, RedisCommandFrame& cmd)
    {
        bool withnx = cmd.GetType() == REDIS_CMD_RENAMENX;
        if (withnx)
        {
            RedisCommandFrame exists("Exists");
            exists.AddArg(cmd.GetArguments()[1]);
            Exists(ctx, exists);
            if (ctx.reply.integer == 1)
            {
                fill_int_reply(ctx.reply, 0);
                return 0;
            }
        }
        else
        {
            DeleteKey(ctx, cmd.GetArguments()[1]);
        }

        KeyType type = KEY_END;
        GetType(ctx, cmd.GetArguments()[0], type);
        switch (type)
        {
            case SET_META:
            {
                RenameSet(ctx, ctx.currentDB, cmd.GetArguments()[0], ctx.currentDB, cmd.GetArguments()[1]);
                break;
            }
            case LIST_META:
            {
                RenameList(ctx, ctx.currentDB, cmd.GetArguments()[0], ctx.currentDB, cmd.GetArguments()[1]);
                break;
            }
            case ZSET_META:
            {
                RenameZSet(ctx, ctx.currentDB, cmd.GetArguments()[0], ctx.currentDB, cmd.GetArguments()[1]);
                break;
            }
            case HASH_META:
            {
                RenameHash(ctx, ctx.currentDB, cmd.GetArguments()[0], ctx.currentDB, cmd.GetArguments()[1]);
                break;
            }
            case STRING_META:
            {
                RenameString(ctx, ctx.currentDB, cmd.GetArguments()[0], ctx.currentDB, cmd.GetArguments()[1]);
                break;
            }
            case BITSET_META:
            {
                RenameBitset(ctx, ctx.currentDB, cmd.GetArguments()[0], ctx.currentDB, cmd.GetArguments()[1]);
                break;
            }
            default:
            {
                fill_error_reply(ctx.reply, "Invalid type to rename");
                break;
            }
        }
        if (withnx)
        {
            fill_int_reply(ctx.reply, 1);
        }
        else
        {
            fill_status_reply(ctx.reply, "OK");
        }
        return 0;
    }
Beispiel #15
0
 int ArdbServer::Quit(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     fill_status_reply(ctx.reply, "OK");
     return -1;
 }
Beispiel #16
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 #17
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 #18
0
 int ArdbServer::Ping(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     fill_status_reply(ctx.reply, "PONG");
     return 0;
 }
Beispiel #19
0
 int ArdbServer::Set(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     const std::string& key = cmd.GetArguments()[0];
     const std::string& value = cmd.GetArguments()[1];
     int ret = 0;
     if (cmd.GetArguments().size() == 2)
     {
         ret = m_db->Set(ctx.currentDB, key, value);
     }
     else
     {
         uint32 i = 0;
         uint64 px = 0, ex = 0;
         for (i = 2; i < cmd.GetArguments().size(); i++)
         {
             std::string tmp = string_tolower(cmd.GetArguments()[i]);
             if (tmp == "ex" || tmp == "px")
             {
                 int64 iv;
                 if (!raw_toint64(cmd.GetArguments()[i + 1].c_str(), cmd.GetArguments()[i + 1].size(), iv) || iv < 0)
                 {
                     fill_error_reply(ctx.reply, "value is not an integer or out of range");
                     return 0;
                 }
                 if (tmp == "px")
                 {
                     px = iv;
                 }
                 else
                 {
                     ex = iv;
                 }
                 i++;
             }
             else
             {
                 break;
             }
         }
         bool hasnx = false, hasxx = false;
         bool syntaxerror = false;
         if (i < cmd.GetArguments().size() - 1)
         {
             syntaxerror = true;
         }
         if (i == cmd.GetArguments().size() - 1)
         {
             std::string cmp = string_tolower(cmd.GetArguments()[i]);
             if (cmp != "nx" && cmp != "xx")
             {
                 syntaxerror = true;
             }
             else
             {
                 hasnx = cmp == "nx";
                 hasxx = cmp == "xx";
             }
         }
         if (syntaxerror)
         {
             fill_error_reply(ctx.reply, "syntax error");
             return 0;
         }
         int nxx = 0;
         if (hasnx)
         {
             nxx = -1;
         }
         if (hasxx)
         {
             nxx = 1;
         }
         ret = m_db->Set(ctx.currentDB, key, value, ex, px, nxx);
     }
     if (0 == ret)
     {
         fill_status_reply(ctx.reply, "OK");
     }
     else
     {
         switch (ret)
         {
             case ERR_INVALID_TYPE:
             {
                 fill_error_reply(ctx.reply, "invalid type");
                 break;
             }
             case ERR_KEY_EXIST:
             case ERR_NOT_EXIST:
             {
                 ctx.reply.type = REDIS_REPLY_NIL;
                 break;
             }
             default:
             {
                 fill_error_reply(ctx.reply, "set failed");
                 break;
             }
         }
     }
     return 0;
 }
Beispiel #20
0
 int Ardb::UnWatch(Context& ctx, RedisCommandFrame& cmd)
 {
     fill_status_reply(ctx.reply, "OK");
     UnwatchKeys(ctx);
     return 0;
 }