Merge "trace_processor: show cpu_frequency_limits ftrace event on Perfetto UI"
diff --git a/Android.bp b/Android.bp
index f3ebaa9..ff943ad 100644
--- a/Android.bp
+++ b/Android.bp
@@ -223,10 +223,8 @@
srcs: [
":perfetto_include_perfetto_base_base",
":perfetto_include_perfetto_ext_base_base",
- ":perfetto_include_perfetto_profiling_normalize",
":perfetto_src_base_base",
":perfetto_src_base_unix_socket",
- ":perfetto_src_profiling_common_proc_utils",
":perfetto_src_profiling_memory_client",
":perfetto_src_profiling_memory_client_api",
":perfetto_src_profiling_memory_ring_buffer",
@@ -1931,6 +1929,7 @@
"protos/perfetto/common/commit_data_request.proto",
"protos/perfetto/common/data_source_descriptor.proto",
"protos/perfetto/common/descriptor.proto",
+ "protos/perfetto/common/ftrace_descriptor.proto",
"protos/perfetto/common/gpu_counter_descriptor.proto",
"protos/perfetto/common/interceptor_descriptor.proto",
"protos/perfetto/common/observable_events.proto",
@@ -1953,6 +1952,7 @@
"external/perfetto/protos/perfetto/common/commit_data_request.gen.cc",
"external/perfetto/protos/perfetto/common/data_source_descriptor.gen.cc",
"external/perfetto/protos/perfetto/common/descriptor.gen.cc",
+ "external/perfetto/protos/perfetto/common/ftrace_descriptor.gen.cc",
"external/perfetto/protos/perfetto/common/gpu_counter_descriptor.gen.cc",
"external/perfetto/protos/perfetto/common/interceptor_descriptor.gen.cc",
"external/perfetto/protos/perfetto/common/observable_events.gen.cc",
@@ -1975,6 +1975,7 @@
"protos/perfetto/common/commit_data_request.proto",
"protos/perfetto/common/data_source_descriptor.proto",
"protos/perfetto/common/descriptor.proto",
+ "protos/perfetto/common/ftrace_descriptor.proto",
"protos/perfetto/common/gpu_counter_descriptor.proto",
"protos/perfetto/common/interceptor_descriptor.proto",
"protos/perfetto/common/observable_events.proto",
@@ -1997,6 +1998,7 @@
"external/perfetto/protos/perfetto/common/commit_data_request.gen.h",
"external/perfetto/protos/perfetto/common/data_source_descriptor.gen.h",
"external/perfetto/protos/perfetto/common/descriptor.gen.h",
+ "external/perfetto/protos/perfetto/common/ftrace_descriptor.gen.h",
"external/perfetto/protos/perfetto/common/gpu_counter_descriptor.gen.h",
"external/perfetto/protos/perfetto/common/interceptor_descriptor.gen.h",
"external/perfetto/protos/perfetto/common/observable_events.gen.h",
@@ -2023,6 +2025,7 @@
"protos/perfetto/common/commit_data_request.proto",
"protos/perfetto/common/data_source_descriptor.proto",
"protos/perfetto/common/descriptor.proto",
+ "protos/perfetto/common/ftrace_descriptor.proto",
"protos/perfetto/common/gpu_counter_descriptor.proto",
"protos/perfetto/common/interceptor_descriptor.proto",
"protos/perfetto/common/observable_events.proto",
@@ -2044,6 +2047,7 @@
"external/perfetto/protos/perfetto/common/commit_data_request.pb.cc",
"external/perfetto/protos/perfetto/common/data_source_descriptor.pb.cc",
"external/perfetto/protos/perfetto/common/descriptor.pb.cc",
+ "external/perfetto/protos/perfetto/common/ftrace_descriptor.pb.cc",
"external/perfetto/protos/perfetto/common/gpu_counter_descriptor.pb.cc",
"external/perfetto/protos/perfetto/common/interceptor_descriptor.pb.cc",
"external/perfetto/protos/perfetto/common/observable_events.pb.cc",
@@ -2066,6 +2070,7 @@
"protos/perfetto/common/commit_data_request.proto",
"protos/perfetto/common/data_source_descriptor.proto",
"protos/perfetto/common/descriptor.proto",
+ "protos/perfetto/common/ftrace_descriptor.proto",
"protos/perfetto/common/gpu_counter_descriptor.proto",
"protos/perfetto/common/interceptor_descriptor.proto",
"protos/perfetto/common/observable_events.proto",
@@ -2087,6 +2092,7 @@
"external/perfetto/protos/perfetto/common/commit_data_request.pb.h",
"external/perfetto/protos/perfetto/common/data_source_descriptor.pb.h",
"external/perfetto/protos/perfetto/common/descriptor.pb.h",
+ "external/perfetto/protos/perfetto/common/ftrace_descriptor.pb.h",
"external/perfetto/protos/perfetto/common/gpu_counter_descriptor.pb.h",
"external/perfetto/protos/perfetto/common/interceptor_descriptor.pb.h",
"external/perfetto/protos/perfetto/common/observable_events.pb.h",
@@ -2113,6 +2119,7 @@
"protos/perfetto/common/commit_data_request.proto",
"protos/perfetto/common/data_source_descriptor.proto",
"protos/perfetto/common/descriptor.proto",
+ "protos/perfetto/common/ftrace_descriptor.proto",
"protos/perfetto/common/gpu_counter_descriptor.proto",
"protos/perfetto/common/interceptor_descriptor.proto",
"protos/perfetto/common/observable_events.proto",
@@ -2135,6 +2142,7 @@
"external/perfetto/protos/perfetto/common/commit_data_request.pbzero.cc",
"external/perfetto/protos/perfetto/common/data_source_descriptor.pbzero.cc",
"external/perfetto/protos/perfetto/common/descriptor.pbzero.cc",
+ "external/perfetto/protos/perfetto/common/ftrace_descriptor.pbzero.cc",
"external/perfetto/protos/perfetto/common/gpu_counter_descriptor.pbzero.cc",
"external/perfetto/protos/perfetto/common/interceptor_descriptor.pbzero.cc",
"external/perfetto/protos/perfetto/common/observable_events.pbzero.cc",
@@ -2157,6 +2165,7 @@
"protos/perfetto/common/commit_data_request.proto",
"protos/perfetto/common/data_source_descriptor.proto",
"protos/perfetto/common/descriptor.proto",
+ "protos/perfetto/common/ftrace_descriptor.proto",
"protos/perfetto/common/gpu_counter_descriptor.proto",
"protos/perfetto/common/interceptor_descriptor.proto",
"protos/perfetto/common/observable_events.proto",
@@ -2179,6 +2188,7 @@
"external/perfetto/protos/perfetto/common/commit_data_request.pbzero.h",
"external/perfetto/protos/perfetto/common/data_source_descriptor.pbzero.h",
"external/perfetto/protos/perfetto/common/descriptor.pbzero.h",
+ "external/perfetto/protos/perfetto/common/ftrace_descriptor.pbzero.h",
"external/perfetto/protos/perfetto/common/gpu_counter_descriptor.pbzero.h",
"external/perfetto/protos/perfetto/common/interceptor_descriptor.pbzero.h",
"external/perfetto/protos/perfetto/common/observable_events.pbzero.h",
@@ -2391,6 +2401,7 @@
"protos/perfetto/common/commit_data_request.proto",
"protos/perfetto/common/data_source_descriptor.proto",
"protos/perfetto/common/descriptor.proto",
+ "protos/perfetto/common/ftrace_descriptor.proto",
"protos/perfetto/common/gpu_counter_descriptor.proto",
"protos/perfetto/common/interceptor_descriptor.proto",
"protos/perfetto/common/observable_events.proto",
@@ -2921,21 +2932,6 @@
],
}
-// GN: //protos/perfetto/config:merged_config_descriptor
-genrule {
- name: "perfetto_protos_perfetto_config_merged_config_descriptor",
- srcs: [
- "protos/perfetto/config/perfetto_config.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --descriptor_set_out=$(out) $(in)",
- out: [
- "perfetto_protos_perfetto_config_merged_config_descriptor.bin",
- ],
-}
-
// GN: //protos/perfetto/config/power:cpp
genrule {
name: "perfetto_protos_perfetto_config_power_cpp_gen",
@@ -4094,6 +4090,7 @@
"protos/perfetto/common/commit_data_request.proto",
"protos/perfetto/common/data_source_descriptor.proto",
"protos/perfetto/common/descriptor.proto",
+ "protos/perfetto/common/ftrace_descriptor.proto",
"protos/perfetto/common/gpu_counter_descriptor.proto",
"protos/perfetto/common/interceptor_descriptor.proto",
"protos/perfetto/common/observable_events.proto",
@@ -7221,11 +7218,11 @@
genrule {
name: "perfetto_src_perfetto_cmd_gen_cc_config_descriptor",
srcs: [
- ":perfetto_protos_perfetto_config_merged_config_descriptor",
+ ":perfetto_protos_perfetto_config_descriptor",
],
cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
out: [
- "src/perfetto_cmd/perfetto_config.descriptor.h",
+ "src/perfetto_cmd/config.descriptor.h",
],
tool_files: [
"tools/gen_cc_proto_descriptor.py",
@@ -9217,14 +9214,6 @@
],
}
-// GN: //tools/trace_to_text:unittests
-filegroup {
- name: "perfetto_tools_trace_to_text_unittests",
- srcs: [
- "tools/trace_to_text/trace_to_text_unittest.cc",
- ],
-}
-
// GN: //tools/trace_to_text:utils
filegroup {
name: "perfetto_tools_trace_to_text_utils",
@@ -9495,7 +9484,6 @@
":perfetto_src_profiling_perf_producer_unittests",
":perfetto_src_profiling_perf_regs_parsing",
":perfetto_src_profiling_perf_unwinding",
- ":perfetto_src_profiling_symbolizer_symbolize_database",
":perfetto_src_profiling_symbolizer_symbolizer",
":perfetto_src_profiling_symbolizer_unittests",
":perfetto_src_profiling_unittests",
@@ -9596,9 +9584,6 @@
":perfetto_src_tracing_test_tracing_integration_test",
":perfetto_src_tracing_unittests",
":perfetto_tools_sanitizers_unittests_sanitizers_unittests",
- ":perfetto_tools_trace_to_text_trace_to_text_lib",
- ":perfetto_tools_trace_to_text_unittests",
- ":perfetto_tools_trace_to_text_utils",
],
shared_libs: [
"libandroidicu",
@@ -9724,7 +9709,6 @@
"perfetto_src_traced_probes_ftrace_test_messages_cpp_gen_headers",
"perfetto_src_traced_probes_ftrace_test_messages_lite_gen_headers",
"perfetto_src_traced_probes_ftrace_test_messages_zero_gen_headers",
- "perfetto_tools_trace_to_text_gen_cc_trace_descriptor",
],
defaults: [
"perfetto_defaults",
diff --git a/BUILD b/BUILD
index 283d9ce..7e47fd9 100644
--- a/BUILD
+++ b/BUILD
@@ -787,10 +787,10 @@
perfetto_cc_proto_descriptor(
name = "src_perfetto_cmd_gen_cc_config_descriptor",
deps = [
- ":protos_perfetto_config_merged_config_descriptor",
+ ":protos_perfetto_config_descriptor",
],
outs = [
- "src/perfetto_cmd/perfetto_config.descriptor.h",
+ "src/perfetto_cmd/config.descriptor.h",
],
)
@@ -1974,17 +1974,118 @@
# Proto libraries
# ##############################################################################
-# GN target: //protos/perfetto/common:cpp
-perfetto_cc_protocpp_library(
- name = "protos_perfetto_common_cpp",
+# GN target: [//protos/perfetto/config:source_set]
+perfetto_proto_library(
+ name = "config_proto",
+ visibility = PERFETTO_CONFIG.public_visibility,
deps = [
":protos_perfetto_common_protos",
+ ":protos_perfetto_config_android_protos",
+ ":protos_perfetto_config_ftrace_protos",
+ ":protos_perfetto_config_gpu_protos",
+ ":protos_perfetto_config_inode_file_protos",
+ ":protos_perfetto_config_interceptors_protos",
+ ":protos_perfetto_config_power_protos",
+ ":protos_perfetto_config_process_stats_protos",
+ ":protos_perfetto_config_profiling_protos",
+ ":protos_perfetto_config_protos",
+ ":protos_perfetto_config_sys_stats_protos",
+ ":protos_perfetto_config_track_event_protos",
],
)
-# GN target: //protos/perfetto/common:lite
+# GN target: [//protos/perfetto/config:source_set]
perfetto_cc_proto_library(
- name = "protos_perfetto_common_lite",
+ name = "config_cc_proto",
+ visibility = PERFETTO_CONFIG.public_visibility,
+ deps = [
+ ":config_proto",
+ ],
+)
+
+# GN target: [//protos/perfetto/config:source_set]
+perfetto_java_proto_library(
+ name = "config_java_proto",
+ visibility = PERFETTO_CONFIG.public_visibility,
+ deps = [
+ ":config_proto",
+ ],
+)
+
+# GN target: [//protos/perfetto/config:source_set]
+perfetto_java_lite_proto_library(
+ name = "config_java_proto_lite",
+ visibility = PERFETTO_CONFIG.public_visibility,
+ deps = [
+ ":config_proto",
+ ],
+)
+
+# GN target: [//protos/perfetto/trace:non_minimal_source_set, //protos/perfetto/trace:minimal_source_set]
+perfetto_proto_library(
+ name = "trace_proto",
+ visibility = PERFETTO_CONFIG.public_visibility,
+ deps = [
+ ":protos_perfetto_common_protos",
+ ":protos_perfetto_config_android_protos",
+ ":protos_perfetto_config_ftrace_protos",
+ ":protos_perfetto_config_gpu_protos",
+ ":protos_perfetto_config_inode_file_protos",
+ ":protos_perfetto_config_interceptors_protos",
+ ":protos_perfetto_config_power_protos",
+ ":protos_perfetto_config_process_stats_protos",
+ ":protos_perfetto_config_profiling_protos",
+ ":protos_perfetto_config_protos",
+ ":protos_perfetto_config_sys_stats_protos",
+ ":protos_perfetto_config_track_event_protos",
+ ":protos_perfetto_trace_android_protos",
+ ":protos_perfetto_trace_chrome_protos",
+ ":protos_perfetto_trace_filesystem_protos",
+ ":protos_perfetto_trace_ftrace_protos",
+ ":protos_perfetto_trace_gpu_protos",
+ ":protos_perfetto_trace_interned_data_protos",
+ ":protos_perfetto_trace_minimal_protos",
+ ":protos_perfetto_trace_non_minimal_protos",
+ ":protos_perfetto_trace_perfetto_protos",
+ ":protos_perfetto_trace_power_protos",
+ ":protos_perfetto_trace_profiling_protos",
+ ":protos_perfetto_trace_ps_protos",
+ ":protos_perfetto_trace_sys_stats_protos",
+ ":protos_perfetto_trace_system_info_protos",
+ ":protos_perfetto_trace_track_event_protos",
+ ],
+)
+
+# GN target: [//protos/perfetto/trace:non_minimal_source_set, //protos/perfetto/trace:minimal_source_set]
+perfetto_cc_proto_library(
+ name = "trace_cc_proto",
+ visibility = PERFETTO_CONFIG.public_visibility,
+ deps = [
+ ":trace_proto",
+ ],
+)
+
+# GN target: [//protos/perfetto/trace:non_minimal_source_set, //protos/perfetto/trace:minimal_source_set]
+perfetto_java_proto_library(
+ name = "trace_java_proto",
+ visibility = PERFETTO_CONFIG.public_visibility,
+ deps = [
+ ":trace_proto",
+ ],
+)
+
+# GN target: [//protos/perfetto/trace:non_minimal_source_set, //protos/perfetto/trace:minimal_source_set]
+perfetto_java_lite_proto_library(
+ name = "trace_java_proto_lite",
+ visibility = PERFETTO_CONFIG.public_visibility,
+ deps = [
+ ":trace_proto",
+ ],
+)
+
+# GN target: //protos/perfetto/common:cpp
+perfetto_cc_protocpp_library(
+ name = "protos_perfetto_common_cpp",
deps = [
":protos_perfetto_common_protos",
],
@@ -2000,6 +2101,7 @@
"protos/perfetto/common/commit_data_request.proto",
"protos/perfetto/common/data_source_descriptor.proto",
"protos/perfetto/common/descriptor.proto",
+ "protos/perfetto/common/ftrace_descriptor.proto",
"protos/perfetto/common/gpu_counter_descriptor.proto",
"protos/perfetto/common/interceptor_descriptor.proto",
"protos/perfetto/common/observable_events.proto",
@@ -2032,14 +2134,6 @@
],
)
-# GN target: //protos/perfetto/config/android:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_config_android_lite",
- deps = [
- ":protos_perfetto_config_android_protos",
- ],
-)
-
# GN target: //protos/perfetto/config/android:source_set
perfetto_proto_library(
name = "protos_perfetto_config_android_protos",
@@ -2103,14 +2197,6 @@
],
)
-# GN target: //protos/perfetto/config/ftrace:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_config_ftrace_lite",
- deps = [
- ":protos_perfetto_config_ftrace_protos",
- ],
-)
-
# GN target: //protos/perfetto/config/ftrace:source_set
perfetto_proto_library(
name = "protos_perfetto_config_ftrace_protos",
@@ -2138,14 +2224,6 @@
],
)
-# GN target: //protos/perfetto/config/gpu:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_config_gpu_lite",
- deps = [
- ":protos_perfetto_config_gpu_protos",
- ],
-)
-
# GN target: //protos/perfetto/config/gpu:source_set
perfetto_proto_library(
name = "protos_perfetto_config_gpu_protos",
@@ -2174,14 +2252,6 @@
],
)
-# GN target: //protos/perfetto/config/inode_file:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_config_inode_file_lite",
- deps = [
- ":protos_perfetto_config_inode_file_protos",
- ],
-)
-
# GN target: //protos/perfetto/config/inode_file:source_set
perfetto_proto_library(
name = "protos_perfetto_config_inode_file_protos",
@@ -2210,14 +2280,6 @@
],
)
-# GN target: //protos/perfetto/config/interceptors:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_config_interceptors_lite",
- deps = [
- ":protos_perfetto_config_interceptors_protos",
- ],
-)
-
# GN target: //protos/perfetto/config/interceptors:source_set
perfetto_proto_library(
name = "protos_perfetto_config_interceptors_protos",
@@ -2241,34 +2303,6 @@
],
)
-# GN target: //protos/perfetto/config:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_config_lite",
- deps = [
- ":protos_perfetto_config_protos",
- ],
-)
-
-# GN target: //protos/perfetto/config:merged_config_descriptor
-perfetto_proto_descriptor(
- name = "protos_perfetto_config_merged_config_descriptor",
- deps = [
- ":protos_perfetto_config_merged_config_protos",
- ],
- outs = [
- "protos_perfetto_config_merged_config_descriptor.bin",
- ],
-)
-
-# GN target: //protos/perfetto/config:merged_config_source_set
-perfetto_proto_library(
- name = "protos_perfetto_config_merged_config_protos",
- srcs = [
- "protos/perfetto/config/perfetto_config.proto",
- ],
- visibility = PERFETTO_CONFIG.public_visibility,
-)
-
# GN target: //protos/perfetto/config/power:cpp
perfetto_cc_protocpp_library(
name = "protos_perfetto_config_power_cpp",
@@ -2277,14 +2311,6 @@
],
)
-# GN target: //protos/perfetto/config/power:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_config_power_lite",
- deps = [
- ":protos_perfetto_config_power_protos",
- ],
-)
-
# GN target: //protos/perfetto/config/power:source_set
perfetto_proto_library(
name = "protos_perfetto_config_power_protos",
@@ -2312,14 +2338,6 @@
],
)
-# GN target: //protos/perfetto/config/process_stats:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_config_process_stats_lite",
- deps = [
- ":protos_perfetto_config_process_stats_protos",
- ],
-)
-
# GN target: //protos/perfetto/config/process_stats:source_set
perfetto_proto_library(
name = "protos_perfetto_config_process_stats_protos",
@@ -2348,14 +2366,6 @@
],
)
-# GN target: //protos/perfetto/config/profiling:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_config_profiling_lite",
- deps = [
- ":protos_perfetto_config_profiling_protos",
- ],
-)
-
# GN target: //protos/perfetto/config/profiling:source_set
perfetto_proto_library(
name = "protos_perfetto_config_profiling_protos",
@@ -2392,7 +2402,9 @@
"protos/perfetto/config/test_config.proto",
"protos/perfetto/config/trace_config.proto",
],
- visibility = PERFETTO_CONFIG.public_visibility,
+ visibility = [
+ PERFETTO_CONFIG.proto_library_visibility,
+ ],
deps = [
":protos_perfetto_common_protos",
":protos_perfetto_config_android_protos",
@@ -2417,14 +2429,6 @@
],
)
-# GN target: //protos/perfetto/config/sys_stats:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_config_sys_stats_lite",
- deps = [
- ":protos_perfetto_config_sys_stats_protos",
- ],
-)
-
# GN target: //protos/perfetto/config/sys_stats:source_set
perfetto_proto_library(
name = "protos_perfetto_config_sys_stats_protos",
@@ -2456,14 +2460,6 @@
],
)
-# GN target: //protos/perfetto/config/track_event:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_config_track_event_lite",
- deps = [
- ":protos_perfetto_config_track_event_protos",
- ],
-)
-
# GN target: //protos/perfetto/config/track_event:source_set
perfetto_proto_library(
name = "protos_perfetto_config_track_event_protos",
@@ -2638,7 +2634,9 @@
"protos/perfetto/metrics/android/trace_quality.proto",
"protos/perfetto/metrics/android/unsymbolized_frames.proto",
],
- visibility = PERFETTO_CONFIG.public_visibility,
+ visibility = [
+ PERFETTO_CONFIG.proto_library_visibility,
+ ],
)
# GN target: //protos/perfetto/metrics/chrome:descriptor
@@ -2720,14 +2718,6 @@
],
)
-# GN target: //protos/perfetto/trace/android:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_android_lite",
- deps = [
- ":protos_perfetto_trace_android_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/android:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_android_protos",
@@ -2757,14 +2747,6 @@
],
)
-# GN target: //protos/perfetto/trace/chrome:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_chrome_lite",
- deps = [
- ":protos_perfetto_trace_chrome_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/chrome:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_chrome_protos",
@@ -2797,14 +2779,6 @@
],
)
-# GN target: //protos/perfetto/trace/filesystem:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_filesystem_lite",
- deps = [
- ":protos_perfetto_trace_filesystem_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/filesystem:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_filesystem_protos",
@@ -2824,14 +2798,6 @@
],
)
-# GN target: //protos/perfetto/trace/ftrace:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_ftrace_lite",
- deps = [
- ":protos_perfetto_trace_ftrace_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/ftrace:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_ftrace_protos",
@@ -2899,14 +2865,6 @@
],
)
-# GN target: //protos/perfetto/trace/gpu:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_gpu_lite",
- deps = [
- ":protos_perfetto_trace_gpu_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/gpu:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_gpu_protos",
@@ -2934,14 +2892,6 @@
],
)
-# GN target: //protos/perfetto/trace/interned_data:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_interned_data_lite",
- deps = [
- ":protos_perfetto_trace_interned_data_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/interned_data:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_interned_data_protos",
@@ -2971,23 +2921,6 @@
],
)
-# GN target: //protos/perfetto/trace:merged_trace_source_set
-perfetto_proto_library(
- name = "protos_perfetto_trace_merged_trace_protos",
- srcs = [
- "protos/perfetto/trace/perfetto_trace.proto",
- ],
- visibility = PERFETTO_CONFIG.public_visibility,
-)
-
-# GN target: //protos/perfetto/trace:minimal_lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_minimal_lite",
- deps = [
- ":protos_perfetto_trace_minimal_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace:minimal_source_set
perfetto_proto_library(
name = "protos_perfetto_trace_minimal_protos",
@@ -3035,14 +2968,6 @@
],
)
-# GN target: //protos/perfetto/trace:non_minimal_lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_non_minimal_lite",
- deps = [
- ":protos_perfetto_trace_non_minimal_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace:non_minimal_source_set
perfetto_proto_library(
name = "protos_perfetto_trace_non_minimal_protos",
@@ -3056,7 +2981,9 @@
"protos/perfetto/trace/trace_packet_defaults.proto",
"protos/perfetto/trace/ui_state.proto",
],
- visibility = PERFETTO_CONFIG.public_visibility,
+ visibility = [
+ PERFETTO_CONFIG.proto_library_visibility,
+ ],
deps = [
":protos_perfetto_common_protos",
":protos_perfetto_config_android_protos",
@@ -3124,14 +3051,6 @@
],
)
-# GN target: //protos/perfetto/trace/perfetto:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_perfetto_lite",
- deps = [
- ":protos_perfetto_trace_perfetto_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/perfetto:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_perfetto_protos",
@@ -3152,14 +3071,6 @@
],
)
-# GN target: //protos/perfetto/trace/power:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_power_lite",
- deps = [
- ":protos_perfetto_trace_power_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/power:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_power_protos",
@@ -3227,14 +3138,6 @@
],
)
-# GN target: //protos/perfetto/trace/profiling:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_profiling_lite",
- deps = [
- ":protos_perfetto_trace_profiling_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/profiling:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_profiling_protos",
@@ -3262,14 +3165,6 @@
],
)
-# GN target: //protos/perfetto/trace/ps:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_ps_lite",
- deps = [
- ":protos_perfetto_trace_ps_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/ps:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_ps_protos",
@@ -3290,14 +3185,6 @@
],
)
-# GN target: //protos/perfetto/trace/sys_stats:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_sys_stats_lite",
- deps = [
- ":protos_perfetto_trace_sys_stats_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/sys_stats:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_sys_stats_protos",
@@ -3321,14 +3208,6 @@
],
)
-# GN target: //protos/perfetto/trace/system_info:lite
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_system_info_lite",
- deps = [
- ":protos_perfetto_trace_system_info_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/system_info:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_system_info_protos",
@@ -4066,6 +3945,7 @@
deps = [
":protos_perfetto_metrics_protos",
],
+ visibility = PERFETTO_CONFIG.public_visibility,
)
perfetto_java_proto_library(
@@ -4073,27 +3953,7 @@
deps = [
":protos_perfetto_metrics_android_protos",
],
-)
-
-perfetto_java_proto_library(
- name = "protos_perfetto_trace_merged_trace_java",
- deps = [
- ":protos_perfetto_trace_merged_trace_protos",
- ],
-)
-
-perfetto_java_proto_library(
- name = "protos_perfetto_config_merged_config_java",
- deps = [
- ":protos_perfetto_config_merged_config_protos",
- ],
-)
-
-perfetto_java_lite_proto_library(
- name = "protos_perfetto_config_merged_config_java_lite",
- deps = [
- ":protos_perfetto_config_merged_config_protos",
- ],
+ visibility = PERFETTO_CONFIG.public_visibility,
)
perfetto_gensignature_internal_only(
diff --git a/BUILD.extras b/BUILD.extras
index f91b2f4..dbf18af 100644
--- a/BUILD.extras
+++ b/BUILD.extras
@@ -36,6 +36,7 @@
deps = [
":protos_perfetto_metrics_protos",
],
+ visibility = PERFETTO_CONFIG.public_visibility,
)
perfetto_java_proto_library(
@@ -43,27 +44,7 @@
deps = [
":protos_perfetto_metrics_android_protos",
],
-)
-
-perfetto_java_proto_library(
- name = "protos_perfetto_trace_merged_trace_java",
- deps = [
- ":protos_perfetto_trace_merged_trace_protos",
- ],
-)
-
-perfetto_java_proto_library(
- name = "protos_perfetto_config_merged_config_java",
- deps = [
- ":protos_perfetto_config_merged_config_protos",
- ],
-)
-
-perfetto_java_lite_proto_library(
- name = "protos_perfetto_config_merged_config_java_lite",
- deps = [
- ":protos_perfetto_config_merged_config_protos",
- ],
+ visibility = PERFETTO_CONFIG.public_visibility,
)
perfetto_gensignature_internal_only(
diff --git a/BUILD.gn b/BUILD.gn
index 53b8d9a..33f8818 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -134,7 +134,6 @@
"test/configs",
# For syntax-checking the protos.
- "protos/perfetto/config:merged_config_lite",
"protos/perfetto/trace:merged_trace_lite",
# For checking all generated xxx.gen.{cc,h} files without waiting for
diff --git a/CHANGELOG b/CHANGELOG
index ebad664..02ab1f8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
Unreleased:
Tracing service and probes:
- *
+ * Removed merged trace and config protos from Bazel. Embedder should
+ instead depend on the non-merged proto targets.
Trace Processor:
*
UI:
diff --git a/gn/perfetto_unittests.gni b/gn/perfetto_unittests.gni
index dbfa0fa..dec85bc 100644
--- a/gn/perfetto_unittests.gni
+++ b/gn/perfetto_unittests.gni
@@ -80,7 +80,10 @@
if (enable_perfetto_trace_processor) {
perfetto_unittests_targets += [ "src/trace_processor:unittests" ]
- perfetto_unittests_targets += [ "tools/trace_to_text:unittests" ]
+
+ # TODO(mohitms): reenable this once we no longer link lite and full protobuf
+ # simultaneously.
+ # perfetto_unittests_targets += [ "tools/trace_to_text:unittests" ]
if (enable_perfetto_trace_processor_sqlite) {
perfetto_unittests_targets += [ "src/trace_processor/metrics:unittests" ]
diff --git a/include/perfetto/ext/base/string_utils.h b/include/perfetto/ext/base/string_utils.h
index 58444a8..593204f 100644
--- a/include/perfetto/ext/base/string_utils.h
+++ b/include/perfetto/ext/base/string_utils.h
@@ -124,7 +124,6 @@
std::string ReplaceAll(std::string str,
const std::string& to_replace,
const std::string& replacement);
-std::string TrimLeading(const std::string& str);
// A BSD-style strlcpy without the return value.
// Copies at most |dst_size|-1 characters. Unlike strncpy, it always \0
diff --git a/include/perfetto/ext/base/subprocess.h b/include/perfetto/ext/base/subprocess.h
index 80adbdc..cca6c29 100644
--- a/include/perfetto/ext/base/subprocess.h
+++ b/include/perfetto/ext/base/subprocess.h
@@ -106,13 +106,18 @@
// This includes crashes or other signals on UNIX.
};
- enum OutputMode {
+ enum class OutputMode {
kInherit = 0, // Inherit's the caller process stdout/stderr.
- kDevNull, // dup() onto /dev/null
+ kDevNull, // dup() onto /dev/null.
kBuffer, // dup() onto a pipe and move it into the output() buffer.
kFd, // dup() onto the passed args.fd.
};
+ enum class InputMode {
+ kBuffer = 0, // dup() onto a pipe and write args.input on it.
+ kDevNull, // dup() onto /dev/null.
+ };
+
// Input arguments for configuring the subprocess behavior.
struct Args {
Args(std::initializer_list<std::string> _cmd = {}) : exec_cmd(_cmd) {}
@@ -149,11 +154,13 @@
// The file descriptors in this list will not be closed.
std::vector<int> preserve_fds;
- // The data to push in the child process stdin.
+ // The data to push in the child process stdin, if input_mode ==
+ // InputMode::kBuffer.
std::string input;
- OutputMode stdout_mode = kInherit;
- OutputMode stderr_mode = kInherit;
+ InputMode stdin_mode = InputMode::kBuffer;
+ OutputMode stdout_mode = OutputMode::kInherit;
+ OutputMode stderr_mode = OutputMode::kInherit;
base::ScopedPlatformHandle out_fd;
@@ -213,7 +220,7 @@
bool timed_out() const { return s_->timed_out; }
// This contains both stdout and stderr (if the corresponding _mode ==
- // kBuffer). It's non-const so the caller can std::move() it.
+ // OutputMode::kBuffer). It's non-const so the caller can std::move() it.
std::string& output() { return s_->output; }
const std::string& output() const { return s_->output; }
@@ -236,7 +243,7 @@
PlatformProcessId pid;
Status status = kNotStarted;
int returncode = -1;
- std::string output; // Stdin+stderr. Only when kBuffer.
+ std::string output; // Stdin+stderr. Only when OutputMode::kBuffer.
std::unique_ptr<ResourceUsage> rusage{new ResourceUsage()};
bool timed_out = false;
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/infra/luci/recipe_modules/macos_sdk/__init__.py b/infra/luci/recipe_modules/macos_sdk/__init__.py
index 801083d..6a20ec1 100644
--- a/infra/luci/recipe_modules/macos_sdk/__init__.py
+++ b/infra/luci/recipe_modules/macos_sdk/__init__.py
@@ -44,7 +44,7 @@
),
default={
'sdk_version':
- '12D4e',
+ '13C5066c',
'tool_package':
'infra/tools/mac_toolchain/${platform}',
'tool_version':
diff --git a/infra/luci/recipe_modules/macos_sdk/examples/full.expected/mac.json b/infra/luci/recipe_modules/macos_sdk/examples/full.expected/mac.json
index 2f31aaa..7d0f197 100644
--- a/infra/luci/recipe_modules/macos_sdk/examples/full.expected/mac.json
+++ b/infra/luci/recipe_modules/macos_sdk/examples/full.expected/mac.json
@@ -35,7 +35,7 @@
"-kind",
"mac",
"-xcode-version",
- "12d4e",
+ "13c5066c",
"-output-dir",
"[CACHE]/macos_sdk/XCode.app"
],
diff --git a/infra/luci/recipes/perfetto.expected/ci_mac.json b/infra/luci/recipes/perfetto.expected/ci_mac.json
index 33125de..4c9f89f 100644
--- a/infra/luci/recipes/perfetto.expected/ci_mac.json
+++ b/infra/luci/recipes/perfetto.expected/ci_mac.json
@@ -125,7 +125,7 @@
"-kind",
"mac",
"-xcode-version",
- "12d4e",
+ "13c5066c",
"-output-dir",
"[CACHE]/macos_sdk/XCode.app"
],
@@ -677,7 +677,7 @@
"-kind",
"mac",
"-xcode-version",
- "12d4e",
+ "13c5066c",
"-output-dir",
"[CACHE]/macos_sdk/XCode.app"
],
diff --git a/protos/perfetto/common/BUILD.gn b/protos/perfetto/common/BUILD.gn
index 1af189d..5ecc0de 100644
--- a/protos/perfetto/common/BUILD.gn
+++ b/protos/perfetto/common/BUILD.gn
@@ -25,6 +25,7 @@
"commit_data_request.proto",
"data_source_descriptor.proto",
"descriptor.proto",
+ "ftrace_descriptor.proto",
"gpu_counter_descriptor.proto",
"interceptor_descriptor.proto",
"observable_events.proto",
diff --git a/protos/perfetto/common/data_source_descriptor.proto b/protos/perfetto/common/data_source_descriptor.proto
index 2cdace2..dc2d742 100644
--- a/protos/perfetto/common/data_source_descriptor.proto
+++ b/protos/perfetto/common/data_source_descriptor.proto
@@ -18,6 +18,7 @@
package perfetto.protos;
+import "protos/perfetto/common/ftrace_descriptor.proto";
import "protos/perfetto/common/gpu_counter_descriptor.proto";
import "protos/perfetto/common/track_event_descriptor.proto";
@@ -54,4 +55,6 @@
optional GpuCounterDescriptor gpu_counter_descriptor = 5 [lazy = true];
optional TrackEventDescriptor track_event_descriptor = 6 [lazy = true];
+
+ optional FtraceDescriptor ftrace_descriptor = 8 [lazy = true];
}
diff --git a/protos/perfetto/common/ftrace_descriptor.proto b/protos/perfetto/common/ftrace_descriptor.proto
new file mode 100644
index 0000000..5406d6d
--- /dev/null
+++ b/protos/perfetto/common/ftrace_descriptor.proto
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package perfetto.protos;
+
+message FtraceDescriptor {
+ message AtraceCategory {
+ optional string name = 1;
+ optional string description = 2;
+ }
+
+ // Report the available atrace categories.
+ //
+ // Used by Traceur via `perfetto --query`.
+ repeated AtraceCategory atrace_categories = 1;
+}
diff --git a/protos/perfetto/config/BUILD.gn b/protos/perfetto/config/BUILD.gn
index 471bfbe..4b96859 100644
--- a/protos/perfetto/config/BUILD.gn
+++ b/protos/perfetto/config/BUILD.gn
@@ -49,20 +49,3 @@
deps = [ ":source_set" ]
sources = [ "trace_config.proto" ]
}
-
-# This target is not used in the tree and is built only to guarantee that the
-# autogenerated merged proto has a valid syntax.
-perfetto_proto_library("merged_config_@TYPE@") {
- proto_generators = [
- "lite",
- "source_set",
- ]
- sources = [ "perfetto_config.proto" ]
-}
-
-perfetto_proto_library("merged_config_descriptor") {
- proto_generators = [ "descriptor" ]
- generate_descriptor = "perfetto_config.descriptor"
- sources = [ "perfetto_config.proto" ]
- deps = [ ":merged_config_source_set" ]
-}
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index 30195a4..5674f7a 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -13,6 +13,22 @@
option go_package = "github.com/google/perfetto/perfetto_proto";
+// Begin of protos/perfetto/common/ftrace_descriptor.proto
+
+message FtraceDescriptor {
+ message AtraceCategory {
+ optional string name = 1;
+ optional string description = 2;
+ }
+
+ // Report the available atrace categories.
+ //
+ // Used by Traceur via `perfetto --query`.
+ repeated AtraceCategory atrace_categories = 1;
+}
+
+// End of protos/perfetto/common/ftrace_descriptor.proto
+
// Begin of protos/perfetto/common/gpu_counter_descriptor.proto
// Description of GPU counters.
@@ -186,6 +202,8 @@
optional GpuCounterDescriptor gpu_counter_descriptor = 5 [lazy = true];
optional TrackEventDescriptor track_event_descriptor = 6 [lazy = true];
+
+ optional FtraceDescriptor ftrace_descriptor = 8 [lazy = true];
}
// End of protos/perfetto/common/data_source_descriptor.proto
diff --git a/protos/perfetto/trace/BUILD.gn b/protos/perfetto/trace/BUILD.gn
index cfcca49..f0d0462 100644
--- a/protos/perfetto/trace/BUILD.gn
+++ b/protos/perfetto/trace/BUILD.gn
@@ -137,9 +137,6 @@
# This target are not used in the tree and is built only to guarantee that the
# autogenerated merged proto has a valid syntax.
perfetto_proto_library("merged_trace_@TYPE@") {
- proto_generators = [
- "lite",
- "source_set",
- ]
+ proto_generators = [ "lite" ]
sources = [ "perfetto_trace.proto" ]
}
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 7e7747c..5b04757 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -13,6 +13,22 @@
option go_package = "github.com/google/perfetto/perfetto_proto";
+// Begin of protos/perfetto/common/ftrace_descriptor.proto
+
+message FtraceDescriptor {
+ message AtraceCategory {
+ optional string name = 1;
+ optional string description = 2;
+ }
+
+ // Report the available atrace categories.
+ //
+ // Used by Traceur via `perfetto --query`.
+ repeated AtraceCategory atrace_categories = 1;
+}
+
+// End of protos/perfetto/common/ftrace_descriptor.proto
+
// Begin of protos/perfetto/common/gpu_counter_descriptor.proto
// Description of GPU counters.
@@ -186,6 +202,8 @@
optional GpuCounterDescriptor gpu_counter_descriptor = 5 [lazy = true];
optional TrackEventDescriptor track_event_descriptor = 6 [lazy = true];
+
+ optional FtraceDescriptor ftrace_descriptor = 8 [lazy = true];
}
// End of protos/perfetto/common/data_source_descriptor.proto
diff --git a/src/base/string_utils.cc b/src/base/string_utils.cc
index 5efca77..7e98ecd 100644
--- a/src/base/string_utils.cc
+++ b/src/base/string_utils.cc
@@ -205,11 +205,6 @@
return str;
}
-std::string TrimLeading(const std::string& str) {
- size_t idx = str.find_first_not_of(' ');
- return idx == std::string::npos ? str : str.substr(idx);
-}
-
size_t SprintfTrunc(char* dst, size_t dst_size, const char* fmt, ...) {
if (PERFETTO_UNLIKELY(dst_size) == 0)
return 0;
diff --git a/src/base/string_utils_unittest.cc b/src/base/string_utils_unittest.cc
index 39803ff..9a885d1 100644
--- a/src/base/string_utils_unittest.cc
+++ b/src/base/string_utils_unittest.cc
@@ -296,13 +296,6 @@
EXPECT_EQ(ReplaceAll("abc", "c", "bbb"), "abbbb");
}
-TEST(StringUtilsTest, TrimLeading) {
- EXPECT_EQ(TrimLeading(""), "");
- EXPECT_EQ(TrimLeading("a"), "a");
- EXPECT_EQ(TrimLeading(" aaaa"), "aaaa");
- EXPECT_EQ(TrimLeading(" aaaaa "), "aaaaa ");
-}
-
TEST(StringUtilsTest, StringCopy) {
// Nothing should be written when |dst_size| = 0.
{
diff --git a/src/base/subprocess_posix.cc b/src/base/subprocess_posix.cc
index 5e09544..fd32bb9 100644
--- a/src/base/subprocess_posix.cc
+++ b/src/base/subprocess_posix.cc
@@ -100,41 +100,49 @@
if (getppid() == 1)
die("terminating because parent process died");
- if (dup2(args->stdin_pipe_rd, STDIN_FILENO) == -1)
- die("Failed to dup2(STDIN)");
- close(args->stdin_pipe_rd);
+ switch (args->create_args->stdin_mode) {
+ case Subprocess::InputMode::kBuffer:
+ if (dup2(args->stdin_pipe_rd, STDIN_FILENO) == -1)
+ die("Failed to dup2(STDIN)");
+ close(args->stdin_pipe_rd);
+ break;
+ case Subprocess::InputMode::kDevNull:
+ if (dup2(open("/dev/null", O_RDONLY), STDIN_FILENO) == -1)
+ die("Failed to dup2(STDOUT)");
+ break;
+ }
switch (args->create_args->stdout_mode) {
- case Subprocess::kInherit:
+ case Subprocess::OutputMode::kInherit:
break;
- case Subprocess::kDevNull: {
+ case Subprocess::OutputMode::kDevNull: {
if (dup2(open("/dev/null", O_RDWR), STDOUT_FILENO) == -1)
die("Failed to dup2(STDOUT)");
break;
}
- case Subprocess::kBuffer:
+ case Subprocess::OutputMode::kBuffer:
if (dup2(args->stdouterr_pipe_wr, STDOUT_FILENO) == -1)
die("Failed to dup2(STDOUT)");
break;
- case Subprocess::kFd:
+ case Subprocess::OutputMode::kFd:
if (dup2(*args->create_args->out_fd, STDOUT_FILENO) == -1)
die("Failed to dup2(STDOUT)");
break;
}
switch (args->create_args->stderr_mode) {
- case Subprocess::kInherit:
+ case Subprocess::OutputMode::kInherit:
break;
- case Subprocess::kDevNull: {
+ case Subprocess::OutputMode::kDevNull: {
if (dup2(open("/dev/null", O_RDWR), STDERR_FILENO) == -1)
die("Failed to dup2(STDERR)");
break;
}
- case Subprocess::kBuffer:
+ case Subprocess::OutputMode::kBuffer:
if (dup2(args->stdouterr_pipe_wr, STDERR_FILENO) == -1)
die("Failed to dup2(STDERR)");
break;
- case Subprocess::kFd:
+ case Subprocess::OutputMode::kFd:
if (dup2(*args->create_args->out_fd, STDERR_FILENO) == -1)
die("Failed to dup2(STDERR)");
break;
@@ -220,8 +228,10 @@
}
// Setup the pipes for stdin/err redirection.
- s_->stdin_pipe = base::Pipe::Create(base::Pipe::kWrNonBlock);
- proc_args.stdin_pipe_rd = *s_->stdin_pipe.rd;
+ if (args.stdin_mode == InputMode::kBuffer) {
+ s_->stdin_pipe = base::Pipe::Create(base::Pipe::kWrNonBlock);
+ proc_args.stdin_pipe_rd = *s_->stdin_pipe.rd;
+ }
s_->stdouterr_pipe = base::Pipe::Create(base::Pipe::kRdNonBlock);
proc_args.stdouterr_pipe_wr = *s_->stdouterr_pipe.wr;
diff --git a/src/base/subprocess_unittest.cc b/src/base/subprocess_unittest.cc
index b52c804..6cebd1b 100644
--- a/src/base/subprocess_unittest.cc
+++ b/src/base/subprocess_unittest.cc
@@ -74,8 +74,8 @@
#else
Subprocess p({"sh", "-c", "(echo skip_err >&2); echo out_only"});
#endif
- p.args.stdout_mode = Subprocess::kBuffer;
- p.args.stderr_mode = Subprocess::kDevNull;
+ p.args.stdout_mode = Subprocess::OutputMode::kBuffer;
+ p.args.stderr_mode = Subprocess::OutputMode::kDevNull;
EXPECT_TRUE(p.Call());
EXPECT_EQ(p.status(), Subprocess::kTerminated);
@@ -88,8 +88,8 @@
#else
Subprocess p({"sh", "-c", "(echo err_only >&2); echo skip_out"});
#endif
- p.args.stdout_mode = Subprocess::kDevNull;
- p.args.stderr_mode = Subprocess::kBuffer;
+ p.args.stdout_mode = Subprocess::OutputMode::kDevNull;
+ p.args.stderr_mode = Subprocess::OutputMode::kBuffer;
EXPECT_TRUE(p.Call());
EXPECT_EQ(GetOutput(p), "err_only\n");
}
@@ -100,12 +100,54 @@
#else
Subprocess p({"sh", "-c", "echo out; (echo err >&2); echo out2"});
#endif
- p.args.stdout_mode = Subprocess::kBuffer;
- p.args.stderr_mode = Subprocess::kBuffer;
+ p.args.stdout_mode = Subprocess::OutputMode::kBuffer;
+ p.args.stderr_mode = Subprocess::OutputMode::kBuffer;
EXPECT_TRUE(p.Call());
EXPECT_EQ(GetOutput(p), "out\nerr\nout2\n");
}
+TEST(SubprocessTest, CatInputModeDevNull) {
+ std::string ignored_input = "ignored input";
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ Subprocess p({"cmd", "/C", "findstr . || exit 0"});
+#else
+ Subprocess p({"cat", "-"});
+#endif
+ p.args.stdout_mode = Subprocess::OutputMode::kBuffer;
+ p.args.input = ignored_input;
+ p.args.stdin_mode = Subprocess::InputMode::kDevNull;
+ EXPECT_TRUE(p.Call());
+ EXPECT_EQ(p.status(), Subprocess::kTerminated);
+ EXPECT_EQ(GetOutput(p), "");
+}
+
+TEST(SubprocessTest, BothStdoutAndStderrInputModeDevNull) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ Subprocess p({"cmd", "/c", "echo out&&(echo err>&2)&&echo out2"});
+#else
+ Subprocess p({"sh", "-c", "echo out; (echo err >&2); echo out2"});
+#endif
+ p.args.stdout_mode = Subprocess::OutputMode::kBuffer;
+ p.args.stderr_mode = Subprocess::OutputMode::kBuffer;
+ p.args.stdin_mode = Subprocess::InputMode::kDevNull;
+ EXPECT_TRUE(p.Call());
+ EXPECT_EQ(GetOutput(p), "out\nerr\nout2\n");
+}
+
+TEST(SubprocessTest, AllDevNull) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ Subprocess p({"cmd", "/c", "(exit 1)"});
+#else
+ Subprocess p({"false"});
+#endif
+ p.args.stdout_mode = Subprocess::OutputMode::kDevNull;
+ p.args.stderr_mode = Subprocess::OutputMode::kDevNull;
+ p.args.stdin_mode = Subprocess::InputMode::kDevNull;
+ EXPECT_FALSE(p.Call());
+ EXPECT_EQ(p.status(), Subprocess::kTerminated);
+ EXPECT_EQ(p.returncode(), 1);
+}
+
TEST(SubprocessTest, BinTrue) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
Subprocess p({"cmd", "/c", "(exit 0)"});
@@ -134,7 +176,7 @@
#else
Subprocess p({"echo", "-n", "foobar"});
#endif
- p.args.stdout_mode = Subprocess::kBuffer;
+ p.args.stdout_mode = Subprocess::OutputMode::kBuffer;
EXPECT_TRUE(p.Call());
EXPECT_EQ(p.status(), Subprocess::kTerminated);
EXPECT_EQ(p.returncode(), 0);
@@ -148,7 +190,7 @@
#else
Subprocess p({"cat", "-"});
#endif
- p.args.stdout_mode = Subprocess::kBuffer;
+ p.args.stdout_mode = Subprocess::OutputMode::kBuffer;
p.args.input = contents;
EXPECT_TRUE(p.Call());
EXPECT_EQ(p.status(), Subprocess::kTerminated);
@@ -166,7 +208,7 @@
#else
Subprocess p({"cat", tf.path().c_str()});
#endif
- p.args.stdout_mode = Subprocess::kBuffer;
+ p.args.stdout_mode = Subprocess::OutputMode::kBuffer;
EXPECT_TRUE(p.Call());
EXPECT_EQ(GetOutput(p), contents);
}
@@ -174,7 +216,7 @@
TEST(SubprocessTest, Timeout) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
Subprocess p({"ping", "127.0.0.1", "-n", "60"});
- p.args.stdout_mode = Subprocess::kDevNull;
+ p.args.stdout_mode = Subprocess::OutputMode::kDevNull;
#else
Subprocess p({"sleep", "60"});
#endif
@@ -187,7 +229,7 @@
TEST(SubprocessTest, TimeoutNotHit) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
Subprocess p({"ping", "127.0.0.1", "-n", "1"});
- p.args.stdout_mode = Subprocess::kDevNull;
+ p.args.stdout_mode = Subprocess::OutputMode::kDevNull;
#else
Subprocess p({"sleep", "0.01"});
#endif
@@ -201,7 +243,7 @@
#else
Subprocess p({"sh", "-c", "while true; do echo stuff; done"});
#endif
- p.args.stdout_mode = Subprocess::kDevNull;
+ p.args.stdout_mode = Subprocess::OutputMode::kDevNull;
EXPECT_FALSE(p.Call(/*timeout_ms=*/10));
EXPECT_EQ(p.status(), Subprocess::kTerminated);
EXPECT_TRUE(p.timed_out());
@@ -214,8 +256,8 @@
// 'sh -c' is to avoid closing stdin (sleep closes it before sleeping).
Subprocess p({"sh", "-c", "sleep 0.01"});
#endif
- p.args.stdout_mode = Subprocess::kDevNull;
- p.args.stderr_mode = Subprocess::kDevNull;
+ p.args.stdout_mode = Subprocess::OutputMode::kDevNull;
+ p.args.stderr_mode = Subprocess::OutputMode::kDevNull;
p.args.input = GenLargeString();
EXPECT_TRUE(p.Call());
EXPECT_EQ(p.status(), Subprocess::kTerminated);
@@ -232,8 +274,8 @@
// still handle the timeout properly.
Subprocess p({"sh", "-c", "sleep 10"});
#endif
- p.args.stdout_mode = Subprocess::kDevNull;
- p.args.stderr_mode = Subprocess::kDevNull;
+ p.args.stdout_mode = Subprocess::OutputMode::kDevNull;
+ p.args.stderr_mode = Subprocess::OutputMode::kDevNull;
p.args.input = GenLargeString();
EXPECT_FALSE(p.Call(/*timeout_ms=*/10));
EXPECT_EQ(p.status(), Subprocess::kTerminated);
@@ -246,7 +288,7 @@
#else
Subprocess p({"sleep", "1000"});
#endif
- p.args.stdout_mode = Subprocess::kDevNull;
+ p.args.stdout_mode = Subprocess::OutputMode::kDevNull;
p.Start();
EXPECT_EQ(p.Poll(), Subprocess::kRunning);
p.KillAndWaitForTermination();
@@ -267,7 +309,7 @@
#else
Subprocess p({"true"});
#endif
- p.args.stdout_mode = Subprocess::kFd;
+ p.args.stdout_mode = Subprocess::OutputMode::kFd;
p.args.out_fd = std::move(pipe.wr);
p.Start();
@@ -296,7 +338,7 @@
#else
Subprocess p({"sh", "-c", "echo exec_done; while true; do true; done"});
#endif
- p.args.stdout_mode = Subprocess::kBuffer;
+ p.args.stdout_mode = Subprocess::OutputMode::kBuffer;
p.Start();
// Wait for the fork()+exec() to complete.
@@ -365,7 +407,7 @@
#else
Subprocess initial = Subprocess({"sleep", "10000"});
#endif
- initial.args.stdout_mode = Subprocess::kDevNull;
+ initial.args.stdout_mode = Subprocess::OutputMode::kDevNull;
initial.Start();
Subprocess moved(std::move(initial));
EXPECT_EQ(moved.Poll(), Subprocess::kRunning);
@@ -379,7 +421,7 @@
#endif
initial.args.stdout_mode = Subprocess::OutputMode::kBuffer;
initial.Start();
- initial.Wait(/*timeout=*/5000);
+ initial.Wait(/*timeout_ms=*/5000);
EXPECT_EQ(initial.status(), Subprocess::kTerminated);
EXPECT_EQ(initial.returncode(), 0);
EXPECT_EQ(initial.output(), "hello");
@@ -406,7 +448,7 @@
TEST(SubprocessTest, Entrypoint) {
Subprocess p;
p.args.input = "ping\n";
- p.args.stdout_mode = Subprocess::kBuffer;
+ p.args.stdout_mode = Subprocess::OutputMode::kBuffer;
p.args.posix_entrypoint_for_testing = [] {
char buf[32]{};
PERFETTO_CHECK(fgets(buf, sizeof(buf), stdin));
@@ -428,7 +470,7 @@
int pipe2_wr = *pipe2.wr;
Subprocess p({"echo", "123"});
- p.args.stdout_mode = Subprocess::kBuffer;
+ p.args.stdout_mode = Subprocess::OutputMode::kBuffer;
p.args.preserve_fds.push_back(pipe2_wr);
p.args.posix_entrypoint_for_testing = [pipe1_wr, pipe2_wr] {
base::ignore_result(write(pipe1_wr, "fail", 4));
diff --git a/src/base/subprocess_windows.cc b/src/base/subprocess_windows.cc
index d58d7bd..1264655 100644
--- a/src/base/subprocess_windows.cc
+++ b/src/base/subprocess_windows.cc
@@ -61,22 +61,26 @@
if (!cmd.empty())
cmd.resize(cmd.size() - 1);
- s_->stdin_pipe = Pipe::Create();
- // Allow the child process to inherit the other end of the pipe.
- PERFETTO_CHECK(
- ::SetHandleInformation(*s_->stdin_pipe.rd, HANDLE_FLAG_INHERIT, 1));
+ if (args.stdin_mode == InputMode::kBuffer) {
+ s_->stdin_pipe = Pipe::Create();
+ // Allow the child process to inherit the other end of the pipe.
+ PERFETTO_CHECK(
+ ::SetHandleInformation(*s_->stdin_pipe.rd, HANDLE_FLAG_INHERIT, 1));
+ }
- if (args.stderr_mode == kBuffer || args.stdout_mode == kBuffer) {
+ if (args.stderr_mode == OutputMode::kBuffer ||
+ args.stdout_mode == OutputMode::kBuffer) {
s_->stdouterr_pipe = Pipe::Create();
PERFETTO_CHECK(
::SetHandleInformation(*s_->stdouterr_pipe.wr, HANDLE_FLAG_INHERIT, 1));
}
ScopedPlatformHandle nul_handle;
- if (args.stderr_mode == kDevNull || args.stdout_mode == kDevNull) {
- nul_handle.reset(::CreateFileA("NUL", GENERIC_WRITE, FILE_SHARE_WRITE,
- nullptr, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, nullptr));
+ if (args.stderr_mode == OutputMode::kDevNull ||
+ args.stdout_mode == OutputMode::kDevNull) {
+ nul_handle.reset(::CreateFileA(
+ "NUL", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
PERFETTO_CHECK(::SetHandleInformation(*nul_handle, HANDLE_FLAG_INHERIT, 1));
}
@@ -84,13 +88,13 @@
STARTUPINFOA start_info{};
start_info.cb = sizeof(STARTUPINFOA);
- if (args.stderr_mode == kInherit) {
+ if (args.stderr_mode == OutputMode::kInherit) {
start_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
- } else if (args.stderr_mode == kBuffer) {
+ } else if (args.stderr_mode == OutputMode::kBuffer) {
start_info.hStdError = *s_->stdouterr_pipe.wr;
- } else if (args.stderr_mode == kDevNull) {
+ } else if (args.stderr_mode == OutputMode::kDevNull) {
start_info.hStdError = *nul_handle;
- } else if (args.stderr_mode == kFd) {
+ } else if (args.stderr_mode == OutputMode::kFd) {
PERFETTO_CHECK(
::SetHandleInformation(*args.out_fd, HANDLE_FLAG_INHERIT, 1));
start_info.hStdError = *args.out_fd;
@@ -98,13 +102,13 @@
PERFETTO_CHECK(false);
}
- if (args.stdout_mode == kInherit) {
+ if (args.stdout_mode == OutputMode::kInherit) {
start_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
- } else if (args.stdout_mode == kBuffer) {
+ } else if (args.stdout_mode == OutputMode::kBuffer) {
start_info.hStdOutput = *s_->stdouterr_pipe.wr;
- } else if (args.stdout_mode == kDevNull) {
+ } else if (args.stdout_mode == OutputMode::kDevNull) {
start_info.hStdOutput = *nul_handle;
- } else if (args.stdout_mode == kFd) {
+ } else if (args.stdout_mode == OutputMode::kFd) {
PERFETTO_CHECK(
::SetHandleInformation(*args.out_fd, HANDLE_FLAG_INHERIT, 1));
start_info.hStdOutput = *args.out_fd;
@@ -112,7 +116,12 @@
PERFETTO_CHECK(false);
}
- start_info.hStdInput = *s_->stdin_pipe.rd;
+ if (args.stdin_mode == InputMode::kBuffer) {
+ start_info.hStdInput = *s_->stdin_pipe.rd;
+ } else if (args.stdin_mode == InputMode::kDevNull) {
+ start_info.hStdInput = *nul_handle;
+ }
+
start_info.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process.
@@ -149,9 +158,12 @@
s_->status = kRunning;
MovableState* s = s_.get();
- s_->stdin_thread = std::thread(&Subprocess::StdinThread, s, args.input);
+ if (args.stdin_mode == InputMode::kBuffer) {
+ s_->stdin_thread = std::thread(&Subprocess::StdinThread, s, args.input);
+ }
- if (args.stderr_mode == kBuffer || args.stdout_mode == kBuffer) {
+ if (args.stderr_mode == OutputMode::kBuffer ||
+ args.stdout_mode == OutputMode::kBuffer) {
PERFETTO_DCHECK(s_->stdouterr_pipe.rd);
s_->stdouterr_thread = std::thread(&Subprocess::StdoutErrThread, s);
}
@@ -222,14 +234,14 @@
const int64_t wait_start_ms = base::GetWallTimeMs().count();
// Break out of the loop only after both conditions are satisfied:
- // - All stdout/stderr data has been read (if kBuffer).
+ // - All stdout/stderr data has been read (if OutputMode::kBuffer).
// - The process exited.
// Note that the two events can happen arbitrary order. After the process
// exits, there might be still data in the pipe buffer, which we want to
// read fully.
// Note also that stdout/err might be "complete" before starting, if neither
- // is operating in kBuffer mode. In that case we just want to wait for the
- // process termination.
+ // is operating in OutputMode::kBuffer mode. In that case we just want to wait
+ // for the process termination.
//
// Instead, don't wait on the stdin to be fully written. The child process
// might exit prematurely (or crash). If that happens, we can end up in a
diff --git a/src/perfetto_cmd/BUILD.gn b/src/perfetto_cmd/BUILD.gn
index 9cfe232..74ca8fb 100644
--- a/src/perfetto_cmd/BUILD.gn
+++ b/src/perfetto_cmd/BUILD.gn
@@ -82,8 +82,8 @@
}
perfetto_cc_proto_descriptor("gen_cc_config_descriptor") {
- descriptor_name = "perfetto_config.descriptor"
- descriptor_target = "../../protos/perfetto/config:merged_config_descriptor"
+ descriptor_name = "config.descriptor"
+ descriptor_target = "../../protos/perfetto/config:descriptor"
}
source_set("trigger_perfetto_cmd") {
diff --git a/src/perfetto_cmd/pbtxt_to_pb.cc b/src/perfetto_cmd/pbtxt_to_pb.cc
index 7420502..2c7b67a 100644
--- a/src/perfetto_cmd/pbtxt_to_pb.cc
+++ b/src/perfetto_cmd/pbtxt_to_pb.cc
@@ -33,7 +33,7 @@
#include "perfetto/protozero/message.h"
#include "perfetto/protozero/message_handle.h"
#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "src/perfetto_cmd/perfetto_config.descriptor.h"
+#include "src/perfetto_cmd/config.descriptor.h"
#include "protos/perfetto/common/descriptor.gen.h"
@@ -707,8 +707,7 @@
{
file_descriptor_set.ParseFromArray(
- kPerfettoConfigDescriptor.data(),
- static_cast<int>(kPerfettoConfigDescriptor.size()));
+ kConfigDescriptor.data(), static_cast<int>(kConfigDescriptor.size()));
for (const auto& file_descriptor : file_descriptor_set.file()) {
for (const auto& enum_descriptor : file_descriptor.enum_type()) {
const std::string name =
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index e104296..83d76c0 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -64,6 +64,7 @@
#include "src/perfetto_cmd/pbtxt_to_pb.h"
#include "src/perfetto_cmd/trigger_producer.h"
+#include "protos/perfetto/common/ftrace_descriptor.gen.h"
#include "protos/perfetto/common/tracing_service_state.gen.h"
#include "protos/perfetto/common/track_event_descriptor.gen.h"
@@ -1224,13 +1225,21 @@
producer_id_and_name);
// Print the category names for clients using the track event SDK.
if (!ds.ds_descriptor().track_event_descriptor_raw().empty()) {
- auto raw = ds.ds_descriptor().track_event_descriptor_raw();
- perfetto::protos::gen::TrackEventDescriptor desc;
+ const std::string& raw = ds.ds_descriptor().track_event_descriptor_raw();
+ protos::gen::TrackEventDescriptor desc;
if (desc.ParseFromArray(raw.data(), raw.size())) {
for (const auto& cat : desc.available_categories()) {
printf("%s,", cat.name().c_str());
}
}
+ } else if (!ds.ds_descriptor().ftrace_descriptor_raw().empty()) {
+ const std::string& raw = ds.ds_descriptor().ftrace_descriptor_raw();
+ protos::gen::FtraceDescriptor desc;
+ if (desc.ParseFromArray(raw.data(), raw.size())) {
+ for (const auto& cat : desc.atrace_categories()) {
+ printf("%s,", cat.name().c_str());
+ }
+ }
}
printf("\n");
} // for data_sources()
@@ -1260,7 +1269,8 @@
} // for tracing_sessions()
int sessions_listed = static_cast<int>(svc_state.tracing_sessions().size());
- if (sessions_listed != svc_state.num_sessions() && geteuid() != 0) {
+ if (sessions_listed != svc_state.num_sessions() &&
+ base::GetCurrentUserId() != 0) {
printf(
"\n"
"NOTE: Some tracing sessions are not reported in the list above.\n"
diff --git a/src/profiling/common/callstack_trie.h b/src/profiling/common/callstack_trie.h
index f8ca304..f5d2378 100644
--- a/src/profiling/common/callstack_trie.h
+++ b/src/profiling/common/callstack_trie.h
@@ -184,6 +184,8 @@
uint64_t next_callstack_id_ = 0;
+ // Note: profile_module in trace processor relies on the value of this root
+ // callsite being exactly "1". See the perf_sample parsing code.
Node root_{MakeRootFrame(), ++next_callstack_id_};
};
diff --git a/src/profiling/memory/BUILD.gn b/src/profiling/memory/BUILD.gn
index 5400d07..34c6263 100644
--- a/src/profiling/memory/BUILD.gn
+++ b/src/profiling/memory/BUILD.gn
@@ -181,7 +181,6 @@
":wire_protocol",
"../../../gn:default_deps",
"../../base",
- "../common:proc_utils",
]
sources = [ "client_api.cc" ]
}
@@ -296,7 +295,6 @@
"../../../gn:default_deps",
"../../base",
"../../base:unix_socket",
- "../common:proc_utils",
]
public_deps = [ "../../../gn:libunwindstack" ]
sources = [
diff --git a/src/profiling/memory/client_api.cc b/src/profiling/memory/client_api.cc
index 6ec2a61..0d46ac2 100644
--- a/src/profiling/memory/client_api.cc
+++ b/src/profiling/memory/client_api.cc
@@ -28,17 +28,14 @@
#include <atomic>
#include <cinttypes>
#include <memory>
-#include <tuple>
#include <type_traits>
#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/no_destructor.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/unix_socket.h"
#include "perfetto/ext/base/utils.h"
-#include "src/profiling/common/proc_utils.h"
#include "src/profiling/memory/client.h"
#include "src/profiling/memory/client_api_factory.h"
#include "src/profiling/memory/scoped_spinlock.h"
diff --git a/src/profiling/memory/client_api_factory_android.cc b/src/profiling/memory/client_api_factory_android.cc
index 370dd60..16c3a25 100644
--- a/src/profiling/memory/client_api_factory_android.cc
+++ b/src/profiling/memory/client_api_factory_android.cc
@@ -27,7 +27,6 @@
#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/unix_socket.h"
-#include "src/profiling/common/proc_utils.h"
#include "src/profiling/memory/client.h"
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
diff --git a/src/trace_processor/dynamic/ancestor_generator.cc b/src/trace_processor/dynamic/ancestor_generator.cc
index c126ced..1621a37 100644
--- a/src/trace_processor/dynamic/ancestor_generator.cc
+++ b/src/trace_processor/dynamic/ancestor_generator.cc
@@ -20,6 +20,7 @@
#include <set>
#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/util/status_macros.h"
namespace perfetto {
namespace trace_processor {
@@ -50,18 +51,13 @@
}
template <typename T>
-base::Optional<RowMap> BuildAncestorsRowMap(const T& table,
- typename T::Id starting_id) {
+base::Status BuildAncestorsRowMap(const T& table,
+ typename T::Id starting_id,
+ RowMap& rowmap_return) {
auto start_row = table.id().IndexOf(starting_id);
-
if (!start_row) {
- // TODO(lalitm): Ideally this should result in an error, or be filtered out
- // during ValidateConstraints so we can just dereference |start_row|
- // directly. However ValidateConstraints doesn't know the value we're
- // filtering for so can't ensure it exists. For now we return a nullptr
- // which will cause the query to surface an error with the message "SQL
- // error: constraint failed".
- return base::nullopt;
+ return base::ErrStatus("no row with id %" PRIu32 "",
+ static_cast<uint32_t>(starting_id.value));
}
std::vector<uint32_t> parent_rows;
@@ -72,23 +68,25 @@
// Update the loop variable by looking up the next parent_id.
maybe_parent_id = table.parent_id()[parent_row];
}
- return RowMap(std::move(parent_rows));
+ rowmap_return = RowMap{parent_rows};
+ return base::OkStatus();
}
// Constraint_value is used to construct the hidden column "start_id"
// needed by SQL.
// Starting_id refers to the id that is used to generate the ancestors.
template <typename T>
-std::unique_ptr<Table> BuildAncestorsTable(int64_t constraint_value,
- const T& table,
- typename T::Id starting_id) {
+base::Status BuildAncestorsTable(int64_t constraint_value,
+ const T& table,
+ typename T::Id starting_id,
+ std::unique_ptr<Table>& table_return) {
// Build up all the parents row ids.
- auto ancestors = BuildAncestorsRowMap(table, starting_id);
- if (!ancestors) {
- return nullptr;
- }
- return std::unique_ptr<Table>(new Table(ExtendTableWithStartId(
- table.Apply(std::move(*ancestors)), constraint_value)));
+ RowMap ancestors;
+ RETURN_IF_ERROR(BuildAncestorsRowMap(table, starting_id, ancestors));
+
+ table_return.reset(new Table(ExtendTableWithStartId(
+ table.Apply(std::move(ancestors)), constraint_value)));
+ return base::OkStatus();
}
} // namespace
@@ -96,7 +94,7 @@
TraceProcessorContext* context)
: type_(type), context_(context) {}
-util::Status AncestorGenerator::ValidateConstraints(
+base::Status AncestorGenerator::ValidateConstraints(
const QueryConstraints& qc) {
const auto& cs = qc.constraints();
@@ -105,32 +103,46 @@
return c.column == column && c.op == SQLITE_INDEX_CONSTRAINT_EQ;
};
bool has_id_cs = std::find_if(cs.begin(), cs.end(), id_fn) != cs.end();
- return has_id_cs ? util::OkStatus()
- : util::ErrStatus("Failed to find required constraints");
+ return has_id_cs ? base::OkStatus()
+ : base::ErrStatus("Failed to find required constraints");
}
-std::unique_ptr<Table> AncestorGenerator::ComputeTable(
+base::Status AncestorGenerator::ComputeTable(
const std::vector<Constraint>& cs,
const std::vector<Order>&,
- const BitVector&) {
+ const BitVector&,
+ std::unique_ptr<Table>& table_return) {
uint32_t column = GetConstraintColumnIndex(type_, context_);
- auto it = std::find_if(cs.begin(), cs.end(), [column](const Constraint& c) {
- return c.col_idx == column && c.op == FilterOp::kEq;
- });
- PERFETTO_DCHECK(it != cs.end());
- auto start_id = it->value.AsLong();
+ auto constraint_it =
+ std::find_if(cs.begin(), cs.end(), [column](const Constraint& c) {
+ return c.col_idx == column && c.op == FilterOp::kEq;
+ });
+ PERFETTO_DCHECK(constraint_it != cs.end());
+ if (constraint_it == cs.end() ||
+ constraint_it->value.type != SqlValue::Type::kLong) {
+ return base::ErrStatus("invalid start_id");
+ }
+ auto start_id = constraint_it->value.AsLong();
switch (type_) {
- case Ancestor::kSlice:
- return BuildAncestorsTable(
+ case Ancestor::kSlice: {
+ RETURN_IF_ERROR(BuildAncestorsTable(
/* constraint_id = */ start_id, context_->storage->slice_table(),
- /* starting_id = */ SliceId(static_cast<uint32_t>(start_id)));
- case Ancestor::kStackProfileCallsite:
- return BuildAncestorsTable(
+ /* starting_id = */ SliceId(static_cast<uint32_t>(start_id)),
+ table_return));
+ return base::OkStatus();
+ }
+
+ case Ancestor::kStackProfileCallsite: {
+ RETURN_IF_ERROR(BuildAncestorsTable(
/* constraint_id = */ start_id,
context_->storage->stack_profile_callsite_table(),
- /* starting_id = */ CallsiteId(static_cast<uint32_t>(start_id)));
- case Ancestor::kSliceByStack:
+ /* starting_id = */ CallsiteId(static_cast<uint32_t>(start_id)),
+ table_return));
+ return base::OkStatus();
+ }
+
+ case Ancestor::kSliceByStack: {
// Find the all slice ids that have the stack id and find all the
// ancestors of the slice ids.
const auto& slice_table = context_->storage->slice_table();
@@ -148,10 +160,12 @@
}
}
- return std::unique_ptr<Table>(new Table(ExtendTableWithStartId(
+ table_return.reset(new Table(ExtendTableWithStartId(
slice_table.Apply(std::move(result)), start_id)));
+ return base::OkStatus();
+ }
}
- return nullptr;
+ return base::ErrStatus("unknown AncestorGenerator type");
}
Table::Schema AncestorGenerator::CreateSchema() {
@@ -193,7 +207,11 @@
base::Optional<RowMap> AncestorGenerator::GetAncestorSlices(
const tables::SliceTable& slices,
SliceId slice_id) {
- return BuildAncestorsRowMap(slices, slice_id);
+ RowMap ret;
+ auto status = BuildAncestorsRowMap(slices, slice_id, ret);
+ if (!status.ok())
+ return base::nullopt;
+ return std::move(ret); // -Wreturn-std-move-in-c++11
}
} // namespace trace_processor
diff --git a/src/trace_processor/dynamic/ancestor_generator.h b/src/trace_processor/dynamic/ancestor_generator.h
index 48947ac..00679be 100644
--- a/src/trace_processor/dynamic/ancestor_generator.h
+++ b/src/trace_processor/dynamic/ancestor_generator.h
@@ -46,10 +46,11 @@
Table::Schema CreateSchema() override;
std::string TableName() override;
uint32_t EstimateRowCount() override;
- util::Status ValidateConstraints(const QueryConstraints&) override;
- std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob,
- const BitVector& cols_used) override;
+ base::Status ValidateConstraints(const QueryConstraints&) override;
+ base::Status ComputeTable(const std::vector<Constraint>& cs,
+ const std::vector<Order>& ob,
+ const BitVector& cols_used,
+ std::unique_ptr<Table>& table_return) override;
// Returns a RowMap of slice IDs which are ancestors of |slice_id|. Returns
// NULL if an invalid |slice_id| is given. This is used by
diff --git a/src/trace_processor/dynamic/connected_flow_generator.cc b/src/trace_processor/dynamic/connected_flow_generator.cc
index 1032fd7..8dbefa1 100644
--- a/src/trace_processor/dynamic/connected_flow_generator.cc
+++ b/src/trace_processor/dynamic/connected_flow_generator.cc
@@ -34,7 +34,7 @@
ConnectedFlowGenerator::~ConnectedFlowGenerator() = default;
-util::Status ConnectedFlowGenerator::ValidateConstraints(
+base::Status ConnectedFlowGenerator::ValidateConstraints(
const QueryConstraints& qc) {
const auto& cs = qc.constraints();
@@ -47,8 +47,8 @@
std::find_if(cs.begin(), cs.end(), flow_id_fn) != cs.end();
return has_flow_id_cs
- ? util::OkStatus()
- : util::ErrStatus("Failed to find required constraints");
+ ? base::OkStatus()
+ : base::ErrStatus("Failed to find required constraints");
}
namespace {
@@ -196,24 +196,27 @@
} // namespace
-std::unique_ptr<Table> ConnectedFlowGenerator::ComputeTable(
+base::Status ConnectedFlowGenerator::ComputeTable(
const std::vector<Constraint>& cs,
const std::vector<Order>&,
- const BitVector&) {
+ const BitVector&,
+ std::unique_ptr<Table>& table_return) {
const auto& flow = context_->storage->flow_table();
const auto& slice = context_->storage->slice_table();
auto it = std::find_if(cs.begin(), cs.end(), [&flow](const Constraint& c) {
return c.col_idx == flow.GetColumnCount() && c.op == FilterOp::kEq;
});
-
PERFETTO_DCHECK(it != cs.end());
+ if (it == cs.end() || it->value.type != SqlValue::Type::kLong) {
+ return base::ErrStatus("invalid start_id");
+ }
SliceId start_id{static_cast<uint32_t>(it->value.AsLong())};
if (!slice.id().IndexOf(start_id)) {
- PERFETTO_ELOG("Given slice id is invalid (ConnectedFlowGenerator)");
- return nullptr;
+ return base::ErrStatus("invalid slice id %" PRIu32 "",
+ static_cast<uint32_t>(start_id.value));
}
BFS bfs(context_);
@@ -241,11 +244,12 @@
start_ids->Append(start_id.value);
}
- return std::unique_ptr<Table>(
+ table_return.reset(
new Table(flow.Apply(RowMap(std::move(result_rows)))
.ExtendWithColumn("start_id", std::move(start_ids),
TypedColumn<uint32_t>::default_flags() |
TypedColumn<uint32_t>::kHidden)));
+ return base::OkStatus();
}
Table::Schema ConnectedFlowGenerator::CreateSchema() {
diff --git a/src/trace_processor/dynamic/connected_flow_generator.h b/src/trace_processor/dynamic/connected_flow_generator.h
index b2117af..0b8661b 100644
--- a/src/trace_processor/dynamic/connected_flow_generator.h
+++ b/src/trace_processor/dynamic/connected_flow_generator.h
@@ -53,10 +53,11 @@
Table::Schema CreateSchema() override;
std::string TableName() override;
uint32_t EstimateRowCount() override;
- util::Status ValidateConstraints(const QueryConstraints&) override;
- std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob,
- const BitVector& cols_used) override;
+ base::Status ValidateConstraints(const QueryConstraints&) override;
+ base::Status ComputeTable(const std::vector<Constraint>& cs,
+ const std::vector<Order>& ob,
+ const BitVector& cols_used,
+ std::unique_ptr<Table>& table_return) override;
private:
Mode mode_;
diff --git a/src/trace_processor/dynamic/descendant_generator.cc b/src/trace_processor/dynamic/descendant_generator.cc
index ebec3f3..c0df1cd 100644
--- a/src/trace_processor/dynamic/descendant_generator.cc
+++ b/src/trace_processor/dynamic/descendant_generator.cc
@@ -20,6 +20,7 @@
#include <set>
#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/util/status_macros.h"
namespace perfetto {
namespace trace_processor {
@@ -40,40 +41,38 @@
TypedColumn<uint32_t>::default_flags() | TypedColumn<uint32_t>::kHidden);
}
-base::Optional<RowMap> BuildDescendantsRowMap(const tables::SliceTable& slices,
- SliceId starting_id) {
+base::Status BuildDescendantsRowMap(const tables::SliceTable& slices,
+ SliceId starting_id,
+ RowMap& rowmap_return) {
auto start_row = slices.id().IndexOf(starting_id);
// The query gave an invalid ID that doesn't exist in the slice table.
if (!start_row) {
- // TODO(lalitm): Ideally this should result in an error, or be filtered out
- // during ValidateConstraints so we can just dereference |start_row|
- // directly. However ValidateConstraints doesn't know the value we're
- // filtering for so can't ensure it exists. For now we return a nullptr
- // which will cause the query to surface an error with the message "SQL
- // error: constraint failed".
- return base::nullopt;
+ return base::ErrStatus("no row with id %" PRIu32 "",
+ static_cast<uint32_t>(starting_id.value));
}
// All nested descendents must be on the same track, with a ts between
// |start_id.ts| and |start_id.ts| + |start_id.dur|, and who's depth is larger
// then |start_row|'s. So we just use Filter to select all relevant slices.
- return slices.FilterToRowMap(
+ rowmap_return = slices.FilterToRowMap(
{slices.ts().ge(slices.ts()[*start_row]),
slices.ts().le(slices.ts()[*start_row] + slices.dur()[*start_row]),
slices.track_id().eq(slices.track_id()[*start_row].value),
slices.depth().gt(slices.depth()[*start_row])});
+ return base::OkStatus();
}
-std::unique_ptr<Table> BuildDescendantsTable(int64_t constraint_value,
- const tables::SliceTable& slices,
- SliceId starting_id) {
+base::Status BuildDescendantsTable(int64_t constraint_value,
+ const tables::SliceTable& slices,
+ SliceId starting_id,
+ std::unique_ptr<Table>& table_return) {
// Build up all the children row ids.
- auto descendants = BuildDescendantsRowMap(slices, starting_id);
- if (!descendants) {
- return nullptr;
- }
- return std::unique_ptr<Table>(new Table(ExtendTableWithStartId(
- slices.Apply(std::move(*descendants)), constraint_value)));
+ RowMap descendants;
+ RETURN_IF_ERROR(BuildDescendantsRowMap(slices, starting_id, descendants));
+
+ table_return.reset(new Table(ExtendTableWithStartId(
+ slices.Apply(std::move(descendants)), constraint_value)));
+ return base::OkStatus();
}
} // namespace
@@ -81,7 +80,7 @@
TraceProcessorContext* context)
: type_(type), context_(context) {}
-util::Status DescendantGenerator::ValidateConstraints(
+base::Status DescendantGenerator::ValidateConstraints(
const QueryConstraints& qc) {
const auto& cs = qc.constraints();
@@ -90,28 +89,38 @@
return c.column == column && c.op == SQLITE_INDEX_CONSTRAINT_EQ;
};
bool has_id_cs = std::find_if(cs.begin(), cs.end(), id_fn) != cs.end();
- return has_id_cs ? util::OkStatus()
- : util::ErrStatus("Failed to find required constraints");
+ return has_id_cs ? base::OkStatus()
+ : base::ErrStatus("Failed to find required constraints");
}
-std::unique_ptr<Table> DescendantGenerator::ComputeTable(
+base::Status DescendantGenerator::ComputeTable(
const std::vector<Constraint>& cs,
const std::vector<Order>&,
- const BitVector&) {
+ const BitVector&,
+ std::unique_ptr<Table>& table_return) {
const auto& slices = context_->storage->slice_table();
uint32_t column = GetConstraintColumnIndex(context_);
- auto it = std::find_if(cs.begin(), cs.end(), [column](const Constraint& c) {
- return c.col_idx == column && c.op == FilterOp::kEq;
- });
- PERFETTO_DCHECK(it != cs.end());
- auto start_id = it->value.AsLong();
+ auto constraint_it =
+ std::find_if(cs.begin(), cs.end(), [column](const Constraint& c) {
+ return c.col_idx == column && c.op == FilterOp::kEq;
+ });
+ PERFETTO_DCHECK(constraint_it != cs.end());
+ if (constraint_it == cs.end() ||
+ constraint_it->value.type != SqlValue::Type::kLong) {
+ return base::ErrStatus("invalid start_id");
+ }
+ auto start_id = constraint_it->value.AsLong();
switch (type_) {
- case Descendant::kSlice:
- return BuildDescendantsTable(start_id, slices,
- SliceId(static_cast<uint32_t>(start_id)));
- case Descendant::kSliceByStack:
+ case Descendant::kSlice: {
+ RETURN_IF_ERROR(BuildDescendantsTable(
+ start_id, slices, SliceId(static_cast<uint32_t>(start_id)),
+ table_return));
+ return base::OkStatus();
+ }
+
+ case Descendant::kSliceByStack: {
auto result = RowMap();
auto slice_ids = slices.FilterToRowMap({slices.stack_id().eq(start_id)});
@@ -124,10 +133,12 @@
}
}
- return std::unique_ptr<Table>(new Table(
+ table_return.reset(new Table(
ExtendTableWithStartId(slices.Apply(std::move(result)), start_id)));
+ return base::OkStatus();
+ }
}
- return nullptr;
+ return base::ErrStatus("unknown DescendantGenerator type");
}
Table::Schema DescendantGenerator::CreateSchema() {
@@ -156,7 +167,11 @@
base::Optional<RowMap> DescendantGenerator::GetDescendantSlices(
const tables::SliceTable& slices,
SliceId slice_id) {
- return BuildDescendantsRowMap(slices, slice_id);
+ RowMap ret;
+ auto status = BuildDescendantsRowMap(slices, slice_id, ret);
+ if (!status.ok())
+ return base::nullopt;
+ return std::move(ret); // -Wreturn-std-move-in-c++11
}
} // namespace trace_processor
diff --git a/src/trace_processor/dynamic/descendant_generator.h b/src/trace_processor/dynamic/descendant_generator.h
index 216b7e1..318fe7d 100644
--- a/src/trace_processor/dynamic/descendant_generator.h
+++ b/src/trace_processor/dynamic/descendant_generator.h
@@ -41,10 +41,11 @@
Table::Schema CreateSchema() override;
std::string TableName() override;
uint32_t EstimateRowCount() override;
- util::Status ValidateConstraints(const QueryConstraints&) override;
- std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob,
- const BitVector& cols_used) override;
+ base::Status ValidateConstraints(const QueryConstraints&) override;
+ base::Status ComputeTable(const std::vector<Constraint>& cs,
+ const std::vector<Order>& ob,
+ const BitVector& cols_used,
+ std::unique_ptr<Table>& table_return) override;
// Returns a RowMap of slice IDs which are descendants of |slice_id|. Returns
// NULL if an invalid |slice_id| is given. This is used by
diff --git a/src/trace_processor/dynamic/describe_slice_generator.cc b/src/trace_processor/dynamic/describe_slice_generator.cc
index 500d561..ea8a70c 100644
--- a/src/trace_processor/dynamic/describe_slice_generator.cc
+++ b/src/trace_processor/dynamic/describe_slice_generator.cc
@@ -18,6 +18,7 @@
#include "src/trace_processor/analysis/describe_slice.h"
#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/util/status_macros.h"
namespace perfetto {
namespace trace_processor {
@@ -34,10 +35,9 @@
};
auto slice_id_it = std::find_if(cs.begin(), cs.end(), slice_id_fn);
- // We should always have valid iterators here because BestIndex should only
- // allow the constraint set to be chosen when we have an equality constraint
- // on both ts and upid.
PERFETTO_CHECK(slice_id_it != cs.end());
+ // TODO(rsavitski): consider checking type of the SqlValue, as erroneous
+ // queries that pass a null here (or otherwise unexpected type) will crash.
uint32_t slice_id_value = static_cast<uint32_t>(slice_id_it->value.AsLong());
return DescribeSliceGenerator::InputValues{slice_id_value};
@@ -50,7 +50,7 @@
DescribeSliceGenerator::~DescribeSliceGenerator() = default;
-util::Status DescribeSliceGenerator::ValidateConstraints(
+base::Status DescribeSliceGenerator::ValidateConstraints(
const QueryConstraints& qc) {
using T = tables::DescribeSliceTable;
@@ -64,21 +64,21 @@
std::find_if(cs.begin(), cs.end(), slice_id_fn) != cs.end();
return has_slice_id_cs
- ? util::OkStatus()
- : util::ErrStatus("Failed to find required constraints");
+ ? base::OkStatus()
+ : base::ErrStatus("Failed to find required constraints");
}
-std::unique_ptr<Table> DescribeSliceGenerator::ComputeTable(
+base::Status DescribeSliceGenerator::ComputeTable(
const std::vector<Constraint>& cs,
const std::vector<Order>&,
- const BitVector&) {
+ const BitVector&,
+ std::unique_ptr<Table>& table_return) {
auto input = GetDescribeSliceInputValues(cs);
const auto& slices = context_->storage->slice_table();
base::Optional<SliceDescription> opt_desc;
- auto status = DescribeSlice(slices, SliceId{input.slice_id_value}, &opt_desc);
- if (!status.ok())
- return nullptr;
+ RETURN_IF_ERROR(
+ DescribeSlice(slices, SliceId{input.slice_id_value}, &opt_desc));
auto* pool = context_->storage->mutable_string_pool();
std::unique_ptr<tables::DescribeSliceTable> table(
@@ -93,9 +93,8 @@
row.slice_id = input.slice_id_value;
table->Insert(row);
}
- // We need to explicitly std::move as clang complains about a bug in old
- // compilers otherwise (-Wreturn-std-move-in-c++11).
- return std::move(table);
+ table_return = std::move(table);
+ return base::OkStatus();
}
Table::Schema DescribeSliceGenerator::CreateSchema() {
diff --git a/src/trace_processor/dynamic/describe_slice_generator.h b/src/trace_processor/dynamic/describe_slice_generator.h
index fc7d991..fa8a87f 100644
--- a/src/trace_processor/dynamic/describe_slice_generator.h
+++ b/src/trace_processor/dynamic/describe_slice_generator.h
@@ -41,10 +41,11 @@
Table::Schema CreateSchema() override;
std::string TableName() override;
uint32_t EstimateRowCount() override;
- util::Status ValidateConstraints(const QueryConstraints&) override;
- std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob,
- const BitVector& cols_used) override;
+ base::Status ValidateConstraints(const QueryConstraints&) override;
+ base::Status ComputeTable(const std::vector<Constraint>& cs,
+ const std::vector<Order>& ob,
+ const BitVector& cols_used,
+ std::unique_ptr<Table>& table_return) override;
private:
TraceProcessorContext* context_ = nullptr;
diff --git a/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc b/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc
index 617c658..45cf596 100644
--- a/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc
+++ b/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc
@@ -104,7 +104,7 @@
return schema;
}
-util::Status ExperimentalAnnotatedStackGenerator::ValidateConstraints(
+base::Status ExperimentalAnnotatedStackGenerator::ValidateConstraints(
const QueryConstraints& qc) {
const auto& cs = qc.constraints();
int column = static_cast<int>(GetConstraintColumnIndex(context_));
@@ -113,14 +113,15 @@
return c.column == column && c.op == SQLITE_INDEX_CONSTRAINT_EQ;
};
bool has_id_cs = std::find_if(cs.begin(), cs.end(), id_fn) != cs.end();
- return has_id_cs ? util::OkStatus()
- : util::ErrStatus("Failed to find required constraints");
+ return has_id_cs ? base::OkStatus()
+ : base::ErrStatus("Failed to find required constraints");
}
-std::unique_ptr<Table> ExperimentalAnnotatedStackGenerator::ComputeTable(
+base::Status ExperimentalAnnotatedStackGenerator::ComputeTable(
const std::vector<Constraint>& cs,
const std::vector<Order>&,
- const BitVector&) {
+ const BitVector&,
+ std::unique_ptr<Table>& table_return) {
const auto& cs_table = context_->storage->stack_profile_callsite_table();
const auto& f_table = context_->storage->stack_profile_frame_table();
const auto& m_table = context_->storage->stack_profile_mapping_table();
@@ -133,12 +134,17 @@
return c.col_idx == constraint_col && c.op == FilterOp::kEq;
});
PERFETTO_DCHECK(constraint_it != cs.end());
+ if (constraint_it == cs.end() ||
+ constraint_it->value.type != SqlValue::Type::kLong) {
+ return base::ErrStatus("invalid input callsite id");
+ }
- auto start_id = static_cast<uint32_t>(constraint_it->value.AsLong());
+ uint32_t start_id = static_cast<uint32_t>(constraint_it->value.AsLong());
base::Optional<uint32_t> start_row =
cs_table.id().IndexOf(CallsiteId(start_id));
- if (!start_row)
- return nullptr;
+ if (!start_row) {
+ return base::ErrStatus("callsite with id %" PRIu32 " not found", start_id);
+ }
// Iteratively walk the parent_id chain to construct the list of callstack
// entries, each pointing at a frame.
@@ -264,13 +270,14 @@
for (uint32_t i = 0; i < base_rowmap.size(); i++)
start_id_vals->Append(start_id);
- return std::unique_ptr<Table>(new Table(
+ table_return.reset(new Table(
cs_table.Apply(std::move(base_rowmap))
.ExtendWithColumn("annotation", std::move(annotation_vals),
TypedColumn<StringPool::Id>::default_flags())
.ExtendWithColumn("start_id", std::move(start_id_vals),
TypedColumn<uint32_t>::default_flags() |
TypedColumn<uint32_t>::kHidden)));
+ return base::OkStatus();
}
uint32_t ExperimentalAnnotatedStackGenerator::EstimateRowCount() {
diff --git a/src/trace_processor/dynamic/experimental_annotated_stack_generator.h b/src/trace_processor/dynamic/experimental_annotated_stack_generator.h
index f61c166..8b13536 100644
--- a/src/trace_processor/dynamic/experimental_annotated_stack_generator.h
+++ b/src/trace_processor/dynamic/experimental_annotated_stack_generator.h
@@ -38,10 +38,11 @@
Table::Schema CreateSchema() override;
std::string TableName() override;
uint32_t EstimateRowCount() override;
- util::Status ValidateConstraints(const QueryConstraints&) override;
- std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob,
- const BitVector& cols_used) override;
+ base::Status ValidateConstraints(const QueryConstraints&) override;
+ base::Status ComputeTable(const std::vector<Constraint>& cs,
+ const std::vector<Order>& ob,
+ const BitVector& cols_used,
+ std::unique_ptr<Table>& table_return) override;
private:
TraceProcessorContext* context_ = nullptr;
diff --git a/src/trace_processor/dynamic/experimental_counter_dur_generator.cc b/src/trace_processor/dynamic/experimental_counter_dur_generator.cc
index 530fe39..ce60d47 100644
--- a/src/trace_processor/dynamic/experimental_counter_dur_generator.cc
+++ b/src/trace_processor/dynamic/experimental_counter_dur_generator.cc
@@ -43,15 +43,16 @@
return counter_table_->row_count();
}
-util::Status ExperimentalCounterDurGenerator::ValidateConstraints(
+base::Status ExperimentalCounterDurGenerator::ValidateConstraints(
const QueryConstraints&) {
- return util::OkStatus();
+ return base::OkStatus();
}
-std::unique_ptr<Table> ExperimentalCounterDurGenerator::ComputeTable(
+base::Status ExperimentalCounterDurGenerator::ComputeTable(
const std::vector<Constraint>&,
const std::vector<Order>&,
- const BitVector&) {
+ const BitVector&,
+ std::unique_ptr<Table>& table_return) {
if (!dur_column_) {
dur_column_.reset(
new NullableVector<int64_t>(ComputeDurColumn(*counter_table_)));
@@ -65,7 +66,8 @@
.ExtendWithColumn("delta", std::move(delta_column_.get()),
TypedColumn<int64_t>::default_flags());
- return std::unique_ptr<Table>(new Table(t.Copy()));
+ table_return.reset(new Table(t.Copy()));
+ return base::OkStatus();
}
// static
diff --git a/src/trace_processor/dynamic/experimental_counter_dur_generator.h b/src/trace_processor/dynamic/experimental_counter_dur_generator.h
index 4ec9f24..de7071e 100644
--- a/src/trace_processor/dynamic/experimental_counter_dur_generator.h
+++ b/src/trace_processor/dynamic/experimental_counter_dur_generator.h
@@ -33,10 +33,11 @@
Table::Schema CreateSchema() override;
std::string TableName() override;
uint32_t EstimateRowCount() override;
- util::Status ValidateConstraints(const QueryConstraints&) override;
- std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>&,
- const std::vector<Order>&,
- const BitVector& cols_used) override;
+ base::Status ValidateConstraints(const QueryConstraints&) override;
+ base::Status ComputeTable(const std::vector<Constraint>& cs,
+ const std::vector<Order>& ob,
+ const BitVector& cols_used,
+ std::unique_ptr<Table>& table_return) override;
// public + static for testing
static NullableVector<int64_t> ComputeDurColumn(const Table& table);
diff --git a/src/trace_processor/dynamic/experimental_flamegraph_generator.cc b/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
index 1475eab..bcecec1 100644
--- a/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
+++ b/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
@@ -285,7 +285,7 @@
// For filtering, this method uses the same constraints as
// ExperimentalFlamegraphGenerator::GetFlamegraphInputValues and should
// therefore be kept in sync.
-util::Status ExperimentalFlamegraphGenerator::ValidateConstraints(
+base::Status ExperimentalFlamegraphGenerator::ValidateConstraints(
const QueryConstraints& qc) {
using T = tables::ExperimentalFlamegraphNodesTable;
@@ -318,14 +318,15 @@
std::find_if(cs.begin(), cs.end(), profile_type_fn) != cs.end();
return has_ts_cs && (has_upid_cs || has_upid_group_cs) && has_profile_type_cs
- ? util::OkStatus()
- : util::ErrStatus("Failed to find required constraints");
+ ? base::OkStatus()
+ : base::ErrStatus("Failed to find required constraints");
}
-std::unique_ptr<Table> ExperimentalFlamegraphGenerator::ComputeTable(
+base::Status ExperimentalFlamegraphGenerator::ComputeTable(
const std::vector<Constraint>& cs,
const std::vector<Order>&,
- const BitVector&) {
+ const BitVector&,
+ std::unique_ptr<Table>& table_return) {
// Get the input column values and compute the flamegraph using them.
auto values = GetFlamegraphInputValues(cs);
@@ -352,9 +353,8 @@
table->mutable_focus_str()->Set(i, focus_id);
}
}
- // We need to explicitly std::move as clang complains about a bug in old
- // compilers otherwise (-Wreturn-std-move-in-c++11).
- return std::move(table);
+ table_return = std::move(table);
+ return base::OkStatus();
}
Table::Schema ExperimentalFlamegraphGenerator::CreateSchema() {
diff --git a/src/trace_processor/dynamic/experimental_flamegraph_generator.h b/src/trace_processor/dynamic/experimental_flamegraph_generator.h
index c8531ad..4ec3cbc 100644
--- a/src/trace_processor/dynamic/experimental_flamegraph_generator.h
+++ b/src/trace_processor/dynamic/experimental_flamegraph_generator.h
@@ -47,10 +47,11 @@
Table::Schema CreateSchema() override;
std::string TableName() override;
uint32_t EstimateRowCount() override;
- util::Status ValidateConstraints(const QueryConstraints&) override;
- std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob,
- const BitVector& cols_used) override;
+ base::Status ValidateConstraints(const QueryConstraints&) override;
+ base::Status ComputeTable(const std::vector<Constraint>& cs,
+ const std::vector<Order>& ob,
+ const BitVector& cols_used,
+ std::unique_ptr<Table>& table_return) override;
private:
TraceProcessorContext* context_ = nullptr;
diff --git a/src/trace_processor/dynamic/experimental_flat_slice_generator.cc b/src/trace_processor/dynamic/experimental_flat_slice_generator.cc
index 4e8d697..48271b5 100644
--- a/src/trace_processor/dynamic/experimental_flat_slice_generator.cc
+++ b/src/trace_processor/dynamic/experimental_flat_slice_generator.cc
@@ -28,7 +28,7 @@
TraceProcessorContext* context)
: context_(context) {}
-util::Status ExperimentalFlatSliceGenerator::ValidateConstraints(
+base::Status ExperimentalFlatSliceGenerator::ValidateConstraints(
const QueryConstraints& qc) {
using CI = tables::ExperimentalFlatSliceTable::ColumnIndex;
bool has_start_bound = false;
@@ -40,14 +40,15 @@
c.op == SQLITE_INDEX_CONSTRAINT_EQ;
}
return has_start_bound && has_end_bound
- ? util::OkStatus()
- : util::ErrStatus("Failed to find required constraints");
+ ? base::OkStatus()
+ : base::ErrStatus("Failed to find required constraints");
}
-std::unique_ptr<Table> ExperimentalFlatSliceGenerator::ComputeTable(
+base::Status ExperimentalFlatSliceGenerator::ComputeTable(
const std::vector<Constraint>& cs,
const std::vector<Order>&,
- const BitVector&) {
+ const BitVector&,
+ std::unique_ptr<Table>& table_return) {
using CI = tables::ExperimentalFlatSliceTable::ColumnIndex;
auto start_it = std::find_if(cs.begin(), cs.end(), [](const Constraint& c) {
return c.col_idx == static_cast<uint32_t>(CI::start_bound) &&
@@ -57,11 +58,14 @@
return c.col_idx == static_cast<uint32_t>(CI::end_bound) &&
c.op == FilterOp::kEq;
});
+ // TODO(rsavitski): consider checking the values' types (in case of erroneous
+ // queries passing e.g. null).
int64_t start_bound = start_it->value.AsLong();
int64_t end_bound = end_it->value.AsLong();
- return ComputeFlatSliceTable(context_->storage->slice_table(),
- context_->storage->mutable_string_pool(),
- start_bound, end_bound);
+ table_return = ComputeFlatSliceTable(context_->storage->slice_table(),
+ context_->storage->mutable_string_pool(),
+ start_bound, end_bound);
+ return base::OkStatus();
}
std::unique_ptr<tables::ExperimentalFlatSliceTable>
diff --git a/src/trace_processor/dynamic/experimental_flat_slice_generator.h b/src/trace_processor/dynamic/experimental_flat_slice_generator.h
index 480e477..0083457 100644
--- a/src/trace_processor/dynamic/experimental_flat_slice_generator.h
+++ b/src/trace_processor/dynamic/experimental_flat_slice_generator.h
@@ -60,10 +60,11 @@
Table::Schema CreateSchema() override;
std::string TableName() override;
uint32_t EstimateRowCount() override;
- util::Status ValidateConstraints(const QueryConstraints&) override;
- std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob,
- const BitVector& cols_used) override;
+ base::Status ValidateConstraints(const QueryConstraints&) override;
+ base::Status ComputeTable(const std::vector<Constraint>& cs,
+ const std::vector<Order>& ob,
+ const BitVector& cols_used,
+ std::unique_ptr<Table>& table_return) override;
// Visibile for testing.
static std::unique_ptr<tables::ExperimentalFlatSliceTable>
diff --git a/src/trace_processor/dynamic/experimental_sched_upid_generator.cc b/src/trace_processor/dynamic/experimental_sched_upid_generator.cc
index 60d325f..f0cd061 100644
--- a/src/trace_processor/dynamic/experimental_sched_upid_generator.cc
+++ b/src/trace_processor/dynamic/experimental_sched_upid_generator.cc
@@ -41,21 +41,24 @@
return sched_slice_table_->row_count();
}
-util::Status ExperimentalSchedUpidGenerator::ValidateConstraints(
+base::Status ExperimentalSchedUpidGenerator::ValidateConstraints(
const QueryConstraints&) {
- return util::OkStatus();
+ return base::OkStatus();
}
-std::unique_ptr<Table> ExperimentalSchedUpidGenerator::ComputeTable(
+base::Status ExperimentalSchedUpidGenerator::ComputeTable(
const std::vector<Constraint>&,
const std::vector<Order>&,
- const BitVector&) {
+ const BitVector&,
+ std::unique_ptr<Table>& table_return) {
if (!upid_column_) {
upid_column_.reset(new NullableVector<uint32_t>(ComputeUpidColumn()));
}
- return std::unique_ptr<Table>(new Table(sched_slice_table_->ExtendWithColumn(
- "upid", upid_column_.get(),
- TypedColumn<base::Optional<uint32_t>>::default_flags())));
+ table_return =
+ std::unique_ptr<Table>(new Table(sched_slice_table_->ExtendWithColumn(
+ "upid", upid_column_.get(),
+ TypedColumn<base::Optional<uint32_t>>::default_flags())));
+ return base::OkStatus();
}
NullableVector<uint32_t> ExperimentalSchedUpidGenerator::ComputeUpidColumn() {
diff --git a/src/trace_processor/dynamic/experimental_sched_upid_generator.h b/src/trace_processor/dynamic/experimental_sched_upid_generator.h
index e144eea..569e212 100644
--- a/src/trace_processor/dynamic/experimental_sched_upid_generator.h
+++ b/src/trace_processor/dynamic/experimental_sched_upid_generator.h
@@ -35,10 +35,11 @@
Table::Schema CreateSchema() override;
std::string TableName() override;
uint32_t EstimateRowCount() override;
- util::Status ValidateConstraints(const QueryConstraints&) override;
- std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>&,
- const std::vector<Order>&,
- const BitVector& cols_used) override;
+ base::Status ValidateConstraints(const QueryConstraints&) override;
+ base::Status ComputeTable(const std::vector<Constraint>& cs,
+ const std::vector<Order>& ob,
+ const BitVector& cols_used,
+ std::unique_ptr<Table>& table_return) override;
private:
NullableVector<uint32_t> ComputeUpidColumn();
diff --git a/src/trace_processor/dynamic/experimental_slice_layout_generator.cc b/src/trace_processor/dynamic/experimental_slice_layout_generator.cc
index 9b842bb..c6153af 100644
--- a/src/trace_processor/dynamic/experimental_slice_layout_generator.cc
+++ b/src/trace_processor/dynamic/experimental_slice_layout_generator.cc
@@ -62,21 +62,22 @@
return slice_table_->row_count();
}
-util::Status ExperimentalSliceLayoutGenerator::ValidateConstraints(
+base::Status ExperimentalSliceLayoutGenerator::ValidateConstraints(
const QueryConstraints& cs) {
for (const auto& c : cs.constraints()) {
if (c.column == kFilterTrackIdsColumnIndex && sqlite_utils::IsOpEq(c.op)) {
- return util::OkStatus();
+ return base::OkStatus();
}
}
- return util::ErrStatus(
+ return base::ErrStatus(
"experimental_slice_layout must have filter_track_ids constraint");
}
-std::unique_ptr<Table> ExperimentalSliceLayoutGenerator::ComputeTable(
+base::Status ExperimentalSliceLayoutGenerator::ComputeTable(
const std::vector<Constraint>& cs,
const std::vector<Order>&,
- const BitVector&) {
+ const BitVector&,
+ std::unique_ptr<Table>& table_return) {
std::set<TrackId> selected_tracks;
std::string filter_string = "";
for (const auto& c : cs) {
@@ -100,7 +101,8 @@
// Try and find the table in the cache.
auto it = layout_table_cache_.find(filter_id);
if (it != layout_table_cache_.end()) {
- return std::unique_ptr<Table>(new Table(it->second.Copy()));
+ table_return.reset(new Table(it->second.Copy()));
+ return base::OkStatus();
}
// Find all the slices for the tracks we want to filter and create a RowMap
@@ -125,7 +127,9 @@
// Compute the table and add it to the cache for future use.
Table layout_table = ComputeLayoutTable(filtered_table, filter_id);
auto res = layout_table_cache_.emplace(filter_id, std::move(layout_table));
- return std::unique_ptr<Table>(new Table(res.first->second.Copy()));
+
+ table_return.reset(new Table(res.first->second.Copy()));
+ return base::OkStatus();
}
// Build up a table of slice id -> root slice id by observing each
diff --git a/src/trace_processor/dynamic/experimental_slice_layout_generator.h b/src/trace_processor/dynamic/experimental_slice_layout_generator.h
index b2d731e..cc27bb2 100644
--- a/src/trace_processor/dynamic/experimental_slice_layout_generator.h
+++ b/src/trace_processor/dynamic/experimental_slice_layout_generator.h
@@ -38,10 +38,11 @@
Table::Schema CreateSchema() override;
std::string TableName() override;
uint32_t EstimateRowCount() override;
- util::Status ValidateConstraints(const QueryConstraints&) override;
- std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>&,
- const std::vector<Order>&,
- const BitVector& cols_used) override;
+ base::Status ValidateConstraints(const QueryConstraints&) override;
+ base::Status ComputeTable(const std::vector<Constraint>& cs,
+ const std::vector<Order>& ob,
+ const BitVector& cols_used,
+ std::unique_ptr<Table>& table_return) override;
private:
Table ComputeLayoutTable(const Table& table, StringPool::Id filter_id);
diff --git a/src/trace_processor/dynamic/experimental_slice_layout_generator_unittest.cc b/src/trace_processor/dynamic/experimental_slice_layout_generator_unittest.cc
index efb8ae8..81fdb7d 100644
--- a/src/trace_processor/dynamic/experimental_slice_layout_generator_unittest.cc
+++ b/src/trace_processor/dynamic/experimental_slice_layout_generator_unittest.cc
@@ -104,9 +104,11 @@
ExperimentalSliceLayoutGenerator gen(&pool, &slice_table);
- std::unique_ptr<Table> table = gen.ComputeTable(
+ std::unique_ptr<Table> table;
+ auto status = gen.ComputeTable(
{Constraint{kColumn, FilterOp::kEq, SqlValue::String("1")}}, {},
- BitVector());
+ BitVector(), table);
+ EXPECT_TRUE(status.ok());
ExpectOutput(*table, R"(
#####
)");
@@ -123,9 +125,11 @@
ExperimentalSliceLayoutGenerator gen(&pool, &slice_table);
- std::unique_ptr<Table> table = gen.ComputeTable(
+ std::unique_ptr<Table> table;
+ auto status = gen.ComputeTable(
{Constraint{kColumn, FilterOp::kEq, SqlValue::String("1")}}, {},
- BitVector());
+ BitVector(), table);
+ EXPECT_TRUE(status.ok());
ExpectOutput(*table, R"(
#####
#####
@@ -147,9 +151,11 @@
ExperimentalSliceLayoutGenerator gen(&pool, &slice_table);
- std::unique_ptr<Table> table = gen.ComputeTable(
+ std::unique_ptr<Table> table;
+ auto status = gen.ComputeTable(
{Constraint{kColumn, FilterOp::kEq, SqlValue::String("1")}}, {},
- BitVector());
+ BitVector(), table);
+ EXPECT_TRUE(status.ok());
ExpectOutput(*table, R"(
#####
####
@@ -178,9 +184,11 @@
ExperimentalSliceLayoutGenerator gen(&pool, &slice_table);
- std::unique_ptr<Table> table = gen.ComputeTable(
+ std::unique_ptr<Table> table;
+ auto status = gen.ComputeTable(
{Constraint{kColumn, FilterOp::kEq, SqlValue::String("1,2")}}, {},
- BitVector());
+ BitVector(), table);
+ EXPECT_TRUE(status.ok());
ExpectOutput(*table, R"(
####
##
@@ -214,9 +222,11 @@
ExperimentalSliceLayoutGenerator gen(&pool, &slice_table);
- std::unique_ptr<Table> table = gen.ComputeTable(
+ std::unique_ptr<Table> table;
+ auto status = gen.ComputeTable(
{Constraint{kColumn, FilterOp::kEq, SqlValue::String("1,2")}}, {},
- BitVector());
+ BitVector(), table);
+ EXPECT_TRUE(status.ok());
ExpectOutput(*table, R"(
#### ####
## ##
@@ -247,9 +257,11 @@
base::ignore_result(q);
ExperimentalSliceLayoutGenerator gen(&pool, &slice_table);
- std::unique_ptr<Table> table = gen.ComputeTable(
+ std::unique_ptr<Table> table;
+ auto status = gen.ComputeTable(
{Constraint{kColumn, FilterOp::kEq, SqlValue::String("1,2")}}, {},
- BitVector());
+ BitVector(), table);
+ EXPECT_TRUE(status.ok());
ExpectOutput(*table, R"(
####
##
diff --git a/src/trace_processor/dynamic/thread_state_generator.cc b/src/trace_processor/dynamic/thread_state_generator.cc
index f68f127..7790a1f 100644
--- a/src/trace_processor/dynamic/thread_state_generator.cc
+++ b/src/trace_processor/dynamic/thread_state_generator.cc
@@ -31,15 +31,16 @@
ThreadStateGenerator::~ThreadStateGenerator() = default;
-util::Status ThreadStateGenerator::ValidateConstraints(
+base::Status ThreadStateGenerator::ValidateConstraints(
const QueryConstraints&) {
- return util::OkStatus();
+ return base::OkStatus();
}
-std::unique_ptr<Table> ThreadStateGenerator::ComputeTable(
+base::Status ThreadStateGenerator::ComputeTable(
const std::vector<Constraint>&,
const std::vector<Order>&,
- const BitVector&) {
+ const BitVector&,
+ std::unique_ptr<Table>& table_return) {
if (!unsorted_thread_state_table_) {
int64_t trace_end_ts =
context_->storage->GetTraceTimestampBoundsNs().second;
@@ -53,8 +54,11 @@
sorted_thread_state_table_ = unsorted_thread_state_table_->Sort(
{unsorted_thread_state_table_->ts().ascending()});
}
+ // TODO(rsavitski): return base::ErrStatus instead?
PERFETTO_CHECK(sorted_thread_state_table_);
- return std::unique_ptr<Table>(new Table(sorted_thread_state_table_->Copy()));
+ table_return =
+ std::unique_ptr<Table>(new Table(sorted_thread_state_table_->Copy()));
+ return base::OkStatus();
}
std::unique_ptr<tables::ThreadStateTable>
@@ -311,7 +315,7 @@
ThreadSchedInfo& info = state_map[utid];
base::Optional<Variadic> opt_value;
- util::Status status =
+ base::Status status =
context_->storage->ExtractArg(arg_set_id, "io_wait", &opt_value);
// We can't do anything better than ignoring any errors here.
diff --git a/src/trace_processor/dynamic/thread_state_generator.h b/src/trace_processor/dynamic/thread_state_generator.h
index db97925..8e111de 100644
--- a/src/trace_processor/dynamic/thread_state_generator.h
+++ b/src/trace_processor/dynamic/thread_state_generator.h
@@ -38,10 +38,11 @@
Table::Schema CreateSchema() override;
std::string TableName() override;
uint32_t EstimateRowCount() override;
- util::Status ValidateConstraints(const QueryConstraints&) override;
- std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob,
- const BitVector& cols_used) override;
+ base::Status ValidateConstraints(const QueryConstraints&) override;
+ base::Status ComputeTable(const std::vector<Constraint>& cs,
+ const std::vector<Order>& ob,
+ const BitVector& cols_used,
+ std::unique_ptr<Table>& table_return) override;
// Visible for testing.
std::unique_ptr<tables::ThreadStateTable> ComputeThreadStateTable(
diff --git a/src/trace_processor/importers/proto/profile_module.cc b/src/trace_processor/importers/proto/profile_module.cc
index 61b2567..f679ca9 100644
--- a/src/trace_processor/importers/proto/profile_module.cc
+++ b/src/trace_processor/importers/proto/profile_module.cc
@@ -249,9 +249,6 @@
ts, static_cast<double>(sample.timebase_count()),
sampling_stream.timebase_track_id);
- // TODO(rsavitski): empty callsite is not an error for counter-only samples.
- // But consider identifying sequences which *should* have a callstack in every
- // sample, as an invalid stack there is a bug.
SequenceStackProfileTracker& stack_tracker =
sequence_state->state()->sequence_stack_profile_tracker();
ProfilePacketInternLookup intern_lookup(sequence_state);
@@ -259,6 +256,27 @@
base::Optional<CallsiteId> cs_id =
stack_tracker.FindOrInsertCallstack(callstack_iid, &intern_lookup);
+ // A failed lookup of the interned callstack can mean either:
+ // (a) This is a counter-only profile without callstacks. Due to an
+ // implementation quirk, these packets still set callstack_iid
+ // corresponding to a callstack with no frames. To reliably identify this
+ // case (without resorting to config parsing) we further need to rely on
+ // the fact that the implementation (callstack_trie.h) always assigns this
+ // callstack the id "1". Such callstacks should not occur outside of
+ // counter-only profiles, as there should always be at least a synthetic
+ // error frame if the unwinding completely failed.
+ // (b) This is a ring-buffer profile where some of the referenced internings
+ // have been overwritten, and the build predates perf_sample_defaults and
+ // SEQ_NEEDS_INCREMENTAL_STATE sequence flag in perf_sample packets.
+ // Such packets should be discarded.
+ if (!cs_id && callstack_iid != 1) {
+ PERFETTO_DLOG("Discarding perf_sample since callstack_iid [%" PRIu64
+ "] references a missing/partially lost interning according "
+ "to stack_profile_tracker",
+ callstack_iid);
+ return;
+ }
+
UniqueTid utid =
context_->process_tracker->UpdateThread(sample.tid(), sample.pid());
diff --git a/src/trace_processor/metrics/sql/android/android_sysui_cuj.sql b/src/trace_processor/metrics/sql/android/android_sysui_cuj.sql
index 48b5b41..691f690 100644
--- a/src/trace_processor/metrics/sql/android/android_sysui_cuj.sql
+++ b/src/trace_processor/metrics/sql/android/android_sysui_cuj.sql
@@ -374,6 +374,10 @@
WHERE (state = 'R' OR state = 'R+')
GROUP BY frame_number
HAVING SUM(dur) > 8000000
+ AND SUM(dur) > (
+ SELECT 0.4 * dur_main_thread
+ FROM android_sysui_cuj_frames fs
+ WHERE fs.frame_number = android_sysui_cuj_main_thread_state.frame_number)
UNION ALL
SELECT
@@ -394,6 +398,10 @@
WHERE (state = 'R' OR state = 'R+')
GROUP BY frame_number
HAVING SUM(dur) > 8000000
+ AND SUM(dur) > (
+ SELECT 0.4 * dur_render_thread
+ FROM android_sysui_cuj_frames fs
+ WHERE fs.frame_number = android_sysui_cuj_render_thread_state.frame_number)
UNION ALL
SELECT
diff --git a/src/trace_processor/metrics/sql/android/process_metadata.sql b/src/trace_processor/metrics/sql/android/process_metadata.sql
index 6873bb2..7167e12 100644
--- a/src/trace_processor/metrics/sql/android/process_metadata.sql
+++ b/src/trace_processor/metrics/sql/android/process_metadata.sql
@@ -26,7 +26,8 @@
CREATE TABLE process_metadata_table AS
SELECT
process.upid,
- -- TODO(b/169226092) remove this workaround
+ -- workaround for b/169226092: the bug has been fixed it Android T, but
+ -- we support ingesting traces from older Android versions.
CASE
-- cmdline gets rewritten after fork, if these are still there we must
-- have seen a racy capture.
diff --git a/src/trace_processor/sqlite/db_sqlite_table.cc b/src/trace_processor/sqlite/db_sqlite_table.cc
index b6897e1..1146a64 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table.cc
@@ -123,7 +123,7 @@
// Figure out if the table needs explicit args (in the form of constraints
// on hidden columns) passed to it in order to make the query valid.
- util::Status status = generator->ValidateConstraints(
+ base::Status status = generator->ValidateConstraints(
QueryConstraints(std::numeric_limits<uint64_t>::max()));
bool requires_args = !status.ok();
@@ -133,9 +133,9 @@
false, requires_args);
}
-util::Status DbSqliteTable::Init(int, const char* const*, Schema* schema) {
+base::Status DbSqliteTable::Init(int, const char* const*, Schema* schema) {
*schema = ComputeSchema(schema_, name().c_str());
- return util::OkStatus();
+ return base::OkStatus();
}
SqliteTable::Schema DbSqliteTable::ComputeSchema(const Table::Schema& schema,
@@ -169,7 +169,7 @@
BestIndex(schema_, static_table_->row_count(), qc, info);
break;
case TableComputation::kDynamic:
- util::Status status = generator_->ValidateConstraints(qc);
+ base::Status status = generator_->ValidateConstraints(qc);
if (!status.ok())
return SQLITE_CONSTRAINT;
BestIndex(schema_, generator_->EstimateRowCount(), qc, info);
@@ -451,13 +451,21 @@
});
// If we have a dynamically created table, regenerate the table based on
// the new constraints.
+ std::unique_ptr<Table> computed_table;
BitVector cols_used_bv = ColsUsedBitVector(
qc.cols_used(), db_sqlite_table_->schema_.columns.size());
- dynamic_table_ = db_sqlite_table_->generator_->ComputeTable(
- constraints_, orders_, cols_used_bv);
- upstream_table_ = dynamic_table_.get();
- if (!upstream_table_)
+ auto status = db_sqlite_table_->generator_->ComputeTable(
+ constraints_, orders_, cols_used_bv, computed_table);
+
+ if (!status.ok()) {
+ auto* sqlite_err = sqlite3_mprintf(
+ "%s: %s", db_sqlite_table_->name().c_str(), status.c_message());
+ db_sqlite_table_->SetErrorMessage(sqlite_err);
return SQLITE_CONSTRAINT;
+ }
+ PERFETTO_DCHECK(computed_table);
+ dynamic_table_ = std::move(computed_table);
+ upstream_table_ = dynamic_table_.get();
break;
}
}
diff --git a/src/trace_processor/sqlite/db_sqlite_table.h b/src/trace_processor/sqlite/db_sqlite_table.h
index 1e713b2..e1a35b8 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.h
+++ b/src/trace_processor/sqlite/db_sqlite_table.h
@@ -57,17 +57,19 @@
// Checks that the constraint set is valid.
//
- // Returning util::OkStatus means that the required constraints are present
+ // Returning base::OkStatus means that the required constraints are present
// in |qc| for dynamically computing the table (e.g. any required
// constraints on hidden columns for table-valued functions are present).
- virtual util::Status ValidateConstraints(const QueryConstraints& qc) = 0;
+ virtual base::Status ValidateConstraints(const QueryConstraints& qc) = 0;
// Dynamically computes the table given the constraints and order by
// vectors.
- virtual std::unique_ptr<Table> ComputeTable(
- const std::vector<Constraint>& cs,
- const std::vector<Order>& ob,
- const BitVector& cols_used) = 0;
+ // The table is returned via |table_return|. There are no guarantees on
+ // its value if the method returns a non-ok status.
+ virtual base::Status ComputeTable(const std::vector<Constraint>& cs,
+ const std::vector<Order>& ob,
+ const BitVector& cols_used,
+ std::unique_ptr<Table>& table_return) = 0;
};
class Cursor : public SqliteTable::Cursor {
@@ -166,7 +168,7 @@
virtual ~DbSqliteTable() override;
// Table implementation.
- util::Status Init(int,
+ base::Status Init(int,
const char* const*,
SqliteTable::Schema*) override final;
std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
diff --git a/src/traced/probes/android_log/android_log_data_source.cc b/src/traced/probes/android_log/android_log_data_source.cc
index 286d138..4d8d309 100644
--- a/src/traced/probes/android_log/android_log_data_source.cc
+++ b/src/traced/probes/android_log/android_log_data_source.cc
@@ -89,6 +89,7 @@
const ProbesDataSource::Descriptor AndroidLogDataSource::descriptor = {
/*name*/ "android.log",
/*flags*/ Descriptor::kFlagsNone,
+ /*fill_descriptor_func*/ nullptr,
};
AndroidLogDataSource::AndroidLogDataSource(DataSourceConfig ds_config,
diff --git a/src/traced/probes/filesystem/inode_file_data_source.cc b/src/traced/probes/filesystem/inode_file_data_source.cc
index 5362f2c..8185a6e 100644
--- a/src/traced/probes/filesystem/inode_file_data_source.cc
+++ b/src/traced/probes/filesystem/inode_file_data_source.cc
@@ -83,6 +83,7 @@
const ProbesDataSource::Descriptor InodeFileDataSource::descriptor = {
/*name*/ "linux.inode_file_map",
/*flags*/ Descriptor::kFlagsNone,
+ /*fill_descriptor_func*/ nullptr,
};
void CreateStaticDeviceToInodeMap(
@@ -106,7 +107,7 @@
}
InodeFileDataSource::InodeFileDataSource(
- DataSourceConfig ds_config,
+ const DataSourceConfig& ds_config,
base::TaskRunner* task_runner,
TracingSessionID session_id,
std::map<BlockDeviceID, std::unordered_map<Inode, InodeMapValue>>*
diff --git a/src/traced/probes/filesystem/inode_file_data_source.h b/src/traced/probes/filesystem/inode_file_data_source.h
index 54a5d4d..62cc4d7 100644
--- a/src/traced/probes/filesystem/inode_file_data_source.h
+++ b/src/traced/probes/filesystem/inode_file_data_source.h
@@ -56,7 +56,7 @@
static const ProbesDataSource::Descriptor descriptor;
InodeFileDataSource(
- DataSourceConfig,
+ const DataSourceConfig&,
base::TaskRunner*,
TracingSessionID,
std::map<BlockDeviceID, std::unordered_map<Inode, InodeMapValue>>*
diff --git a/src/traced/probes/ftrace/BUILD.gn b/src/traced/probes/ftrace/BUILD.gn
index dcc8ca1..a047684 100644
--- a/src/traced/probes/ftrace/BUILD.gn
+++ b/src/traced/probes/ftrace/BUILD.gn
@@ -113,6 +113,7 @@
"..:data_source",
"../../../../gn:default_deps",
"../../../../include/perfetto/ext/traced",
+ "../../../../protos/perfetto/common:zero",
"../../../../protos/perfetto/trace:zero",
"../../../../protos/perfetto/trace/interned_data:zero",
"../../../../protos/perfetto/trace/profiling:zero",
diff --git a/src/traced/probes/ftrace/ftrace_data_source.cc b/src/traced/probes/ftrace/ftrace_data_source.cc
index a801e05..5b6ac34 100644
--- a/src/traced/probes/ftrace/ftrace_data_source.cc
+++ b/src/traced/probes/ftrace/ftrace_data_source.cc
@@ -16,19 +16,68 @@
#include "src/traced/probes/ftrace/ftrace_data_source.h"
+#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/ext/base/subprocess.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "perfetto/tracing/core/data_source_descriptor.h"
#include "src/traced/probes/ftrace/cpu_reader.h"
#include "src/traced/probes/ftrace/ftrace_controller.h"
+#include "protos/perfetto/common/ftrace_descriptor.pbzero.h"
#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
#include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
namespace perfetto {
+namespace {
+
+void FillFtraceDataSourceDescriptor(DataSourceDescriptor* dsd) {
+ protozero::HeapBuffered<protos::pbzero::FtraceDescriptor> ftd;
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ base::Subprocess p({"/system/bin/atrace", "--list_categories"});
+ p.args.stdin_mode = base::Subprocess::InputMode::kDevNull;
+ p.args.stdout_mode = base::Subprocess::OutputMode::kBuffer;
+ p.args.stderr_mode = base::Subprocess::OutputMode::kBuffer;
+ bool res = p.Call(/*timeout_ms=*/20000);
+ if (res) {
+ for (base::StringSplitter ss(std::move(p.output()), '\n'); ss.Next();) {
+ base::StringView line(ss.cur_token(), ss.cur_token_size());
+ size_t pos = line.find(" - ");
+ if (pos == line.npos) {
+ continue;
+ }
+ base::StringView name = line.substr(0, pos);
+ // Trim initial whitespaces
+ auto it = std::find_if(name.begin(), name.end(),
+ [](char c) { return c != ' '; });
+ name = name.substr(static_cast<size_t>(it - name.begin()));
+
+ base::StringView desc = line.substr(pos + 3);
+
+ protos::pbzero::FtraceDescriptor::AtraceCategory* cat =
+ ftd->add_atrace_categories();
+ cat->set_name(name.data(), name.size());
+ cat->set_description(desc.data(), desc.size());
+ }
+ } else {
+ PERFETTO_ELOG("Failed to run atrace --list_categories code(%d): %s",
+ p.returncode(), p.output().c_str());
+ }
+#endif
+
+ dsd->set_ftrace_descriptor_raw(ftd.SerializeAsString());
+}
+
+} // namespace
// static
const ProbesDataSource::Descriptor FtraceDataSource::descriptor = {
/*name*/ "linux.ftrace",
/*flags*/ Descriptor::kFlagsNone,
+ /*fill_descriptor_func*/ &FillFtraceDataSourceDescriptor,
};
FtraceDataSource::FtraceDataSource(
diff --git a/src/traced/probes/initial_display_state/initial_display_state_data_source.cc b/src/traced/probes/initial_display_state/initial_display_state_data_source.cc
index 332cbf5..85ea606 100644
--- a/src/traced/probes/initial_display_state/initial_display_state_data_source.cc
+++ b/src/traced/probes/initial_display_state/initial_display_state_data_source.cc
@@ -34,6 +34,7 @@
InitialDisplayStateDataSource::descriptor = {
/* name */ "android.polled_state",
/* flags */ Descriptor::kFlagsNone,
+ /*fill_descriptor_func*/ nullptr,
};
InitialDisplayStateDataSource::InitialDisplayStateDataSource(
diff --git a/src/traced/probes/metatrace/metatrace_data_source.cc b/src/traced/probes/metatrace/metatrace_data_source.cc
index 1c5a2a7..6849579 100644
--- a/src/traced/probes/metatrace/metatrace_data_source.cc
+++ b/src/traced/probes/metatrace/metatrace_data_source.cc
@@ -32,6 +32,7 @@
const ProbesDataSource::Descriptor MetatraceDataSource::descriptor = {
/*name*/ MetatraceWriter::kDataSourceName,
/*flags*/ Descriptor::kFlagsNone,
+ /*fill_descriptor_func*/ nullptr,
};
MetatraceDataSource::MetatraceDataSource(base::TaskRunner* task_runner,
diff --git a/src/traced/probes/packages_list/packages_list_data_source.cc b/src/traced/probes/packages_list/packages_list_data_source.cc
index f9919b8..8276f62 100644
--- a/src/traced/probes/packages_list/packages_list_data_source.cc
+++ b/src/traced/probes/packages_list/packages_list_data_source.cc
@@ -32,6 +32,7 @@
const ProbesDataSource::Descriptor PackagesListDataSource::descriptor = {
/*name*/ "android.packages_list",
/*flags*/ Descriptor::kFlagsNone,
+ /*fill_descriptor_func*/ nullptr,
};
bool ParsePackagesListStream(protos::pbzero::PackagesList* packages_list_packet,
diff --git a/src/traced/probes/power/android_power_data_source.cc b/src/traced/probes/power/android_power_data_source.cc
index dac5bde..9d2d9a5 100644
--- a/src/traced/probes/power/android_power_data_source.cc
+++ b/src/traced/probes/power/android_power_data_source.cc
@@ -51,6 +51,7 @@
const ProbesDataSource::Descriptor AndroidPowerDataSource::descriptor = {
/*name*/ "android.power",
/*flags*/ Descriptor::kHandlesIncrementalState,
+ /*fill_descriptor_func*/ nullptr,
};
// Dynamically loads the libperfetto_android_internal.so library which
diff --git a/src/traced/probes/power/linux_power_sysfs_data_source.cc b/src/traced/probes/power/linux_power_sysfs_data_source.cc
index ff1e8b4..2e7d66e 100644
--- a/src/traced/probes/power/linux_power_sysfs_data_source.cc
+++ b/src/traced/probes/power/linux_power_sysfs_data_source.cc
@@ -105,6 +105,7 @@
const ProbesDataSource::Descriptor LinuxPowerSysfsDataSource::descriptor = {
/*name*/ "linux.sysfs_power",
/*flags*/ Descriptor::kFlagsNone,
+ /*fill_descriptor_func*/ nullptr,
};
LinuxPowerSysfsDataSource::LinuxPowerSysfsDataSource(
diff --git a/src/traced/probes/probes_data_source.h b/src/traced/probes/probes_data_source.h
index 6ceef56..9025046 100644
--- a/src/traced/probes/probes_data_source.h
+++ b/src/traced/probes/probes_data_source.h
@@ -31,12 +31,16 @@
// Static properties for a data source. Needs to be available before
// instantiating each data source. It must have static lifetime.
struct Descriptor {
+ using FillDescriptorFunc = void (*)(DataSourceDescriptor*);
enum Flags : uint32_t {
kFlagsNone = 0,
kHandlesIncrementalState = 1 << 0,
};
const char* const name;
uint32_t flags;
+ // If not nullptr, called to fill data source specific fields in
+ // DataSourceDescriptor.
+ FillDescriptorFunc fill_descriptor_func;
};
ProbesDataSource(TracingSessionID, const Descriptor*);
diff --git a/src/traced/probes/probes_producer.cc b/src/traced/probes/probes_producer.cc
index ebe5745..8b9fc46 100644
--- a/src/traced/probes/probes_producer.cc
+++ b/src/traced/probes/probes_producer.cc
@@ -32,6 +32,7 @@
#include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
#include "perfetto/tracing/core/data_source_config.h"
#include "perfetto/tracing/core/data_source_descriptor.h"
+#include "perfetto/tracing/core/forward_decls.h"
#include "perfetto/tracing/core/trace_config.h"
#include "src/android_stats/statsd_logging_helper.h"
#include "src/traced/probes/android_log/android_log_data_source.h"
@@ -66,19 +67,6 @@
constexpr size_t kTracingSharedMemSizeHintBytes = 1024 * 1024;
constexpr size_t kTracingSharedMemPageSizeHintBytes = 32 * 1024;
-ProbesDataSource::Descriptor const* const kAllDataSources[]{
- &FtraceDataSource::descriptor, //
- &ProcessStatsDataSource::descriptor, //
- &InodeFileDataSource::descriptor, //
- &SysStatsDataSource::descriptor, //
- &AndroidPowerDataSource::descriptor, //
- &LinuxPowerSysfsDataSource::descriptor, //
- &AndroidLogDataSource::descriptor, //
- &PackagesListDataSource::descriptor, //
- &MetatraceDataSource::descriptor, //
- &SystemInfoDataSource::descriptor, //
- &InitialDisplayStateDataSource::descriptor, //
-};
} // namespace
// State transition diagram:
@@ -107,42 +95,6 @@
ftrace_.reset();
}
-void ProbesProducer::OnConnect() {
- PERFETTO_DCHECK(state_ == kConnecting);
- state_ = kConnected;
- ResetConnectionBackoff();
- PERFETTO_LOG("Connected to the service");
-
- // Register all the data sources.
- for (const FtraceDataSource::Descriptor* desc : kAllDataSources) {
- DataSourceDescriptor proto_desc;
- proto_desc.set_name(desc->name);
- proto_desc.set_will_notify_on_start(true);
- proto_desc.set_will_notify_on_stop(true);
- using Flags = ProbesDataSource::Descriptor::Flags;
- if (desc->flags & Flags::kHandlesIncrementalState)
- proto_desc.set_handles_incremental_state_clear(true);
- endpoint_->RegisterDataSource(proto_desc);
- }
-
- // Used by tracebox to synchronize with traced_probes being registered.
- if (all_data_sources_registered_cb_) {
- endpoint_->Sync(all_data_sources_registered_cb_);
- }
-}
-
-void ProbesProducer::OnDisconnect() {
- PERFETTO_DCHECK(state_ == kConnected || state_ == kConnecting);
- PERFETTO_LOG("Disconnected from tracing service");
- if (state_ == kConnected)
- return task_runner_->PostTask([this] { this->Restart(); });
-
- state_ = kNotConnected;
- IncreaseConnectionBackoff();
- task_runner_->PostDelayedTask([this] { this->Connect(); },
- connection_backoff_ms_);
-}
-
void ProbesProducer::Restart() {
// We lost the connection with the tracing service. At this point we need
// to reset all the data sources. Trying to handle that manually is going to
@@ -159,73 +111,9 @@
ConnectWithRetries(socket_name, task_runner);
}
-void ProbesProducer::SetupDataSource(DataSourceInstanceID instance_id,
- const DataSourceConfig& config) {
- PERFETTO_DLOG("SetupDataSource(id=%" PRIu64 ", name=%s)", instance_id,
- config.name().c_str());
- PERFETTO_DCHECK(data_sources_.count(instance_id) == 0);
- TracingSessionID session_id = config.tracing_session_id();
- PERFETTO_CHECK(session_id > 0);
-
- std::unique_ptr<ProbesDataSource> data_source;
- if (config.name() == FtraceDataSource::descriptor.name) {
- data_source = CreateFtraceDataSource(session_id, config);
- } else if (config.name() == InodeFileDataSource::descriptor.name) {
- data_source = CreateInodeFileDataSource(session_id, config);
- } else if (config.name() == ProcessStatsDataSource::descriptor.name) {
- data_source = CreateProcessStatsDataSource(session_id, config);
- } else if (config.name() == SysStatsDataSource::descriptor.name) {
- data_source = CreateSysStatsDataSource(session_id, config);
- } else if (config.name() == AndroidPowerDataSource::descriptor.name) {
- data_source = CreateAndroidPowerDataSource(session_id, config);
- } else if (config.name() == LinuxPowerSysfsDataSource::descriptor.name) {
- data_source = CreateLinuxPowerSysfsDataSource(session_id, config);
- } else if (config.name() == AndroidLogDataSource::descriptor.name) {
- data_source = CreateAndroidLogDataSource(session_id, config);
- } else if (config.name() == PackagesListDataSource::descriptor.name) {
- data_source = CreatePackagesListDataSource(session_id, config);
- } else if (config.name() == MetatraceDataSource::descriptor.name) {
- data_source = CreateMetatraceDataSource(session_id, config);
- } else if (config.name() == SystemInfoDataSource::descriptor.name) {
- data_source = CreateSystemInfoDataSource(session_id, config);
- } else if (config.name() == InitialDisplayStateDataSource::descriptor.name) {
- data_source = CreateInitialDisplayStateDataSource(session_id, config);
- }
-
- if (!data_source) {
- PERFETTO_ELOG("Failed to create data source '%s'", config.name().c_str());
- return;
- }
-
- session_data_sources_.emplace(session_id, data_source.get());
- data_sources_[instance_id] = std::move(data_source);
-}
-
-void ProbesProducer::StartDataSource(DataSourceInstanceID instance_id,
- const DataSourceConfig& config) {
- PERFETTO_DLOG("StartDataSource(id=%" PRIu64 ", name=%s)", instance_id,
- config.name().c_str());
- auto it = data_sources_.find(instance_id);
- if (it == data_sources_.end()) {
- // Can happen if SetupDataSource() failed (e.g. ftrace was busy).
- PERFETTO_ELOG("Data source id=%" PRIu64 " not found", instance_id);
- return;
- }
- ProbesDataSource* data_source = it->second.get();
- if (data_source->started)
- return;
- if (config.trace_duration_ms() != 0) {
- uint32_t timeout = 5000 + 2 * config.trace_duration_ms();
- watchdogs_.emplace(
- instance_id, base::Watchdog::GetInstance()->CreateFatalTimer(
- timeout, base::WatchdogCrashReason::kTraceDidntStop));
- }
- data_source->started = true;
- data_source->Start();
- endpoint_->NotifyDataSourceStarted(instance_id);
-}
-
-std::unique_ptr<ProbesDataSource> ProbesProducer::CreateFtraceDataSource(
+template <>
+std::unique_ptr<ProbesDataSource>
+ProbesProducer::CreateDSInstance<FtraceDataSource>(
TracingSessionID session_id,
const DataSourceConfig& config) {
// Don't retry if FtraceController::Create() failed once.
@@ -262,20 +150,24 @@
return std::unique_ptr<ProbesDataSource>(std::move(data_source));
}
-std::unique_ptr<ProbesDataSource> ProbesProducer::CreateInodeFileDataSource(
+template <>
+std::unique_ptr<ProbesDataSource>
+ProbesProducer::CreateDSInstance<InodeFileDataSource>(
TracingSessionID session_id,
- DataSourceConfig source_config) {
+ const DataSourceConfig& source_config) {
PERFETTO_LOG("Inode file map setup (target_buf=%" PRIu32 ")",
source_config.target_buffer());
auto buffer_id = static_cast<BufferID>(source_config.target_buffer());
if (system_inodes_.empty())
CreateStaticDeviceToInodeMap("/system", &system_inodes_);
return std::unique_ptr<InodeFileDataSource>(new InodeFileDataSource(
- std::move(source_config), task_runner_, session_id, &system_inodes_,
- &cache_, endpoint_->CreateTraceWriter(buffer_id)));
+ source_config, task_runner_, session_id, &system_inodes_, &cache_,
+ endpoint_->CreateTraceWriter(buffer_id)));
}
-std::unique_ptr<ProbesDataSource> ProbesProducer::CreateProcessStatsDataSource(
+template <>
+std::unique_ptr<ProbesDataSource>
+ProbesProducer::CreateDSInstance<ProcessStatsDataSource>(
TracingSessionID session_id,
const DataSourceConfig& config) {
auto buffer_id = static_cast<BufferID>(config.target_buffer());
@@ -284,7 +176,9 @@
std::unique_ptr<CpuFreqInfo>(new CpuFreqInfo())));
}
-std::unique_ptr<ProbesDataSource> ProbesProducer::CreateAndroidPowerDataSource(
+template <>
+std::unique_ptr<ProbesDataSource>
+ProbesProducer::CreateDSInstance<AndroidPowerDataSource>(
TracingSessionID session_id,
const DataSourceConfig& config) {
auto buffer_id = static_cast<BufferID>(config.target_buffer());
@@ -293,8 +187,9 @@
endpoint_->CreateTraceWriter(buffer_id)));
}
+template <>
std::unique_ptr<ProbesDataSource>
-ProbesProducer::CreateLinuxPowerSysfsDataSource(
+ProbesProducer::CreateDSInstance<LinuxPowerSysfsDataSource>(
TracingSessionID session_id,
const DataSourceConfig& config) {
auto buffer_id = static_cast<BufferID>(config.target_buffer());
@@ -303,7 +198,9 @@
endpoint_->CreateTraceWriter(buffer_id)));
}
-std::unique_ptr<ProbesDataSource> ProbesProducer::CreateAndroidLogDataSource(
+template <>
+std::unique_ptr<ProbesDataSource>
+ProbesProducer::CreateDSInstance<AndroidLogDataSource>(
TracingSessionID session_id,
const DataSourceConfig& config) {
auto buffer_id = static_cast<BufferID>(config.target_buffer());
@@ -312,7 +209,9 @@
endpoint_->CreateTraceWriter(buffer_id)));
}
-std::unique_ptr<ProbesDataSource> ProbesProducer::CreatePackagesListDataSource(
+template <>
+std::unique_ptr<ProbesDataSource>
+ProbesProducer::CreateDSInstance<PackagesListDataSource>(
TracingSessionID session_id,
const DataSourceConfig& config) {
auto buffer_id = static_cast<BufferID>(config.target_buffer());
@@ -320,7 +219,9 @@
config, session_id, endpoint_->CreateTraceWriter(buffer_id)));
}
-std::unique_ptr<ProbesDataSource> ProbesProducer::CreateSysStatsDataSource(
+template <>
+std::unique_ptr<ProbesDataSource>
+ProbesProducer::CreateDSInstance<SysStatsDataSource>(
TracingSessionID session_id,
const DataSourceConfig& config) {
auto buffer_id = static_cast<BufferID>(config.target_buffer());
@@ -329,7 +230,9 @@
std::unique_ptr<CpuFreqInfo>(new CpuFreqInfo())));
}
-std::unique_ptr<ProbesDataSource> ProbesProducer::CreateMetatraceDataSource(
+template <>
+std::unique_ptr<ProbesDataSource>
+ProbesProducer::CreateDSInstance<MetatraceDataSource>(
TracingSessionID session_id,
const DataSourceConfig& config) {
auto buffer_id = static_cast<BufferID>(config.target_buffer());
@@ -337,7 +240,9 @@
task_runner_, session_id, endpoint_->CreateTraceWriter(buffer_id)));
}
-std::unique_ptr<ProbesDataSource> ProbesProducer::CreateSystemInfoDataSource(
+template <>
+std::unique_ptr<ProbesDataSource>
+ProbesProducer::CreateDSInstance<SystemInfoDataSource>(
TracingSessionID session_id,
const DataSourceConfig& config) {
auto buffer_id = static_cast<BufferID>(config.target_buffer());
@@ -346,8 +251,9 @@
std::unique_ptr<CpuFreqInfo>(new CpuFreqInfo())));
}
+template <>
std::unique_ptr<ProbesDataSource>
-ProbesProducer::CreateInitialDisplayStateDataSource(
+ProbesProducer::CreateDSInstance<InitialDisplayStateDataSource>(
TracingSessionID session_id,
const DataSourceConfig& config) {
auto buffer_id = static_cast<BufferID>(config.target_buffer());
@@ -356,6 +262,136 @@
endpoint_->CreateTraceWriter(buffer_id)));
}
+// Another anonymous namespace. This cannot be moved into the anonymous
+// namespace on top (it would fail to compile), because the CreateDSInstance
+// methods need to be fully declared before.
+namespace {
+
+using ProbesDataSourceFactoryFunc = std::unique_ptr<ProbesDataSource> (
+ ProbesProducer::*)(TracingSessionID, const DataSourceConfig&);
+
+struct DataSourceTraits {
+ const ProbesDataSource::Descriptor* descriptor;
+ ProbesDataSourceFactoryFunc factory_func;
+};
+
+template <typename T>
+constexpr DataSourceTraits Ds() {
+ return DataSourceTraits{&T::descriptor, &ProbesProducer::CreateDSInstance<T>};
+}
+
+const DataSourceTraits kAllDataSources[] = {
+ Ds<AndroidLogDataSource>(), Ds<AndroidPowerDataSource>(),
+ Ds<FtraceDataSource>(), Ds<InitialDisplayStateDataSource>(),
+ Ds<InodeFileDataSource>(), Ds<LinuxPowerSysfsDataSource>(),
+ Ds<MetatraceDataSource>(), Ds<PackagesListDataSource>(),
+ Ds<ProcessStatsDataSource>(), Ds<SysStatsDataSource>(),
+ Ds<SystemInfoDataSource>(),
+};
+
+} // namespace
+
+void ProbesProducer::OnConnect() {
+ PERFETTO_DCHECK(state_ == kConnecting);
+ state_ = kConnected;
+ ResetConnectionBackoff();
+ PERFETTO_LOG("Connected to the service");
+
+ std::array<DataSourceDescriptor, base::ArraySize(kAllDataSources)>
+ proto_descs;
+ // Generate all data source descriptors.
+ for (size_t i = 0; i < proto_descs.size(); i++) {
+ DataSourceDescriptor& proto_desc = proto_descs[i];
+ const ProbesDataSource::Descriptor* desc = kAllDataSources[i].descriptor;
+
+ proto_desc.set_name(desc->name);
+ proto_desc.set_will_notify_on_start(true);
+ proto_desc.set_will_notify_on_stop(true);
+ using Flags = ProbesDataSource::Descriptor::Flags;
+ if (desc->flags & Flags::kHandlesIncrementalState)
+ proto_desc.set_handles_incremental_state_clear(true);
+ if (desc->fill_descriptor_func) {
+ desc->fill_descriptor_func(&proto_desc);
+ }
+ }
+
+ // Register all the data sources. Separate from the above loop because, if
+ // generating a data source descriptor takes too long, we don't want to be in
+ // a state where only some data sources are registered.
+ for (const DataSourceDescriptor& proto_desc : proto_descs) {
+ endpoint_->RegisterDataSource(proto_desc);
+ }
+
+ // Used by tracebox to synchronize with traced_probes being registered.
+ if (all_data_sources_registered_cb_) {
+ endpoint_->Sync(all_data_sources_registered_cb_);
+ }
+}
+
+void ProbesProducer::OnDisconnect() {
+ PERFETTO_DCHECK(state_ == kConnected || state_ == kConnecting);
+ PERFETTO_LOG("Disconnected from tracing service");
+ if (state_ == kConnected)
+ return task_runner_->PostTask([this] { this->Restart(); });
+
+ state_ = kNotConnected;
+ IncreaseConnectionBackoff();
+ task_runner_->PostDelayedTask([this] { this->Connect(); },
+ connection_backoff_ms_);
+}
+
+void ProbesProducer::SetupDataSource(DataSourceInstanceID instance_id,
+ const DataSourceConfig& config) {
+ PERFETTO_DLOG("SetupDataSource(id=%" PRIu64 ", name=%s)", instance_id,
+ config.name().c_str());
+ PERFETTO_DCHECK(data_sources_.count(instance_id) == 0);
+ TracingSessionID session_id = config.tracing_session_id();
+ PERFETTO_CHECK(session_id > 0);
+
+ std::unique_ptr<ProbesDataSource> data_source;
+
+ for (const DataSourceTraits& rds : kAllDataSources) {
+ if (rds.descriptor->name != config.name()) {
+ continue;
+ }
+ data_source = (this->*(rds.factory_func))(session_id, config);
+ break;
+ }
+
+ if (!data_source) {
+ PERFETTO_ELOG("Failed to create data source '%s'", config.name().c_str());
+ return;
+ }
+
+ session_data_sources_[session_id].emplace(data_source->descriptor,
+ data_source.get());
+ data_sources_[instance_id] = std::move(data_source);
+}
+
+void ProbesProducer::StartDataSource(DataSourceInstanceID instance_id,
+ const DataSourceConfig& config) {
+ PERFETTO_DLOG("StartDataSource(id=%" PRIu64 ", name=%s)", instance_id,
+ config.name().c_str());
+ auto it = data_sources_.find(instance_id);
+ if (it == data_sources_.end()) {
+ // Can happen if SetupDataSource() failed (e.g. ftrace was busy).
+ PERFETTO_ELOG("Data source id=%" PRIu64 " not found", instance_id);
+ return;
+ }
+ ProbesDataSource* data_source = it->second.get();
+ if (data_source->started)
+ return;
+ if (config.trace_duration_ms() != 0) {
+ uint32_t timeout = 5000 + 2 * config.trace_duration_ms();
+ watchdogs_.emplace(
+ instance_id, base::Watchdog::GetInstance()->CreateFatalTimer(
+ timeout, base::WatchdogCrashReason::kTraceDidntStop));
+ }
+ data_source->started = true;
+ data_source->Start();
+ endpoint_->NotifyDataSourceStarted(instance_id);
+}
+
void ProbesProducer::StopDataSource(DataSourceInstanceID id) {
PERFETTO_LOG("Producer stop (id=%" PRIu64 ")", id);
auto it = data_sources_.find(id);
@@ -374,12 +410,19 @@
endpoint_->NotifyDataSourceStopped(id);
TracingSessionID session_id = data_source->tracing_session_id;
- auto range = session_data_sources_.equal_range(session_id);
- for (auto kv = range.first; kv != range.second; kv++) {
- if (kv->second != data_source)
- continue;
- session_data_sources_.erase(kv);
- break;
+
+ auto session_it = session_data_sources_.find(session_id);
+ if (session_it != session_data_sources_.end()) {
+ auto desc_range = session_it->second.equal_range(data_source->descriptor);
+ for (auto ds_it = desc_range.first; ds_it != desc_range.second; ds_it++) {
+ if (ds_it->second == data_source) {
+ session_it->second.erase(ds_it);
+ if (session_it->second.empty()) {
+ session_data_sources_.erase(session_it);
+ }
+ break;
+ }
+ }
}
data_sources_.erase(it);
watchdogs_.erase(id);
@@ -476,56 +519,44 @@
// userspace tracing buffer. If more than one ftrace data sources are active,
// this call typically happens after writing for all session has been handled.
void ProbesProducer::OnFtraceDataWrittenIntoDataSourceBuffers() {
- TracingSessionID last_session_id = 0;
- FtraceMetadata* metadata = nullptr;
- InodeFileDataSource* inode_data_source = nullptr;
- ProcessStatsDataSource* ps_data_source = nullptr;
+ for (const auto& tracing_session : session_data_sources_) {
+ // Take the metadata (e.g. new pids) collected from ftrace and pass it to
+ // other interested data sources (e.g. the process scraper to get command
+ // lines on new pids and tgid<>tid mappings). Note: there can be more than
+ // one ftrace data source per session. All of them should be considered
+ // (b/169226092).
+ const std::unordered_multimap<const ProbesDataSource::Descriptor*,
+ ProbesDataSource*>& ds_by_type =
+ tracing_session.second;
+ auto ft_range = ds_by_type.equal_range(&FtraceDataSource::descriptor);
- // unordered_multimap guarantees that entries with the same key are contiguous
- // in the iteration.
- for (auto it = session_data_sources_.begin(); /* check below*/; it++) {
- // If this is the last iteration or the session id has changed,
- // dispatch the metadata update to the linked data sources, if any.
- if (it == session_data_sources_.end() || it->first != last_session_id) {
- bool has_inodes = metadata && !metadata->inode_and_device.empty();
- bool has_pids = metadata && !metadata->pids.empty();
- bool has_rename_pids = metadata && !metadata->rename_pids.empty();
- if (has_inodes && inode_data_source)
- inode_data_source->OnInodes(metadata->inode_and_device);
- // Ordering the rename pids before the seen pids is important so that any
- // renamed processes get scraped in the OnPids call.
- if (has_rename_pids && ps_data_source)
- ps_data_source->OnRenamePids(metadata->rename_pids);
- if (has_pids && ps_data_source)
- ps_data_source->OnPids(metadata->pids);
- if (metadata)
- metadata->Clear();
- metadata = nullptr;
- inode_data_source = nullptr;
- ps_data_source = nullptr;
- if (it == session_data_sources_.end())
- break;
- last_session_id = it->first;
- }
- ProbesDataSource* ds = it->second;
- if (!ds->started)
- continue;
-
- if (ds->descriptor == &FtraceDataSource::descriptor) {
- metadata = static_cast<FtraceDataSource*>(ds)->mutable_metadata();
- } else if (ds->descriptor == &InodeFileDataSource::descriptor) {
- inode_data_source = static_cast<InodeFileDataSource*>(ds);
- } else if (ds->descriptor == &ProcessStatsDataSource::descriptor) {
- // A trace session might have declared more than one ps data source.
- // In those cases we often use one for a full dump on startup (
- // targeting a dedicated buffer) and another one for on-demand dumps
- // targeting the main buffer.
- // Only use the one that has on-demand dumps enabled, if any.
- auto ps = static_cast<ProcessStatsDataSource*>(ds);
- if (ps->on_demand_dumps_enabled())
- ps_data_source = ps;
- }
- } // for (session_data_sources_)
+ auto ino_range = ds_by_type.equal_range(&InodeFileDataSource::descriptor);
+ auto ps_range = ds_by_type.equal_range(&ProcessStatsDataSource::descriptor);
+ for (auto ft_it = ft_range.first; ft_it != ft_range.second; ft_it++) {
+ auto* ftrace_ds = static_cast<FtraceDataSource*>(ft_it->second);
+ if (!ftrace_ds->started)
+ continue;
+ auto* metadata = ftrace_ds->mutable_metadata();
+ for (auto ps_it = ps_range.first; ps_it != ps_range.second; ps_it++) {
+ auto* ps_ds = static_cast<ProcessStatsDataSource*>(ps_it->second);
+ if (!ps_ds->started || !ps_ds->on_demand_dumps_enabled())
+ continue;
+ // Ordering the rename pids before the seen pids is important so that
+ // any renamed processes get scraped in the OnPids call.
+ if (!metadata->rename_pids.empty())
+ ps_ds->OnRenamePids(metadata->rename_pids);
+ if (!metadata->pids.empty())
+ ps_ds->OnPids(metadata->pids);
+ }
+ for (auto in_it = ino_range.first; in_it != ino_range.second; in_it++) {
+ auto* inode_ds = static_cast<InodeFileDataSource*>(in_it->second);
+ if (!inode_ds->started)
+ continue;
+ inode_ds->OnInodes(metadata->inode_and_device);
+ }
+ metadata->Clear();
+ } // for (FtraceDataSource)
+ } // for (tracing_session)
}
void ProbesProducer::ConnectWithRetries(const char* socket_name,
diff --git a/src/traced/probes/probes_producer.h b/src/traced/probes/probes_producer.h
index 6650501..b021ee5 100644
--- a/src/traced/probes/probes_producer.h
+++ b/src/traced/probes/probes_producer.h
@@ -66,42 +66,13 @@
// Our Impl
void ConnectWithRetries(const char* socket_name,
base::TaskRunner* task_runner);
- std::unique_ptr<ProbesDataSource> CreateFtraceDataSource(
+
+ // Constructs an instance of a data source of type T.
+ template <typename T>
+ std::unique_ptr<ProbesDataSource> CreateDSInstance(
TracingSessionID session_id,
const DataSourceConfig& config);
- std::unique_ptr<ProbesDataSource> CreateProcessStatsDataSource(
- TracingSessionID session_id,
- const DataSourceConfig& config);
- std::unique_ptr<ProbesDataSource> CreateInodeFileDataSource(
- TracingSessionID session_id,
- DataSourceConfig config);
- std::unique_ptr<ProbesDataSource> CreateSysStatsDataSource(
- TracingSessionID session_id,
- const DataSourceConfig& config);
- std::unique_ptr<ProbesDataSource> CreateAndroidPowerDataSource(
- TracingSessionID session_id,
- const DataSourceConfig& config);
- std::unique_ptr<ProbesDataSource> CreateAndroidPowerStatsDataSource(
- TracingSessionID session_id,
- const DataSourceConfig& config);
- std::unique_ptr<ProbesDataSource> CreateAndroidLogDataSource(
- TracingSessionID session_id,
- const DataSourceConfig& config);
- std::unique_ptr<ProbesDataSource> CreateLinuxPowerSysfsDataSource(
- TracingSessionID session_id,
- const DataSourceConfig& config);
- std::unique_ptr<ProbesDataSource> CreatePackagesListDataSource(
- TracingSessionID session_id,
- const DataSourceConfig& config);
- std::unique_ptr<ProbesDataSource> CreateMetatraceDataSource(
- TracingSessionID session_id,
- const DataSourceConfig& config);
- std::unique_ptr<ProbesDataSource> CreateSystemInfoDataSource(
- TracingSessionID session_id,
- const DataSourceConfig& config);
- std::unique_ptr<ProbesDataSource> CreateInitialDisplayStateDataSource(
- TracingSessionID session_id,
- const DataSourceConfig& config);
+
void ActivateTrigger(std::string trigger);
// Calls `cb` when all data sources have been registered.
@@ -141,8 +112,17 @@
std::unordered_map<DataSourceInstanceID, std::unique_ptr<ProbesDataSource>>
data_sources_;
- // Keeps (pointers to) data sources ordered by session id.
- std::unordered_multimap<TracingSessionID, ProbesDataSource*>
+ // Keeps (pointers to) data sources grouped by session id and data source
+ // type. The pointers do not own the data sources (they're owned by
+ // data_sources_).
+ //
+ // const ProbesDataSource::Descriptor* identifies the type.
+ //
+ // Used by OnFtraceDataWrittenIntoDataSourceBuffers().
+ std::unordered_map<
+ TracingSessionID,
+ std::unordered_multimap<const ProbesDataSource::Descriptor*,
+ ProbesDataSource*>>
session_data_sources_;
std::unordered_multimap<FlushRequestID, DataSourceInstanceID>
diff --git a/src/traced/probes/ps/process_stats_data_source.cc b/src/traced/probes/ps/process_stats_data_source.cc
index 76e8ccc..d61e41c 100644
--- a/src/traced/probes/ps/process_stats_data_source.cc
+++ b/src/traced/probes/ps/process_stats_data_source.cc
@@ -84,6 +84,7 @@
const ProbesDataSource::Descriptor ProcessStatsDataSource::descriptor = {
/*name*/ "linux.process_stats",
/*flags*/ Descriptor::kHandlesIncrementalState,
+ /*fill_descriptor_func*/ nullptr,
};
ProcessStatsDataSource::ProcessStatsDataSource(
diff --git a/src/traced/probes/sys_stats/sys_stats_data_source.cc b/src/traced/probes/sys_stats/sys_stats_data_source.cc
index 93c292b..9f2875f 100644
--- a/src/traced/probes/sys_stats/sys_stats_data_source.cc
+++ b/src/traced/probes/sys_stats/sys_stats_data_source.cc
@@ -70,6 +70,7 @@
const ProbesDataSource::Descriptor SysStatsDataSource::descriptor = {
/*name*/ "linux.sys_stats",
/*flags*/ Descriptor::kFlagsNone,
+ /*fill_descriptor_func*/ nullptr,
};
SysStatsDataSource::SysStatsDataSource(
diff --git a/src/traced/probes/system_info/system_info_data_source.cc b/src/traced/probes/system_info/system_info_data_source.cc
index 3e96239..2178556 100644
--- a/src/traced/probes/system_info/system_info_data_source.cc
+++ b/src/traced/probes/system_info/system_info_data_source.cc
@@ -42,6 +42,7 @@
const ProbesDataSource::Descriptor SystemInfoDataSource::descriptor = {
/* name */ "linux.system_info",
/* flags */ Descriptor::kFlagsNone,
+ /* fill_descriptor_func */ nullptr,
};
SystemInfoDataSource::SystemInfoDataSource(
diff --git a/test/configs/BUILD.gn b/test/configs/BUILD.gn
index b57b9aa..230fe01 100644
--- a/test/configs/BUILD.gn
+++ b/test/configs/BUILD.gn
@@ -21,8 +21,7 @@
script = "../../tools/protoc_helper.py"
deps = [
- "../../protos/perfetto/config:merged_config_source_set",
- "../../protos/perfetto/trace:merged_trace_source_set",
+ "../../protos/perfetto/trace:non_minimal_source_set",
protoc_target,
]
diff --git a/test/stress_test/stress_test.cc b/test/stress_test/stress_test.cc
index c8e9503..75de80a 100644
--- a/test/stress_test/stress_test.cc
+++ b/test/stress_test/stress_test.cc
@@ -178,7 +178,8 @@
traced.args.env = env_;
if (!verbose) {
traced.args.out_fd = OpenLogFile(result_dir + "/traced.log");
- traced.args.stderr_mode = traced.args.stdout_mode = base::Subprocess::kFd;
+ traced.args.stderr_mode = traced.args.stdout_mode =
+ base::Subprocess::OutputMode::kFd;
}
traced.Start();
g_sig->pids_to_kill.emplace_back(traced.pid());
@@ -195,7 +196,7 @@
producer.args.out_fd =
OpenLogFile(result_dir + "/producer." + std::to_string(i) + ".log");
producer.args.stderr_mode = producer.args.stdout_mode =
- base::Subprocess::kFd;
+ base::Subprocess::OutputMode::kFd;
}
producer.args.env = env_;
producer.Start();
@@ -213,7 +214,7 @@
if (!verbose) {
consumer.args.out_fd = OpenLogFile(result_dir + "/perfetto.log");
consumer.args.stderr_mode = consumer.args.stdout_mode =
- base::Subprocess::kFd;
+ base::Subprocess::OutputMode::kFd;
}
remove(trace_file_path.c_str());
consumer.Start();
diff --git a/test/test_helper.h b/test/test_helper.h
index 778f88a..12d436d 100644
--- a/test/test_helper.h
+++ b/test/test_helper.h
@@ -350,8 +350,8 @@
Exec(const std::string& argv0,
std::initializer_list<std::string> args,
std::string input = "") {
- subprocess_.args.stderr_mode = base::Subprocess::kBuffer;
- subprocess_.args.stdout_mode = base::Subprocess::kDevNull;
+ subprocess_.args.stderr_mode = base::Subprocess::OutputMode::kBuffer;
+ subprocess_.args.stdout_mode = base::Subprocess::OutputMode::kDevNull;
subprocess_.args.input = input;
#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
diff --git a/tools/ftrace_proto_gen/proto_gen_utils.cc b/tools/ftrace_proto_gen/proto_gen_utils.cc
index 189c8f1..95a6531 100644
--- a/tools/ftrace_proto_gen/proto_gen_utils.cc
+++ b/tools/ftrace_proto_gen/proto_gen_utils.cc
@@ -38,8 +38,8 @@
const std::string platform = "linux64";
#endif
base::Subprocess clang_fmt({"buildtools/" + platform + "/clang-format"});
- clang_fmt.args.stdout_mode = base::Subprocess::kBuffer;
- clang_fmt.args.stderr_mode = base::Subprocess::kInherit;
+ clang_fmt.args.stdout_mode = base::Subprocess::OutputMode::kBuffer;
+ clang_fmt.args.stderr_mode = base::Subprocess::OutputMode::kInherit;
clang_fmt.args.input = input;
PERFETTO_CHECK(clang_fmt.Call());
return std::move(clang_fmt.output());
diff --git a/tools/gen_bazel b/tools/gen_bazel
index e5c7f82..d330855 100755
--- a/tools/gen_bazel
+++ b/tools/gen_bazel
@@ -25,6 +25,7 @@
from __future__ import print_function
import argparse
+import itertools
import json
import os
import re
@@ -76,21 +77,25 @@
# Root proto targets (to force discovery of intermediate proto targets).
# These targets are marked public.
+# TODO(lalitm): remove these in a followup.
proto_targets = [
- '//protos/perfetto/trace:merged_trace_source_set',
- '//protos/perfetto/trace:non_minimal_lite',
- '//protos/perfetto/trace:non_minimal_source_set',
- '//protos/perfetto/config:merged_config_source_set',
'//protos/perfetto/metrics:lite',
'//protos/perfetto/metrics:source_set',
- '//protos/perfetto/metrics/android:lite',
- '//protos/perfetto/metrics/android:source_set',
- '//protos/perfetto/trace:source_set',
- '//protos/perfetto/config:source_set',
'//protos/third_party/chromium:lite',
'//protos/third_party/chromium:source_set',
]
+# Proto target groups which will be made public.
+proto_groups = {
+ 'config': [
+ '//protos/perfetto/config:source_set'
+ ],
+ 'trace': [
+ '//protos/perfetto/trace:non_minimal_source_set',
+ '//protos/perfetto/trace:minimal_source_set'
+ ],
+}
+
# Path for the protobuf sources in the standalone build.
buildtools_protobuf_src = '//buildtools/protobuf/src'
@@ -257,15 +262,17 @@
return gn_utils.label_to_target_name_with_path(gn_name)
+def get_bazel_proto_sources_label(target_name):
+ """Converts a GN target name into a Bazel proto label name."""
+ return re.sub('_(lite|zero|cpp|ipc|source_set|descriptor)$', '',
+ get_bazel_label_name(target_name)) + '_protos'
+
+
def gen_proto_label(target):
""" Generates the xx_proto_library label for proto targets."""
assert (target.type == 'proto_library')
- def get_sources_label(target_name):
- return re.sub('_(lite|zero|cpp|ipc|source_set|descriptor)$', '',
- get_bazel_label_name(target_name)) + '_protos'
-
- sources_label_name = get_sources_label(target.name)
+ sources_label_name = get_bazel_proto_sources_label(target.name)
# For 'source_set' plugins, we don't want to generate any plugin-dependent
# targets so just return the label of the proto sources only.
@@ -276,7 +283,7 @@
assert (all(x.endswith('.proto') for x in target.sources))
sources_label.srcs = sorted([x[2:] for x in target.sources]) # Strip //.
sources_label.deps = sorted(
- [':' + get_sources_label(x) for x in target.proto_deps])
+ [':' + get_bazel_proto_sources_label(x) for x in target.proto_deps])
# In Bazel, proto_paths are not a supported concept becauase strong
# dependency checking is enabled. Instead, we need to depend on the target
@@ -295,7 +302,7 @@
sources_label.visibility = ['PERFETTO_CONFIG.proto_library_visibility']
sources_label.exports = sorted([
- ':' + get_sources_label(d) for d in target.proto_exports
+ ':' + get_bazel_proto_sources_label(d) for d in target.proto_exports
])
return sources_label
@@ -332,7 +339,7 @@
# implicit.
if target.proto_plugin == 'descriptor':
plugin_label.deps += [
- ':' + get_sources_label(x) for x in target.proto_deps
+ ':' + get_bazel_proto_sources_label(x) for x in target.proto_deps
]
else:
plugin_label.deps += [':' + sources_label_name]
@@ -345,6 +352,56 @@
return plugin_label
+def gen_proto_group_target(gn, name, target_names):
+ # Get a recursive list of the proto_library targets rooted here which
+ # have src.
+ deps_set = set()
+ def recursive_deps(name, deps_set):
+ target = gn.get_target(name)
+ deps_set.add(target.name)
+ for name in target.proto_deps:
+ recursive_deps(name, deps_set)
+
+ for n in target_names:
+ recursive_deps(n, deps_set)
+
+ deps_list = sorted(list(deps_set))
+ comment = f'''[{', '.join(target_names)}]'''
+
+ # First, create a root source set target which references all the child
+ # source set targets. We publish this as well as depending on this in all
+ # subsequent targets.
+ sources_label = BazelLabel(name + '_proto', 'perfetto_proto_library')
+ sources_label.deps = [
+ ':' + get_bazel_proto_sources_label(name) for name in deps_set
+ ]
+ sources_label.visibility = PUBLIC_VISIBILITY
+ sources_label.comment = comment
+
+ # Next we create a cc proto target depending on the source set target.
+ cc_label = BazelLabel(name + '_cc_proto', 'perfetto_cc_proto_library')
+ cc_label.deps = [':' + sources_label.name]
+ cc_label.visibility = PUBLIC_VISIBILITY
+ cc_label.comment = comment
+
+ # Next we create a java proto target depending on the source set
+ # target.
+ java_label = BazelLabel(name + '_java_proto', 'perfetto_java_proto_library')
+ java_label.deps = [':' + sources_label.name]
+ java_label.visibility = PUBLIC_VISIBILITY
+ java_label.comment = comment
+
+ # Finally we create a java lite proto target depending on the source
+ # set target.
+ lite_name = name + '_java_proto_lite'
+ java_lite_label = BazelLabel(lite_name, 'perfetto_java_lite_proto_library')
+ java_lite_label.deps = [':' + sources_label.name]
+ java_lite_label.visibility = PUBLIC_VISIBILITY
+ java_lite_label.comment = comment
+
+ return [sources_label, cc_label, java_label, java_lite_label]
+
+
def gen_target(gn_target):
if gn_target.type == 'proto_library':
return [gen_proto_label(gn_target)]
@@ -511,6 +568,10 @@
# ##############################################################################
'''.lstrip()
+ # Generate targets for proto groups.
+ for l_name, t_names in proto_groups.items():
+ res += ''.join(str(x) for x in gen_proto_group_target(gn, l_name, t_names))
+
# Force discovery of explicilty listed root proto targets.
for target_name in sorted(proto_targets):
gn.get_target(target_name)
diff --git a/ui/build.js b/ui/build.js
index e01e45d..e043026 100644
--- a/ui/build.js
+++ b/ui/build.js
@@ -466,6 +466,13 @@
absPath = pjoin(ROOT_DIR, uri);
}
+ // Don't serve contents outside of the project root (b/221101533).
+ if (path.relative(ROOT_DIR, absPath).startsWith('..')) {
+ res.writeHead(403);
+ res.end('403 Forbidden - Request path outside of the repo root');
+ return;
+ }
+
fs.readFile(absPath, function(err, data) {
if (err) {
res.writeHead(404);
diff --git a/ui/src/assets/common.scss b/ui/src/assets/common.scss
index 4aeb978..86c0ccb 100644
--- a/ui/src/assets/common.scss
+++ b/ui/src/assets/common.scss
@@ -205,10 +205,6 @@
width: 100%;
}
-.x-scrollable {
- overflow-x: auto;
-}
-
.query-table {
width: 100%;
font-size: 14px;
@@ -481,6 +477,10 @@
height: 20px;
}
+.x-scrollable {
+ overflow-x: auto;
+}
+
header.overview {
display: flex;
align-content: center;
diff --git a/ui/src/frontend/details_panel.ts b/ui/src/frontend/details_panel.ts
index 9c8969a..98dc6a8 100644
--- a/ui/src/frontend/details_panel.ts
+++ b/ui/src/frontend/details_panel.ts
@@ -407,7 +407,7 @@
return {key: tab.key, name: tab.name};
}),
}),
- m('.details-panel-container',
+ m('.details-panel-container.x-scrollable',
m(PanelContainer, {doesScroll: true, panels, kind: 'DETAILS'})));
}
}