Skip to content

Commit

Permalink
fix issue 2096: The setrange and setbit commands do not retain the ex…
Browse files Browse the repository at this point in the history
…piration time of the original key (#2095)

* fix setrange/bitop cmd lost key expire time

* Update string_test.go
  • Loading branch information
u6th9d authored Nov 4, 2023
1 parent 94bee9c commit d6ea4e2
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
6 changes: 6 additions & 0 deletions src/storage/src/redis_strings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -658,10 +658,12 @@ Status RedisStrings::SetBit(const Slice& key, int64_t offset, int32_t on, int32_
Status s = db_->Get(default_read_options_, key, &meta_value);
if (s.ok() || s.IsNotFound()) {
std::string data_value;
int32_t timestamp = 0;
if (s.ok()) {
ParsedStringsValue parsed_strings_value(&meta_value);
if (!parsed_strings_value.IsStale()) {
data_value = parsed_strings_value.value().ToString();
timestamp = parsed_strings_value.timestamp();
}
}
size_t byte = offset >> 3;
Expand All @@ -687,6 +689,7 @@ Status RedisStrings::SetBit(const Slice& key, int64_t offset, int32_t on, int32_
data_value.append(1, byte_val);
}
StringsValue strings_value(data_value);
strings_value.set_timestamp(timestamp);
return db_->Put(rocksdb::WriteOptions(), key, strings_value.Encode());
} else {
return s;
Expand Down Expand Up @@ -803,13 +806,15 @@ Status RedisStrings::Setrange(const Slice& key, int64_t start_offset, const Slic
ScopeRecordLock l(lock_mgr_, key);
Status s = db_->Get(default_read_options_, key, &old_value);
if (s.ok()) {
int32_t timestamp = 0;
ParsedStringsValue parsed_strings_value(&old_value);
parsed_strings_value.StripSuffix();
if (parsed_strings_value.IsStale()) {
std::string tmp(start_offset, '\0');
new_value = tmp.append(value.data());
*ret = static_cast<int32_t>(new_value.length());
} else {
timestamp = parsed_strings_value.timestamp();
if (static_cast<size_t>(start_offset) > old_value.length()) {
old_value.resize(start_offset);
new_value = old_value.append(value.data());
Expand All @@ -824,6 +829,7 @@ Status RedisStrings::Setrange(const Slice& key, int64_t start_offset, const Slic
}
*ret = static_cast<int32_t>(new_value.length());
StringsValue strings_value(new_value);
strings_value.set_timestamp(timestamp);
return db_->Put(default_write_options_, key, strings_value.Encode());
} else if (s.IsNotFound()) {
std::string tmp(start_offset, '\0');
Expand Down
30 changes: 27 additions & 3 deletions tests/integration/string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,23 @@ var _ = Describe("String Commands", func() {
Expect(get.Val()).To(Equal("hello"))
})

It("should SetBit", func() {
setBit := client.SetBit(ctx, "key_3s", 7, 1)
Expect(setBit.Err()).NotTo(HaveOccurred())
Expect(setBit.Val()).To(Equal(int64(0)))

Expect(client.Expire(ctx, "key_3s", 3*time.Second).Val()).To(Equal(true))
Expect(client.TTL(ctx, "key_3s").Val()).NotTo(Equal(int64(-2)))

setBit = client.SetBit(ctx, "key_3s", 69, 1)
Expect(client.TTL(ctx, "key_3s").Val()).NotTo(Equal(int64(-2)))
Expect(setBit.Err()).NotTo(HaveOccurred())
Expect(setBit.Val()).To(Equal(int64(0)))

time.Sleep(4 * time.Second)
Expect(client.TTL(ctx, "key_3s").Val()).To(Equal(time.Duration(-2)))
})

It("should GetBit", func() {
setBit := client.SetBit(ctx, "key", 7, 1)
Expect(setBit.Err()).NotTo(HaveOccurred())
Expand Down Expand Up @@ -882,17 +899,24 @@ var _ = Describe("String Commands", func() {
})

It("should SetRange", func() {
set := client.Set(ctx, "key", "Hello World", 0)
set := client.Set(ctx, "key_3s", "Hello World", 0)
Expect(set.Err()).NotTo(HaveOccurred())
Expect(set.Val()).To(Equal("OK"))

range_ := client.SetRange(ctx, "key", 6, "Redis")
Expect(client.Expire(ctx, "key_3s", 3*time.Second).Val()).To(Equal(true))
Expect(client.TTL(ctx, "key_3s").Val()).NotTo(Equal(int64(-2)))

range_ := client.SetRange(ctx, "key_3s", 6, "Redis")
Expect(range_.Err()).NotTo(HaveOccurred())
Expect(range_.Val()).To(Equal(int64(11)))

get := client.Get(ctx, "key")
get := client.Get(ctx, "key_3s")
Expect(get.Err()).NotTo(HaveOccurred())
Expect(get.Val()).To(Equal("Hello Redis"))
Expect(client.TTL(ctx, "key_3s").Val()).NotTo(Equal(int64(-2)))

time.Sleep(4 * time.Second)
Expect(client.TTL(ctx, "key_3s").Val()).To(Equal(time.Duration(-2)))
})

It("should StrLen", func() {
Expand Down

0 comments on commit d6ea4e2

Please sign in to comment.