2018-02-01 17:55:08 +00:00
|
|
|
#include "ThreadStatus.h"
|
|
|
|
#include <common/logger_useful.h>
|
2018-05-17 16:01:41 +00:00
|
|
|
#include <Common/TaskStatsInfoGetter.h>
|
2018-05-29 18:14:31 +00:00
|
|
|
#include <Common/CurrentThread.h>
|
2018-05-31 15:54:08 +00:00
|
|
|
#include <Interpreters/Context.h>
|
|
|
|
#include <Interpreters/QueryThreadLog.h>
|
|
|
|
#include <Interpreters/ProcessList.h>
|
2018-05-17 16:01:41 +00:00
|
|
|
|
2018-06-06 20:57:07 +00:00
|
|
|
#include <Poco/Thread.h>
|
|
|
|
#include <Poco/Ext/ThreadNumber.h>
|
2018-02-01 17:55:08 +00:00
|
|
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/resource.h>
|
2018-03-01 16:52:24 +00:00
|
|
|
#include <pthread.h>
|
2018-05-17 16:01:41 +00:00
|
|
|
#include <linux/taskstats.h>
|
2018-02-01 17:55:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace ProfileEvents
|
|
|
|
{
|
|
|
|
extern const Event RealTimeMicroseconds;
|
2018-05-31 15:54:08 +00:00
|
|
|
extern const Event UserTimeMicroseconds;
|
|
|
|
extern const Event SystemTimeMicroseconds;
|
|
|
|
extern const Event SoftPageFaults;
|
|
|
|
extern const Event HardPageFaults;
|
|
|
|
extern const Event VoluntaryContextSwitches;
|
|
|
|
extern const Event InvoluntaryContextSwitches;
|
|
|
|
|
|
|
|
extern const Event OSIOWaitMicroseconds;
|
2018-05-17 16:01:41 +00:00
|
|
|
extern const Event OSReadBytes;
|
|
|
|
extern const Event OSWriteBytes;
|
|
|
|
extern const Event OSReadChars;
|
|
|
|
extern const Event OSWriteChars;
|
2018-02-01 17:55:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2018-05-29 18:14:31 +00:00
|
|
|
|
2018-02-01 17:55:08 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int LOGICAL_ERROR;
|
2018-03-01 16:52:24 +00:00
|
|
|
extern const int PTHREAD_ERROR;
|
2018-02-01 17:55:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
/// Implicitly finalizes current thread in the destructor
|
|
|
|
class ThreadStatus::CurrentThreadScope
|
2018-05-29 18:14:31 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2018-06-06 20:57:07 +00:00
|
|
|
CurrentThreadScope() = default;
|
2018-05-29 18:14:31 +00:00
|
|
|
|
|
|
|
~CurrentThreadScope()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2018-06-04 14:16:27 +00:00
|
|
|
ThreadStatus & thread = *CurrentThread::get();
|
|
|
|
|
2018-06-06 20:57:07 +00:00
|
|
|
LOG_DEBUG(thread.log, "Thread " << thread.thread_number << " exited");
|
2018-06-13 19:01:07 +00:00
|
|
|
thread.detachQuery(true, true);
|
2018-05-29 18:14:31 +00:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
std::terminate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
thread_local ThreadStatusPtr current_thread = ThreadStatus::create();
|
|
|
|
|
|
|
|
/// Order of current_thread and current_thread_scope matters
|
2018-05-31 15:54:08 +00:00
|
|
|
static thread_local ThreadStatus::CurrentThreadScope current_thread_scope;
|
2018-05-29 18:14:31 +00:00
|
|
|
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
/// Handles overflow
|
|
|
|
template <typename TUInt>
|
|
|
|
inline TUInt safeDiff(TUInt prev, TUInt curr)
|
|
|
|
{
|
|
|
|
return curr >= prev ? curr - prev : 0;
|
|
|
|
}
|
|
|
|
|
2018-05-29 18:14:31 +00:00
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
static UInt64 getCurrentTimeNanoseconds(clockid_t clock_type = CLOCK_MONOTONIC)
|
2018-02-01 17:55:08 +00:00
|
|
|
{
|
|
|
|
struct timespec ts;
|
|
|
|
clock_gettime(clock_type, &ts);
|
2018-06-01 15:32:27 +00:00
|
|
|
return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
|
2018-02-01 17:55:08 +00:00
|
|
|
}
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
|
2018-02-01 17:55:08 +00:00
|
|
|
struct RusageCounters
|
|
|
|
{
|
2018-05-31 15:54:08 +00:00
|
|
|
/// In nanoseconds
|
2018-02-01 17:55:08 +00:00
|
|
|
UInt64 real_time = 0;
|
|
|
|
UInt64 user_time = 0;
|
|
|
|
UInt64 sys_time = 0;
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
UInt64 soft_page_faults = 0;
|
|
|
|
UInt64 hard_page_faults = 0;
|
2018-02-01 17:55:08 +00:00
|
|
|
UInt64 voluntary_context_switches = 0;
|
|
|
|
UInt64 involuntary_context_switches = 0;
|
|
|
|
|
|
|
|
RusageCounters() = default;
|
2018-05-31 15:54:08 +00:00
|
|
|
RusageCounters(const ::rusage & rusage_, UInt64 real_time_)
|
2018-02-01 17:55:08 +00:00
|
|
|
{
|
2018-05-31 15:54:08 +00:00
|
|
|
set(rusage_, real_time_);
|
2018-02-01 17:55:08 +00:00
|
|
|
}
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
void set(const ::rusage & rusage, UInt64 real_time_)
|
2018-02-01 17:55:08 +00:00
|
|
|
{
|
2018-05-31 15:54:08 +00:00
|
|
|
real_time = real_time_;
|
|
|
|
user_time = rusage.ru_utime.tv_sec * 1000000000UL + rusage.ru_utime.tv_usec;
|
|
|
|
sys_time = rusage.ru_stime.tv_sec * 1000000000UL + rusage.ru_stime.tv_usec;
|
|
|
|
|
|
|
|
soft_page_faults = static_cast<UInt64>(rusage.ru_minflt);
|
|
|
|
hard_page_faults = static_cast<UInt64>(rusage.ru_majflt);
|
|
|
|
voluntary_context_switches = static_cast<UInt64>(rusage.ru_nvcsw);
|
|
|
|
involuntary_context_switches = static_cast<UInt64>(rusage.ru_nivcsw);
|
2018-02-01 17:55:08 +00:00
|
|
|
}
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
static RusageCounters zeros(UInt64 real_time_ = getCurrentTimeNanoseconds())
|
2018-02-01 17:55:08 +00:00
|
|
|
{
|
|
|
|
RusageCounters res;
|
2018-05-31 15:54:08 +00:00
|
|
|
res.real_time = real_time_;
|
2018-05-29 18:14:31 +00:00
|
|
|
return res;
|
2018-02-01 17:55:08 +00:00
|
|
|
}
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
static RusageCounters current(UInt64 real_time_ = getCurrentTimeNanoseconds())
|
2018-02-01 17:55:08 +00:00
|
|
|
{
|
2018-05-31 15:54:08 +00:00
|
|
|
::rusage rusage;
|
|
|
|
::getrusage(RUSAGE_THREAD, &rusage);
|
|
|
|
return RusageCounters(rusage, real_time_);
|
2018-02-01 17:55:08 +00:00
|
|
|
}
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
static void incrementProfileEvents(const RusageCounters & prev, const RusageCounters & curr, ProfileEvents::Counters & profile_events)
|
2018-02-01 17:55:08 +00:00
|
|
|
{
|
2018-05-31 15:54:08 +00:00
|
|
|
profile_events.increment(ProfileEvents::RealTimeMicroseconds, (curr.real_time - prev.real_time) / 1000U);
|
|
|
|
profile_events.increment(ProfileEvents::UserTimeMicroseconds, (curr.user_time - prev.user_time) / 1000U);
|
|
|
|
profile_events.increment(ProfileEvents::SystemTimeMicroseconds, (curr.sys_time - prev.sys_time) / 1000U);
|
|
|
|
|
|
|
|
profile_events.increment(ProfileEvents::SoftPageFaults, curr.soft_page_faults - prev.soft_page_faults);
|
|
|
|
profile_events.increment(ProfileEvents::HardPageFaults, curr.hard_page_faults - prev.hard_page_faults);
|
2018-02-01 17:55:08 +00:00
|
|
|
}
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
static void updateProfileEvents(RusageCounters & last_counters, ProfileEvents::Counters & profile_events)
|
2018-02-01 17:55:08 +00:00
|
|
|
{
|
2018-05-29 18:14:31 +00:00
|
|
|
auto current_counters = current();
|
2018-05-31 15:54:08 +00:00
|
|
|
incrementProfileEvents(last_counters, current_counters, profile_events);
|
2018-05-29 18:14:31 +00:00
|
|
|
last_counters = current_counters;
|
2018-02-01 17:55:08 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-05-29 18:14:31 +00:00
|
|
|
struct TasksStatsCounters
|
|
|
|
{
|
|
|
|
::taskstats stat;
|
|
|
|
|
|
|
|
TasksStatsCounters() = default;
|
|
|
|
|
|
|
|
static TasksStatsCounters zeros()
|
|
|
|
{
|
|
|
|
TasksStatsCounters res;
|
|
|
|
memset(&res.stat, 0, sizeof(stat));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static TasksStatsCounters current();
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
static void incrementProfileEvents(const TasksStatsCounters & prev, const TasksStatsCounters & curr, ProfileEvents::Counters & profile_events)
|
2018-05-29 18:14:31 +00:00
|
|
|
{
|
2018-05-31 15:54:08 +00:00
|
|
|
profile_events.increment(ProfileEvents::OSIOWaitMicroseconds,
|
|
|
|
safeDiff(prev.stat.blkio_delay_total, curr.stat.blkio_delay_total) / 1000U);
|
|
|
|
profile_events.increment(ProfileEvents::OSReadBytes, safeDiff(prev.stat.read_bytes, curr.stat.read_bytes));
|
|
|
|
profile_events.increment(ProfileEvents::OSWriteBytes, safeDiff(prev.stat.write_bytes, curr.stat.write_bytes));
|
|
|
|
profile_events.increment(ProfileEvents::OSReadChars, safeDiff(prev.stat.read_char, curr.stat.read_char));
|
|
|
|
profile_events.increment(ProfileEvents::OSWriteChars, safeDiff(prev.stat.write_char, curr.stat.write_char));
|
2018-05-29 18:14:31 +00:00
|
|
|
}
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
static void updateProfileEvents(TasksStatsCounters & last_counters, ProfileEvents::Counters & profile_events)
|
2018-05-29 18:14:31 +00:00
|
|
|
{
|
|
|
|
auto current_counters = current();
|
2018-05-31 15:54:08 +00:00
|
|
|
incrementProfileEvents(last_counters, current_counters, profile_events);
|
2018-05-29 18:14:31 +00:00
|
|
|
last_counters = current_counters;
|
|
|
|
}
|
|
|
|
};
|
2018-02-01 17:55:08 +00:00
|
|
|
|
2018-05-29 18:14:31 +00:00
|
|
|
TasksStatsCounters TasksStatsCounters::current()
|
2018-03-01 16:52:24 +00:00
|
|
|
{
|
2018-05-29 18:14:31 +00:00
|
|
|
TasksStatsCounters res;
|
2018-06-09 15:29:08 +00:00
|
|
|
current_thread->taskstats_getter->getStat(res.stat, current_thread->os_thread_id);
|
2018-05-29 18:14:31 +00:00
|
|
|
return res;
|
2018-03-01 16:52:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-02-01 17:55:08 +00:00
|
|
|
ThreadStatus::ThreadStatus()
|
|
|
|
{
|
2018-06-04 14:16:27 +00:00
|
|
|
thread_number = Poco::ThreadNumber::get();
|
|
|
|
os_thread_id = TaskStatsInfoGetter::getCurrentTID();
|
|
|
|
|
|
|
|
last_rusage = std::make_unique<RusageCounters>();
|
|
|
|
last_taskstats = std::make_unique<TasksStatsCounters>();
|
|
|
|
taskstats_getter = std::make_unique<TaskStatsInfoGetter>();
|
2018-03-01 16:52:24 +00:00
|
|
|
|
2018-06-09 15:29:08 +00:00
|
|
|
memory_tracker.setDescription("(for thread)");
|
|
|
|
log = &Poco::Logger::get("ThreadStatus");
|
|
|
|
|
2018-06-06 20:57:07 +00:00
|
|
|
/// 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-03-01 16:52:24 +00:00
|
|
|
|
2018-05-29 18:14:31 +00:00
|
|
|
ThreadStatusPtr ThreadStatus::create()
|
|
|
|
{
|
|
|
|
return ThreadStatusPtr(new ThreadStatus);
|
2018-02-01 17:55:08 +00:00
|
|
|
}
|
|
|
|
|
2018-06-06 20:57:07 +00:00
|
|
|
ThreadStatus::~ThreadStatus() = default;
|
2018-06-01 19:39:32 +00:00
|
|
|
|
|
|
|
void ThreadStatus::initializeQuery()
|
|
|
|
{
|
|
|
|
if (thread_state != ThreadState::QueryInitializing && thread_state != ThreadState::DetachedFromQuery)
|
|
|
|
throw Exception("Unexpected thread state " + std::to_string(getCurrentState()) + __PRETTY_FUNCTION__, ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
thread_state = ThreadState::QueryInitializing;
|
2018-02-01 17:55:08 +00:00
|
|
|
}
|
|
|
|
|
2018-05-29 18:14:31 +00:00
|
|
|
void ThreadStatus::attachQuery(
|
2018-05-31 15:54:08 +00:00
|
|
|
QueryStatus * parent_query_,
|
|
|
|
ProfileEvents::Counters * parent_counters,
|
|
|
|
MemoryTracker * parent_memory_tracker,
|
2018-06-06 20:57:07 +00:00
|
|
|
const SystemLogsQueueWeakPtr & logs_queue_ptr_,
|
2018-05-29 18:14:31 +00:00
|
|
|
bool check_detached)
|
2018-02-01 17:55:08 +00:00
|
|
|
{
|
2018-06-01 19:39:32 +00:00
|
|
|
if (thread_state == ThreadState::AttachedToQuery)
|
2018-05-31 15:54:08 +00:00
|
|
|
{
|
|
|
|
if (check_detached)
|
|
|
|
throw Exception("Can't attach query to the thread, it is already attached", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
return;
|
|
|
|
}
|
2018-02-01 17:55:08 +00:00
|
|
|
|
2018-06-01 19:39:32 +00:00
|
|
|
if (thread_state != ThreadState::DetachedFromQuery && thread_state != ThreadState::QueryInitializing)
|
|
|
|
throw Exception("Unexpected thread state " + std::to_string(getCurrentState()) + __PRETTY_FUNCTION__, ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
{
|
|
|
|
std::lock_guard lock(mutex);
|
|
|
|
parent_query = parent_query_;
|
|
|
|
performance_counters.setParent(parent_counters);
|
|
|
|
memory_tracker.setParent(parent_memory_tracker);
|
2018-06-06 20:57:07 +00:00
|
|
|
logs_queue_ptr = logs_queue_ptr_;
|
2018-06-01 19:39:32 +00:00
|
|
|
}
|
2018-03-01 16:52:24 +00:00
|
|
|
|
2018-06-13 19:01:07 +00:00
|
|
|
/// 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)");
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
/// Try extract as many information as possible from ProcessList
|
2018-06-01 19:39:32 +00:00
|
|
|
if (parent_query)
|
2018-03-01 16:52:24 +00:00
|
|
|
{
|
2018-05-31 15:54:08 +00:00
|
|
|
/// Attach current thread to list of query threads
|
|
|
|
{
|
2018-06-01 19:39:32 +00:00
|
|
|
std::unique_lock lock(parent_query->threads_mutex);
|
2018-05-31 15:54:08 +00:00
|
|
|
|
2018-06-01 19:39:32 +00:00
|
|
|
if (parent_query->thread_statuses.empty())
|
|
|
|
parent_query->master_thread = shared_from_this();
|
2018-05-31 15:54:08 +00:00
|
|
|
|
2018-06-01 19:39:32 +00:00
|
|
|
if (!parent_query->thread_statuses.emplace(thread_number, shared_from_this()).second)
|
|
|
|
throw Exception("Thread " + std::to_string(thread_number) + " is attached twice", ErrorCodes::LOGICAL_ERROR);
|
2018-05-31 15:54:08 +00:00
|
|
|
}
|
|
|
|
|
2018-06-01 19:39:32 +00:00
|
|
|
query_context = parent_query->tryGetQueryContext();
|
|
|
|
if (query_context)
|
2018-05-31 15:54:08 +00:00
|
|
|
{
|
2018-06-01 19:39:32 +00:00
|
|
|
log_to_query_thread_log = query_context->getSettingsRef().log_query_threads.value != 0;
|
|
|
|
log_profile_events = query_context->getSettingsRef().log_profile_events.value != 0;
|
2018-05-31 15:54:08 +00:00
|
|
|
|
|
|
|
if (!getGlobalContext())
|
2018-06-01 19:39:32 +00:00
|
|
|
global_context = &query_context->getGlobalContext();
|
2018-05-31 15:54:08 +00:00
|
|
|
}
|
2018-03-01 16:52:24 +00:00
|
|
|
}
|
2018-02-01 17:55:08 +00:00
|
|
|
|
2018-06-01 19:39:32 +00:00
|
|
|
thread_state = ThreadState::AttachedToQuery;
|
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
query_start_time_nanoseconds = getCurrentTimeNanoseconds();
|
|
|
|
query_start_time = time(nullptr);
|
2018-06-04 14:16:27 +00:00
|
|
|
++queries_started;
|
|
|
|
|
|
|
|
*last_rusage = RusageCounters::current(query_start_time_nanoseconds);
|
|
|
|
*last_taskstats = TasksStatsCounters::current();
|
2018-02-01 17:55:08 +00:00
|
|
|
}
|
|
|
|
|
2018-06-13 19:01:07 +00:00
|
|
|
void ThreadStatus::detachQuery(bool exit_if_already_detached, bool thread_exits)
|
2018-02-01 17:55:08 +00:00
|
|
|
{
|
2018-06-13 19:01:07 +00:00
|
|
|
if (exit_if_already_detached && thread_state == ThreadState::DetachedFromQuery)
|
|
|
|
{
|
|
|
|
thread_state = thread_exits ? ThreadState::Died : ThreadState::DetachedFromQuery;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-06-01 19:39:32 +00:00
|
|
|
if (thread_state != ThreadState::AttachedToQuery && thread_state != ThreadState::QueryInitializing)
|
|
|
|
throw Exception("Unexpected thread state " + std::to_string(getCurrentState()) + __PRETTY_FUNCTION__, ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
2018-05-29 18:14:31 +00:00
|
|
|
updatePerfomanceCountersImpl();
|
2018-02-01 17:55:08 +00:00
|
|
|
|
2018-05-31 15:54:08 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
if (log_to_query_thread_log)
|
|
|
|
if (auto global_context = getGlobalContext())
|
|
|
|
if (auto thread_log = global_context->getQueryThreadLog())
|
|
|
|
logToQueryThreadLog(*thread_log);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
tryLogCurrentException(log);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
std::lock_guard lock(mutex);
|
|
|
|
|
|
|
|
/// Detach from parent
|
2018-06-01 19:39:32 +00:00
|
|
|
performance_counters.setParent(&ProfileEvents::global_counters);
|
2018-05-31 15:54:08 +00:00
|
|
|
memory_tracker.setParent(nullptr);
|
|
|
|
query_context = nullptr;
|
2018-06-01 19:39:32 +00:00
|
|
|
}
|
2018-05-31 15:54:08 +00:00
|
|
|
|
2018-06-01 19:39:32 +00:00
|
|
|
thread_state = thread_exits ? ThreadState::Died : ThreadState::DetachedFromQuery;
|
|
|
|
log_to_query_thread_log = true;
|
|
|
|
log_profile_events = true;
|
|
|
|
}
|
|
|
|
|
2018-06-09 15:29:08 +00:00
|
|
|
|
2018-06-01 19:39:32 +00:00
|
|
|
void ThreadStatus::updatePerfomanceCountersImpl()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2018-06-04 14:16:27 +00:00
|
|
|
RusageCounters::updateProfileEvents(*last_rusage, performance_counters);
|
|
|
|
TasksStatsCounters::updateProfileEvents(*last_taskstats, performance_counters);
|
2018-06-01 19:39:32 +00:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
tryLogCurrentException(log);
|
2018-05-31 15:54:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ThreadStatus::logToQueryThreadLog(QueryThreadLog & thread_log)
|
|
|
|
{
|
|
|
|
QueryThreadLogElement elem;
|
|
|
|
|
|
|
|
elem.event_time = time(nullptr);
|
|
|
|
elem.query_start_time = query_start_time;
|
|
|
|
elem.query_duration_ms = (getCurrentTimeNanoseconds() - query_start_time_nanoseconds) / 1000000U;
|
|
|
|
|
|
|
|
elem.read_rows = progress_in.rows.load(std::memory_order_relaxed);
|
|
|
|
elem.read_bytes = progress_in.bytes.load(std::memory_order_relaxed);
|
|
|
|
elem.written_rows = progress_out.rows.load(std::memory_order_relaxed);
|
|
|
|
elem.written_bytes = progress_out.bytes.load(std::memory_order_relaxed);
|
2018-06-09 15:29:08 +00:00
|
|
|
elem.memory_usage = memory_tracker.getPeak();
|
2018-05-31 15:54:08 +00:00
|
|
|
|
2018-06-01 11:58:17 +00:00
|
|
|
elem.thread_name = getThreadName();
|
2018-06-01 19:39:32 +00:00
|
|
|
elem.thread_number = thread_number;
|
2018-05-31 15:54:08 +00:00
|
|
|
elem.os_thread_id = os_thread_id;
|
|
|
|
|
2018-06-01 19:39:32 +00:00
|
|
|
if (parent_query)
|
2018-05-31 15:54:08 +00:00
|
|
|
{
|
|
|
|
{
|
2018-06-01 19:39:32 +00:00
|
|
|
std::shared_lock threads_mutex(parent_query->threads_mutex);
|
|
|
|
|
|
|
|
if (parent_query->master_thread)
|
|
|
|
{
|
|
|
|
elem.master_thread_number = parent_query->master_thread->thread_number;
|
|
|
|
elem.master_os_thread_id = parent_query->master_thread->os_thread_id;
|
|
|
|
}
|
2018-05-31 15:54:08 +00:00
|
|
|
}
|
|
|
|
|
2018-06-01 19:39:32 +00:00
|
|
|
elem.query = parent_query->query;
|
|
|
|
elem.client_info = parent_query->getClientInfo();
|
2018-05-31 15:54:08 +00:00
|
|
|
}
|
2018-02-01 17:55:08 +00:00
|
|
|
|
2018-06-01 11:58:17 +00:00
|
|
|
if (log_profile_events)
|
2018-05-31 15:54:08 +00:00
|
|
|
{
|
2018-06-01 11:58:17 +00:00
|
|
|
/// NOTE: Here we are in the same thread, so we can make memcpy()
|
2018-06-01 19:39:32 +00:00
|
|
|
elem.profile_counters = std::make_shared<ProfileEvents::Counters>(performance_counters.getPartiallyAtomicSnapshot());
|
2018-05-31 15:54:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
thread_log.add(elem);
|
2018-02-01 17:55:08 +00:00
|
|
|
}
|
|
|
|
|
2018-06-01 19:39:32 +00:00
|
|
|
void ThreadStatus::clean()
|
2018-03-01 16:52:24 +00:00
|
|
|
{
|
2018-06-01 19:39:32 +00:00
|
|
|
{
|
|
|
|
std::lock_guard lock(mutex);
|
|
|
|
parent_query = nullptr;
|
|
|
|
}
|
2018-05-31 15:54:08 +00:00
|
|
|
|
2018-06-01 19:39:32 +00:00
|
|
|
if (thread_state != ThreadState::DetachedFromQuery && thread_state != ThreadState::Died)
|
|
|
|
throw Exception("Unexpected thread state " + std::to_string(getCurrentState()) + __PRETTY_FUNCTION__, ErrorCodes::LOGICAL_ERROR);
|
2018-05-29 18:14:31 +00:00
|
|
|
}
|
2018-02-01 17:55:08 +00:00
|
|
|
|
|
|
|
}
|