@@ -51,63 +51,6 @@ bool IsGoodForListpack(CmdArgList args, const uint8_t* lp) {
5151}
5252
5353using container_utils::GetStringMap;
54- using container_utils::LpFind;
55-
56- pair<uint8_t*, bool> LpDelete(uint8_t* lp, string_view field) {
57- uint8_t* fptr = lpFirst(lp);
58- DCHECK(fptr);
59- fptr = lpFind(lp, fptr, (unsigned char*)field.data(), field.size(), 1);
60- if (fptr == NULL) {
61- return make_pair(lp, false);
62- }
63-
64- /* Delete both of the key and the value. */
65- lp = lpDeleteRangeWithEntry(lp, &fptr, 2);
66- return make_pair(lp, true);
67- }
68-
69- // returns a new pointer to lp. Returns true if field was inserted or false it it already existed.
70- // skip_exists controls what happens if the field already existed. If skip_exists = true,
71- // then val does not override the value and listpack is not changed. Otherwise, the corresponding
72- // value is overridden by val.
73- pair<uint8_t*, bool> LpInsert(uint8_t* lp, string_view field, string_view val, bool skip_exists) {
74- uint8_t* vptr;
75-
76- uint8_t* fptr = lpFirst(lp);
77- uint8_t* fsrc = field.empty() ? lp : (uint8_t*)field.data();
78-
79- // if we vsrc is NULL then lpReplace will delete the element, which is not what we want.
80- // therefore, for an empty val we set it to some other valid address so that lpReplace
81- // will do the right thing and encode empty string instead of deleting the element.
82- uint8_t* vsrc = val.empty() ? lp : (uint8_t*)val.data();
83-
84- bool updated = false;
85-
86- if (fptr) {
87- fptr = lpFind(lp, fptr, fsrc, field.size(), 1);
88- if (fptr) {
89- if (skip_exists) {
90- return make_pair(lp, false);
91- }
92- /* Grab pointer to the value (fptr points to the field) */
93- vptr = lpNext(lp, fptr);
94- updated = true;
95-
96- /* Replace value */
97- lp = lpReplace(lp, &vptr, vsrc, val.size());
98- DCHECK_EQ(0u, lpLength(lp) % 2);
99- }
100- }
101-
102- if (!updated) {
103- /* Push new field/value pair onto the tail of the listpack */
104- // TODO: we should at least allocate once for both elements.
105- lp = lpAppend(lp, fsrc, field.size());
106- lp = lpAppend(lp, vsrc, val.size());
107- }
108-
109- return make_pair(lp, !updated);
110- }
11154
11255struct HMapWrap {
11356 private:
@@ -263,12 +206,13 @@ OpStatus OpIncrBy(const OpArgs& op_args, string_view key, string_view field, Inc
263206 unsigned enc = pv.Encoding();
264207
265208 if (enc == kEncodingListPack) {
266- uint8_t intbuf[LP_INTBUF_SIZE];
267- uint8_t* lp = (uint8_t*)pv.RObjPtr();
209+ detail::ListpackWrap lw{static_cast<uint8_t*>(pv.RObjPtr())};
268210 optional<string_view> res;
269211
270- if (!add_res.is_new)
271- res = LpFind(lp, field, intbuf);
212+ if (!add_res.is_new) {
213+ if (auto it = lw.Find(field); it != lw.end())
214+ res = (*it).second;
215+ }
272216
273217 OpStatus status = IncrementValue(res, param);
274218 if (status != OpStatus::OK) {
@@ -279,14 +223,14 @@ OpStatus OpIncrBy(const OpArgs& op_args, string_view key, string_view field, Inc
279223 double new_val = get<double>(*param);
280224 char buf[128];
281225 char* str = RedisReplyBuilder::FormatDouble(new_val, buf, sizeof(buf));
282- lp = LpInsert(lp, field, str, false).first ;
226+ lw.Insert( field, str, false);
283227 } else { // integer increment
284228 int64_t new_val = get<int64_t>(*param);
285229 absl::AlphaNum an(new_val);
286- lp = LpInsert(lp, field, an.Piece(), false).first ;
230+ lw.Insert( field, an.Piece(), false);
287231 }
288232
289- pv.SetRObjPtr(lp );
233+ pv.SetRObjPtr(lw.GetPointer() );
290234 } else {
291235 DCHECK_EQ(enc, kEncodingStrMap2);
292236 StringMap* sm = GetStringMap(pv, op_args.db_cntx);
@@ -387,19 +331,13 @@ OpResult<uint32_t> OpDel(const OpArgs& op_args, string_view key, CmdArgList valu
387331 unsigned enc = pv.Encoding();
388332
389333 if (enc == kEncodingListPack) {
390- uint8_t* lp = (uint8_t*)pv.RObjPtr();
391- for (auto s : values) {
392- auto res = LpDelete(lp, s);
393- if (res.second) {
334+ detail::ListpackWrap lw{static_cast<uint8_t*>(pv.RObjPtr())};
335+ for (string_view s : values) {
336+ if (lw.Delete(s))
394337 ++deleted;
395- lp = res.first;
396- if (lpLength(lp) == 0) {
397- key_remove = true;
398- break;
399- }
400- }
401338 }
402- pv.SetRObjPtr(lp);
339+ pv.SetRObjPtr(lw.GetPointer());
340+ key_remove = lw.size() == 0;
403341 } else {
404342 DCHECK_EQ(enc, kEncodingStrMap2);
405343 StringMap* sm = GetStringMap(pv, op_args.db_cntx);
@@ -505,17 +443,16 @@ OpResult<uint32_t> OpSet(const OpArgs& op_args, string_view key, CmdArgList valu
505443 unsigned created = 0;
506444
507445 if (lp) {
508- bool inserted;
509446 size_t malloc_reserved = zmalloc_size(lp);
510447 size_t min_sz = EstimateListpackMinBytes(values);
511448 if (min_sz > malloc_reserved) {
512449 lp = (uint8_t*)zrealloc(lp, min_sz);
513450 }
451+ detail::ListpackWrap lw{lp};
514452 for (size_t i = 0; i < values.size(); i += 2) {
515- tie(lp, inserted) = LpInsert(lp, ArgS(values, i), ArgS(values, i + 1), op_sp.skip_if_exists);
516- created += inserted;
453+ created += lw.Insert(values[i], values[i + 1], op_sp.skip_if_exists);
517454 }
518- pv.SetRObjPtr(lp );
455+ pv.SetRObjPtr(lw.GetPointer() );
519456 } else {
520457 DCHECK_EQ(kEncodingStrMap2, pv.Encoding()); // Dictionary
521458 StringMap* sm = GetStringMap(pv, op_args.db_cntx);
@@ -1102,10 +1039,8 @@ int32_t HSetFamily::FieldExpireTime(const DbContext& db_context, const PrimeValu
11021039 DCHECK_EQ(OBJ_HASH, pv.ObjType());
11031040
11041041 if (pv.Encoding() == kEncodingListPack) {
1105- uint8_t intbuf[LP_INTBUF_SIZE];
1106- uint8_t* lp = (uint8_t*)pv.RObjPtr();
1107- optional<string_view> res = LpFind(lp, field, intbuf);
1108- return res ? -1 : -3;
1042+ detail::ListpackWrap lw{static_cast<uint8_t*>(pv.RObjPtr())};
1043+ return lw.Find(field) == lw.end() ? -3 : -1;
11091044 } else {
11101045 StringMap* string_map = (StringMap*)pv.RObjPtr();
11111046 string_map->set_time(MemberTimeSeconds(db_context.time_now_ms));
0 commit comments