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