Skip to content

Commit 4c38857

Browse files
committed
Merge PR ceph#60174 into main
* refs/pull/60174/head: common/Finisher: pass name as std::string_view to ctor common/Finisher: add method get_thread_name() mgr/ActivePyModule: build thread name with fmt mgr/ActivePyModule: return std::string_view instead of std::string copy common/Finisher: use fmt to build strings common/Finisher: un-inline ctor and dtor common/Finisher: add `const` to several fields common/Finisher: merge duplicate field initializers common/Finisher: call notify_one() instead of notify_all() common/Finisher: wake up after pushing to the queue common/Finisher: do not wake up the thread if already running common/Finisher: call logger without holding the lock common/Finisher: use `std::lock_guard` instead of `std::unique_lock` common/Finisher: merge all queue() container methods into one template Reviewed-by: Patrick Donnelly <[email protected]>
2 parents 35c0078 + efc96a2 commit 4c38857

File tree

4 files changed

+70
-84
lines changed

4 files changed

+70
-84
lines changed

src/common/Finisher.cc

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,40 @@
22
// vim: ts=8 sw=2 smarttab
33

44
#include "Finisher.h"
5+
#include "common/perf_counters.h"
6+
7+
#include <fmt/core.h>
58

69
#define dout_subsys ceph_subsys_finisher
710
#undef dout_prefix
811
#define dout_prefix *_dout << "finisher(" << this << ") "
912

13+
Finisher::Finisher(CephContext *cct_) :
14+
cct(cct_), finisher_lock(ceph::make_mutex("Finisher::finisher_lock")),
15+
thread_name("fn_anonymous"),
16+
finisher_thread(this) {}
17+
18+
Finisher::Finisher(CephContext *cct_, std::string_view name, std::string &&tn) :
19+
cct(cct_), finisher_lock(ceph::make_mutex(fmt::format("Finisher::{}", name))),
20+
thread_name(std::move(tn)),
21+
finisher_thread(this) {
22+
PerfCountersBuilder b(cct, fmt::format("finisher-{}", name),
23+
l_finisher_first, l_finisher_last);
24+
b.add_u64(l_finisher_queue_len, "queue_len");
25+
b.add_time_avg(l_finisher_complete_lat, "complete_latency");
26+
logger = b.create_perf_counters();
27+
cct->get_perfcounters_collection()->add(logger);
28+
logger->set(l_finisher_queue_len, 0);
29+
logger->set(l_finisher_complete_lat, 0);
30+
}
31+
32+
Finisher::~Finisher() {
33+
if (logger && cct) {
34+
cct->get_perfcounters_collection()->remove(logger);
35+
delete logger;
36+
}
37+
}
38+
1039
void Finisher::start()
1140
{
1241
ldout(cct, 10) << __func__ << dendl;
@@ -20,7 +49,7 @@ void Finisher::stop()
2049
finisher_stop = true;
2150
// we don't have any new work to do, but we want the worker to wake up anyway
2251
// to process the stop condition.
23-
finisher_cond.notify_all();
52+
finisher_cond.notify_one();
2453
finisher_lock.unlock();
2554
finisher_thread.join(); // wait until the worker exits completely
2655
ldout(cct, 10) << __func__ << " finish" << dendl;
@@ -40,7 +69,7 @@ void Finisher::wait_for_empty()
4069

4170
bool Finisher::is_empty()
4271
{
43-
std::unique_lock ul(finisher_lock);
72+
const std::lock_guard l{finisher_lock};
4473
return finisher_queue.empty();
4574
}
4675

src/common/Finisher.h

Lines changed: 31 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,8 @@
1919
#include "include/common_fwd.h"
2020
#include "common/Thread.h"
2121
#include "common/ceph_mutex.h"
22-
#include "common/perf_counters.h"
2322
#include "common/Cond.h"
2423

25-
2624
/// Finisher queue length performance counter ID.
2725
enum {
2826
l_finisher_first = 997082,
@@ -37,23 +35,23 @@ enum {
3735
* contexts to complete is thread-safe.
3836
*/
3937
class Finisher {
40-
CephContext *cct;
38+
CephContext *const cct;
4139
ceph::mutex finisher_lock; ///< Protects access to queues and finisher_running.
4240
ceph::condition_variable finisher_cond; ///< Signaled when there is something to process.
4341
ceph::condition_variable finisher_empty_cond; ///< Signaled when the finisher has nothing more to process.
44-
bool finisher_stop; ///< Set when the finisher should stop.
45-
bool finisher_running; ///< True when the finisher is currently executing contexts.
46-
bool finisher_empty_wait; ///< True mean someone wait finisher empty.
42+
bool finisher_stop = false; ///< Set when the finisher should stop.
43+
bool finisher_running = false; ///< True when the finisher is currently executing contexts.
44+
bool finisher_empty_wait = false; ///< True mean someone wait finisher empty.
4745

4846
/// Queue for contexts for which complete(0) will be called.
4947
std::vector<std::pair<Context*,int>> finisher_queue;
5048
std::vector<std::pair<Context*,int>> in_progress_queue;
5149

52-
std::string thread_name;
50+
const std::string thread_name;
5351

5452
/// Performance counter for the finisher's queue length.
5553
/// Only active for named finishers.
56-
PerfCounters *logger;
54+
PerfCounters *logger = nullptr;
5755

5856
void *finisher_thread_entry();
5957

@@ -66,56 +64,34 @@ class Finisher {
6664
public:
6765
/// Add a context to complete, optionally specifying a parameter for the complete function.
6866
void queue(Context *c, int r = 0) {
69-
std::unique_lock ul(finisher_lock);
70-
bool was_empty = finisher_queue.empty();
71-
finisher_queue.push_back(std::make_pair(c, r));
72-
if (was_empty) {
73-
finisher_cond.notify_one();
67+
{
68+
const std::lock_guard l{finisher_lock};
69+
const bool should_notify = finisher_queue.empty() && !finisher_running;
70+
finisher_queue.push_back(std::make_pair(c, r));
71+
if (should_notify) {
72+
finisher_cond.notify_one();
73+
}
7474
}
75+
7576
if (logger)
7677
logger->inc(l_finisher_queue_len);
7778
}
7879

79-
void queue(std::list<Context*>& ls) {
80+
// TODO use C++20 concept checks instead of SFINAE
81+
template<typename T>
82+
auto queue(T &ls) -> decltype(std::distance(ls.begin(), ls.end()), void()) {
8083
{
81-
std::unique_lock ul(finisher_lock);
82-
if (finisher_queue.empty()) {
83-
finisher_cond.notify_all();
84-
}
85-
for (auto i : ls) {
86-
finisher_queue.push_back(std::make_pair(i, 0));
87-
}
88-
if (logger)
89-
logger->inc(l_finisher_queue_len, ls.size());
90-
}
91-
ls.clear();
92-
}
93-
void queue(std::deque<Context*>& ls) {
94-
{
95-
std::unique_lock ul(finisher_lock);
96-
if (finisher_queue.empty()) {
97-
finisher_cond.notify_all();
98-
}
99-
for (auto i : ls) {
84+
const std::lock_guard l{finisher_lock};
85+
const bool should_notify = finisher_queue.empty() && !finisher_running;
86+
for (Context *i : ls) {
10087
finisher_queue.push_back(std::make_pair(i, 0));
10188
}
102-
if (logger)
103-
logger->inc(l_finisher_queue_len, ls.size());
104-
}
105-
ls.clear();
106-
}
107-
void queue(std::vector<Context*>& ls) {
108-
{
109-
std::unique_lock ul(finisher_lock);
110-
if (finisher_queue.empty()) {
111-
finisher_cond.notify_all();
89+
if (should_notify) {
90+
finisher_cond.notify_one();
11291
}
113-
for (auto i : ls) {
114-
finisher_queue.push_back(std::make_pair(i, 0));
115-
}
116-
if (logger)
117-
logger->inc(l_finisher_queue_len, ls.size());
11892
}
93+
if (logger)
94+
logger->inc(l_finisher_queue_len, ls.size());
11995
ls.clear();
12096
}
12197

@@ -137,36 +113,17 @@ class Finisher {
137113

138114
bool is_empty();
139115

116+
std::string_view get_thread_name() const noexcept {
117+
return thread_name;
118+
}
119+
140120
/// Construct an anonymous Finisher.
141121
/// Anonymous finishers do not log their queue length.
142-
explicit Finisher(CephContext *cct_) :
143-
cct(cct_), finisher_lock(ceph::make_mutex("Finisher::finisher_lock")),
144-
finisher_stop(false), finisher_running(false), finisher_empty_wait(false),
145-
thread_name("fn_anonymous"), logger(0),
146-
finisher_thread(this) {}
122+
explicit Finisher(CephContext *cct_);
147123

148124
/// Construct a named Finisher that logs its queue length.
149-
Finisher(CephContext *cct_, std::string name, std::string tn) :
150-
cct(cct_), finisher_lock(ceph::make_mutex("Finisher::" + name)),
151-
finisher_stop(false), finisher_running(false), finisher_empty_wait(false),
152-
thread_name(tn), logger(0),
153-
finisher_thread(this) {
154-
PerfCountersBuilder b(cct, std::string("finisher-") + name,
155-
l_finisher_first, l_finisher_last);
156-
b.add_u64(l_finisher_queue_len, "queue_len");
157-
b.add_time_avg(l_finisher_complete_lat, "complete_latency");
158-
logger = b.create_perf_counters();
159-
cct->get_perfcounters_collection()->add(logger);
160-
logger->set(l_finisher_queue_len, 0);
161-
logger->set(l_finisher_complete_lat, 0);
162-
}
163-
164-
~Finisher() {
165-
if (logger && cct) {
166-
cct->get_perfcounters_collection()->remove(logger);
167-
delete logger;
168-
}
169-
}
125+
Finisher(CephContext *cct_, std::string_view name, std::string &&tn);
126+
~Finisher();
170127
};
171128

172129
/// Context that is completed asynchronously on the supplied finisher.

src/mgr/ActivePyModule.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include "PyModuleRunner.h"
2828
#include "PyModule.h"
2929

30+
#include <fmt/core.h>
31+
3032
#include <vector>
3133
#include <string>
3234

@@ -46,16 +48,14 @@ class ActivePyModule : public PyModuleRunner
4648

4749
std::string m_command_perms;
4850
const MgrSession* m_session = nullptr;
49-
std::string fin_thread_name;
5051
public:
5152
Finisher finisher; // per active module finisher to execute commands
5253

5354
public:
5455
ActivePyModule(const PyModuleRef &py_module_,
5556
LogChannelRef clog_)
5657
: PyModuleRunner(py_module_, clog_),
57-
fin_thread_name(std::string("m-fin-" + py_module->get_name()).substr(0,15)),
58-
finisher(g_ceph_context, thread_name, fin_thread_name)
58+
finisher(g_ceph_context, thread_name, fmt::format("m-fin-{}", py_module->get_name()).substr(0,15))
5959

6060
{
6161
}
@@ -97,14 +97,14 @@ class ActivePyModule : public PyModuleRunner
9797
uri = str;
9898
}
9999

100-
std::string get_uri() const
100+
std::string_view get_uri() const
101101
{
102102
return uri;
103103
}
104104

105-
std::string get_fin_thread_name() const
105+
std::string_view get_fin_thread_name() const
106106
{
107-
return fin_thread_name;
107+
return finisher.get_thread_name();
108108
}
109109

110110
bool is_authorized(const std::map<std::string, std::string>& arguments) const;

src/mgr/ActivePyModules.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -770,9 +770,9 @@ std::map<std::string, std::string> ActivePyModules::get_services() const
770770
std::map<std::string, std::string> result;
771771
std::lock_guard l(lock);
772772
for (const auto& [name, module] : modules) {
773-
std::string svc_str = module->get_uri();
773+
const std::string_view svc_str = module->get_uri();
774774
if (!svc_str.empty()) {
775-
result[name] = svc_str;
775+
result.emplace(name, svc_str);
776776
}
777777
}
778778

0 commit comments

Comments
 (0)