@@ -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