@@ -33,11 +33,18 @@ void OSDOperationRegistry::do_stop()
3333 /* add_ref= */ false
3434 };
3535 });
36+ last_of_recents = std::end (historic_registry);
3637 // to_ref_down is going off
3738}
3839
3940OSDOperationRegistry::OSDOperationRegistry ()
40- : OperationRegistryT(seastar::this_shard_id()) {}
41+ : OperationRegistryT(seastar::this_shard_id())
42+ {
43+ constexpr auto historic_reg_index =
44+ static_cast <size_t >(OperationTypeCode::historic_client_request);
45+ auto & historic_registry = get_registry<historic_reg_index>();
46+ last_of_recents = std::begin (historic_registry);
47+ }
4148
4249static auto get_duration (const ClientRequest& client_request)
4350{
@@ -48,46 +55,51 @@ static auto get_duration(const ClientRequest& client_request)
4855
4956void OSDOperationRegistry::put_historic (const ClientRequest& op)
5057{
51- using crimson::common::local_conf;
5258 // unlink the op from the client request registry. this is a part of
5359 // the re-link procedure. finally it will be in historic registry.
5460 constexpr auto client_reg_index =
5561 static_cast <size_t >(OperationTypeCode::client_request);
5662 constexpr auto historic_reg_index =
5763 static_cast <size_t >(OperationTypeCode::historic_client_request);
58- constexpr auto slow_historic_reg_index =
59- static_cast <size_t >(OperationTypeCode::historic_slow_client_request);
60-
6164 auto & client_registry = get_registry<client_reg_index>();
62- // slow ops should put into historic_slow_client_request list
63- // we only save the newest op
64- if (get_duration (op) > local_conf ()->osd_op_complaint_time ) {
65- auto & slow_historic_registry = get_registry<slow_historic_reg_index>();
66- slow_historic_registry.splice (std::end (slow_historic_registry),
67- client_registry,
68- client_registry.iterator_to (op));
69-
70- if (num_slow_ops >= local_conf ()->osd_op_history_slow_op_size ) {
71- slow_historic_registry.pop_front ();
72- } else {
73- ++num_slow_ops;
74- }
75- } else {
76- auto & historic_registry = get_registry<historic_reg_index>();
77- historic_registry.splice (std::end (historic_registry),
78- client_registry,
79- client_registry.iterator_to (op));
80-
81- if (num_recent_ops >= local_conf ()->osd_op_history_size ) {
82- historic_registry.pop_front ();
83- } else {
84- ++num_recent_ops;
85- }
86- }
87-
65+ auto & historic_registry = get_registry<historic_reg_index>();
66+ historic_registry.splice (std::end (historic_registry),
67+ client_registry,
68+ client_registry.iterator_to (op));
8869 ClientRequest::ICRef (
8970 &op, /* add_ref= */ true
9071 ).detach (); // yes, "leak" it for now!
72+
73+ // check whether the history size limit is not exceeded; if so, then
74+ // purge the oldest op.
75+ // NOTE: Operation uses the auto-unlink feature of boost::intrusive.
76+ // NOTE: the cleaning happens in OSDOperationRegistry::do_stop()
77+ using crimson::common::local_conf;
78+ if (num_recent_ops >= local_conf ()->osd_op_history_size ) {
79+ ++last_of_recents;
80+ ++num_slow_ops;
81+ } else {
82+ ++num_recent_ops;
83+ }
84+ if (num_slow_ops > local_conf ()->osd_op_history_slow_op_size ) {
85+ // we're interested in keeping slowest ops. if the slow op history
86+ // is disabled, the list will have only one element, so the full-blown
87+ // search will boil down into `.front()`.
88+ const auto fastest_historic_iter = std::min_element (
89+ std::cbegin (historic_registry), last_of_recents,
90+ [] (const auto & lop, const auto & rop) {
91+ const auto & lclient_request = static_cast <const ClientRequest&>(lop);
92+ const auto & rclient_request = static_cast <const ClientRequest&>(rop);
93+ return get_duration (lclient_request) < get_duration (rclient_request);
94+ });
95+ assert (fastest_historic_iter != std::end (historic_registry));
96+ const auto & fastest_historic_op =
97+ static_cast <const ClientRequest&>(*fastest_historic_iter);
98+ historic_registry.erase (fastest_historic_iter);
99+ // clear a previously "leaked" op
100+ ClientRequest::ICRef (&fastest_historic_op, /* add_ref= */ false );
101+ --num_slow_ops;
102+ }
91103}
92104
93105size_t OSDOperationRegistry::dump_historic_client_requests (ceph::Formatter* f) const
@@ -113,20 +125,33 @@ size_t OSDOperationRegistry::dump_historic_client_requests(ceph::Formatter* f) c
113125
114126size_t OSDOperationRegistry::dump_slowest_historic_client_requests (ceph::Formatter* f) const
115127{
116- const auto & slow_historic_client_registry =
117- get_registry<static_cast <size_t >(OperationTypeCode::historic_slow_client_request )>(); // ClientRequest::type)>();
128+ const auto & historic_client_registry =
129+ get_registry<static_cast <size_t >(OperationTypeCode::historic_client_request )>(); // ClientRequest::type)>();
118130 f->open_object_section (" op_history" );
119- f->dump_int (" size" , slow_historic_client_registry .size ());
131+ f->dump_int (" size" , historic_client_registry .size ());
120132 // TODO: f->dump_int("duration", history_duration.load());
121133 // the intrusive list is configured to not store the size
134+ std::multimap<utime_t ,
135+ const ClientRequest*,
136+ std::greater<utime_t >> sorted_slowest_ops;
137+ // iterating over the entire registry as a slow op could be also
138+ // in the "recently added" part.
139+ std::transform (std::begin (historic_client_registry),
140+ std::end (historic_client_registry),
141+ std::inserter (sorted_slowest_ops, std::end (sorted_slowest_ops)),
142+ [] (const Operation& op) {
143+ const auto & cop = static_cast <const ClientRequest&>(op);
144+ return std::make_pair (get_duration (cop), &cop);
145+ });
146+ f->open_array_section (" ops" );
147+ using crimson::common::local_conf;
122148 size_t ops_count = 0 ;
149+ for (auto it = std::begin (sorted_slowest_ops);
150+ ops_count < local_conf ()->osd_op_history_slow_op_size
151+ && it != std::end (sorted_slowest_ops);
152+ ++it, ++ops_count)
123153 {
124- f->open_array_section (" ops" );
125- for (const auto & op : slow_historic_client_registry) {
126- op.dump (f);
127- ++ops_count;
128- }
129- f->close_section ();
154+ it->second ->dump (f);
130155 }
131156 f->close_section ();
132157 return ops_count;
0 commit comments