Skip to content

Commit d61600f

Browse files
committed
[WIP] CheckerComponent#Stop(): wait for own Checkable#ProcessCheckResult() to finish
1 parent 3f0430a commit d61600f

File tree

4 files changed

+89
-2
lines changed

4 files changed

+89
-2
lines changed

lib/checker/checkercomponent.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ void CheckerComponent::OnConfigLoaded()
6060
void CheckerComponent::Start(bool runtimeCreated)
6161
{
6262
ObjectImpl<CheckerComponent>::Start(runtimeCreated);
63+
CheckResultProducerComponent::Start();
6364

6465
Log(LogInformation, "CheckerComponent")
6566
<< "'" << GetName() << "' started.";
@@ -81,6 +82,7 @@ void CheckerComponent::Stop(bool runtimeRemoved)
8182
m_CV.notify_all();
8283
}
8384

85+
CheckResultProducerComponent::Stop();
8486
m_ResultTimer->Stop(true);
8587
m_Thread.join();
8688

@@ -232,7 +234,7 @@ void CheckerComponent::ExecuteCheckHelper(const Checkable::Ptr& checkable)
232234
try {
233235
checkable->ExecuteCheck();
234236
} catch (const std::exception& ex) {
235-
CheckResult::Ptr cr = new CheckResult();
237+
CheckResult::Ptr cr = new CheckResult(this);
236238
cr->SetState(ServiceUnknown);
237239

238240
String output = "Exception occurred while checking '" + checkable->GetName() + "': " + DiagnosticInformation(ex);

lib/checker/checkercomponent.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ struct CheckableNextCheckExtractor
4646
/**
4747
* @ingroup checker
4848
*/
49-
class CheckerComponent final : public ObjectImpl<CheckerComponent>
49+
class CheckerComponent final : public ObjectImpl<CheckerComponent>, public CheckResultProducerComponent
5050
{
5151
public:
5252
DECLARE_OBJECT(CheckerComponent);

lib/icinga/checkresult.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,51 @@ double CheckResult::CalculateLatency() const
3333
return latency;
3434
}
3535

36+
bool CheckResultProducerComponent::try_lock_shared() noexcept
37+
{
38+
auto expected (m_State.load());
39+
decltype(expected) desired;
40+
41+
do {
42+
if (!expected.m_InstanceIsActive) {
43+
return false;
44+
}
45+
46+
desired = expected;
47+
++desired.m_ProcessingCheckResults;
48+
} while (!m_State.compare_exchange_weak(expected, desired));
49+
50+
return true;
51+
}
52+
53+
void CheckResultProducerComponent::unlock_shared() noexcept
54+
{
55+
auto state (ModifyState([](auto& desired) { --desired.m_ProcessingCheckResults; }));
56+
57+
if (!state.m_ProcessingCheckResults) {
58+
m_CV.notify_all();
59+
}
60+
}
61+
62+
/**
63+
* Allow processing check results.
64+
*/
65+
void CheckResultProducerComponent::Start()
66+
{
67+
ModifyState([](auto& desired) { desired.m_InstanceIsActive = 1; });
68+
}
69+
70+
/**
71+
* Disallow processing new check results, wait for all currently processed ones to finish.
72+
*/
73+
void CheckResultProducerComponent::Stop()
74+
{
75+
ModifyState([](auto& desired) { desired.m_InstanceIsActive = 0; });
76+
77+
std::unique_lock lock (m_Mutex);
78+
m_CV.wait(lock, [this] { return !m_State.load().m_ProcessingCheckResults; });
79+
}
80+
3681
ObjectFactory TypeHelper<CheckResult, false>::GetFactory()
3782
{
3883
return &Factory;

lib/icinga/checkresult.hpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
#ifndef CHECKRESULT_H
44
#define CHECKRESULT_H
55

6+
#include "base/atomic.hpp"
67
#include "icinga/i2-icinga.hpp"
78
#include "icinga/checkresult-ti.hpp"
9+
#include <condition_variable>
10+
#include <cstdint>
11+
#include <mutex>
812
#include <utility>
913

1014
namespace icinga
@@ -60,6 +64,42 @@ class CheckResult final : public ObjectImpl<CheckResult>
6064
CheckResultProducer::Ptr m_Producer;
6165
};
6266

67+
class CheckResultProducerComponent : public CheckResultProducer
68+
{
69+
public:
70+
bool try_lock_shared() noexcept override;
71+
void unlock_shared() noexcept override;
72+
73+
protected:
74+
void Start();
75+
void Stop();
76+
77+
private:
78+
struct State
79+
{
80+
uint32_t m_InstanceIsActive = 0;
81+
uint32_t m_ProcessingCheckResults = 0;
82+
};
83+
84+
Atomic<State> m_State {State{}};
85+
std::mutex m_Mutex;
86+
std::condition_variable m_CV;
87+
88+
template<class F>
89+
State ModifyState(const F& func)
90+
{
91+
auto expected (m_State.load());
92+
decltype(expected) desired;
93+
94+
do {
95+
desired = expected;
96+
func(desired);
97+
} while (!m_State.compare_exchange_weak(expected, desired));
98+
99+
return desired;
100+
}
101+
};
102+
63103
template<>
64104
struct TypeHelper<CheckResult, false>
65105
{

0 commit comments

Comments
 (0)