ClickHouse/dbms/src/Common/ThreadStatus.cpp

124 lines
3.2 KiB
C++
Raw Normal View History

2018-08-22 00:24:55 +00:00
#include <sstream>
#include <common/Types.h>
2018-05-29 18:14:31 +00:00
#include <Common/CurrentThread.h>
#include <Common/Exception.h>
#include <Common/ThreadProfileEvents.h>
2018-08-22 00:24:55 +00:00
#include <Common/TaskStatsInfoGetter.h>
#include <Common/ThreadStatus.h>
2018-08-22 00:24:55 +00:00
#include <Poco/Logger.h>
#include <Poco/Ext/ThreadNumber.h>
namespace DB
{
2018-05-29 18:14:31 +00:00
namespace ErrorCodes
{
extern const int LOGICAL_ERROR;
extern const int PTHREAD_ERROR;
}
2018-05-29 18:14:31 +00:00
/// Order of current_thread and current_thread_scope matters
thread_local ThreadStatusPtr current_thread = ThreadStatus::create();
thread_local ThreadStatus::CurrentThreadScope current_thread_scope;
2018-05-29 18:14:31 +00:00
TasksStatsCounters TasksStatsCounters::current()
{
2018-05-29 18:14:31 +00:00
TasksStatsCounters res;
current_thread->taskstats_getter->getStat(res.stat, current_thread->os_thread_id);
2018-05-29 18:14:31 +00:00
return res;
}
ThreadStatus::ThreadStatus()
{
thread_number = Poco::ThreadNumber::get();
os_thread_id = TaskStatsInfoGetter::getCurrentTID();
last_rusage = std::make_unique<RUsageCounters>();
last_taskstats = std::make_unique<TasksStatsCounters>();
memory_tracker.setDescription("(for thread)");
log = &Poco::Logger::get("ThreadStatus");
/// NOTE: It is important not to do any non-trivial actions (like updating ProfileEvents or logging) before ThreadStatus is created
/// Otherwise it could lead to SIGSEGV due to current_thread dereferencing
2018-05-29 18:14:31 +00:00
}
2018-05-29 18:14:31 +00:00
ThreadStatusPtr ThreadStatus::create()
{
return ThreadStatusPtr(new ThreadStatus);
}
ThreadStatus::~ThreadStatus() = default;
void ThreadStatus::initPerformanceCounters()
{
performance_counters_finalized = false;
/// Clear stats from previous query if a new query is started
/// TODO: make separate query_thread_performance_counters and thread_performance_counters
performance_counters.resetCounters();
memory_tracker.resetCounters();
memory_tracker.setDescription("(for thread)");
query_start_time_nanoseconds = getCurrentTimeNanoseconds();
query_start_time = time(nullptr);
++queries_started;
*last_rusage = RUsageCounters::current(query_start_time_nanoseconds);
2018-08-22 00:41:30 +00:00
if (TaskStatsInfoGetter::checkPermissions())
{
taskstats_getter = std::make_unique<TaskStatsInfoGetter>();
*last_taskstats = TasksStatsCounters::current();
2018-08-22 00:41:30 +00:00
}
}
void ThreadStatus::updatePerformanceCounters()
{
try
{
RUsageCounters::updateProfileEvents(*last_rusage, performance_counters);
2018-08-22 00:41:30 +00:00
if (taskstats_getter)
TasksStatsCounters::updateProfileEvents(*last_taskstats, performance_counters);
}
catch (...)
{
tryLogCurrentException(log);
}
}
void ThreadStatus::assertState(const std::initializer_list<int> & permitted_states, const char * description)
{
for (auto permitted_state : permitted_states)
{
if (getCurrentState() == permitted_state)
return;
}
std::stringstream ss;
ss << "Unexpected thread state " << getCurrentState();
if (description)
ss << ": " << description;
throw Exception(ss.str(), ErrorCodes::LOGICAL_ERROR);
}
void ThreadStatus::attachInternalTextLogsQueue(const InternalTextLogsQueuePtr & logs_queue)
{
logs_queue_ptr = logs_queue;
if (!thread_group)
return;
std::unique_lock lock(thread_group->mutex);
thread_group->logs_queue_ptr = logs_queue;
}
}