Setup all registered datasources on config change
A producer can have multiple datasources with the same name registered.
This CL makes sure all of them are correctly set up and started after
a config change (previously only the first one was set up).
Bug: crbug.com/1465310
Change-Id: I25de24879106e1412ef537cd008aa3ad7397c1e6
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 154b931..fe593e3 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -1120,6 +1120,14 @@
*cfg_data_source.mutable_producer_name_regex_filter() =
new_producer_name_regex_filter;
+ // Get the list of producers that are already set up.
+ std::unordered_set<uint16_t> set_up_producers;
+ auto& ds_instances = tracing_session->data_source_instances;
+ for (auto instance_it = ds_instances.begin();
+ instance_it != ds_instances.end(); ++instance_it) {
+ set_up_producers.insert(instance_it->first);
+ }
+
// Scan all the registered data sources with a matching name.
auto range = data_sources_.equal_range(cfg_data_source.config().name());
for (auto it = range.first; it != range.second; it++) {
@@ -1134,19 +1142,9 @@
continue;
}
- bool already_setup = false;
- auto& ds_instances = tracing_session->data_source_instances;
- for (auto instance_it = ds_instances.begin();
- instance_it != ds_instances.end(); ++instance_it) {
- if (instance_it->first == it->second.producer_id &&
- instance_it->second.data_source_name ==
- cfg_data_source.config().name()) {
- already_setup = true;
- break;
- }
- }
-
- if (already_setup)
+ // If this producer is already set up, we assume that all datasources
+ // in it started already.
+ if (set_up_producers.count(it->second.producer_id))
continue;
// If it wasn't previously setup, set it up now.
diff --git a/src/tracing/core/tracing_service_impl_unittest.cc b/src/tracing/core/tracing_service_impl_unittest.cc
index 3eb3671..6262db6 100644
--- a/src/tracing/core/tracing_service_impl_unittest.cc
+++ b/src/tracing/core/tracing_service_impl_unittest.cc
@@ -1606,6 +1606,62 @@
Mock::VerifyAndClearExpectations(producer3.get());
}
+TEST_F(TracingServiceImplTest, ProducerNameFilterChangeTwoDataSources) {
+ std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
+ consumer->Connect(svc.get());
+
+ std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
+ producer1->Connect(svc.get(), "mock_producer_1");
+ producer1->RegisterDataSource("data_source");
+
+ std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
+ producer2->Connect(svc.get(), "mock_producer_2");
+ producer2->RegisterDataSource("data_source");
+ producer2->RegisterDataSource("data_source");
+
+ TraceConfig trace_config;
+ trace_config.add_buffers()->set_size_kb(128);
+ auto* data_source = trace_config.add_data_sources();
+ data_source->mutable_config()->set_name("data_source");
+ *data_source->add_producer_name_filter() = "mock_producer_1";
+
+ // Enable tracing with only mock_producer_1 enabled;
+ // the rest should not start up.
+ consumer->EnableTracing(trace_config);
+
+ producer1->WaitForTracingSetup();
+ EXPECT_CALL(*producer1, SetupDataSource(_, _)).Times(1);
+ EXPECT_CALL(*producer1, StartDataSource(_, _)).Times(1);
+
+ task_runner.RunUntilIdle();
+ Mock::VerifyAndClearExpectations(producer1.get());
+ Mock::VerifyAndClearExpectations(producer2.get());
+
+ // Enable mock_producer_2, both instances of "data_source" should start
+ *data_source->add_producer_name_regex_filter() = ".*_producer_[2]";
+ consumer->ChangeTraceConfig(trace_config);
+
+ producer2->WaitForTracingSetup();
+ EXPECT_CALL(*producer2, SetupDataSource(_, _)).Times(2);
+ EXPECT_CALL(*producer2, StartDataSource(_, _)).Times(2);
+
+ task_runner.RunUntilIdle();
+ Mock::VerifyAndClearExpectations(producer1.get());
+ Mock::VerifyAndClearExpectations(producer2.get());
+
+ consumer->DisableTracing();
+ consumer->FreeBuffers();
+
+ EXPECT_CALL(*producer1, StopDataSource(_)).Times(1);
+ EXPECT_CALL(*producer2, StopDataSource(_)).Times(2);
+
+ consumer->WaitForTracingDisabled();
+
+ task_runner.RunUntilIdle();
+ Mock::VerifyAndClearExpectations(producer1.get());
+ Mock::VerifyAndClearExpectations(producer2.get());
+}
+
TEST_F(TracingServiceImplTest, DisconnectConsumerWhileTracing) {
std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
consumer->Connect(svc.get());