blob: 5fce273d5f25a355dadffde623e36da322d17ef4 [file] [log] [blame]
Isabelle Taylord404ea12018-02-19 17:28:01 +00001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "src/traced/probes/probes_producer.h"
18
19#include <stdio.h>
Anna Zappone4ea73c02018-03-09 16:01:21 +000020#include <sys/stat.h>
Primiano Tucci52526602018-03-29 22:53:10 +010021
22#include <algorithm>
Anna Zappone27ac99c2018-03-06 14:25:35 +000023#include <queue>
Isabelle Taylord404ea12018-02-19 17:28:01 +000024#include <string>
25
26#include "perfetto/base/logging.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010027#include "perfetto/ext/base/utils.h"
28#include "perfetto/ext/base/weak_ptr.h"
29#include "perfetto/ext/traced/traced.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010030#include "perfetto/ext/tracing/core/trace_packet.h"
31#include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
Primiano Tucci0f9e0222019-06-05 09:36:41 +010032#include "perfetto/tracing/core/data_source_config.h"
33#include "perfetto/tracing/core/data_source_descriptor.h"
34#include "perfetto/tracing/core/trace_config.h"
Primiano Tucci64df2ca2019-01-03 22:26:47 +000035#include "src/traced/probes/android_log/android_log_data_source.h"
Anna Zappone2a6f9042018-03-14 13:26:07 +000036#include "src/traced/probes/filesystem/inode_file_data_source.h"
Primiano Tucci0f2f3b42019-05-21 19:37:01 +010037#include "src/traced/probes/ftrace/ftrace_config.h"
Primiano Tuccifd8240d2018-08-01 09:34:54 +010038#include "src/traced/probes/ftrace/ftrace_data_source.h"
Primiano Tuccib02d8dc2019-06-04 11:46:43 +010039#include "src/traced/probes/metatrace/metatrace_data_source.h"
Florian Mayer12f0f8e2019-04-02 12:31:13 +010040#include "src/traced/probes/packages_list/packages_list_data_source.h"
Primiano Tuccib86e9ca2018-12-03 20:20:11 +010041#include "src/traced/probes/power/android_power_data_source.h"
Primiano Tuccifd8240d2018-08-01 09:34:54 +010042#include "src/traced/probes/probes_data_source.h"
Primiano Tucci64df2ca2019-01-03 22:26:47 +000043#include "src/traced/probes/ps/process_stats_data_source.h"
44#include "src/traced/probes/sys_stats/sys_stats_data_source.h"
Isabelle Taylord404ea12018-02-19 17:28:01 +000045
Anna Zappone27ac99c2018-03-06 14:25:35 +000046#include "perfetto/trace/filesystem/inode_file_map.pbzero.h"
Isabelle Taylord404ea12018-02-19 17:28:01 +000047#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
Hector Dearman3afb1e02018-04-27 16:46:52 +010048#include "perfetto/trace/ftrace/ftrace_stats.pbzero.h"
Isabelle Taylord404ea12018-02-19 17:28:01 +000049#include "perfetto/trace/trace_packet.pbzero.h"
50
51namespace perfetto {
52namespace {
53
Primiano Tucci3cbb10a2018-04-10 17:52:40 +010054constexpr uint32_t kInitialConnectionBackoffMs = 100;
55constexpr uint32_t kMaxConnectionBackoffMs = 30 * 1000;
Primiano Tucci50e9eda2018-11-20 10:52:35 +010056
Sami Kyostila0a34b032019-05-16 18:28:48 +010057// Should be larger than FtraceController::kControllerFlushTimeoutMs.
Primiano Tucci50e9eda2018-11-20 10:52:35 +010058constexpr uint32_t kFlushTimeoutMs = 1000;
59
Primiano Tucci578d7842018-03-29 15:27:05 +010060constexpr char kFtraceSourceName[] = "linux.ftrace";
61constexpr char kProcessStatsSourceName[] = "linux.process_stats";
62constexpr char kInodeMapSourceName[] = "linux.inode_file_map";
Primiano Tucci82a8bfd2018-09-19 11:33:04 +010063constexpr char kSysStatsSourceName[] = "linux.sys_stats";
Primiano Tuccib86e9ca2018-12-03 20:20:11 +010064constexpr char kAndroidPowerSourceName[] = "android.power";
Primiano Tucci64df2ca2019-01-03 22:26:47 +000065constexpr char kAndroidLogSourceName[] = "android.log";
Florian Mayer12f0f8e2019-04-02 12:31:13 +010066constexpr char kPackagesListSourceName[] = "android.packages_list";
Isabelle Taylord404ea12018-02-19 17:28:01 +000067
68} // namespace.
69
70// State transition diagram:
71// +----------------------------+
72// v +
73// NotStarted -> NotConnected -> Connecting -> Connected
74// ^ +
75// +--------------+
76//
77
Primiano Tuccifd8240d2018-08-01 09:34:54 +010078ProbesProducer::ProbesProducer() : weak_factory_(this) {}
79ProbesProducer::~ProbesProducer() {
80 // The ftrace data sources must be deleted before the ftrace controller.
81 data_sources_.clear();
82 ftrace_.reset();
83}
Isabelle Taylord404ea12018-02-19 17:28:01 +000084
85void ProbesProducer::OnConnect() {
86 PERFETTO_DCHECK(state_ == kConnecting);
87 state_ = kConnected;
88 ResetConnectionBackoff();
89 PERFETTO_LOG("Connected to the service");
90
Primiano Tucci82a8bfd2018-09-19 11:33:04 +010091 {
92 DataSourceDescriptor desc;
93 desc.set_name(kFtraceSourceName);
94 endpoint_->RegisterDataSource(desc);
95 }
Isabelle Taylord404ea12018-02-19 17:28:01 +000096
Primiano Tucci82a8bfd2018-09-19 11:33:04 +010097 {
98 DataSourceDescriptor desc;
99 desc.set_name(kProcessStatsSourceName);
Ryan Savitskic4ecf3e2019-05-13 10:58:23 +0100100 desc.set_handles_incremental_state_clear(true);
Primiano Tucci82a8bfd2018-09-19 11:33:04 +0100101 endpoint_->RegisterDataSource(desc);
102 }
Anna Zappone27ac99c2018-03-06 14:25:35 +0000103
Primiano Tucci82a8bfd2018-09-19 11:33:04 +0100104 {
105 DataSourceDescriptor desc;
106 desc.set_name(kInodeMapSourceName);
107 endpoint_->RegisterDataSource(desc);
108 }
109
110 {
111 DataSourceDescriptor desc;
112 desc.set_name(kSysStatsSourceName);
113 endpoint_->RegisterDataSource(desc);
114 }
Primiano Tuccib86e9ca2018-12-03 20:20:11 +0100115
116 {
117 DataSourceDescriptor desc;
118 desc.set_name(kAndroidPowerSourceName);
119 endpoint_->RegisterDataSource(desc);
120 }
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000121
122 {
123 DataSourceDescriptor desc;
124 desc.set_name(kAndroidLogSourceName);
125 endpoint_->RegisterDataSource(desc);
126 }
Florian Mayer12f0f8e2019-04-02 12:31:13 +0100127
128 {
129 DataSourceDescriptor desc;
130 desc.set_name(kPackagesListSourceName);
131 endpoint_->RegisterDataSource(desc);
132 }
Primiano Tuccib02d8dc2019-06-04 11:46:43 +0100133
134 {
135 DataSourceDescriptor desc;
136 desc.set_name(MetatraceDataSource::kDataSourceName);
137 endpoint_->RegisterDataSource(desc);
138 }
Isabelle Taylord404ea12018-02-19 17:28:01 +0000139}
140
141void ProbesProducer::OnDisconnect() {
142 PERFETTO_DCHECK(state_ == kConnected || state_ == kConnecting);
Isabelle Taylord404ea12018-02-19 17:28:01 +0000143 PERFETTO_LOG("Disconnected from tracing service");
Primiano Tuccie56411c2018-03-30 01:15:02 +0100144 if (state_ == kConnected)
145 return task_runner_->PostTask([this] { this->Restart(); });
Isabelle Taylord404ea12018-02-19 17:28:01 +0000146
Primiano Tuccie56411c2018-03-30 01:15:02 +0100147 state_ = kNotConnected;
148 IncreaseConnectionBackoff();
Isabelle Taylord404ea12018-02-19 17:28:01 +0000149 task_runner_->PostDelayedTask([this] { this->Connect(); },
150 connection_backoff_ms_);
151}
152
Primiano Tuccie56411c2018-03-30 01:15:02 +0100153void ProbesProducer::Restart() {
154 // We lost the connection with the tracing service. At this point we need
155 // to reset all the data sources. Trying to handle that manually is going to
156 // be error prone. What we do here is simply desroying the instance and
157 // recreating it again.
158 // TODO(hjd): Add e2e test for this.
159
160 base::TaskRunner* task_runner = task_runner_;
161 const char* socket_name = socket_name_;
162
163 // Invoke destructor and then the constructor again.
164 this->~ProbesProducer();
165 new (this) ProbesProducer();
166
167 ConnectWithRetries(socket_name, task_runner);
168}
169
Primiano Tucci674076d2018-10-01 10:41:09 +0100170void ProbesProducer::SetupDataSource(DataSourceInstanceID instance_id,
Primiano Tucciafb72b52018-09-25 09:37:24 +0100171 const DataSourceConfig& config) {
Primiano Tucci674076d2018-10-01 10:41:09 +0100172 PERFETTO_DLOG("SetupDataSource(id=%" PRIu64 ", name=%s)", instance_id,
173 config.name().c_str());
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100174 PERFETTO_DCHECK(data_sources_.count(instance_id) == 0);
Primiano Tucci03de28f2018-08-01 11:29:46 +0100175 TracingSessionID session_id = config.tracing_session_id();
176 PERFETTO_CHECK(session_id > 0);
Hector Dearman0ff07c72018-03-15 09:54:46 +0000177
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100178 std::unique_ptr<ProbesDataSource> data_source;
Hector Dearman0ff07c72018-03-15 09:54:46 +0000179 if (config.name() == kFtraceSourceName) {
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000180 data_source = CreateFtraceDataSource(session_id, config);
Hector Dearman0ff07c72018-03-15 09:54:46 +0000181 } else if (config.name() == kInodeMapSourceName) {
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000182 data_source = CreateInodeFileDataSource(session_id, config);
Hector Dearman0ff07c72018-03-15 09:54:46 +0000183 } else if (config.name() == kProcessStatsSourceName) {
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000184 data_source = CreateProcessStatsDataSource(session_id, config);
Primiano Tucci82a8bfd2018-09-19 11:33:04 +0100185 } else if (config.name() == kSysStatsSourceName) {
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000186 data_source = CreateSysStatsDataSource(session_id, config);
Primiano Tuccib86e9ca2018-12-03 20:20:11 +0100187 } else if (config.name() == kAndroidPowerSourceName) {
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000188 data_source = CreateAndroidPowerDataSource(session_id, config);
189 } else if (config.name() == kAndroidLogSourceName) {
190 data_source = CreateAndroidLogDataSource(session_id, config);
Florian Mayer12f0f8e2019-04-02 12:31:13 +0100191 } else if (config.name() == kPackagesListSourceName) {
192 data_source = CreatePackagesListDataSource(session_id, config);
Primiano Tuccib02d8dc2019-06-04 11:46:43 +0100193 } else if (config.name() == MetatraceDataSource::kDataSourceName) {
194 data_source = CreateMetatraceDataSource(session_id, config);
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100195 }
196
197 if (!data_source) {
198 PERFETTO_ELOG("Failed to create data source '%s'", config.name().c_str());
Hector Dearman0ff07c72018-03-15 09:54:46 +0000199 return;
200 }
201
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100202 session_data_sources_.emplace(session_id, data_source.get());
203 data_sources_[instance_id] = std::move(data_source);
Primiano Tucci674076d2018-10-01 10:41:09 +0100204}
Hector Dearman0ff07c72018-03-15 09:54:46 +0000205
Primiano Tucci674076d2018-10-01 10:41:09 +0100206void ProbesProducer::StartDataSource(DataSourceInstanceID instance_id,
207 const DataSourceConfig& config) {
208 PERFETTO_DLOG("StartDataSource(id=%" PRIu64 ", name=%s)", instance_id,
209 config.name().c_str());
210 auto it = data_sources_.find(instance_id);
211 if (it == data_sources_.end()) {
Primiano Tucci8a0dc5d2018-10-02 12:51:11 +0100212 // Can happen if SetupDataSource() failed (e.g. ftrace was busy).
Primiano Tucci674076d2018-10-01 10:41:09 +0100213 PERFETTO_ELOG("Data source id=%" PRIu64 " not found", instance_id);
214 return;
215 }
216 ProbesDataSource* data_source = it->second.get();
217 if (data_source->started)
218 return;
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100219 if (config.trace_duration_ms() != 0) {
220 uint32_t timeout = 5000 + 2 * config.trace_duration_ms();
221 watchdogs_.emplace(
222 instance_id, base::Watchdog::GetInstance()->CreateFatalTimer(timeout));
Isabelle Taylord404ea12018-02-19 17:28:01 +0000223 }
Primiano Tucci674076d2018-10-01 10:41:09 +0100224 data_source->started = true;
225 data_source->Start();
Isabelle Taylord404ea12018-02-19 17:28:01 +0000226}
227
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100228std::unique_ptr<ProbesDataSource> ProbesProducer::CreateFtraceDataSource(
Hector Dearman0ff07c72018-03-15 09:54:46 +0000229 TracingSessionID session_id,
Hector Dearman0ff07c72018-03-15 09:54:46 +0000230 const DataSourceConfig& config) {
Isabelle Taylord404ea12018-02-19 17:28:01 +0000231 // Don't retry if FtraceController::Create() failed once.
232 // This can legitimately happen on user builds where we cannot access the
233 // debug paths, e.g., because of SELinux rules.
234 if (ftrace_creation_failed_)
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100235 return nullptr;
Isabelle Taylord404ea12018-02-19 17:28:01 +0000236
237 // Lazily create on the first instance.
238 if (!ftrace_) {
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100239 ftrace_ = FtraceController::Create(task_runner_, this);
Isabelle Taylord404ea12018-02-19 17:28:01 +0000240
241 if (!ftrace_) {
242 PERFETTO_ELOG("Failed to create FtraceController");
243 ftrace_creation_failed_ = true;
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100244 return nullptr;
Isabelle Taylord404ea12018-02-19 17:28:01 +0000245 }
246
247 ftrace_->DisableAllEvents();
248 ftrace_->ClearTrace();
249 }
250
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000251 PERFETTO_LOG("Ftrace setup (target_buf=%" PRIu32 ")", config.target_buffer());
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100252 const BufferID buffer_id = static_cast<BufferID>(config.target_buffer());
Primiano Tucci0f2f3b42019-05-21 19:37:01 +0100253 FtraceConfig ftrace_config;
254 ftrace_config.ParseRawProto(config.ftrace_config_raw());
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100255 std::unique_ptr<FtraceDataSource> data_source(new FtraceDataSource(
Primiano Tucci0f2f3b42019-05-21 19:37:01 +0100256 ftrace_->GetWeakPtr(), session_id, std::move(ftrace_config),
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100257 endpoint_->CreateTraceWriter(buffer_id)));
258 if (!ftrace_->AddDataSource(data_source.get())) {
259 PERFETTO_ELOG(
Primiano Tucci8a0dc5d2018-10-02 12:51:11 +0100260 "Failed to setup tracing (too many concurrent sessions or ftrace is "
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100261 "already in use)");
262 return nullptr;
Hector Dearmanee3c49d2018-02-28 14:10:22 +0000263 }
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100264 return std::move(data_source);
Anna Zappone27ac99c2018-03-06 14:25:35 +0000265}
266
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100267std::unique_ptr<ProbesDataSource> ProbesProducer::CreateInodeFileDataSource(
Hector Dearman0ff07c72018-03-15 09:54:46 +0000268 TracingSessionID session_id,
Primiano Tuccidae35652018-03-29 18:32:02 +0100269 DataSourceConfig source_config) {
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000270 PERFETTO_LOG("Inode file map setup (target_buf=%" PRIu32 ")",
271 source_config.target_buffer());
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100272 auto buffer_id = static_cast<BufferID>(source_config.target_buffer());
Anna Zappone2a6f9042018-03-14 13:26:07 +0000273 if (system_inodes_.empty())
Hector Dearman7fabd702018-03-28 12:37:15 +0100274 CreateStaticDeviceToInodeMap("/system", &system_inodes_);
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100275 return std::unique_ptr<InodeFileDataSource>(new InodeFileDataSource(
276 std::move(source_config), task_runner_, session_id, &system_inodes_,
277 &cache_, endpoint_->CreateTraceWriter(buffer_id)));
Isabelle Taylord404ea12018-02-19 17:28:01 +0000278}
279
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100280std::unique_ptr<ProbesDataSource> ProbesProducer::CreateProcessStatsDataSource(
Hector Dearman0ff07c72018-03-15 09:54:46 +0000281 TracingSessionID session_id,
Hector Dearman0ff07c72018-03-15 09:54:46 +0000282 const DataSourceConfig& config) {
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100283 auto buffer_id = static_cast<BufferID>(config.target_buffer());
Primiano Tucci8a0dc5d2018-10-02 12:51:11 +0100284 return std::unique_ptr<ProcessStatsDataSource>(new ProcessStatsDataSource(
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700285 task_runner_, session_id, endpoint_->CreateTraceWriter(buffer_id),
286 config));
Isabelle Taylord404ea12018-02-19 17:28:01 +0000287}
288
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000289std::unique_ptr<ProbesDataSource> ProbesProducer::CreateAndroidPowerDataSource(
290 TracingSessionID session_id,
291 const DataSourceConfig& config) {
Primiano Tuccib86e9ca2018-12-03 20:20:11 +0100292 auto buffer_id = static_cast<BufferID>(config.target_buffer());
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000293 return std::unique_ptr<ProbesDataSource>(
Primiano Tuccib86e9ca2018-12-03 20:20:11 +0100294 new AndroidPowerDataSource(config, task_runner_, session_id,
295 endpoint_->CreateTraceWriter(buffer_id)));
296}
297
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000298std::unique_ptr<ProbesDataSource> ProbesProducer::CreateAndroidLogDataSource(
Primiano Tucci82a8bfd2018-09-19 11:33:04 +0100299 TracingSessionID session_id,
Primiano Tucci82a8bfd2018-09-19 11:33:04 +0100300 const DataSourceConfig& config) {
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000301 auto buffer_id = static_cast<BufferID>(config.target_buffer());
302 return std::unique_ptr<ProbesDataSource>(
303 new AndroidLogDataSource(config, task_runner_, session_id,
304 endpoint_->CreateTraceWriter(buffer_id)));
305}
306
Florian Mayer12f0f8e2019-04-02 12:31:13 +0100307std::unique_ptr<ProbesDataSource> ProbesProducer::CreatePackagesListDataSource(
308 TracingSessionID session_id,
309 const DataSourceConfig& config) {
310 auto buffer_id = static_cast<BufferID>(config.target_buffer());
311 return std::unique_ptr<ProbesDataSource>(new PackagesListDataSource(
312 session_id, endpoint_->CreateTraceWriter(buffer_id)));
313}
314
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000315std::unique_ptr<ProbesDataSource> ProbesProducer::CreateSysStatsDataSource(
316 TracingSessionID session_id,
317 const DataSourceConfig& config) {
Primiano Tucci82a8bfd2018-09-19 11:33:04 +0100318 auto buffer_id = static_cast<BufferID>(config.target_buffer());
Primiano Tucci8a0dc5d2018-10-02 12:51:11 +0100319 return std::unique_ptr<SysStatsDataSource>(
Primiano Tucci82a8bfd2018-09-19 11:33:04 +0100320 new SysStatsDataSource(task_runner_, session_id,
321 endpoint_->CreateTraceWriter(buffer_id), config));
Primiano Tucci82a8bfd2018-09-19 11:33:04 +0100322}
323
Primiano Tuccib02d8dc2019-06-04 11:46:43 +0100324std::unique_ptr<ProbesDataSource> ProbesProducer::CreateMetatraceDataSource(
325 TracingSessionID session_id,
326 const DataSourceConfig& config) {
327 auto buffer_id = static_cast<BufferID>(config.target_buffer());
328 return std::unique_ptr<ProbesDataSource>(new MetatraceDataSource(
329 task_runner_, session_id, endpoint_->CreateTraceWriter(buffer_id)));
330}
331
Primiano Tucciafb72b52018-09-25 09:37:24 +0100332void ProbesProducer::StopDataSource(DataSourceInstanceID id) {
Isabelle Taylord404ea12018-02-19 17:28:01 +0000333 PERFETTO_LOG("Producer stop (id=%" PRIu64 ")", id);
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100334 auto it = data_sources_.find(id);
335 if (it == data_sources_.end()) {
Primiano Tucci8a0dc5d2018-10-02 12:51:11 +0100336 // Can happen if SetupDataSource() failed (e.g. ftrace was busy).
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100337 PERFETTO_ELOG("Cannot stop data source id=%" PRIu64 ", not found", id);
338 return;
339 }
340 ProbesDataSource* data_source = it->second.get();
341 TracingSessionID session_id = data_source->tracing_session_id;
342 auto range = session_data_sources_.equal_range(session_id);
343 for (auto kv = range.first; kv != range.second; kv++) {
344 if (kv->second != data_source)
345 continue;
346 session_data_sources_.erase(kv);
347 break;
348 }
349 data_sources_.erase(it);
Hector Dearman77451692018-03-08 16:21:13 +0000350 watchdogs_.erase(id);
Isabelle Taylord404ea12018-02-19 17:28:01 +0000351}
352
Primiano Tuccidca727d2018-04-04 11:31:55 +0200353void ProbesProducer::OnTracingSetup() {}
Isabelle Taylor69faa902018-03-21 15:42:03 +0000354
Primiano Tuccid52e6272018-04-06 19:06:53 +0200355void ProbesProducer::Flush(FlushRequestID flush_request_id,
356 const DataSourceInstanceID* data_source_ids,
357 size_t num_data_sources) {
Primiano Tucci50e9eda2018-11-20 10:52:35 +0100358 PERFETTO_DCHECK(flush_request_id);
359 auto weak_this = weak_factory_.GetWeakPtr();
360
361 // Issue a Flush() to all started data sources.
362 bool flush_queued = false;
Primiano Tuccid52e6272018-04-06 19:06:53 +0200363 for (size_t i = 0; i < num_data_sources; i++) {
Primiano Tucci50e9eda2018-11-20 10:52:35 +0100364 DataSourceInstanceID ds_id = data_source_ids[i];
365 auto it = data_sources_.find(ds_id);
Primiano Tucci674076d2018-10-01 10:41:09 +0100366 if (it == data_sources_.end() || !it->second->started)
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100367 continue;
Primiano Tucci50e9eda2018-11-20 10:52:35 +0100368 pending_flushes_.emplace(flush_request_id, ds_id);
369 flush_queued = true;
370 auto flush_callback = [weak_this, flush_request_id, ds_id] {
371 if (weak_this)
372 weak_this->OnDataSourceFlushComplete(flush_request_id, ds_id);
373 };
374 it->second->Flush(flush_request_id, flush_callback);
Primiano Tuccid52e6272018-04-06 19:06:53 +0200375 }
Primiano Tucci50e9eda2018-11-20 10:52:35 +0100376
377 // If there is nothing to flush, ack immediately.
378 if (!flush_queued) {
379 endpoint_->NotifyFlushComplete(flush_request_id);
380 return;
381 }
382
383 // Otherwise, post the timeout task.
384 task_runner_->PostDelayedTask(
385 [weak_this, flush_request_id] {
386 if (weak_this)
387 weak_this->OnFlushTimeout(flush_request_id);
388 },
389 kFlushTimeoutMs);
390}
391
392void ProbesProducer::OnDataSourceFlushComplete(FlushRequestID flush_request_id,
393 DataSourceInstanceID ds_id) {
394 PERFETTO_DLOG("Flush %" PRIu64 " acked by data source %" PRIu64,
395 flush_request_id, ds_id);
396 auto range = pending_flushes_.equal_range(flush_request_id);
397 for (auto it = range.first; it != range.second; it++) {
398 if (it->second == ds_id) {
399 pending_flushes_.erase(it);
400 break;
401 }
402 }
403
404 if (pending_flushes_.count(flush_request_id))
405 return; // Still waiting for other data sources to ack.
406
407 PERFETTO_DLOG("All data sources acked to flush %" PRIu64, flush_request_id);
408 endpoint_->NotifyFlushComplete(flush_request_id);
409}
410
411void ProbesProducer::OnFlushTimeout(FlushRequestID flush_request_id) {
412 if (pending_flushes_.count(flush_request_id) == 0)
413 return; // All acked.
414 PERFETTO_ELOG("Flush(%" PRIu64 ") timed out", flush_request_id);
415 pending_flushes_.erase(flush_request_id);
Primiano Tuccid52e6272018-04-06 19:06:53 +0200416 endpoint_->NotifyFlushComplete(flush_request_id);
417}
418
Ryan Savitskic4ecf3e2019-05-13 10:58:23 +0100419void ProbesProducer::ClearIncrementalState(
420 const DataSourceInstanceID* data_source_ids,
421 size_t num_data_sources) {
422 for (size_t i = 0; i < num_data_sources; i++) {
423 DataSourceInstanceID ds_id = data_source_ids[i];
424 auto it = data_sources_.find(ds_id);
425 if (it == data_sources_.end() || !it->second->started)
426 continue;
427
428 it->second->ClearIncrementalState();
429 }
430}
431
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100432// This function is called by the FtraceController in batches, whenever it has
433// read one or more pages from one or more cpus and written that into the
434// userspace tracing buffer. If more than one ftrace data sources are active,
435// this call typically happens after writing for all session has been handled.
436void ProbesProducer::OnFtraceDataWrittenIntoDataSourceBuffers() {
437 TracingSessionID last_session_id = 0;
438 FtraceMetadata* metadata = nullptr;
439 InodeFileDataSource* inode_data_source = nullptr;
440 ProcessStatsDataSource* ps_data_source = nullptr;
441
442 // unordered_multimap guarantees that entries with the same key are contiguous
443 // in the iteration.
444 for (auto it = session_data_sources_.begin(); /* check below*/; it++) {
Primiano Tucci674076d2018-10-01 10:41:09 +0100445 // If this is the last iteration or the session id has changed,
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100446 // dispatch the metadata update to the linked data sources, if any.
447 if (it == session_data_sources_.end() || it->first != last_session_id) {
448 bool has_inodes = metadata && !metadata->inode_and_device.empty();
449 bool has_pids = metadata && !metadata->pids.empty();
Lalit Magantia48a9dd2019-05-17 14:08:27 +0100450 bool has_rename_pids = metadata && !metadata->rename_pids.empty();
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100451 if (has_inodes && inode_data_source)
452 inode_data_source->OnInodes(metadata->inode_and_device);
Lalit Magantia48a9dd2019-05-17 14:08:27 +0100453 // Ordering the rename pids before the seen pids is important so that any
454 // renamed processes get scraped in the OnPids call.
455 if (has_rename_pids && ps_data_source)
456 ps_data_source->OnRenamePids(metadata->rename_pids);
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100457 if (has_pids && ps_data_source)
458 ps_data_source->OnPids(metadata->pids);
459 if (metadata)
460 metadata->Clear();
461 metadata = nullptr;
462 inode_data_source = nullptr;
463 ps_data_source = nullptr;
464 if (it == session_data_sources_.end())
465 break;
466 last_session_id = it->first;
467 }
468 ProbesDataSource* ds = it->second;
Primiano Tucci674076d2018-10-01 10:41:09 +0100469 if (!ds->started)
470 continue;
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100471 switch (ds->type_id) {
472 case FtraceDataSource::kTypeId:
473 metadata = static_cast<FtraceDataSource*>(ds)->mutable_metadata();
474 break;
475 case InodeFileDataSource::kTypeId:
476 inode_data_source = static_cast<InodeFileDataSource*>(ds);
477 break;
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700478 case ProcessStatsDataSource::kTypeId: {
479 // A trace session might have declared more than one ps data source.
480 // In those cases we often use one for a full dump on startup (
481 // targeting a dedicated buffer) and another one for on-demand dumps
482 // targeting the main buffer.
483 // Only use the one that has on-demand dumps enabled, if any.
484 auto ps = static_cast<ProcessStatsDataSource*>(ds);
485 if (ps->on_demand_dumps_enabled())
486 ps_data_source = ps;
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100487 break;
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700488 }
Primiano Tucci82a8bfd2018-09-19 11:33:04 +0100489 case SysStatsDataSource::kTypeId:
Primiano Tucci64df2ca2019-01-03 22:26:47 +0000490 case AndroidLogDataSource::kTypeId:
Florian Mayerd1c6a0a2019-04-23 17:54:38 +0100491 case PackagesListDataSource::kTypeId:
Primiano Tuccib02d8dc2019-06-04 11:46:43 +0100492 case MetatraceDataSource::kTypeId:
Primiano Tucci82a8bfd2018-09-19 11:33:04 +0100493 break;
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100494 default:
Florian Mayer6db99a92018-10-18 11:34:55 +0100495 PERFETTO_DFATAL("Invalid data source.");
Primiano Tuccifd8240d2018-08-01 09:34:54 +0100496 } // switch (type_id)
497 } // for (session_data_sources_)
498}
499
Isabelle Taylord404ea12018-02-19 17:28:01 +0000500void ProbesProducer::ConnectWithRetries(const char* socket_name,
501 base::TaskRunner* task_runner) {
502 PERFETTO_DCHECK(state_ == kNotStarted);
503 state_ = kNotConnected;
504
505 ResetConnectionBackoff();
506 socket_name_ = socket_name;
507 task_runner_ = task_runner;
508 Connect();
509}
510
511void ProbesProducer::Connect() {
512 PERFETTO_DCHECK(state_ == kNotConnected);
513 state_ = kConnecting;
Isabelle Taylor86262cb2018-03-27 16:00:54 +0100514 endpoint_ = ProducerIPCClient::Connect(
Primiano Tucci578d7842018-03-29 15:27:05 +0100515 socket_name_, this, "perfetto.traced_probes", task_runner_);
Isabelle Taylord404ea12018-02-19 17:28:01 +0000516}
517
518void ProbesProducer::IncreaseConnectionBackoff() {
519 connection_backoff_ms_ *= 2;
520 if (connection_backoff_ms_ > kMaxConnectionBackoffMs)
521 connection_backoff_ms_ = kMaxConnectionBackoffMs;
522}
523
524void ProbesProducer::ResetConnectionBackoff() {
525 connection_backoff_ms_ = kInitialConnectionBackoffMs;
526}
527
Isabelle Taylord404ea12018-02-19 17:28:01 +0000528} // namespace perfetto