Skip to content

Commit fd4f702

Browse files
abhijatromange
authored andcommitted
fix(hset_family): Fix val being overwritten by TTL (#5094)
When hset is loaded from rdb, if a ttl is specified by the user, the code recreates a string_view on top of the same memory location, tset_blob_, that was used for val earlier. This causes the val string view to point to the same value now as TTL has. For example if the val string view was 'x' earlier (points to tset_blob_, size 1), and ttl is 7777777, val now becomes '7'. To fix this val is now given it's own string. TTL is kept as string view as the pointer is not reused anywhere in the following loop. Signed-off-by: Abhijat Malviya <abhijat@dragonflydb.io>
1 parent 316bcae commit fd4f702

File tree

2 files changed

+31
-15
lines changed

2 files changed

+31
-15
lines changed

src/server/rdb_load.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,11 +482,12 @@ void RdbLoaderBase::OpaqueObjLoader::CreateHMap(const LoadTrace* ltrace) {
482482
}
483483
});
484484
std::string key;
485+
std::string val;
485486
for (size_t i = 0; i < ltrace->arr.size(); i += increment) {
486487
// ToSV may reference an internal buffer, therefore we can use only before the
487488
// next call to ToSV. To workaround, copy the key locally.
488489
key = ToSV(ltrace->arr[i].rdb_var);
489-
string_view val = ToSV(ltrace->arr[i + 1].rdb_var);
490+
val = ToSV(ltrace->arr[i + 1].rdb_var);
490491

491492
if (ec_)
492493
return;

tests/dragonfly/replication_test.py

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,18 @@
1-
import random
2-
3-
from itertools import chain, repeat
4-
import re
5-
import pytest
6-
import asyncio
7-
import async_timeout
81
import platform
9-
import pymemcache
10-
import logging
2+
import shutil
113
import tarfile
124
import urllib.request
13-
import shutil
14-
from redis import asyncio as aioredis
15-
from .utility import *
16-
from .instance import DflyInstanceFactory, DflyInstance
17-
from .seeder import Seeder as SeederV2
5+
from itertools import chain, repeat
6+
7+
import async_timeout
8+
import pymemcache
9+
1810
from . import dfly_args
11+
from .instance import DflyInstanceFactory, DflyInstance
1912
from .proxy import Proxy
2013
from .seeder import DebugPopulateSeeder
14+
from .seeder import Seeder as SeederV2
15+
from .utility import *
2116

2217
ADMIN_PORT = 1211
2318

@@ -3115,3 +3110,23 @@ async def test_partial_replication_on_same_source_master(df_factory, use_takeove
31153110
lines = replica2.find_in_logs(f"Started full with localhost:{replica1.port}")
31163111
assert len(lines) == 0
31173112
assert len(replica1.find_in_logs("No partial sync due to diff")) > 0
3113+
3114+
3115+
async def test_replicate_hset_with_expiry(df_factory: DflyInstanceFactory):
3116+
master = df_factory.create(proactor_threads=2)
3117+
replica = df_factory.create(proactor_threads=2)
3118+
3119+
master.start()
3120+
replica.start()
3121+
3122+
cm = master.client()
3123+
await cm.execute_command("HSETEX key 86400 name 1234")
3124+
3125+
cr = replica.client()
3126+
await cr.execute_command(f"REPLICAOF localhost {master.port}")
3127+
await wait_available_async(cr)
3128+
3129+
result = await cr.hgetall("key")
3130+
3131+
assert "name" in result
3132+
assert result["name"] == "1234"

0 commit comments

Comments
 (0)