21
21
#include " redis_hash.h"
22
22
23
23
#include < rocksdb/status.h>
24
+ #include < sys/wait.h>
24
25
25
26
#include < algorithm>
26
27
#include < cctype>
@@ -46,15 +47,15 @@ rocksdb::Status Hash::Size(const Slice &user_key, uint64_t *size) {
46
47
HashMetadata metadata (false );
47
48
rocksdb::Status s = GetMetadata (Database::GetOptions{}, ns_key, &metadata);
48
49
if (!s.ok ()) return s;
49
- // if field expiration is disabled,
50
+ // if field expiration is disabled,
50
51
// the size field in metadata is the length of hash
51
52
if (!metadata.IsFieldExpirationEnabled ()) {
52
53
*size = metadata.size ;
53
54
return rocksdb::Status::OK ();
54
55
}
55
56
56
57
// otherwise, we have to check each field to calc the length
57
- LatestSnapShot ss (storage_);
58
+ LatestSnapShot ss (storage_);
58
59
std::string prefix_key = InternalKey (ns_key, " " , metadata.version , storage_->IsSlotIdEncoded ()).Encode ();
59
60
std::string next_version_prefix_key =
60
61
InternalKey (ns_key, " " , metadata.version + 1 , storage_->IsSlotIdEncoded ()).Encode ();
@@ -101,6 +102,9 @@ rocksdb::Status Hash::IncrBy(const Slice &user_key, const Slice &field, int64_t
101
102
HashMetadata metadata;
102
103
rocksdb::Status s = GetMetadata (GetOptions{}, ns_key, &metadata);
103
104
if (!s.ok () && !s.IsNotFound ()) return s;
105
+ if (s.IsNotFound ()) {
106
+ metadata.field_encoding = HashSubkeyEncoding::VALUE_WITH_TTL;
107
+ }
104
108
105
109
uint64_t expire = 0 ;
106
110
std::string sub_key = InternalKey (ns_key, field, metadata.version , storage_->IsSlotIdEncoded ()).Encode ();
@@ -156,6 +160,9 @@ rocksdb::Status Hash::IncrByFloat(const Slice &user_key, const Slice &field, dou
156
160
HashMetadata metadata;
157
161
rocksdb::Status s = GetMetadata (GetOptions{}, ns_key, &metadata);
158
162
if (!s.ok () && !s.IsNotFound ()) return s;
163
+ if (s.IsNotFound ()) {
164
+ metadata.field_encoding = HashSubkeyEncoding::VALUE_WITH_TTL;
165
+ }
159
166
160
167
uint64_t expire = 0 ;
161
168
std::string sub_key = InternalKey (ns_key, field, metadata.version , storage_->IsSlotIdEncoded ()).Encode ();
@@ -294,6 +301,12 @@ rocksdb::Status Hash::MSet(const Slice &user_key, const std::vector<FieldValue>
294
301
rocksdb::Status s = GetMetadata (GetOptions{}, ns_key, &metadata);
295
302
if (!s.ok () && !s.IsNotFound ()) return s;
296
303
304
+ // For avoid affect existing data,
305
+ // we only encode ttl of field on new hash object.
306
+ if (s.IsNotFound ()) {
307
+ metadata.field_encoding = HashSubkeyEncoding::VALUE_WITH_TTL;
308
+ }
309
+
297
310
int added = 0 ;
298
311
auto batch = storage_->GetWriteBatchBase ();
299
312
WriteBatchLogData log_data (kRedisHash );
@@ -502,6 +515,11 @@ rocksdb::Status Hash::ExpireFields(const Slice &user_key, uint64_t expire_ms, co
502
515
return rocksdb::Status::OK ();
503
516
}
504
517
518
+ // we don't support encode ttl on existing hash object
519
+ if (!metadata.IsFieldExpirationEnabled ()) {
520
+ return rocksdb::Status::NotSupported (" can't expire fields on existing hash object" );
521
+ }
522
+
505
523
rocksdb::ReadOptions read_options = storage_->DefaultMultiGetOptions ();
506
524
read_options.snapshot = ss.GetSnapShot ();
507
525
@@ -565,35 +583,6 @@ rocksdb::Status Hash::ExpireFields(const Slice &user_key, uint64_t expire_ms, co
565
583
}
566
584
}
567
585
568
- // convert rest field encoding
569
- if (!metadata.IsFieldExpirationEnabled ()) {
570
- metadata.field_encoding = HashSubkeyEncoding::VALUE_WITH_TTL;
571
-
572
- std::unordered_set<std::string_view> field_set;
573
- for (auto field : fields) {
574
- if (!field_set.emplace (field.ToStringView ()).second ) {
575
- continue ;
576
- }
577
- }
578
-
579
- std::string prefix_key = InternalKey (ns_key, " " , metadata.version , storage_->IsSlotIdEncoded ()).Encode ();
580
- std::string next_version_prefix_key =
581
- InternalKey (ns_key, " " , metadata.version + 1 , storage_->IsSlotIdEncoded ()).Encode ();
582
-
583
- rocksdb::Slice upper_bound (next_version_prefix_key);
584
- read_options.iterate_upper_bound = &upper_bound;
585
-
586
- auto iter = util::UniqueIterator (storage_, read_options);
587
- for (iter->Seek (prefix_key); iter->Valid () && iter->key ().starts_with (prefix_key); iter->Next ()) {
588
- InternalKey sub_ikey (iter->key (), storage_->IsSlotIdEncoded ());
589
- auto value = iter->value ().ToString ();
590
- if (field_set.find (sub_ikey.GetSubKey ().ToStringView ()) == field_set.end ()) {
591
- encodeExpireToValue (&value, 0 );
592
- batch->Put (sub_ikey.Encode (), value);
593
- }
594
- }
595
- }
596
-
597
586
std::string bytes;
598
587
metadata.Encode (&bytes);
599
588
batch->Put (metadata_cf_handle_, ns_key, bytes);
@@ -747,7 +736,7 @@ bool Hash::ExistValidField(const Slice &ns_key, const HashMetadata &metadata) {
747
736
return true ;
748
737
}
749
738
750
- LatestSnapShot ss (storage_);
739
+ LatestSnapShot ss (storage_);
751
740
std::string prefix_key = InternalKey (ns_key, " " , metadata.version , storage_->IsSlotIdEncoded ()).Encode ();
752
741
std::string next_version_prefix_key =
753
742
InternalKey (ns_key, " " , metadata.version + 1 , storage_->IsSlotIdEncoded ()).Encode ();
0 commit comments