コード例 #1
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 int Ardb::HashGetAll(Context& ctx, const Slice& key, RedisReply& reply)
 {
     ValueObject meta;
     int err = GetMetaValue(ctx, key, HASH_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     reply.type = REDIS_REPLY_ARRAY;
     if (0 != err)
     {
         return 0;
     }
     HashIterator iter;
     err = HashIter(ctx, meta, "", iter, true);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     reply.type = REDIS_REPLY_ARRAY;
     while (iter.Valid())
     {
         const Data* field = iter.Field();
         Data* value = iter.Value();
         RedisReply& r = reply.AddMember();
         fill_value_reply(r, *field);
         RedisReply& r1 = reply.AddMember();
         fill_value_reply(r1, *value);
         iter.Next();
     }
     return 0;
 }
コード例 #2
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 int Ardb::HMGet(Context& ctx, RedisCommandFrame& cmd)
 {
     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;
     if (err == 0)
     {
         for (uint32 i = 1; i < cmd.GetArguments().size(); i++)
         {
             Data value;
             Data field(cmd.GetArguments()[i]);
             RedisReply& r = ctx.reply.AddMember();
             if (0 == HashGet(ctx, meta, field, value))
             {
                 r.type = REDIS_REPLY_STRING;
                 value.GetDecodeString(r.str);
             }
             else
             {
                 r.type = REDIS_REPLY_NIL;
             }
         }
     }
     else
     {
         ctx.reply.ReserveMember(cmd.GetArguments().size());
     }
     return 0;
 }
コード例 #3
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 int Ardb::HashLen(Context& ctx, const Slice& key)
 {
     ValueObject meta;
     int err = GetMetaValue(ctx, key, HASH_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     if (err == ERR_NOT_EXIST)
     {
         fill_int_reply(ctx.reply, 0);
     }
     else
     {
         if (meta.meta.Length() < 0)
         {
             HashIterator iter;
             meta.meta.len = 0;
             HashIter(ctx, meta, "", iter, true);
             while (iter.Valid())
             {
                 meta.meta.len++;
                 iter.Next();
             }
             SetKeyValue(ctx, meta);
         }
         fill_int_reply(ctx.reply, meta.meta.Length());
     }
     return 0;
 }
コード例 #4
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 int Ardb::HIncrbyFloat(Context& ctx, RedisCommandFrame& cmd)
 {
     double increment, val = 0;
     if (!GetDoubleValue(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 value;
     Data field(cmd.GetArguments()[1]);
     if (0 == err)
     {
         HashGet(ctx, meta, field, value);
         if (!value.GetDouble(val))
         {
             fill_error_reply(ctx.reply, "value is not a float or out of range");
             return 0;
         }
     }
     val += increment;
     std::string tmp;
     fast_dtoa(val, 10, tmp);
     value.SetString(tmp, false);
     HashSet(ctx, meta, field, value);
     fill_str_reply(ctx.reply, tmp);
     return 0;
 }
コード例 #5
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 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;
 }
コード例 #6
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 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;
 }
コード例 #7
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;
    }
コード例 #8
0
ファイル: t_list.cpp プロジェクト: huokedu/ardb
 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;
 }
コード例 #9
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 int Ardb::HSet(Context& ctx, RedisCommandFrame& cmd)
 {
     ValueObject meta;
     int err = GetMetaValue(ctx, cmd.GetArguments()[0], HASH_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     Data field(cmd.GetArguments()[1]), value(cmd.GetArguments()[2]);
     HashSet(ctx, meta, field, value);
     //fill_int_reply(ctx.reply, err);
     return 0;
 }
コード例 #10
0
ファイル: keys.cpp プロジェクト: boreys/ardb
 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;
 }
コード例 #11
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 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;
 }
コード例 #12
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 int Ardb::HVals(Context& ctx, RedisCommandFrame& cmd)
 {
     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;
     if (0 != err)
     {
         return 0;
     }
     HashIterator iter;
     err = HashIter(ctx, meta, "", iter, true);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     ctx.reply.type = REDIS_REPLY_ARRAY;
     while (iter.Valid())
     {
         Data* value = iter.Value();
         RedisReply& r = ctx.reply.AddMember();
         fill_value_reply(r, *value);
         iter.Next();
     }
     return 0;
 }
コード例 #13
0
ファイル: t_list.cpp プロジェクト: huokedu/ardb
 int Ardb::LPush(Context& ctx, RedisCommandFrame& cmd)
 {
     ValueObject meta;
     int err = GetMetaValue(ctx, cmd.GetArguments()[0], LIST_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     KeyLockerGuard lock(m_key_lock, ctx.currentDB, cmd.GetArguments()[0]);
     BatchWriteGuard guard(GetKeyValueEngine(), cmd.GetArguments().size() > 2);
     for (uint32 i = 1; i < cmd.GetArguments().size(); i++)
     {
         ListInsert(ctx, meta, NULL, cmd.GetArguments()[i], true, false);
     }
     SetKeyValue(ctx, meta);
     return 0;
 }
コード例 #14
0
ファイル: geo.cpp プロジェクト: harveyaot/ardb
 int ArdbServer::GeoSearch(ArdbConnContext& ctx, RedisCommandFrame& cmd)
 {
     GeoSearchOptions options;
     std::string err;
     if (0 != options.Parse(cmd.GetArguments(), err, 1))
     {
         fill_error_reply(ctx.reply, "%s", err.c_str());
         return 0;
     }
     ValueDataDeque res;
     int ret = m_db->GeoSearch(ctx.currentDB, cmd.GetArguments()[0], options, res);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, ret);
     fill_array_reply(ctx.reply, res);
     return 0;
 }
コード例 #15
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 int Ardb::HKeys(Context& ctx, RedisCommandFrame& cmd)
 {
     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;
     if (0 != err)
     {
         return 0;
     }
     HashIterator iter;
     err = HashIter(ctx, meta, "", iter, true);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     ctx.reply.type = REDIS_REPLY_ARRAY;
     while (iter.Valid())
     {
         const Data* value = iter.Field();
         RedisReply& r = ctx.reply.AddMember();
         std::string tmp;
         fill_str_reply(r, value->GetDecodeString(tmp));
         iter.Next();
     }
     return 0;
 }
コード例 #16
0
ファイル: t_list.cpp プロジェクト: huokedu/ardb
 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;
 }
コード例 #17
0
ファイル: t_list.cpp プロジェクト: huokedu/ardb
 int Ardb::RenameList(Context& ctx, DBID srcdb, const std::string& srckey, DBID dstdb, const std::string& dstkey)
 {
     Context tmpctx;
     tmpctx.currentDB = srcdb;
     ValueObject v;
     int err = GetMetaValue(tmpctx, srckey, LIST_META, v);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     if (0 != err)
     {
         fill_error_reply(ctx.reply, "no such key or some error");
         return 0;
     }
     if (v.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST)
     {
         DelKeyValue(tmpctx, v.key);
         v.key.encode_buf.Clear();
         v.key.db = dstdb;
         v.key.key = dstkey;
         v.meta.expireat = 0;
         SetKeyValue(ctx, v);
     }
     else
     {
         ListIterator iter;
         ListIter(ctx, v, iter, false);
         tmpctx.currentDB = dstdb;
         ValueObject dstmeta;
         dstmeta.key.type = KEY_META;
         dstmeta.key.key = dstkey;
         dstmeta.type = LIST_META;
         dstmeta.meta.SetFlag(COLLECTION_FLAG_SEQLIST);
         dstmeta.meta.SetEncoding(COLLECTION_ENCODING_ZIPLIST);
         BatchWriteGuard guard(GetKeyValueEngine());
         while (iter.Valid())
         {
             std::string tmpstr;
             ListInsert(tmpctx, dstmeta, NULL, iter.Element()->GetDecodeString(tmpstr), false, false);
             iter.Next();
         }
         SetKeyValue(tmpctx, dstmeta);
         tmpctx.currentDB = srcdb;
         DeleteKey(tmpctx, srckey);
     }
     ctx.data_change = true;
     return 0;
 }
コード例 #18
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 int Ardb::RenameHash(Context& ctx, DBID srcdb, const std::string& srckey, DBID dstdb, const std::string& dstkey)
 {
     Context tmpctx;
     tmpctx.currentDB = srcdb;
     ValueObject v;
     int err = GetMetaValue(tmpctx, srckey, HASH_META, v);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     if (0 != err)
     {
         fill_error_reply(ctx.reply, "no such key or some error");
         return 0;
     }
     if (v.meta.encoding == COLLECTION_ECODING_ZIPMAP)
     {
         DelKeyValue(tmpctx, v.key);
         v.key.encode_buf.Clear();
         v.key.db = dstdb;
         v.key.key = dstkey;
         v.meta.expireat = 0;
         SetKeyValue(ctx, v);
     }
     else
     {
         HashIterator iter;
         HashIter(ctx, v, "", iter, false);
         tmpctx.currentDB = dstdb;
         ValueObject dstmeta;
         dstmeta.key.type = KEY_META;
         dstmeta.key.key = dstkey;
         dstmeta.type = HASH_META;
         dstmeta.meta.encoding = COLLECTION_ECODING_ZIPMAP;
         BatchWriteGuard guard(GetKeyValueEngine());
         while (iter.Valid())
         {
             HashSet(tmpctx, dstmeta, *(iter.Field()), *(iter.Value()));
             iter.Next();
         }
         SetKeyValue(tmpctx, dstmeta);
         tmpctx.currentDB = srcdb;
         DeleteKey(tmpctx, srckey);
     }
     ctx.data_change = true;
     return 0;
 }
コード例 #19
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 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;
 }
コード例 #20
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 int Ardb::HashGet(Context& ctx, const std::string& key, const std::string& field, Data& v)
 {
     ValueObject meta;
     int err = GetMetaValue(ctx, key, HASH_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     Data f;
     f.SetString(field, true);
     err = HashGet(ctx, meta, f, v);
     if (err == ERR_NOT_EXIST)
     {
         ctx.reply.type = REDIS_REPLY_NIL;
     }
     else
     {
         ctx.reply.type = REDIS_REPLY_STRING;
         v.GetDecodeString(ctx.reply.str);
     }
     return 0;
 }
コード例 #21
0
ファイル: geo.cpp プロジェクト: harveyaot/ardb
 /*
  *  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;
 }
コード例 #22
0
ファイル: t_hash.cpp プロジェクト: cvan/ardb
 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;
 }
コード例 #23
0
ファイル: t_list.cpp プロジェクト: huokedu/ardb
 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;
 }
コード例 #24
0
ファイル: t_list.cpp プロジェクト: huokedu/ardb
    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;
    }
コード例 #25
0
ファイル: t_list.cpp プロジェクト: huokedu/ardb
    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;
    }
コード例 #26
0
ファイル: t_list.cpp プロジェクト: huokedu/ardb
 int Ardb::ListPop(Context& ctx, const std::string& key, bool lpop)
 {
     ValueObject meta;
     KeyLockerGuard keylock(m_key_lock, ctx.currentDB, key);
     int err = GetMetaValue(ctx, key, LIST_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     if (0 != err)
     {
         ctx.reply.type = REDIS_REPLY_NIL;
         return 0;
     }
     BatchWriteGuard guard(GetKeyValueEngine(), meta.meta.Encoding() != COLLECTION_ENCODING_ZIPLIST);
     if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST)
     {
         if (!meta.meta.ziplist.empty())
         {
             if (lpop)
             {
                 Data& data = meta.meta.ziplist.front();
                 fill_value_reply(ctx.reply, data);
                 meta.meta.ziplist.pop_front();
             }
             else
             {
                 Data& data = meta.meta.ziplist.back();
                 fill_value_reply(ctx.reply, data);
                 meta.meta.ziplist.pop_back();
             }
             if (meta.meta.ziplist.empty())
             {
                 DelKeyValue(ctx, meta.key);
             }
             else
             {
                 SetKeyValue(ctx, meta);
             }
         }
         else
         {
             ctx.reply.type = REDIS_REPLY_NIL;
         }
         return 0;
     }
     else
     {
         bool poped = false;
         if (meta.meta.IsSequentialList())
         {
             if (meta.meta.Length() > 0)
             {
                 ValueObject lkv;
                 lkv.key.type = LIST_ELEMENT;
                 lkv.key.key = meta.key.key;
                 lkv.key.db = ctx.currentDB;
                 lkv.key.score = lpop ? meta.meta.min_index : meta.meta.max_index;
                 if (0 == GetKeyValue(ctx, lkv.key, &lkv))
                 {
                     DelKeyValue(ctx, lkv.key);
                     if (lpop)
                     {
                         meta.meta.min_index.IncrBy(1);
                     }
                     else
                     {
                         meta.meta.max_index.IncrBy(-1);
                     }
                     meta.meta.len--;
                     poped = true;
                     fill_value_reply(ctx.reply, lkv.element);
                 }
             }
         }
         else
         {
             ListIterator iter;
             err = ListIter(ctx, meta, iter, !lpop);
             while (iter.Valid())
             {
                 if (!poped)
                 {
                     fill_value_reply(ctx.reply, *(iter.Element()));
                     poped = true;
                     meta.meta.len--;
                     KeyObject k;
                     k.type = LIST_ELEMENT;
                     k.key = meta.key.key;
                     k.db = ctx.currentDB;
                     k.score = *(iter.Score());
                     DelKeyValue(ctx, k);
                 }
                 else
                 {
                     if (lpop)
                     {
                         meta.meta.min_index = *(iter.Score());
                     }
                     else
                     {
                         meta.meta.max_index = *(iter.Score());
                     }
                     break;
                 }
                 if (lpop)
                 {
                     iter.Next();
                 }
                 else
                 {
                     iter.Prev();
                 }
             }
         }
         if (poped)
         {
             if (meta.meta.Length() > 0)
             {
                 SetKeyValue(ctx, meta);
             }
             else
             {
                 DelKeyValue(ctx, meta.key);
             }
         }
         else
         {
             ctx.reply.type = REDIS_REPLY_NIL;
         }
         return 0;
     }
 }
コード例 #27
0
ファイル: t_hash.cpp プロジェクト: 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;
    }
コード例 #28
0
ファイル: t_list.cpp プロジェクト: huokedu/ardb
    int Ardb::ListRange(Context& ctx, const Slice& key, int64 start, int64 end)
    {
        ValueObject meta;
        int err = GetMetaValue(ctx, key, LIST_META, meta);
        CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
        /* convert negative indexes */
        if (start < 0)
            start = meta.meta.Length() + start;
        if (end < 0)
            end = meta.meta.Length() + end;
        if (start < 0)
            start = 0;

        /* Invariant: start >= 0, so this test will be true when end < 0.
         * The range is empty when start > end or start >= length. */
        ctx.reply.type = REDIS_REPLY_ARRAY;
        if (start > end || start >= meta.meta.Length())
        {
            return 0;
        }
        if (end >= meta.meta.Length())
            end = meta.meta.Length() - 1;
        int64 rangelen = (end - start) + 1;
        if (meta.meta.Encoding() == COLLECTION_ENCODING_ZIPLIST)
        {
            uint32 i = start;
            while (rangelen-- && i < meta.meta.ziplist.size())
            {
                RedisReply& r = ctx.reply.AddMember();
                fill_value_reply(r, meta.meta.ziplist[i++]);
            }
        }
        else
        {
            ListIterator iter;
            if (meta.meta.IsSequentialList())
            {
                SequencialListIter(ctx, meta, iter, start);
                uint32 count = 0;
                while (iter.Valid() && count < rangelen)
                {
                    RedisReply& r = ctx.reply.AddMember();
                    fill_value_reply(r, iter.Element());
                    count++;
                    iter.Next();
                }
            }
            else
            {
                if (start > meta.meta.len / 2)
                {
                    start -= meta.meta.len;
                    end -= meta.meta.len;
                }

                ListIter(ctx, meta, iter, start < 0);
                int64 cursor = start < 0 ? -1 : 0;
                while (iter.Valid())
                {
                    if (cursor >= start && cursor <= end)
                    {
                        RedisReply& r = ctx.reply.AddMember();
                        fill_value_reply(r, iter.Element());
                    }
                    if (start < 0)
                    {
                        if (cursor < start)
                        {
                            break;
                        }
                        cursor--;
                    }
                    else
                    {
                        if (cursor > end)
                        {
                            break;
                        }
                        cursor++;
                    }
                    iter.Next();
                }
            }
        }
        return 0;
    }
コード例 #29
0
ファイル: geo.cpp プロジェクト: boreys/ardb
 int Ardb::GeoSearch(Context& ctx, RedisCommandFrame& cmd)
 {
     GeoSearchOptions options;
     std::string err;
     if (0 != options.Parse(cmd.GetArguments(), err, 1))
     {
         fill_error_reply(ctx.reply, "%s", err.c_str());
         return 0;
     }
     ValueObject meta;
     int ret = GetMetaValue(ctx, cmd.GetArguments()[0], ZSET_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, ret);
     ctx.reply.type = REDIS_REPLY_ARRAY;
     if (0 != ret)
     {
         return 0;
     }
     uint64 t1 = get_current_epoch_millis();
     uint32 min_radius = 75; //magic number
     if (options.asc && options.limit > 0 && options.offset == 0 && options.radius > min_radius)
     {
         uint32 old_radius = options.radius;
         options.radius = min_radius;
         do
         {
             ctx.reply.Clear();
             int point_num = GeoSearchByOptions(ctx, meta, options);
             if(point_num < 0)
             {
                 break;
             }
             if (options.radius == old_radius)
             {
                 break;
             }
             if (point_num > 0)
             {
                 if (point_num >= options.limit)
                 {
                     break;
                 }
                 options.radius *= sqrt((options.limit / point_num) + 1);
             }
             else
             {
                 options.radius *= 8;
             }
             if (options.radius > old_radius)
             {
                 options.radius = old_radius;
             }
         } while (options.radius <= old_radius);
     }
     else
     {
         GeoSearchByOptions(ctx, meta, options);
     }
     ctx.reply.type = REDIS_REPLY_ARRAY;
     uint64 t2 = get_current_epoch_millis();
     DEBUG_LOG("####Cost %llums to range geosearch", t2 - t1);
     return 0;
 }
コード例 #30
0
ファイル: t_list.cpp プロジェクト: huokedu/ardb
 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;
 }