/* * 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; }
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; } }