empiredan commented on code in PR #1511:
URL: 
https://github.com/apache/incubator-pegasus/pull/1511#discussion_r1259123752


##########
src/server/pegasus_server_impl.cpp:
##########
@@ -2625,6 +2627,72 @@ pegasus_server_impl::get_restore_dir_from_env(const 
std::map<std::string, std::s
     return res;
 }
 
+void pegasus_server_impl::update_rocksdb_dynamic_options(
+    const std::map<std::string, std::string> &envs)
+{
+    if (envs.empty()) {
+        return;
+    }
+
+    std::unordered_map<std::string, std::string> new_options;
+    for (const auto &option : ROCKSDB_DYNAMIC_OPTIONS) {
+        auto find = envs.find(option);
+        if (find == envs.end()) {
+            continue;
+        }
+
+        std::vector<std::string> args;
+        // split_args example: Parse "write_buffer_size" from 
"rocksdb.write_buffer_size"
+        dsn::utils::split_args(option.c_str(), args, '.');
+        new_options[args[1]] = find->second;

Review Comment:
   ```suggestion
           CHECK_EQ(args.size(), 2);
           new_options[args[1]] = find->second;
   ```



##########
src/base/pegasus_const.cpp:
##########
@@ -101,4 +108,45 @@ const std::string 
USER_SPECIFIED_COMPACTION("user_specified_compaction");
 const std::string READ_SIZE_THROTTLING("replica.read_throttling_by_size");
 
 const std::string ROCKSDB_ALLOW_INGEST_BEHIND("rocksdb.allow_ingest_behind");
+
+const std::string ROCKSDB_WRITE_BUFFER_SIZE("rocksdb.write_buffer_size");
+
+const std::string ROCKSDB_NUM_LEVELS("rocksdb.num_levels");
+
+const std::set<std::string> ROCKSDB_DYNAMIC_OPTIONS = {
+    ROCKSDB_WRITE_BUFFER_SIZE,
+};
+const std::set<std::string> ROCKSDB_STATIC_OPTIONS = {
+    ROCKSDB_NUM_LEVELS,
+};
+
+const std::unordered_map<std::string, cf_opts_setter> cf_opts_setters = {
+    {ROCKSDB_WRITE_BUFFER_SIZE,
+     [](const std::string &str, rocksdb::ColumnFamilyOptions &option) -> bool {
+         uint64_t val = 0;
+         if (!dsn::buf2uint64(str, val))
+             return false;

Review Comment:
   ```suggestion
            if (!dsn::buf2uint64(str, val)) {
                return false;
            }
   ```



##########
src/server/pegasus_server_impl.cpp:
##########
@@ -2650,11 +2719,20 @@ void 
pegasus_server_impl::update_app_envs_before_open_db(
     update_validate_partition_hash(envs);
     update_user_specified_compaction(envs);
     _manual_compact_svc.start_manual_compact_if_needed(envs);
+    set_rocksdb_options_before_creating(envs);
 }
 
 void pegasus_server_impl::query_app_envs(/*out*/ std::map<std::string, 
std::string> &envs)
 {
     envs[ROCKSDB_ENV_USAGE_SCENARIO_KEY] = _usage_scenario;
+    // write_buffer_size involves random values (refer to 
pegasus_server_impl::set_usage_scenario),
+    // so it can only be taken from _data_cf_opts
+    envs[ROCKSDB_WRITE_BUFFER_SIZE] = fmt::format("{}", 
_data_cf_opts.write_buffer_size);
+
+    // Get Data ColumnFamilyOptions directly from _data_cf
+    rocksdb::ColumnFamilyDescriptor desc;
+    rocksdb::Status s = _data_cf->GetDescriptor(&desc);
+    envs[ROCKSDB_NUM_LEVELS] = fmt::format("{}", desc.options.num_levels);

Review Comment:
   Assign from `cf_opts_getters` ?



##########
src/base/pegasus_const.cpp:
##########
@@ -101,4 +108,45 @@ const std::string 
USER_SPECIFIED_COMPACTION("user_specified_compaction");
 const std::string READ_SIZE_THROTTLING("replica.read_throttling_by_size");
 
 const std::string ROCKSDB_ALLOW_INGEST_BEHIND("rocksdb.allow_ingest_behind");
+
+const std::string ROCKSDB_WRITE_BUFFER_SIZE("rocksdb.write_buffer_size");
+
+const std::string ROCKSDB_NUM_LEVELS("rocksdb.num_levels");
+
+const std::set<std::string> ROCKSDB_DYNAMIC_OPTIONS = {
+    ROCKSDB_WRITE_BUFFER_SIZE,
+};
+const std::set<std::string> ROCKSDB_STATIC_OPTIONS = {
+    ROCKSDB_NUM_LEVELS,
+};
+
+const std::unordered_map<std::string, cf_opts_setter> cf_opts_setters = {
+    {ROCKSDB_WRITE_BUFFER_SIZE,
+     [](const std::string &str, rocksdb::ColumnFamilyOptions &option) -> bool {
+         uint64_t val = 0;
+         if (!dsn::buf2uint64(str, val))
+             return false;
+         option.write_buffer_size = static_cast<size_t>(val);
+         return true;
+     }},
+    {ROCKSDB_NUM_LEVELS,
+     [](const std::string &str, rocksdb::ColumnFamilyOptions &option) -> bool {
+         int32_t val = 0;
+         if (!dsn::buf2int32(str, val))
+             return false;
+         option.num_levels = val;
+         return true;
+     }},
+};
+
+const std::unordered_map<std::string, cf_opts_getter> cf_opts_getters = {
+    {ROCKSDB_WRITE_BUFFER_SIZE,
+     [](/*out*/ std::string &str, const rocksdb::ColumnFamilyOptions &option) {

Review Comment:
   We could follow [Google 
Style](https://google.github.io/styleguide/cppguide.html#Inputs_and_Outputs), 
putting all output parameters at the rightmost side:
   ```
   When ordering function parameters, put all input-only parameters before any 
output parameters. In particular, do not add new parameters to the end of the 
function just because they are new; place new input-only parameters before the 
output parameters.
   ```



##########
src/server/pegasus_server_impl.cpp:
##########
@@ -2650,11 +2719,20 @@ void 
pegasus_server_impl::update_app_envs_before_open_db(
     update_validate_partition_hash(envs);
     update_user_specified_compaction(envs);
     _manual_compact_svc.start_manual_compact_if_needed(envs);
+    set_rocksdb_options_before_creating(envs);
 }
 
 void pegasus_server_impl::query_app_envs(/*out*/ std::map<std::string, 
std::string> &envs)
 {
     envs[ROCKSDB_ENV_USAGE_SCENARIO_KEY] = _usage_scenario;
+    // write_buffer_size involves random values (refer to 
pegasus_server_impl::set_usage_scenario),
+    // so it can only be taken from _data_cf_opts
+    envs[ROCKSDB_WRITE_BUFFER_SIZE] = fmt::format("{}", 
_data_cf_opts.write_buffer_size);

Review Comment:
   Assign from `cf_opts_getters` ?



##########
src/server/test/pegasus_server_impl_test.cpp:
##########
@@ -95,6 +97,51 @@ class pegasus_server_impl_test : public 
pegasus_server_test_base
             ASSERT_EQ(before_count + test.expect_perf_counter_incr, 
after_count);
         }
     }
+
+    void test_open_db_with_rocksdb_envs(bool is_restart)
+    {
+        struct create_test
+        {
+            std::string env_key;
+            std::string env_value;
+            std::string expect_value;
+        } tests[] = {
+            {"rocksdb.num_levels", "5", "5"}, {"rocksdb.write_buffer_size", 
"33554432", "33554432"},
+        };
+
+        std::map<std::string, std::string> all_test_envs;
+        {
+            // Make sure all rocksdb options of ROCKSDB_DYNAMIC_OPTIONS and 
ROCKSDB_STATIC_OPTIONS
+            // are tested.
+            for (auto test : tests) {
+                all_test_envs[test.env_key] = test.env_value;
+            }
+            for (const auto &option : pegasus::ROCKSDB_DYNAMIC_OPTIONS) {
+                ASSERT_TRUE(all_test_envs.find(option) != all_test_envs.end());
+            }
+            for (const auto &option : pegasus::ROCKSDB_STATIC_OPTIONS) {
+                ASSERT_TRUE(all_test_envs.find(option) != all_test_envs.end());
+            }
+        }
+
+        start(all_test_envs);
+        if (is_restart) {
+            _server->stop(false);
+            start();
+        }
+
+        std::map<std::string, std::string> query_envs;
+        _server->query_app_envs(query_envs);
+        for (auto test : tests) {
+            auto iter = query_envs.find(test.env_key);

Review Comment:
   ```suggestion
               const auto &iter = query_envs.find(test.env_key);
   ```



##########
src/server/pegasus_server_impl.cpp:
##########
@@ -2650,11 +2719,20 @@ void 
pegasus_server_impl::update_app_envs_before_open_db(
     update_validate_partition_hash(envs);
     update_user_specified_compaction(envs);
     _manual_compact_svc.start_manual_compact_if_needed(envs);
+    set_rocksdb_options_before_creating(envs);
 }
 
 void pegasus_server_impl::query_app_envs(/*out*/ std::map<std::string, 
std::string> &envs)
 {
     envs[ROCKSDB_ENV_USAGE_SCENARIO_KEY] = _usage_scenario;
+    // write_buffer_size involves random values (refer to 
pegasus_server_impl::set_usage_scenario),
+    // so it can only be taken from _data_cf_opts
+    envs[ROCKSDB_WRITE_BUFFER_SIZE] = fmt::format("{}", 
_data_cf_opts.write_buffer_size);
+
+    // Get Data ColumnFamilyOptions directly from _data_cf
+    rocksdb::ColumnFamilyDescriptor desc;
+    rocksdb::Status s = _data_cf->GetDescriptor(&desc);

Review Comment:
   ```suggestion
       auto s = _data_cf->GetDescriptor(&desc);
       CHECK_TRUE(s.ok());
   ```



##########
src/server/test/pegasus_server_impl_test.cpp:
##########
@@ -95,6 +97,51 @@ class pegasus_server_impl_test : public 
pegasus_server_test_base
             ASSERT_EQ(before_count + test.expect_perf_counter_incr, 
after_count);
         }
     }
+
+    void test_open_db_with_rocksdb_envs(bool is_restart)
+    {
+        struct create_test
+        {
+            std::string env_key;
+            std::string env_value;
+            std::string expect_value;
+        } tests[] = {
+            {"rocksdb.num_levels", "5", "5"}, {"rocksdb.write_buffer_size", 
"33554432", "33554432"},
+        };
+
+        std::map<std::string, std::string> all_test_envs;
+        {
+            // Make sure all rocksdb options of ROCKSDB_DYNAMIC_OPTIONS and 
ROCKSDB_STATIC_OPTIONS
+            // are tested.
+            for (auto test : tests) {
+                all_test_envs[test.env_key] = test.env_value;
+            }
+            for (const auto &option : pegasus::ROCKSDB_DYNAMIC_OPTIONS) {
+                ASSERT_TRUE(all_test_envs.find(option) != all_test_envs.end());
+            }
+            for (const auto &option : pegasus::ROCKSDB_STATIC_OPTIONS) {
+                ASSERT_TRUE(all_test_envs.find(option) != all_test_envs.end());
+            }
+        }
+
+        start(all_test_envs);
+        if (is_restart) {
+            _server->stop(false);
+            start();
+        }
+
+        std::map<std::string, std::string> query_envs;
+        _server->query_app_envs(query_envs);
+        for (auto test : tests) {

Review Comment:
   ```suggestion
           for (const auto &test : tests) {
   ```



##########
src/server/test/pegasus_server_impl_test.cpp:
##########
@@ -95,6 +97,51 @@ class pegasus_server_impl_test : public 
pegasus_server_test_base
             ASSERT_EQ(before_count + test.expect_perf_counter_incr, 
after_count);
         }
     }
+
+    void test_open_db_with_rocksdb_envs(bool is_restart)
+    {
+        struct create_test
+        {
+            std::string env_key;
+            std::string env_value;
+            std::string expect_value;
+        } tests[] = {
+            {"rocksdb.num_levels", "5", "5"}, {"rocksdb.write_buffer_size", 
"33554432", "33554432"},
+        };
+
+        std::map<std::string, std::string> all_test_envs;
+        {
+            // Make sure all rocksdb options of ROCKSDB_DYNAMIC_OPTIONS and 
ROCKSDB_STATIC_OPTIONS
+            // are tested.
+            for (auto test : tests) {

Review Comment:
   ```suggestion
               for (const auto &test : tests) {
   ```



##########
src/meta/test/meta_app_operation_test.cpp:
##########
@@ -373,43 +382,106 @@ TEST_F(meta_app_operation_test, create_app)
         bool success_if_exist;
         app_status::type before_status;
         error_code expected_err;
-    } tests[] = {{APP_NAME, -1, 3, 2, 3, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 0, 3, 2, 3, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, -1, 1, 3, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, 0, 1, 3, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, 6, 2, 4, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, 7, 2, 6, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, 6, 2, 5, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, 5, 2, 4, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, 4, 2, 3, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, 6, 2, 6, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, 6, 2, 7, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME + "_1", 4, 5, 2, 5, 1, false, 
app_status::AS_INVALID, ERR_OK},
-                 {APP_NAME + "_2", 4, 5, 2, 6, 1, false, 
app_status::AS_INVALID, ERR_OK},
-                 {APP_NAME + "_3", 4, 4, 2, 4, 1, false, 
app_status::AS_INVALID, ERR_OK},
-                 {APP_NAME + "_4", 4, 4, 2, 6, 1, false, 
app_status::AS_INVALID, ERR_OK},
-                 {APP_NAME + "_5", 4, 3, 2, 4, 1, false, 
app_status::AS_INVALID, ERR_OK},
-                 {APP_NAME + "_6", 4, 4, 2, 5, 1, false, 
app_status::AS_INVALID, ERR_OK},
-                 {APP_NAME, 4, 3, 2, 5, 4, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, 3, 2, 4, 5, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, 3, 2, 4, 4, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, 3, 2, 2, 4, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, 3, 2, 3, 4, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME, 4, 4, 2, 3, 4, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
-                 {APP_NAME + "_7", 4, 3, 2, 4, 3, false, 
app_status::AS_INVALID, ERR_OK},
-                 {APP_NAME, 4, 1, 1, 0, 1, false, app_status::AS_INVALID, 
ERR_STATE_FREEZED},
-                 {APP_NAME, 4, 2, 2, 1, 1, false, app_status::AS_INVALID, 
ERR_STATE_FREEZED},
-                 {APP_NAME, 4, 3, 3, 2, 1, false, app_status::AS_INVALID, 
ERR_STATE_FREEZED},
-                 {APP_NAME + "_8", 4, 3, 3, 3, 1, false, 
app_status::AS_INVALID, ERR_OK},
-                 {APP_NAME + "_9", 4, 1, 1, 1, 1, false, 
app_status::AS_INVALID, ERR_OK},
-                 {APP_NAME + "_10", 4, 2, 1, 2, 2, false, 
app_status::AS_INVALID, ERR_OK},
-                 {APP_NAME, 4, 3, 2, 3, 3, false, app_status::AS_INVALID, 
ERR_OK},
-                 {APP_NAME, 4, 3, 2, 3, 3, false, app_status::AS_INVALID, 
ERR_APP_EXIST},
-                 {APP_NAME, 4, 3, 2, 3, 3, false, app_status::AS_CREATING, 
ERR_BUSY_CREATING},
-                 {APP_NAME, 4, 3, 2, 3, 3, false, app_status::AS_RECALLING, 
ERR_BUSY_CREATING},
-                 {APP_NAME, 4, 3, 2, 3, 3, false, app_status::AS_DROPPING, 
ERR_BUSY_DROPPING},
-                 {APP_NAME, 4, 3, 2, 3, 3, false, app_status::AS_DROPPED, 
ERR_OK},
-                 {APP_NAME, 4, 3, 2, 3, 3, true, app_status::AS_INVALID, 
ERR_OK}};
+        std::map<std::string, std::string> envs = {};
+    } tests[] = {
+        {APP_NAME, -1, 3, 2, 3, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 0, 3, 2, 3, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, -1, 1, 3, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, 0, 1, 3, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, 6, 2, 4, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, 7, 2, 6, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, 6, 2, 5, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, 5, 2, 4, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, 4, 2, 3, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, 6, 2, 6, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, 6, 2, 7, 1, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME + "_1", 4, 5, 2, 5, 1, false, app_status::AS_INVALID, 
ERR_OK},
+        {APP_NAME + "_2", 4, 5, 2, 6, 1, false, app_status::AS_INVALID, 
ERR_OK},
+        {APP_NAME + "_3", 4, 4, 2, 4, 1, false, app_status::AS_INVALID, 
ERR_OK},
+        {APP_NAME + "_4", 4, 4, 2, 6, 1, false, app_status::AS_INVALID, 
ERR_OK},
+        {APP_NAME + "_5", 4, 3, 2, 4, 1, false, app_status::AS_INVALID, 
ERR_OK},
+        {APP_NAME + "_6", 4, 4, 2, 5, 1, false, app_status::AS_INVALID, 
ERR_OK},
+        {APP_NAME, 4, 3, 2, 5, 4, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, 3, 2, 4, 5, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, 3, 2, 4, 4, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, 3, 2, 2, 4, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, 3, 2, 3, 4, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME, 4, 4, 2, 3, 4, false, app_status::AS_INVALID, 
ERR_INVALID_PARAMETERS},
+        {APP_NAME + "_7", 4, 3, 2, 4, 3, false, app_status::AS_INVALID, 
ERR_OK},
+        {APP_NAME, 4, 1, 1, 0, 1, false, app_status::AS_INVALID, 
ERR_STATE_FREEZED},
+        {APP_NAME, 4, 2, 2, 1, 1, false, app_status::AS_INVALID, 
ERR_STATE_FREEZED},
+        {APP_NAME, 4, 3, 3, 2, 1, false, app_status::AS_INVALID, 
ERR_STATE_FREEZED},
+        {APP_NAME + "_8", 4, 3, 3, 3, 1, false, app_status::AS_INVALID, 
ERR_OK},
+        {APP_NAME + "_9", 4, 1, 1, 1, 1, false, app_status::AS_INVALID, 
ERR_OK},
+        {APP_NAME + "_10", 4, 2, 1, 2, 2, false, app_status::AS_INVALID, 
ERR_OK},
+        {APP_NAME, 4, 3, 2, 3, 3, false, app_status::AS_INVALID, ERR_OK},
+        {APP_NAME, 4, 3, 2, 3, 3, false, app_status::AS_INVALID, 
ERR_APP_EXIST},
+        {APP_NAME, 4, 3, 2, 3, 3, false, app_status::AS_CREATING, 
ERR_BUSY_CREATING},
+        {APP_NAME, 4, 3, 2, 3, 3, false, app_status::AS_RECALLING, 
ERR_BUSY_CREATING},
+        {APP_NAME, 4, 3, 2, 3, 3, false, app_status::AS_DROPPING, 
ERR_BUSY_DROPPING},
+        {APP_NAME, 4, 3, 2, 3, 3, false, app_status::AS_DROPPED, ERR_OK},
+        {APP_NAME, 4, 3, 2, 3, 3, true, app_status::AS_INVALID, ERR_OK},
+        {APP_NAME,
+         4,
+         3,
+         2,
+         3,
+         3,
+         false,
+         app_status::AS_INVALID,
+         ERR_INVALID_PARAMETERS,
+         {{"rocksdb.num_levels", "0"}}},
+        {APP_NAME,
+         4,
+         3,
+         2,
+         3,
+         3,
+         false,
+         app_status::AS_INVALID,
+         ERR_INVALID_PARAMETERS,
+         {{"rocksdb.num_levels", "11"}}},
+        {APP_NAME + "_11",
+         4,
+         3,
+         2,
+         3,
+         3,
+         false,
+         app_status::AS_INVALID,
+         ERR_OK,
+         {{"rocksdb.num_levels", "5"}}},
+        {APP_NAME,
+         4,
+         3,
+         2,
+         3,
+         3,
+         false,
+         app_status::AS_INVALID,
+         ERR_INVALID_PARAMETERS,
+         {{"rocksdb.write_buffer_size", "1000"}}},
+        {APP_NAME,
+         4,
+         3,
+         2,
+         3,
+         3,
+         false,
+         app_status::AS_INVALID,
+         ERR_INVALID_PARAMETERS,
+         {{"rocksdb.write_buffer_size", "1073741824"}}},
+        {APP_NAME + "_12",
+         4,
+         3,
+         2,
+         3,
+         3,
+         false,
+         app_status::AS_INVALID,
+         ERR_OK,
+         {{"rocksdb.write_buffer_size", "33554432"}}},
+    };

Review Comment:
   Could add test cases whose string-typed parameters are invalid numbers for  
`rocksdb.num_levels` and `rocksdb.write_buffer_size`, for example, some 
non-digital character in the string.



##########
src/server/test/pegasus_server_impl_test.cpp:
##########
@@ -95,6 +97,51 @@ class pegasus_server_impl_test : public 
pegasus_server_test_base
             ASSERT_EQ(before_count + test.expect_perf_counter_incr, 
after_count);
         }
     }
+
+    void test_open_db_with_rocksdb_envs(bool is_restart)
+    {
+        struct create_test
+        {
+            std::string env_key;
+            std::string env_value;
+            std::string expect_value;
+        } tests[] = {
+            {"rocksdb.num_levels", "5", "5"}, {"rocksdb.write_buffer_size", 
"33554432", "33554432"},
+        };
+
+        std::map<std::string, std::string> all_test_envs;
+        {
+            // Make sure all rocksdb options of ROCKSDB_DYNAMIC_OPTIONS and 
ROCKSDB_STATIC_OPTIONS
+            // are tested.
+            for (auto test : tests) {
+                all_test_envs[test.env_key] = test.env_value;
+            }
+            for (const auto &option : pegasus::ROCKSDB_DYNAMIC_OPTIONS) {
+                ASSERT_TRUE(all_test_envs.find(option) != all_test_envs.end());
+            }
+            for (const auto &option : pegasus::ROCKSDB_STATIC_OPTIONS) {
+                ASSERT_TRUE(all_test_envs.find(option) != all_test_envs.end());
+            }
+        }
+
+        start(all_test_envs);
+        if (is_restart) {
+            _server->stop(false);
+            start();
+        }
+
+        std::map<std::string, std::string> query_envs;
+        _server->query_app_envs(query_envs);
+        for (auto test : tests) {
+            auto iter = query_envs.find(test.env_key);
+            if (iter != query_envs.end()) {
+                ASSERT_EQ(iter->second, test.expect_value);
+            } else {
+                ASSERT_EQ(test.env_key,
+                          fmt::format("query_app_envs not supported {}", 
test.env_key));

Review Comment:
   Has "not supported" not been added as a test case 



##########
src/base/pegasus_const.cpp:
##########
@@ -101,4 +108,45 @@ const std::string 
USER_SPECIFIED_COMPACTION("user_specified_compaction");
 const std::string READ_SIZE_THROTTLING("replica.read_throttling_by_size");
 
 const std::string ROCKSDB_ALLOW_INGEST_BEHIND("rocksdb.allow_ingest_behind");
+
+const std::string ROCKSDB_WRITE_BUFFER_SIZE("rocksdb.write_buffer_size");
+
+const std::string ROCKSDB_NUM_LEVELS("rocksdb.num_levels");
+
+const std::set<std::string> ROCKSDB_DYNAMIC_OPTIONS = {
+    ROCKSDB_WRITE_BUFFER_SIZE,
+};
+const std::set<std::string> ROCKSDB_STATIC_OPTIONS = {
+    ROCKSDB_NUM_LEVELS,
+};
+
+const std::unordered_map<std::string, cf_opts_setter> cf_opts_setters = {
+    {ROCKSDB_WRITE_BUFFER_SIZE,
+     [](const std::string &str, rocksdb::ColumnFamilyOptions &option) -> bool {
+         uint64_t val = 0;
+         if (!dsn::buf2uint64(str, val))
+             return false;
+         option.write_buffer_size = static_cast<size_t>(val);
+         return true;
+     }},
+    {ROCKSDB_NUM_LEVELS,
+     [](const std::string &str, rocksdb::ColumnFamilyOptions &option) -> bool {
+         int32_t val = 0;
+         if (!dsn::buf2int32(str, val))
+             return false;

Review Comment:
   ```suggestion
            if (!dsn::buf2int32(str, val)) {
                return false;
            }
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to