Пример #1
0
 int Comms::Del(Context& ctx, RedisCommandFrame& cmd)
 {
     mmkv::DataArray fs;
     for (uint32 i = 0; i < cmd.GetArguments().size(); i++)
     {
         fs.push_back(cmd.GetArguments()[i]);
     }
     int err = m_kv_store->Del(ctx.currentDB, fs);
     if (err >= 0)
     {
         if (err > 0)
         {
             for (uint32 i = 0; i < cmd.GetArguments().size(); i++)
             {
                 FireKeyChangedEvent(ctx, cmd.GetArguments()[i]);
             }
         }
         fill_int_reply(ctx.reply, err);
     }
     else
     {
         FillErrorReply(ctx, err);
     }
     return 0;
 }
Пример #2
0
 int Comms::LInsert(Context& ctx, RedisCommandFrame& cmd)
 {
     bool before_or_after = false;
     if (!strcasecmp(cmd.GetArguments()[1].c_str(), "before"))
     {
         before_or_after = true;
     }
     else if (!strcasecmp(cmd.GetArguments()[1].c_str(), "after"))
     {
         before_or_after = false;
     }
     else
     {
         fill_error_reply(ctx.reply, "Syntax error");
         return 0;
     }
     int err = m_kv_store->LInsert(ctx.currentDB, cmd.GetArguments()[0], before_or_after, cmd.GetArguments()[2],
             cmd.GetArguments()[3]);
     if (err >= 0 || -1 == err)
     {
         fill_int_reply(ctx.reply, err);
         if (err > 0)
         {
             FireKeyChangedEvent(ctx, cmd.GetArguments()[0]);
         }
     }
     else
     {
         FillErrorReply(ctx, err);
     }
     return 0;
 }
Пример #3
0
 int Ardb::PUnsubscribeChannel(Context& ctx, const std::string& pattern, bool notify)
 {
     ctx.GetPubsub().pubsub_patterns.erase(pattern);
     WriteLockGuard<SpinRWLock> guard(m_pubsub_ctx_lock);
     PubsubContextTable::iterator it = m_pubsub_patterns.find(pattern);
     int ret = 0;
     if (it != m_pubsub_patterns.end())
     {
         it->second.erase(&ctx);
         if (it->second.empty())
         {
             m_pubsub_patterns.erase(it);
         }
         ret = 1;
     }
     if (notify && NULL != ctx.client)
     {
         RedisReply r;
         RedisReply& r1 = r.AddMember();
         RedisReply& r2 = r.AddMember();
         RedisReply& r3 = r.AddMember();
         fill_str_reply(r1, "punsubscribe");
         fill_str_reply(r2, pattern);
         fill_int_reply(r3, ctx.GetPubsub().pubsub_channels.size() + ctx.GetPubsub().pubsub_patterns.size());
         ctx.client->Write(r);
     }
     return ret;
 }
Пример #4
0
Файл: geo.cpp Проект: cvan/ardb
    /*
     *  GEOADD key MERCATOR|WGS84 x y value [x y value....]
     */
    int Ardb::GeoAdd(Context& 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;
        }
        GeoHashRange lat_range, lon_range;
        GeoHashHelper::GetCoordRange(options.coord_type, lat_range, lon_range);

        KeyLockerGuard keylock(m_key_lock, ctx.currentDB, cmd.GetArguments()[0]);
        ValueObject meta;
        int ret = GetMetaValue(ctx, cmd.GetArguments()[0], ZSET_META, meta);
        CHECK_ARDB_RETURN_VALUE(ctx.reply, ret);

        RedisCommandFrame zadd("zadd");
        zadd.AddArg(cmd.GetArguments()[0]);
        BatchWriteGuard guard(GetKeyValueEngine());
        GeoPointArray::iterator git = options.points.begin();
        uint32 count = 0;
        while (git != options.points.end())
        {
            GeoPoint& point = *git;
            if (point.x < lon_range.min || point.x > lon_range.max || point.y < lat_range.min
                    || point.y > lat_range.max)
            {
                guard.MarkFailed();
                break;
            }
            GeoHashBits hash;
            geohash_encode(&lat_range, &lon_range, point.y, point.x, 30, &hash);
            GeoHashFix60Bits score = hash.bits;
            Data score_value;
            score_value.SetInt64((int64) score);
            Data element;
            element.SetString(point.value, true);
            count += ZSetAdd(ctx, meta, element, score_value, NULL);

            std::string tmp;
            score_value.GetDecodeString(tmp);
            zadd.AddArg(tmp);
            element.GetDecodeString(tmp);
            zadd.AddArg(tmp);
            git++;
        }
        if (guard.Success())
        {
            SetKeyValue(ctx, meta);
            RewriteClientCommand(ctx, zadd);
            fill_int_reply(ctx.reply, count);
        }
        else
        {
            fill_error_reply(ctx.reply, "Invalid arguments");
        }
        return 0;
    }
Пример #5
0
 int Ardb::ListLen(Context& ctx, const Slice& key)
 {
     ValueObject meta;
     int err = GetMetaValue(ctx, key, LIST_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     fill_int_reply(ctx.reply, meta.meta.Length());
     return 0;
 }
Пример #6
0
 int Ardb::Publish(Context& ctx, RedisCommandFrame& cmd)
 {
     const std::string& channel = cmd.GetArguments()[0];
     const std::string& message = cmd.GetArguments()[1];
     int count = 0;
     count += PublishMessage(ctx, channel, message);
     fill_int_reply(ctx.reply, count);
     return 0;
 }
Пример #7
0
 int Ardb::TTL(Context& ctx, RedisCommandFrame& cmd)
 {
     uint64 ms;
     int err = GenericTTL(ctx, cmd.GetArguments()[0], ms);
     if (0 == err)
     {
         fill_int_reply(ctx.reply, (ms - get_current_epoch_millis()) / 1000);
     }
     return 0;
 }
Пример #8
0
 int Ardb::Expireat(Context& ctx, RedisCommandFrame& cmd)
 {
     uint32 v = 0;
     if (!check_uint32_arg(ctx.reply, cmd.GetArguments()[1], v))
     {
         return 0;
     }
     int err = GenericExpire(ctx, cmd.GetArguments()[0], v * 1000);
     fill_int_reply(ctx.reply, err == 0 ? 1 : 0);
     return 0;
 }
Пример #9
0
 int Ardb::Expire(Context& ctx, RedisCommandFrame& cmd)
 {
     uint64 v = 0;
     if (!check_uint64_arg(ctx.reply, cmd.GetArguments()[1], v))
     {
         return 0;
     }
     int err = GenericExpire(ctx, cmd.GetArguments()[0], v * 1000 + get_current_epoch_millis());
     fill_int_reply(ctx.reply, err == 0 ? 1 : 0);
     return 0;
 }
Пример #10
0
 int Ardb::GenericTTL(Context& ctx, const Slice& key, uint64& ms)
 {
     ValueObject meta;
     int err = GetMetaValue(ctx, key, KEY_END, meta);
     if (0 != err)
     {
         if (err == ERR_NOT_EXIST)
         {
             fill_int_reply(ctx.reply, -2);
         }
         return err;
     }
     ms = meta.meta.expireat;
     if (0 == ms)
     {
         fill_int_reply(ctx.reply, -1);
         return -1;
     }
     return 0;
 }
Пример #11
0
 int ArdbServer::SetRange(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     int32 offset;
     if (!string_toint32(cmd.GetArguments()[1], offset))
     {
         fill_error_reply(ctx.reply, "value is not an integer or out of range");
         return 0;
     }
     int ret = m_db->SetRange(ctx.currentDB, cmd.GetArguments()[0], offset, cmd.GetArguments()[2]);
     fill_int_reply(ctx.reply, ret);
     return 0;
 }
Пример #12
0
 void fill_int_array_reply(RedisReply& reply, T& v)
 {
     reply.type = REDIS_REPLY_ARRAY;
     typename T::iterator it = v.begin();
     while (it != v.end())
     {
         RedisReply r;
         fill_int_reply(r, *it);
         reply.elements.push_back(r);
         it++;
     }
 }
Пример #13
0
 int Comms::LLen(Context& ctx, RedisCommandFrame& cmd)
 {
     int err = m_kv_store->LLen(ctx.currentDB, cmd.GetArguments()[0]);
     if (err >= 0)
     {
         fill_int_reply(ctx.reply, err);
     }
     else
     {
         FillErrorReply(ctx, err);
     }
     return 0;
 }
Пример #14
0
 int Ardb::PExpire(Context& ctx, RedisCommandFrame& cmd)
 {
     uint32 v = 0;
     if (!check_uint32_arg(ctx.reply, cmd.GetArguments()[1], v))
     {
         return 0;
     }
     ValueObject meta;
     int err = GenericExpire(ctx, cmd.GetArguments()[0], v + get_current_epoch_millis());
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     fill_int_reply(ctx.reply, err == 0 ? 1 : 0);
     return 0;
 }
Пример #15
0
 int Ardb::HDel(Context& ctx, RedisCommandFrame& cmd)
 {
     ValueObject meta;
     int err = GetMetaValue(ctx, cmd.GetArguments()[0], HASH_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     int count = 0;
     if (err == 0)
     {
         BatchWriteGuard guard(GetKeyValueEngine());
         for (uint32 i = 1; i < cmd.GetArguments().size(); i++)
         {
             Data field(cmd.GetArguments()[i]);
             Data value;
             err = HashGet(ctx, meta, field, value);
             if (err == 0)
             {
                 if (meta.meta.encoding != COLLECTION_ECODING_ZIPMAP)
                 {
                     KeyObject k;
                     k.db = ctx.currentDB;
                     k.key = cmd.GetArguments()[0];
                     k.type = HASH_FIELD;
                     k.element = field;
                     DelKeyValue(ctx, k);
                     if (meta.meta.len > 0)
                     {
                         meta.meta.len--;
                     }
                 }
                 else
                 {
                     meta.meta.zipmap.erase(field);
                 }
                 count++;
             }
         }
         if (count > 0)
         {
             if (meta.meta.Length() != 0)
             {
                 SetKeyValue(ctx, meta);
             }
             else
             {
                 DelKeyValue(ctx, meta.key);
             }
         }
     }
     fill_int_reply(ctx.reply, count);
     return 0;
 }
Пример #16
0
 int ArdbServer::Decr(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     int64_t val;
     int ret = m_db->Decr(ctx.currentDB, cmd.GetArguments()[0], 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;
 }
Пример #17
0
 int ArdbServer::Append(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     const std::string& key = cmd.GetArguments()[0];
     const std::string& value = cmd.GetArguments()[1];
     int ret = m_db->Append(ctx.currentDB, key, value);
     if (ret > 0)
     {
         fill_int_reply(ctx.reply, ret);
     }
     else
     {
         fill_error_reply(ctx.reply, "failed to append key:%s", key.c_str());
     }
     return 0;
 }
Пример #18
0
 int Ardb::Del(Context& ctx, RedisCommandFrame& cmd)
 {
     if (ctx.IsSlave() && m_cfg.slave_ignore_del)
     {
         return 0;
     }
     BatchWriteGuard guard(GetKeyValueEngine());
     int count = 0;
     for (uint32 i = 0; i < cmd.GetArguments().size(); i++)
     {
         count += DeleteKey(ctx, cmd.GetArguments()[i]);
     }
     fill_int_reply(ctx.reply, count);
     return 0;
 }
Пример #19
0
 int Ardb::ListInsert(Context& ctx, const std::string& key, const std::string* match, const std::string& value,
         bool head, bool abort_nonexist)
 {
     ValueObject meta;
     int err = GetMetaValue(ctx, key, LIST_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     BatchWriteGuard guard(GetKeyValueEngine(), meta.meta.Encoding() != COLLECTION_ENCODING_ZIPLIST);
     if (0 != err && abort_nonexist)
     {
         fill_int_reply(ctx.reply, 0);
         return 0;
     }
     ListInsert(ctx, meta, match, value, head, abort_nonexist);
     SetKeyValue(ctx, meta);
     return 0;
 }
Пример #20
0
 int Comms::Persist(Context& ctx, RedisCommandFrame& cmd)
 {
     int err = m_kv_store->Persist(ctx.currentDB, cmd.GetArguments()[0]);
     if (err >= 0)
     {
         if (err > 0)
         {
             FireKeyChangedEvent(ctx, cmd.GetArguments()[0]);
         }
         fill_int_reply(ctx.reply, err);
     }
     else
     {
         FillErrorReply(ctx, err);
     }
     return 0;
 }
Пример #21
0
 int ArdbServer::MSetNX(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     if (cmd.GetArguments().size() % 2 != 0)
     {
         fill_error_reply(ctx.reply, "wrong number of arguments for MSETNX");
         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]);
     }
     int count = m_db->MSetNX(ctx.currentDB, keys, vals);
     fill_int_reply(ctx.reply, count);
     return 0;
 }
Пример #22
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;
 }
Пример #23
0
 int Comms::RPush(Context& ctx, RedisCommandFrame& cmd)
 {
     mmkv::DataArray fs;
     for (uint32 i = 1; i < cmd.GetArguments().size(); i++)
     {
         fs.push_back(cmd.GetArguments()[i]);
     }
     int err = m_kv_store->RPush(ctx.currentDB, cmd.GetArguments()[0], fs);
     if (err >= 0)
     {
         fill_int_reply(ctx.reply, err);
         FireKeyChangedEvent(ctx, cmd.GetArguments()[0]);
         WakeBlockingListsByKey(ctx, cmd.GetArguments()[0]);
     }
     else
     {
         FillErrorReply(ctx, err);
     }
     return 0;
 }
Пример #24
0
 int Ardb::HSetNX(Context& ctx, RedisCommandFrame& cmd)
 {
     ValueObject meta;
     int err = GetMetaValue(ctx, cmd.GetArguments()[0], HASH_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     Data value;
     Data field(cmd.GetArguments()[1]);
     err = HashGet(ctx, meta, field, value);
     if (err == ERR_NOT_EXIST)
     {
         value.SetString(cmd.GetArguments()[2], true);
         HashSet(ctx, meta, field, value);
         err = 1;
     }
     else
     {
         err = 0;
     }
     fill_int_reply(ctx.reply, err);
     return 0;
 }
Пример #25
0
    int Ardb::SubscribeChannel(Context& ctx, const std::string& channel, bool notify)
    {
        ctx.GetPubsub().pubsub_channels.insert(channel);
        {
            WriteLockGuard<SpinRWLock> guard(m_pubsub_ctx_lock);
            m_pubsub_channels[channel].insert(&ctx);
        }

        if (notify && NULL != ctx.client)
        {
            RedisReply r;
            RedisReply& r1 = r.AddMember();
            RedisReply& r2 = r.AddMember();
            RedisReply& r3 = r.AddMember();
            fill_str_reply(r1, "subscribe");
            fill_str_reply(r2, channel);
            fill_int_reply(r3, ctx.GetPubsub().pubsub_channels.size() + ctx.GetPubsub().pubsub_patterns.size());
            ctx.client->Write(r);
        }
        return 0;
    }
Пример #26
0
 int Comms::Expireat(Context& ctx, RedisCommandFrame& cmd)
 {
     uint64 v = 0;
     if (!check_uint64_arg(ctx.reply, cmd.GetArguments()[1], v))
     {
         return 0;
     }
     int err = m_kv_store->PExpireat(ctx.currentDB, cmd.GetArguments()[0], v * 1000);
     if (err >= 0)
     {
         if (err > 0)
         {
             FireKeyChangedEvent(ctx, cmd.GetArguments()[0]);
         }
         fill_int_reply(ctx.reply, err);
     }
     else
     {
         FillErrorReply(ctx, err);
     }
     return 0;
 }
Пример #27
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;
 }
Пример #28
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;
 }
Пример #29
0
 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;
 }
Пример #30
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;
    }