| 44 | } |
| 45 | |
| 46 | int RelayThreadMonitor::svc() |
| 47 | { |
| 48 | OpenDDS::DCPS::ThreadStatusManager& thread_status_manager = TheServiceParticipant->get_thread_status_manager(); |
| 49 | ThreadStatusManager::Start s(thread_status_manager, "RtpsRelay RelayThreadMonitor"); |
| 50 | |
| 51 | ACE_GUARD_RETURN(ACE_Thread_Mutex, g, mutex_, -1); |
| 52 | |
| 53 | for (auto count = 0; running_; count = (count + 1) % config_.thread_status_safety_factor()) { |
| 54 | condition_.wait_until(MonotonicTimePoint::now() + thread_status_manager.thread_status_interval(), thread_status_manager); |
| 55 | if (!running_) { |
| 56 | break; |
| 57 | } |
| 58 | OpenDDS::DCPS::InternalThreadBuiltinTopicDataSeq datas; |
| 59 | DDS::SampleInfoSeq infos; |
| 60 | const DDS::ReturnCode_t ret = thread_status_reader_->read(datas, |
| 61 | infos, |
| 62 | DDS::LENGTH_UNLIMITED, |
| 63 | DDS::ANY_SAMPLE_STATE, |
| 64 | DDS::ANY_VIEW_STATE, |
| 65 | DDS::ANY_INSTANCE_STATE); |
| 66 | if (ret != DDS::RETCODE_OK) { |
| 67 | ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: RelayThreadMonitor::svc failed to read %C\n", OpenDDS::DCPS::retcode_to_string(ret))); |
| 68 | continue; |
| 69 | } |
| 70 | |
| 71 | const SystemTimePoint expire = SystemTimePoint::now() - thread_status_manager.thread_status_interval() * config_.thread_status_safety_factor(); |
| 72 | const auto log_all_threads = count == 0 && config_.log_thread_status(); |
| 73 | std::vector<DDS::UInt32> late_thread_indexes; |
| 74 | |
| 75 | for (CORBA::ULong idx = 0; idx != infos.length(); ++idx) { |
| 76 | if (infos[idx].valid_data) { |
| 77 | const auto& bit_sample = datas[idx]; |
| 78 | const auto thread_id = bit_sample.thread_id.in(); |
| 79 | auto& utilization = utilization_[thread_id]; |
| 80 | const auto old_utilization = utilization; |
| 81 | utilization = bit_sample.utilization; |
| 82 | if (config_.log_utilization_changes() && std::abs(utilization - old_utilization) > 0.2) { // 20% change |
| 83 | ACE_DEBUG((LM_INFO, "(%P|%t) INFO: Thread %C utilization changed significantly: %.2f%% -> %.2f%%\n", |
| 84 | thread_id, old_utilization * 100, utilization * 100)); |
| 85 | } |
| 86 | |
| 87 | } else if (infos[idx].instance_state != DDS::ALIVE_INSTANCE_STATE) { |
| 88 | utilization_.erase(datas[idx].thread_id.in()); |
| 89 | } |
| 90 | |
| 91 | if (log_all_threads) { |
| 92 | ACE_DEBUG((LM_INFO, "(%P|%t) INFO: Thread Status %C %C\n", |
| 93 | infos[idx].valid_data ? to_json(datas[idx]).c_str() : datas[idx].thread_id.in(), |
| 94 | to_json(infos[idx]).c_str())); |
| 95 | } |
| 96 | |
| 97 | if (infos[idx].instance_state == DDS::ALIVE_INSTANCE_STATE && SystemTimePoint(infos[idx].source_timestamp) < expire) { |
| 98 | late_thread_indexes.push_back(idx); |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | for (const auto idx : late_thread_indexes) { |
| 103 | const SystemTimePoint timestamp(infos[idx].source_timestamp); |
nothing calls this directly
no test coverage detected