@@ -351,65 +351,104 @@ void AnalyzeSets(const std::string& path, std::vector<KeyInfo>& key_infos, const
351351
352352 std::cout << " Analyzing sets database at " << path << " ..." << std::endl;
353353
354- // 初始化存储选项
355- storage::StorageOptions storage_options;
356- storage::Storage storage;
357- rocksdb::Status s = storage.Open (storage_options, path);
354+ // Open database with column families
355+ rocksdb::DBOptions db_options;
356+ std::vector<rocksdb::ColumnFamilyDescriptor> column_families;
357+ column_families.emplace_back (rocksdb::kDefaultColumnFamilyName , rocksdb::ColumnFamilyOptions ());
358+ column_families.emplace_back (" data_cf" , rocksdb::ColumnFamilyOptions ());
358359
359- if (!s.ok ()) {
360- std::cerr << " Error opening sets database: " << s.ToString () << std::endl;
360+ std::vector<rocksdb::ColumnFamilyHandle*> handles;
361+ rocksdb::DB* db;
362+ rocksdb::Status status = rocksdb::DB::OpenForReadOnly (db_options, path, column_families, &handles, &db);
363+
364+ if (!status.ok ()) {
365+ std::cerr << " Error opening sets database: " << status.ToString () << std::endl;
361366 return ;
362367 }
363-
364- // 使用Scan API遍历所有set keys
365- std::string start_key;
366- const std::string pattern (" *" );
367- const int64_t count = 1000 ;
368- std::string next_key;
369- bool scan_finished = false ;
370-
371- while (!scan_finished) {
372- std::vector<std::string> keys;
373- s = storage.Scanx (storage::DataType::kSets , start_key, pattern, count, &keys, &next_key);
374- if (!s.ok ()) {
375- std::cerr << " Error scanning sets: " << s.ToString () << std::endl;
376- break ;
377- }
378-
379- // 如果next_key为空,或者没有找到更多键,则结束扫描
380- if (next_key.empty () || keys.empty ()) {
381- scan_finished = true ;
382- }
368+
369+ int64_t curtime;
370+ db->GetEnv ()->GetCurrentTime (&curtime).ok ();
371+
372+ rocksdb::ReadOptions read_options;
373+
374+ // Using an unordered_map to group set members by key
375+ std::unordered_map<std::string, std::pair<int64_t , int64_t >> set_sizes; // key -> (size, ttl)
376+
377+ // Read metadata from default column family (handles[0])
378+ auto meta_iter = db->NewIterator (read_options, handles[0 ]);
379+ for (meta_iter->SeekToFirst (); meta_iter->Valid (); meta_iter->Next ()) {
380+ rocksdb::Slice key_slice = meta_iter->key ();
381+ rocksdb::Slice value_slice = meta_iter->value ();
382+ std::string key = key_slice.ToString ();
383383
384- start_key = next_key ;
384+ int64_t ttl = - 1 ;
385385
386- // 处理每个集合键
387- for (const auto & key : keys) {
388- int64_t sum = 0 ;
389- sum = sum + key.size () + 12 ; // 基础元数据大小
390-
391- // 获取set的所有成员
392- std::vector<std::string> members;
393- int64_t ttl = -1 ;
386+ // Parse metadata value to get TTL
387+ if (value_slice.size () >= storage::ParsedBaseMetaValue::kBaseMetaValueSuffixLength ) {
388+ storage::ParsedSetsMetaValue parsed_meta (value_slice);
394389
395- s = storage. SMembersWithTTL (key, &members, &ttl);
396- if (!s. ok () ) {
390+ // Skip stale or empty sets
391+ if (parsed_meta. IsStale () || parsed_meta. count () == 0 ) {
397392 continue ;
398393 }
399394
400- // 计算每个成员的大小并加总
401- for (const auto & member : members) {
402- sum = sum + 4 + key.size () + 4 + member.size ();
395+ int32_t timestamp = parsed_meta.timestamp ();
396+ if (timestamp > 0 && !parsed_meta.IsPermanentSurvival ()) {
397+ int64_t diff = timestamp - curtime;
398+ ttl = diff > 0 ? diff : -2 ;
403399 }
400+ }
401+
402+ // Initialize with base metadata size (key + 12 bytes overhead)
403+ int64_t sum = key.size () + 12 ;
404+ set_sizes[key] = std::make_pair (sum, ttl);
405+ }
406+ delete meta_iter;
407+
408+ // Read data members from data column family (handles[1])
409+ auto data_iter = db->NewIterator (read_options, handles[1 ]);
410+ for (data_iter->SeekToFirst (); data_iter->Valid (); data_iter->Next ()) {
411+ rocksdb::Slice encoded_key_slice = data_iter->key ();
412+ rocksdb::Slice value_slice = data_iter->value ();
413+
414+ // Parse the data key to extract the set key and member
415+ try {
416+ storage::ParsedSetsMemberKey parsed_key (encoded_key_slice);
417+ std::string set_key = parsed_key.key ().ToString ();
418+ std::string member = parsed_key.member ().ToString ();
404419
405- // 如果key大小超过阈值,添加到结果集
406- if (sum >= config.min_size ) {
407- std::string display_key = ReplaceAll (key, " \n " , " \\ n" );
408- display_key = ReplaceAll (display_key, " " , " \\ x20" );
409- key_infos.emplace_back (" set" , display_key, sum, ttl);
420+ // Calculate member size: 4 (size prefix) + key + 4 (size prefix) + member
421+ int64_t member_size = 4 + set_key.size () + 4 + member.size ();
422+
423+ // Add member size to the corresponding set
424+ auto it = set_sizes.find (set_key);
425+ if (it != set_sizes.end ()) {
426+ it->second .first += member_size;
427+ } else {
428+ // If metadata not found, initialize with member size and default ttl
429+ set_sizes[set_key] = std::make_pair (set_key.size () + 12 + member_size, -1 );
410430 }
431+ } catch (...) {
432+ // Skip malformed keys
433+ continue ;
411434 }
412435 }
436+ delete data_iter;
437+
438+ // Add set keys to the result
439+ for (const auto & entry : set_sizes) {
440+ if (entry.second .first >= config.min_size ) {
441+ std::string display_key = ReplaceAll (entry.first , " \n " , " \\ n" );
442+ display_key = ReplaceAll (display_key, " " , " \\ x20" );
443+ key_infos.emplace_back (" set" , display_key, entry.second .first , entry.second .second );
444+ }
445+ }
446+
447+ // Cleanup
448+ for (auto handle : handles) {
449+ delete handle;
450+ }
451+ delete db;
413452}
414453
415454// Analyze zsets database
@@ -607,68 +646,103 @@ void AnalyzeLists(const std::string& path, std::vector<KeyInfo>& key_infos, cons
607646
608647 std::cout << " Analyzing lists database at " << path << " ..." << std::endl;
609648
610- // 初始化存储选项
611- storage::StorageOptions storage_options;
612- storage::Storage storage;
613- rocksdb::Status s = storage.Open (storage_options, path);
649+ // Open database with column families
650+ rocksdb::DBOptions db_options;
651+ std::vector<rocksdb::ColumnFamilyDescriptor> column_families;
652+ column_families.emplace_back (rocksdb::kDefaultColumnFamilyName , rocksdb::ColumnFamilyOptions ());
653+ column_families.emplace_back (" data_cf" , rocksdb::ColumnFamilyOptions ());
614654
615- if (!s.ok ()) {
616- std::cerr << " Error opening lists database: " << s.ToString () << std::endl;
655+ std::vector<rocksdb::ColumnFamilyHandle*> handles;
656+ rocksdb::DB* db;
657+ rocksdb::Status status = rocksdb::DB::OpenForReadOnly (db_options, path, column_families, &handles, &db);
658+
659+ if (!status.ok ()) {
660+ std::cerr << " Error opening lists database: " << status.ToString () << std::endl;
617661 return ;
618662 }
619-
620- // 使用Scan API遍历所有list keys
621- std::string start_key;
622- const std::string pattern (" *" );
623- const int64_t count = 1000 ;
624- const int64_t batch_count = 1000 ;
625- std::string next_key;
626- bool scan_finished = false ;
627-
628- while (!scan_finished) {
629- std::vector<std::string> keys;
630- s = storage.Scanx (storage::DataType::kLists , start_key, pattern, count, &keys, &next_key);
631- if (!s.ok ()) {
632- std::cerr << " Error scanning lists: " << s.ToString () << std::endl;
633- break ;
634- }
635-
636- // 如果next_key为空,或者没有找到更多键,则结束扫描
637- if (next_key.empty () || keys.empty ()) {
638- scan_finished = true ;
639- }
663+
664+ int64_t curtime;
665+ db->GetEnv ()->GetCurrentTime (&curtime).ok ();
666+
667+ rocksdb::ReadOptions read_options;
668+
669+ // Using an unordered_map to group list items by key
670+ std::unordered_map<std::string, std::pair<int64_t , int64_t >> list_sizes; // key -> (size, ttl)
671+
672+ // Read metadata from default column family (handles[0])
673+ auto meta_iter = db->NewIterator (read_options, handles[0 ]);
674+ for (meta_iter->SeekToFirst (); meta_iter->Valid (); meta_iter->Next ()) {
675+ rocksdb::Slice key_slice = meta_iter->key ();
676+ rocksdb::Slice value_slice = meta_iter->value ();
677+ std::string key = key_slice.ToString ();
640678
641- start_key = next_key ;
679+ int64_t ttl = - 1 ;
642680
643- // 处理每个列表键
644- for (const auto & key : keys) {
645- int64_t sum = 0 ;
646- sum = sum + key.size () + 12 + 16 ; // 基础元数据大小
681+ // Parse metadata value to get TTL
682+ if (value_slice.size () >= storage::ParsedBaseMetaValue::kBaseMetaValueSuffixLength ) {
683+ storage::ParsedListsMetaValue parsed_meta (value_slice);
647684
648- // 获取list的所有元素,分批获取
649- int64_t pos = 0 ;
650- std::vector<std::string> list_items ;
651- int64_t ttl = - 1 ;
685+ // Skip stale or empty lists
686+ if (parsed_meta. IsStale () || parsed_meta. count () == 0 ) {
687+ continue ;
688+ }
652689
653- s = storage.LRangeWithTTL (key, pos, pos + batch_count - 1 , &list_items, &ttl);
654- while (s.ok () && !list_items.empty ()) {
655- for (const auto & item : list_items) {
656- sum = sum + 4 + key.size () + 4 + 8 + item.size ();
657- }
658-
659- pos += batch_count;
660- list_items.clear ();
661- s = storage.LRange (key, pos, pos + batch_count - 1 , &list_items);
690+ int32_t timestamp = parsed_meta.timestamp ();
691+ if (timestamp > 0 && !parsed_meta.IsPermanentSurvival ()) {
692+ int64_t diff = timestamp - curtime;
693+ ttl = diff > 0 ? diff : -2 ;
662694 }
695+ }
696+
697+ // Initialize with base metadata size (key + 12 + 16 bytes overhead)
698+ int64_t sum = key.size () + 12 + 16 ;
699+ list_sizes[key] = std::make_pair (sum, ttl);
700+ }
701+ delete meta_iter;
702+
703+ // Read data items from data column family (handles[1])
704+ auto data_iter = db->NewIterator (read_options, handles[1 ]);
705+ for (data_iter->SeekToFirst (); data_iter->Valid (); data_iter->Next ()) {
706+ rocksdb::Slice encoded_key_slice = data_iter->key ();
707+ rocksdb::Slice value_slice = data_iter->value ();
708+
709+ // Parse the data key to extract the list key
710+ try {
711+ storage::ParsedBaseDataKey parsed_key (encoded_key_slice); // Lists use BaseDataKey directly
712+ std::string list_key = parsed_key.key ().ToString ();
713+
714+ // Calculate element size: 4 + key + 4 + 8 (index) + element
715+ int64_t element_size = 4 + list_key.size () + 4 + 8 + value_slice.size ();
663716
664- // 如果key大小超过阈值,添加到结果集
665- if (sum >= config.min_size ) {
666- std::string display_key = ReplaceAll (key, " \n " , " \\ n" );
667- display_key = ReplaceAll (display_key, " " , " \\ x20" );
668- key_infos.emplace_back (" list" , display_key, sum, ttl);
717+ // Add element size to the corresponding list
718+ auto it = list_sizes.find (list_key);
719+ if (it != list_sizes.end ()) {
720+ it->second .first += element_size;
721+ } else {
722+ // If metadata not found, initialize with element size and default ttl
723+ list_sizes[list_key] = std::make_pair (list_key.size () + 12 + 16 + element_size, -1 );
669724 }
725+ } catch (...) {
726+ // Skip malformed keys
727+ continue ;
670728 }
671729 }
730+ delete data_iter;
731+
732+ // Add list keys to the result
733+ for (const auto & entry : list_sizes) {
734+ if (entry.second .first >= config.min_size ) {
735+ std::string display_key = ReplaceAll (entry.first , " \n " , " \\ n" );
736+ display_key = ReplaceAll (display_key, " " , " \\ x20" );
737+ key_infos.emplace_back (" list" , display_key, entry.second .first , entry.second .second );
738+ }
739+ }
740+
741+ // Cleanup
742+ for (auto handle : handles) {
743+ delete handle;
744+ }
745+ delete db;
672746}
673747
674748// Get the prefix of a key
0 commit comments