Skip to content
This repository has been archived by the owner on Jun 23, 2022. It is now read-only.

refactor(util): use flags to define configurations #275

Merged
merged 13 commits into from
Apr 29, 2020

Conversation

neverchanje
Copy link
Contributor

@neverchanje neverchanje commented Jul 21, 2019

Introduction

flags.h defines a series of utilities that provide gflags-style config definition. The main difference is that gflags uses command-line flags, our implementation reads "config.ini" for flags.

Let's see an example of the new flag API:

for each of the replicas,

pegasus_server_impl::pegasus_server_impl() {
   _db_opts.max_background_compactions =
        (int)dsn_config_get_value_int64("pegasus.server",
                                        "rocksdb_max_background_compactions",
                                        12,
                                        "rocksdb options.max_background_compactions");
}

the current implementation has to specify the config section, description, default value, and read the config value, though all replicas use the same config value. After this PR, the implementation can be simplified to:

DSN_DEFINE_int64("pegasus.server",
                 rocksdb_max_background_compactions,
                 12,
                 "rocksdb options.max_background_compactions");

pegasus_server_impl::pegasus_server_impl() {
   _db_opts.max_background_compactions = FLAGS_rocksdb_max_background_compactions;
}

Compared to the original configuration API, which reads configuration item every time it is used (though config file is pre-loaded, reading the item still costs one ex-lock operation), flags.h inits all configurations at the start time, freeing our developer in some way.

From the framework's perspective, all the flags are inited at dsn_run(), after the configurations are loaded. Of course, you cannot use the flag before dsn::flags_initialize().

    if (!dsn_config_load(config_file, config_arguments)) {
        printf("Fail to load config file %s\n", config_file);
        return false;
    }
    dsn::flags_initialize();

Side effects

This PR doesn't change any behavior related to configurations. It only introduces a new utility.

Manual Tests

1. Tests flag validation works

DSN_DEFINE_validator(stderr_start_level, [](const char *level) -> bool {
    return strcmp(level, "LOG_LEVEL_INVALID") != 0;
});

Use config stderr_start_level == LOG_LEVEL_INVALID, the validation failed and generated a coredump.

[tools.simple_logger]
 stderr_start_level = LOG_LEVEL_INVALID

Outputs:

simple_logger.cpp:53:operator()():assertion expression: FLAGS_VALIDATOR_FN_stderr_start_level(FLAGS_stderr_start_level)
simple_logger.cpp:53:operator()():validation failed: stderr_start_level
[1]    27047 abort (core dumped)  GTEST_FILTER=core.dlog_f ./dsn.core.tests config-test.ini

2. Tests correct flag value is loaded

Set config short_header = true. Output:

W2020-01-30 21:11:32.891 (1580389892891799962 6ac9) client.io-thrd.27337: You may need priviledge to set thread priority. errno = 1

Set config short_header = false. Apparently, short_header is well loaded. The logger prints function's name ahead of the message:

W2020-01-30 21:12:04.018 (1580389924018533331 6bcf) client.io-thrd.27599: task_worker.cpp:120:set_priority(): You may need priviledge to set thread priority. errno = 1

@foreverneverer

This comment has been minimized.

@neverchanje neverchanje changed the title utils: use flags to define configuration item refactor(util): use flags to define configuration item Jan 29, 2020
@neverchanje neverchanje changed the title refactor(util): use flags to define configuration item refactor(util): use flags to define configurations Jan 29, 2020
neverchanje added 2 commits January 30, 2020 20:46
@neverchanje neverchanje changed the title refactor(util): use flags to define configurations refactor(util): use flags to define configurations [WIP] Feb 19, 2020
@neverchanje neverchanje changed the title refactor(util): use flags to define configurations [WIP] refactor(util): use flags to define configurations Apr 13, 2020
DSN_DEFINE_bool("tools.simple_logger", fast_flush, false, "whether to flush immediately");

DSN_DEFINE_bool("tools.simple_logger",
short_header,
Copy link
Contributor

@foreverneverer foreverneverer Apr 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the value of one config format isn't right, for example, size = 1MB and size=1024, what happen?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behavior is exactly the same as dsn_config_get_value_int64 like formerly it does.

class flag_registry : public utils::singleton<flag_registry>
{
public:
flag_registry() {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to move it to private for singleton.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

singleton requires constructor to be public, or the compilation wil fail.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make ::utils::singleton<flag_registry> to be friend class of flag_registry may help.

Wu Tao and others added 2 commits April 27, 2020 23:45
@acelyc111
Copy link
Member

After this patch, we can provide a way to modify configs at runtime (just in-memory configs, not configs in file)

};

#define FLAG_REG_CONSTRUCTOR(type, type_enum) \
flag_registerer::flag_registerer( \
Copy link
Contributor

@levy5307 levy5307 Apr 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the name is flag_registerer, but not flag_register?

Copy link
Contributor Author

@neverchanje neverchanje Apr 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These class names are learned from gflags. If users are familiar with gflags, he will soon get started to use dsn flags.

See this: https://github.com/gflags/gflags/blob/master/src/gflags.h.in#L432.

"registerer" plays the role to register the flag, where "register" is a verb, not a noun.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants