@@ -1492,6 +1492,246 @@ TEST_F(DBTest, MetaDataTest) {
14921492 CheckLiveFilesMeta (live_file_meta, files_by_level);
14931493}
14941494
1495+ TEST_F (DBTest, GetColumnFamilyMetaDataWithKeyRangeAndLevel) {
1496+ Options options = CurrentOptions ();
1497+ options.create_if_missing = true ;
1498+ options.disable_auto_compactions = true ;
1499+
1500+ int64_t temp_time = 0 ;
1501+ ASSERT_OK (options.env ->GetCurrentTime (&temp_time));
1502+
1503+ DestroyAndReopen (options);
1504+
1505+ Random rnd (301 );
1506+ int key_index = 0 ;
1507+ for (int i = 0 ; i < 100 ; ++i) {
1508+ // Add a single blob reference to each file
1509+ std::string blob_index;
1510+ BlobIndex::EncodeBlob (&blob_index, /* blob_file_number */ i + 1000 ,
1511+ /* offset */ 1234 , /* size */ 5678 , kNoCompression );
1512+
1513+ WriteBatch batch;
1514+ ASSERT_OK (WriteBatchInternal::PutBlobIndex (&batch, 0 , Key (key_index),
1515+ blob_index));
1516+ ASSERT_OK (dbfull ()->Write (WriteOptions (), &batch));
1517+
1518+ ++key_index;
1519+
1520+ // Fill up the rest of the file with random values.
1521+ GenerateNewFile (&rnd, &key_index, /* nowait */ true );
1522+
1523+ ASSERT_OK (Flush ());
1524+ }
1525+
1526+ std::vector<std::vector<FileMetaData>> files_by_level;
1527+ dbfull ()->TEST_GetFilesMetaData (db_->DefaultColumnFamily (), &files_by_level);
1528+
1529+ ASSERT_OK (options.env ->GetCurrentTime (&temp_time));
1530+
1531+ ColumnFamilyMetaData cf_meta;
1532+ // Keys in the SST files are distributed
1533+ // (key000000, key000100) ->File 1
1534+ // (key000101, key000201) -> File 2
1535+ // (key000202, key000302) -> File 3
1536+ // (key009999, key010099) -> File 100
1537+
1538+ // With keySlice (key000050, key000150) => should only pick 2 files(instead of
1539+ // default 100 that is in the level)
1540+ auto startKey = Slice (" key000050" );
1541+ auto endKey = Slice (" key000150" );
1542+ GetColumnFamilyMetaDataOptions cf_options (startKey, endKey, 0 );
1543+ db_->GetColumnFamilyMetaData (cf_options, &cf_meta);
1544+ ASSERT_EQ (cf_meta.levels .size (), 1 );
1545+ const auto & level_meta_from_cf = cf_meta.levels [0 ];
1546+ ASSERT_EQ (level_meta_from_cf.files .size (), 2 );
1547+ ASSERT_LT (level_meta_from_cf.files [1 ].smallestkey ,
1548+ std::string (startKey.data ()));
1549+ ASSERT_GT (level_meta_from_cf.files [0 ].largestkey , std::string (endKey.data ()));
1550+
1551+ GetColumnFamilyMetaDataOptions cf_option_default;
1552+ db_->GetColumnFamilyMetaData (cf_option_default, &cf_meta);
1553+ ASSERT_EQ (cf_meta.levels .size (), 1 );
1554+ ASSERT_EQ (cf_meta.levels [0 ].files .size (), 100 );
1555+
1556+ // Test with start key valid and end key unbounded
1557+ // This should get all files from key000150 onwards (99 files)
1558+ auto startKeyUnbounded = Slice (" key000150" );
1559+ GetColumnFamilyMetaDataOptions cf_options_unbounded_end (startKeyUnbounded,
1560+ OptSlice (), 0 );
1561+ db_->GetColumnFamilyMetaData (cf_options_unbounded_end, &cf_meta);
1562+ ASSERT_EQ (cf_meta.levels .size (), 1 );
1563+ ASSERT_EQ (cf_meta.levels [0 ].files .size (), 99 );
1564+
1565+ // Test with end key valid and start key unbounded
1566+ // This should get all files from beginning to key000250 ( 3 files)
1567+ auto endKeyUnbounded = Slice (" key000250" );
1568+ GetColumnFamilyMetaDataOptions cf_options_unbounded_start (OptSlice (),
1569+ endKeyUnbounded, 0 );
1570+ db_->GetColumnFamilyMetaData (cf_options_unbounded_start, &cf_meta);
1571+ ASSERT_EQ (cf_meta.levels .size (), 1 );
1572+ ASSERT_EQ (cf_meta.levels [0 ].files .size (), 3 );
1573+ }
1574+
1575+ TEST_F (DBTest, GetColumnFamilyMetaDataBottommostLevel) {
1576+ Options options = CurrentOptions ();
1577+ options.create_if_missing = true ;
1578+ options.disable_auto_compactions = true ;
1579+ options.num_levels = 7 ;
1580+
1581+ DestroyAndReopen (options);
1582+
1583+ Random rnd (301 );
1584+ int key_index = 0 ;
1585+
1586+ for (int i = 0 ; i < 100 ; ++i) {
1587+ GenerateNewFile (&rnd, &key_index, /* nowait */ true );
1588+ ASSERT_OK (Flush ());
1589+ }
1590+
1591+ CompactRangeOptions compact_options;
1592+ compact_options.bottommost_level_compaction =
1593+ BottommostLevelCompaction::kForce ;
1594+ compact_options.change_level = true ;
1595+ compact_options.target_level = 6 ;
1596+ ASSERT_OK (db_->CompactRange (compact_options, nullptr , nullptr ));
1597+
1598+ // Nothing on Level 0 after compaction
1599+ ColumnFamilyMetaData cf_meta;
1600+ GetColumnFamilyMetaDataOptions cf_options_0 (OptSlice (), OptSlice (), 0 );
1601+ db_->GetColumnFamilyMetaData (cf_options_0, &cf_meta);
1602+
1603+ ASSERT_EQ (cf_meta.levels .size (), 0 );
1604+ ASSERT_EQ (cf_meta.file_count , 0 );
1605+
1606+ // Data should be in Level 6
1607+ GetColumnFamilyMetaDataOptions cf_options (OptSlice (), OptSlice (), 6 );
1608+ db_->GetColumnFamilyMetaData (cf_options, &cf_meta);
1609+
1610+ ASSERT_EQ (cf_meta.levels .size (), 1 );
1611+ ASSERT_EQ (cf_meta.levels [0 ].level , 6 );
1612+ ASSERT_GT (cf_meta.levels [0 ].files .size (), 0 );
1613+ size_t all_files = cf_meta.levels [0 ].files .size ();
1614+
1615+ // Keys in the SST files are distributed across level 6
1616+ // Test with key range - should only return files within the range
1617+ auto startKey = Slice (" key000050" );
1618+ auto endKey = Slice (" key000150" );
1619+ GetColumnFamilyMetaDataOptions cf_options_range (startKey, endKey, 6 );
1620+ db_->GetColumnFamilyMetaData (cf_options_range, &cf_meta);
1621+
1622+ ASSERT_EQ (cf_meta.levels .size (), 1 );
1623+ ASSERT_EQ (cf_meta.levels [0 ].level , 6 );
1624+ ASSERT_GT (cf_meta.levels [0 ].files .size (), 0 );
1625+ size_t files_in_range = cf_meta.levels [0 ].files .size ();
1626+
1627+ // Files in range should be less than or equal to all files
1628+ ASSERT_LE (files_in_range, all_files);
1629+ }
1630+
1631+ TEST_F (DBTest, GetColumnFamilyMetaDataMultipleLevels) {
1632+ Options options = CurrentOptions ();
1633+ options.create_if_missing = true ;
1634+ options.disable_auto_compactions = true ;
1635+ options.num_levels = 7 ;
1636+
1637+ DestroyAndReopen (options);
1638+
1639+ Random rnd (301 );
1640+ int key_index = 0 ;
1641+
1642+ for (int i = 0 ; i < 50 ; ++i) {
1643+ GenerateNewFile (&rnd, &key_index, /* nowait */ true );
1644+ ASSERT_OK (Flush ());
1645+ }
1646+
1647+ CompactRangeOptions compact_options;
1648+ compact_options.bottommost_level_compaction =
1649+ BottommostLevelCompaction::kForce ;
1650+ compact_options.change_level = true ;
1651+ compact_options.target_level = 6 ;
1652+ ASSERT_OK (db_->CompactRange (compact_options, nullptr , nullptr ));
1653+
1654+ for (int i = 0 ; i < 30 ; ++i) {
1655+ GenerateNewFile (&rnd, &key_index, /* nowait */ true );
1656+ ASSERT_OK (Flush ());
1657+ }
1658+
1659+ // First verify both levels have files without key range filter
1660+ ColumnFamilyMetaData cf_meta_all_no_range;
1661+ GetColumnFamilyMetaDataOptions cf_options_all_no_range;
1662+ db_->GetColumnFamilyMetaData (cf_options_all_no_range, &cf_meta_all_no_range);
1663+
1664+ bool has_level_0 = false ;
1665+ bool has_level_6 = false ;
1666+ for (const auto & level : cf_meta_all_no_range.levels ) {
1667+ if (level.level == 0 && level.files .size () > 0 ) {
1668+ has_level_0 = true ;
1669+ }
1670+ if (level.level == 6 && level.files .size () > 0 ) {
1671+ has_level_6 = true ;
1672+ }
1673+ }
1674+
1675+ ASSERT_TRUE (has_level_0);
1676+ ASSERT_TRUE (has_level_6);
1677+
1678+ // Test querying bottommost level only with key range
1679+ // Use a range that should be in the first set of files (now in level 6)
1680+ auto startKey = Slice (" key000050" );
1681+ auto endKey = Slice (" key000150" );
1682+ ColumnFamilyMetaData cf_meta_bottommost;
1683+ GetColumnFamilyMetaDataOptions cf_options_bottommost (startKey, endKey, 6 );
1684+ db_->GetColumnFamilyMetaData (cf_options_bottommost, &cf_meta_bottommost);
1685+
1686+ ASSERT_EQ (cf_meta_bottommost.levels .size (), 1 );
1687+ ASSERT_EQ (cf_meta_bottommost.levels [0 ].level , 6 );
1688+ ASSERT_GT (cf_meta_bottommost.levels [0 ].files .size (), 0 );
1689+ size_t level_6_files_in_range = cf_meta_bottommost.levels [0 ].files .size ();
1690+
1691+ // Test querying all levels with same key range
1692+ ColumnFamilyMetaData cf_meta_all;
1693+ GetColumnFamilyMetaDataOptions cf_options_all (startKey, endKey);
1694+ db_->GetColumnFamilyMetaData (cf_options_all, &cf_meta_all);
1695+
1696+ size_t level_6_files_in_range_from_all = 0 ;
1697+ for (const auto & level : cf_meta_all.levels ) {
1698+ if (level.level == 6 ) {
1699+ level_6_files_in_range_from_all = level.files .size ();
1700+ }
1701+ }
1702+
1703+ ASSERT_GT (level_6_files_in_range_from_all, 0 );
1704+ ASSERT_EQ (level_6_files_in_range, level_6_files_in_range_from_all);
1705+ }
1706+
1707+ TEST_F (DBTest, GetColumnFamilyMetaDataEmptyDB) {
1708+ Options options = CurrentOptions ();
1709+ options.create_if_missing = true ;
1710+ options.num_levels = 7 ;
1711+
1712+ DestroyAndReopen (options);
1713+
1714+ // Test on empty database
1715+ ColumnFamilyMetaData cf_meta_empty_db;
1716+ GetColumnFamilyMetaDataOptions cf_options_empty_db;
1717+ db_->GetColumnFamilyMetaData (cf_options_empty_db, &cf_meta_empty_db);
1718+
1719+ ASSERT_EQ (cf_meta_empty_db.levels .size (), 0 );
1720+ ASSERT_EQ (cf_meta_empty_db.file_count , 0 );
1721+ ASSERT_EQ (cf_meta_empty_db.size , 0 );
1722+
1723+ // Test on empty database with key range
1724+ auto startKey = Slice (" key000050" );
1725+ auto endKey = Slice (" key000150" );
1726+ ColumnFamilyMetaData cf_meta_empty_range;
1727+ GetColumnFamilyMetaDataOptions cf_options_empty_range (startKey, endKey);
1728+ db_->GetColumnFamilyMetaData (cf_options_empty_range, &cf_meta_empty_range);
1729+
1730+ ASSERT_EQ (cf_meta_empty_range.levels .size (), 0 );
1731+ ASSERT_EQ (cf_meta_empty_range.file_count , 0 );
1732+ ASSERT_EQ (cf_meta_empty_range.size , 0 );
1733+ }
1734+
14951735TEST_F (DBTest, AllMetaDataTest) {
14961736 Options options = CurrentOptions ();
14971737 options.create_if_missing = true ;
@@ -3535,6 +3775,11 @@ class ModelDB : public DB {
35353775 void GetColumnFamilyMetaData (ColumnFamilyHandle* /* column_family*/ ,
35363776 ColumnFamilyMetaData* /* metadata*/ ) override {}
35373777
3778+ void GetColumnFamilyMetaData (
3779+ ColumnFamilyHandle* /* column_family*/ ,
3780+ const GetColumnFamilyMetaDataOptions& /* options*/ ,
3781+ ColumnFamilyMetaData* /* metadata*/ ) override {}
3782+
35383783 Status GetDbIdentity (std::string& /* identity*/ ) const override {
35393784 return Status::OK ();
35403785 }
0 commit comments