Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

log: Use the coarse real time clock in log timestamps #18141

Merged
merged 6 commits into from Oct 9, 2017

Conversation

adamemerson
Copy link
Contributor

With an option to use the higher resolution clock if we want to.

This address a Trello Card or whatever.

@liewegas liewegas changed the title Use the coarse real time clock in log timestamps log: Use the coarse real time clock in log timestamps Oct 6, 2017
Copy link
Member

@liewegas liewegas left a comment

Choose a reason for hiding this comment

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

Yay! This looks good.

I don't suppose there's a way to annotate the time_point so that we know whether it's coarse or not? Then we could output only 3 decimal places of precision for coarse stamps and 6 for fine...

Copy link
Contributor

@tchaikov tchaikov left a comment

Choose a reason for hiding this comment

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

i failed to find a caller of _get_val<>().

@@ -162,6 +162,7 @@ struct md_config_t {
int _get_val(const std::string &key, char **buf, int len) const;
Option::value_t get_val_generic(const std::string &key) const;
template<typename T> T get_val(const std::string &key) const;
template<typename T> T _get_val(const std::string &key) const;
Copy link
Contributor

Choose a reason for hiding this comment

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

do we have a caller of this function now?

Copy link
Member

Choose a reason for hiding this comment

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

+    if (changed.find("log_coarse_timestamps") != changed.end()) {
 +      log->set_coarse_timestamps(conf->_get_val("log_coarse_timestamps"));
 +    }

template<typename T> T md_config_t::_get_val(const std::string &key) const {
Option::value_t generic_val = this->get_val_generic(key);
get_typed_value_visitor<T> gtv;
return boost::apply_visitor(gtv, generic_val);
Copy link
Contributor

@tchaikov tchaikov Oct 6, 2017

Choose a reason for hiding this comment

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

it's identical to

template<typename T> T md_config_t::get_val(const std::string &key) const

why shall we use it instead of md_config_t::get_val() ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for catching this. It was SUPPOSED to _get_val() instead of get_value_generic since _get_val desn't take a lock. I'll push an update in a moment.

Copy link
Contributor

@tchaikov tchaikov Oct 7, 2017

Choose a reason for hiding this comment

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

@adamemerson it's not changed. am i missing something?

scratch that.

Copy link
Contributor

@tchaikov tchaikov left a comment

Choose a reason for hiding this comment

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

no need to introduce _get_val().

We create a new time type to support using coarse timestamps (for
performance) by default while still allowing the user to switch to
fine timestamps.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
The tests should, really, get their time from the same source as the
log, and also probably use the same interface to creating entries that
other people do. So add an optional message argument and have the
tests use that rather than using the new operator directly.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
@adamemerson
Copy link
Contributor Author

@liewegas Times are marked as coarse or fine and print three or six digits depending.

When notified by a config observer, the config lock is already held,
create a _get_val template to manipulate newstyle options when
notified.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
And set up an observer in CephContext to coarsen/refine time stamps as
requested.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Have each timestamp know whether it's coarse or fine. Print six figures
for fine stamps and three for coarse.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
template<typename T> T md_config_t::_get_val(const std::string &key) const {
Option::value_t generic_val = this->_get_val(key);
get_typed_value_visitor<T> gtv;
return boost::apply_visitor(gtv, generic_val);
Copy link
Contributor

Choose a reason for hiding this comment

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

@jcsp @adamemerson why don't we just use boost::get<> ?

@tchaikov tchaikov merged commit 3b9564f into ceph:master Oct 9, 2017
@adamemerson adamemerson deleted the wip-log-time branch October 9, 2017 15:42
// An alternative might be to pass a std::unique_lock to
// handle_conf_change and have a version of get_var that can take it
// by reference and lock as appropriate.
Mutex::Locker l(lock);
Copy link
Contributor

Choose a reason for hiding this comment

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

I am late reviewing this, but this looks scary. Holding md_config_t::lock while calling into handle_conf_change of observers: then the observers can't use get_val (it takes the lock) to react to the changes!

The comment in config.h is referring to the old struct-based config, where holding the lock would be a good thing because it would render it safe to read that struct, rather than in the get_val world where holding the lock is a recipe for deadlocks

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did look through the rest of the file as a sanity check. It seems that we acquire the lock in apply_changes before calling _apply_changes which calls handle_conf_change.

So we had observers being called with the lock held in one path and without the lock held in the other path. I wouldn't be against swinging the change in the other direction and releasing the lock before calling the observers from _apply_changes if you think that would be safer.

Copy link
Member

Choose a reason for hiding this comment

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

We need the lock to cover the handle_conf_change methods until all of the strings are gone from legacy_config_opts.h. Since injectargs etc already hold the lock this change seems correct.

The larger/more annoying issue is that the get_val() calls in handle_conf_change. Maybe we can fix those just by marking the mutex recursive?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That was why I added the _get_val template. A recursive mutex would work, too, as would passing a unique_lock reference into handle_conf_change that can be passed to get_val which can just look to see whether to acquire it or not.

Copy link
Member

Choose a reason for hiding this comment

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

The unique_lock approach seems fragile: we'd have to update all current implementations that use get_val(), and going forward developers have to remember that all future calls to get_val() have to pass the unique_lock ref along to a get_val() variant that takes it. And if they don't they'll only notice if they test changing the config option online and deadlock the config update thread.

My vote is recursive mutex, with a plan to remove it if/when legacy_config_opts ever gets emptied out...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Huh. Looks like it already is recursive. I didn't realize that when I was worried about deadlock before. In that case all we really need to do is back out my _get_val change and just call get_val as normal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants